fix(simulation): one shared invent_coastal_position — PR #208 review round (T-1160)
Hoshe found the concrete residual: the hand-copied driver block called derive_temperature_c unconditionally where invent_primitives prefers the lapse-adjusted region baseline on non-airless bodies — driver_temp feeds glaciation/moisture into the warp magnitude, so orbital displacement could still differ from District at the same position (the ticket's defect class, one step upstream); the copy structurally couldn't branch right because region_baseline_at_district was computed after it. Tyre demanded the structural cure: steps 1-3 now live in ONE shared helper (invent_coastal_position -> warped position + CoastCharacter); invent_primitives composes helper + detail-scatter; the orbital path hoists the baseline and makes a single helper call. The audit test's own 'District-style' side turned out to be a THIRD copy carrying the same bug — rewired to the real helper (raw pre-fix side untouched as the historical baseline; refreshed: 5.01% disagreement, mean 5,957.9 m, 748.9 ns/cell). Golden verified byte-identical under forced regen, with the reason traced: the wire temperature never flowed through the buggy internal branch, and the fixture's probe positions cross no discrete boundary — the 267-body audit is the instrument that sees the drift. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1148,10 +1148,14 @@ struct InventedPrimitives {
|
||||
ocean_fraction_q: i32,
|
||||
}
|
||||
|
||||
/// Compose the invented district primitives at one position — the shared front
|
||||
/// half of BOTH derivation paths ([`derive_district`] on-demand and
|
||||
/// [`derive_district_profile`] batch), so the D-227 invention can never diverge
|
||||
/// between them again (the pre-T-1125 failure: the batch path was scatter-free).
|
||||
/// Compose steps 1-3 of the invented-coastline pipeline — the driver-tier
|
||||
/// climate estimate, the body/position coast character, and the warped
|
||||
/// sampling position those two produce. **The single shared implementation**
|
||||
/// (T-1160 PR #208 review, hoshe + tyre): every caller that needs the
|
||||
/// invented coastline's WARPED POSITION (never a second hand-synced copy of
|
||||
/// this branch) goes through here — [`invent_primitives`] (steps 1-3, then
|
||||
/// composes step 4 on top) and [`derive_orbital_at_metres`] (steps 1-3 only,
|
||||
/// no step 4).
|
||||
///
|
||||
/// Steps:
|
||||
/// 1. **Driver tier (one-step-stale, T-1125 circularity ruling):** the raw
|
||||
@@ -1160,23 +1164,43 @@ struct InventedPrimitives {
|
||||
/// these stale drivers; it never reads the warped values it produces. The
|
||||
/// raw inputs are the coarse ~40–160 km/pixel envelope anyway, so one step
|
||||
/// of staleness is far below the signal's own resolution.
|
||||
///
|
||||
/// **Region-baseline branch (T-1160 PR #208 fix):** `driver_temp` prefers
|
||||
/// the lapse-adjusted [`derive_district_temperature_c`] whenever
|
||||
/// `region_baseline_c` is `Some` — the SAME branch [`derive_district_profile`]'s
|
||||
/// batch path and [`derive_at_metres`]'s on-demand path have always used —
|
||||
/// falling back to the body-level [`derive_temperature_c`] only for airless
|
||||
/// bodies (`region_baseline_c: None`, no region climate to lapse-adjust).
|
||||
/// Before this fix, a hand-copied version of this block inside
|
||||
/// `derive_orbital_at_metres` called `derive_temperature_c`
|
||||
/// UNCONDITIONALLY — wrong on every non-airless body (the entire coastline
|
||||
/// population), silently producing a different `driver_temp` →
|
||||
/// `driver_moisture` → `driver_glaciation` (a discrete band) →
|
||||
/// `coast_character_at` → warp displacement than District/Quarter at the
|
||||
/// identical position, reintroducing the exact T-1160 defect class one
|
||||
/// step upstream of the fix that closed it for the sampling position
|
||||
/// itself.
|
||||
/// 2. **Character:** tier-1 body envelope ([`coast_invention::body_coast_envelope`];
|
||||
/// `derive_tectonic_class` hoisted here — it needs only `BodyParams`) +
|
||||
/// tier-2 position character ([`coast_invention::coast_character_at`]).
|
||||
/// 3. **Invented coastline:** every envelope field (elevation, slope, ocean
|
||||
/// mask) is sampled at the SAME warped position, so terrain moves coherently
|
||||
/// — a warped-in bay carries its sea-level elevation with it.
|
||||
/// 4. **Slope-independent scatter:** the character's `scatter_floor` breaks the
|
||||
/// old amplitude-slaved-to-coarse-slope collapse (invention ≈ 0 exactly on
|
||||
/// low-relief coasts); `ridge` carries fjord/tectonic sharpness.
|
||||
/// 3. **Invented coastline:** the warped `(spx, spy)` position — every
|
||||
/// envelope field (elevation, slope, ocean mask) a caller samples at this
|
||||
/// position moves coherently — a warped-in bay carries its sea-level
|
||||
/// elevation with it.
|
||||
///
|
||||
/// `body_params` must already carry the district's `latitude_deg`.
|
||||
///
|
||||
/// `min_wavelength_m` (T-1149, zoom ladder §2): threaded straight to the
|
||||
/// `terrain_detail` scatter call — octaves finer than this are truncated.
|
||||
/// `0.0` = no cutoff = today's behavior.
|
||||
/// coast-warp call — octaves finer than this are truncated. `0.0` = no
|
||||
/// cutoff = today's behavior.
|
||||
///
|
||||
/// Returns `(spx, spy, ch)`: the warped position, plus the resolved
|
||||
/// [`coast_invention::CoastCharacter`] — [`invent_primitives`]' step 4
|
||||
/// (slope-independent scatter) reads `ch.scatter_floor`/`ch.ridge`, so the
|
||||
/// character has to come back out rather than be recomputed a second time.
|
||||
/// [`derive_orbital_at_metres`] (steps 1-3 only) uses just the position.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn invent_primitives(
|
||||
fn invent_coastal_position(
|
||||
seed: SeedChain,
|
||||
body_params: &BodyParams,
|
||||
climate: &ClimateConstants,
|
||||
@@ -1187,7 +1211,7 @@ fn invent_primitives(
|
||||
world_y_m: f64,
|
||||
region_baseline_c: Option<f32>,
|
||||
min_wavelength_m: f64,
|
||||
) -> InventedPrimitives {
|
||||
) -> (f64, f64, coast_invention::CoastCharacter) {
|
||||
// ── 1. Driver tier: UNWARPED raw-bilinear climate (one-step-stale). ─────
|
||||
let raw_elev_q =
|
||||
((bilinear(&ta.elev_pct, ta.w, ta.h, px, py) as f64 * 100.0).round() as i32).clamp(0, 100);
|
||||
@@ -1220,11 +1244,58 @@ fn invent_primitives(
|
||||
|
||||
// ── 3. Invented coastline: warp the whole envelope sampling. ────────────
|
||||
// T-1162: the coast warp gets the SAME min_wavelength_m cutoff as the
|
||||
// terrain-detail scatter below — one rung, one cutoff, applied to both
|
||||
// continuous fields that compose the invented coastline.
|
||||
// terrain-detail scatter (invent_primitives' step 4) — one rung, one
|
||||
// cutoff, applied to both continuous fields that compose the invented
|
||||
// coastline.
|
||||
let (wdx, wdy) =
|
||||
coast_invention::coast_warp_px(seed.seed(), world_x_m, world_y_m, &ch, min_wavelength_m);
|
||||
let (spx, spy) = (px + wdx, py + wdy);
|
||||
(px + wdx, py + wdy, ch)
|
||||
}
|
||||
|
||||
/// Compose the invented district primitives at one position — the shared front
|
||||
/// half of BOTH derivation paths ([`derive_district`] on-demand and
|
||||
/// [`derive_district_profile`] batch), so the D-227 invention can never diverge
|
||||
/// between them again (the pre-T-1125 failure: the batch path was scatter-free).
|
||||
///
|
||||
/// Steps 1-3 (driver tier, character, invented warped position) are
|
||||
/// [`invent_coastal_position`] — this function calls it, samples the
|
||||
/// envelope at the returned position, then composes step 4 (slope-independent
|
||||
/// scatter) on top:
|
||||
/// 4. **Slope-independent scatter:** the character's `scatter_floor` breaks the
|
||||
/// old amplitude-slaved-to-coarse-slope collapse (invention ≈ 0 exactly on
|
||||
/// low-relief coasts); `ridge` carries fjord/tectonic sharpness.
|
||||
///
|
||||
/// `body_params` must already carry the district's `latitude_deg`.
|
||||
///
|
||||
/// `min_wavelength_m` (T-1149, zoom ladder §2): threaded straight to the
|
||||
/// `terrain_detail` scatter call — octaves finer than this are truncated.
|
||||
/// `0.0` = no cutoff = today's behavior.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn invent_primitives(
|
||||
seed: SeedChain,
|
||||
body_params: &BodyParams,
|
||||
climate: &ClimateConstants,
|
||||
ta: &TerrainAnalysis,
|
||||
px: f64,
|
||||
py: f64,
|
||||
world_x_m: f64,
|
||||
world_y_m: f64,
|
||||
region_baseline_c: Option<f32>,
|
||||
min_wavelength_m: f64,
|
||||
) -> InventedPrimitives {
|
||||
// ── Steps 1-3: driver tier, character, invented warped position. ────────
|
||||
let (spx, spy, ch) = invent_coastal_position(
|
||||
seed,
|
||||
body_params,
|
||||
climate,
|
||||
ta,
|
||||
px,
|
||||
py,
|
||||
world_x_m,
|
||||
world_y_m,
|
||||
region_baseline_c,
|
||||
min_wavelength_m,
|
||||
);
|
||||
let elev_pct = bilinear(&ta.elev_pct, ta.w, ta.h, spx, spy) as f64;
|
||||
let slope_deg = bilinear(&ta.slope_deg, ta.w, ta.h, spx, spy) as f64;
|
||||
let ocean_frac = bilinear_bool(&ta.ocean_mask, ta.w, ta.h, spx, spy) as f64;
|
||||
@@ -1931,12 +2002,16 @@ fn derive_at_metres_with_riparian(
|
||||
/// coarse-granularity twin of [`derive_at_metres`] that skips MOST of
|
||||
/// [`invent_primitives`] — **no detail-scatter octave sum, no classification
|
||||
/// noise call of any kind** — but DOES apply the coast-warp position shift
|
||||
/// (T-1160). Per the design doc's orbital row: "`region_baseline_at_district`
|
||||
/// only — bilinear blend of 4 region baselines, no [detail-scatter]
|
||||
/// invention, no classification [driver]." Orbital sample spacing (≥205 km,
|
||||
/// D-243's region rung and coarser) sits below `detail_scatter`'s own octave
|
||||
/// floor (`OCTAVE_WAVELENGTHS_M`'s coarsest entry is 32,768 m ≈ 32.8 km — an
|
||||
/// order of magnitude finer than a region), so the invented RELIEF texture has
|
||||
/// (T-1160) via [`invent_coastal_position`], the SAME shared steps 1-3
|
||||
/// helper [`invent_primitives`] composes on top of (never a hand-copied
|
||||
/// replica of that logic — see the helper's own doc for why that class of
|
||||
/// bug is now structurally closed, not just fixed once). Per the design
|
||||
/// doc's orbital row: "`region_baseline_at_district` only — bilinear blend
|
||||
/// of 4 region baselines, no [detail-scatter] invention, no classification
|
||||
/// [driver]." Orbital sample spacing (≥205 km, D-243's region rung and
|
||||
/// coarser) sits below `detail_scatter`'s own octave floor
|
||||
/// (`OCTAVE_WAVELENGTHS_M`'s coarsest entry is 32,768 m ≈ 32.8 km — an order
|
||||
/// of magnitude finer than a region), so the invented RELIEF texture has
|
||||
/// nothing left to contribute at this spacing; running it would burn cycles
|
||||
/// synthesizing detail no orbital pixel can resolve. The coastline WARP is
|
||||
/// different: `WARP_OCTAVE_WAVELENGTHS_M`'s coarsest entries run up to 262,144 m
|
||||
@@ -1951,20 +2026,30 @@ fn derive_at_metres_with_riparian(
|
||||
/// position**, plus the **region climate baseline** — this function samples
|
||||
/// exactly those, nothing else.
|
||||
///
|
||||
/// **Ordering (T-1160 PR #208 fix):** `region_baseline_at_district` is
|
||||
/// called BEFORE [`invent_coastal_position`], not after — the helper's
|
||||
/// driver-tier branch (step 1) needs the resolved baseline to pick the SAME
|
||||
/// region-baseline-preferring formula `invent_primitives`/`derive_at_metres`
|
||||
/// use. A structurally-forced-wrong hand-copy of the driver tier (computed
|
||||
/// before the baseline existed in scope) is exactly the bug PR #208 review
|
||||
/// caught: it could not branch correctly no matter how carefully it was
|
||||
/// hand-synced, because the value it needed to branch on didn't exist yet.
|
||||
///
|
||||
/// **Cost model (T-1160 audit, measured on 267 real bodies, release build):**
|
||||
/// the added driver-tier climate + `coast_character_at` + `coast_warp_px` work
|
||||
/// costs ~784 ns/cell (`coast_warp_px` alone: ~528 ns/cell) — roughly half of
|
||||
/// what `invent_primitives`' FULL pipeline costs on top of this function's own
|
||||
/// ~903 ns/cell baseline (`bench_derive_orbital_at_metres_region_spacing`:
|
||||
/// orbital 902.6 ns/cell vs. full `derive_at_metres` 1940.6 ns/cell at the same
|
||||
/// spacing — a 2.15x gap, of which detail-scatter/classification-noise is the
|
||||
/// remainder this function still skips). At the D-255(a) fixed-rung ceiling
|
||||
/// (3,840×2,160 = 8.3M cells) the added cost is ~6.5 s single-threaded / low
|
||||
/// hundreds of ms on the row-chunked parallel serving path (T-1151); at a
|
||||
/// realistic Global-rung Earth-sized-body canvas (195×97 ≈ 18.9K cells) it is
|
||||
/// ~15 ms. Accepted: coastline correctness at the orbital/Region seam is worth
|
||||
/// a sub-millisecond-to-low-second cost that scales with (and is bounded by)
|
||||
/// the same canvas-size ceiling every other rung's cost already respects.
|
||||
/// (now inside [`invent_coastal_position`]) costs ~784 ns/cell (`coast_warp_px`
|
||||
/// alone: ~528 ns/cell) — roughly half of what `invent_primitives`' FULL
|
||||
/// pipeline costs on top of this function's own ~903 ns/cell baseline
|
||||
/// (`bench_derive_orbital_at_metres_region_spacing`: orbital 902.6 ns/cell vs.
|
||||
/// full `derive_at_metres` 1940.6 ns/cell at the same spacing — a 2.15x gap, of
|
||||
/// which detail-scatter/classification-noise is the remainder this function
|
||||
/// still skips). At the D-255(a) fixed-rung ceiling (3,840×2,160 = 8.3M cells)
|
||||
/// the added cost is ~6.5 s single-threaded / low hundreds of ms on the
|
||||
/// row-chunked parallel serving path (T-1151); at a realistic Global-rung
|
||||
/// Earth-sized-body canvas (195×97 ≈ 18.9K cells) it is ~15 ms. Accepted:
|
||||
/// coastline correctness at the orbital/Region seam is worth a
|
||||
/// sub-millisecond-to-low-second cost that scales with (and is bounded by) the
|
||||
/// same canvas-size ceiling every other rung's cost already respects.
|
||||
///
|
||||
/// Produces the SAME six-field tail every other rung produces (`morphology_zone`,
|
||||
/// `elev_q`, `temperature_c`, `moisture_q`, `vegetation_class`, `glaciation_grade`)
|
||||
@@ -2028,61 +2113,14 @@ pub fn derive_orbital_at_metres(
|
||||
..body_params.clone()
|
||||
};
|
||||
|
||||
// T-1160: coast-warp the sampling POSITION (steps 1-3 of
|
||||
// `invent_primitives`), but skip step 4 (slope-independent detail-scatter)
|
||||
// — the envelope carries no per-cell slope signal at orbital spacing (see
|
||||
// the function doc's note on `slope_q`, unchanged). Before this fix, this
|
||||
// function sampled `ta.elev_pct`/`ta.ocean_mask` RAW while District/Quarter
|
||||
// sampled the SAME arrays at the coast-warped position — a structurally
|
||||
// different coastline at the orbital-to-district seam (audit: 5.0%
|
||||
// land/ocean classification disagreement at coastal-band cells across 267
|
||||
// real bodies, mean displacement ~6.0 km / max ~18.9 km at region
|
||||
// spacing). Applying the warp here makes the orbital rung sample the SAME
|
||||
// invented coastline every finer rung already draws — coarser density,
|
||||
// same line, not a different line (T-1160).
|
||||
//
|
||||
// Driver tier: raw-bilinear reads feed the coast character exactly as
|
||||
// `invent_primitives` step 1 does (one-step-stale climate driving the
|
||||
// coast personality, never circular on its own warped output).
|
||||
let raw_elev_q =
|
||||
((bilinear(&ta.elev_pct, ta.w, ta.h, px, py) as f64 * 100.0).round() as i32).clamp(0, 100);
|
||||
let raw_ocean_q = ((bilinear_bool(&ta.ocean_mask, ta.w, ta.h, px, py) as f64 * 100.0).round()
|
||||
as i32)
|
||||
.clamp(0, 100);
|
||||
let driver_params = BodyParams {
|
||||
elevation_km: (raw_elev_q as f64 / 100.0) * MAX_REGION_ELEVATION_KM,
|
||||
..params.clone()
|
||||
};
|
||||
let driver_temp = derive_temperature_c(&driver_params, climate, seed.seed());
|
||||
let driver_moisture = derive_moisture_q(&driver_params, raw_elev_q, raw_ocean_q, climate);
|
||||
let driver_glaciation = derive_glaciation_grade_from_climate(driver_temp, driver_moisture);
|
||||
|
||||
// Character + invented coastline (steps 2-3): same body-personality
|
||||
// envelope + position character + warp displacement District/Quarter use,
|
||||
// applied to the SAME `(px, py)` this function already resolved.
|
||||
let tectonic = derive_tectonic_class(body_params);
|
||||
let envelope = coast_invention::body_coast_envelope(body_params, tectonic);
|
||||
let ch = coast_invention::coast_character_at(
|
||||
&envelope,
|
||||
seed.seed(),
|
||||
world_x_m,
|
||||
world_y_m,
|
||||
lat_deg,
|
||||
driver_glaciation,
|
||||
driver_moisture,
|
||||
);
|
||||
let (wdx, wdy) = coast_invention::coast_warp_px(seed.seed(), world_x_m, world_y_m, &ch, 0.0);
|
||||
let (spx, spy) = (px + wdx, py + wdy);
|
||||
|
||||
let elev_q = ((bilinear(&ta.elev_pct, ta.w, ta.h, spx, spy) as f64 * 100.0).round() as i32)
|
||||
.clamp(0, 100);
|
||||
let ocean_fraction_q = ((bilinear_bool(&ta.ocean_mask, ta.w, ta.h, spx, spy) as f64 * 100.0)
|
||||
.round() as i32)
|
||||
.clamp(0, 100);
|
||||
// No invented ruggedness at orbital spacing (see the function doc's note
|
||||
// on slope_q) — the envelope carries no per-cell slope signal this coarse.
|
||||
let slope_q = 0;
|
||||
|
||||
// T-1160 PR #208 fix: `region_baseline_at_district` is hoisted ABOVE the
|
||||
// coastal-position work below — the shared helper's driver tier (step 1)
|
||||
// needs it to pick the SAME region-baseline-preferring branch
|
||||
// `invent_primitives`/`derive_at_metres` use. The pre-fix structure
|
||||
// computed this AFTER a hand-copied driver-tier block, which is exactly
|
||||
// why that copy could not branch correctly and silently called the
|
||||
// airless-only `derive_temperature_c` unconditionally (see
|
||||
// `invent_coastal_position`'s doc for the full defect story).
|
||||
let district_pos: DistrictPos = (
|
||||
(wx / scale::DISTRICT_M as f64).floor() as i32,
|
||||
(wy / scale::DISTRICT_M as f64).floor() as i32,
|
||||
@@ -2097,6 +2135,41 @@ pub fn derive_orbital_at_metres(
|
||||
None, // no pre-built cache; derive on-the-fly, same posture as derive_at_metres
|
||||
);
|
||||
|
||||
// T-1160: coast-warp the sampling POSITION via the SAME shared helper
|
||||
// (`invent_coastal_position`, steps 1-3 of `invent_primitives`) District/
|
||||
// Quarter use — step 4 (slope-independent detail-scatter) is skipped
|
||||
// (the envelope carries no per-cell slope signal at orbital spacing, see
|
||||
// the function doc's note on `slope_q`). Before T-1160, this function
|
||||
// sampled `ta.elev_pct`/`ta.ocean_mask` RAW while District/Quarter
|
||||
// sampled the SAME arrays at the coast-warped position — a structurally
|
||||
// different coastline at the orbital-to-district seam (audit: 5.0%
|
||||
// land/ocean classification disagreement at coastal-band cells across 267
|
||||
// real bodies, mean displacement ~6.0 km / max ~18.9 km at region
|
||||
// spacing). Routing through the ONE shared helper (rather than a
|
||||
// hand-copied replica) makes the region-baseline branch structurally
|
||||
// impossible to diverge again.
|
||||
let (spx, spy, _ch) = invent_coastal_position(
|
||||
seed,
|
||||
¶ms,
|
||||
climate,
|
||||
ta,
|
||||
px,
|
||||
py,
|
||||
world_x_m,
|
||||
world_y_m,
|
||||
region_baseline_c,
|
||||
0.0,
|
||||
);
|
||||
|
||||
let elev_q = ((bilinear(&ta.elev_pct, ta.w, ta.h, spx, spy) as f64 * 100.0).round() as i32)
|
||||
.clamp(0, 100);
|
||||
let ocean_fraction_q = ((bilinear_bool(&ta.ocean_mask, ta.w, ta.h, spx, spy) as f64 * 100.0)
|
||||
.round() as i32)
|
||||
.clamp(0, 100);
|
||||
// No invented ruggedness at orbital spacing (see the function doc's note
|
||||
// on slope_q) — the envelope carries no per-cell slope signal this coarse.
|
||||
let slope_q = 0;
|
||||
|
||||
// T-1184: same continuous filled-surface comparison every rung samples,
|
||||
// at the orbital rung's own (px, py) — lake edges refine at Region
|
||||
// spacing exactly as they do at every finer rung (D-227 amendment (4)).
|
||||
@@ -3572,19 +3645,34 @@ mod tests {
|
||||
/// orbital-vs-district coastline positional divergence that existed
|
||||
/// BEFORE this ticket: `derive_orbital_at_metres` used to sample
|
||||
/// `ta.ocean_mask` raw (no `coast_warp_px`) while District/Quarter warped
|
||||
/// the same mask first (`invent_primitives` step 3). This test
|
||||
/// independently reimplements both the pre-fix raw read (a) and the
|
||||
/// District-style warped read (b) — deliberately NOT calling
|
||||
/// `derive_orbital_at_metres` itself, so the measurement stays valid as a
|
||||
/// historical baseline regardless of that function's current
|
||||
/// implementation — loads every real `heightmap.png` under
|
||||
/// `wiki/star-systems/`, and for a grid of region-spacing sample points on
|
||||
/// each body reports how often (a) and (b) disagree on land/ocean
|
||||
/// classification, the warp displacement converted to real metres, and
|
||||
/// the per-cell cost of computing (b). These are the numbers T-1160's
|
||||
/// fix (applying the warp at orbital sampling, see
|
||||
/// `derive_orbital_at_metres`'s doc) is based on. `#[ignore]`d — reads
|
||||
/// ~267 real wiki heightmap files, run explicitly:
|
||||
/// the same mask first (`invent_primitives` step 3).
|
||||
///
|
||||
/// Side (a), the pre-fix raw read, deliberately stays a hand-rolled
|
||||
/// historical baseline (NOT a call into current production code) — it
|
||||
/// exists to measure what the BUG used to do, so it must not silently
|
||||
/// track whatever `derive_orbital_at_metres` does today.
|
||||
///
|
||||
/// Side (b), the "District-style warped read," calls the REAL production
|
||||
/// [`region_baseline_at_district`] + [`invent_coastal_position`] (PR #208
|
||||
/// review fix) rather than hand-copying their steps a third time — the
|
||||
/// original version of this test independently reimplemented the
|
||||
/// driver-tier branch inline (unconditional `derive_temperature_c`,
|
||||
/// never the region-baseline-preferring `derive_district_temperature_c`),
|
||||
/// which was itself a THIRD copy of the exact defect class T-1160 exists
|
||||
/// to close, undetected because this test's own numbers still "looked
|
||||
/// plausible" without ever exercising the region-baseline branch. Routing
|
||||
/// through the shared helper means this test's post-fix side can never
|
||||
/// drift from what `derive_orbital_at_metres`/`invent_primitives`
|
||||
/// actually do.
|
||||
///
|
||||
/// Loads every real `heightmap.png` under `wiki/star-systems/`, and for a
|
||||
/// grid of region-spacing sample points on each body reports how often
|
||||
/// (a) and (b) disagree on land/ocean classification, the warp
|
||||
/// displacement converted to real metres, and the per-cell cost of
|
||||
/// computing (b). These are the numbers T-1160's fix (applying the warp
|
||||
/// at orbital sampling, see `derive_orbital_at_metres`'s doc) is based
|
||||
/// on. `#[ignore]`d — reads ~267 real wiki heightmap files, run
|
||||
/// explicitly:
|
||||
/// `cargo test --release -p settled-reach-server derive_orbital_coastline_divergence_audit -- --ignored --nocapture`
|
||||
#[test]
|
||||
#[ignore]
|
||||
@@ -3614,7 +3702,6 @@ mod tests {
|
||||
let mut displacement_samples = 0u64;
|
||||
|
||||
let mut warp_evals = 0u64;
|
||||
let mut warp_only_nanos = 0u64;
|
||||
let mut warp_plus_character_nanos = 0u64;
|
||||
|
||||
for hm_path in &heightmaps {
|
||||
@@ -3639,9 +3726,7 @@ mod tests {
|
||||
};
|
||||
let circumference_m = std::f64::consts::TAU * 6371.0 * 1000.0;
|
||||
let meridian_m = std::f64::consts::PI * 6371.0 * 1000.0;
|
||||
|
||||
let tectonic = derive_tectonic_class(&body_params);
|
||||
let envelope = coast_invention::body_coast_envelope(&body_params, tectonic);
|
||||
let body_id = "audit_body";
|
||||
|
||||
// Sample on a region-spacing grid across the whole body — same
|
||||
// spacing the orbital/Region rung actually renders at.
|
||||
@@ -3692,43 +3777,54 @@ mod tests {
|
||||
total_cells += 1;
|
||||
|
||||
// (b) District-style warped read at the SAME position —
|
||||
// mirrors invent_primitives' driver-tier + character +
|
||||
// warp steps, using the real per-body envelope. Timed
|
||||
// calls the REAL production region_baseline_at_district +
|
||||
// invent_coastal_position (PR #208 review fix) rather
|
||||
// than hand-copying their steps a third time (see this
|
||||
// test's own doc for why that was the bug). Timed
|
||||
// separately from the file-I/O/drainage/TerrainAnalysis
|
||||
// setup above — this is the actual per-cell cost T-1160
|
||||
// would add at orbital sampling, not body-load overhead.
|
||||
let cell_start = Instant::now();
|
||||
let raw_elev_q = ((bilinear(&ta.elev_pct, ta.w, ta.h, px, py) as f64 * 100.0)
|
||||
.round() as i32)
|
||||
.clamp(0, 100);
|
||||
let driver_params = BodyParams {
|
||||
elevation_km: (raw_elev_q as f64 / 100.0) * MAX_REGION_ELEVATION_KM,
|
||||
let params = BodyParams {
|
||||
latitude_deg: lat_deg,
|
||||
..body_params.clone()
|
||||
};
|
||||
let driver_temp = derive_temperature_c(&driver_params, &climate, seed.seed());
|
||||
let driver_moisture =
|
||||
derive_moisture_q(&driver_params, raw_elev_q, raw_ocean_q, &climate);
|
||||
let driver_glaciation =
|
||||
derive_glaciation_grade_from_climate(driver_temp, driver_moisture);
|
||||
|
||||
let ch = coast_invention::coast_character_at(
|
||||
&envelope,
|
||||
let district_pos: DistrictPos = (
|
||||
(wx / scale::DISTRICT_M as f64).floor() as i32,
|
||||
(wy / scale::DISTRICT_M as f64).floor() as i32,
|
||||
);
|
||||
let region_baseline_c = region_profile::region_baseline_at_district(
|
||||
seed.seed(),
|
||||
wx,
|
||||
wy,
|
||||
lat_deg,
|
||||
driver_glaciation,
|
||||
driver_moisture,
|
||||
body_id,
|
||||
district_pos,
|
||||
¶ms,
|
||||
&climate,
|
||||
seed,
|
||||
None,
|
||||
);
|
||||
warp_plus_character_nanos += cell_start.elapsed().as_nanos() as u64;
|
||||
|
||||
warp_evals += 1;
|
||||
let warp_call_start = Instant::now();
|
||||
let (wdx, wdy) = coast_invention::coast_warp_px(seed.seed(), wx, wy, &ch, 0.0);
|
||||
warp_only_nanos += warp_call_start.elapsed().as_nanos() as u64;
|
||||
warp_plus_character_nanos += warp_call_start.elapsed().as_nanos() as u64;
|
||||
let (spx, spy) = (px + wdx, py + wdy);
|
||||
let cell_start = Instant::now();
|
||||
let (spx, spy, _ch) = invent_coastal_position(
|
||||
seed,
|
||||
¶ms,
|
||||
&climate,
|
||||
&ta,
|
||||
px,
|
||||
py,
|
||||
wx,
|
||||
wy,
|
||||
region_baseline_c,
|
||||
0.0,
|
||||
);
|
||||
// The helper is one atomic call now (steps 1-3 fused, PR
|
||||
// #208 review fix) — a single timing captures the full
|
||||
// per-cell added cost; there is no longer a meaningful
|
||||
// way to isolate "just coast_warp_px" from "driver tier +
|
||||
// character" as two separate measurements the way the
|
||||
// pre-fix hand-inlined version allowed.
|
||||
warp_plus_character_nanos += cell_start.elapsed().as_nanos() as u64;
|
||||
let (wdx, wdy) = (spx - px, spy - py);
|
||||
|
||||
let warped_ocean_q =
|
||||
((bilinear_bool(&ta.ocean_mask, ta.w, ta.h, spx, spy) as f64 * 100.0)
|
||||
.round() as i32)
|
||||
@@ -3765,11 +3861,6 @@ mod tests {
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
let ns_per_warp_call = if warp_evals > 0 {
|
||||
warp_only_nanos as f64 / warp_evals as f64
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
let ns_per_full_cell_cost = if warp_evals > 0 {
|
||||
warp_plus_character_nanos as f64 / warp_evals as f64
|
||||
} else {
|
||||
@@ -3783,10 +3874,7 @@ mod tests {
|
||||
eprintln!("mean warp displacement: {mean_displacement_m:.1} m");
|
||||
eprintln!("max warp displacement: {max_displacement_m:.1} m");
|
||||
eprintln!(
|
||||
"coast_warp_px call cost: {ns_per_warp_call:.1} ns/call ({warp_evals} calls, {warp_only_nanos} ns total)"
|
||||
);
|
||||
eprintln!(
|
||||
"full added cost/cell: {ns_per_full_cell_cost:.1} ns/cell (driver temp/moisture/glaciation + coast_character_at + coast_warp_px)"
|
||||
"full added cost/cell: {ns_per_full_cell_cost:.1} ns/cell (invent_coastal_position: driver temp/moisture/glaciation + coast_character_at + coast_warp_px, one production call)"
|
||||
);
|
||||
|
||||
// Sanity floor — this audit is meaningless if it silently sampled
|
||||
|
||||
Reference in New Issue
Block a user