minigames-kit: add Heave (sustained-exertion) minigame

minigames-kit: add Heave (sustained-exertion) minigame

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

What

Adds Heave, the ninth minigame in minigames-kit — the "strain against resistance" mechanic specced in TODO_CAVE_MINIGAMES.md.

Press and hold to pour force into a load bar; it eases off when released. Resistance gives way in stages (each needs its threshold held for a few ticks) while a grip meter drains the whole time, faster while bearing down. Push past the slip ceiling and you lose your hold — load snaps to zero, grip takes a hit. The skill is pacing — heave, breathe, heave — not mashing.

Fills a real gap: TimingBar is a single instant, SteadyHands is fine correction; neither is sustained exertion. Maps to the cave's >STRAIN!< moments (prying the five-foot clam with the trident, forcing the oil-freed door).

Contract (same as the other eight)

  • Feature-gated module heave (added to all); kit bumped to 0.1.7.
  • 20 ms tick counter; seeded, deterministic stage curve.
  • Pure, unit-tested physics kept out of the UI: stage_threshold() and HeaveState::step().
  • Plain HeaveResult { opened, stages_cleared, stages, slips, grip_left } via on_complete; scoring left to the host.
  • Press-vs-not input only (no coordinate math) → one-thumbed on touch.
  • Standalone runnable demo crate examples/heave (just example heave).

One refinement over the spec: grip drains at a reduced idle rate so a do-nothing run always terminates (otherwise never-pressing would hang the minigame).

Tests

cargo test -p minigames-kit — 6 new Heave tests pass, including the behavioral guarantees: never-pressing fails with no progress, mashing slips and can't open it, and paced play in the holding band opens it cleanly with no slips. cargo check -p minigames-kit-heave compiles the demo.

🤖 Generated with Claude Code

Last updated 2026-06-12