Commit graph

29 commits

Author SHA1 Message Date
c71026fd94 feat: task-09 verdict — BALANCED becomes plain "v5", COMPACT retires (terrain-water task 10 prerequisite)
The documented one-liner the task-09 gate triggers: TerrainCurve gate
is now "off"|"v5" (default v5 = the BALANCED preset, id 2);
"v5-compact" retired with a verdict-specific error, "v5-balanced"
redirects to plain "v5". Knots/TCRV encoding unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 18:00:21 -04:00
4797086a13 docs: curve v5 — TCRV preset extension, tri-state gate (terrain-water task 09)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 04:19:58 -04:00
02577872f2 feat: curve v5 — corner fixes + COMPACT/BALANCED taste presets (terrain-water task 09)
The three corner fixes (both presets): riser endpoint slope floors
0.2 -> 0.1 (0.1u + 0.9*smoothstep — climbs decelerate into shelves and
accelerate out); summit-spike base floor 0.1 -> 0.05
(0.05u + 0.95*u^4 — no hard skirt under the peaks); SHELF_SPAN_MIN
2 m -> 6 m (pronounced shelves keep a gentle tilt).

Knots are preset-parameterized (CurveKnots, explicit parameter — pure,
D-035), calibrated from the same pooled batch-04 CDF:
COMPACT  P65/77/84/88/94/97 -> 65/12/7/4/6/3/3 land split
BALANCED P60/73/83/88/96/99 -> 60/13/10/5/8/3/1
Gate: "off"|"v5-compact"|"v5-balanced" (batch-only tri-state;
interim default v5-balanced pending the developer's verdict — the
winner becomes plain "v5" in a follow-up commit); v1-v4 retired
loudly. Assertion runs per preset (8 corners x per-seed spikeMax; the
lowered floors stay strictly positive). TCRV v5 extension (+9 B):
preset id + K5/K6 — the effective curve is unambiguous from the
record; old records parse (version-dispatched); harness compares.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 04:11:53 -04:00
68f7bca8e0 docs: curve v4 — TCRV modulation extension, TerrainCurve v4 default (terrain-water task 08)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 03:31:13 -04:00
4d2e024b2f feat: curve v4 — spatially modulated shelves (terrain-water task 08)
Per the task-07 gate: the terraces work but uniform anchors put a flat
ring at exactly 100 m and 220 m on every mountain. v4 keeps v3's
structure (frozen toe/rise, three risers, per-seed u4 spike to 420 m)
and turns the shelf anchors into smooth spatial fields: bench
100+-12 m and plateau 220+-20 m via two decorrelated very-low-freq
Simplex fields (~3 undulations per island width), plus a strength
field (~5/island) blending each shelf's output span between ~2 m
(pronounced flat) and ~25 m (barely a hint) — the optional strength
modulation shipped, ordering-safe by construction (worst-case bench
top 0.6962 < plateau min 0.9468). Field seeds derive from the RESOLVED
noise seed + fixed offsets (7101/7207/7303) — no config knob. Apply is
per-column with all modulated values as pure parameters (D-035); the
classify path never sees them.

Monotonicity assertion now sweeps all 8 modulation-extreme corners x
per-seed spikeMax. TerrainCurve gate "off"|"v4" (default v4);
v1-v3 retired loudly. TCRV extended (+36 B when version>=4:
amplitudes, span range, frequencies, seed offsets — length-framed
section makes the layout change safe; parser dispatches on the curve
version byte; harness compares the extension).

Note: MapGenerator.cs also carries the developer's editor whitespace
normalization (spaces->tabs, git diff -w empty before this change).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 03:30:27 -04:00
a046486a58 docs: curve v3 — TCRV per-version anchor semantics, TerrainCurve v3 default (terrain-water task 07)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 02:27:30 -04:00
ae7431ac87 feat: curve v3 — terraced ascent, two benches, white plateau at 220 m (terrain-water task 07)
Per the task-06 ground-test verdict (floor and 420 m ceiling frozen;
v2's ascent read flat-then-wall — 87% of the vertical budget in the
last 4% of input): the ascent is rebuilt as a terraced climb. Knots
recalibrated from the same pooled batch-04 land CDF at
P59/72/82/87/95/98 (K=0.509179/0.604081/0.698485/0.767213/0.930304/
1.050720), pooled land fractions exactly 59/13/10/5/8/3/2 (orange/red/
foothill-riser/bench/mid-riser/plateau/spike). Segments: frozen toe
and rise (storm anchors), smoothstep foothill riser to a near-flat
100 m bench, smoothstep mid riser to the near-flat white plateau at
220 m (relocated from 50 m — mountain towns/snow belong there),
per-seed-normalized u4 summit spike to 420 m (both retained from v2),
linear tail. Per-seed effective-curve monotonicity assertion retained.

