feat: add simulation action definitions
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
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() == 7,
|
||||
"Registry should contain all seven executable prototype actions"
|
||||
)
|
||||
|
||||
var profession_ids := SimulationDefinitions.get_profession_ids()
|
||||
_check(
|
||||
profession_ids.size() == 5,
|
||||
"Registry should contain all five prototype professions"
|
||||
)
|
||||
for profession_id in profession_ids:
|
||||
_check(
|
||||
SimulationDefinitions.get_profession(profession_id) != null,
|
||||
"Profession lookup should return '%s'" % profession_id
|
||||
)
|
||||
|
||||
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)
|
||||
Reference in New Issue
Block a user