extends SceneTree
## GATE — TerraceGraph, the large-scale terraced landform (2026-10-06).
## T1 the builder's graph and the bridged scene's (blender/geiss_terraces.tscn) both
## compile to proc_density; the scene carries every TKNOBS knob as a labelled node
## T2 CONTINUOUS: along transects at 0.05 m, the terraced height never jumps (max step
## far below a terrace's height). NEGATIVE CONTROL: sharpness 1e4 makes the snap a
## near-sawtooth and MUST fail the same check — the first undersea graph's floors
## were exactly such a jump and meshed as floating razor sheets
## T3 TERRACED: most of the ground lies on a tread (the snap within 0.04 of a level)
## T6 RANDOM HEIGHTS: the tread levels' spacings lie in step * (1 ± step_random) and
## actually spread across it (not one uniform step)
## T4 RELIEF: the smooth field's p5..p95 over a 40 km grid is the `relief` knob ±15 %
## T5 the surface is where the density says: d(x, T(x)) == 0 and d is +below / -above
## CPU, through evaluate_socket on the builder with a constant Vector in place of Position.
##
## Run: CI=true HYPERTPS_DAEMON_TCP=127.0.0.1:1 "$HYPER_TPS_GODOT" --headless --path . --script res://scenes/test/gate_terrace_graph.gd
var ok := true
var checks := 0
func _p(c: bool, m: String, got: Variant = "") -> void:
checks += 1
print(("ok " if c else "FAIL: ") + m + ("" if str(got) == "" else " (" + str(got) + ")"))
if not c:
ok = false
func _init() -> void:
_run()
print("\n%d checks — %s" % [checks, "PASS" if ok else "FAIL"])
quit(0 if ok else 1)
class Sampler:
var b := TerraceGraph.new()
var ids: Dictionary
func _init(knobs: Dictionary = {}) -> void:
ids = b.build(ProcNodeGraph.new(), Vector3.ZERO, knobs)
func at(p: Vector3, what: String = "out") -> float:
b.g.get_node(ids["p"]).set("value", p)
return float(b.g.evaluate_socket(ids[what], 0))
## Largest |dT| between neighbours 0.05 m apart along three 400 m transects.
func _max_jump(s: Sampler) -> float:
var worst := 0.0
for z in [130.0, -2710.0, 5520.0]:
var prev := s.at(Vector3(-200.0, 0.0, z), "T")
var x := -200.0
while x < 200.0:
x += 0.05
var t := s.at(Vector3(x, 0.0, z), "T")
worst = maxf(worst, absf(t - prev))
prev = t
return worst
func _run() -> void:
var step := float(TerraceGraph.TKNOBS["step"])
# ---- T1 ----
var built := TerraceGraph.make_terraces()
_p(String(built.compile_to_glsl_function("proc_density", false, PackedStringArray())).contains("float proc_density"),
"T1 the builder's graph compiles to proc_density")
var saved := TerraceGraph.load_terraces()
_p(saved != null and String(saved.compile_to_glsl_function("proc_density", false, PackedStringArray())).contains("float proc_density"),
"T1 %s holds a graph that compiles" % TerraceGraph.SCENE_T)
var have := UnderseaGeissGraph.knobs_from(saved)
var missing: Array = []
for key: String in TerraceGraph.TKNOBS:
if not have.has(key):
missing.append(key)
_p(missing.is_empty(), "T1 the scene carries every knob as a labelled node (%d)" % have.size(), missing)
var s := Sampler.new()
# ---- T2 ----
var jump := _max_jump(s)
_p(jump < 0.25 * step, "T2 the terraced height is continuous (max step over 0.05 m %.2f m, terrace %.0f m)" % [jump, step])
var saw := _max_jump(Sampler.new({"sharpness": 10000.0}))
_p(saw >= 0.25 * step, "T2 negative control: a near-sawtooth snap FAILS the same check (max step %.2f m)" % saw)
# ---- T3 + T4 ----
var hs: Array[float] = []
var levels := {}
var on_tread := 0
var n := 0
for i in 41:
for kk in 41:
var p := Vector3(-20000.0 + i * 1000.0 + 13.7, 0.0, -20000.0 + kk * 1000.0 + 7.1)
hs.append(s.at(p, "H"))
var sn := s.at(p, "snap")
if sn < 0.04 or sn > 0.96:
on_tread += 1
n += 1
_p(float(on_tread) / n > 0.7, "T3 most of the ground is on a tread (%.0f %% with the snap within 0.04 of a level)" % (100.0 * on_tread / n))
# ---- T6 ----
# A dense transect: H is continuous, so walking it at 2 m visits EVERY level between
# its lowest and highest point, and consecutive collected levels are true neighbours
# (a coarse grid skips levels, and a skipped gap is indistinguishable by size).
var x := -20000.0
while x < 20000.0:
levels[snappedf(s.at(Vector3(x, 0.0, 1234.5), "lo"), 0.001)] = true
x += 2.0
var lv: Array = levels.keys()
lv.sort()
var gmin := 1e9
var gmax := 0.0
for i in range(1, lv.size()):
var gap := float(lv[i]) - float(lv[i - 1])
gmin = minf(gmin, gap)
gmax = maxf(gmax, gap)
var r := float(TerraceGraph.TKNOBS["step_random"])
_p(lv.size() >= 8 and gmin >= step * (1.0 - r) - 0.01 and gmax <= step * (1.0 + r) + 0.01,
"T6 every step height is within step * (1 ± step_random) = %.0f..%.0f m" % [step * (1.0 - r), step * (1.0 + r)],
"%d levels, gaps %.1f..%.1f m" % [lv.size(), gmin, gmax])
_p(gmax - gmin >= step * r, "T6 the step heights are RANDOM, not uniform (gaps span %.1f m)" % (gmax - gmin))
hs.sort()
var span := hs[int(n * 0.95)] - hs[int(n * 0.05)]
var relief := float(TerraceGraph.TKNOBS["relief"])
_p(absf(span - relief) <= 0.15 * relief, "T4 the smooth field's p5..p95 is the relief knob ±15 %",
"%.0f m against %.0f m (F_SPAN %.3f; measured span in F units %.3f)" % [span, relief, TerraceGraph.F_SPAN, span / relief * TerraceGraph.F_SPAN])
# ---- T5 ----
var bad := 0
for i in 20:
var p := Vector3(-3000.0 + i * 311.0, 0.0, 977.0 - i * 129.0)
var t := s.at(p, "T")
var on := absf(s.at(Vector3(p.x, t, p.z)))
if on > 1e-3 or s.at(Vector3(p.x, t - 1.0, p.z)) <= 0.0 or s.at(Vector3(p.x, t + 1.0, p.z)) >= 0.0:
bad += 1
_p(bad == 0, "T5 d is 0 on T, solid 1 m below, air 1 m above (20 columns)", bad)