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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>