TerrainCurve gate: "off"|"v3" (default v3); v1/v2 retired with a
loud config error (old blueprints regenerable). TCRV: knot slots carry
K1..K4 (K5/K6 are version constants), PlateauLo/Hi carry the two bench
anchors; version byte selects the semantics.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 02:26:36 -04:00
5720f05a5b docs: curve v2 — TCRV spikeMax semantics, TerrainCurve v2 default, v1 retired (terrain-water task 06)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 00:29:34 -04:00
ac67c27952 feat: curve v2 — per-seed spike normalization, u4 wall, 420 m ceiling (terrain-water task 06)
Per the task-05 hillshade-gate verdict: lowlands frozen (identity/toe/
rise/shoulder/plateau byte-unchanged); the spike now maps [t4,
hMaxSeed] — each seed's own raw pre-curve maximum, computed in a new
pass-1 over GenerateTopography — onto the peak band, so every island
reaches the ceiling (v1's pooled-max domain left mid-range seeds at
110–175 m). Spike stiffened to 0.1u + 0.9u^4; peak cap raised to
420 m above sea (1.82869). Degenerate near-flat guard: spike domain
floored at t4 + 0.01. The curve is now SEED-DEPENDENT: hMaxSeed is a
pure parameter (D-035), recorded in TCRV (field renamed
HMaxCal -> SpikeMax, same byte layout; v1 semantics = pooled max, v2 =
per-seed), and the monotonicity assertion runs per generation against
the effective curve. TerrainCurve gate: "off"|"v2" (default v2);
"v1" retired with a loud config error (task-05 blueprints are
regenerable). Classify path untouched — the biome/water oracle must
hold unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 00:21:25 -04:00
9ebb8296c9 docs: TCRV section entry + TerrainCurve config note + 0_height snapshot (terrain-water task 05)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 15:26:09 -04:00
e7de292b3d feat: 0_height hillshade snapshot + TCRV blueprint section + harness (terrain-water task 05)
0_height: hypsometric storm-ladder tint x Lambert NW hillshade over
the curved heights, captured after topography in both curve modes —
relief is finally visible. Renumbers nothing.

TCRV (50 B, emitted when the curve is on): curve version + input knots
+ output bands, so blueprints are self-describing about the map their
heights went through (H7 spirit). Parsed into
WorldBlueprint.TerrainCurve (null = raw legacy profile); server treats
it as metadata. Round-trip harness compares it when present.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 15:24:33 -04:00
67868638be feat: height-redistribution curve, gated + biome-invariant (terrain-water task 05)
HeightCurve (pure static, D-035): calibrated monotonic piecewise map —
identity at/below sea 0.15; ease-out toe to the orange ceiling 0.206
(75% coverage, knot t1=P75=0.628736 from batch-04's pooled flat-sea
land CDF, 340.6M samples); linear rise to red 0.27 (t2=P90); smooth
shoulder to the 50m plateau shelf 0.3492 (t3=P93); near-flat plateau
step (t4=P96); accelerating spike to the 220m peak cap 1.0265; linear
tail past the calibrated max. Strict monotonicity asserted numerically
at startup, loud throw on violation.

Applied in GenerateTopography AFTER noise+falloff+Trench, BEFORE the
crater carve (carve cuts curved terrain; rim/bowl untouched by the
curve). Biome oracle mechanism: a retained uncurved classify heightmap
(alias of _heightMap when off, zero cost) feeds biome rules, both
flood fills, and the shared water predicates — classification is
curve-invariant by construction. Towns/roads/diagnostics/exported
heights use curved terrain; town positions may legitimately move.

