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>
144 lines
7.6 KiB
Markdown
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.
|