Pac-Man’s loop — clear every pellet, dodge four ghosts with distinct personalities, flip the chase with a power pellet — but the maze is a city block grid seen from a chase camera, and the walls are buildings. The one mechanical addition changes how the loop feels: you can jump. A handful of buildings are low enough to hop onto; ghosts are street-bound, so a rooftop is a safe island. Each roof holds a golden bonus pellet that counts toward the clear, so height is part of the route, not just an escape hatch.
How it plays
- WASD / arrows to run the streets, Space to hop. Rooftop pads (the teal, low buildings) are reachable from the street; everything taller is a wall.
- Four ghosts run classic-style AI on the street graph: at every intersection each picks the legal turn that minimizes distance to its own target — the red one targets you, pink aims ahead of you, cyan mirrors red through your position, orange chases only while far. Scatter/chase waves alternate on a timer, exactly like the arcade rhythm.
- Power pellets (the four corners) flip ghosts to frightened: slower, blue, edible for 200/400/800/1600. Eaten ghosts fly home as eyes and re-emerge.
- Ghosts can only kill you at street level — airborne or on a roof you’re safe. They’ll be waiting when you come down, and the streets are where the pellets are.
Structure
The sim (src/sim.js + src/maze.js) is framework-free and headlessly
testable: fixed-timestep player physics (circle-vs-building collision with a
height check, so jumping over a low roof and getting walled by a tower use the
same code path), grid-locked ghost movement, and an event list per tick that
the shell turns into audio. src/scene3d.js takes an injected THREE and
builds the city — instanced buildings with canvas-generated lit windows,
instanced pellets, hemisphere-jaw player with a chomp cycle — and syncs it
from sim state each frame. test/run.test.mjs BFS-checks that every pellet
is reachable from spawn (roof pellets by jump), then plays scripted games:
eat a pellet run, hop a rooftop for its bonus, get killed at street level,
survive the same ambush airborne, and eat a frightened ghost.
The demo is the committed prebuilt bundle per ADR-0002: demo/ carries its
own copy of the modules plus three.js, no build step.

