magicciv/.project/objectives/p2-53a-sentry-guard-action-kind.md
Natalie e5b9d10b61 feat(@projects/@magic-civilization): add lab and hud system components
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-05-01 22:23:54 -04:00

4 KiB

id title priority status scope owner updated_at coordinates_with evidence
p2-53a Sentry/Guard ActionKind — add Sentry/Unsentry to mc-core with wake-on-vision p2 done game1 wireguard 2026-05-01
p2-53
p1-20
p1-21
src/simulator/crates/mc-core/src/action.rs
src/simulator/crates/mc-turn/src/game_state.rs
src/simulator/crates/mc-turn/src/processor.rs
src/simulator/crates/mc-turn/src/action_handlers.rs
public/games/age-of-dwarves/data/unit_actions.json
src/game/engine/scenes/hud/unit_panel.gd

Summary

Gap 1 from p2-53: The design page at .project/designs/app/src/pages/UnitActions.tsx proposes Guard (sentry posture, no stat bonus, wakes on enemy entering vision range) as distinct from Fortify (cumulative dig-in, wakes only on adjacency). The shipped game had only Fortify/Unfortify. Decision: add ActionKind::Sentry / ActionKind::Unsentry with wake-on-vision predicate in processor.rs turn-end phase.

This is the canonical template objective for p2-53. The pattern established here — Rust enum variant + DisabledReason + UnitCapability field + legal_actions() gate + UnitState field + turn-phase hook + JSON keyword map + GDScript signal + action handler + tests + objective file — is the exact pattern followed by every downstream child (53f, 53g, 53h, 53i).

Mechanical definition:

  • Sentry: unit enters sentry posture. No stat bonus (unlike Fortify's cumulative defense). Consumes movement. Mutually exclusive with Fortify and Patrol.
  • Unsentry: manual exit from sentry posture. Always enabled while sentrying.
  • Wake-on-vision: at turn-end phase (after fauna encounters, before PvP combat — Phase 5a-sentry), any sentrying unit with an enemy unit within 2 hex radius automatically wakes (is_sentrying → false). This is the load-bearing distinction from Fortify.

Acceptance

  • ActionKind::Sentry and ActionKind::Unsentry added to mc-core/src/action.rs; as_str/from_str/display_order (23, 24) wired. See src/simulator/crates/mc-core/src/action.rs:43-44.
  • DisabledReason::AlreadySentrying and NotSentrying added with vocab_key entries "disabled_reason_already_sentrying" / "disabled_reason_not_sentrying". See src/simulator/crates/mc-core/src/action.rs:149-150.
  • UnitCapability::is_sentrying: bool added; legal_actions() gates: sentrying→Unsentry enabled + Sentry disabled(AlreadySentrying); fortified→Sentry disabled(AlreadyFortified); patrolling→Sentry disabled(AlreadyPatrolling); else enabled if has_movement. See src/simulator/crates/mc-core/src/action.rs.
  • UnitState::is_sentrying: bool added to mc-turn/src/game_state.rs with #[serde(default)]. See src/simulator/crates/mc-turn/src/game_state.rs.
  • ✓ Wake-on-vision phase wake_sentrying_units() added to processor.rs step() between Phase 5a (fauna encounters) and Phase 5b (PvP combat). See src/simulator/crates/mc-turn/src/processor.rs.
  • handle_sentry() and handle_unsentry() added to action_handlers.rs; Sentry/Unsentry match arms wired in invoke(). See src/simulator/crates/mc-turn/src/action_handlers.rs.
  • unit_actions.json adds "sentry" to by_unit_type melee/ranged arrays and "sentry" keyword in by_keyword. See public/games/age-of-dwarves/data/unit_actions.json.
  • unit_panel.gd _KIND_TO_SIGNAL wires "sentry" and "unsentry""sentry_pressed" signal; signal declared. See src/game/engine/scenes/hud/unit_panel.gd.
  • cargo test -p mc-core -p mc-turn --lib passes: mc-core 83/83, mc-turn 154/154 (1 ignored pre-existing). Four new sentry tests added.
  • cargo check --workspace clean (solo_dominion is_sentrying field also patched).

Non-goals

  • Wiring Sentry in the GDExtension bridge's legal_actions_for signature with a live is_sentrying parameter (the bridge defaults to false until the GDScript Unit.gd exposes the field — follow-up).
  • Aerial, heroic, or caravan actions (Game 2/3 scope per scope-game1-vs-game2.md).
  • Per-archetype specials (53f/53g/53h/53i follow the pattern established here).