DEV Community

IdleCultivation
IdleCultivation

Posted on

How a game should say no: designing refusals people can act on

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

Most interface effort goes into the path where things work. This stretch I went the other way and audited every place the game declines to do what was asked, which is a surprisingly large surface in a game full of requirements, and one where almost nothing had been designed at all.

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

Refusing by doing nothing

The most common shape, and the worst. Several actions refused by returning the state unchanged. Press the button, nothing happens, no message, no animation, no explanation.

From the player's side that is indistinguishable from a broken button, and it is worse than a broken button, because a broken button gets reported and this does not. The player concludes the feature does not work and stops pressing it, which means the failure never reaches you.

Three of these were in the same panel. Each had a good reason to refuse and none of them said it.

Pill shelf that states its weekly limit plainly instead of silently refusing

The spinner that never ends

Second shape. A request goes out, and the code around it handles the case where it succeeds. There is no branch for anything else. When the request does not succeed the interface stays in the state it entered, which is the loading state, forever.

This one has a tell: the copy says loading and the situation is not loading, it is finished and failed. Any interface with a loading state needs the third state as well, and the third state needs words. Not a spinner that stops, not an empty panel: a sentence saying what did not work.

I have written this bug in every project I have ever worked on. Handling only the good branch is not laziness, it is what the shape of the code encourages, because success is the branch you were thinking about when you wrote it.

The refusal nobody could read

Third, and specific to a game shipping in eleven languages. Some refusals were translated and some were not, and the untranslated ones sat in exactly the paths a confused player travels.

Failure copy is where translation matters most and gets audited least. Anybody can navigate an interface whose labels they cannot read, by shape and position. Nobody can act on a refusal they cannot read.

Quest Hall in Japanese, where refusal text needs translating as much as labels

The action that did not ask

The fourth is the opposite failure: not refusing when it should have.

Two of the most destructive actions in the game, one that scatters your accumulated progression and one that ends a lifetime, went ahead on a single press. No confirmation, no summary of what is about to be lost. That is not a refusal problem exactly, it is the same design gap seen from the other side: the game had no vocabulary for standing between the player and an outcome.

The version that shipped asks, and the asking names what will be destroyed. Naming it matters. A generic are you sure trains people to press yes.

The four rules

Written down, because I want to apply them to the next feature rather than to the next audit.

A refusal changes something visible. If the state after the press is identical to the state before, the player has learned nothing.

A refusal names its reason, in the player's language, in terms of the game rather than the system. Not invalid state. You need thirty more of this herb.

A refusal that is a requirement is a to do list. The best refusals tell the player the next thing to go and do, which turns a wall into a signpost at no extra cost.

Alchemy Pavilion naming the missing herbs and where to go to find them

And a request has three outcomes, not two. Loading, done, and did not work, with the third one written before you ship.

The check that had been red so long nobody read it

One more from the same stretch, on the same theme of signals that go unheard.

Four of this project's automated checks had been failing for a long time. Not badly: a handful of stale complaints each, all known, none urgent. And a check that is always red is a check nobody reads, so a genuinely new problem lands in it and joins the noise.

Getting all four back to green took a day of unglamorous work and immediately paid off, because the next real failure was visible as a change instead of as one more line in a list that was always there. Same lesson as everything above: a signal that is always present is not a signal.

Play it at Myriad Immortal Sect.

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

Top comments (0)