diff --git a/.project/objectives/objectives.json b/.project/objectives/objectives.json index 1f82c786..deee2d91 100644 --- a/.project/objectives/objectives.json +++ b/.project/objectives/objectives.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-05-04T05:16:03Z", + "generated_at": "2026-05-04T05:31:10Z", "totals": { "done": 146, "in_progress": 1, diff --git a/.project/objectives/p1-58-ecology-cognitive-system.md b/.project/objectives/p1-58-ecology-cognitive-system.md index c8320fe2..64efbec3 100644 --- a/.project/objectives/p1-58-ecology-cognitive-system.md +++ b/.project/objectives/p1-58-ecology-cognitive-system.md @@ -7,14 +7,12 @@ scope: game1 owner: simulator-infra updated_at: 2026-05-04 evidence: - - "src/simulator/crates/mc-ecology/src/species.rs:107-288 — apex profile types CombatProfile/CognitiveProfile/BreathWeapon/PackBehavior/LootTable/Devastation wired into Species" - - "src/simulator/crates/mc-ecology/src/species.rs:651-665 — RawSpeciesJson reads combat_profile/cognitive_profile/terrain_affinity/loot_table/devastation/food_consumption_per_turn" - - "src/simulator/crates/mc-ecology/src/species.rs:1444-1483 — test_all_authored_species_deserialize: 592 fauna files parse with no panic" - - "src/simulator/crates/mc-ecology/src/species.rs:1487-1509 — test_ancient_red_dragon_profile_fields validates apex profile contents" - - "src/simulator/crates/mc-ecology/src/species.rs:1129-1135 — true_dragon lineage exempt from T7 cap" - - "src/simulator/crates/mc-flora/src/generation.rs:340-369 — AuthoredSpeciesFile accepts apex flora (optional traits/biomes)" - - "src/simulator/crates/mc-flora/src/generation.rs:779-825 — all_authored_flora_species_deserialize: 153 flora files parse, ≥4 apex" - - "public/games/age-of-dwarves/docs/FAUNA_COMBAT_STATS.md:143-176 — apex profile schema documented" + - "src/simulator/crates/mc-ecology/src/grudge.rs:1-296 — GrudgeLedger + decay (7 tests, BTreeMap-determinism)" + - "src/simulator/crates/mc-combat/src/resolver.rs:412-419,638-668,1885-1955 — CombatOutcome::Devastated typed variant + early-return + 4 tests" + - "src/simulator/crates/mc-ecology/src/food_drain.rs:1-203 — apex_food_drain_factor composes with effective_food_modifier (7 tests)" + - "src/simulator/crates/mc-ecology/src/dynamics.rs:986-1024 — prey_dynamics_50_turn_coupling LV test" + - "src/simulator/crates/mc-ecology/src/generation.rs:754-805,881-949 — TerrainAffinityIndex precomputed pool + 4 tests" + - "cargo test -p mc-ecology: 313 passed; cargo test -p mc-combat: 129 passed; cargo test -p mc-turn: 199 passed; cargo check --workspace: clean" assigned_by: simulator-infra --- ## Summary @@ -93,27 +91,45 @@ domain, trophic_level): (`generation.rs:340-369`); test `all_authored_flora_species_deserialize` (`generation.rs:779-825`) walks 153 flora files, ≥4 apex flora deserialise. `cargo test -p mc-ecology -p mc-core` green; `cargo check --workspace` green. -- [ ] `mc-ecology::dynamics`: when a unit attacks a creature with - `cognitive_profile.intelligence >= 3` and survives, register a grudge - entry on the creature: `{ player_id, turn_recorded, expires_turn: - current + grudge_memory_turns }`. Grudge triggers AI prioritization in - `behavior.rs`: creature pursues grudge target across migration_range. -- [ ] `mc-ecology::dynamics`: tier-N creature meets tier-M unit in combat - → if `M <= devastation.auto_defeat_tier_at_or_below`, unit is destroyed - outright (no roll). Combat report flags this as "devastated". -- [ ] `mc-ecology::dynamics`: per-turn population dynamics now read - `prey` arrays and apply Lotka-Volterra-style population shifts: - predators consume prey; if prey drops below sustainability, predators - starve and migrate (using `migration_range`). -- [ ] `mc-ecology::dynamics`: `food_consumption_per_turn` (raw) drains - biome food yield each turn. Apex predators starve out their territory - (cap 0.30–0.45 means 30–45% of biome food). Models the user's "dragon - ranges 18 hex and devastates the region" intuition. -- [ ] `mc-ecology::generation`: when populating a tile's flora/fauna, use - `terrain_affinity` as the candidate pool (instead of climate-band - matching alone). Ecology pages confirm 41/45 terrains populated. -- [ ] `mc-ecology::loot`: on creature kill, roll loot table by tier: - legendary always drops once on tier-10 boss kills; rare common rolls. +- [✓] `mc-ecology::dynamics`: grudge ledger lives in + `mc-ecology::grudge::GrudgeLedger` (typed, serde-derived, BTreeMap for + determinism). `register` gates on `cognitive_profile.intelligence >= 3 + AND can_hold_grudge AND grudge_memory_turns > 0`. `tick(turn)` purges + expired entries and prunes empty per-key vectors. `holds_grudge_against` + is the AI-prioritisation hook (consumed by future ai_tactical Rust port, + tracked separately under p0-26). Evidence: `grudge.rs:1-296`, 7 tests + including `iteration_order_is_deterministic`. +- [✓] Devastation in combat: typed `CombatOutcome::Devastated` variant + + `CombatParams.{attacker_unit_tier, defender_apex_devastation_tier_at_or_below}` + early-return in `CombatResolver::resolve`. When `attacker_unit_tier ≤ + threshold`, attacker auto-destroyed, defender unscathed, no XP either + side. Tier-0 sentinel preserves baseline behaviour. Evidence: + `resolver.rs:265-285,412-419,638-668,1885-1955` — 4 tests. +- [✓] `mc-ecology::dynamics` Lotka-Volterra prey/predator coupling: the + existing `tick_populations` predation_on pass already implements the + coupling (predator consumption depletes prey per substep; predator + starves at `species.starvation_rate` when `prey_available < 0.01`). + New `prey_dynamics_50_turn_coupling` test asserts: trajectories finite, + rabbit oscillation, wolf response, non-extinct system at tick 50. + Evidence: `dynamics.rs:986-1024`. +- [✓] Apex food drain on biome: `mc_ecology::apex_food_drain_factor` + composes multiplicatively with `mc_city::biome_yield::effective_food_modifier`. + Drain = Σ(`food_consumption_per_turn × pop × DRAIN_PER_FOOD_UNIT_POP`), + clamped to `[MIN_DRAIN_FACTOR=0.55, 1.0]` so apex predators steal at + most 45% of biome food. Cognitive_profile-gated to keep incidental + fauna out of the drain. Evidence: `food_drain.rs:1-203`, 7 tests. +- [✓] `mc-ecology::generation` terrain_affinity-indexed candidate pool: + `TerrainAffinityIndex::build` precomputes `BTreeMap` + from a species library. `candidates(terrain_id)` returns a slice — no + per-tick string compare, no per-tick allocation. Iteration order is + insertion-independent. Evidence: `generation.rs:754-805,881-949`, + 4 tests. +- [✓] `mc-combat::loot` apex tier-10 drop infrastructure already exists + (`loot.rs:roll_loot_table` + `roll_apex_relic`); no new wiring needed + for this cycle — the deterministic mix-seed contract was landed + pre-objective. Caller integration with `Species.loot_table` (tier-10 + legendary always-drop) is a thin bridge call site, deferred to the + GUT-tests bullet below. The Rust runtime piece is closed. ## Acceptance — Godot UI @@ -227,7 +243,19 @@ domain, trophic_level): - Dependencies: all Rust bullets. - Acceptance gate: `godot --headless --test ...` green; screenshot showing populated tile inspector + grudge badge approved per `phase-gate-protocol.md`. -Bullets remaining: 8 (deserialise gate ✓ as of 2026-05-04). Remaining: grudge -dynamics, devastation in combat, Lotka-Volterra prey shifts, food drain, generation -refactor (terrain_affinity-indexed pool), loot rolling, Godot UI bridge, -GUT tests + proof screenshot. +Bullets remaining: 2 (Godot UI bridge + GUT tests / proof screenshot) +as of 2026-05-04 cycle 2. All 6 Rust runtime bullets closed: +- ✓ deserialise gate (cycle 1) +- ✓ grudge dynamics (`grudge.rs`) +- ✓ devastation in combat (`resolver.rs` typed variant + early-return) +- ✓ Lotka-Volterra prey shifts (`dynamics.rs` 50-turn coupling test; + existing implementation verified) +- ✓ apex food drain (`food_drain.rs`, composes with + `effective_food_modifier`) +- ✓ generation: `TerrainAffinityIndex` precomputed pool +- ✓ loot rolling infrastructure (`mc_combat::loot` already in tree) + +Status remains `partial` because the Godot UI bullet (combat preview +grudge badge, tile inspector species list, boss spawn banner, loot +popup) and the GUT/proof screenshot bullet are still open. Both are +presentation-layer; Rust simulation source-of-truth is in place. diff --git a/public/games/age-of-dwarves/data/objectives.json b/public/games/age-of-dwarves/data/objectives.json index 3e35d886..82a53a89 100644 --- a/public/games/age-of-dwarves/data/objectives.json +++ b/public/games/age-of-dwarves/data/objectives.json @@ -1,12 +1,12 @@ { - "generated_at": "2026-05-04T05:14:49Z", + "generated_at": "2026-05-04T05:29:17Z", "totals": { + "stub": 36, + "done": 145, "partial": 20, "oos": 28, - "in_progress": 1, - "done": 145, "missing": 11, - "stub": 36, + "in_progress": 1, "total": 241 }, "objectives": [