magicciv/.project/objectives/p2-58b-ambient-encounter-hook.md
Natalie 4203a301cf feat(@projects/@magic-civilization): add ambient encounter roll completion status
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-05-06 23:37:16 -07:00

3 KiB

id title priority status scope owner updated_at evidence
p2-58b Ambient encounter hook — mc-turn::movement calls roll_ambient_encounter per tile step p2 done game1 unassigned 2026-05-07
src/game/engine/tests/integration/test_p2_58b_ambient_encounter.gd — headless GUT test asserting ambient_encounter_count ≥ 1 within 50 steps at fauna_density=0.8 (cycle 39)
src/simulator/api-gdext/src/lib.rs — turn_result_to_dict extended with ambient_encounter_count + ambient_encounters[] from TurnEvent::AmbientEncounterFired (cycle 39)
src/simulator/api-gdext/src/lib.rs — dict_to_tile extended for fauna_density + ecosystem_tier + fauna_index (cycle 39)
src/game/engine/src/autoloads/event_bus.gd — ambient_encounter_fired signal declared (cycle 39)
src/simulator/crates/mc-turn/tests/ambient_encounter_integration.rs — Rust 1/1 passing (prior cycles)
cargo check -p magic-civ-physics-gdext — clean (cycle 39)

Summary

With TileState.fauna_density and TileState.fauna_index now populated (p2-58a), the per-tile-moved hook in mc-turn::movement (or processor.rs movement phase) can build AmbientTileCtx from the live GameState and call mc_ecology::encounter::roll_ambient_encounter(...).

Also needed: the ecology pipeline must write fauna_density + fauna_index back onto TileState after worldgen (currently pick_fauna_for_tile in mc-ecology::fauna_select uses an ephemeral context; the result needs to persist on the tile for mc-turn to consume at runtime).

Acceptance

  • mc-ecology finalise pass not needed — fauna_density and fauna_index are already on TileState from p2-58a (worldgen writes them directly). The hook reads them at runtime from GameState::grid.tiles[tile_idx].
  • mc-turn::processor.rs Step 1b builds AmbientTileCtx from TileState.fauna_density + .fauna_index per unit per turn.
  • ✓ Calls mc_core::encounter::roll_ambient_encounter(ctx, unit_kind, rates, &mut rng) and pushes TurnEvent::AmbientEncounterFired to result.events_emitted.
  • cargo test -p mc-turn --test ambient_encounter_integration — 1/1 passing (50-step walk through fauna_density=0.8 tile yields ≥1 encounter, seeded deterministic).
  • ✓ GUT integration test: test_p2_58b_ambient_encounter.gd — headless GUT test asserting step() result ambient_encounter_count ≥ 1 within 50 steps at fauna_density=0.8, ecosystem_tier=5. Additionally asserts barren tile (density=0.0) yields zero encounters. EventBus.ambient_encounter_fired signal declared in event_bus.gd for live-game dispatch. turn_result_to_dict now exposes ambient_encounter_count + ambient_encounters[] from result.events_emitted. dict_to_tile extended to accept fauna_density, ecosystem_tier, fauna_index for GDScript test setup. (cycle 39)

Out of scope

  • Pioneer escort rules (p2-59).
  • Lair siege/assault/raid (p3-10).
  • Encounter narrative text / event cards — separate UI objective.