Kingsroad is a fixed-road tower defence, and its maps are generated. That means the game has to answer a question before it shows you anything: is this map actually beatable?
Our answer is a reference build — a competent, unexciting set of towers the generator plays through the real game — plus a three-rung repair ladder for maps that fail:
- Add a build pad.
- Trim the wave curve.
- Ease the enemy health curve.
Rung 3 is the backstop. It always works, because you can always make enemies weaker.
The diagnostic line that gave it away
repairs: 6, trims: 12, hpScale: 0.43
All on one map. And hpScale 0.43 is a 57% difficulty cut, presented in the logs as a successful repair.
Rung 1 had never helped once. The reference build was gold-limited, not space-limited, so the extra pads it added just sat there empty while the map still failed and fell through to rung 3, which quietly made the game much easier and reported success.
A repair rung that does not touch the binding constraint is worse than no rung at all, because the backstop underneath it succeeds silently. You get a green pipeline, a "repaired" label, and a game that has been defanged.
The tell is exactly what we saw: every rung firing at once. If all your fallbacks trigger on the same input, none of them is aimed.
The fix was upstream of the difficulty entirely
Rung 2 was also wrong — it trimmed the whole wave curve rather than the wave that actually leaked. Fixing that helped. But the real problem was not in the repair ladder at all.
Road length was rolled per band, in steps of 2 or 3, which produced roads between 45 and 59 cells on a single grid shape. Total damage a build can deliver scales directly with road length: a tower shoots at what walks past it, and a short road means fewer things walk past. The short roads were the ones failing. Every time.
Solving band count for a target road length per shape, instead of rolling it, removed the failures. The sweep went to 60 of 60 maps clean on the first attempt, hpScale 1.0, median 22 milliseconds. No repairs needed, so no repairs hiding anything.
Then the same bug turned up again, narrower: at 8 columns the serpentine's traverses were only 6 cells long, and every single map that fell through all three rungs was 8 wide. Fixed by clamping the generator to at least 10 columns — again, not by tuning.
When one input dimension accounts for 100% of your failures, that dimension is the bug, not the balance.
Assert that the backstop never fires
This is the part worth stealing regardless of what you are generating.
A backstop that can always succeed will always succeed, and it will read as green forever. The only way to know it is not carrying you is to assert it stays idle:
check('no map needed the health curve eased', sweep.every(r => r.hpScale === 1))
That one line converts a silent crutch into a build failure. If it ever goes red, a generator defect just appeared and you will hear about it on the day it lands rather than six months later when someone notices the game is too easy.
A difficulty band worth reusing
Once maps were genuinely clean, we needed to know they were interestingly clean rather than trivial. The measure: sweep the enemy health multiplier upward until the reference build first leaks.
Median breaking point 1.3x, minimum 1.1, maximum 1.75. That says a competent build wins with real slack, and a careless one does not — which is the shape a difficulty band should have.
Assert both ends of it. A proof with no breaking point below, say, 2.2x is not measuring a game anybody can lose.
Play it: Kingsroad · how to play
Related reading: don't resample, kill the rival solution · five wrong ways to prove a racing game is fair