Files
gamedev-the-steward/tests/unit/test_simulation_services.gd
T
2026-07-11 19:58:47 +02:00

184 lines
7.4 KiB
GDScript

extends GutTest
const SimulationEventLogScript := preload("res://simulation/events/SimulationEventLog.gd")
const VillageEconomyScript := preload("res://simulation/economy/VillageEconomy.gd")
const RelationshipSystemScript := preload("res://simulation/relationships/RelationshipSystem.gd")
const EventKnowledgeSystemScript := preload("res://simulation/knowledge/EventKnowledgeSystem.gd")
func test_storage_never_accepts_more_than_its_capacity() -> void:
var storage := StorageStateRecord.create(&"test_storage", {"food": 4.5}, 5.0)
assert_eq(storage.deposit(SimulationIds.RESOURCE_FOOD, 2.0), 0.5)
assert_eq(storage.get_amount(SimulationIds.RESOURCE_FOOD), 5.0)
assert_eq(storage.get_available_capacity(), 0.0)
func test_economy_moves_inventory_into_authoritative_storage() -> void:
var village := SimVillage.new()
village.food = 3.0
var economy := VillageEconomyScript.new()
economy.configure(village, false)
economy.initialize_storage()
var npc := SimNPC.new(7, "Tester", SimulationIds.PROFESSION_FARMER, 5.0, 5.0)
npc.add_inventory(SimulationIds.RESOURCE_FOOD, 2.0)
assert_eq(economy.deposit_inventory(npc, SimulationIds.RESOURCE_FOOD), 2.0)
assert_eq(npc.get_inventory_amount(SimulationIds.RESOURCE_FOOD), 0.0)
assert_eq(economy.get_pantry().get_amount(SimulationIds.RESOURCE_FOOD), 5.0)
assert_eq(village.food, 5.0)
func test_event_log_preserves_order_and_derives_consumption_rate() -> void:
var event_log := SimulationEventLogScript.new()
event_log.record_narrative(10, SimulationIds.EVENT_TASK_STARTED, 4, &"", "Study")
event_log.record_economic(
20,
SimulationIds.EVENT_ITEM_CONSUMED,
4,
SimulationIds.STORAGE_VILLAGE_PANTRY,
&"consumed",
SimulationIds.RESOURCE_FOOD,
1.0
)
assert_eq(event_log.events.size(), 2)
assert_eq(int(event_log.events[0].data["event_id"]), 0)
assert_eq(int(event_log.events[1].data["event_id"]), 1)
assert_eq(event_log.get_for_actor(4).size(), 2)
assert_eq(float(event_log.get_consumption_rates(200)["food_per_day"]), 1.0)
var legacy_event_data := event_log.events[1].to_dictionary()
legacy_event_data["schema_version"] = EconomicEventRecord.LEGACY_SCHEMA_VERSION
legacy_event_data.erase("world_position")
var migrated_event := EconomicEventRecord.from_dictionary(legacy_event_data)
assert_not_null(migrated_event)
assert_eq(migrated_event.get_world_position(), Vector3.ZERO)
func test_food_aid_builds_directed_trust_once_per_event() -> void:
var contributor := SimNPC.new(0, "Amina", SimulationIds.PROFESSION_FARMER, 5.0, 5.0)
var observer := SimNPC.new(1, "Tarik", SimulationIds.PROFESSION_GUARD, 5.0, 5.0)
contributor.home_position = Vector3.ZERO
observer.home_position = Vector3(1.0, 0.0, 0.0)
observer.hunger = 85.0
var villagers: Array[SimNPC] = [contributor, observer]
var relationship_system := RelationshipSystemScript.new()
relationship_system.initialize_households(villagers)
var deposit_event := EconomicEventRecord.create(
7,
SimulationIds.EVENT_STORAGE_DEPOSITED,
12,
contributor.id,
SimulationIds.npc_inventory_id(contributor.id),
SimulationIds.STORAGE_VILLAGE_PANTRY,
SimulationIds.RESOURCE_FOOD,
2.0
)
var later_deposit_event := EconomicEventRecord.create(
8,
SimulationIds.EVENT_STORAGE_DEPOSITED,
13,
contributor.id,
SimulationIds.npc_inventory_id(contributor.id),
SimulationIds.STORAGE_VILLAGE_PANTRY,
SimulationIds.RESOURCE_FOOD,
1.0
)
var knower_ids: Array[int] = [contributor.id, observer.id]
relationship_system.apply_event(deposit_event, villagers, knower_ids)
relationship_system.apply_event(later_deposit_event, villagers, knower_ids)
relationship_system.apply_event(deposit_event, villagers, knower_ids)
var relationship: RelationshipStateRecord = relationship_system.get_relationship(
observer.id, contributor.id
)
assert_eq(relationship.get_trust(), 0.8)
assert_eq(relationship.get_last_trust_cause_event_id(), 8)
assert_eq(
relationship_system.get_relationship(contributor.id, observer.id).get_trust(),
RelationshipStateRecord.NEUTRAL_TRUST
)
func test_event_knowledge_is_spatial_directed_and_idempotent() -> void:
var actor := SimNPC.new(0, "Amina", SimulationIds.PROFESSION_FARMER, 5.0, 5.0)
var nearby := SimNPC.new(1, "Tarik", SimulationIds.PROFESSION_GUARD, 5.0, 5.0)
var distant := SimNPC.new(2, "Jasmin", SimulationIds.PROFESSION_GUARD, 5.0, 5.0)
actor.position = Vector3.ZERO
nearby.position = Vector3(4.0, 0.0, 0.0)
distant.position = Vector3(20.0, 0.0, 0.0)
var villagers: Array[SimNPC] = [actor, nearby, distant]
var event := EconomicEventRecord.create(
12,
SimulationIds.EVENT_STORAGE_DEPOSITED,
30,
actor.id,
SimulationIds.npc_inventory_id(actor.id),
SimulationIds.STORAGE_VILLAGE_PANTRY,
SimulationIds.RESOURCE_FOOD,
2.0,
Vector3.ZERO
)
actor.position = Vector3(100.0, 0.0, 0.0)
var knowledge_system := EventKnowledgeSystemScript.new()
assert_eq(knowledge_system.observe_event(event, villagers).size(), 2)
assert_eq(knowledge_system.observe_event(event, villagers).size(), 0)
assert_true(knowledge_system.knows_event(actor.id, 12))
assert_true(knowledge_system.knows_event(nearby.id, 12))
assert_false(knowledge_system.knows_event(distant.id, 12))
assert_eq(knowledge_system.get_knowers(12), [actor.id, nearby.id])
assert_eq(
knowledge_system.get_record(actor.id, 12).get_acquisition_method(),
SimulationIds.KNOWLEDGE_ACQUISITION_PERFORMED
)
assert_eq(
knowledge_system.get_record(nearby.id, 12).get_acquisition_method(),
SimulationIds.KNOWLEDGE_ACQUISITION_WITNESSED
)
func test_event_communication_preserves_first_provenance_and_stops_after_one_hop() -> void:
var actor := SimNPC.new(0, "Amina", SimulationIds.PROFESSION_FARMER, 5.0, 5.0)
var witness := SimNPC.new(1, "Tarik", SimulationIds.PROFESSION_GUARD, 5.0, 5.0)
var listener := SimNPC.new(2, "Jasmin", SimulationIds.PROFESSION_GUARD, 5.0, 5.0)
var relay_target := SimNPC.new(3, "Elma", SimulationIds.PROFESSION_GUARD, 5.0, 5.0)
actor.position = Vector3.ZERO
witness.position = Vector3(2.0, 0.0, 0.0)
listener.position = Vector3(20.0, 0.0, 0.0)
relay_target.position = Vector3(20.0, 0.0, 1.0)
var villagers: Array[SimNPC] = [actor, witness, listener, relay_target]
var event := EconomicEventRecord.create(
21,
SimulationIds.EVENT_STORAGE_DEPOSITED,
40,
actor.id,
SimulationIds.npc_inventory_id(actor.id),
SimulationIds.STORAGE_VILLAGE_PANTRY,
SimulationIds.RESOURCE_FOOD,
2.0,
Vector3.ZERO
)
var knowledge_system := EventKnowledgeSystemScript.new()
knowledge_system.observe_event(event, villagers)
assert_null(knowledge_system.communicate_event(event, listener.id, relay_target.id))
var communicated := knowledge_system.communicate_event(event, witness.id, listener.id)
assert_not_null(communicated)
assert_eq(
communicated.get_acquisition_method(), SimulationIds.KNOWLEDGE_ACQUISITION_COMMUNICATED
)
assert_eq(communicated.get_source_npc_id(), witness.id)
assert_null(knowledge_system.communicate_event(event, actor.id, listener.id))
assert_eq(knowledge_system.get_record(listener.id, event.data["event_id"]), communicated)
assert_null(knowledge_system.communicate_event(event, listener.id, relay_target.id))
assert_false(knowledge_system.knows_event(relay_target.id, int(event.data["event_id"])))
var actor_gap_system := EventKnowledgeSystemScript.new()
var direct_witness_records: Array[KnownEventStateRecord] = [
KnownEventStateRecord.create(
witness.id, int(event.data["event_id"]), SimulationIds.KNOWLEDGE_ACQUISITION_WITNESSED
)
]
actor_gap_system.restore(direct_witness_records)
assert_null(actor_gap_system.communicate_event(event, witness.id, actor.id))