extends SceneTree var _checks := 0 var _failures := 0 var _runtime: Variant var _clock: Variant var _state: Variant var _serial := 0 func _initialize() -> void: call_deferred("_run") func _run() -> void: _runtime = load("res://autoload/simulation_runtime.gd").new() _clock = load("res://autoload/game_clock.gd").new() _state = load("res://autoload/game_state.gd").new() _reset() _expect(_runtime.path_service.get_vertical_walk_requires_connector(), "new Runtime requires explicit vertical transport") _expect(_runtime.definition_registry.facility_count() == 25, "Runtime registers baseline16, stairs, infirmary, premium room/dormitory, chapel and A07/A08 warps") var before: Dictionary = _runtime.create_snapshot() var invalid := _command(&"build_facility", {&"definition_id": &"guest_stairs", &"origin": Vector3i(4, 3, 0)}) _expect(not invalid.is_success() and invalid.details.get(&"reason") == &"STAIR_LANDING_MISSING", "stairs without a lower landing reject before any construction") _expect(_runtime.construction_service.get_jobs().is_empty() and _state.get_resource(&"gold") == 5000, "missing landing spends no money and starts no job") _build(&"guest_stairs", Vector3i(4, 1, 0)) _build(&"guest_stairs", Vector3i(4, 2, 0)) var route: Array = _runtime.path_service.find_path(Vector3i(4, 0, 0), Vector3i(4, 2, 0)) _expect(route.size() == 3 and _runtime.path_service.calculate_path_cost(route) == 300, "two staircase floors cost three walking minutes") _expect(_runtime._estimated_actor_path_minutes(route, Array([], TYPE_STRING_NAME, &"", null)) == 3, "actor arrival estimate includes stair time") var spawn := _command(&"spawn_guest", {&"guest_id": &"stair.guest", &"guest_type_id": &"traveler", &"gold": 100, &"options": {&"current_cell": Vector3i(4, 0, 0), &"state": GuestRuntime.State.MOVING, &"state_entered_at": _clock.absolute_minute - 1, &"planned_exit_at": _clock.absolute_minute + 2000, &"path_handle": {&"target_cell": Vector3i(4, 2, 0)}}}) _expect(spawn.is_success(), "public guest spawn creates a real stair traveller") _clock.advance_minutes(1) var guest: GuestRuntime = _runtime.guest_service.get_guest(&"stair.guest") _expect(guest.current_cell == Vector3i(4, 0, 0), "after one minute guest is still completing the first staircase") var mid: Dictionary = _runtime.create_snapshot() _expect(mid[&"systems"][&"runtime"][&"movement_credits"][0][&"credit"] == 1000, "partial staircase persists one minute of movement credit") _expect(_runtime.restore_snapshot(mid) and _runtime.create_snapshot() == mid, "half-finished staircase restores exactly") _clock.advance_minutes(2) var arrived: Dictionary = _runtime.create_snapshot() _expect(_runtime.guest_service.get_guest(&"stair.guest").current_cell == Vector3i(4, 2, 0), "two floors complete in three actual simulation minutes") _expect(_runtime.restore_snapshot(mid), "restore partial staircase for deterministic replay") _clock.advance_minutes(2) _expect(_runtime.create_snapshot() == arrived, "fractional stair travel replays every aggregate exactly") var bad := mid.duplicate(true) bad[&"systems"][&"runtime"][&"movement_credits"][0][&"credit"] = 1500 _expect(not _runtime.restore_snapshot(bad) and _runtime.create_snapshot() == arrived, "unspent complete stair step is rejected atomically") bad = mid.duplicate(true) bad[&"systems"][&"runtime"][&"path"][&"vertical_walk_requires_connector"] = false _expect(not _runtime.restore_snapshot(bad), "current Runtime cannot save unrestricted vertical walking") bad = mid.duplicate(true) bad[&"systems"][&"runtime"].erase(&"legacy_stairs") _expect(not _runtime.restore_snapshot(bad), "current Runtime requires stair ownership metadata") bad = mid.duplicate(true) bad[&"systems"][&"runtime"][&"runtime_schema_version"] = 8 bad[&"systems"][&"runtime"].erase(&"legacy_stairs") bad[&"systems"][&"runtime"][&"path"][&"vertical_walk_requires_connector"] = false _expect(not _runtime.restore_snapshot(bad), "older Runtime label cannot smuggle current Path policy fields") var blockade := mid.duplicate(true) for traffic: Dictionary in blockade[&"systems"][&"runtime"][&"path"][&"cell_traffic"]: if traffic[&"cell"] == Vector3i(4, 1, 0): traffic[&"temporary_block"] = true _expect(_runtime.restore_snapshot(blockade), "temporary blockade preserves valid fractional staircase credit") _expect(_runtime.restore_snapshot(_runtime.create_snapshot()), "blocked partial staircase re-saves canonically") _reset() _build(&"guest_corridor", Vector3i(4, 1, 0)) _build(&"guest_stairs", Vector3i(4, 2, 0)) var lower_id := _facility_at(Vector3i(4, 1, 0)) var upper_id := _facility_at(Vector3i(4, 2, 0)) var blocked := _command(&"demolish_facility", {&"instance_id": lower_id}) _expect(not blocked.is_success() and blocked.details.get(&"reason") == &"STAIR_LANDING_IN_USE", "occupied lower landing rejects demolition before a broken stair is created") _expect(_runtime.restore_snapshot(_runtime.create_snapshot()), "rejected stair demolition remains saveable") _expect(_command(&"demolish_facility", {&"instance_id": upper_id}).is_success(), "upper staircase can be removed first") _expect(_command(&"demolish_facility", {&"instance_id": lower_id}).is_success(), "unused lower corridor can then be removed") _reset() _build(&"service_stairs", Vector3i(4, 1, 1)) _expect(_runtime.path_service.find_path(Vector3i(4, 0, 1), Vector3i(4, 1, 1)).is_empty(), "guests cannot use service stairs") _expect(_runtime.path_service.find_path(Vector3i(4, 0, 1), Vector3i(4, 1, 1), [0, 1], [&"staff"]).size() == 2, "staff can use service stairs") _test_legacy() _test_occupied_stair_demolition() print("Runtime stairs: %d checks, %d failures" % [_checks, _failures]) _runtime.free() _clock.free() _state.free() quit(1 if _failures else 0) func _test_legacy() -> void: _reset() _build(&"guest_corridor", Vector3i(4, 1, 0)) _build(&"guest_corridor", Vector3i(4, 2, 0)) _expect(_runtime.path_service.find_path(Vector3i(4, 0, 0), Vector3i(4, 2, 0)).is_empty(), "new corridors do not act as invisible stairs") var legacy: Dictionary = _runtime.create_snapshot() var data: Dictionary = legacy[&"systems"][&"runtime"] data[&"runtime_schema_version"] = 8 data.erase(&"legacy_stairs") preload("res://tests/fixtures/pre_upkeep_runtime.gd").strip_empty_upkeep(data) data[&"path"][&"schema_version"] = 4 data[&"path"].erase(&"vertical_walk_requires_connector") data[&"path"].erase(&"transit_actor_ids") _expect(_runtime.restore_snapshot(legacy), "actual v8 structure migrates existing vertical corridors") var records: Array = _runtime.legacy_stairs.create_snapshot()[&"stairs"] _expect(records.size() == 2 and _runtime.path_service.get_vertical_walk_requires_connector(), "migration materializes only the two original vertical links") var route: Array = _runtime.path_service.find_path(Vector3i(4, 0, 0), Vector3i(4, 2, 0)) _expect(route.size() == 3 and _runtime.path_service.calculate_path_cost(route) == 200, "old corridor stairs retain their original speed and reachability") var canonical: Dictionary = _runtime.create_snapshot() var preview := WorldPreview.new() preview.size=Vector2(1280,720) preview.set_runtime(_runtime) preview.layer_mode=WorldPreview.LayerMode.BACK preview.reset_view() var ghost_ids: Array = [] for item: Dictionary in preview._other_layer_rooms(): if item.get(&"legacy_stair",false): ghost_ids.append(item[&"id"]) _expect(ghost_ids.size()==2 and ghost_ids.has(records[0][&"id"]) and ghost_ids.has(records[1][&"id"]), "opposite-layer view renders each actually migrated legacy connector once") preview.free() _expect(_runtime.create_snapshot()==canonical,"migrated legacy visualization does not alter canonical save or routes") _expect(_runtime.restore_snapshot(canonical) and _runtime.create_snapshot() == canonical, "migrated save is canonical and migration does not repeat") var malformed := canonical.duplicate(true) malformed[&"systems"][&"runtime"][&"legacy_stairs"][&"stairs"].pop_back() _expect(not _runtime.restore_snapshot(malformed) and _runtime.create_snapshot() == canonical, "orphan legacy connector is rejected atomically") var upper_id := _facility_at(Vector3i(4, 2, 0)) _expect(_command(&"demolish_facility", {&"instance_id": upper_id}).is_success(), "legacy upper landing can be demolished normally") _expect(_runtime.legacy_stairs.create_snapshot()[&"stairs"].size() == 1, "demolition retires that stair's ownership record") _build(&"guest_corridor", Vector3i(4, 2, 0)) _expect(_runtime.path_service.find_path(Vector3i(4, 1, 0), Vector3i(4, 2, 0)).is_empty(), "rebuilding a plain corridor never regenerates a legacy staircase") _expect(_runtime.restore_snapshot(_runtime.create_snapshot()), "pruned and rebuilt topology remains saveable") func _reset() -> void: _clock.reset(1, 6, 0) _state.reset() _expect(_runtime.initialize(_clock, _state, 90416)[&"valid"], "stairs fixture initializes") _runtime.configure_save_policy({&"enabled": false, &"daily_checkpoint_enabled": false}) _clock.set_paused(true) func _build(id: StringName, origin: Vector3i) -> void: var built := _command(&"build_facility", {&"definition_id": id, &"origin": origin}) _expect(built.is_success(), "normal construction accepts %s %s: %s" % [id, origin, built.message]) _clock.advance_minutes(10) _expect(not _facility_at(origin).is_empty(), "construction completes %s %s" % [id, origin]) func _facility_at(origin: Vector3i) -> StringName: for facility: Dictionary in _runtime.construction_service.get_facilities(): if facility[&"origin"] == origin: return facility[&"instance_id"] return &"" func _command(type: StringName, payload: Dictionary) -> CommandResult: _serial += 1 return _runtime.submit_command(type, payload, &"manager", &"", 0, -1, StringName("runtime.stairs.%d" % _serial)) func _expect(ok: bool, label: String) -> void: _checks += 1 if not ok: _failures += 1 push_error(label) else: print("PASS: ", label) func _test_occupied_stair_demolition() -> void: _reset() _build(&"guest_stairs", Vector3i(4, 1, 0)) var stair_id := _facility_at(Vector3i(4, 1, 0)) _expect(_command(&"spawn_guest", {&"guest_id": &"occupied.stair", &"guest_type_id": &"traveler", &"gold": 100, &"options": {&"current_cell": Vector3i(4, 1, 0), &"state": GuestRuntime.State.MOVING, &"state_entered_at": _clock.absolute_minute - 1, &"planned_exit_at": _clock.absolute_minute + 100, &"path_handle": {&"target_cell": Vector3i(4, 0, 0)}}}).is_success(), "real guest is standing on upper staircase landing") var paths: Dictionary = _runtime.path_service.create_snapshot() var rejected := _command(&"demolish_facility", {&"instance_id": stair_id}) _expect(not rejected.is_success() and rejected.details.get(&"reason") == &"FACILITY_OCCUPIED", "occupied staircase cannot delete a real guest's landing") _expect(_runtime.path_service.create_snapshot() == paths and _runtime.guest_service.get_guest(&"occupied.stair").current_cell == Vector3i(4, 1, 0), "demolition rejection preserves actor projection and position") _expect(_runtime.restore_snapshot(_runtime.create_snapshot()), "occupied staircase rejection leaves a valid canonical save") _clock.advance_minutes(2) _expect(_runtime.guest_service.get_guest(&"occupied.stair").current_cell == Vector3i(4, 0, 0), "guest physically finishes descending before demolition") _expect(_command(&"demolish_facility", {&"instance_id": stair_id}).is_success(), "empty staircase can be removed after the guest leaves") _expect(_runtime.restore_snapshot(_runtime.create_snapshot()), "post-descent demolition remains saveable")