docs(@projects/@magic-civilization): 🦌 p3-27 — concrete biosphere-headless implementation design

Researched the real ecology/flora crate APIs and recorded a ready-to-build spec: reuse
EcologyEngine (process_step + continuation_state save/restore) + EcologyConfig::from_json;
persist the opaque continuation-JSON on GameState (worldsim_state_json) + boot-load the config
bundle (#[serde(skip)] + FFI), mirroring the climate/events pattern. Ecology is already ticked
in GdFaunaEcology for the live game; the headless TurnProcessor just needs the same wiring.
7-step plan + test strategy captured.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Natalie 2026-06-26 17:03:54 -04:00
parent f8eadc9119
commit b8d2a1f20e

View file

@ -37,3 +37,41 @@ Created 2026-06-26. Needs grid fields for fauna/flora populations + fish_stock/r
persist on `state.grid` (or a parallel store) so a fresh per-turn processor operates on
persistent biosphere state — same pattern as climate state on the grid. Underlies the
plague/pandemic/marine events.
## Concrete implementation design (researched 2026-06-26, grounded in verified crate APIs)
**Existing machinery (reuse, don't rebuild):**
- `mc_ecology::engine::EcologyEngine``with_config(EcologyConfig)` + `load_species_library`,
`process_step(&mut GridState, dt: f32, seed: u64) -> Vec<FloraTransition>` (the per-turn
tick), `continuation_state() -> EcologyContinuationState`, `restore_continuation_state(..)`.
- `EcologyContinuationState` (engine.rs) — `#[derive(Default, Serialize, Deserialize)]`,
tuple-key serde; tile_populations + species_registry + tick_count. Already the opaque
`worldsim_state` save payload.
- `mc_ecology::config::EcologyConfig::from_json(land, food_web, social)`; species via
`load_species_library(&[&str])`.
- Already ticked in `GdFaunaEcology` (api-gdext/src/lib.rs:840) for the LIVE game; headless
`TurnProcessor` never constructs/ticks it (verified 0 hits).
- `mc-ecology` does NOT depend on `mc-state` → no circular-dep risk, but use opaque-JSON on
GameState to keep mc-state dep-free (mc-turn deps both and does the parse).
**Plan (mirrors the climate/events boot pattern):**
1. `GameState += #[serde(default)] pub worldsim_state_json: String` (persistent ecology
continuation — survives save/load) and `#[serde(skip)] pub ecology_config_json: String`
(boot-loaded config bundle: land/food_web/social + species JSON array).
2. `mc-turn::ecology_phase::process_ecology_phase(state)`: if `ecology_config_json` empty →
no-op (like climate's grid guard). Else build `EcologyEngine::with_config(parsed)` +
`load_species_library`, `restore_continuation_state` from `worldsim_state_json` (if set),
`process_step(grid, 1.0, seed)` → flora transitions, apply transitions to grid tiles,
then `state.worldsim_state_json = to_string(engine.continuation_state())`.
3. Wire into `step()` after climate (ecology reacts to the freshly-ticked climate).
4. FFI `GdPlayerApi::set_ecology_config_json` + harness `player_api_main._apply_ecology_config`
(bundle the ecology JSONs via DataLoader), mirroring `_apply_events_config`.
5. Flora succession: `mc-flora::FloraEngine` tick (same pattern) OR via the FloraTransitions
that `EcologyEngine::process_step` already returns — confirm whether ecology's process_step
subsumes flora succession before adding a separate flora phase.
6. Marine: port `marine_harvest.gd` (fish_stock/reef) — `mc_ecology::fish` module exists.
7. Then enable plague/pandemic/marine event categories (p3-26 B8) against the live populations.
Tests: deterministic — seed a population + minimal real config (`config::load_real_config`
test helper), tick via the phase, assert populations evolve + a flora transition applies +
continuation JSON round-trips.