extends Node
## PROBE (not a gate) — fold cost of the F2 stack (#120, docs/node-tree-and-stacks.md §3.5
## "measured, not asserted"): N box shapes, each with a mirror + an array of 2 + one live
## cut, against the same N plain boxes. Prints full-refold time (median of 3) and the live
## brush count after each stage. One N per process: PROBE_N (default 50).
##
## RUN: PROBE_N=500 CI=true "$HYPER_TPS_GODOT" --headless --path . res://scenes/test/_probe_mod_fold_time.tscn
var persist: Node
var level: Node
func _ready() -> void:
var gs: Node = get_tree().root.get_node_or_null("/root/GameState")
gs.route("world:level:*", 1, "peer")
var keet: Node = get_tree().root.get_node_or_null("/root/KeetService")
if keet != null:
keet.current_member_id = "probe"
get_tree().root.get_node("/root/GameMode").set_mode("build")
var map: Node3D = (load("res://scenes/maps/map_dev_test.tscn") as PackedScene).instantiate()
add_child(map)
for i in 6:
await get_tree().process_frame
persist = map.get("_persist")
level = map.get("level")
var n := int(OS.get_environment("PROBE_N")) if OS.get_environment("PROBE_N") != "" else 50
var shapes: Array = []
for k in n:
var at := Vector3(200 + (k % 25) * 6, 0, 200 + (k / 25) * 6)
shapes.append(persist.record("shape.create", {"type": "box", "gv": 1, "params": {},
"frame": SceneObjects.xform_to(Transform3D(Basis.IDENTITY, at)),
"size": [2, 1, 2], "material_id": 2, "level_id": 0}))
var plain := _time()
var plain_n: int = (level.get_live_brush_ids() as PackedInt32Array).size()
for s1: String in shapes:
persist.record("mod.create", {"target": s1, "mod": "mirror", "params": {"axis": "x", "offset": 0.0}})
persist.record("mod.create", {"target": s1, "mod": "array", "params": {"count": 2, "offset": [0.0, 0.0, 1.0]}})
var mods := _time()
var mods_n: int = (level.get_live_brush_ids() as PackedInt32Array).size()
for s2: String in shapes:
var fr: Transform3D = persist.shape_state(s2)["frame"]
var c: String = persist.record("shape.create", {"type": "box", "gv": 1, "params": {},
"frame": SceneObjects.xform_to(Transform3D(Basis.IDENTITY, fr.origin + Vector3(0.5, 0.5, 0.5))),
"size": [1, 1, 1], "material_id": 2, "level_id": 0})
persist.record("op.create", {"op": "subtract", "cutter": c, "targets": [s2]})
var stack := _time()
var stack_n: int = (level.get_live_brush_ids() as PackedInt32Array).size()
print("PROBE N=%d | plain %.1f ms %d brushes | +mirror+array %.1f ms %d | +cut %.1f ms %d"
% [n, plain, plain_n, mods, mods_n, stack, stack_n])
get_tree().quit(0)
## A full refold, median of 3 (the tail fold is lost once any live op exists, §9a).
func _time() -> float:
var ts: Array = []
for i in 3:
persist.set("_brush_ver_folded", -1) # force the brush half
persist.set("_ix_tail_ok", false)
var t0 := Time.get_ticks_usec()
persist.refold()
ts.append(float(Time.get_ticks_usec() - t0) / 1000.0)
ts.sort()
return ts[1]