fix(simulation): address PR #46 review — zone tests, doc accuracy, TBD comment

Add 3 zone enrichment tests to observer pipeline (tile inside zone,
tile outside zone, absent ZoneMap resource). Fix misleading Decay
Observatory doc comment that claimed Direct start when test starts at
KnowsDetails. Add production population TBD note on ZoneMap.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-19 18:22:48 +01:00
co-authored by Claude Opus 4.6
parent 51abc3e3c1
commit dd1dd0feec
3 changed files with 120 additions and 3 deletions
+113
View File
@@ -2466,3 +2466,116 @@ fn blocked_entities_sorted_ascending() {
assert!(snapshot.blocked_entities.contains(&npc_b_sid.0));
assert!(snapshot.blocked_entities.contains(&npc_c_sid.0));
}
// -----------------------------------------------------------------------
// Zone enrichment tests (#523, D-077)
// -----------------------------------------------------------------------
#[test]
fn zone_map_enriches_visible_tiles_with_zone_id() {
// Tile inside a zone should get zone_id = Some(zone_id)
use crate::simulation::zone::ZoneMap;
let mut world = setup_world(32, 32);
let mut zone_map = ZoneMap::default();
// Zone 42 covers (14..18, 14..18) — includes the observer's tile at (16,16)
zone_map.set_rect(14, 14, 4, 4, 0, 42);
world.insert_resource(zone_map);
world.spawn((
PlayerCharacter,
TilePosition::new(16, 16, 0),
Facing::default(),
KnowledgeGraph::new(),
NearbyInteractionBuffer::default(),
MonologueBuffer::default(),
));
run_observer_pipeline(&mut world);
let buffer = world.resource::<SnapshotBuffer>();
let snapshot = buffer.snapshot.as_ref().unwrap();
// Observer's tile (16, 16) is inside zone 42
let observer_tile = snapshot
.visible_tiles
.iter()
.find(|t| t.x == 16 && t.y == 16 && t.z == 0)
.expect("observer tile should be visible");
assert_eq!(
observer_tile.zone_id,
Some(42),
"tile inside zone should have zone_id"
);
}
#[test]
fn zone_map_tiles_outside_zone_get_none() {
// Tile outside any zone should get zone_id = None
use crate::simulation::zone::ZoneMap;
let mut world = setup_world(32, 32);
let mut zone_map = ZoneMap::default();
// Zone only covers (0..2, 0..2) — far from observer at (16,16)
zone_map.set_rect(0, 0, 2, 2, 0, 7);
world.insert_resource(zone_map);
world.spawn((
PlayerCharacter,
TilePosition::new(16, 16, 0),
Facing::default(),
KnowledgeGraph::new(),
NearbyInteractionBuffer::default(),
MonologueBuffer::default(),
));
run_observer_pipeline(&mut world);
let buffer = world.resource::<SnapshotBuffer>();
let snapshot = buffer.snapshot.as_ref().unwrap();
// Observer's tile (16, 16) is outside any zone
let observer_tile = snapshot
.visible_tiles
.iter()
.find(|t| t.x == 16 && t.y == 16 && t.z == 0)
.expect("observer tile should be visible");
assert_eq!(
observer_tile.zone_id, None,
"tile outside any zone should have zone_id = None"
);
}
#[test]
fn no_zone_map_resource_tiles_have_no_zone_id() {
// When ZoneMap resource is absent, all tiles should have zone_id = None
let mut world = setup_world(32, 32);
// Do NOT insert ZoneMap resource
world.spawn((
PlayerCharacter,
TilePosition::new(16, 16, 0),
Facing::default(),
KnowledgeGraph::new(),
NearbyInteractionBuffer::default(),
MonologueBuffer::default(),
));
run_observer_pipeline(&mut world);
let buffer = world.resource::<SnapshotBuffer>();
let snapshot = buffer.snapshot.as_ref().unwrap();
assert!(
!snapshot.visible_tiles.is_empty(),
"should have visible tiles"
);
// All tiles should have zone_id = None when no ZoneMap exists
for tile in &snapshot.visible_tiles {
assert_eq!(
tile.zone_id, None,
"tile ({},{}) should have zone_id = None without ZoneMap resource",
tile.x, tile.y
);
}
}
+3
View File
@@ -18,6 +18,9 @@ use bevy_ecs::prelude::*;
///
/// Zone IDs are opaque u16 values — the client maintains its own
/// `zone_id → zone_name / temperature_tint / ambient_layer` mapping.
///
/// Production population path is TBD — currently populated only by
/// Gauntlet room builders via `set_rect` / `set`.
#[derive(Resource, Debug, Default)]
pub struct ZoneMap {
zones: BTreeMap<(i32, i32, i32), u16>,
@@ -1,8 +1,9 @@
//! Decay Observatory — Room 13 (24x14)
//!
//! Tests D-041 (knowledge graph decay). Observer starts with Direct confidence
//! on an NPC in LOS, then LOS is broken. Tick advances verify confidence
//! degrades: Direct → KnowsDetails → KnowsOf → Suspects → Stale (D-041).
//! Tests D-041 (knowledge graph decay). Observer sees an NPC (Direct), then
//! LOS is broken (drops to KnowsDetails). Tick advances verify confidence
//! degrades: KnowsDetails → KnowsOf → Suspects (floor). Separate test
//! confirms Stale state triggers when age exceeds stale_after threshold.
//!
//! Decay runs once per game-minute (every 10 ticks, D-031). Confidence floor
//! is Suspects — decay never removes an entity from the knowledge graph.