warren
A roguelike with persistent progression, in Lua, driven from the terminal. Generated runs, classes, mutators and cross-run "legacy" - with a headless mode and determinism checks.
A roguelike with persistent progression in Lua, terminal-driven. Generated runs, classes and mutators, a cross-run legacy system. The key: a run is both random and fully deterministic, because the same seed must produce exactly the same run.
Overview
A roguelike lives on randomness: every run a different level layout, different items, different choices. But if that randomness were truly random, you could neither test the game nor compare results fairly. warren resolves that paradox with a seed that makes the world fresh for the player and repeatable for the machine.
Everything else is wrapped around this one property: classes, mutators and the legacy layer between games. Determinism here is not a limit on the fun but the foundation on which both the tests and meaningful progression can rest.
Random for the player, repeatable for the machine
The whole run is derived from a single number. The same seed always births the same world, but the player still sees freshness because the seed changes each game. The randomness is thus apparent in the technical sense and real in the felt sense: the level layout, items and events are computed, not rolled anew.
The key is that every draw goes through this one generator seeded by the number. If a single call reaches for randomness from outside it, determinism shatters, which is why the whole run must dutifully pass through the same source.
Determinism as a testing tool
Since the seed fully determines the run, it can be replayed without a human. warren has a headless mode that plays itself on a given seed and checks the result is identical every time. That turns a lottery into something you can regress: if a code change breaks determinism, the test catches it right away.
Test determinism counterfactually: introduce an unexpected randomness call outside the main generator and check that a run from the same seed stops matching. If the test does not notice, it is guarding nothing.
Legacy, the trace of previous runs
Persistent progression means the hero's death does not wipe everything. Between runs a legacy layer remains: unlocked classes, mutators that change the rules, small permanent bonuses. That way the next game starts differently from the last, even though the engine is still fully deterministic on its seed.
Separating those two layers matters here. The seed rules a single run, legacy carries between them, and the two must not mix, otherwise progression would contaminate the repeatability of a single game.
What comes from the seed and what from legacy
| Element | Source |
|---|---|
| Level layout | seed |
| Items and events | seed |
| Unlocked classes | legacy, permanent |
| Rule-changing mutators | legacy, permanent |
More projects
More work from the same category - see how we tackle similar challenges.
Have a similar project?
Get in touch - a quote is free and comes back within an hour.



