A dedicated term, not the edge noise scaled: pass 1's edge noise is positive-only, squircle- modulated, 2.5x the base frequency - the coastline's jitter; scaling it would roughen the whole rim and bias the coast inward. CoastalFragment adds, to the PRE-power falloff, amp * window(f) * noise(x + off, y + off) with its own deterministic field (seed offset 9109, coordinate offset 0.37 map widths - D-059), zero-mean, at 12 periods per map width (the lobe/neck scale, chosen by probe against 20 and 32: 20 climbs into smalls, 32 is fuzz), weighted by a smooth window on the falloff value itself, centred 0.66 (the coast's falloff for a median base noise, from the 08 diagnosis), half-width 0.18, EXACTLY ZERO beyond - so the interior, the massif and the deep sea are bit-identical by construction. Thin necks of barely-land flip first; nothing is detected, nothing is stamped. FragmentBitesOnly is exposed (probed: it erodes the coast inward - mainland -3/-8/-14 % at 0.06/0.15/0.30 - rather than detaching pieces; off by default). Batch: BatchRoot(9, "coastal_fragment") - 4 amplitudes (0.06, 0.15, 0.30, 0.50) x task 08's two seeds at 4096, stretch fixed at 2 (08's stretch_3 rung, whose dump is the bit-identical baseline, a8), sinker untouched, speck revert at < 4 cells, offshore/shelf off; lean render (regions overlay + relief + .f32), the hemisphere-split count/size table with largest-three and histograms. Oracle, all passing: a1 (the curve untouched), a8 x2 (frag OFF at stretch 2 == the 08 field, 16.8 M cells each), interior locked (r: every cell clear of the window bit-identical, 8/8), high-ground report (s, informational), centre is land, tag/coastline, classify == raw, ids and heights deterministic. The read: both hemispheres fragment; the north more readily (N 10 -> 28, 13 -> 40 islands across the ladder; S 4 -> 31, 14 -> 28) and the south's big stretch pieces are the zero-mean noise's other edge: on 999999937 the 83k-cell southern fragment is BRIDGED back onto the mainland at amp 0.50 (mainland +183k). The working range is amp 0.15-0.30; 0.50 is the bookend. Graduation held. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013EY3ZTF6NwzF8ukBHQXSK7
60 lines
3.4 KiB
C#
60 lines
3.4 KiB
C#
using System;
|
||
|
||
namespace IslaApocalypse.Tools
|
||
{
|
||
/// <summary>
|
||
/// ⭐ COASTAL FRAGMENTATION (chat2/09, EXPLORATION) — a perimeter-wide, band-limited, zero-mean noise
|
||
/// on the PRE-power falloff, applied only inside the coastal window.
|
||
///
|
||
/// ═══ WHY A DEDICATED TERM AND NOT THE EDGE NOISE SCALED ═══
|
||
///
|
||
/// Pass 1's edge noise is <c>(noise+1)/2 · 0.15 · squircle</c>: positive-only (it only ever PUSHES
|
||
/// the falloff up), modulated by the squircle (strongest at the rim, zero at the centre), sampled at
|
||
/// 2.5× the base frequency. Scaling it would roughen the whole rim and bias the coast inward; it is
|
||
/// the coastline's jitter, not a margin-targeted cutter. This term is separate: its own deterministic
|
||
/// field (seed offset + a coordinate offset in map widths), its own frequency (the neck/lobe scale),
|
||
/// zero-mean (it bites AND builds, so the coast is redrawn rather than eroded), and weighted by a
|
||
/// smooth WINDOW on the falloff value itself:
|
||
///
|
||
/// w(f) = 1 − smoothstep(|f − centre| / halfWidth) (exactly 0 beyond ± halfWidth)
|
||
/// falloff += amp · w(f) · noise(x + off, y + off) noise ∈ [−1, 1]
|
||
///
|
||
/// The coast sits where rawBase − falloff^2.5 crosses sea, i.e. near f ≈ 0.66 for a median rawBase
|
||
/// (chat2/08 diagnosis), so a window centred there covers the barely-land / barely-sea margin
|
||
/// around the whole perimeter, north and south. Cells whose falloff is clear of the window — the
|
||
/// interior, the massif, the deep sea — get w = 0 and are bit-identical by construction (asserted).
|
||
///
|
||
/// SELF-TARGETING: every lobe hangs off a neck of barely-land, cells whose height sits a hair above
|
||
/// sea. A bite of the same Δfalloff flips those first; solid land inside the window (a coastal hill)
|
||
/// moves in height but does not flip. No neck is detected; the margin selects itself. Amplitude is
|
||
/// the ladder; frequency is fixed and exposed as the secondary dial.
|
||
/// </summary>
|
||
public static class CoastalFragment
|
||
{
|
||
/// <summary>Periods per map width. The base noise is ≈ 4/map, the edge noise ≈ 10/map; lobes in the 08 plates are 2–7 % of the map. Chosen by the chat2/09 probe.</summary>
|
||
public const float DefaultFreqPerMapWidth = 12f;
|
||
|
||
/// <summary>The coastal window's centre in pre-power falloff units (the coast's falloff for a median base noise).</summary>
|
||
public const float DefaultBandCentre = 0.66f;
|
||
|
||
/// <summary>Half-width of the window. 0.18 spans f ∈ [0.48, 0.84] — the whole fringe, nothing of the interior.</summary>
|
||
public const float DefaultBandHalfWidth = 0.18f;
|
||
|
||
/// <summary>Bites only by default? Set by the chat2/09 probe (see the report): zero-mean redraws the margin and can bridge islands back; bites-only only cuts.</summary>
|
||
public const bool DefaultBitesOnly = false;
|
||
|
||
/// <summary>The field's seed offset (a SEED offset, like the islet layer's 7607).</summary>
|
||
public const int SeedOffset = 9109;
|
||
|
||
/// <summary>The field's coordinate offset, IN MAP WIDTHS (D-059) — decorrelates it from the base field's realization at every size.</summary>
|
||
public const float OffsetMapWidths = 0.37f;
|
||
|
||
/// <summary>The window weight for a pre-power falloff value.</summary>
|
||
public static float Window(float falloff, float centre, float halfWidth)
|
||
{
|
||
float t = MathF.Abs(falloff - centre) / halfWidth;
|
||
if (t >= 1f) return 0f;
|
||
return 1f - t * t * (3f - 2f * t);
|
||
}
|
||
}
|
||
}
|