Architecture
How Undermountain Dwarves is built — the current shape of the game.
One simulation, two ways to play
Everything runs on a single, self-contained simulation core: pure JavaScript with no framework and no rendering code inside it, so the exact same rules drive both the single-player game and the online world.
- Single-player runs the simulation entirely in your browser and saves to local storage. No server; it works offline.
- The public world runs that same simulation on the server, authoritatively, and streams it to every connected player in real time.
The world
A tile grid across ten vertical z-levels. The surface is generated from noise into biomes — grass, forest, desert, snow, foothills, lakes, and cave entrances — and below it lies soil and then rock, with ore that grows richer (and hazards like cave-ins and magma that grow deadlier) the deeper you dig.
Dwarves are autonomous agents: they claim jobs, find their way with pathfinding across the 3-D tile graph (including stairs between levels), and carry the work out over time.
Time
A fixed-timestep clock. The world advances in discrete ticks — ten per second at normal speed — and nothing is instant: mining, hauling, building, farming, eating, and sleeping all take real ticks. In single-player you can pause and change speed; in the public world, time always runs forward at one real-time speed for everyone.
The client
Plain HTML, CSS, and JavaScript with a Canvas tile renderer and a classic ASCII aesthetic — no build step, no dependencies. The simulation is kept separate from the rendering and input layers, which is what lets the very same code also run headless on a server.
The online world
The public world is a Cloudflare Worker plus a Durable Object:
- One Durable Object owns the shared world and runs the authoritative simulation.
- When you join, you receive a full snapshot of the world; after that the server sends small updates several times a second containing only what changed.
- Your client renders exactly what the server sends and forwards your actions as commands. The server validates every command, so the world stays consistent for everyone connected.
- The world simulates while players are present and sleeps when it's empty, catching up when someone returns.
Sign-in is handled by Supabase (email and password), which issues the tokens the server uses to identify players.
Deterministic core
The simulation is deterministic and seeded. That's what keeps single-player saves reproducible and the live multiplayer world consistent across every client. An automated test suite exercises the tick clock, the job and crafting loops, world generation, save/load, and the multiplayer networking.