games/fort-nash: fix code-review findings in the engine

games/fort-nash: fix code-review findings in the engine

#31 in Riparion/riparion-retro — merged 2026-06-11

Fixes seven findings from a recall-biased code review of the new fort-nash crate (all in the engine).

Correctness

  1. Ice-death lost message — the fatal frozen-Cumberland crossing did message_keyed(...) then die() then return with no advance(), so the "ice splinters…" line was orphaned (GameOver never drains the queue). Now drains it first, like every other death-with-narration path.
  2. resolve_shot fabricated a gunfightself.shot.take().unwrap_or(ShotPurpose::Bandits) would resolve a desynced/None shot as a Bandits fight (deducting bullets/coin). Now let Some(purpose) = self.shot.take() else { return }, a no-op like the other resolvers.
  3. begin() incomplete reset — it now also resets resume, shot_word, and pending_task, so a new game can't inherit a previous run's minigame/resume state.

Cleanup / altitude

5 + 9. Six-fold pending slots / single-variant SteadyTask — the four pending_* slots collapse into one pending_task: Option<MiniTask> (Dose/Ice/Sequence/Brigade, with a mode() method), and SteadyTask is folded into MiniTask::Ice with its one-arm match inlined. The UI reads via illness_task()/sequence_task()/brigade_task()/is_ice_crossing(). This is the same consolidation already applied to sibling kaintuck. 7. Duplicated pass fall-through — extracted resume_after_mountain_incident(), shared by resolve_climb and the blizzard arm of resolve_brigade (and fixed the stale "Blue Mountains" comment). 8. terrain_kind() magic literals — replaced with a CHECKPOINTS table that references the named mile constants, so the displayed terrain can't drift from where the passes fire.

Notes

  • SAVE_VERSION bumped to 2 (#5/#9 change the serialized Game); v1 saves fall back to a fresh game. Crate bumped 0.1.3 → 0.1.4.
  • Adds a regression test for the ice-break narration; all 50 engine tests pass, clippy clean.

Deliberately not in this PR

  • Out-of-order minigame intro messages — this is the codebase's universal "queue message → launch minigame → message shows after" pattern (e.g. outlaws → gunfight); changing only blizzard/cold would make them inconsistent, and a global fix needs new resume machinery.
  • Engine duplication with oregon-trailfort-nash's engine is a near-copy of the Oregon Trail engine; extracting the shared turn-loop/leg machine into retro-kit and rewiring three games is a multi-crate project that warrants its own PR.

🤖 Generated with Claude Code

Last updated 2026-06-12