greytide

Devlog ·

Every table was too hard or too easy, and the dial the agents turned stopped working

Balancing twelve tables meant measuring a bot that swings by up to fourteen lives from one run to the next, and then finding that the obvious dial, enemy health, had nothing left to give.

Issues: #258, #139, #395, #398, #381 · Agents quoted: the worker on the balance pass, issue 258; the worker on bed and workbench, issue 398; the workers on run pacing, issues 139 and 395

The target is simple: the good bot, which plays like a competent player, should finish a table with 8 to 12 of its 20 lives left. Earlier posts left every new table somewhere else. The workbench was too easy, the sill was lost on wave 8, and the lead had told the table workers to stop tuning because bot games took hours on a crowded computer. Issue 258 was the clean-up, and it took two merged passes and a third task.

One sample is noise

The first pass (pull request 393) changed each table's health growth, the number that makes later waves tougher, using one headless bot run per value. Every table lost at its old value. The worker's note on what went wrong is short: "one bot sample per value swings by 3 to 17 lives, and merging origin/unity mid-way made the bot far stronger, so a second and third sweep were needed."

Two things had moved under it. The bot's results were wide, and another worker's change to the tower tray made the bot buy more towers, which invalidated numbers already taken. The pull request said plainly that the target was "not reliably hit" and listed what was not run at its final value.

The second pass averaged three runs per value, about 100 headless runs in all, eight players at a time. The worker noted that a player does not exit after the table-end line, so the sweep script waited for that line and stopped each player by its own process id. The result (pull request 397): eight of twelve tables within about one life of the target. The attic, kitchen and desk averaged 8, the garage 9, the bathroom, couch and pub 11, the game store 13.

The picnic that lost fifteen of fifteen

The picnic table lost 15 of 15 runs at growth 0.1, whatever share of each wave the worker changed. About 150 kills in eight waves starved the bot of points. The fix was not in the enemies' health at all: fewer trails open early (two, three, four instead of two to six), grunts thinned less and tough ones more, and growth set to 0. The next runs won with 4, 2, 9 and then 15 lives.

When growth stopped mattering

The bed and the workbench did not move. The workbench ended with 17 to 20 lives at growth 2.8, 5 and 12, and a 1.5 times larger crowd changed nothing. They went to a new task, issue 398.

Its worker raised the bed's growth to 15 and got 15, 14 and 18 lives; the workbench gave 20, 20 and 16. The worker's explanation: "a hit never counts for less than a tenth, which caps the effect near 10x." Past a point the game's own floor on damage meant health could not be raised further in any useful way.

So the worker turned walking speed instead, only when a table is played on its own, so that a full run keeps its own pace. The bed lost at wave 6 to 8 at speeds 1.5 and 2.0, gave 6 lives at 1.3, 9 at 1.22 and 12 at 1.15. The workbench lost at 2.5, gave 8 at 1.85, 11 at 1.8 and 14 at 1.7. Rebuilt with the chosen constants, the bed at 1.2 gave 12, 13 and 13 and the workbench at 1.8 gave 15, 14 and 10. The worker's own reading: run-to-run noise is about five lives.

A different problem in full runs

Issues 139 and 395 were about time, not lives. A full run was taking too long: the good bot needed 1,161 seconds on the desk and 1,555 on the bed, against a target of 8 to 12 minutes per table.

The worker on 139 first lowered late-wave health growth, which barely moved the times. Its note says why: the waves were limited by the crowd, by enemies being knocked back in the kill zone, and by a mini-boss and boss walk of 60 to 100 seconds each. Health was not the limit. So it added a per-board table of crowd size, walking speed, knockback and boss health. Two merges from other workers in the middle, a bigger tray and a health retune, each made earlier measurements worthless, so it measured again.

The worker on 395 found the same thing: "Lowering the enemy count alone did not shorten the bed (941 s at count 0.3); walking speed set the time." The sill was hardest. Smaller or slower hordes meant fewer kills, fewer points and fewer towers, and it lost on wave 7; a larger count held it. Playing a board as the second table straight after a skipped first lost everything, so the worker added a flag that forces which boards come up, and played the desk first.

Three whole runs on three seeds all won, with every table between 599 and 680 simulated seconds, and the careless bot lost table two on six boards. The desk, for the same bot, had ended anywhere from 1 to 19 lives.

The floor under all of it

All of this measured lives, and the overnight QA pass (told in an earlier post) had already shown what lives were hiding. Nine tables ended on one life of twenty because a floor keeps the game alive while the horde walks through, and the first boss leaked on 10 of 11 tables. That is issue 381, still open when this was written; its brief says the good bot should end table one with at most half its lives lost and report the floor-absorbed leaks in the summary line. The 8-to-12 figures above are therefore measured by a bot, on a scale whose bottom is padded.

What nobody has checked yet