7 KiB
7 KiB
| id | title | priority | status | scope | owner | updated_at | evidence | blocked_by | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| p3-13c | Biological events — plague, bloom, migration_pulse | p3 | done | game1 | unassigned | 2026-05-13 |
|
Context
public/games/age-of-dwarves/docs/ECOLOGY_BINDING.md describes biological dynamics riding on the flora/fauna indexes. This objective adds three turn-derived biological events: plague (pop-density × low-medical), bloom (favourable climate window → flora yield spike), migration_pulse (fauna density wave through corridors).
Acceptance
- ✓
mc-ecology::derive_biological_events(grid, thresholds, turn, seed) -> Vec<BiologicalEvent>returnsPlague { col,row,severity },Bloom { col,row,intensity },MigrationPulse { from_col,from_row,to_col,to_row,magnitude }. Signature differs from the spec (turn,world,players): tile-only signals per Out-of-scope §;playersdeferred.src/simulator/crates/mc-ecology/src/biological.rs:175-260. - ✓ Typed
BiologicalEventenum lives inmc-ecology::biological(re-exported from crate root) rather thanmc-core::events— sibling cratesmc-climate::weather::WeatherEventfollow the same in-domain pattern, nomc-core::eventsmodule exists.src/simulator/crates/mc-ecology/src/biological.rs:42-65+src/simulator/crates/mc-ecology/src/lib.rs:36-43. - ✓ Plague per-city pop-density × inverse-medical-buildings + adjacent-city spread. Tile proxy:
civilization_presence× lowquality. Adjacency spread second pass (lines 327-357): for each primary plague source, each of 6 axial neighbours receives a spread Plague event ifcivilization_presence ≥ plague_civ_min * plague_spread_factorandquality ≤ plague_quality_max; spread severity = source ×plague_spread_severity_scale; deduped via HashSet so primary-infected tiles are never double-counted.test_plague_spreads_to_adjacent_citiescovers the cluster and severity-attenuation assertions. - ✓ Bloom "N consecutive turns" optimal window. Streak implemented (p3-13c closure, 2026-05-13):
TileState::bloom_streak: u8added tomc-core::grid::TileStatewith#[serde(default)]for save backward-compat (src/simulator/crates/mc-core/src/grid/mod.rs:284-291).mc_ecology::biological::advance_bloom_streak(grid, thresholds)(biological.rs:205-232) increments per-tile when the climate window holds (mean_temp ∈ [temp_min,temp_max],mean_precip ≥ precip_min,canopy_cover ≥ canopy_min,undergrowth ≥ undergrowth_min) and resets to 0 otherwise; saturates atu8::MAX. Bloom emission gates ontile.bloom_streak >= thresholds.bloom_streak_min(default 3, configurable via JSONbloom.streak_min). Wired intomc-sim::event_dispatch::dispatch_world_eventsimmediately beforederive_biological_eventseach turn (event_dispatch.rs:73-95).test_bloom_requires_consecutive_turnsverifies streak<min suppresses bloom across turns 1+2, streak≥min fires on turn 3, and window-break resets streak to 0. - ✓ Migration pulse along corridor with per-tile fauna-density check. Multi-hop chain walk (lines 270-324): from each qualifying source (≥
migration_source_min), attempts up tomigration_max_hopssingle-turn hops; each hop picks the first axial neighbour withlair_population ≤ migration_neighbour_maxand(source_pop - neighbour_pop) ≥ migration_differential_min;source_popheld constant across the chain so the wave propagates through depleted corridor tiles without diminishing; emits oneMigrationPulseper hop.test_migration_multi_hop_corridorcovers 2-hop corridor andmax_hopscap. - ✓
cargo test -p mc-ecologygreen:test_plague_spreads_via_density,test_bloom_requires_optimal_window,test_migration_pulse_traverses_corridorall pass; suite total 317 (313 pre-existing + 4 new incl.thresholds_load_from_spec_json). Run fromsrc/simulator/:cargo test -p mc-ecology --lib.src/simulator/crates/mc-ecology/src/biological.rs:280-410.
Source-of-truth rails
- Rust crate:
mc-ecology::biologicalowns event derivation. ✓ - JSON path: spec said
public/resources/ecology/biological/_config.json; landed atpublic/games/age-of-dwarves/data/balance/biological_events.jsonper closing-task directive (thedata/balance/dir is the established home for tunable thresholds —EVENT_FREQUENCY_SPEC.mdcross-refs balance-style files;public/resources/ecology/{flora,fauna}/remains species data). - Enum location:
mc-ecology::biological::BiologicalEvent(typed; not in mc-core — siblingmc-climate::weather::WeatherEventprecedent). NoEventSeverityreuse: p3-13a's WeatherEvent encodes severity inline asf32, so we follow that convention.
Out of scope
- Cross-realm plague diplomacy effects — separate ticket.
- New species authoring.
- Player remediation (medical buildings effect) tuning.
References
public/games/age-of-dwarves/docs/ECOLOGY_BINDING.md- Sibling:
p3-13a,p3-13b,p3-13d