Files
gamedev-the-steward/tests/simulation_definitions_test.gd
admin c61d286005 feat: wood inventory, carrying, and woodpile storage
Wood now follows the same gather-carry-deposit pattern as food. NPCs put harvested wood into inventory, walk to the VillageWoodpile StorageNode, and deposit it. Village wood syncs from storage. Player harvesting also routes wood to the woodpile. ActiveWorldAdapter exposes woodpile routing for DEPOSIT_WOOD action targeting. WorldViewManager recognizes wood inventory changes. Tests verify woodpile node existence, storage ID, navigation reachability, and adapter routing.
2026-07-08 18:55:51 +02:00

130 lines
4.0 KiB
GDScript

extends SceneTree
var failures: Array[String] = []
func _initialize() -> void:
call_deferred("_run")
func _run() -> void:
_test_registry_integrity()
_test_definition_backed_behavior()
_test_state_reference_validation()
_test_id_round_trip()
if failures.is_empty():
print("[TEST] Simulation definitions passed")
quit(0)
return
for failure in failures:
push_error("[TEST] " + failure)
quit(1)
func _test_registry_integrity() -> void:
var errors := SimulationDefinitions.validate()
_check(errors.is_empty(), "Definition registry should validate: %s" % [errors])
var action_ids: Array[StringName] = []
for definition in SimulationDefinitions.get_actions():
action_ids.append(definition.action_id)
_check(
SimulationDefinitions.get_action(definition.action_id) == definition,
"Action lookup should return '%s'" % definition.action_id
)
_check(action_ids.size() == 11, "Registry should contain all eleven executable prototype actions")
var profession_ids := SimulationDefinitions.get_profession_ids()
_check(profession_ids.size() == 5, "Registry should contain all five prototype professions")
var profession_colors := {}
for profession_id in profession_ids:
var profession := SimulationDefinitions.get_profession(profession_id)
_check(
profession != null,
"Profession lookup should return '%s'" % profession_id
)
if profession != null:
profession_colors[profession.visual_color.to_html()] = true
_check(
profession_colors.size() == profession_ids.size(),
"Each profession should have a distinct definition-backed visual color"
)
func _test_definition_backed_behavior() -> void:
var npc := SimNPC.new(500, "DefinitionWorker", SimulationIds.PROFESSION_SCHOLAR, 5.0, 5.0)
npc.set_task(SimulationIds.ACTION_STUDY)
var study := SimulationDefinitions.get_action(SimulationIds.ACTION_STUDY)
_check(
is_equal_approx(npc.task_duration, study.default_duration),
"SimNPC should use the action definition's default duration"
)
_check(
study.preferred_profession_id == SimulationIds.PROFESSION_SCHOLAR,
"Study should reference the stable scholar profession ID"
)
var gather := SimulationDefinitions.get_action(SimulationIds.ACTION_GATHER_FOOD)
_check(
(
gather.target_type == SimulationIds.TARGET_RESOURCE
and gather.resource_action_id == SimulationIds.ACTION_GATHER_FOOD
),
"Gather-food target metadata should come from its definition"
)
func _test_state_reference_validation() -> void:
var npc := SimNPC.new(501, "ValidationWorker", SimulationIds.PROFESSION_FARMER, 5.0, 5.0)
var valid_data := NPCStateRecord.capture(npc).to_dictionary()
var invalid_profession := valid_data.duplicate(true)
invalid_profession["profession"] = "missing_profession"
_check(
NPCStateRecord.from_dictionary(invalid_profession) == null,
"NPC state should reject an unknown profession ID"
)
var invalid_action := valid_data.duplicate(true)
invalid_action["current_task"] = "missing_action"
_check(
NPCStateRecord.from_dictionary(invalid_action) == null,
"NPC state should reject an unknown action ID"
)
func _test_id_round_trip() -> void:
var manager: Node = load("res://simulation/SimulationManager.gd").new()
manager.debug_logs = false
root.add_child(manager)
manager.set_process(false)
var json_state: String = manager.serialize_state()
var restored: Node = load("res://simulation/SimulationManager.gd").new()
restored.debug_logs = false
root.add_child(restored)
restored.set_process(false)
_check(
restored.restore_state_from_json(json_state),
"Definition-backed IDs should restore from serialized state"
)
for npc in restored.npcs:
_check(
typeof(npc.profession) == TYPE_STRING_NAME, "Profession should restore as StringName"
)
_check(
typeof(npc.current_task) == TYPE_STRING_NAME,
"Current action should restore as StringName"
)
_check(
SimulationDefinitions.get_profession(npc.profession) != null,
"Restored profession should resolve through the registry"
)
manager.free()
restored.free()
func _check(condition: bool, message: String) -> void:
if not condition:
failures.append(message)