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 |
|
|
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::SentryandActionKind::Unsentryadded tomc-core/src/action.rs;as_str/from_str/display_order(23, 24) wired. Seesrc/simulator/crates/mc-core/src/action.rs:43-44. - ✓
DisabledReason::AlreadySentryingandNotSentryingadded withvocab_keyentries"disabled_reason_already_sentrying"/"disabled_reason_not_sentrying". Seesrc/simulator/crates/mc-core/src/action.rs:149-150. - ✓
UnitCapability::is_sentrying: booladded;legal_actions()gates: sentrying→Unsentry enabled + Sentry disabled(AlreadySentrying); fortified→Sentry disabled(AlreadyFortified); patrolling→Sentry disabled(AlreadyPatrolling); else enabled if has_movement. Seesrc/simulator/crates/mc-core/src/action.rs. - ✓
UnitState::is_sentrying: booladded tomc-turn/src/game_state.rswith#[serde(default)]. Seesrc/simulator/crates/mc-turn/src/game_state.rs. - ✓ Wake-on-vision phase
wake_sentrying_units()added toprocessor.rsstep()between Phase 5a (fauna encounters) and Phase 5b (PvP combat). Seesrc/simulator/crates/mc-turn/src/processor.rs. - ✓
handle_sentry()andhandle_unsentry()added toaction_handlers.rs; Sentry/Unsentry match arms wired ininvoke(). Seesrc/simulator/crates/mc-turn/src/action_handlers.rs. - ✓
unit_actions.jsonadds"sentry"toby_unit_typemelee/ranged arrays and"sentry"keyword inby_keyword. Seepublic/games/age-of-dwarves/data/unit_actions.json. - ✓
unit_panel.gd_KIND_TO_SIGNALwires"sentry"and"unsentry"→"sentry_pressed"signal; signal declared. Seesrc/game/engine/scenes/hud/unit_panel.gd. - ✓
cargo test -p mc-core -p mc-turn --libpasses: mc-core 83/83, mc-turn 154/154 (1 ignored pre-existing). Four new sentry tests added. - ✓
cargo check --workspaceclean (solo_dominionis_sentryingfield also patched).
Non-goals
- Wiring Sentry in the GDExtension bridge's
legal_actions_forsignature with a liveis_sentryingparameter (the bridge defaults tofalseuntil the GDScriptUnit.gdexposes 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).