An in-game chat box with a cheat code typed into it and a sarcastic commander reply printed underneath

Cheat codes as a development tool

Labs & Testing8 min readUpdated
ClaudeBuilt the thing
Adam SturrockDecided what mattered

Written up later from the commit history. Dated to when the work landed.

Type deep pockets into the chat box during a match and you get 10,000 gold, 10,000 lumber, 10,000 stone and 5,000 oil, and then your own commander comes on the radio to tell you your ancestors would be proud of your resourcefulness. The list runs to 23 codes, 12 of which toggle on and off.

Dwarf miners cutting into a glowing gold seam underground while others carry ore sacks along a timber bridge

They are not there as a treat for players. They are there because putting the game into a specific state quickly is the single most useful thing a development tool can do, and cheat codes turned out to be the cheapest interface for that which already existed. Adam plays the game to judge it, and half of judging it is reaching the part he wants to look at without playing twenty minutes of economy first.

What is on the list

Everything lives in one list, each entry carrying the code, whether it takes a number, and what it does. The Cheats screen in the menus is rendered straight from that list, so the documentation cannot drift away from what the game accepts. Roughly, they fall into four groups.

Resources. deep pockets, mine shaft, timber, quarry and black gold. All of them take an amount, so mine shaft 1000000 grants a million gold, which is the cap.

Rules off. iron curtain for invincible units, swift hammer for instant building and training, pack it in to train past the food cap, bottomless well for unlimited spellcasting, never say die so you cannot be defeated, and master builder to make every technology available.

The world. all seeing eye reveals the map, eternal sun and endless night pin the time of day, still hours freezes it wherever it is, bone dust sets how fast corpses and rubble decay with zero meaning never, and jukebox plays any soundtrack mid-battle.

Endings. paper thin kills every enemy unit, mountain king is instant victory, crumble is instant defeat, and greybeard gives every one of your heroes a thousand experience.

Then stone legend, which switches on hero possession so you can select a hero and drive it directly in third person. That one is a whole game mode hiding behind a cheat code.

None of them work in multiplayer, and where that is enforced is the important part. The switch lives in the part of the game that owns the real simulation, not in the chat box, so editing your own copy does not get you invincibility against a stranger.

The commander answers back

Every cheat has a written reply, and the replies are not congratulatory. iron curtain gets "Invincible troops. Real brave, commander. Why not just play with paper dolls instead?" Turning it off gets "Back to mortality, are we? Almost thought you'd grown a conscience." pack it in, which removes the food cap, gets "No food, no housing, no limits. Where exactly are all these soldiers sleeping, commander? On top of each other?"

Some of those are spoken rather than only printed. Each line is generated as speech by ElevenLabs in nine faction voices, using the same voice settings as the commander who narrates the rest of a match, so the insult sounds like the character it should. Toggles get two recordings, one for on and one for off.

A goblin workshop mid-explosion, green lightning and flying gears with the crew scattering in every direction

The one that is not on the list

Three codes are handled but deliberately left off the list, so they never appear on the Cheats screen. Two of them switch on developer overlays, and both return nothing at all, so no reply is printed.

The third is split, and it is the reason this post is filed under labs.

split draws the 2D game and the 3D game at the same time, in the same match, divided by an animated lightning bolt. It was built for filming a trailer, because Adam wanted a shot showing both art styles at once and there is no way to film that from two separate recordings. It takes a small set of options.

CommandEffect
splitTurn the split view on or off
split sweepThe divider travels across the battlefield and back
split line 5-95Park the divider at a fixed percentage across
split angle -45..45Tilt the divider away from vertical
split pitch 1-60Tilt the 3D camera down from overhead
split speed 0.1-10How fast it sweeps, where 1 is a twelve second cycle

The camera is locked across both halves. The two renderers are drawing the same world at the same moment from the same viewpoint, so the divider is a comparison rather than a transition. Filming both art styles in one shot therefore costs a typed command and a screen recorder rather than any capture rig, which fits the general approach taken in the trailer work.

There is one implementation detail worth stealing. The part of the game that handles typed codes has no access to the renderers or the camera, so it sends an event carrying a payload the listener can write into, and the listener writes its reply back onto it. Events here are delivered immediately rather than queued, so by the time the send returns, the reply is sitting there to be printed in the chat box. That is a return value smuggled through an event, and it is exactly the right amount of machinery for one hidden command.

Why the development pages depend on this

A lab wants a clean scene, which mostly means removing things the game does on its own. The spell lab needs two of them gone, and it gets them in two different ways.

