Honor & Ash
Play it here: tristanbabcock.com/honorashdemo
Honor & Ash is a browser roguelike about running an army across a procedurally generated medieval world. You start as a character with a handful of peasants and a name nobody’s heard of. Everything else — the 256x256 continent, its elevation and biomes, every settlement’s population and garrison and ruling family, every roaming warband — is generated from a seed and then simulated forward, turn by turn, whether or not you’re standing there to watch it happen.
That last part is the design idea I keep building the rest of the game around: the world doesn’t wait for you. Other factions’ armies march, raid, and besiege settlements on their own schedule. New independent warbands spawn into the world periodically. If you wander off toward the coast for a hundred turns, the interior isn’t paused — you come back to find borders that have actually moved. It’s less “open world theme park” and more “the sim is the game, and you’re a participant in it, not the center of it.”
Wandering the map is where you run into wild encounters — bandits, rival warbands, whatever’s roaming near you that turn — rendered as a forced-perspective battlefield with both formations facing off, leaders and banners up front, rank after rank of troops shrinking away toward the horizon.
Settlements are where the actual game gets played: recruit peasants into your army, buy supplies, trade, or put a garrison to the sword and try to raze the place. Villages are common and lightly defended; citadels are rare, walled, and run by kings. I spent a big chunk of this project’s development on the settlement screen specifically, procedurally building each one’s skyline — keeps with a chance at battlements or a corner tower, castles with flanking towers and an outer chemise wall, citadels ringed with a cluster of smaller cottages — from the settlement’s own seed, so the same keep always looks the same keep, but no two keeps look alike.
That screenshot is a decent example of the thing I spent the most hours fighting: making a 2D scene of scattered objects on flat ground actually read as depth instead of “small stuff pasted near the top of the screen.” The trick, once I actually wrote it down, is that objects can’t just get smaller as they move toward the horizon — they have to shrink along a curve that’s steep close to the vanishing point and flattens out near the viewer, because that’s how real perspective falls off. A straight linear shrink reads as flat and floaty no matter how correct the math looks on paper. I ended up documenting the whole thing as a standing rule in the repo (PERSPECTIVE_RULE.md) after fixing the same category of bug — huts that looked like they were floating instead of receding — for the second time, so every future scattered-on-the-ground object (trees, rocks, cottages, whatever comes next) gets built against the same formula instead of reinventing it slightly wrong.
The rest of the presentation layer follows the same instinct: weather, time of day, and moon phase are all driven off the same deterministic world state the simulation uses, not decorative randomness bolted onto the view — so if the game log says it started raining on turn 40, the rain actually shows up on both the world map and inside every scene that turn, and buildings actually darken at night instead of staying lit against a black sky.
More recently I’ve been trying to get this actually playable on a phone, which turned out to be its own rabbit hole. The game was built keyboard-first — WASD/arrows to move, X to inspect, Enter to interact, Escape to back out — so step one was a fullscreen toggle (there’s no reliable browser event for “the player left fullscreen,” so on mobile the button has to just stay on screen the whole time rather than disappear after one use) plus an on-screen D-pad and a diamond of face buttons standing in for the keyboard, dispatching the exact same key codes the game already listens for. Step two was less obvious: on a tall phone screen the fixed-resolution canvas gets letterboxed down small, and it turned out to be centered twice — Phaser’s own centering logic plus a leftover CSS rule both trying to center the same element, compounding into a canvas visibly shoved off to one side. One of those had to go.
The D-pad ended up docked into the game-log panel itself rather than floating over the map — putting movement controls on top of the thing you’re trying to navigate defeats the point of adding them.
Like the rest of what’s gone up here lately, this one’s built almost entirely with coding agents — TypeScript, Phaser, a real test suite, and a lot of “here’s a screenshot, here’s what’s wrong with it” iteration. Procedural generation turns out to be a good fit for that workflow: the rules are precise enough to specify exactly, and the output is visual enough to verify by just looking at it, which makes for a fast loop between “describe the bug” and “confirm it’s fixed.”