extends SceneTree ## Boundary test: tries to escape the valley in several directions by walking ## and spamming jump at the mountain rim, and fails if the player ever gets past ## the invisible wall, falls off the map, or ends up stuck below the waterline ## (in a pit near the edge). ## ## Run: godot --headless --path . --fixed-fps 30 --script res://tests/test_boundary.gd const DIRECTIONS := 24 const SECONDS_PER_TRY := 25.0 func _initialize() -> void: var world: Node3D = load("res://scenes/world.tscn").instantiate() root.add_child(world) _run.call_deferred(world) func _run(world: Node3D) -> void: for _i in range(10): await physics_frame var terrain: Node3D = world.get_node("Terrain") var player: CharacterBody3D = world.get_node("Player") var failures := 0 var tick := 1.0 / Engine.physics_ticks_per_second for i in range(DIRECTIONS): var ang := TAU * i / DIRECTIONS var out := Vector3(cos(ang), 0.0, sin(ang)) var start: Vector3 = out * (terrain.play_radius - 12.0) start.y = terrain.sample_height(start.x, start.z) + 1.0 player.global_position = start player.velocity = Vector3.ZERO player.rotation = Vector3(0.0, atan2(-out.x, -out.z), 0.0) Input.action_press("move_forward") var escaped := false var max_d := 0.0 var frames := int(SECONDS_PER_TRY / tick) for f in range(frames): if f % 12 == 0: Input.action_press("jump") elif f % 12 == 1: Input.action_release("jump") await physics_frame var p := player.global_position max_d = maxf(max_d, Vector2(p.x, p.z).length()) if not terrain.inside_boundary(p.x, p.z, -1.5) or p.y < terrain.min_height - 5.0: escaped = true break Input.action_release("move_forward") Input.action_release("jump") var p := player.global_position if not escaped and p.y < terrain.water_level - 0.5: escaped = true # stuck in a pit below the waterline print("dir %2d (%3d deg): %s max radius %.1f final (%.1f, %.1f, %.1f)" % [ i, int(rad_to_deg(ang)), "FAILED" if escaped else "held", max_d, p.x, p.y, p.z]) if escaped: failures += 1 print("RESULT: %s (%d/%d directions held)" % ["PASS" if failures == 0 else "FAIL", DIRECTIONS - failures, DIRECTIONS]) quit(1 if failures > 0 else 0)