feat(simulation): Sprint 18 — 9 server systems

Background tier state machines (#95), NPC vision (#115), player-
awareness behavior (#244), skill system & combat flag (#91), social
propagation (#249), examine mechanic (#242), character pressure
framework (#248), save state data model (#256), tell state wiring
(#337). Protocol version bumped 13→14 for examine_result and
character_pressure snapshot fields.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-25 09:50:37 +01:00
co-authored by Claude Opus 4.6
parent 2eca8e961b
commit 276538cde1
16 changed files with 4450 additions and 5 deletions
+43
View File
@@ -1100,6 +1100,49 @@ mod tests {
assert_eq!(edge.trust, 7);
}
#[test]
#[test]
fn spawn_npc_combat_trained_sets_skill_flag() {
// #91: combat_trained: true in YAML sets SkillSet.combat_trained = true.
// Known gap: CombatCapability is NOT yet attached for content-spawned NPCs
// (see TODO in spawn.rs near "Supporting axis 3: Skills"). The procedural
// path (generate.rs) correctly attaches CombatCapability. This test documents
// current behavior so the gap is visible in CI.
let mut world = create_test_world();
let mut profile = create_test_profile();
profile.skills = Some(NpcSkills {
combat_trained: Some(true),
skills: Some({
let mut m = std::collections::BTreeMap::new();
m.insert("combat".to_string(), 7);
m
}),
});
let mut result = SpawnResult::default();
spawn_npc(&mut world, &profile, &mut result);
let entity = world
.resource::<EntityRegistry>()
.to_entity(&result.npc_ids["test-npc"])
.unwrap();
// SkillSet.combat_trained is correctly set from YAML (#91 — done)
let skills = world.get::<npc::SkillSet>(entity).unwrap();
assert!(
skills.combat_trained,
"SkillSet.combat_trained should be true when YAML sets combat_trained: true"
);
// Known gap: CombatCapability not yet attached in content-spawn path.
// The procedural path (generate.rs) does attach it — content path has TODO.
// Update this assertion when the TODO is resolved.
assert!(
world.get::<npc::CombatCapability>(entity).is_none(),
"CombatCapability not yet attached in content-spawn path (known gap — see spawn.rs TODO)"
);
}
#[test]
fn resolve_relationships_skips_unknown_targets() {
let mut world = create_test_world();