Quest: Warrior Dragon Plays Itself: From the King's Throne Room to the Dragonlord's True Form
Start Quest: Warrior Dragon with --demo and nobody touches the controller. The in-engine AI picks New Quest, listens to King Lorik, opens the treasure chest, takes the Magic Key to the locked door, walks down through Tantegel Castle and out into Alefgard, then fights whatever jumps out of the grass. Point it at the Dragonlord and it wins that fight too. Everything below was recorded from the game running headless on a virtual display, with no human input.
--demo run below. Watch on YouTubeIt plays with the same buttons you do. AIEngine.gd is an autoload inside the Godot game. It can only send the input actions a player can (move_up, move_down, move_left, move_right, ui_accept, ui_cancel, cmd_menu), so it opens the command window and moves the cursor to TAKE or DOOR like a person would. It never teleports and never sets the game state directly. Each tick it reads the same JSON the game's HTTP control server publishes (/state for the hero, dialog, menus and battle, /screen for a walkable map of the visible tiles with every chest, door and staircase marked). It runs a breadth-first search to its next goal and walks there in strides: on a straight run it holds the direction down across several tiles and lets go as the hero steps onto the last one, instead of tapping once per tile.
A run from New Quest reads like this (taken from the state log the capture script recorded):
The bug it found for us. The first time we ran it this week, the hero opened the chest, unlocked the door and then walked into the throne-room counter forever. Yesterday's tile audit (85c4559f) made tile 8 the counter around King Lorik, and a floor tile in every town, but the control server still listed tiles 8 and 21 as staircases in /screen. The AI treated the counter at (5,3) as the nearest staircase. Only tiles 33 and 34 are staircases; mapped stairs come from stair_registry.json. With that fixed in 4f6bbe3d, the same run gets from New Quest to the overworld in about twelve seconds. No test caught this; an AI player did, just by trying to play.
Boss fights. The Enemy AI side of demo mode is the game's normal monster logic: attack patterns, spells and fire breath from monsters.json. To show the Player AI against the strongest monsters we used the debug launcher's battle test, which starts a fight against any of the 40 monsters with whatever hero stats you give it:
A level-15 hero with 90 HP lost to the Golem. At level 20 the AI beat it twice, and at level 30 it beat the Green Dragon, the Dragonlord's final form on its own (dragonlord_form2) and the full two-stage Dragonlord fight. That last fight is below, about seven seconds from A Dragonlord draws near! to the final blow:
What the --demo mode can't do yet, which is the to-do list. The full-game play mode in the video above does all of it: it routes across Alefgard, casts spells and earns its level before Charlock (how that mode works).
- The overworld has no goal. The AI has routes for the throne room and the castle's first floor. Outside, it walks a right, down, left, up loop next to the castle, which is enough to trigger random encounters but not to reach Brecconary. It wanders back through the castle gate now and then, and the castle logic walks it straight back out.
- It never casts spells. In battle it chooses FIGHT, or ITEM to use a Herb when HP falls under 35%. The hero in the Dragonlord fight had 190 MP and HEALMORE but no Herb, so at 36 HP it attacked again. It got lucky.
- Boss fights start from the debug launcher. The new-game run can't reach Charlock yet, so the boss footage uses a hand-picked hero level, not one the AI earned.
Watch it yourself. From games/quest-warrior-dragon, run ./launch.sh --demo, or set DW_DEMO=1. In a running game, POST /command with start_demo or stop_demo switches the AI on or off, and capture_screenshot saves the frame exactly as the game draws it, which is how the stills above were taken. The videos are an ffmpeg recording of the Xvfb display the game ran on.