Files
gamedev-the-steward/tests/conflict_war_system_test.gd
T

193 lines
5.8 KiB
GDScript

extends SceneTree
var failures: Array[String] = []
var war_outcomes: Array[StringName] = []
func _initialize() -> void:
call_deferred("_run")
func _run() -> void:
_test_combat_and_wolf()
_test_war_motivation()
_test_player_combat_and_restore()
_finish()
func _test_combat_and_wolf() -> void:
var manager := _create_manager(981)
var npc: SimNPC = manager.npcs[0]
npc.position = Vector3.ZERO
var npc_combatant: CombatantStateRecord = manager.get_combatant(
SimulationIds.npc_combatant_id(npc.id)
)
_check(
(
npc_combatant != null
and is_equal_approx(npc_combatant.get_health(), 100.0)
and npc_combatant.get_faction_id() == SimulationIds.FACTION_VILLAGE
),
"Each living villager should gain a village combatant record"
)
var wolf_id: StringName = manager.spawn_wolf(Vector3(1.0, 0.0, 0.0))
_check(wolf_id != &"", "A hungry wolf should spawn as a hostile combatant")
var wolf: CombatantStateRecord = manager.get_combatant(wolf_id)
_check(wolf.is_hostile(), "A spawned wolf should be hostile")
manager.simulate_tick()
_check(
wolf.get_health() == 40.0 and npc_combatant.get_health() < 100.0,
"A nearby wolf should wound the villager with its claw"
)
var hurt_found := _has_event(manager, SimulationIds.EVENT_COMBATANT_HURT)
_check(hurt_found, "The wolf's attack should record a combatant_hurt fact")
for _tick in 40:
manager.simulate_tick()
_check(
npc.is_dead or not wolf.is_alive(),
"A prolonged wolf fight should resolve with a death on one side"
)
manager.free()
func _test_war_motivation() -> void:
var strong_manager := _create_manager(982)
_set_all_strength(strong_manager, 9.0)
strong_manager.war_resolved.connect(_on_war_resolved)
for _tick in 400:
strong_manager.simulate_tick()
var strong_plan: StringName = strong_manager.get_tribe_war_plan()
var strong_raiders := _count_raiders(strong_manager)
_check(
(
strong_plan in [SimulationIds.WAR_PLAN_PLANNED, SimulationIds.WAR_PLAN_NONE]
and strong_raiders == 0
),
"A strong village should make the hungry tribe plan but never dare to raid"
)
strong_manager.free()
var weak_manager := _create_manager(983)
_set_all_strength(weak_manager, 1.0)
var weak_outcomes: Array[StringName] = []
weak_manager.war_resolved.connect(func(outcome): weak_outcomes.append(outcome))
for _tick in 200:
weak_manager.simulate_tick()
_check(
weak_manager.get_tribe_war_plan() == SimulationIds.WAR_PLAN_PLANNED,
"A hungry tribe should first watch a weak food-rich village before striking"
)
for _tick in 200:
weak_manager.simulate_tick()
_check(
weak_manager.get_tribe_war_plan() == SimulationIds.WAR_PLAN_RAIDING,
"A weak village with plenty of food should be raided once the tribe commits"
)
_check(_count_raiders(weak_manager) > 0, "The raid should spawn hostile raiders")
var resolved := false
for _tick in 600:
weak_manager.simulate_tick()
if weak_manager.get_tribe_war_plan() != SimulationIds.WAR_PLAN_RAIDING:
resolved = true
break
_check(
resolved and not weak_outcomes.is_empty(),
"The raid should resolve into a war outcome with recorded consequences"
)
weak_manager.free()
func _test_player_combat_and_restore() -> void:
var manager := _create_manager(984)
var wolf_id: StringName = manager.spawn_wolf(Vector3(0.0, 0.0, 0.0))
var wolf: CombatantStateRecord = manager.get_combatant(wolf_id)
_check(
is_equal_approx(manager.player_attack(wolf_id), 24.0),
"The player's sword strike should deal its configured damage"
)
_check(is_equal_approx(wolf.get_health(), 16.0), "The wolf should survive one sword strike")
manager.player_attack(wolf_id)
_check(not wolf.is_alive(), "A second sword strike should kill the wolf")
_check(
_has_event(manager, SimulationIds.EVENT_COMBATANT_KILLED),
"The player's kill should record a combatant_killed fact"
)
_check(
manager.get_living_hostile_combatants().is_empty(),
"The dead wolf should leave the living-hostile set"
)
var saved_json: String = manager.serialize_state()
var restored := _create_manager(985)
_check(
restored.restore_state_from_json(saved_json),
"Combatants and factions should survive schema-v14 save and restore"
)
_check(
(
restored.get_state_checksum() == manager.get_state_checksum()
and restored.get_faction(SimulationIds.FACTION_TRIBE) != null
and not restored.get_combatant(wolf_id).is_alive()
),
"Restore should preserve combatant health, factions, and checksum"
)
restored.free()
manager.free()
func _set_all_strength(manager: Node, strength: float) -> void:
for npc in manager.npcs:
npc.strength = strength
func _count_raiders(manager: Node) -> int:
var count := 0
for combatant in manager.conflict_system.get_all_combatants():
if combatant.get_kind() == SimulationIds.COMBATANT_KIND_RAIDER:
count += 1
return count
func _has_event(manager: Node, event_type: StringName) -> bool:
for event in manager.economic_events:
if StringName(event.data["event_type"]) == event_type:
return true
return false
func _on_war_resolved(_outcome: StringName) -> void:
war_outcomes.append(_outcome)
func _create_manager(seed_value: int = 981) -> Node:
var manager: Node = load("res://simulation/SimulationManager.gd").new()
manager.simulation_seed = seed_value
manager.debug_logs = false
var home_positions: Array[Vector3] = [
Vector3(0.0, 0.0, 0.0),
Vector3(2.0, 0.0, 0.0),
Vector3(10.0, 0.0, 0.0),
Vector3(12.0, 0.0, 0.0),
Vector3(30.0, 0.0, 30.0),
Vector3(40.0, 0.0, 40.0),
]
manager.home_positions = home_positions
root.add_child(manager)
manager.set_process(false)
return manager
func _finish() -> void:
if failures.is_empty():
print("[TEST] Conflict and war passed: combat, wolves, motivation, raids")
quit(0)
return
for failure in failures:
push_error("[TEST] " + failure)
quit(1)
func _check(condition: bool, message: String) -> void:
if not condition:
failures.append(message)