Files
settled-reach/docs/workshops/atlas-derivation-model.md
T
jpmschweitzerandClaude Opus 4.7 f1c1d2c8f0 docs(decisions): atlas-to-tile derivation model — D-227/D-228 + Q-100..105
Atlas-derivation workshop output (Jeroen + Tyre / Nigel / Burnelli / Gestalt).
The foundational world-derivation model:

- D-227 deterministic-rebuild world model: world = pure function of seed+atlas,
  derived on demand + cached, only tile mutators persisted, fully volumetric
  (voxel / subvoxel), vertical extent physical not floor-count, variable-height
  floors (cave/basement/built all count).
- D-228 composite tile schema: orthogonal axes (TerrainMaterial / FloorMaterial /
  Vegetation / Water / elevation), derived shape + tactical form, region-level
  morphology zones, cohesion matrix, dynamic clock-bound region seasonal state
  (water-height / snow / weather / crop-cycle from one cheap per-region calc).
- Q-100..Q-105: biome authority, refinement contract (+ body-class river density
  + ocean mask), cohesion-matrix algorithm, mutator op schema, floor-to-voxel-z
  mapping, region seasonal/clock state.
- Workshop brief: docs/workshops/atlas-derivation-model.md.

Epic #974 + ocean-mask story #975 track implementation (Phase 4 milestone).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 12:55:57 +02:00

144 lines
7.6 KiB
Markdown

