Games That Play Themselves: Building Attract Modes with AI

/ / 7 min read

Games That Play Themselves: Building Attract Modes with AI

Walk into any arcade from the 1980s and you’d see it — rows of cabinets running silent demos, each game playing itself in an endless loop, waiting for a quarter. Attract mode. It’s one of the oldest conventions in game design, and one of the most overlooked.

In the Dark Factory, our AI agents recently shipped attract modes for all four games simultaneously. The twist: the same AI systems that build these games also wrote the AI players that demo them. Here’s how each one works, and what it reveals about building convincing game AI from scratch.

Why Attract Mode Matters

Attract mode isn’t just eye candy. It serves three practical purposes:

  1. Showcases core mechanics without requiring the player to learn controls first
  2. Proves the game loop works — if the AI can play it, the systems are solid
  3. Catches edge cases — an AI player hammering your game loop continuously is an excellent stress test

Every Dark Factory game triggers its demo after 10 seconds of idle time on the title screen. Any keypress or click returns to the menu instantly. Simple contract, consistent across the studio.

Polybreak: Paddle Tracking with Intentional Failure

Polybreak is a 100-level breakout game. Its attract mode AI has one job: track the ball with the paddle. But a perfect AI player isn’t interesting to watch — it would clear every level without drama.

The solution is intentional lag. The AI paddle tracks the ball’s X position, but its movement speed is clamped. When the ball moves fast enough, the paddle literally can’t keep up. The AI also tracks a predicted miss point — when it knows it will fail to catch the ball, it commits to a miss location rather than jittering.

-- AI paddle: track ball x with lag
local target_x
if d.missing then
  target_x = d.miss_x - PADDLE_W / 2
else
  target_x = b.x - PADDLE_W / 2
end
local diff = target_x - d.paddle_x

This creates natural-looking gameplay. The paddle makes saves, barely misses others, and occasionally pulls off a dramatic last-second catch. The ball physics, brick collisions, and particle effects all run at full fidelity. It looks like someone is actually playing — just not very well.

Chronostone: Auto-Battle Decision Trees

Chronostone is a turn-based RPG, which presents a different challenge. You can’t just track a ball — you need to make tactical decisions.

The demo spawns a party of three characters (Kael the warrior, Lyra the mage, Finn the ranger) at level 1, pits them against 2-3 random enemies from the forest zone, and enables an auto-play system that issues commands every 0.6 seconds.

The decision tree is deliberately simple:

  1. Check if any ally is below 30% HP — if yes, heal them
  2. Otherwise, attack the nearest enemy
-- Check if any ally needs healing (< 30% HP)
local healTarget = nil
for _, pi in ipairs(ap) do
  local p = party[pi]
  if p.hp > 0 and p.hp / p.maxhp < 0.3 then
    healTarget = pi
    break
  end
end

This is enough to demonstrate the full battle system — HP bars animate, MP gets consumed, enemies die with dissolve effects, damage numbers float. The AI doesn’t play optimally (it ignores elemental weaknesses, doesn’t use items, never buffs), but it shows what combat looks like. When the battle ends, the demo resets and waits for the next idle window.

Voidrunner: Dodge-Priority Shmup AI

Voidrunner is a vertical scrolling shooter — 10 sectors, 100 waves, bullet-hell patterns. Its attract mode AI needs to handle two competing priorities: dodging incoming fire and shooting enemies.

The architecture is a simple priority system:

  1. If an enemy bullet is within 120 pixels, dodge it — move perpendicular to the bullet’s trajectory
  2. Otherwise, move toward the nearest enemy
  3. Always fire at the nearest target
-- Dodge incoming bullets (priority if close)
if nearBullet and bulletDist < 120 then
  -- Move perpendicular to bullet direction
end
-- Move toward nearest enemy
-- Fire weapon at nearest enemy

The demo starts the player at sector 1 with boosted HP (20 instead of the default) and a tier-2 weapon. The extra health means the AI survives long enough to show off multiple enemy types and bullet patterns. When it eventually dies — and it always does — the demo ends and returns to the menu.

The dodge-priority approach means the AI looks competent but not superhuman. It weaves through bullet patterns, takes some hits, and occasionally gets overwhelmed. Exactly what you’d want a demo to look like.

Dreadnought: Patrolling Dark Corridors

Dreadnought is a top-down survival horror game with cone-of-vision mechanics. Its attract mode is the most ambitious — it generates a small L-shaped station corridor and populates it with patrolling aliens.

The demo builds a 20×15 tile map with walls, gaps, and corridors. The player bot follows a fixed waypoint loop through the station while three aliens patrol their own independent routes at different speeds (25-35 pixels per second).

The AI has one survival behavior: if an alien enters a 120-pixel threat radius and is roughly ahead (within a 108-degree cone), the player swerves perpendicular to escape.

if adist < 120 then
  local relAngle = math.atan2(ady, adx) - p.angle
  if math.abs(relAngle) < math.pi * 0.6 then
    -- Swerve perpendicular to avoid incoming alien
    local swerveDir = relAngle > 0 and -1 or 1
    p.x = p.x + mcos(p.angle + swerveDir * math.pi/2) * p.speed * 1.3 * dt
    p.y = p.y + msin(p.angle + swerveDir * math.pi/2) * p.speed * 1.3 * dt
  end
end

The speed multiplier on the dodge (1.3x) makes escapes look desperate rather than casual. The player bot wanders through dark corridors with its flashlight cone, narrowly avoids aliens, and occasionally gets cornered. It captures the survival horror tension without any scripted sequences.

The Pattern: Minimum Viable Intelligence

All four attract modes share a design philosophy: the AI should be smart enough to showcase the game, but dumb enough to fail entertainingly.

Game AI Type Core Mechanic Intentional Weakness
Polybreak Paddle tracking Follow ball X with lag Speed-clamped paddle can’t save everything
Chronostone Decision tree Heal < 30% HP, else attack Ignores elements, items, buffs
Voidrunner Priority dodge Dodge bullets > attack enemies Limited threat radius, gets overwhelmed
Dreadnought Waypoint patrol Follow path, swerve from threats Fixed routes, no pathfinding, limited cone

None of these AIs would impress a game AI researcher. They don’t use behavior trees, utility systems, GOAP, or neural networks. They use the absolute minimum logic needed to create convincing gameplay footage. And that’s exactly right — attract mode is a trailer, not a benchmark.

AI Building AI Players

There’s something recursive about AI agents writing AI game players. The development agents understand the game mechanics because they built them. When they write the attract mode, they’re encoding their understanding of what makes the game interesting to watch.

The Polybreak agent knows the fun is in near-misses, so it builds in intentional lag. The Dreadnought agent knows tension comes from close calls in dark corridors, so it builds in proximity-based swerving. Each attract mode is a compression of the game’s design intent into the simplest possible decision loop.

Across four games, four genres, four different core mechanics — the attract modes shipped in the same development cycle, each tuned to its game’s personality. No designer hand-tuned the parameters. The agents played, observed, and adjusted until the demos looked right.

Walk up to any of these games idle on a screen, and they look alive. That’s the whole point. Same as it was in 1985.

// Leave a Response

Required fields are marked *