The computer opponent is silenced by handing it an empty function to run each tick, so it keeps its base and its units for authenticity and simply never acts. The fog is removed by calling the cheat system with the string all seeing eye, verbatim, exactly as a player would type it. Not a separate reveal path, not a private flag. The cheat. That is the cheapest possible reuse, and it means the lab and the player are exercising one piece of code, which is the rule the labs are built on.

The same argument covers the rest. swift hammer gets you to a late-game army without playing twenty minutes of economy. bone dust 0 keeps corpses on the field forever, which is the only way to look at how corpses are drawn at all, since by default the evidence decays while you are still setting up the shot. never say die stops a session ending because a target dummy died, which is a real failure for a spell preview page. still hours freezes the lighting so two screenshots taken a minute apart are comparable. That players also enjoy all of them is a happy second use.

The commented-out line that should have been a command

The rule this collapses to applies to any project with a simulation in it, game or not. If your code contains a line saying "uncomment this to test X", that is a switch you have needed more than once and have not built. So build it, and build it somewhere you can reach while the thing you are debugging is already running, rather than before it starts.

The switches worth building are not arbitrary. They are the ones that delete a variable from an observation, and the list is short and much the same everywhere: stop the other side acting, remove the thing that hides state, skip the waiting, freeze the clock, stop the evidence expiring, and stop the session ending on its own. Six switches cover most of what a debugging session needs, and every one of them is something a player would enjoy too, which is why building them properly costs so little.

Three properties are what stop it rotting.

One list is the source of truth, and any documentation renders from it. A cheats screen generated from the same list the parser reads cannot describe a command that does not exist, and a hand-written list will be wrong within a month. The strong form puts the behaviour in the list too, so a command cannot exist in one place and not the other.

// One list, read by the parser, the help text and the dev tools.
export const COMMANDS = [
  {
    code: 'reveal',
    help: 'Reveal the whole map',
    toggle: true,
    run: (world, on) => { world.fog = !on; return on ? 'Map revealed.' : 'Fog restored.'; },
  },
  {
    code: 'grant',
    help: 'Grant gold, e.g. "grant 5000"',
    run: (world, _on, amount = 1000) => { world.gold += amount; return `+${amount} gold.`; },
  },
];
 
const active = new Set();
 
export function runCommand(world, input) {
  const trimmed = input.trim().toLowerCase();
  const def = COMMANDS.find((c) => trimmed === c.code || trimmed.startsWith(c.code + ' '));
  if (!def) return null;              // not a command; let the chat box have it
  const arg = trimmed.slice(def.code.length).trim();
  const on = def.toggle ? !active.has(def.code) : false;
  if (def.toggle) { on ? active.add(def.code) : active.delete(def.code); }
  return def.run(world, on, arg === '' ? undefined : Number(arg));
}
 
export const helpText = () =>
  COMMANDS.map((c) => `${c.code.padEnd(8)} ${c.help}`).join('\n');

Toggles remember their own state, an argument is optional and converted once, unknown input comes back empty so the chat box keeps it as chat, and the help screen is a loop over the same list rather than a second document. It is the shape any command table should converge on, because it is the only shape that guarantees everything shown on screen is something the parser will actually accept.

Development tools call the command, not a private path. The spell lab removes fog by typing the reveal cheat, not by setting a flag somewhere. That is one piece of code exercised twice, rather than two that agree until they do not, and it means a broken cheat is a broken game rather than a broken lab that goes unopened for weeks.

The gate that switches it off belongs in the authoritative process. Ours lives with the real simulation rather than in the chat box, because anything enforced in the interface is enforced only for people who have not edited it.

Where a cheat list wants to go next

The direction of travel is coverage. Twenty three codes were enough for the debugging sessions that produced them, and the next one will be written the first time Adam types something that ought to have worked and finds it does not. That is a reasonable way to grow a list of switches, because a switch that has never been wanted is a switch that will not be maintained.

Questions

How do you enter cheat codes in Shards of Stone?

Open the chat box during a match and type the code. Several take a number, so typing deep pockets followed by 500000 grants that amount of each resource instead of the default, capped at a million. The full list is on the Cheats screen in the menus, which is generated from the same list the game matches against.

Do cheats work in multiplayer?

No. Invincibility and instant building are switched off in multiplayer, and the switch lives in the part of the game that owns the real simulation rather than in the interface. A player editing their own copy cannot turn it back on for themselves.

Why would a developer ship cheat codes in a strategy game?

Because they are the fastest way to put a game into a specific state for testing. Revealing the map, freezing the time of day, granting resources and skipping build times all remove a variable from whatever is being looked at. Here the development pages call the reveal cheat directly rather than writing their own.

← All posts