Config gate TerrainCurve: "off"|"v1" (default v1), unknown values
rejected loudly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 15:22:53 -04:00
e435843e9a docs: SeaLevelModel/SeaLevelValue config notes (terrain-water task 04)
Both sea-level modes documented (flat default 0.15 / legacy field
Lerp); noted the blueprint does not record which model produced it —
the WBTB levels are the observable. Batch runner lives in /tmp
(throwaway), not in-repo.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 06:25:19 -04:00
200adcaf5a feat: config-gated flat-scalar sea level (D-033, terrain-water task 04)
SeaLevelModel: "flat" (one scalar, SeaLevelValue) or "field" (the
legacy latitude Lerp 0.26..0.15). Only GetSeaLevel's body changes —
all nine call sites (crater carve target, both flood fills, biome
split, beach band, Capitol window, town filters, A* zero-point)
inherit the model automatically; no consumer re-tuning. Default:
flat 0.15, pinned in ServerConfig.json.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 06:20:48 -04:00
1f957b3430 docs: water sections (WBID/WBTB/WSRF), no-BSIN rationale, SkipRoads + water stage in READMEs (terrain-water task 03)
Byte-accurate entries for the three water sections (transitional
per-body level rule, provisional salinity, WSRF sentinel/quantization),
updated size math (~576 MiB at 8K with water), the on-the-record
rationale for NOT serializing basins, and README updates for the new
pipeline stage, the 0_water snapshot, and the SkipRoads toggle.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 01:40:48 -04:00
3bf822dac6 feat: WBID/WBTB/WSRF blueprint sections + parser + harness extension (terrain-water task 03)
Three new v2 tagged sections carrying the water-bodies stage output:
WBID (MapSize^2 u16 body ids; 0 none, 1 ocean, 2..N lakes), WBTB
(count-prefixed 20-byte records: id, type, provisional salinity,
transitional flat surface level, pixel count, centroid), WSRF
(MapSize^2 u16 quantized levels; 0 = no-water sentinel, 1 + L*32768
encoding, ~7.7 mm world resolution). Written only when the blueprint
carries water; absent on legacy re-encodes. Parser registers all
three (length + type checks) into new WorldBlueprint members —
consumed by nothing at runtime. Round-trip harness now compares the
water sections whenever the source carries them; v1-source baseline
stays green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 01:31:50 -04:00
d296ef30c4 feat: shared water predicates + water-bodies stage + priority-flood diagnostics (terrain-water task 03)
IsWaterPixel/IsOceanPixel/IsLakePixel are the single per-pixel water
truth; AssignBiomesAndDraw's water branch now calls them (verbatim
rules — behavior-preserving, proven by the bit-identical-biomes oracle
at acceptance). New IdentifyWaterBodies stage between the masks and
biomes: ocean = body 1, lakes labeled 2..N with CalculateTrueOcean's
4-connectivity in deterministic scan order; one transitional surface
level per body (GetSeaLevel at the body centroid; ocean at map
centre). 0_water snapshot painted from the stage's own outputs.

Priority-flood pit-fill (heap + pit-queue variant) runs as validated
diagnostics only — serializes nothing, asserts filled>=original and
full-map non-ascending drainage (reverse BFS, no sampling), reports
closed-basin statistics.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 01:29:51 -04:00
81f7030140 feat: SkipRoads iteration toggle (terrain-water task 03)
Config flag SkipRoads (default false): when on, GenerateRoadsAsync and
the 3_roads snapshot are skipped entirely; export proceeds with all
four road sections present but empty (both v2 and legacy v1 permit
zero counts); the console states loudly that the blueprint is a
road-less iteration artifact.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 01:27:36 -04:00
fb14b0693b chore: Godot .uid files for the new task-02 scripts
Generated by the engine on first run of the project after the v2
envelope landed (terrain-water task 02).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 00:17:46 -04:00
a7e6c17422 docs: BLUEPRINT_FORMAT.md + README updates for the v2 container (terrain-water task 02)
Byte-accurate v2 contract (magic/version, tagged sections, registered
FourCC table, validation rules, re-encode sentinels, extension path)
plus the v1 legacy summary — v1 stays live per the safety-net plan.
READMEs updated additively: parser dispatch, dual-write outputs,
harness usage, server params cross-check, wire-format hazard rewording
(u8 on v2 path, range-checked; append-only rule unchanged).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-06 07:31:03 -04:00
8532d88771 feat: blueprint v2 reader dispatch + validation + params cross-check (terrain-water task 02)
Reader sniffs the first byte (0x49 raw-ISLA v2 vs 0x07 v1 string
prefix) and routes to the v2 tagged-section parser or the intact v1
path (v1 loads log a deprecation warning — fallback stays live).

v2 validation: magic/version gate (loud reject), MapSize sanity bound
[256, 32768] before allocation, every section length checked against
remaining file, section-consumed-exactly check, params-first and
no-duplicate-section rules, biome and town-tier ordinal range checks.
Unknown tags skip by length — the forward-compat property D-030 buys.

ServerChunkManager cross-checks embedded params against config
(seed + MapSize) and logs a prominent desync warning — canon H7's
silent failure becomes loud. ServerConfig.json pins the reference
world: WorldSeed 1409879727, 8K.

Round-trip oracle GREEN: reference v1 (537,054,156 B) -> v2
(335,727,522 B, -192 MB) -> parse -> semantic equality holds
(heights bitwise, biomes, 94 towns, 4/1/37/39 road paths
point-for-point). v1 parse 1.9s, v2 write 1.4s, v2 parse 1.6s.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-06 07:27:42 -04:00
c305fd6565 feat: blueprint v2 envelope — writer, dual-write, round-trip harness (terrain-water task 02)
v2 tagged-section container (D-030): raw ISLA magic + u32 version gate,
[u32 tag][u64 length][payload] sections — params (resolved generation
inputs incl. impact centre), heights f32, biomes u8, towns with the
highway-node flag, four road tiers identified by tag not position.

