extends SceneTree var failures := 0 var won_count := 0 var lost_count := 0 func check(value: bool, message: String) -> void: if not value: push_error(message) failures += 1 func _initialize() -> void: call_deferred("run") func run() -> void: var game = load("res://games/tempest/Tempest.tscn").instantiate() root.add_child(game) game.set_physics_process(false) game.game_won.connect(func(): won_count += 1) game.game_lost.connect(func(): lost_count += 1) check(game.start_game() and not game.start_game(),"single start") check(game.phase == "select","start opens selection") game.rotate_steps(2) game.confirm_level() check(game.stage == 5 and game.score == 0 and game.pending_bonus == 16000,"level five bonus is deferred") game._physics_process(1.5) check(game.phase == "play","ready transitions") game.rotate_steps(-1) check(game.lane == 15,"lane wrapping") game.fire_timer = 0.0 game.enemies.assign([game.make_enemy("flipper",15,.9)]) game.fire() game._step_play(.1) check(game.score == 150,"swept shot scores flipper") game.enemies.assign([game.make_enemy("tanker",15,.6)]) game.fire_timer = 0 game.shots.clear() game.fire() game._step_play(.2) check(game.enemies.size() == 2 and game.enemies[0].kind == "flipper","tanker splits on hit") game.superzap() check(game.enemies.is_empty() and game.zap_uses == 1,"first zap clears") game.enemies.assign([game.make_enemy("flipper",0,.1),game.make_enemy("flipper",1,.2)]) game.zap_flash = 0 game.superzap() check(game.enemies.size() == 1 and game.zap_uses == 2,"second zap kills one") game.zap_flash = 0 game.superzap() check(game.enemies.size() == 1,"third zap unavailable") game.enemies.clear() game.remaining = 0 var prior_score: int = game.score game._step_play(.01) check(game.phase == "dive" and game.score == prior_score+16000 and game.cleared == 1,"first clear earns bonus") game._physics_process(1.7) check(game.phase == "space","dive enters starfield") game._physics_process(1.3) check(game.phase == "arrive" and game.stage == 6,"next tube arrives") game._physics_process(1.7) check(game.phase == "ready" and game.pending_bonus == 0,"bonus not repeated") game.cleared = game.stages_to_win game.phase = "space" game.phase_time = .1 game._physics_process(.2) game._physics_process(1.1) game._physics_process(1.1) check(game.phase == "won" and won_count == 1 and not game.is_running,"single room win counts clears not level number") game.reset_game() game.start_game() game._physics_process(10.1) check(game.phase == "ready" and game.stage == 1,"selection timeout starts default") game.phase = "play" game.lives = 1 game.remaining = 10 game.enemies.assign([game.make_enemy("flipper",game.lane,1.0)]) game._step_play(.01) game._physics_process(1.3) check(game.phase == "lost" and lost_count == 1,"last life loses") game.reset_game() game.start_game() game.confirm_level() game.phase = "play" var enemy: Dictionary = game.make_enemy("flipper",15,.6) game._start_roll(enemy,1) check(game.collision_lane(enemy) == 15,"roll collision starts in source lane") enemy.roll = .1 check(game.collision_lane(enemy) == 0,"roll collision ends in destination lane") game.enemies.assign([game.make_enemy("spiker",3,.64)]) game._step_play(.2) check(game.spikes.has(3) and game.enemies[0].retreat,"spiker builds and retreats") game.spikes[3] = .4 game.phase = "dive" game.phase_time = .6 game.lane = 3 game.cleared = 1 var prior_lives: int = game.lives game._physics_process(.01) check(game.phase == "death" and game.lives == prior_lives-1 and game.cleared == 0,"warp spike collision") var board = game.get_node("VectorBoard") var center: Vector2 = (board.rim(0,0)+board.rim(8,0))*.5 check(is_equal_approx(center.x,320) and center.y > 410,"vanishing point centered and low") game.stage = 9 game.phase = "play" game.lane = 0 game.rotate_steps(-1) check(game.lane == 0,"open tube does not wrap") game.lane = 15 game.rotate_steps(1) check(game.lane == 15,"open tube right boundary") game.stages_to_win = 0 game.phase = "space" game.phase_time = .1 game._physics_process(.2) check(game.phase == "arrive","endless mode keeps progressing") # Simulate a longer random play sequence to exercise rendering data and AI. game.reset_game() game.start_game() game.selection = 4 game.confirm_level() game.phase = "play" game.lives = 999 for i in range(3600): if i%6 == 0: game.rotate_steps(1) game.fire_timer = maxf(0,game.fire_timer-1.0/60) game.fire() game._physics_process(1.0/60) check(game.score >= 0,"minute of simulation completes") print("Tempest v2 checks complete: ",failures," failures") game.get_node("VectorAudio").stop() await create_timer(.2).timeout game.queue_free() await process_frame quit(failures)