extends SceneTree ## The Roomba contract, measured: ## 1. docked at spawn — contributes nothing to residual motion (probe_levels covers ## the number; here we assert it is genuinely asleep and un-awake) ## 2. wakes on the first smash in the site ## 3. eats debris: a shard dropped in front of it is gone within a few seconds, ## and the score went DOWN for it ## ## Godot --headless --path game --script dev/probe_roomba.gd func _initialize() -> void: var main: Node = (load("res://main.tscn") as PackedScene).instantiate() get_root().add_child(main) await process_frame for i in 70: await physics_frame var roombas := get_nodes_in_group("roomba") if roombas.size() != 1: print("FAIL: expected 1 roomba in scranton, got %d" % roombas.size()) quit(1) return var r: Roomba = roombas[0] print("docked: awake=%s sleeping=%s at %s" % [r._awake, r.sleeping, r.global_position.snappedf(0.01)]) if r._awake: print("FAIL: roomba should be docked until the first smash") quit(1) return # smash the nearest smashable that isn't the roomba -> it must wake var victim: Smashable = null var best := INF for n in get_nodes_in_group("smashable"): if n is Roomba or not (n is Smashable) or (n as RigidBody3D).freeze: continue var d: float = (n.global_position - r.global_position).length_squared() if d < best: best = d victim = n victim.smash(Vector3(0, 2, 0), 999.0) await physics_frame if not r._awake: print("FAIL: roomba did not wake on the first smash") quit(1) return print("woke on first smash: OK") # drop a fresh piece of debris directly in its path and count down var score_before: int = main.get("_score") var shard := RigidBody3D.new() shard.add_to_group("debris") var col := CollisionShape3D.new() var box := BoxShape3D.new() box.size = Vector3(0.06, 0.06, 0.06) col.shape = box shard.add_child(col) main.get("_world").add_child(shard) shard.global_position = r.global_position + Vector3(0.05, 0.12, 0.0) var eaten := false for i in 300: # up to 5 s await physics_frame if not is_instance_valid(shard) or shard.is_queued_for_deletion(): eaten = true break var score_after: int = main.get("_score") print("shard eaten=%s score %d -> %d roomba _eaten=%d" % [ eaten, score_before, score_after, r._eaten]) if eaten and r._eaten >= 1: print("ROOMBA OK") quit(0) else: print("FAIL: shard survived the roomba for 5 s") quit(1)