Skip to content

The tick

The engine advances in whole simulated hours. There are no partial ticks, no variable timesteps, no sub-hour ordering. Everything a tank does in an hour settles in one call, and the hour is the smallest thing that exists.

The rest of time is derived from a single counter. Hour of day is that counter modulo 24 and day number is it divided by 24, so a photoperiod, a feeding routine and a month of cycling are all read off the same integer.

StageWhat settlesWhy here
EnvironmentThe clock advances, the passive readings are recomputed — light, through the green water the hour starts with, flow, surface, aeration — and the hour’s light is written into the day’s history; then room-driven drift and evaporation applyThe hour has to exist before anything can read it
EquipmentSubstrate, hardscape, heater, top-off, CO₂ and doser act on the water they have just metEquipment answers conditions, so it cannot run ahead of them
BiologyPlants and the blooms in one pass, then livestock, then the clutches and broods on the brood buffers livestock just settledEach reads the one before it; plants and the blooms draw on the water as one
ResourcesGas exchange, rot and nitrification move what the living just produced, on one oxygen solveThe chemistry closes the hour’s books on everything emitted above
AlertsThresholds are compared against the settled hour, and each crossing is logged onceAn alert on a mid-tick number describes a state the tank was never in

The sequence exists so that every reader sees a value that has already settled this hour. Plants and the blooms read the equipment’s hour, livestock read a tank the flora has already been through. Reversing any pair would not break anything visibly — it would quietly make one of them an hour stale. Plants and the blooms share one pass because they share the water: they fill their stores in one call, so none gets first pick of the water, and each reads the others as the hour starts. Against the nitrifying colony the order does pick: the flora take their ammonia from what the colony left, and the colony oxidises what they leave beside the hour’s gill excretion.

Inside a stage the opposite rule holds. Systems in the same tier all read the same state and their results are applied together, so two of them drawing on one pool in the same hour never see each other’s withdrawal. Their shared stock is solved once for all of them instead: the last tier’s oxygen is the level gas exchange, rot and both nitrifier guilds leave the water at together, each on its own curve, as the flora’s pass solves its CO₂. That is rates into stocks doing the scheduling.

A tick takes a state and returns a new one. Nothing is mutated in place, and the state handed in is still valid and still readable after the call.

PropertyWhat it buys
The input state survives the callThe hour can be diffed, replayed, or kept as an undo point
Changes are data before they are changesEvery movement of a resource carries the mechanism that produced it
Randomness is a serializable seedThe same state and the same seed give the same hour on any machine
Nothing reads a wall clockThe engine’s only notion of time is the counter it is handed

Keeper actions apply immediately rather than waiting for the hour to turn: feeding, water changes, dosing, planting, trimming, scrubbing algae, and adding or removing stock. They are the one path by which anything outside the engine changes a tank, and the next tick meets the tank they left behind.

src/simulation/ — the tick and the system registry at its root, the core systems under systems/, the devices under equipment/, and the per-organism orchestrators under flora/ — plants and the blooms — and livestock/.