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

57 lines
3.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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"*.