chat2/02 dissolved the terraces and lost two thirds of the mountain with them, then
concluded the loss was structural and needed a Phase-1 noise change. That conclusion
was wrong, and this commit is the refutation.
A monotone curve is a free reparametrization: it may be gentle in one place and steep
in another, and can lift bottom-heavy input into a substantial massif without ever
going flat. The area above a height is set by where the percentile->height mapping
crosses it, and that mapping is entirely ours to choose. The 02 sweep that "proved"
the loss structural varied climbFeather, which shapes the JOIN, not the mass
distribution — the wrong knob, and too strong a conclusion drawn from it.
Core/ClimbCalibration — the climb's control points are now MEASURED off the staircase
instead of invented from shape knobs. For p in {10,30,50,70,85,95} of above-ceiling
land, take that percentile's raw height and its staircase output height; PCHIP through
the pairs. That reproduces the staircase's elevation envelope, so the mountain mass
returns, while MinNormalizedSecant floors every grade so the flat bench and plateau
interiors become slope. The floor bites on exactly one segment — the plateau — which
is precisely where the staircase was flat.
ContinuousCurve.BuildCalibrated joins it to the same pinned lowland handover, the same
C1 join and the same per-seed spikeMax. The 02 analytic path survives unchanged as the
"before" contrast, and deliberately keeps its strictly-increasing-secant rule: a
calibrated curve is WAVY by design, so convexity is the wrong invariant for it and the
secant floor is the right one.
peakSharpness replaces summitDrama and fixes its bad trade. Drama steepened the peak by
pulling the summit ONSET down, dragging the whole massif with it (p99 199 -> 121 m).
Sharpness reshapes only above the last measured percentile, leaving that height fixed,
so peak and massif are independent: raising it leaves p90, >100 m and >220 m untouched
and only moves land within the summit.
Measured, both seeds, 2048:
variant >100 m >220 m p90
staircase (target) 16.05% 4.53% 127.4 m
continuous_02default 4.80% 0.63% 58.4 m
continuous_restored 14.25% 3.45% 123.2 m
continuous_bigger 19.70% 5.80% 163.5 m
Oracle all hard checks pass, including (a2) staircase still bit-identical to task 01's
dump and (d) lowlands bit-identical across every calibrated variant. New (g) reports
land above 100/220 m per variant and is deliberately NOT gated — it is a taste target
the developer tunes, and gating it would make mountainLift unusable. What it must never
do is stay silent, which is how 02 lost the mountain unnoticed.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DCWNaDZPfTiAy3meGNGgqt
|
||
|---|---|---|
| Client | ||
| Core | ||
| Server | ||
| Tools | ||
| .gitattributes | ||
| .gitignore | ||
| islaApocalypse-v2.csproj | ||
| islaApocalypse-v2.sln | ||
| project.godot | ||
| README.md | ||
Isla Apocalypse — v2
The rewrite (D-049). A post-apocalyptic survival voxel game: one island, generated once offline, loaded by everyone.
Status: Phase 2 — shaping. Phase 0 laid the contracts and the tooling rails; Phase 1 ported the crown-jewel noise and pass 1 (the island's raw shape); chat2/01 added pass 2a — the height redistribution curve and shelf detail, re-calibrated against this repo's own output, with the two-height-field split and an automatic oracle.
Still no erosion, rivers, water bodies, crater carve, coast shelf, offshore islets, biomes, roads or mesher.
⚠ Two repos. Never one.
| Repo | Role |
|---|---|
~/celerNexus/islaApocalypse-v2/ (this) |
The rewrite. Every line of new code is written here. |
~/celerNexus/islaApocalypse/ |
⛔ READ-ONLY. The pre-rewrite prototype, archived at ab78883, tag pre-rewrite-reference. Ported FROM; never written to. |
~/celerNexus/islaApocalypse-vault-v0.1/ |
The design vault — the source of truth for WHAT and WHY. The vault leads. |
The old codebase is a spent quarry (D-050): mined, never tracked, never synced, never canon'd. Writing rewrite code into it would corrupt the very thing being ported from.
⚠ Runtime data isolation — do not weaken
This project pins its user:// directory away from the old prototype's, which holds the
preserved reference seeds, blueprints and batches:
user:// → ~/.local/share/islaApocalypse-v2/ ← this project
~/.local/share/godot/app_userdata/islaApocalypse/ ← ⛔ the OLD prototype. Never touch.
Pinned two ways in project.godot — a distinct application/config/name and
use_custom_user_dir + custom_user_dir_name. Both must stay.
⚠ Do not document this with a comment in
project.godot— it will not survive.Godot rewrites
project.godoton import and STRIPS ALL COMMENTS, replacing the header with its own boilerplate. (Measured: a warning block written there was gone after the next--import. The settings survived; only the explanation was deleted.) So the warning lives here, and the guarantee is enforced by the probe below — which exits non-zero on a clash and therefore works in a pre-flight check, not just by eye.
After any change to the [application] block, re-run the probe:
Godot_v4.7.2-stable_mono_linux.x86_64 --headless \
--path ~/celerNexus/islaApocalypse-v2 res://Tools/Scenes/UserDirProbe.tscn
Layout
Core/ math + data only, ENGINE-FREE — depends on nothing above it
Server/ authoritative logic — may use Core (empty: not yet its phase)
Client/ rendering — may use Core (empty: not yet its phase)
Tools/ the offline generator — ⚠ may NOT use Client
Each layer has a README.md stating its role and its boundary. Read the one for the layer you are
about to write in — they carry the reasons, not just the rules.
The contracts this phase establishes
- ★★ The column model (D-053) — the world as a 2D grid of columns, each a stack of
(material, thickness)runs. Air is the top run; there is no air-vs-solid height branch. →Core/Scripts/Column.cs - The material schemas (D-054) — terrain and building, two schemas bridged by a transformation
seam that is deliberately empty. Identity is a registry key, never an ordinal. Mesh style is
per-origin, never a material property. →
Core/Scripts/MaterialRegistry.cs - The scaling discipline — nothing uses a raw pixel number.
→
Core/Scripts/GenerationScale.cs - The vertical yardstick — ONE metres-per-raw-unit number, not three constants and twenty
literals as the prototype had. →
Core/Scripts/WorldScale.cs - The elevation profile — the 7-band redistribution curve, identity at and below sea, its
knots measured rather than chosen. →
Core/Scripts/HeightCurve.cs - The two-height-field split (D-046) —
heightClassifyis raw and is the oracle;heightis curved and is what gets drawn. →Tools/Scripts/Pass2Result.cs - Tooling safety — every path env-overridable, deletion refused by code.
→
Core/Scripts/ToolingPaths.cs,Core/Scripts/FileSafety.cs
Build
dotnet build
Godot_v4.7.2-stable_mono_linux.x86_64 --headless --import --path .
Godot 4.7.2 (mono) · .NET 8 (net8.0) · Godot.NET.Sdk/4.7.2
The reference repo is Godot 4.7.1. This repo deliberately targets 4.7.2 — clean rewrite, current tooling. 4.7.1 is the port source, not a constraint on new code.
⚠
<RollForward>Major</RollForward>in the.csprojis load-bearing.The target is
net8.0but this machine carries only a .NET 10 runtime. Without that property the generatedruntimeconfig.jsonrolls forward by MINOR only and every run fails with "You must install .NET 8". This bites at run time, not build time — the build succeeds either way — so re-check the emittedruntimeconfig.jsonafter any.csprojchange.
What this phase is NOT
No mesher, no stratigraphy, no biomes, no water, no rivers, no erosion. The pipeline is 2D-maps-first (D-056): stages 1–5 are flat maps, gotten completely right before a single 3D vertex exists. Building the mesher before the data is right is the specific trap this rewrite exists to undo.
And the curve is a BASELINE, not a verdict. It is ported faithfully and calibrated honestly so that later reshaping has a control to be judged against. Whether this elevation profile — 60 % of land in the bottom 14 m, 4 % above the plateau — is the one the world wants is an open question the histograms exist to inform, not one this port has answered.