feat(simulation): Sprint 2 — perception system (LOS, vision cone, observer) #9

Closed
jpmschweitzer wants to merge 0 commits from server into main
Owner

Summary

Sprint 2 "See" server implementation — fog of perception working through the bridge.

  • ObserverSnapshot v2 schema (#358, #25): version field, GameTime (day/phase/paused), FacingDirection (8-directional), VisibleTile, VisibilitySector (Forward/Peripheral), visibility tag on entities. All msgpack fixtures regenerated.
  • Symmetric shadowcasting (#359, #110): Albert Ford algorithm with rational fraction slopes. Benchmarked 1.2–10.5× faster than recursive. Symmetry guaranteed (D-035, resolves Q-018).
  • Vision cone (#111): Forward (~120°) at full range, Peripheral (~180° each side) at reduced range, Blind (~60° behind) excluded. Facing component updated on player movement.
  • Observer visibility query (#112): Replaces unfiltered generate_snapshot with compute_observer_snapshot combining shadowcasting + vision cone. Only visible entities/tiles cross the bridge — information asymmetry enforced (D-011).

Test plan

  • 82/82 tests pass (cargo nextest run)
  • 7 observer unit tests (player visible, NPC in LOS, NPC behind wall, blind spot, z-level, game_time, visible_tiles)
  • 9 vision cone unit tests (all 8 directions, sector classification, apply_vision_cone filtering)
  • 8 shadowcasting unit tests (open field, walls, range, corners, pillars, symmetry)
  • Benchmark: symmetric <1ms at 150×150 range 20
  • E2E game_loop test passes with new observer pipeline
  • All serialization roundtrips pass with v2 schema
  • Msgpack fixtures regenerated for client compatibility

🤖 Generated with Claude Code

## Summary Sprint 2 "See" server implementation — fog of perception working through the bridge. - **ObserverSnapshot v2 schema** (#358, #25): version field, GameTime (day/phase/paused), FacingDirection (8-directional), VisibleTile, VisibilitySector (Forward/Peripheral), visibility tag on entities. All msgpack fixtures regenerated. - **Symmetric shadowcasting** (#359, #110): Albert Ford algorithm with rational fraction slopes. Benchmarked 1.2–10.5× faster than recursive. Symmetry guaranteed (D-035, resolves Q-018). - **Vision cone** (#111): Forward (~120°) at full range, Peripheral (~180° each side) at reduced range, Blind (~60° behind) excluded. Facing component updated on player movement. - **Observer visibility query** (#112): Replaces unfiltered `generate_snapshot` with `compute_observer_snapshot` combining shadowcasting + vision cone. Only visible entities/tiles cross the bridge — information asymmetry enforced (D-011). ## Test plan - [x] 82/82 tests pass (`cargo nextest run`) - [x] 7 observer unit tests (player visible, NPC in LOS, NPC behind wall, blind spot, z-level, game_time, visible_tiles) - [x] 9 vision cone unit tests (all 8 directions, sector classification, apply_vision_cone filtering) - [x] 8 shadowcasting unit tests (open field, walls, range, corners, pillars, symmetry) - [x] Benchmark: symmetric <1ms at 150×150 range 20 - [x] E2E game_loop test passes with new observer pipeline - [x] All serialization roundtrips pass with v2 schema - [x] Msgpack fixtures regenerated for client compatibility 🤖 Generated with [Claude Code](https://claude.com/claude-code)
jpmschweitzer added 5 commits 2026-02-12 00:24:36 +01:00
Expand wire protocol with version field, GameTime (day/phase/paused),
FacingDirection (8-directional), VisibleTile, VisibilitySector
(Forward/Peripheral), and visibility tag on VisibleEntity.
Regenerate all msgpack fixtures for client compatibility.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Albert Ford's symmetric shadowcasting algorithm using rational
fraction slopes. Benchmarked 1.2-10.5x faster than recursive with
guaranteed symmetry (if A sees B, B sees A). Resolves Q-018 as D-035.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement direction-dependent visibility modulation per D-015.
Forward cone (~120 deg) at full range, peripheral (~180 deg each side)
at reduced range, blind spot (~60 deg behind) excluded. Facing component
updated on player movement via facing_from_delta.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace unfiltered generate_snapshot with compute_observer_snapshot
that combines shadowcasting + vision cone to send only visible
entities and tiles. Enforces information asymmetry (D-011): NPCs
behind walls or in the blind spot are excluded from the snapshot.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Author
Owner

Dual-Agent Review: server -> main

Hoshe (Code Quality): APPROVE

High-quality perception system. 24 unit tests across 3 modules, proper separation of concerns (shadowcast -> vision cone -> observer), mathematically sound rational fraction arithmetic. All operations well within 100ms tick budget (D-026). No critical bugs.

# File Severity Issue
1 shadowcast.rs:~30 suggestion Add cross-multiplication comment to Fraction comparison
2 shadowcast.rs:~120 warning Fraction arithmetic could overflow i32 at extreme ranges (safe at range 20)
3 observer.rs:~75 suggestion Sector lookup fallback to Peripheral — consider .expect() to catch logic bugs
4 vision_cone.rs:~105 suggestion Add comment explaining angle wrapping logic

Tyre (Architecture): APPROVE

Correct D-011, D-015, D-035 implementation. System ordering verified. Deterministic shadowcast (rational fractions), presentation-only float in vision cone. v2 schema evolution clean with version field.

# File Severity Issue
1 vision_cone.rs:90-130 warning Float atan2 non-deterministic — OK since sectors are presentation-only. Document for future multiplayer.
2 observer.rs:~72 suggestion Prioritize #362 StableEntityId before D-041 knowledge graph
3 bridge/mod.rs suggestion Old generate_snapshot is dead code — remove or feature-gate

Verdict: APPROVED

No blocking issues. Suggestions are polish items for follow-up.

## Dual-Agent Review: server -> main ### Hoshe (Code Quality): APPROVE High-quality perception system. 24 unit tests across 3 modules, proper separation of concerns (shadowcast -> vision cone -> observer), mathematically sound rational fraction arithmetic. All operations well within 100ms tick budget (D-026). No critical bugs. | # | File | Severity | Issue | |---|------|----------|-------| | 1 | shadowcast.rs:~30 | suggestion | Add cross-multiplication comment to Fraction comparison | | 2 | shadowcast.rs:~120 | warning | Fraction arithmetic could overflow i32 at extreme ranges (safe at range 20) | | 3 | observer.rs:~75 | suggestion | Sector lookup fallback to Peripheral — consider `.expect()` to catch logic bugs | | 4 | vision_cone.rs:~105 | suggestion | Add comment explaining angle wrapping logic | ### Tyre (Architecture): APPROVE Correct D-011, D-015, D-035 implementation. System ordering verified. Deterministic shadowcast (rational fractions), presentation-only float in vision cone. v2 schema evolution clean with version field. | # | File | Severity | Issue | |---|------|----------|-------| | 1 | vision_cone.rs:90-130 | warning | Float atan2 non-deterministic — OK since sectors are presentation-only. Document for future multiplayer. | | 2 | observer.rs:~72 | suggestion | Prioritize #362 StableEntityId before D-041 knowledge graph | | 3 | bridge/mod.rs | suggestion | Old generate_snapshot is dead code — remove or feature-gate | ### Verdict: APPROVED No blocking issues. Suggestions are polish items for follow-up.
jpmschweitzer closed this pull request 2026-02-12 00:32:02 +01:00

Pull request closed

This pull request cannot be reopened because the branch was deleted.
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: jpmschweitzer/settled-reach#9