feat(simulation): spawn 3 NPCs with full component bundles
Implements ticket #84 for Sprint 3: - Replace single bare NPC with 3 distinct NPCs: dock worker (16,13) with full 4-phase routine and MovementSpeed(2), field tech (14,18) with partial routine, stationary guard (18,14) with no routine - Register all entities (player + 3 NPCs) in EntityRegistry - Populate RelationshipGraph with colleague and rival edges - Add NpcPlugin to app for routine system registration - Add multi-entity visibility tests: 3 NPCs in LOS all visible, NPC behind wall excluded from snapshot Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -701,4 +701,71 @@ mod tests {
|
||||
"entity without last_known_position should not appear as ghost"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiple_npcs_in_los_all_visible() {
|
||||
let mut world = setup_world(32, 32);
|
||||
world.spawn((
|
||||
PlayerCharacter,
|
||||
TilePosition::new(16, 16, 0),
|
||||
Facing(FacingDirection::North),
|
||||
KnowledgeGraph::new(),
|
||||
));
|
||||
// Three NPCs in front of player, no walls
|
||||
world.spawn((crate::npc::Npc, TilePosition::new(16, 14, 0)));
|
||||
world.spawn((crate::npc::Npc, TilePosition::new(14, 14, 0)));
|
||||
world.spawn((crate::npc::Npc, TilePosition::new(18, 14, 0)));
|
||||
|
||||
let mut schedule = bevy_ecs::schedule::Schedule::default();
|
||||
schedule.add_systems(compute_observer_snapshot);
|
||||
schedule.run(&mut world);
|
||||
|
||||
let buffer = world.resource::<SnapshotBuffer>();
|
||||
let snapshot = buffer.snapshot.as_ref().unwrap();
|
||||
// Player + 3 NPCs = 4 entities
|
||||
assert_eq!(snapshot.entities.len(), 4);
|
||||
let npcs: Vec<_> = snapshot
|
||||
.entities
|
||||
.iter()
|
||||
.filter(|e| matches!(e.kind, EntityKind::Npc))
|
||||
.collect();
|
||||
assert_eq!(npcs.len(), 3);
|
||||
assert!(npcs.iter().all(|n| n.observation == EntityVisibility::Visible));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn npc_behind_wall_excluded_from_multi_entity_snapshot() {
|
||||
let mut world = setup_world(32, 32);
|
||||
// Wall at (16,14)
|
||||
world
|
||||
.resource_mut::<WalkabilityMap>()
|
||||
.set_walkable(&TilePosition::new(16, 14, 0), false);
|
||||
|
||||
world.spawn((
|
||||
PlayerCharacter,
|
||||
TilePosition::new(16, 16, 0),
|
||||
Facing(FacingDirection::North),
|
||||
KnowledgeGraph::new(),
|
||||
));
|
||||
// NPC 1: behind wall (should be hidden)
|
||||
world.spawn((crate::npc::Npc, TilePosition::new(16, 13, 0)));
|
||||
// NPC 2: to the side, no wall (should be visible)
|
||||
world.spawn((crate::npc::Npc, TilePosition::new(14, 14, 0)));
|
||||
// NPC 3: also visible
|
||||
world.spawn((crate::npc::Npc, TilePosition::new(18, 15, 0)));
|
||||
|
||||
let mut schedule = bevy_ecs::schedule::Schedule::default();
|
||||
schedule.add_systems(compute_observer_snapshot);
|
||||
schedule.run(&mut world);
|
||||
|
||||
let buffer = world.resource::<SnapshotBuffer>();
|
||||
let snapshot = buffer.snapshot.as_ref().unwrap();
|
||||
// Player + 2 visible NPCs = 3 (NPC behind wall excluded)
|
||||
let npcs: Vec<_> = snapshot
|
||||
.entities
|
||||
.iter()
|
||||
.filter(|e| matches!(e.kind, EntityKind::Npc))
|
||||
.collect();
|
||||
assert_eq!(npcs.len(), 2, "NPC behind wall should be excluded");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user