One pass that grows and decays: why we didn’t build a second engine for dying
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, piling up in the world. Death was a dead end. Giving it a second act without disturbing a single living thing turned out to mean 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 deserves spelling out. 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 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. The world’s living things update on a slow, deliberate heartbeat, an ecology tick that comes a few times a second. Once per tick, 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, breaking 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 no compromise: 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 that 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 the resulting state byte for byte 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. The entire effect is 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 profile carries a wobble of its own, added on at the end and floored the same way growth’s is — the shape that later drowned the seasons on the growing side, held here on purpose. That staged leaving, a death handed back slowly rather than deleted, is told in making loss matter; 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: we mark it gone and leave it 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, in 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 would only be finished later; here we laid 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.

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.



