Growth speed vs height
Shorter seedling_hours/young_hours reach maturity — and reproduction — sooner, but trade away the final height that wins light. The classic fast-and-small versus slow-and-tall split.
The Living World
This page is a roadmap, not a changelog. Today every oak in FloraForge shares one fixed recipe. The plan is to make those numbers heritable — a tiny genome per plant, mutating as it spreads — so that, over many sim-days, populations drift to fit the ground they grow on. The remarkable part is how little new machinery it needs: the growth and spread systems already shipped do most of the work.
The baseline
A species is currently a fixed recipe: a single JSON file plus a placement profile. Every individual of that species shares the exact same numbers; two oaks differ only because each is shaped by its own per-plant random seed. Nothing a plant experiences in the world changes what it passes on, because today it passes on nothing at all.
Body plan and height range, trunk taper, base flare and straightness, branching (apical dominance, max depth, the 137.5° spiral arrangement, insertion angles, gravity response), crown shape, density and asymmetry, foliage style, and bark/leaf colour. The growth engine expands these into a unique 3D plant.
Where the recipe is allowed to grow: permitted biomes, a spawn weight, a
moisture band, an altitude band, a near-water boost, a maximum slope, and the
life-cycle numbers — spread_radius, spread_chance,
seedling_hours, young_hours.
The single source of individuality today. It jitters geometry within the recipe's bounds, but it is not inherited — a plant's offspring start from the same preset, not from their parent.
The vision
The planned change is a single shift in where a trait's value comes from: not the shared preset, but the individual plant. Five steps, drawn as a loop because that is exactly what it is — each generation feeds the next.
1 Seed a genomePlanned
Each plant carries a compact vector of trait values, initialised from its species preset. At world creation every individual is still effectively the baseline — the genome simply records it explicitly.
2 Inherit & mutatePlanned
On the daily spread pass, a seedling copies its parent's genome with small, bounded mutations. Reproduction already exists — this rides the same pass.
3 Selection, for freeAlready in the engine
The existing placement validation is the fitness function. A drought-tolerant mutant's seedlings survive where the baseline is rejected — no new code path, just a candidate that passes a test its parent's offspring would fail.
4 Drift to fitPlanned
Over many sim-days, populations shift to match local terrain: willows hugging rivers ever tighter, oaks on dry ridges growing shorter and deeper-rooted.
5 SpeciationPlanned
When a local population's genome drifts far enough from the preset, it is promoted to a named variant in the herbarium — a new species born from place.
Only inherit and mutate are new. Maturation runs on the analytic growth clock that already exists; selection is the placement validation that already gatekeeps every seedling. Evolution is mostly wiring, not invention.
Candidates
Not every number should be heritable, but the placement profile is full of values that map cleanly onto real evolutionary trade-offs. A shortlist of strong candidates, each one a tension rather than a free win.
Shorter seedling_hours/young_hours reach maturity — and reproduction — sooner, but trade away the final height that wins light. The classic fast-and-small versus slow-and-tall split.
Widening the lower edge of the min_moisture band lets seedlings survive drier ground, opening grassland and desert fringes the baseline is rejected from.
Raising max_altitude and shrugging off steeper max_slope pushes a lineage up the mountains, toward ground its ancestors could not hold.
High spread_chance with short spread_radius floods nearby ground with cheap seeds; the opposite invests in fewer, farther, more robust ones. Many cheap vs few hardy.
A stronger near_water_boost binds a lineage to shorelines and river margins — the niche willows and palms already lean into, sharpened generation by generation.
A denser crown gathers more light but catches more wind on exposed ridges. A form trait whose pay-off depends on where the plant ends up standing.
Colour drifting with climate makes adaptation visible: a hillside whose oaks have paled or reddened as their genome diverged from the lowland stock — evolution you can see from the air.
The hoped-for outcome: a single ancestral species, carried across a moisture gradient, drifting into distinct local forms — without any of those forms being hand-authored. Selection writes them, the terrain decides.
Engineering
Evolution is appealing in the abstract and ruinous in the details if the data model fights it. FloraForge's does not — but only if the design respects four hard constraints the existing systems impose. Honesty about these is what keeps the plan tractable.
A plant is a packed 16-byte struct — quantized position and height, rotation, a species index, a stage byte, and born_hour. Millions are held resident. A genome has to be a handful of compact, quantized values, not a sprawling record.
Stage is computed from age on demand, not advanced per tick. Heritable life-cycle traits must keep that property: a genome can change the thresholds, but the model stays a pure function of age.
Spread RNG is keyed on a plant's index within its chunk and the world seed, so a downloaded base snapshot and a local regeneration evolve identically. Mutation must draw from that same keyed stream — reproducible from the seed, never wall-clock random.
The base world is regenerable and versioned by a gen_key; only the spread-delta is saved. Heritable genomes therefore belong to spread offspring, layered on top of the snapshot — not baked into the base every client downloads.
Heritable traits build directly on growth and spread. Read how the life cycle works today, or head back to the field guide for the species and biomes this all grows from.
Growth & Life Cycle Back to the Field Guide