feat(simulation): add Sound Lab, Decay Observatory, Shift Change gauntlet rooms (#505)
Three new gauntlet test rooms for Sprint 13, each targeting a specific system under test. StableIds are additive-only (66–74). Sound Lab (66-68): Three NPCs at calibrated tile distances (2, 6, 12 tiles) verify D-018 three-range sound model. Tests confirm Close ≤3, Medium ≤8, Long ≤20 tile thresholds via SoundEvent::audible_at(). Decay Observatory (69): Single NPC observed in LOS then broken. Tests confirm D-041 confidence decay: KnowsDetails → KnowsOf → Suspects (floor), and Stale state when stale_after threshold is exceeded. Shift Change (70-71): Two NPCs with DailyRoutine components. Test confirms D-031 phase-boundary check_phase_transition issues PathRequest only to NPCs not already at their target location. Sprint 13 reset plates (72-74) wired per existing pattern. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -200,6 +200,61 @@ pub const CONFRONTATION_STAGE: GauntletRoom = GauntletRoom {
|
||||
}),
|
||||
};
|
||||
|
||||
/// Sound Lab — Room 12 (34x20)
|
||||
/// Tests D-018 (three-range sound model). Sound-emitting NPCs at calibrated
|
||||
/// distances from the observer: Close (2 tiles), Medium (6 tiles), Long (12 tiles).
|
||||
pub const SOUND_LAB: GauntletRoom = GauntletRoom {
|
||||
name: "sound_lab",
|
||||
origin: TilePosition {
|
||||
x: 0,
|
||||
y: 104,
|
||||
z: 0,
|
||||
},
|
||||
size: (34, 20),
|
||||
spawn: TilePosition {
|
||||
x: 10,
|
||||
y: 114,
|
||||
z: 0,
|
||||
},
|
||||
observer: TilePosition {
|
||||
x: 10,
|
||||
y: 114,
|
||||
z: 0,
|
||||
},
|
||||
observer_facing: Facing(FacingDirection::East),
|
||||
reset_plate: Some(TilePosition {
|
||||
x: 16,
|
||||
y: 103,
|
||||
z: 0,
|
||||
}),
|
||||
};
|
||||
|
||||
/// Decay Observatory — Room 13 (24x14)
|
||||
/// Tests D-041 knowledge graph decay. NPC observed in LOS then LOS broken;
|
||||
/// confidence degrades Direct → KnowsDetails → KnowsOf → Suspects over ticks.
|
||||
pub const DECAY_OBSERVATORY: GauntletRoom = GauntletRoom {
|
||||
name: "decay_observatory",
|
||||
origin: TilePosition { x: 0, y: 24, z: 0 },
|
||||
size: (24, 14),
|
||||
spawn: TilePosition { x: 10, y: 30, z: 0 },
|
||||
observer: TilePosition { x: 10, y: 30, z: 0 },
|
||||
observer_facing: Facing(FacingDirection::East),
|
||||
reset_plate: Some(TilePosition { x: 15, y: 23, z: 0 }),
|
||||
};
|
||||
|
||||
/// Shift Change — Room 14 (16x24)
|
||||
/// Tests D-031 day-phase transitions. Two NPCs with DailyRoutine components
|
||||
/// receive PathRequests when game clock crosses a phase boundary.
|
||||
pub const SHIFT_CHANGE: GauntletRoom = GauntletRoom {
|
||||
name: "shift_change",
|
||||
origin: TilePosition { x: 64, y: 78, z: 0 },
|
||||
size: (16, 24),
|
||||
spawn: TilePosition { x: 72, y: 90, z: 0 },
|
||||
observer: TilePosition { x: 72, y: 90, z: 0 },
|
||||
observer_facing: Facing(FacingDirection::North),
|
||||
reset_plate: Some(TilePosition { x: 72, y: 78, z: 0 }),
|
||||
};
|
||||
|
||||
/// All rooms in canonical spawn order.
|
||||
/// THIS ORDER DETERMINES STABLEID ASSIGNMENT.
|
||||
/// Do not reorder existing entries. Append new rooms at the end.
|
||||
@@ -215,6 +270,9 @@ pub const ROOMS: &[GauntletRoom] = &[
|
||||
SPRINT_GAUNTLET,
|
||||
EAVESDROP_ALCOVE,
|
||||
CONFRONTATION_STAGE,
|
||||
SOUND_LAB,
|
||||
DECAY_OBSERVATORY,
|
||||
SHIFT_CHANGE,
|
||||
];
|
||||
|
||||
/// Look up which room a position falls in.
|
||||
@@ -259,6 +317,12 @@ pub const EAVESDROP_ALCOVE_STABLE_IDS: (u64, u64) = (58, 60);
|
||||
pub const CONFRONTATION_STAGE_STABLE_IDS: (u64, u64) = (61, 62);
|
||||
/// Reset plates for Sprint 11 rooms (sprint_gauntlet, eavesdrop_alcove, confrontation_stage).
|
||||
pub const SPRINT11_RESET_PLATE_STABLE_IDS: (u64, u64) = (63, 65);
|
||||
// Sprint 13 rooms — appended after SPRINT11_RESET_PLATE_STABLE_IDS per additive-only rule.
|
||||
pub const SOUND_LAB_STABLE_IDS: (u64, u64) = (66, 68);
|
||||
pub const DECAY_OBSERVATORY_STABLE_IDS: (u64, u64) = (69, 69);
|
||||
pub const SHIFT_CHANGE_STABLE_IDS: (u64, u64) = (70, 71);
|
||||
/// Reset plates for Sprint 13 rooms (sound_lab, decay_observatory, shift_change).
|
||||
pub const SPRINT13_RESET_PLATE_STABLE_IDS: (u64, u64) = (72, 74);
|
||||
|
||||
/// Number of actively-spawned entities in the current Gauntlet build.
|
||||
/// Derived from StableId ranges of all rooms + player + reset plates.
|
||||
@@ -275,7 +339,11 @@ pub const EXPECTED_ENTITY_COUNT: usize = 1 // player (StableId 0)
|
||||
+ (SPRINT_GAUNTLET_STABLE_IDS.1 - SPRINT_GAUNTLET_STABLE_IDS.0 + 1) as usize
|
||||
+ (EAVESDROP_ALCOVE_STABLE_IDS.1 - EAVESDROP_ALCOVE_STABLE_IDS.0 + 1) as usize
|
||||
+ (CONFRONTATION_STAGE_STABLE_IDS.1 - CONFRONTATION_STAGE_STABLE_IDS.0 + 1) as usize
|
||||
+ (SPRINT11_RESET_PLATE_STABLE_IDS.1 - SPRINT11_RESET_PLATE_STABLE_IDS.0 + 1) as usize;
|
||||
+ (SPRINT11_RESET_PLATE_STABLE_IDS.1 - SPRINT11_RESET_PLATE_STABLE_IDS.0 + 1) as usize
|
||||
+ (SOUND_LAB_STABLE_IDS.1 - SOUND_LAB_STABLE_IDS.0 + 1) as usize
|
||||
+ (DECAY_OBSERVATORY_STABLE_IDS.1 - DECAY_OBSERVATORY_STABLE_IDS.0 + 1) as usize
|
||||
+ (SHIFT_CHANGE_STABLE_IDS.1 - SHIFT_CHANGE_STABLE_IDS.0 + 1) as usize
|
||||
+ (SPRINT13_RESET_PLATE_STABLE_IDS.1 - SPRINT13_RESET_PLATE_STABLE_IDS.0 + 1) as usize;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
@@ -384,7 +452,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn all_rooms_in_correct_order() {
|
||||
assert_eq!(ROOMS.len(), 11);
|
||||
assert_eq!(ROOMS.len(), 14);
|
||||
assert_eq!(ROOMS[0].name, "central_hub");
|
||||
assert_eq!(ROOMS[1].name, "fog_theater");
|
||||
assert_eq!(ROOMS[2].name, "occlusion_corridor");
|
||||
@@ -396,6 +464,9 @@ mod tests {
|
||||
assert_eq!(ROOMS[8].name, "sprint_gauntlet");
|
||||
assert_eq!(ROOMS[9].name, "eavesdrop_alcove");
|
||||
assert_eq!(ROOMS[10].name, "confrontation_stage");
|
||||
assert_eq!(ROOMS[11].name, "sound_lab");
|
||||
assert_eq!(ROOMS[12].name, "decay_observatory");
|
||||
assert_eq!(ROOMS[13].name, "shift_change");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -458,6 +529,10 @@ mod tests {
|
||||
EAVESDROP_ALCOVE_STABLE_IDS,
|
||||
CONFRONTATION_STAGE_STABLE_IDS,
|
||||
SPRINT11_RESET_PLATE_STABLE_IDS,
|
||||
SOUND_LAB_STABLE_IDS,
|
||||
DECAY_OBSERVATORY_STABLE_IDS,
|
||||
SHIFT_CHANGE_STABLE_IDS,
|
||||
SPRINT13_RESET_PLATE_STABLE_IDS,
|
||||
];
|
||||
for (i, a) in ranges.iter().enumerate() {
|
||||
for (j, b) in ranges.iter().enumerate() {
|
||||
|
||||
Reference in New Issue
Block a user