refactor(simulation): harden #952 cascade per QA + architecture review
Addresses the Hoshe (QA) + Tyre (architecture) review of the SeedChain/cascade work: - Golden was pinning an empty river network (128x64 produced 0 river cells). Bumped to 256x128, where GJ1c yields a real network (93 river cells, 19 mouths) — Layer 1's rivers are now actually guarded, not just attractors. - SeedChain::for_body(world_seed, body_id) + fnv1a_64: the single canonical body_id(String) -> u64 path (FNV-1a, the repo convention), so callers can't derive divergent worlds from the same seed via different ad-hoc hashes. The golden now uses it. - Stability guards: seed_domain_discriminants_are_pinned test (CI fails if a SeedDomain tag is renumbered); AttractorType gains #[repr(u8)] + explicit discriminants (it's cast as a sort key in features.rs). - Tests: SeedChain::root(0) non-degenerate; run_cascade error path (missing file -> Err, not panic). - Comments: clarified the id=0 derivations (sibling separation is caller-side via the per-district/quarter chain; #957 threads the index), tightened the all_district_types reachability comment (it pins the seed-0 sequence, not a probabilistic claim), and noted the golden's WORLD_SEED is cosmetic at Layers 0-1 + the x86_64 f32 capture caveat. Deferred with reason: the run_cascade -> CascadeInputs struct refactor (Tyre) is left for #954 — designing Layer-2's context shape now would be later-phase detail, and there's a single caller to migrate then. EntityRng keeps its domainless combine (migrating is stream-changing) — noted in D-224. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -14,22 +14,27 @@
|
||||
//!
|
||||
//! Regenerate after an intended change:
|
||||
//! UPDATE_GOLDEN=1 cargo test --test cascade_golden
|
||||
//!
|
||||
//! Golden captured on x86_64. The downsample and sub-biome cost use f32, so a
|
||||
//! different architecture could in principle round differently — regenerate
|
||||
//! per-arch if CI ever moves off x86_64.
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use serde_json::{json, Value};
|
||||
use settled_reach_server::atlas::cascade::{run_cascade_from_heightmap, CascadeLayer};
|
||||
use settled_reach_server::atlas::heightmap::load_heightmap_png;
|
||||
use settled_reach_server::seed::{SeedChain, SeedDomain};
|
||||
use settled_reach_server::seed::SeedChain;
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
/// Source heightmap — a real committed body, relative to the server manifest dir.
|
||||
const SOURCE_HEIGHTMAP: &str = "../wiki/star-systems/GJ-1/bodies/GJ1c/heightmap.png";
|
||||
/// Downsample target: small enough for a compact golden, large enough for real
|
||||
/// drainage/feature structure.
|
||||
const DOWNSAMPLE: (u32, u32) = (128, 64);
|
||||
/// World seed for the run. Layers 0–1 are RNG-free; this is carried for the
|
||||
/// SeedChain contract (D-224).
|
||||
/// Downsample target: large enough that GJ1c's drainage produces a real river
|
||||
/// network (not just attractors), small enough for a compact golden.
|
||||
const DOWNSAMPLE: (u32, u32) = (256, 128);
|
||||
/// World seed for the run. Cosmetic here — Layers 0–1 are RNG-free, so changing
|
||||
/// it does not change the golden; it is carried only to exercise the SeedChain
|
||||
/// contract end-to-end (D-224). Seed-sensitivity gets pinned once Layer 3+ lands.
|
||||
const WORLD_SEED: u64 = 42;
|
||||
const GOLDEN: &str = "tests/golden/cascade_layer1.json";
|
||||
|
||||
@@ -49,7 +54,7 @@ fn cascade_layer0_to_1_matches_golden() {
|
||||
|
||||
// ── Layer 1 — downsample, then run the cascade to topography. ───────────
|
||||
let small = heightmap.downsample(DOWNSAMPLE.0, DOWNSAMPLE.1);
|
||||
let body_seed = SeedChain::root(WORLD_SEED).derive(SeedDomain::Body, 1);
|
||||
let body_seed = SeedChain::for_body(WORLD_SEED, "GJ1c");
|
||||
let snapshot = run_cascade_from_heightmap(body_seed, small, CascadeLayer::Topography);
|
||||
let layer1 = snapshot.layer1.expect("Layer 1 ran");
|
||||
|
||||
|
||||
+5826
-4004
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user