Core.Lattice.PrimitiveField v1, opt-in per strate (legacy Maze/VerticalShaft stay legacy): resolves the real arrival and departure mouths first, plans a mandatory spine, then maze cells and two dead ends (9 rooms, 9 edges, stable IDs). The spine descends 20 m through four helix turns (6 m radius, 3 m clear width, 5 m pitch, 2.6 m clearance; max grade 10.0 deg); each feature is one filleted void (0.57 m measured). Final-field reachability passes at 883 stations; an orphaned shaft control is rejected; exact intervals (0 misses) and a whole-surface audit with 0 flags. Whole view 1.69 s (above the 1 s target). fast/medium/full PASS. Research R27 (self-checked): static stream-to-pool water design. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
84 lines
3.8 KiB
Python
84 lines
3.8 KiB
Python
#!/usr/bin/env python3
|
|
"""Split the owner surface strate around a small, opt-in native maze strate."""
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
from pathlib import Path
|
|
|
|
|
|
def sha256(path: Path) -> str:
|
|
digest = hashlib.sha256()
|
|
with path.open("rb") as stream:
|
|
for block in iter(lambda: stream.read(1024 * 1024), b""):
|
|
digest.update(block)
|
|
return digest.hexdigest()
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--owner", type=Path, required=True)
|
|
parser.add_argument("--out", type=Path, required=True)
|
|
args = parser.parse_args()
|
|
|
|
root = json.loads(args.owner.read_text(encoding="utf-8"))
|
|
strates = root.get("strates")
|
|
if not isinstance(strates, list):
|
|
raise ValueError("owner input has no strates array")
|
|
by_index = {int(row.get("index", -1)): row for row in strates if isinstance(row, dict)}
|
|
if set(by_index) != {0, 1} or len(strates) != 2:
|
|
raise ValueError("fixture requires the reviewed two-strate owner input")
|
|
upper, surface = by_index[0], by_index[1]
|
|
if (int(upper.get("asset", {}).get("GeneratorType", -1)) != 0
|
|
or int(surface.get("asset", {}).get("GeneratorType", -1)) != 4):
|
|
raise ValueError("fixture requires TunnelNetwork over SurfaceWorld")
|
|
if int(upper.get("passage_config", {}).get("Connections", -1)) != 1:
|
|
raise ValueError("owner arrival passage count differs from the reviewed input")
|
|
|
|
# Keep both resolved mouths in the small synthetic Maze layer. The authored
|
|
# owner reach ranges are intentionally broad and can place a synthetic mouth
|
|
# hundreds of metres beyond a four-chunk prototype layer.
|
|
upper["passage_config"].update({"ReachMin": 32, "ReachMax": 32})
|
|
upper["asset"]["PassageConfig"].update({"ReachMin": 32, "ReachMax": 32})
|
|
|
|
maze = json.loads(json.dumps(surface))
|
|
maze.update({"index": 1, "top_chunk_z": -16, "bottom_chunk_z": -19,
|
|
"height_chunks": 4})
|
|
maze["asset"].update({"StrateName": "L58 Native Lattice Maze",
|
|
"GeneratorType": 3, "StrateHeightInChunks": 4})
|
|
maze["asset"].setdefault("MazeParams", {})["BoundarySealThickness"] = 8
|
|
maze["passage_config"]["Connections"] = 1
|
|
maze["passage_config"].update({"ReachMin": 32, "ReachMax": 32})
|
|
maze["asset"]["PassageConfig"].update({"Connections": 1, "ReachMin": 32, "ReachMax": 32})
|
|
|
|
lower = json.loads(json.dumps(surface))
|
|
lower.update({"index": 2, "top_chunk_z": -20, "bottom_chunk_z": -23,
|
|
"height_chunks": 4})
|
|
lower["asset"].update({"StrateName": "L58 Lower Surface", "GeneratorType": 4,
|
|
"StrateHeightInChunks": 4})
|
|
lower["passage_config"]["Connections"] = 1
|
|
lower["asset"]["PassageConfig"]["Connections"] = 1
|
|
|
|
root["total_strates"] = 3
|
|
root["strates"] = [upper, maze, lower]
|
|
# Keep the legacy passage portals proportional to this compact native
|
|
# prototype; the owner world remains at its authored scale.
|
|
root.update({"owner_voxel_size_cm": 6.25,
|
|
"owner_voxel_size_microns": 62500,
|
|
"core_voxel_size_cm": 25,
|
|
"core_voxel_size_microns": 250000,
|
|
"owner_to_core_length_scale": 0.25})
|
|
args.out.parent.mkdir(parents=True, exist_ok=True)
|
|
args.out.write_text(json.dumps(root, indent=2, sort_keys=True) + "\n",
|
|
encoding="utf-8")
|
|
print(f"[LatticeFixtureBuild] source={args.owner} source_sha256={sha256(args.owner)} "
|
|
f"fixture={args.out} fixture_sha256={sha256(args.out)} "
|
|
"strates=0:TunnelNetwork,1:Maze[4 chunks],2:SurfaceWorld[60 chunks] "
|
|
"owner_input_untouched=true status=PASS")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|