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>
57 lines
3.6 KiB
Markdown
57 lines
3.6 KiB
Markdown
# 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((T−bioVegTempMin)/(bioVegTempOpt−bioVegTempMin),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 + (1−w)) · 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"*.
|