Files
settled-reach/tooling/planet-gen/test_sim_determinism.py
T
jpmschweitzerandClaude Opus 4.7 dd296b1ae5 test: review-driven determinism + coverage (#953 #963)
From the Hoshe/Tyre review:
- drainage: assert flow_accumulation/max_accumulation determinism + clamp ≥ 1
  (the D-209 strength denominator); isolated-basin merge path (no panic).
- subbiome: each derivable variant reachable + Volcanic never emitted.
- planet_simulation: new test_sim_determinism.py — same body simulates to a
  bit-identical elevation array at 1024×512 (the 271-body bake can't be cheaply
  re-run, so a silent drift = full re-bake). Verified PASS.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 08:09:26 +02:00

72 lines
2.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""Determinism guard for planet_simulation.simulate() (#963).
The 1024×512 elevation bump (D-202 amended) claims to be deterministic — the
271-body heightmap bake cannot be re-run cheaply, so a silent non-determinism
means a full regeneration. This asserts that simulating the same body twice
yields a bit-identical elevation array.
Run: uv run python tooling/planet-gen/test_sim_determinism.py
Exit: 0 = deterministic, 1 = drift detected, 2 = could not find a test body.
"""
import hashlib
import sqlite3
import sys
from pathlib import Path
REPO = Path(__file__).resolve().parent.parent.parent
sys.path.insert(0, str(REPO / "tooling" / "planet-gen"))
import numpy as np # noqa: E402
from body_definition_parser import parse_system # noqa: E402
from planet_simulation import GRID_H, GRID_W, simulate # noqa: E402
def _elev_hash(terrain) -> str:
arr = np.ascontiguousarray(terrain["elevation"], dtype=np.float32)
return hashlib.sha256(arr.tobytes()).hexdigest()
def main() -> int:
conn = sqlite3.connect(str(REPO / "server" / "data" / "systems.db"))
rows = conn.execute(
"SELECT body_id, terrain_reference FROM bodies "
"WHERE inhabited=1 AND terrain_reference IS NOT NULL AND population>0 "
"AND system_id != 'GJ 0' ORDER BY body_id LIMIT 30"
).fetchall()
checked = 0
for body_id, tref in rows:
if checked >= 3:
break
sys_index = tref.split("/bodies/")[0] + "/index.md"
try:
defs = parse_system(sys_index)
except Exception:
continue
bd = next((d for d in defs if d.get("id") == body_id), None)
if bd is None:
continue
t1 = simulate(bd)
t2 = simulate(bd)
if not t1 or "elevation" not in t1:
continue
h1, h2 = _elev_hash(t1), _elev_hash(t2)
ok = h1 == h2 and t1["elevation"].shape == (GRID_H, GRID_W)
print(f" {body_id}: {'OK' if ok else 'DRIFT'} {h1[:16]} shape={t1['elevation'].shape}")
if not ok:
print(f"FAIL: {body_id} elevation is non-deterministic ({h1[:16]} != {h2[:16]})")
return 1
checked += 1
if checked == 0:
print("SKIP: no testable body found")
return 2
print(f"PASS: {checked} bodies simulate deterministically at {GRID_W}×{GRID_H}")
return 0
if __name__ == "__main__":
sys.exit(main())