extends SceneTree ## Emergency-aftermath smoke: places an unjustified emergency call, checks the ## investigation note and reputation hit, forces the responder to arrive, and ## verifies the evacuation outcome locks the door and clears the entrance. ## ## Usage: ## godot --headless --path . --script res://src/test/smoke_emergency.gd ## Exit code 0 = pass, 1 = failure. const MAX_FRAMES := 900 var frame := 0 var gm: Node = null var started := false var step := 0 var failures: Array[String] = [] func _initialize() -> void: root.size = Vector2i(1280, 720) root.add_child(load("res://scenes/main.tscn").instantiate()) func _process(_delta: float) -> bool: frame += 1 if gm == null: gm = root.find_child("GameManager", true, false) return false if not started: gm.call("_on_venue_selected", "hollywood_building") started = true return false if frame > MAX_FRAMES: _fail("timeout before the emergency aftermath ran") return true if frame < 200: return false if step == 0: if gm.npcs.is_empty(): return false gm.call("_on_guard_target", gm.npcs[0]) # A tourist: no weapon, low danger. gm.current_npc_truth = {"weapons_seen": false, "danger_level": 1} var rating_before: float = gm.coordinator.reputation.rating gm.call("_on_radio_submitted", { "npc_id": gm.current_incident_npc_id, "location": "entrance", "description": "tourist", "behavior": "standing", "weapons_seen": false, "danger_level": 1, }, true) _check(gm.coordinator.investigations.size() == 1, "unjustified emergency opens one investigation") _check(gm.coordinator.reputation.rating < rating_before, "unjustified emergency loses reputation") _check(gm.coordinator.radio.pending_calls.size() == 1, "the emergency call is pending") _check(not gm.door.locked, "the door is open before the responder arrives") step = 1 if step == 1: # Fast-forward the arrival delay. gm.coordinator.radio.tick(30.0) _check(gm.coordinator.radio.pending_calls.is_empty(), "the responder arrived") _check(gm.coordinator.responder_outcomes.has("evacuation"), "low-danger emergency resolves as evacuation") _check(gm.door.locked, "evacuation locks the door") var clearing := 0 for npc in gm.npcs: if is_instance_valid(npc) and (npc.reaction_mode == "flee" or npc.npc.leave_requested): clearing += 1 _check(clearing > 0, "evacuation sends people away from the entrance (%d clearing)" % clearing) var review: Dictionary = gm.coordinator.build_review() _check((review.get("review", review).get("responder_outcomes", []) as Array).has("evacuation"), "the review carries the responder outcome") _check((review.get("investigations", []) as Array).size() == 1, "the review carries the investigation note") step = 2 if step == 2: _finish() return true return false func _check(condition: bool, message: String) -> void: if condition: print("ok: " + message) else: _fail(message) func _fail(message: String) -> void: failures.append(message) _finish() func _finish() -> void: if failures.is_empty(): print("SMOKE OK: emergency aftermath (investigation, evacuation, review)") quit(0) else: for message in failures: printerr("SMOKE FAIL: " + message) quit(1)