Quarter becomes the deepest navigable rung. Block and Chunk leave the ladder. The rule, from the amendment: the deepest Atlas rung is the one at which a screen pixel shows one subtile. At the uniform 2x2 px display ratio a 3440x1440 window gives 540 gridunits on the short axis, so Quarter's 512 m extent draws 0.948 m per gridunit -- about one voxel per gridunit and one 0.5 m subtile per pixel. Block (0.237) and Chunk (0.119) magnify beneath the finest datum that can exist, and measured as exactly that on Ferrath: one morphology zone, one vegetation class, an unbroken colour field. They were not missing a feature; there was nothing left to show them. CHUNK ITSELF IS UNTOUCHED. It remains D-243's 64 m stream/derive unit and is where Phase 5 derives first-person walkable content -- D-012's load-around-the-player is expressed in chunks. Block remains the 128 m generator planning unit. Both keep their enum variants, their extent_m answers and their wire vocabulary. What was retired is the claim that a MAP of one is worth looking at. DEEP_RUNGS moved with the floor, and this is the part worth reading twice. It is a mandatory D-255(d) hardening: a per-body retention cap bounding how much ground an exhaustive pan can hold resident at fine spacing. Left as [Block, Chunk] it would have guarded rungs no client can request -- dead code -- while the accumulation gap silently re-opened under Quarter, now the finest navigable rung at ~0.95 m per gridunit. It is now [District, Quarter]. A control that names its targets by rung has to follow the ladder when the ladder moves. Six tests pinned the old floor and were updated rather than deleted, since each was protecting a real property: the clamp tests now clamp at Quarter, and the disk-cache tests use Region for "shallow" (District is capped now) and Quarter for "deep". One new test pins the distinction the change turns on -- the retired rungs are absent from RUNG_LADDER but still present in RUNG_EXTENT_M, because viewability was retired, not vocabulary. Also removes the four capture scenarios for the retired rungs, including the two blank goldens that had been passing against blank captures. 1838 client tests, 0 failed. Server clippy clean, step_canvas suite green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
374 lines
14 KiB
GDScript
374 lines
14 KiB
GDScript
extends RefCounted
|
|
## Setup hooks for visual test scenarios.
|
|
## Config (tests/visual.json) controls WHAT to run; this file controls HOW to
|
|
## set up each scenario in-engine. Called by visual_capture.gd after main.tscn
|
|
## is loaded and settled.
|
|
##
|
|
## Autoload globals (FogState, SimBridge, GameState) are NOT available as
|
|
## compile-time identifiers in -s mode. All methods receive tree_root and
|
|
## look up autoloads via get_node("/root/...").
|
|
|
|
|
|
## Ferrath and its system, shared by the descent-ladder cases below (the older
|
|
## per-rung cases still inline their own copies — left alone rather than
|
|
## churned, since touching them would move goldens for no reason).
|
|
const _FERRATH := {
|
|
"body_id": "GJ820Bc",
|
|
"body_radius_km": 6062.0,
|
|
"proper_name": "Ferrath",
|
|
"terrain_reference": "wiki/star-systems/GJ-820B/bodies/GJ820Bc/heightmap.png",
|
|
}
|
|
const _CYGNI_B := {"system_id": "GJ 820B", "proper_name": "Cygni B"}
|
|
|
|
## A known-good LAND point on Ferrath, in world metres. Sourced from the
|
|
## cascade's highest-scoring city placement (city 24386 @ heightmap pixel
|
|
## (52, 395), survey cell (49, 6), score 7200 — printed by `cargo run --bin
|
|
## aliveness_probe -- --body GJ820Bc`), but read it as "somewhere the
|
|
## generator considers good ground", NOT as a settlement to look at: a
|
|
## CityPlacement is a match record — a pixel, an archetype, a founding
|
|
## orientation — and no streets, footprints or buildings exist anywhere yet.
|
|
## Drawing settlements is T-1207 (wave 2), deliberately deferred.
|
|
##
|
|
## Re-run the probe if the cascade seed or placement rules change: a stale
|
|
## value here silently reframes the ladder rather than failing.
|
|
const _FERRATH_LAND := Vector2(29422009.0, -5675959.0)
|
|
|
|
|
|
## Apply scenario-specific setup before tick advancement.
|
|
## Returns true if the scenario is recognized, false otherwise.
|
|
func apply_setup(scenario_name: String, tree_root: Node) -> bool:
|
|
match scenario_name:
|
|
"implant_pending":
|
|
# #960: overlay the diegetic Layer-1 "generating" indicator for
|
|
# visual sign-off. Loaded via load() — class_name isn't available
|
|
# in -s mode (per this file's header note).
|
|
var pending_script: GDScript = load("res://ui/implant/implant_pending.gd")
|
|
var theme_res: Resource = load("res://ui/implant/default_implant.tres")
|
|
var layer := CanvasLayer.new()
|
|
layer.layer = 100
|
|
tree_root.add_child(layer)
|
|
var indicator: Control = pending_script.new()
|
|
indicator.name = "VisualImplantPending"
|
|
layer.add_child(indicator)
|
|
indicator.apply_implant_theme(theme_res)
|
|
indicator.position = Vector2(370.0, 240.0) # centered at 960x540
|
|
indicator.start("GENERATING LAYER 1")
|
|
|
|
"atlas_gen_open":
|
|
# #960 live inspection: open the actual atlas app through HudGroups (the
|
|
# production opener), navigate to GJ71c's regional screen, and enable the
|
|
# region-ramp overlays — exercises the opener + the live request → cascade
|
|
# → render pipeline against a connected server (SR_LIVE=1). D-255 rewrite:
|
|
# the pre-stepped l1_rivers/l1_basins/l1_attractors overlay ids retired
|
|
# with AtlasWindowViewer — StepCanvasViewer's own toggle group is exactly
|
|
# the three gen_dw_* region-ramp colorizers (step_canvas_viewer.gd's
|
|
# OVERLAY_DEFS), so this now enables all three instead.
|
|
var hud_groups: Node = tree_root.get_node("/root/HudGroups")
|
|
var registry: Node = tree_root.get_node("/root/ImplantRegistry")
|
|
hud_groups.open_app("implant/map")
|
|
var app: Variant = registry.get_app_instance("implant/map")
|
|
if app == null:
|
|
push_warning("VisualScenarios: atlas app not instantiated")
|
|
return true
|
|
var body := {
|
|
"body_id": "GJ71c",
|
|
"body_radius_km": 5503.5,
|
|
"proper_name": "Threshold",
|
|
"terrain_reference": "wiki/star-systems/GJ-71/bodies/GJ71c/heightmap.png",
|
|
}
|
|
app.nav.push(
|
|
"regional", {"body": body, "system": {"system_id": "GJ 71", "proper_name": "GJ 71"}}
|
|
)
|
|
var viewer: Variant = app._regional_screen._viewer
|
|
viewer.set_overlay_visible("gen_dw_temp", true)
|
|
|
|
# T-1157 (D-255 rewrite): the stepped-Atlas golden matrix — goldens key
|
|
# on (body, rung), not the retired continuous-zoom (body, zoom, overlay-
|
|
# set) triples T-1120 curated. Each case below pins ONE body/rung/
|
|
# overlay combo, driven through the SAME production surface the app
|
|
# itself uses: AtlasApp._on_body_selected()'s own tail
|
|
# (nav.push("regional", ...)) to enter, then StepCanvasViewer.jump_to()
|
|
# for every rung below Global — the T-1157 harness-inventory "fixed-
|
|
# center revisit" pattern (world_center literally re-requested, not
|
|
# re-derived from a cursor gesture), so the SAME world point is hit on
|
|
# every run regardless of viewport size or cursor-anchoring math. The
|
|
# Global rung needs no jump_to() call at all: enter() always lands on
|
|
# it (world_center == ZERO, D-255(a)) — it is the natural replacement
|
|
# for the old whole-body "fit zoom" shot.
|
|
"atlas_GJ380c_Global":
|
|
_setup_atlas_golden_shot(
|
|
tree_root,
|
|
{
|
|
"body_id": "GJ380c",
|
|
"body_radius_km": 6238.4,
|
|
"proper_name": "Lendel",
|
|
"terrain_reference": "wiki/star-systems/GJ-380/bodies/GJ380c/heightmap.png",
|
|
},
|
|
{"system_id": "GJ 380", "proper_name": "Groombridge"},
|
|
"Global",
|
|
["gen_dw_temp"]
|
|
)
|
|
|
|
"atlas_GJ380c_Region":
|
|
_setup_atlas_golden_shot(
|
|
tree_root,
|
|
{
|
|
"body_id": "GJ380c",
|
|
"body_radius_km": 6238.4,
|
|
"proper_name": "Lendel",
|
|
"terrain_reference": "wiki/star-systems/GJ-380/bodies/GJ380c/heightmap.png",
|
|
},
|
|
{"system_id": "GJ 380", "proper_name": "Groombridge"},
|
|
"Region",
|
|
["gen_dw_moisture"]
|
|
)
|
|
|
|
"atlas_GJ380c_District":
|
|
_setup_atlas_golden_shot(
|
|
tree_root,
|
|
{
|
|
"body_id": "GJ380c",
|
|
"body_radius_km": 6238.4,
|
|
"proper_name": "Lendel",
|
|
"terrain_reference": "wiki/star-systems/GJ-380/bodies/GJ380c/heightmap.png",
|
|
},
|
|
{"system_id": "GJ 380", "proper_name": "Groombridge"},
|
|
"District",
|
|
[]
|
|
)
|
|
|
|
"atlas_GJ144e_Global":
|
|
_setup_atlas_golden_shot(
|
|
tree_root,
|
|
{
|
|
"body_id": "GJ144e",
|
|
"body_radius_km": 6959.3,
|
|
"proper_name": "Vethis",
|
|
"terrain_reference": "wiki/star-systems/GJ-144/bodies/GJ144e/heightmap.png",
|
|
},
|
|
{"system_id": "GJ 144", "proper_name": "Ran"},
|
|
"Global",
|
|
[]
|
|
)
|
|
|
|
"atlas_GJ144e_Quarter":
|
|
_setup_atlas_golden_shot(
|
|
tree_root,
|
|
{
|
|
"body_id": "GJ144e",
|
|
"body_radius_km": 6959.3,
|
|
"proper_name": "Vethis",
|
|
"terrain_reference": "wiki/star-systems/GJ-144/bodies/GJ144e/heightmap.png",
|
|
},
|
|
{"system_id": "GJ 144", "proper_name": "Ran"},
|
|
"Quarter",
|
|
["gen_dw_veg"]
|
|
)
|
|
|
|
"atlas_GJ338Bd_Global":
|
|
_setup_atlas_golden_shot(
|
|
tree_root,
|
|
{
|
|
"body_id": "GJ338Bd",
|
|
"body_radius_km": 6711.0,
|
|
"proper_name": "Arbour",
|
|
"terrain_reference": "wiki/star-systems/GJ-338B/bodies/GJ338Bd/heightmap.png",
|
|
},
|
|
{"system_id": "GJ 338B", "proper_name": "Arbour"},
|
|
"Global",
|
|
["gen_dw_moisture"]
|
|
)
|
|
|
|
"atlas_GJ820Bc_Global":
|
|
_setup_atlas_golden_shot(
|
|
tree_root,
|
|
{
|
|
"body_id": "GJ820Bc",
|
|
"body_radius_km": 6062.0,
|
|
"proper_name": "Ferrath",
|
|
"terrain_reference": "wiki/star-systems/GJ-820B/bodies/GJ820Bc/heightmap.png",
|
|
},
|
|
{"system_id": "GJ 820B", "proper_name": "Cygni B"},
|
|
"Global",
|
|
[]
|
|
)
|
|
|
|
"atlas_GJ820Bc_District":
|
|
_setup_atlas_golden_shot(
|
|
tree_root,
|
|
{
|
|
"body_id": "GJ820Bc",
|
|
"body_radius_km": 6062.0,
|
|
"proper_name": "Ferrath",
|
|
"terrain_reference": "wiki/star-systems/GJ-820B/bodies/GJ820Bc/heightmap.png",
|
|
},
|
|
{"system_id": "GJ 820B", "proper_name": "Cygni B"},
|
|
"District",
|
|
["gen_dw_temp"]
|
|
)
|
|
|
|
# The descent ladder (2026-08-06): the SAME body at the SAME world point,
|
|
# once per rung, so the rungs read as a sequence rather than as unrelated
|
|
# frames. Anchored on land (see _FERRATH_LAND) instead of world-metre
|
|
# ZERO, which is just the origin of the region grid and lands wherever it
|
|
# happens to land.
|
|
#
|
|
# What this ladder is for: whether the NATURE layer stays legible as you
|
|
# descend — relief, coast, watercourses, biome character. It is NOT
|
|
# waiting for cities to appear; nothing civilizational is generated yet
|
|
# and none is due before T-1207. No overlays, deliberately: a colour ramp
|
|
# on top would mask the very thing being judged.
|
|
"atlas_GJ820Bc_land_Region":
|
|
_setup_atlas_golden_shot(
|
|
tree_root, _FERRATH, _CYGNI_B, "Region", [], _FERRATH_LAND
|
|
)
|
|
|
|
"atlas_GJ820Bc_land_District":
|
|
_setup_atlas_golden_shot(
|
|
tree_root, _FERRATH, _CYGNI_B, "District", [], _FERRATH_LAND
|
|
)
|
|
|
|
"atlas_GJ820Bc_land_Quarter":
|
|
_setup_atlas_golden_shot(
|
|
tree_root, _FERRATH, _CYGNI_B, "Quarter", [], _FERRATH_LAND
|
|
)
|
|
|
|
|
|
"atlas_GJ251c_Global":
|
|
_setup_atlas_golden_shot(
|
|
tree_root,
|
|
{
|
|
"body_id": "GJ251c",
|
|
"proper_name": "Ruhr",
|
|
"terrain_reference": "wiki/star-systems/GJ-251/bodies/GJ251c/heightmap.png",
|
|
},
|
|
{"system_id": "GJ 251", "proper_name": "Renaissance"},
|
|
"Global",
|
|
["gen_dw_veg"]
|
|
)
|
|
|
|
"atlas_GJ251c_Region":
|
|
_setup_atlas_golden_shot(
|
|
tree_root,
|
|
{
|
|
"body_id": "GJ251c",
|
|
"proper_name": "Ruhr",
|
|
"terrain_reference": "wiki/star-systems/GJ-251/bodies/GJ251c/heightmap.png",
|
|
},
|
|
{"system_id": "GJ 251", "proper_name": "Renaissance"},
|
|
"Region",
|
|
[]
|
|
)
|
|
|
|
"atlas_GJ244Ad_Global":
|
|
_setup_atlas_golden_shot(
|
|
tree_root,
|
|
{
|
|
"body_id": "GJ244Ad",
|
|
"proper_name": "Edict",
|
|
"terrain_reference": "wiki/star-systems/GJ-244A/bodies/GJ244Ad/heightmap.png",
|
|
},
|
|
{"system_id": "GJ 244A", "proper_name": "Sirius"},
|
|
"Global",
|
|
["gen_dw_temp"]
|
|
)
|
|
|
|
_:
|
|
push_warning("VisualScenarios: unknown scenario '%s'" % scenario_name)
|
|
return false
|
|
|
|
return true
|
|
|
|
|
|
## Post-tick setup — called after N ticks have been advanced.
|
|
## Use for state that depends on tick processing.
|
|
##
|
|
## Currently a no-op: every scenario that needed it was a top-down/fog/dialogue
|
|
## case, deleted 2026-08-06 (Jeroen's call) along with the rest of the legacy
|
|
## suite. The hook stays because visual_capture.gd calls it unconditionally and
|
|
## the stepped-Atlas scenarios may yet need a post-tick step.
|
|
func post_setup(_scenario_name: String, _tree_root: Node) -> void:
|
|
pass
|
|
|
|
|
|
## Apply flow action — called for each step in a movie flow.
|
|
func apply_flow_action(action: String, tree_root: Node) -> void:
|
|
var sim_bridge := tree_root.get_node("/root/SimBridge")
|
|
|
|
match action:
|
|
"wait":
|
|
pass # No-op — just captures current state
|
|
|
|
"select_option_1":
|
|
# Simulate selecting the first dialogue option
|
|
if sim_bridge.harness:
|
|
sim_bridge.harness.process_input("DialogueOption1")
|
|
|
|
_:
|
|
# Movement actions and Interact pass through to TestHarness
|
|
if sim_bridge.harness:
|
|
sim_bridge.harness.process_input(action)
|
|
|
|
|
|
## T-1157 (D-255 rewrite, supersedes the T-1120 continuous-zoom helper):
|
|
## shared setup for the "atlas_<body>_<rung>" golden cases above — opens the
|
|
## Atlas via the SAME production tail AtlasApp._on_body_selected() itself
|
|
## uses (nav.push("regional", {body, system})), then lands on `rung` via
|
|
## StepCanvasViewer's real navigation surface: entering always lands on
|
|
## Global (D-255(a), RegionalScreen.enter() -> StepCanvasViewer.enter()) —
|
|
## for any other rung, jump_to(Vector2.ZERO, rung) is called next, the T-1157
|
|
## harness-inventory "fixed-center revisit" pattern (a literal, always-valid
|
|
## world point — the exact center of every body's own region grid — rather
|
|
## than a cursor-anchored derivation that would depend on viewport size).
|
|
## Every fixed rung's viewport-fit extent is still whatever _request_extent()
|
|
## itself computes from the live viewport (matching production — the goldens
|
|
## are NOT pinning a synthetic extent), only world_center and rung are fixed.
|
|
##
|
|
## Mirrors visual_capture.gd's _run_atlas_matrix() rung/overlay logic (kept
|
|
## independent rather than shared code — visual_capture.gd extends SceneTree
|
|
## and this extends RefCounted, different -s mode load contexts, and the
|
|
## duplication is small and stable: both read the same public StepCanvasViewer
|
|
## surface, jump_to()/get_overlay_defs()/set_overlay_visible()/get_request()).
|
|
## `world_center` defaults to ZERO — the original fixed-center revisit point,
|
|
## which every pre-2026-08-06 golden uses. But world-metre zero is just the
|
|
## origin of the body's region grid, and on a real body that is almost never
|
|
## anywhere interesting: on Ferrath the principal settlement sits at
|
|
## (29 422 009, -5 675 959) m. So every deep-rung golden captured at ZERO was
|
|
## framing an arbitrary patch — which is why Block and Chunk "passed" while
|
|
## showing flat water. Pass a real coordinate (aliveness_probe prints the
|
|
## principal settlement's world metres) to descend somewhere that has content.
|
|
func _setup_atlas_golden_shot(
|
|
tree_root: Node,
|
|
body: Dictionary,
|
|
system: Dictionary,
|
|
rung: String,
|
|
overlay_ids: Array,
|
|
world_center: Vector2 = Vector2.ZERO
|
|
) -> void:
|
|
var hud_groups: Node = tree_root.get_node("/root/HudGroups")
|
|
var registry: Node = tree_root.get_node("/root/ImplantRegistry")
|
|
hud_groups.open_app("implant/map")
|
|
var app: Variant = registry.get_app_instance("implant/map")
|
|
if app == null:
|
|
push_warning("VisualScenarios: atlas app not instantiated")
|
|
return
|
|
app.nav.push("regional", {"body": body, "system": system})
|
|
var viewer: Variant = app._regional_screen._viewer
|
|
if viewer == null:
|
|
push_warning("VisualScenarios: regional screen has no viewer")
|
|
return
|
|
|
|
for def: Dictionary in viewer.get_overlay_defs():
|
|
var overlay_id: String = str(def.get("id", ""))
|
|
if str(def.get("group", "")) == "toggle":
|
|
viewer.set_overlay_visible(overlay_id, overlay_ids.has(overlay_id))
|
|
for overlay_id: String in overlay_ids:
|
|
viewer.set_overlay_visible(overlay_id, true)
|
|
|
|
if rung != "Global":
|
|
# enter() (called via nav.push above) always lands on Global first —
|
|
# jump_to() is the fixed-center revisit intent that descends to any
|
|
# other rung at a literal, reproducible world_center (D-255(a): every
|
|
# body's region grid is centered on world-metre ZERO).
|
|
viewer.jump_to(world_center, rung)
|