- BlueprintFormat.cs: the single tag/constant registry.
- BlueprintWriter.WriteV2: blueprint-typed, callable outside a
  generation run; generator and harness are both just callers.
- ExportMapData dual-writes: v2 under the primary seed name, legacy v1
  beside it as _v1.dat (safety net; removal is a future task).
- MapDataParser: LoadMapDataFromPath entry point; v1 parse body
  extracted intact as LoadV1 (v2 reader lands in the next commit).
- RoundTripHarness scene: load v1 -> write v2 -> load v2 -> semantic
  equality, headless, seconds per cycle.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-06 07:24:08 -04:00
e070bbc9da fix: restore comment marker on WorldSeed line (build blocker)
Uncommenting the random-seed line left its trailing prose 'if 0 also
randomizes' as code, which stopped the whole project compiling. Only the
comment marker is restored — the choice of random-vs-fixed seed is left as set.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 22:43:19 -04:00
783ee8b016 docs: fix MATH_MARCHING_CUBES §4 polarity + dims
Task 17 corrected the density sign convention in §1-§2 but left §4's worked
example on the old inverted convention, so the doc contradicted itself. §4 now
matches: negative is underground, positive is air. Also corrects a stale
16x16x64 chunk reference to 24x24x256.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 21:32:51 -04:00
d72ffc0183 docs: bring all READMEs current with actual code (post-sweep-10 truth pass)
Every README was read first, checked against the code in its directory, then
rewritten to describe what the code actually does now.

Corrected throughout: map size is config-driven (8192 default) not a fixed
4096; chunks are 24x24x256 not 32x32; road carving is implemented for all four
tiers, not a 'next step'; Data/ and Resources/ are empty, not populated.

Also fixed MATH_MARCHING_CUBES.md, which documented the density sign convention
exactly backwards — it claimed positive was underground, where the code treats
positive as above the surface and counts a corner inside when density < iso.
Getting that backwards inverts every normal, a bug this project has hit before.

The root README now carries accurate run steps: F5 runs the map generator (not
the game), F6 on Scenes/Main.tscn runs the 3D world, and ChunkRadius is a load
radius that should be dropped to 4-8 while iterating.

Docs only. No code changed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 05:23:58 -04:00
f9ea2da3f4 roads: enable Rugged+Trail carving + per-tier character (D-022)
All four road tiers now carve into the 3D world. Rugged and Trail were
generated, exported and parsed all along, but nothing ever consumed them —
which is why county roads visible on the 2D map did not exist in 3D.

Tier identity is now carried into the carve via a RoadSegment struct, so each
tier gets its own width, shoulder and grade-smoothing from one tunable block in
Constants: highways widest and holding a grade, trails narrow and hugging the
land. Rugged and Trail surface as dirt rather than asphalt.

Because tiers now have different reach, nearest-by-distance was no longer a
sound way to pick the governing road — a nearby footpath could shadow a highway
whose shoulder still covered the column. The carve now considers only roads
whose shoulder actually reaches, and takes the closest of those.

The per-chunk cull pad is derived from the widest shoulder plus a margin, so
widening a road cannot silently truncate it at chunk edges.

Untouched: density field, Marching Cubes interpolation/welding, chunk dims,
the .dat contract, the 2D A* generation, and mesher normals.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 03:53:32 -04:00
0910338a2a F2: continuous road grade — along-segment elevation + joint smoothing (D-021)
Road elevation is now sampled at the point on the road segment nearest the
column being carved, instead of at the segment's midpoint. The old behaviour
gave every column near a segment that segment's single midpoint height, so each
stretch of road was one flat plank and consecutive planks stepped like a
staircase wherever the road crossed a gradient.

Elevation now varies continuously along the segment, and because neighbouring
segments share an end point the height matches exactly at the joins. A new
ROAD_GRADE_SMOOTHING constant dials between holding a straight grade
(cut-and-fill) and hugging the land, per D-021.

Untouched: density field, Marching Cubes, chunk dimensions, the .dat contract,
and the 2D A* road network itself. Only how existing paths are carved into 3D.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 02:20:50 -04:00
ea11258871 F1: soft-fade biome color blending (BLEND_BAND_METERS, geometry untouched)
Vertex colour is now chosen from the true, unrounded surface height and faded
between adjacent materials across a tunable band, instead of switching at one
rounded integer depth. This removes the horizontal contour banding.

Colour path only: density field, Marching Cubes interpolation/welding, chunk
dimensions, the .dat contract and all road logic are untouched. BlockID
classification is unchanged and still drives non-visual use.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 01:51:06 -04:00
7f0f43b5fb baseline: working salvaged prototype on Godot 4.7.1 (pre-F1)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 01:45:41 -04:00