extends SceneTree var failures: Array[String] = [] func _initialize() -> void: call_deferred("_run") func _run() -> void: var manager := _create_manager(971) var ticks_per_day: int = manager.get_knowledge_review_interval() var berry := ResourceNode.new() berry.name = "SeasonBerry" berry.node_id = &"season_berry" berry.action_id = SimulationIds.ACTION_GATHER_FOOD berry.resource_id = SimulationIds.RESOURCE_FOOD berry.initial_amount = 2.0 berry.max_amount = 2.0 berry.regrow_rate = 0.1 berry.debug_label_enabled = false var interaction_point := Marker3D.new() interaction_point.name = "InteractionPoint" interaction_point.position = Vector3.ZERO berry.add_child(interaction_point) root.add_child(berry) await process_frame _check( manager.register_resource_node(berry), "Season test should bind a real finite ResourceNode" ) var state: ResourceStateRecord = manager.get_resource_state(berry.node_id) manager.clock.elapsed_ticks = 0 * ticks_per_day + 50 _check( ( manager.get_season() == &"warm" and is_equal_approx(manager._gather_yield_multiplier(), 1.0) ), "The first season days should be warm with full yields" ) _check( is_equal_approx(manager.harvest_resource_node(berry), 2.0), "Warm-season gathering should extract the full configured yield" ) state.set_amount_remaining(2.0) manager.clock.elapsed_ticks = 3 * ticks_per_day + 50 _check( ( manager.get_season() == &"cold" and is_equal_approx(manager._gather_yield_multiplier(), 0.5) ), "Later season days should be cold with reduced yields" ) _check( is_equal_approx(manager.harvest_resource_node(berry), 1.0), "Cold-season gathering should extract only half the configured yield" ) state.set_amount_remaining(0.5) manager.simulate_tick() _check( is_equal_approx(state.get_amount_remaining(), 0.5), "Cold-season regrowth should pause until warmer days" ) manager.clock.elapsed_ticks = 4 * ticks_per_day + 50 _check(manager.get_season() == &"warm", "The season should return warm after the cold spell") manager.simulate_tick() _check( is_equal_approx(state.get_amount_remaining(), 0.6), "Regrowth should resume once the warm season returns" ) manager.clock.elapsed_ticks = 3 * ticks_per_day + 50 var saved_json: String = manager.serialize_state() var restored := _create_manager(972) _check( restored.restore_state_from_json(saved_json), "Seasonal clock state should survive save and restore" ) _check( ( restored.get_state_checksum() == manager.get_state_checksum() and restored.get_season() == &"cold" and is_equal_approx(restored._gather_yield_multiplier(), 0.5) ), "Restore should re-derive the same cold season and its reduced yields" ) restored.free() berry.queue_free() manager.free() _finish() func _create_manager(seed_value: int = 971) -> 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] Seasonal rhythm passed: cold yields + paused regrowth") 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)