The soil holds a fixed number of seed "slots". Every simulated year the seed bank S (seeds/m²) evolves continuously between disturbances:
Seed rain (input): dS/dt += R (rain rate, /m²/yr)
Background loss: dS/dt −= L · S (decay + predation, fraction/yr)
Both terms are applied as a real per-seed stochastic birth/death process on the slot population, not a scripted animation: each simulated year a Poisson-like number of slots is activated (rain) or deactivated (loss) so the on-screen seed count is the literal state variable, not a proxy for it.
A disturbance does not remove seeds directly. It sets a germination cue strength c (0–1) — fire ≈ 0.85, tillage ≈ 0.55, canopy gap ≈ 0.30, each further scaled by the intensity slider — and the germinated fraction is read off a logistic response curve:
germination fraction: f(c) = 1 / (1 + e^(−k·(c − c₀))) k=9, c₀=0.45
germinated seeds: ΔS = f(c) · S(t) (subtracted from S immediately)
Because f(c) is monotonically increasing, a stronger disturbance (higher effective cue strength) always germinates a larger share of whatever seed bank has accumulated since the last event — a real threshold-triggered pulse, not a fixed percentage. Between pulses S climbs back up as seed rain keeps falling on the undisturbed plot, exactly like a real forest floor refilling its dormant seed bank between fires or ploughings.
- Seed rain input — how fast new dormant seeds arrive from surrounding vegetation.
- Background loss — how fast standing dormant seeds lose viability or are eaten while waiting.
- Disturbance intensity — multiplies every disturbance type's cue strength before it hits the logistic curve.