islaApocalypse/Tools
beezm 6960c2a2e8 feat: river bed carving with SHORT/LOWGROUND lowland routing A/B (terrain-water task 22, C0b part 2a)
Executes the frozen task-21b plan as real terrain — the first river pass to
modify the render map. NO WATER (part 2b waters the gated routing style).

RiverCarvePass (D-035 numeric): reruns DrainageAnalysis in-pipeline
(deterministic — same seed, same eroded surface, same plan), routes each routed
giant's lowland reach to the nearest ocean by deterministic Dijkstra under two
config-gated cost models — 'short' (distance + uphill penalty; heads direct) vs
'lowground' (cost ~ elevation above sea; follows the lowest ground and
meanders) — then carves every promoted course as a parabolic channel with a
smoothstep shoulder. Width/depth grow downstream with sqrt(drainage); bed
profile forced monotone non-increasing toward the outlet (water must flow) and
clamped to sea + RiverSeaMargin EVERYWHERE, with below-sea cells read-only and
the crater core excluded — the erosion flood-guard discipline, asserted per
generation by the water-pixel A/B (throws on any change).

Pipeline slot: AFTER GenerateTowns (towns read the render map for land/slope/
water checks — carving first would move towns and destabilise every A/B) and
BEFORE roads (a full run's A* should see the beds).

ISLA_SERVER_CONFIG env override added to ConfigManager: batch/A-B tooling loads
an alternate config file and the developer's live ServerConfig.json is never
written by tooling again (the task-19 restore near-miss class is retired).

Measured, seed 1280587109 (both variants): oracle md5-identical to baseline
(BIOM/WBID bitwise equal), 0 newly-below-sea cells, below-sea untouched, island
top 457.65 m exact, lowest carved cell exactly sea+margin (37.85 m), and
Rivers='off' is bitwise identical to the task-19 blueprint. All routed giants
reach the ocean in both styles. Wander (polyline/straight): SHORT 1.02-1.06 vs
LOWGROUND 1.24-1.38; SHORT carves 811k m3 (cuts through rises, max cumulative
cut 14.6 m), LOWGROUND 481k m3 (goes around, 14.3 m). Pass cost ~25 s (plan
21 s, routing 1.4-2.5 s, carve 0.3 s).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-11 19:16:37 -04:00
..
Scenes feat: drainage-network promotion analysis — the river PLAN (terrain-water task 21, C0b part 1) 2026-08-11 18:06:21 -04:00
Scripts feat: river bed carving with SHORT/LOWGROUND lowland routing A/B (terrain-water task 22, C0b part 2a) 2026-08-11 19:16:37 -04:00
README.md docs: water sections (WBID/WBTB/WSRF), no-BSIN rationale, SkipRoads + water stage in READMEs (terrain-water task 03) 2026-08-07 01:40:48 -04:00

/Tools

Offline developer utilities. Nothing here ships. These generate the source data that /Server and /Client later consume, which keeps world-generation logic out of the shipped client.

The 2D world generator

Script: Tools/Scripts/MapGenerator.cs · Scenes: Tools/Scenes/MapPreview.tscn and Scenes/MapCaptureTool.tscn

Builds the topographical and logistical foundation of the island before any 3D exists.

  • Resolution is config-driven, from ServerConfig.json's MapProfile: 4K/6K/8K/10K → 4096 / 6144 / 8192 / 10240. Shipped default is 8K. 1 pixel = 1 in-game metre = 1 voxel footprint. (The MapSize field initialiser in the script says 4096, but it is overwritten from config before use.)
  • Topography: FastNoiseLite plus distance-falloff maths for a guaranteed mainland island, a mountain spine, dynamic temperature-driven sea level, and an impact crater pushed into the northern coast (carved at 80 % of its radius so a landbridge always survives).
  • Water bodies: the classified water promoted into explicit blueprint data (ocean + labeled lakes with transitional per-body levels — WBID/WBTB/WSRF sections), plus priority-flood basin diagnostics. The SkipRoads config toggle turns a full ~26-min generation into a ~80 s road-less iteration cycle.
  • Logistics: AStarGrid2D pathfinding producing a looping continental highway, a branch to the mountain hub, and county roads daisy-chained outward with Prim's algorithm. Paths are decimated (RamerDouglasPeucker) then smoothed (4 Chaikin passes).
  • Zoning: biome mapping and tiered town/POI placement by slope, temperature and proximity.

⚠️ A* is the known bottleneck

The grid is one node per pixel — 67 million nodes at 8K — and the weight-setup pass walks every one of them. A full generation can stall long enough that runs get abandoned. await yields are sprinkled through the road stage, but they cannot interrupt a single engine-side GetPointPath call, so they only help between paths. Expect a regeneration to take minutes, or to need abandoning.

Outputs — written to user://, not into the project

File What it is
MapData_Seed_<seed>.dat The binary blueprint the server reads — v2 tagged container (~336 MB at 8K; contract in Core/Scripts/BLUEPRINT_FORMAT.md)
MapData_Seed_<seed>_v1.dat The same content in the legacy v1 format (~512 MB), dual-written as a safety net until a future removal task
Map_Seed_<seed>.png Visual snapshot of the map, for reviewing and picking seeds

On Linux: ~/.local/share/godot/app_userdata/islaApocolypse/.

Running it

Open Tools/Scenes/MapPreview.tscn and press F6. It is also the project's main scene, so pressing F5 anywhere runs this — which is why F5 regenerates your world instead of starting the game. Use Scenes/MapCaptureTool.tscn when you specifically want the full-resolution PNG.

Rules

  1. No client dependencies. Nothing here may reference UI, player controllers or shaders in /Client.
  2. Data out, nothing in. Tools emit .dat/.png/.json; they never write to a live server save.
  3. No magic numbers. Distances and radii scale off MapSize or the derived scaleFactor, so the generator behaves the same at every profile.