DEV Community

IdleCultivation
IdleCultivation

Posted on

If someone might want it different, it should not be a literal

Development covered 2 Aug 2026 to 6 Aug 2026 (commit dates).

The rule this project has settled on is one question. Could somebody reasonably want this value different, without a code change? If yes, it is a setting, and a number sitting in a source file is a defect.

Myriad Immortal Sect, the game this devlog is about. Play it free in the browser

That covers far more than it first sounds like: drop chances, cooldowns, discount rates, caps, page sizes, thresholds, feature switches, and quite a lot of text. This stretch moved another few dozen of them and found both of the ways the discipline fails.

Failure one: a setting nothing reads

A tax on one transaction had been a proper setting for months. It was registered, it had a sensible default, it appeared in the operator's list of things to change, and no code anywhere read it. The tax was never charged.

This is the shape I now watch for hardest, because it is invisible from every angle. The operator sees a control. The code compiles. Tests of the transaction pass, since the transaction works fine without the charge. Only somebody comparing the design to the running economy notices.

The check that catches it is boring: a test that walks every registered setting and fails when one has no reader. Turned on, it found a handful, some real gaps and some deliberate placeholders that then had to be annotated as such, which is itself useful documentation.

Failure two: the literal left behind

The opposite and more common. Somebody registers a setting, gives it the old value as its default, and does not remove the old constant. Now there are two sources for one number.

The operator changes the setting and nothing happens. No error, no warning, and the most natural conclusion is that the system is broken rather than that the code is reading the other copy. I have watched this cost an hour more than once, and the discount on one faction's goods this stretch was exactly it: a setting named after the discount, and code applying its own value.

Store prices with a sect discount applied, a value meant to be tunable

Registering the setting is half the job. Deleting the literal is the other half, and it is the half that makes the feature real.

The value that was copied instead of derived

A subtler cousin. Whether an item is purchasable was stored as a flag on the item, filled in when the catalogue was first created, and the shop's actual stock list was maintained separately.

So removing an item from the shop left the flag saying yes. Everything downstream that asked whether the thing was purchasable, including the game itself, kept saying yes. Deriving the flag from the stock list rather than copying it at creation time removed the whole class.

General Store recipe shelf, its stock list deciding what can be bought

The general rule is the same as with duplicated constants. Every fact should have one home, and anything else that needs it should compute it rather than remember it.

The offline default has to agree

One wrinkle specific to a game that runs on the player's device: some settings have to reach the client, and the client has to work when it cannot reach anything.

So each of those values exists twice on purpose. There is the one an operator sets and the one compiled into the game as a floor for when nothing is reachable. That is a sanctioned duplicate, and it is only safe if the two are identical, because otherwise the game behaves one way with a connection and another way without, which is close to undiagnosable from a bug report.

The way to keep that honest is a test asserting the compiled floor equals the registered default. The interesting part is that this test also catches a subtler regression: if somebody stops marking a value as one the client is allowed to see, nothing errors, the game just quietly keeps its floor forever.

What should stay in the code

Not everything, and the exceptions are worth being clear about, because an over-applied rule is its own mess.

Structural values, where a different number would be a different design rather than a different setting. Certain kinds of item hold exactly one per slot, and making that adjustable would not be flexibility, it would be a way to corrupt saves.

Treasures screen where each equipment slot and gem socket holds exactly one item

Version markers on saved data, for the same reason. Formula shapes, as opposed to their coefficients: the curve is code, the numbers on it are settings.

Everything else, in my experience, is a setting waiting for the day somebody needs it at three in the morning without a deployment.

Everything here ships in Idle Cultivation Game.

Myriad Immortal Sect, the game this devlog is about. Play it free in the browser

Top comments (1)

Collapse
 
launchgatecheck profile image
Launch Gate •

The no-reader test catches a useful structural gap. I'd pair it with a behavioral test for the tax: change the setting away from its default and assert that the charged amount changes. A reader can exist while its value is ignored later. For the offline floor, how do you distinguish "could not fetch configuration" from "this setting was accidentally removed from the client-visible set"? Both can return the same default, so a provenance/status marker would help keep that regression visible.