extends Node # Operator-only, invoked explicitly by -- --forge-acceptance. # Input goes through Godot events/physics. No direct score or collision mutation. var checks: Array = [] var game: Node2D func _ready() -> void: game = get_parent() call_deferred("run") func check(label: String, ok: bool) -> void: checks.append({"label": label, "pass": ok}) if not ok: push_error(label) get_tree().quit(1) assert(ok, label) func key(code: int, pressed: bool) -> void: var event := InputEventKey.new() event.physical_keycode = code event.keycode = code event.pressed = pressed Input.parse_input_event(event) func ticks(count: int) -> void: for index in count: await get_tree().physics_frame await get_tree().process_frame func travel(code: int, axis: String, destination: float, increasing: bool, stop_on_win: bool = false) -> void: key(code, true) var reached := false for index in 400: await ticks(1) var value: float = game.player.position.x if axis == "x" else game.player.position.y if (value >= destination if increasing else value <= destination) or (stop_on_win and (game.won or game.lost)): reached = true break key(code, false) await ticks(2) check("physics travel %s to %s" % [axis, destination], reached) func run() -> void: await ticks(2) check("real configured main scene and CharacterBody2D", get_tree().current_scene == game and game.player is CharacterBody2D) check("real five exported frames and recorded 10 FPS", game.sprite.sprite_frames.get_frame_count("default") == 5 and game.sprite.sprite_frames.get_animation_speed("default") == 10) check("initial score and visible goals", game.score == 0 and not game.won and game.coins.all(func(c): return c.visible)) var initial_frame: int = game.sprite.frame await ticks(8) check("engine animation advances in gameplay scene", game.sprite.frame != initial_frame and game.sprite.is_playing()) key(KEY_RIGHT, true) await ticks(120) key(KEY_RIGHT, false) await ticks(2) check("actual keyboard movement reaches solid wall", game.player.position.x > 240 and game.player.position.x < 251) check("physics collision prevents crossing wall", game.player.is_on_wall()) check("Area2D goal counted once on real body overlap", game.score == 1 and not game.coins[0].visible) var stopped: Vector2 = game.player.position await ticks(10) check("released key stops displacement", game.player.position.is_equal_approx(stopped)) game.restart() await ticks(2) key(KEY_D, true) key(KEY_W, true) await ticks(20) key(KEY_D, false) key(KEY_W, false) await ticks(2) check("diagonal WASD is normalized instead of faster", game.player.position.distance_to(game.START) > 45 and game.player.position.distance_to(game.START) < 55) game.restart() await ticks(2) key(KEY_RIGHT, true) await ticks(5) game.notification(MainLoop.NOTIFICATION_APPLICATION_FOCUS_OUT) await ticks(2) var focus_position: Vector2 = game.player.position var focus_frame: int = game.sprite.frame await ticks(10) check("focus-out notification clears movement and pauses", game.frozen and game.player.position.is_equal_approx(focus_position) and game.sprite.frame == focus_frame and not Input.is_action_pressed("forge_right")) key(KEY_RIGHT, false) key(KEY_P, true) await ticks(2) key(KEY_P, false) await ticks(8) check("P resumes animation without stale held movement", not game.frozen and game.sprite.is_playing() and game.player.position.is_equal_approx(focus_position)) key(KEY_R, true) await ticks(2) key(KEY_R, false) await ticks(2) check("actual R input restores score goals and player", game.score == 0 and game.player.position.is_equal_approx(game.START) and game.coins.all(func(c): return c.visible)) await travel(KEY_RIGHT, "x", 190, true) check("first goal collected again after restart", game.score == 1) await travel(KEY_UP, "y", 74, false) await travel(KEY_RIGHT, "x", 420, true) check("second goal via route above obstacle", game.score == 2 and not game.coins[1].visible) await travel(KEY_RIGHT, "x", 480, true) await travel(KEY_DOWN, "y", 310, true, true) check("third real goal produces win and clear label", game.score == 3 and game.won and game.label.text.begins_with("Goal reached!")) var finish: Vector2 = game.player.position key(KEY_LEFT, true) await ticks(15) key(KEY_LEFT, false) check("terminal state stops movement and no duplicate score", game.player.position.is_equal_approx(finish) and game.score == 3) key(KEY_R, true) await ticks(2) key(KEY_R, false) await ticks(2) check("second round restarts after terminal state", not game.won and game.score == 0 and game.player.position.is_equal_approx(game.START)) await travel(KEY_RIGHT, "x", 190, true) check("second round goals still respond", game.score == 1) game.restart() await ticks(2) key(KEY_P, true) await ticks(2) key(KEY_P, false) var paused_time: float = game.remaining var paused_patrol: Vector2 = game.patrol.position await ticks(120) check("pause freezes actual timer and enemy", game.frozen and game.remaining == paused_time and game.patrol.position == paused_patrol) game.restart() await ticks(2) await travel(KEY_DOWN, "y", 320, true) await travel(KEY_RIGHT, "x", 240, true, true) check("real Area2D patrol contact ends the run", game.lost and not game.won and game.label.text.begins_with("Run ended!")) var lost_position: Vector2 = game.player.position var lost_time: float = game.remaining key(KEY_UP, true) await ticks(15) key(KEY_UP, false) check("lost state stops movement timer and animation", game.player.position == lost_position and game.remaining == lost_time and not game.sprite.is_playing()) game.restart() await ticks(2) await ticks(3610) check("sixty seconds of real physics expire without score mutation", game.lost and game.remaining == 0.0 and game.score == 0) game.restart() await ticks(2) check("loss restart resets patrol goals timer and animation", not game.lost and game.score == 0 and game.remaining > 59.9 and game.coins.all(func(c): return c.visible) and game.sprite.is_playing()) var report := {"checks": checks, "engine": Engine.get_version_info().string, "headless": DisplayServer.get_name() == "headless", "projectName": ProjectSettings.get_setting("application/config/name"), "scope": "Godot Coin Room 1.0 scene, parsed key events, real physics, Area2D pickups/patrol loss, timeout, animation, pause/restart and explicit focus-out notification. Not OS keyboard, physical input, GPU/editor visual review or independent external AI output."} var target := OS.get_environment("FORGE_COIN_ROOM_REPORT") check("operator report destination supplied", not target.is_empty()) var file := FileAccess.open(target, FileAccess.WRITE) file.store_string(JSON.stringify(report, "\t") + "\n") file.close() print("FORGE_COIN_ROOM_OK checks=" + str(checks.size())) get_tree().quit(0)