extends SceneTree ## SITE 7 contract — the imported shop: ## - it builds, with racks AND bins ## - the cascade came off the shop's own data: racks hold bins via `supported_by` ## - smashing one rack releases exactly ITS bins, and no others ## - the real genre labels survived the import ## ## Godot --headless --path game --script dev/probe_store.gd func _initialize() -> void: var main: Node = (load("res://main.tscn") as PackedScene).instantiate() get_root().add_child(main) await process_frame main._load_level("store") for i in 70: await physics_frame var racks: Array = [] var bins: Array = [] var labelled := 0 for n in get_nodes_in_group("smashable"): var s := n as Smashable if s == null: continue if s.supports.size() > 0: racks.append(s) if s.freeze: bins.append(s) if s.has_meta("label"): labelled += 1 print("racks holding bins: %d frozen bins: %d labelled bins: %d" % [ racks.size(), bins.size(), labelled]) # --- the four rooms, and that you can actually walk between them ------------------- var spec: Dictionary = Levels.record_store() var walls: Array = spec.get("walls", []) var doors := 0 for w in walls: if (w as Dictionary).has("door"): doors += 1 print("interior walls: %d, of which %d have a doorway" % [walls.size(), doors]) if doors < 3: print("FAIL: the rooms are walled off from each other (need a door per portal)") quit(1) return # spawn must be standing in open air, not inside a wall or a rack var sp: Vector3 = spec["spawn"]["at"] var space := main.get_viewport().world_3d.direct_space_state var q := PhysicsShapeQueryParameters3D.new() var cap := CapsuleShape3D.new() cap.radius = 0.34 cap.height = 1.7 q.shape = cap q.transform = Transform3D(Basis.IDENTITY, sp + Vector3(0, 0.9, 0)) # the player is already standing here — that's the point, not an obstruction var pl = main.get("_player") if pl != null: q.exclude = [(pl as CollisionObject3D).get_rid()] var blocked := space.intersect_shape(q, 4) var names := "" for b in blocked: var c = b.get("collider") if c is Node: names += " " + String((c as Node).name) print("spawn at %s — %d bodies in the way:%s" % [sp.snappedf(0.01), blocked.size(), names]) if blocked.size() > 0: print("FAIL: spawn is inside geometry") quit(1) return if racks.is_empty() or bins.is_empty(): print("FAIL: the shop did not import (no racks holding bins)") quit(1) return if labelled < 20: print("FAIL: the real genre labels did not survive the import") quit(1) return # find the rack carrying the most bins and knock it over var best: Smashable = racks[0] for r in racks: if r.supports.size() > best.supports.size(): best = r var mine: Array = [] for b in best.supports: if is_instance_valid(b): mine.append(b) var others: Array = [] for b in bins: if is_instance_valid(b) and not mine.has(b): others.append(b) var others_frozen_before := 0 for b in others: if (b as RigidBody3D).freeze: others_frozen_before += 1 print("smashing '%s' — it carries %d bins" % [best.name, mine.size()]) best.smash(Vector3(0, 1, 0), 999.0) await physics_frame await physics_frame var released := 0 for b in mine: if is_instance_valid(b) and not (b as RigidBody3D).freeze: released += 1 var others_still := 0 for b in others: if is_instance_valid(b) and (b as RigidBody3D).freeze: others_still += 1 print("its bins released: %d/%d other bins still frozen: %d/%d" % [ released, mine.size(), others_still, others_frozen_before]) if released == mine.size() and others_still == others_frozen_before: print("STORE OK") quit(0) else: print("FAIL: cascade released the wrong set of bins") quit(1)