planetsim/docs/fauna-flora-plan.md
Jonas Reith 53e371bb2f Add Biota stage: flora, fauna & funga (density + slot/point population)
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>
2026-06-25 13:56:03 +02:00

3.6 KiB
Raw Permalink Blame History

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; test test_biota.cpp; controls 8/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

  1. 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((TbioVegTempMin)/(bioVegTempOptbioVegTempMin),0,1) and a moisture factor clamp(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 + (1w)) · coldTolerance (bioFungaMoistRef, bioFungaTempMin) — thrives moist + with organic matter, persists in cold shade where flora thins, ~0 in hot dry desert.
  2. Discrete slot/point population (sBiota, saved v7) — generated on demand (generateBiota(), key L, settled world). Each land cell draws broad archetypes (NOT real species) from the comprehensive append-only table biotaArchetypes() — 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 (full Class > Order > Family available), 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".