Files
gamedev-the-steward/tests/relationship_consequence_test.gd
T
2026-07-11 11:27:40 +02:00

174 lines
5.3 KiB
GDScript

extends SceneTree
var failures: Array[String] = []
func _initialize() -> void:
call_deferred("_run")
func _run() -> void:
var manager := _create_manager()
var contributor: SimNPC = manager.npcs[0]
var observer: SimNPC = manager.npcs[1]
var stranger: SimNPC = manager.npcs[2]
var relationship: RelationshipStateRecord = manager.relationship_system.get_relationship(
observer.id, contributor.id
)
_check(relationship != null, "Nearby household NPCs should begin with a directed relationship")
if relationship == null:
manager.free()
_finish()
return
observer.hunger = 85.0
stranger.hunger = 85.0
contributor.position = Vector3.ZERO
observer.position = Vector3(4.0, 0.0, 0.0)
stranger.position = Vector3(20.0, 0.0, 0.0)
contributor.add_inventory(SimulationIds.RESOURCE_FOOD, 2.0)
var deposited: float = manager.economy.deposit_inventory(
contributor, SimulationIds.RESOURCE_FOOD
)
_check(is_equal_approx(deposited, 2.0), "The real economy path should deposit contributed food")
var cause_event: EconomicEventRecord = manager.get_relationship_cause(relationship)
var cause_event_id := int(cause_event.data["event_id"]) if cause_event != null else -1
_check(
is_equal_approx(relationship.get_trust(), 0.65),
"Food aid should raise the hungry familiar NPC's directed trust"
)
_check(
(
cause_event != null
and StringName(cause_event.data["event_type"]) == SimulationIds.EVENT_STORAGE_DEPOSITED
and int(cause_event.data["actor_id"]) == contributor.id
),
"Trust should reference the exact structured deposit event that caused it"
)
_check(
(
manager.npc_knows_event(contributor.id, cause_event_id)
and manager.npc_knows_event(observer.id, cause_event_id)
and not manager.npc_knows_event(stranger.id, cause_event_id)
),
"Only the contributor and nearby observer should know the deposit fact"
)
var reverse: RelationshipStateRecord = manager.relationship_system.get_relationship(
contributor.id, observer.id
)
_check(
(
reverse != null
and is_equal_approx(reverse.get_trust(), RelationshipStateRecord.NEUTRAL_TRUST)
),
"Food aid trust should remain directed instead of changing both people implicitly"
)
_check(
manager.relationship_system.get_relationship(stranger.id, contributor.id) == null,
"A distant NPC should not gain trust without an existing familiar relationship"
)
var pantry: StorageStateRecord = manager.get_pantry()
pantry.withdraw(
SimulationIds.RESOURCE_FOOD,
maxf(
(
pantry.get_amount(SimulationIds.RESOURCE_FOOD)
- (ActionSelectionSystem.RELATIONSHIP_AID_PANTRY_THRESHOLD - 5.0)
),
0.0
)
)
manager.economy.sync_resource(SimulationIds.RESOURCE_FOOD)
contributor.hunger = 95.0
contributor.is_starving = true
observer.profession = SimulationIds.PROFESSION_GUARD
observer.hunger = 20.0
observer.energy = 80.0
observer.inventory.clear()
observer.last_task = &""
manager.economy.deposit_resource(SimulationIds.RESOURCE_WOOD, 10.0)
manager.village.safety = 50.0
manager.village.knowledge = 20.0
manager.village.update_priorities()
var neutral_choice: ActionSelectionResult = ActionSelectionSystem.new().select_action(
observer, manager.village, 0.5, manager.npcs
)
var helping_choice: ActionSelectionResult = manager.action_selector.select_action(
observer, manager.village, 0.5, manager.npcs
)
_check(
neutral_choice.action_id == SimulationIds.ACTION_PATROL,
"Without relationship context, the guard should keep doing ordinary patrol work"
)
_check(
(
helping_choice.action_id == SimulationIds.ACTION_GATHER_FOOD
and contributor.npc_name in helping_choice.reason
),
"Trust should visibly redirect ordinary work toward helping a starving acquaintance"
)
var saved_json: String = manager.serialize_state()
var restored := _create_manager(999)
_check(
restored.restore_state_from_json(saved_json),
"Relationship state and its event cause should restore through the world schema"
)
var restored_relationship: RelationshipStateRecord = (
restored.relationship_system.get_relationship(observer.id, contributor.id)
)
_check(
(
restored_relationship != null
and is_equal_approx(restored_relationship.get_trust(), relationship.get_trust())
and (
restored_relationship.get_last_trust_cause_event_id()
== relationship.get_last_trust_cause_event_id()
)
),
"Save/load should preserve directed trust and its causal event identity"
)
_check(
restored.get_state_checksum() == manager.get_state_checksum(),
"Restored relationship state should retain the complete deterministic checksum"
)
manager.free()
restored.free()
_finish()
func _finish() -> void:
if failures.is_empty():
print("[TEST] Relationship consequence passed: food aid -> trust -> helping choice")
quit(0)
return
for failure in failures:
push_error("[TEST] " + failure)
quit(1)
func _create_manager(seed_value: int = 801) -> 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(1.0, 0.0, 0.0),
Vector3(20.0, 0.0, 20.0),
Vector3(30.0, 0.0, 30.0),
Vector3(40.0, 0.0, 40.0),
Vector3(50.0, 0.0, 50.0),
]
manager.home_positions = home_positions
root.add_child(manager)
manager.set_process(false)
return manager
func _check(condition: bool, message: String) -> void:
if not condition:
failures.append(message)