DEVLOG · 03

The Bot That Learned to Play

July 12, 2026

Dreadmark has no QA department, but its combat still needs testing hundreds of times a day. So we built an AI bot that actually plays the game. It moves, kites, dodges telegraphs, picks targets and spends resources, and a telemetry pipeline turns every run it plays into data we can analyze.

The brain is a utility AI. On every tick, each possible action scores itself from 0 to 1, whether that is kiting, dodging, disengaging or one of the five skills. The best score wins, and emergency actions can interrupt anything above a threshold. Nothing in the decisions is random, so a rerun plays out exactly the same way. The bot follows a written playstyle, with stutter-step kiting as the basis and efficiency only where it stays safe. Every run writes a structured log, and the analyzer reads the red flags first: hits that landed after their telegraph ended, dodge charges wasted on trivial threats, and deaths along with the chain of events behind them. Every kind of bug we find becomes a permanent rule, so it can never come back unnoticed. That paid off quickly. The bot found real bugs nobody had spotted by eye, like a telegraph that ended early, an arrow that couldn't be dodged and a wind-up that tracked too fast to escape. Each one showed up in a log before a human ever felt cheated.

The bot dueling the Heavy with its health nearly gone
The bot mid-run: dueling the Heavy, one dodge charge spent, victory a few swings away.

Its first standing order was a hard one. It had to clear every monster without taking a single hit, and it took ten rounds of run, analyze, fix and rerun to get there. The damage it took fell with each run, from 100 to 72 to 20, until the log finally read six kills, zero damage taken, 75 seconds.

To push it harder it needed better opposition, so the sandbox got a proper arena, with three waves of skeletons, rangers and a heavy spawning in rings around you. The player got something new as well. The monsters' attacks have always shown red telegraphs, and now every aimed ability is hold-to-aim and paints a blue preview of the exact area it will hit, such as Cleave's cone, Lunge's corridor and Consecrated Ground's disc. The preview is drawn from the same numbers the damage uses, so it can't lie about reach. Then the designer picked up the controls himself, and his play was logged in as much detail as the bot's. The aim was a bot that plays like a person, mistakes included, and for that we needed a person to compare it with.

Comparing the two showed what the bot was missing. Head to head, the human cleared the thirty-three-monster gauntlet in about ninety seconds and took about 175 damage. The bot needed twice the time and took twice the damage. Its reflexes were not the problem, since it dodges more often and reads telegraphs to the frame. The difference was tempo. The human avoids melee by spacing instead of relying on i-frames, and calmly takes a few arrows as the price of never stopping. The bot paid for its safety with long retreats and spent half the clock walking. Having both datasets also caught a bug that neither would have caught alone. One bot batch posted suspiciously perfect numbers because not one enemy arrow connected. The new crossbow-bolt model carried a leftover invisible collider that made each shot delete itself at launch. Rangers had been firing blanks all batch.

Then the bot learned from the designer. He pointed out a habit of his own. He circles a pack to herd it into a clump, so one big cleave hits five skulls, while the bot had been running straight away and stretching them into a line of single targets. Circling became part of the bot's playstyle the same evening, and its first batch with it was five perfect clears out of five.

The last gap closed once we stopped counting damage per run and started counting it per second. The bot loses health at almost exactly the human rate, around 1.7 a second. It was just as safe, only twice as slow, and a fight that lasts twice as long costs twice the health. Splitting the damage by source showed that seventy percent of it was plain skeleton melee, taken point-blank in the middle of the crowd. That was exactly where our own advice to keep the pack tight had put it. Two changes fixed it: never get surrounded, and use reach. A skeleton's arm reaches about two metres and the Penitent's cleave reaches past three, and we had never used that gap. The bot stopped walking in to swing and started cleaving from outside their reach, the same wide three-target swing thrown from a spot the skeletons can't touch. Damage per clear fell by about seventy percent. The bot now clears all three waves without dying and takes less damage than the designer does. It was the first time it clearly beat the person who built the game it plays.

The safest damage is the damage you deal from outside the enemy's reach. Players of the genre have known that for a long time, and we learned it again by watching a machine walk into the middle of every fight until it stopped.

All entries