Ports the reference's v5 height curve and shelf-detail passes onto Phase 1's shape and re-calibrates them against this repo's actual pass-1 distribution. This is the BASELINE the reshape gets judged against, not the reshape. Core (engine-free, D-060): - WorldScale — THE vertical yardstick. One metres/raw number (251), replacing the prototype's three duplicate M_PER_UNIT constants and ~20 bare literals. The chunk-height coupling it had there is recorded as a DEFERRED vault decision, not inherited. RawFromMetres divides, matching the reference bit-for-bit. - HeightCurve — the 7 bands, the frozen corner-fix blends, the per-seed spike normalization, the 24-corner monotonicity sweep that throws and refuses. Identity at and below sea, which everything downstream rests on. - CurveKnots / CurveAnchors — input knots (measured percentiles) and output anchors (storm ladder) split apart and both made parameters, so the anchors are A/B-able without editing source. The reference's shipped knots are kept beside the measured ones as the fidelity yardstick. - TerrainDetailPass — micro-relief skin plus the shelf-edge KNOT warp (which slides K3/K4/K5, not height — that is what keeps monotonicity structural). The crater exclusion is ported and inert until the carve lands. Tools: - Shaping — pass 2a, producing the two height fields. classify is bit-for-bit the raw pass-1 field; render is curved and detailed. Aliased when the curve is off, as the reference did. Pass1Result is left immutable so the oracle can compare. - LandHistogram — the calibration engine AND the diagnostic. The reference shipped six knot literals and threw the measuring instrument away; this rebuilds it. - ShapingOracle + CurveBaselineTool — four automatic checks before anything is looked at, and the batch that runs them. Measured, not assumed: - Knots re-measured over a 6-seed / 12.8M-sample pool. They differ from the reference's by at most 5.6 m of world height, against a 44.7 m per-seed spread — the pass-1 port is faithful. - Oracle all pass, including pass 1 bit-identical to Phase 1's own .f32 dump. - Band shares land on 60/13/10/5/8/3/1 to 0.00 pp. - Knots hold across map size: the 8K delta (5.8 m) sits inside seed noise. The finding the histograms deliver: 83% of land ends below 100 m and 96% below 220 m, with the median column at 13 m. That is the share targets doing exactly what they say, not a bug — and it is the developer's call, which is why nothing here reshapes it and the palette was deliberately left mis-fitted rather than recalibrated to disguise it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DCWNaDZPfTiAy3meGNGgqt
67 lines
4.3 KiB
Markdown
67 lines
4.3 KiB
Markdown
# Core — math and data only
|
|
|
|
**Holds:** the column model, the material schemas, the scaling discipline, tooling path
|
|
resolution and the file-safety rails. Constants and contracts.
|
|
|
|
**Boundary: Core depends on nothing above it.** Not on `Server/`, not on `Client/`, not on
|
|
`Tools/`. The dependency arrow points one way into this folder and never out of it.
|
|
|
|
> ### ⚠ Additional boundary, tighter than the layer rule: **Core is engine-free.**
|
|
>
|
|
> No `using Godot;` anywhere in this folder. Core is plain C# — no `Node`, no `GD.Print`, no
|
|
> `ProjectSettings`, no engine types in any signature.
|
|
>
|
|
> **Two reasons, both load-bearing.** (1) D-049 commits to *"C# for fast iteration, with C++-ready
|
|
> seams… port path-by-path when settled and hot"* — the hot paths that get ported first are exactly
|
|
> the ones in here, and a type that names `Godot.Vector2` cannot cross that seam. (2) It keeps the
|
|
> column model testable and reviewable without standing up an engine.
|
|
>
|
|
> Where Core genuinely needs something the engine knows — the resolved `user://` directory — the
|
|
> engine layer **hands it in** (`ToolingPaths.Configure`), rather than Core reaching for it.
|
|
> If you find yourself wanting an engine type here, the type belongs one layer up.
|
|
|
|
## What is in here
|
|
|
|
| File | What it is |
|
|
|---|---|
|
|
| `Scripts/Column.cs` | ★★ **The load-bearing contract** (D-053). A column as run-length bands; `MaterialRun`; `RunOrigin`. Read its header before touching anything that stores world data. |
|
|
| `Scripts/ColumnGrid.cs` | The 2D grid of columns. Shape only — chunking and streaming are later phases. |
|
|
| `Scripts/MaterialKey.cs` | Material **identity** — a registry key, never an ordinal. |
|
|
| `Scripts/TerrainMaterial.cs` | A row in the terrain schema (D-054). |
|
|
| `Scripts/BuildingMaterial.cs` | A row in the building schema (D-054). |
|
|
| `Scripts/MaterialRegistry.cs` | Both registries, append-only, seed rows only. |
|
|
| `Scripts/RecipeRegistry.cs` | The transformation seam — **deliberately empty**. |
|
|
| `Scripts/GenerationScale.cs` | ⭐ The scaling discipline. `MapSize`, `ScaleFactor`, normalized offsets, the two frequency conventions. |
|
|
| `Scripts/WorldScale.cs` | ⭐ **The vertical yardstick.** The ONE metres↔raw conversion (251 m/unit). No literal `251f` anywhere else. |
|
|
| `Scripts/HeightCurve.cs` | ⭐⭐ The height-redistribution curve (v5), 7 bands. **Identity at and below sea.** |
|
|
| `Scripts/CurveKnots.cs` | The six INPUT knots — percentiles of the measured land CDF, plus the reference's for comparison. |
|
|
| `Scripts/CurveAnchors.cs` | The OUTPUT anchors — the storm-ladder elevations each band lands at. |
|
|
| `Scripts/TerrainDetailPass.cs` | Shelf micro-relief + the shelf-edge **knot warp**. Output-height only. |
|
|
| `Scripts/ToolingPaths.cs` | Every tooling path, env-overridable, resolved in one place. |
|
|
| `Scripts/FileSafety.cs` | The permanent file-safety rules, as throws rather than sentences. |
|
|
|
|
## The three rules this layer exists to make unbreakable
|
|
|
|
1. **Air is the top run.** There is no "air vs solid" height branch, anywhere, ever.
|
|
→ `Scripts/Column.cs`.
|
|
2. **Properties come from the registry, never from storage.** A run stores an identity.
|
|
→ `Scripts/MaterialRegistry.cs`.
|
|
3. **Nothing uses a raw pixel number.** Every distance is a fraction of `MapSize`.
|
|
→ `Scripts/GenerationScale.cs`.
|
|
4. **There is one metres-per-raw-unit number.** The prototype scattered `251` across three
|
|
duplicate constants and ~20 literals, and the generator never used the derived one at all.
|
|
→ `Scripts/WorldScale.cs`.
|
|
|
|
## Not here, and not by accident
|
|
|
|
- **No water.** Water is an overlay over the columns (levels-not-cells), never a band.
|
|
- **No biomes.** Biomes are a later *classification* of finished shape, not an input to it (D-049).
|
|
- **No algorithms** *beyond the height curve*. Phase 2 added `HeightCurve` and
|
|
`TerrainDetailPass` here because they are pure, engine-free, C++-candidate math that defines the
|
|
world's elevation profile — a contract, not a tool's dial. Stratigraphy, feature passes, meshing
|
|
and run-splitting on dig are still later phases.
|
|
- **No erosion, rivers, water bodies, crater carve, coast shelf or offshore islets.** Later chat2
|
|
tasks; the curve is deliberately the only pass-2 element present.
|
|
|
|
→ `Design - Data - Column Model.md`, `Design - Data - Material Schema.md`,
|
|
`Design - Tooling - Scaling Discipline.md`
|