diff --git a/.project/objectives/p3-27-biosphere-headless.md b/.project/objectives/p3-27-biosphere-headless.md index 4de8fe36..a282d85e 100644 --- a/.project/objectives/p3-27-biosphere-headless.md +++ b/.project/objectives/p3-27-biosphere-headless.md @@ -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` (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.