World-Creation stage after biomes. Two layers (raylib-free engine):
- Per-cell density scalars (flora/fauna/funga in [0,1]) derived from the
climate fields each tick (drive color modes 8/9/0). Flora = Liebig-min of
temp & moisture; fauna ~ flora with carnivores gated on local prey; funga =
moisture/organic-matter-led + cold-tolerant. Zero on water/ice.
- On-demand discrete population (key L, saved as v7): each land cell draws
broad archetypes from a comprehensive table into a per-kind slot cap +
density-scaled point budget (size -> cost), weighted by biome/climate
suitability and a regional bonus for same-biome neighbours. Separate RNG
seeded from cfg.seed so generating biota never perturbs tectonic determinism.
Organisms are labelled by taxonomy (Family + Size + role, e.g. "Felidae
(Big, Carnivore)") with the full Class > Order > Family tree stored, never an
informal common name. Cell-info panel word-wraps + aggregates duplicates so the
lists no longer get cut off.
New: src/sim/PlanetBiota.{hpp,cpp} + PlanetFlora/Fauna/FungiGen.cpp, color
modes/colors, bio* config knobs, save v7 (older saves load with empty
population), test_biota.cpp (densities, fauna<=capacity, carnivore gating,
slot/point budgets, determinism + RNG isolation, v7 round-trip). Docs updated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3.6 KiB
Biota — Flora · Fauna · Funga (density + slot/point population)
Status: implemented. This supersedes the original density-only sketch. The discrete slot/point design comes from
docs/fauna_generation_plan.md; this doc records the unified, shipped design. Code:src/sim/PlanetBiota.{hpp,cpp}+PlanetFloraGen/FaunaGen/FungiGen.cpp; testtest_biota.cpp; controls8/9/0(density views) +L(generate population).
Three kinds (Biota)
Living things are split into Flora (plants), Fauna (animals) and Funga (fungi). Funga is not a plant but is generated with a flora-like environmental system and its own rules; all three share the same per-cell slot/point logic.
Two layers
- Density scalars (
sFloraDensity/sFaunaDensity/sFungaDensity∈ [0,1]) — derived from the climate fields each tick (like biomes/climate), drive the colour views. 0 on water/Ice.- Flora = NPP-style Liebig minimum of a temperature factor
clamp((T−bioVegTempMin)/(bioVegTempOpt−bioVegTempMin),0,1)and a moisture factorclamp(sMoist/bioVegMoistRef,0,1). - Fauna = herbivore carrying capacity
clamp(floraDensity·bioFaunaProductivity,0,1); carnivores in the population are gated on neighbourhood prey ≥bioCarnPreyMin. - Funga =
min(moistFactor, bioFungaFloraWeight·floraDensity + (1−w)) · coldTolerance(bioFungaMoistRef,bioFungaTempMin) — thrives moist + with organic matter, persists in cold shade where flora thins, ~0 in hot dry desert.
- Flora = NPP-style Liebig minimum of a temperature factor
- Discrete slot/point population (
sBiota, saved v7) — generated on demand (generateBiota(), keyL, settled world). Each land cell draws broad archetypes (NOT real species) from the comprehensive append-only tablebiotaArchetypes()— each carries a Class/Order/Family + Size (Tiny..Huge), a biome mask and a climate tolerance. A cell has a per-kind slot cap (distinct types) and a density-scaled point budget (size → cost Tiny=1…Huge=5); archetypes are added until slots full or points exhausted. Selection is weighted by biome/climate suitability × a regional bonus for archetypes already placed in already-filled, same-biome neighbours (homogeneous regions, variety at boundaries). Organisms are named by taxonomy — Family + Size + role (fullClass > Order > Familyavailable), never an informal common name ("Felidae", not "cat"; Felidae is the family, cat a common name). Generalist families get a biome adjective ("Desert Muridae" / "Forest Muridae").
Config knobs (bio*, in planet.cfg)
bioVegTempMin(-5), bioVegTempOpt(15), bioVegMoistRef(0.5), bioFaunaProductivity(0.9),
bioCarnPreyMin(0.30), bioCarnScale(1.0), bioFungaMoistRef(0.4), bioFungaFloraWeight(0.6),
bioFungaTempMin(-15), bioRegionBonus(0.5), slot caps bioFlora/Fauna/FungaSlots(12/10/8),
point budgets bioFlora/Fauna/FungaPoints(20/16/14).
Determinism & persistence
generateBiota() uses a separate RNG seeded from cfg.seed (not Planet::rngState), so it
never perturbs tectonic determinism (asserted in test_biota.cpp). The population is saved
(save v7); densities are derived/not-saved. Older saves load with an empty population (press
L). The archetype table is append-only — indices are serialized.
Out of scope (future / Live World)
Time-evolving populations (growth, migration, predator-prey dynamics, extinction), seasons, and true species/typed organisms — reserved for the Live World real-time mode. This stage answers "what could live here", not "what is living/evolving here".