# Workshop — The Atlas → Tile Derivation Model
*Driven by the water model, but the water model is only the forcing instance.*
## Why this, why now
We are building the generation cascade (Phase 4). The viewer (#960) surfaced a
problem that looks like "lakes" but is actually the **inter-level derivation
contract**: how coarse, map-scale planetary data becomes fine, coherent,
per-tile geometry without squared/blocky artifacts. This is **cascade-first**:
if we bake the wrong derivation model now, every layer below (economic →
settlement → quarters → tiles) inherits it and it becomes very expensive to
unwind. Decide it before those layers exist. Stations are out of scope here —
**bodies first**.
## The methodology: reverse the derivation
Do **not** start from "what can the cascade derive?" Start from the target:
> **Build the complete list of everything a tile on a body must contain.**
> Then work backward: for each item, how do we derive it deterministically from
> (a) a **prebaked atlas dataset** and/or (b) a **seeded algorithm**?
The requirements list is the spec. The cascade is the mechanism that satisfies
it. We want the list first so the cascade is designed to a known target, not
grown by accretion.
## The three legs (generalized from the water instance)
**1. Dual artifact — baked render ↔ semantic model.**
The reliefmap should have lakes/rivers/coastlines **baked in** (authoritative
*visual*, no toggles — yes, that means regenerating reliefmaps). Separately,
there is a **semantic model** (rivers as flow-carrying paths, lakes as regions,
coasts as curves) that is the authoritative *generation input*. The reliefmap is
a render of the model at map scale; the model is what lower levels consume.
**2. Multi-scale refinement contract — hint, not squared truth.**
A reliefmap pixel is a map-scale rendering, not ground truth to copy downward. A
2-px river (sized for map visibility) is kilometers wide at tile scale; a
land/water pixel edge is a staircase coastline. So coarse data is a **semantic
hint + a seed**, and each lower level **deterministically refines** it into
smooth, ~1-tile-scale geometry that *respects* the hint without copying its
resolution. "Somewhere in this band a coherent coastline passes"; "a river of
roughly this flow threads this corridor."
**3. Context-driven algorithm family — selection is part of generation.**
Refinement is not one algorithm. The *choice* is driven by local context:
- **Rivers**: low slope → meandering, wide, lazy, floodplains/oxbows; steep →
incised, straighter, gorges, knickpoint waterfalls; (braided/deltaic at the
extremes).
- **Coasts**: low relief + sediment → smooth dune-lined strands; hard rock +
high relief → craggy cliffs; drowned glaciated valleys → fjords.
Contract: **hint + local context + seed → algorithm selection → geometry.** Same
hint, different terrain, genuinely different feature.
## The expanding atlas (a key consideration for the brief)
Satisfying the per-tile list will almost certainly require **more prebaked
planetary layers** than heightmap + reliefmap — plausibly: lithology
distribution, a water-bodies layer, prevailing winds, temperature/precipitation,
glaciation history, biomes. The workshop must take a position on:
- **Which layers are prebaked vs runtime-derived** (storage + determinism + the
modding story — D-225's mod-first intent applies).
- **Context data we have vs owe**: slope/relief derive from the heightmap, but
lithology (crag-vs-dune) and glaciation (fjords) may not exist yet. Decide
whether morphology is selected from proxies we have, or a thin new context
layer is owed (with its determinism + ownership cost).
- **Organizational (future, "at some point")**: moving all wiki content +
heightmaps into a new `gamedata/` atlas subtree sitting next to `server/` and
`client/`. Not a round-1 deliverable, but flag whether the data model implies
it and roughly when.
## Questions to resolve (each → a D-record or a tracked open question)
1. **The per-tile content requirements list** — the target (reverse-derivation).
2. **Biome authority**`planet-gen` reliefmap coloring vs in-cascade
`subbiome::classify`; which is canonical, and what that implies for where
water (and other features) is authored.
3. **The atlas dataset family** — which layers are prebaked; format; determinism.
4. **Dual artifact** — baked reliefmap ↔ semantic model: representation + how they
stay in sync (regen pipeline).
5. **The refinement contract** — the inter-layer hint+seed→geometry API;
anti-squaring; how each layer hands constraints to the next.
6. **Context-driven morphology** — the algorithm families + the context inputs
they require; the have-vs-owe data fork.
7. **Cascade placement + `gamedata/` restructure** — where water/derivation is
authored; restructure scope/timing.
8. **Determinism** — D-010 integer-only must hold across all refinement +
selection (seed → identical geometry).
## Team angles
- **Tyre** — architecture: the derivation/refinement contract, dual raster +
semantic data structures, deterministic downscaling, atlas-layer storage, the
`gamedata/` restructure feasibility, performance/memory at tile scale.
- **Nigel** — procedural variety/emergence: does the algorithm family +
reverse-derivation yield rich, sensible, non-repetitive worlds across seeds?
Where does sameness creep in? What's the second-playthrough payoff?
- **Gestalt** — systems meaning: drive the per-tile requirements list from "what
creates interesting decisions / gameplay," and the consequences of morphology
(a fjord is a deep defensible harbor; a meandering river is fertile +
bridgeable; a craggy coast resists landing).
- **Burnelli** — economic layer needs: what the economy reads from the atlas —
water as trade corridor vs barrier, ports/harbors, resource distribution, the
regional scale the economy actually operates at.
## Round 1 task (each agent)
Read this brief + the pointed code/decisions, then post an **opening position**
on your angle that includes:
1. Your contribution to the **reverse requirements list** — what must a tile (or
the data feeding it) contain, from your lens.
2. The key **forks/risks** you see in the derivation model.
3. Anything in the current code/decisions that **constrains or contradicts** the
approach.
This is investigation + position, **not** final design. Flag blockers early
(heartbeat rule below).
## Reading
- **Code**: `server/src/atlas/heightmap.rs` (normalized elevation + `sea_level`,
downsample), `server/src/atlas/drainage.rs` (existing `depression_fill`, D8
routing, rivers/basins, the new Moore boundary trace), `server/src/atlas/layer1.rs`
(`Layer1Output` incl. `grid_w/grid_h`), `server/src/atlas/layer_proxy.rs`
(D-225 proxy). `tooling/planet-gen/``render_heightmap.py`,
`planet_renderer.py` (ocean colors, biome coloring), `planet_simulation.py`
(`max_elevation_km`, biome assignment).
- **Decisions**: D-202 (canonical 16-bit heightmap), D-208 (drainage), D-209 /
D-210 (attractors / sub-biomes), D-225 (layer-stream proxy, mod-first),
D-166 (generation-before-player). The cascade phase table in `CLAUDE.md`.
- **Constraints**: D-010 (determinism, integer-only), cascade-first (no detail
from a later phase), the no-squaring principle above.
## Process
Round-based. The lead synthesizes after each round and pulls Jeroen in — he
decides when to dismiss. **Close only when D-record(s) + ticket(s) exist** (hard
deliverables). Teammates edit files; the **lead** does all git.
**Heartbeat rule:** if you work a single task >15 min without progress, message
the lead with what's blocking you. Do not silently retry.