islaApocalypse-v2/README.md
beezm 35b4818e9e Phase 2a: the faithful redistribution curve, re-measured against v2's own output
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
2026-08-20 01:38:10 -04:00

114 lines
5.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.godot` on 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:
```bash
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) — `heightClassify` is raw and is the oracle;
`height` is 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
```bash
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 `.csproj` is load-bearing.
>
> The target is `net8.0` but this machine carries only a .NET 10 runtime. Without that property the
> generated `runtimeconfig.json` rolls 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 emitted `runtimeconfig.json` after any `.csproj` change.
## 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 15 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.