0.5m sim tiles for movement/LOS granularity, 1m visual tiles for proportional art and readable spaces (2x retina factor). All world geometry constrained to 2x2 sim tile minimum so cover/LOS maps 1:1 with visuals. Entities occupy 1x1 sim tiles for fine positioning. Updates: D-043, D-044, D-051, D-056, D-059 annotations, workshop outcomes (art direction + control/interaction), sprint 6 briefings, decision index, and CLAUDE.md. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
8.8 KiB
8.8 KiB
Sprint 6: Touch — Server Tasks
Goal: Movement stances, fog rebuild, multi-verb interactions, and smuggler inventory
Branch: server
Agents: Dudley (simulation), Tyre (architecture), Hoshe (QA)
New Tickets
| # | Title | Blocked by |
|---|---|---|
| #449 | ObserverSnapshot v6 — add player_stance, player_inventory wire fields | — |
| #417 | Stance system — Sprint/Walk/Careful/Crouch with tick-based movement | #444 (done) |
| #418 | MovementProfile component per archetype | #417 |
| #419 | Sprint interaction buffer suppression | #417 |
| #420 | Same-tile occupancy — TilePresence with posture layers | #444 (done) |
| #421 | ObjectType component + verb sets per type | — |
| #422 | Two-phase verb computation — KG-gated Phase 2 observer filter | #421 |
| #424 | Smuggler inventory — CarriedBy component, Take/Place verbs, info boundary | #445 (done) |
| #428 | Sprint anomaly monologue — double-take survival | — |
Use db/connectors/ticket show <id> for full details.
Key Decisions
decisions/scope.md— D-053 (Movement as stance toggle system), D-065 (Smuggler inventory)decisions/architecture.md— D-054 (Tile-based movement with same-tile occupancy), D-055 (Sprint explicitly suppresses interaction buffer)decisions/perception.md— D-057 (Entity interaction — vertical list, two-phase verb computation)
Open Questions Resolved
- OQ-01: Tile size — Resolved to 0.5m x 0.5m sim tiles (ticket #444, done). Amended by D-066: dual-scale grid with 1m visual tiles (2x retina factor). All world geometry 2x2 sim tile minimum.
- OQ-24: Inventory capacity — Resolved to 3x3 grid = 9 slots universal (ticket #445, done)
Notes
#449: ObserverSnapshot v6 — player_stance, player_inventory
- What exists:
server/src/bridge/types.rsdefines ObserverSnapshot v5 (current version: 4, see line 30-48) - Needs: Add two new fields to ObserverSnapshot struct:
player_stance: MovementStance(enum: Sprint/Walk/Careful/Crouch)player_inventory: Vec<VisibleItem>(items carried by player, visible to player only per D-010 info boundary)
- Integration: #417 provides MovementStance enum, #424 provides CarriedBy component query
- Critical path: This ticket unblocks client #439 (stance UI) and #438 (inventory UI)
#417: Stance system — tick-based movement
- What exists:
server/src/simulation/movement.rshas basic movement at 1 tile/2 ticks (Walk default) - Needs: Add MovementStance component (enum: Sprint/Walk/Careful/Crouch/Prone), implement stance ladder toggling via PlayerAction::ToggleStance, apply tick multipliers per stance (Sprint=1/1, Walk=1/2, Careful=1/3, Crouch=TBD), wire monologue rate modifiers (Sprint=40%, Walk=100%, Careful=150%)
- D-053 spec: Sprint suppresses monologue to 40%, Careful enhances it to 150%. Perception coupling is multiplicative. No vision cone changes (cognitive, not sensory).
- Gotcha: Prone is toggle-out only in normal play (must stand up explicitly). Future combat allows "hit the deck" quick-entry. v0.1 scope: Sprint/Walk/Careful/Crouch only.
- Integration: Blocks #418 (MovementProfile), #419 (sprint suppression), #426 (ListeningFocus deferred), #439 (client stance UI)
#418: MovementProfile component per archetype
- Needs: Add MovementProfile component storing default stance per archetype (smuggler=Walk, detective=Walk). Apply on spawn.
- Rationale: Future archetypes may have different defaults (e.g., maintenance worker defaults to Careful). Smuggler and detective both start Walk for v0.1.
- Integration: Blocked by #417 (stance system must exist first)
#419: Sprint interaction buffer suppression
- What exists:
server/src/simulation/interaction.rscomputes nearby_interactions for ObserverSnapshot - Needs: When player stance == Sprint, explicitly clear interaction buffer (nearby_interactions = empty vec). Anomaly monologue survives sprint (D-055: sprint suppresses interpretation, not sensory data).
- D-055 spec: Interaction verbs not computed during sprint. Sprint double-take: if character passes anomaly while sprinting, delayed monologue fires retroactively ("Wait — was that Kael? At this hour?").
- Integration: Blocked by #417 (stance system), works with #428 (anomaly monologue)
#420: Same-tile occupancy — TilePresence layers
- What exists: Movement system uses discrete tile positions (Position component)
- Needs: Add TilePresence component (enum: Standing/Prone/Seated/Fixture), allow multiple entities per tile if different posture layers, update collision detection to check layer conflicts
- D-054 spec: Tile-based movement enables determinism (D-010 principle 4). Occupancy adds positioning depth (doorway blocking, eavesdrop positioning, sitting at furniture) within tile constraints. ~150 lines.
- Integration: Crouch stance (#417) uses Prone/Seated layer. Enables future eavesdrop mechanics (#426, deferred).
#421: ObjectType component + verb sets per type
- Needs: Add ObjectType component (enum: Readable, Container, Terminal, Door, Pickup, Furniture), define verb sets per type (e.g., Readable → {Read, Observe}, Container → {Open, Search, Observe}), spawn objects with ObjectType in map loader
- D-057 context: ObjectType drives Phase 1 verb computation (max possible verb set, no KG). Phase 2 filters by observer's KG.
- Integration: Blocks #422 (two-phase verb computation)
#422: Two-phase verb computation — KG observer filter
- What exists:
server/src/simulation/interaction.rscomputes verbs,server/src/knowledge/has KG query infrastructure - Needs: Refactor verb computation into two phases:
- Phase 1 (simulation, no KG): Query ObjectType component → return max verb set for that type
- Phase 2 (observer, reads KG): Filter Phase 1 verbs by player's knowledge (e.g., Confront requires KnowsDetails+ per D-041), apply POI priority flips, add contradiction markers, character-archetype verb variation (smuggler sees "Move/Stash", detective sees "Scan/Flag" for same crate)
- D-057 spec: Vertical list handles 2-4 options max. New verbs unlocked by KG changes highlighted with glow (client-side). Character differentiation via Phase 2 observer filter, not separate verb systems.
- Integration: Blocked by #421 (ObjectType). Enables rich interactions without hardcoding character logic into simulation.
#424: Smuggler inventory — CarriedBy, Take/Place verbs
- What exists: Entities are world entities in ECS, KG tracks knowledge (not items)
- Needs: Add CarriedBy(StableId) component referencing carrier entity, implement Take/Place verbs (add/remove CarriedBy component), respect info boundary (carried items private, not visible to other entities unless revealed via search/scan/confrontation), query system: all items WHERE CarriedBy == player
- D-065 spec: Knowledge is primary inventory (you SAW the manifest). Physical inventory is secondary (3 specific items for smuggler in v0.1: manifest copy, access token, comm log). Smuggler 9 slots, detective 2 slots (D-065 updated after OQ-24 resolution: 3x3 grid = 9 slots universal).
- Gotcha: Contraband detection (#425, deferred) will scan carried items via KG + CarriedBy query. Items behind info boundary until revealed.
- Integration: Blocks #425 (contraband, deferred), #438 (client inventory UI)
#428: Sprint anomaly monologue — double-take
- Needs: When player in Sprint stance passes an anomaly (e.g., THE FRIEND in wrong location/wrong time), suppress immediate monologue but fire delayed retroactive monologue after ~1-2s: "Wait — was that Kael? At this hour?"
- D-055 context: Sprint suppresses interpretation (monologue at 40%), not sensory data. Anomaly survival creates the "sprint double-take" feel — character's brain catches up after the fact.
- Integration: Works with #419 (sprint suppression), uses existing monologue pipeline (#414, done in Sprint 5)
Dependency Chain
Critical path:
#449 (ObserverSnapshot v6) → standalone, unblocks client #438, #439
#417 (Stance system)
├─→ #418 (MovementProfile)
├─→ #419 (Sprint suppression)
└─→ #420 (TilePresence, parallel but both use tick system)
#421 (ObjectType) → #422 (Two-phase verb computation)
#424 (Smuggler inventory) → standalone, unblocks client #438
#428 (Sprint anomaly monologue) → standalone, parallel work
PR Workflow
When ready to submit, create a PR with tea CLI. All flags are required to avoid TTY prompts (see CLAUDE.md "Gitea access" section):
tea pr create \
--repo jpmschweitzer/settled-reach \
--login schweitz \
--title "feat(simulation): movement stances, tile occupancy, two-phase verbs, smuggler inventory" \
--description "Sprint 6 server deliverables per D-053, D-054, D-055, D-057, D-065" \
--base main \
--head server