One pass that grows and decays: why we didn’t build a second engine for dying

← All field notes

For a long stretch of development, plants in The Long Watch could grow old and die — and then nothing happened. A dead plant just sat there, forever: never removed, never breaking down, quietly piling up in the world. Death was a dead end. This is the story of giving it a second act without disturbing a single living thing, and why that meant not building the obvious second engine.

The tempting wrong shape

When you set out to add decay to a world that already grows, the tidy instinct is to build a parallel machine. You have a system that walks the plants and grows them; surely dying and rotting deserves its own system, walking the dead and breaking them down. Two engines, two responsibilities, neatly separated. It reads well on a whiteboard.

We didn’t do that, and the reason is worth being honest about. A separate decay engine sounds clean but it isn’t free: it’s a second walk over the same world, a second place to get the ordering wrong, a second thing to keep reproducible, and — most dangerous of all — a second system that could quietly perturb the first. But adding decay had exactly one non-negotiable constraint: it must not change how a growing plant behaves, at all. The forest that was already growing had to keep growing identically. Two engines make that a thing you hope for. We wanted it to be a thing we could prove.

One walk, one move

So we folded growth and decay into a single pass. Once per ecology tick — the world’s living things update on a slow, deliberate heartbeat, a few times a second — one walk steps through every plant in the world and advances each by exactly one move. Not two moves, not a growth pass followed by a decay pass: one walk, and for each plant, a single step.

What that step is depends on one question asked of the plant itself: is it still alive? A living plant takes a growth step — it reads its surroundings, accrues a little progress, maybe climbs to its next life stage. A plant that has died but isn’t yet gone takes a decay step instead — it breaks down a notch further. A plant that has finished decomposing does nothing at all. The branches are mutually exclusive by construction: a plant is either alive or it is dead, never both, so it takes the growth move or the decay move, and the other branch is simply never reached for it.

A plant is either alive or dead. So on any given tick it grows or it decays — never both, never neither-but-also-both. The two behaviours can’t collide because they can’t share a plant.

That mutual exclusion is the quiet hinge the whole design hangs on. It’s why one engine is not a compromise but the more honest shape: growth and decay aren’t two systems competing for the same plants, they’re two faces of one lifecycle, and a single thing can only be wearing one face at a time. Naming the pass for only half of what it does — calling it growth when it now also handles dying — would have been a small lie we’d have to remember forever. So it grows and decays, and we built it and named it as one thing.

The proof we held ourselves to

The constraint — decay changes nothing about growth — is easy to assert and easy to be wrong about. We made it the named exit criterion for the whole effort, the single thing that had to be true before we’d call it done, and then we went and checked it the only way worth trusting.

We ran a scenario with no dead plants in it — a purely growing world — and compared it, down to the byte of resulting state, against the same world from before decay existed at all. It reproduced exactly. Not approximately, not within tolerance: identically. And the reason is the structure above, not luck. With nothing dead in the world, the decay branch is never taken. Every plant is alive, every plant takes the growth step, and the growth step is the same code it always was. The new branch is present but dormant; the path the growing world actually walks is untouched. So the world that grew before decay existed and the world that grows alongside decay are, for a forest with no deaths in it yet, the very same world.

There’s a sharper, harder version of that humility — what happens once decay does run and the loop closes back onto growth through the soil, where “reads nothing of each other” stops meaning “uncoupled.” That coupling, and how it fooled every careful reading of the code, is a postmortem of its own. The point that belongs here is the smaller, earlier one: the growing-only world was provably unmoved, because the move that wasn’t taken can’t change anything.


Gentle by design, on the way out

A decay step had to look like something, and we were careful about what. There is no separate rotting model, no second shape swapped in: a decomposing plant renders as the living one, only with its colour tinted progressively more muted as it breaks down. The further along it is, the duller and softer it reads, until it fades from the world entirely. That’s the whole look — colour muting and dimming toward gone, never anything graphic or grim. It keeps the world’s cozy-but-serious register all the way down to the last blade.

The lifecycle the decay step walks is staged, and which stages a plant passes through — and how long it lingers — isn’t baked into the code: it lives in each species’ own death profile, the same data-driven way the rest of a plant is described. That staged leaving — how a death isn’t a deletion so much as a slow handing-back — is its own story, and for a tree that lives for in-game decades it stretches into a leaving paced to a life. What matters for the single pass is only this: grass and oak run the identical walk; they just carry different leavings.

One more decision kept the single pass simple. A plant that finishes decomposing isn’t torn out of the world on the spot — it’s marked gone and left where it lay, a quiet placeholder, while the living count drops so the population stays honest. Actually reclaiming those empty slots is a more delicate problem than it looks, and we deliberately deferred it until the world holds far more plants than it did then; the bookkeeping of keeping the body without keeping the slot is told elsewhere. A gone plant does no work and is never drawn, so for the pass it costs almost nothing — the walk skips over it and moves on.

What it cost, and what it didn’t

Because growth and decay share one walk, there was no second budget to defend. We measured the combined pass under load — a world busy with both growing and rotting plants — and it held a steady frame rate with margin to spare: the heaviest frame landed well under the ceiling we’d set, and the rate never sagged toward the floor. No re-tuning, no parallel system to profile. One walk is one thing to keep fast, and it stayed fast.

This same pass also laid the groundwork for the part that makes death matter — a decomposing plant enriching the ground beneath it, so the next thing to root there comes up a shade faster. That write-back wasn’t finished here; it was the plumbing underneath a payoff told in the post above. What we shipped that day was narrower and, to us, foundational: death stopped being a dead end. A plant could now grow, age, die, and break down and finally leave — all of it on one heartbeat, one move at a time.

An aerial view of a golden-hour voxel meadow of mostly green grass, with a scattered few blades dulled to muted brown and grey as they decompose and settle into litter on the ground.Concept art · pre‑alpha
A decomposing plant isn’t a new shape — it’s the living one, colour muting toward gone.

The lesson generalised past plants. The cleanest-looking option for adding a behaviour to a system that already works — a fresh, separate engine — is often the one that makes the promise hardest to keep. Folding the new behaviour into the existing walk, behind a branch the old world never takes, let us add an entire second act to a plant’s life and still hand back the exact same forest we started with. The most reassuring thing a change can do is leave no trace where it isn’t wanted.

Keep reading

Concept art · pre‑alpha