feat(@projects/@magic-civilization): ✨ add substrate-flora ontology split task
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
557a506bec
commit
a16fa074c9
4 changed files with 141 additions and 8 deletions
|
|
@ -16,9 +16,9 @@
|
|||
|---|---|---|---|---|---|---|---|
|
||||
| **P0** | 43 | 0 | 0 | 0 | 0 | 0 | 43 |
|
||||
| **P1** | 36 | 1 | 14 | 0 | 14 | 1 | 66 |
|
||||
| **P2** | 33 | 0 | 5 | 1 | 6 | 6 | 51 |
|
||||
| **P2** | 33 | 0 | 5 | 1 | 7 | 6 | 52 |
|
||||
| **P3 (oos)** | 3 | 0 | 0 | 0 | 1 | 19 | 23 |
|
||||
| **total** | **115** | **1** | **19** | **1** | **21** | **26** | **183** |
|
||||
| **total** | **115** | **1** | **19** | **1** | **22** | **26** | **184** |
|
||||
|
||||
</td><td valign='top' style='padding-left:2em'>
|
||||
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
| Team Lead | Remaining |
|
||||
|---|---|
|
||||
| [terraformer](../team-leads/terraformer.md) | 9 |
|
||||
| [terraformer](../team-leads/terraformer.md) | 10 |
|
||||
| [warcouncil](../team-leads/warcouncil.md) | 7 |
|
||||
| [asset-sprite](../team-leads/asset-sprite.md) | 6 |
|
||||
| [shipwright](../team-leads/shipwright.md) | 5 |
|
||||
|
|
@ -204,6 +204,7 @@
|
|||
| [p2-49](p2-49-climate-axes-latitude-continentality.md) | 🟡 partial | Climate axes refactor — latitude + continentality + zonal winds as first-class per-hex inputs | [terraformer](../team-leads/terraformer.md) | 2026-04-30 |
|
||||
| [p2-50](p2-50-rng-determinism-pin.md) | 🟡 partial | Deterministic RNG + seed-derivation pin across mc-mapgen / mc-climate / mc-ecology | [terraformer](../team-leads/terraformer.md) | 2026-04-30 |
|
||||
| [p2-51](p2-51-world-shape-knobs.md) | 🟡 partial | Player-facing world-shape parameters on new-game screen | [terraformer](../team-leads/terraformer.md) | 2026-04-30 |
|
||||
| [p2-52](p2-52-substrate-flora-cover-ontology-split.md) | ❌ missing | Split terrain enum into substrate × flora-cover layers (resolve biome ontology) | [terraformer](../team-leads/terraformer.md) | 2026-05-01 |
|
||||
|
||||
## Out of Scope (Game 2 / Game 3)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,121 @@
|
|||
---
|
||||
id: p2-52
|
||||
title: Split terrain enum into substrate × flora-cover layers (resolve biome ontology)
|
||||
priority: p2
|
||||
status: missing
|
||||
scope: game1
|
||||
owner: terraformer
|
||||
updated_at: 2026-05-01
|
||||
canonical_doc: public/games/age-of-dwarves/docs/terrain/CLIMATE.md
|
||||
coordinates_with:
|
||||
- p1-46
|
||||
- p1-48
|
||||
- p1-50
|
||||
- p2-49
|
||||
- p2-51
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
The current `terrain.json` enum (16 IDs) conflates three orthogonal
|
||||
ecological layers into a single field:
|
||||
|
||||
| Layer | Examples currently in terrain enum | Should live where |
|
||||
|---|---|---|
|
||||
| **Substrate** (geological / hydrological) | `mountains`, `hills`, `ocean`, `coast`, `lake`, `inland_sea`, `volcano`, `ice`, `snow` | terrain (correct) |
|
||||
| **Flora-cover** (emergent from species) | `forest`, `jungle`, `boreal_forest`, `grassland`, `swamp` | derived from flora selector |
|
||||
| **Substrate × climate composite** | `desert`, `tundra`, `plains` | derived label, not authored |
|
||||
|
||||
The `feature_type: "foliage"` field on `forest`/`jungle`/`boreal_forest`
|
||||
in `public/games/age-of-dwarves/data/terrain/land_forest.json` is the
|
||||
data layer admitting these are flora cover masquerading as terrain.
|
||||
|
||||
This conflation propagates everywhere:
|
||||
- Flora species `biomes[]` arrays list flora-cover types as locking
|
||||
conditions (a beech tree's `biomes = [temperate_forest, forest]` —
|
||||
both are flora-cover labels, not substrates)
|
||||
- Climate classifier (`mc-climate::derive::classify_terrain_whittaker`)
|
||||
emits flora-cover names from T/P bands directly, skipping the
|
||||
substrate axis
|
||||
- Terrain blends (`terrain_blends.json`) mix substrate edges
|
||||
(`coast+plains → shore`) with flora-cover edges
|
||||
(`forest+plains → grass_fringe`) on equal footing
|
||||
|
||||
This objective restructures the data model into three independent layers
|
||||
that the renderer composes into a final visual:
|
||||
|
||||
```
|
||||
Substrate ← Tectonics + Hydrology output
|
||||
× Climate ← (t_band, p_band, riparian_distance)
|
||||
× Flora-cover ← Ecology selector output (canopy/understory/ground/bare)
|
||||
= Biome label ← Display name only, derived not stored
|
||||
```
|
||||
|
||||
## Why p2 (not p1) and why Game 1 not Game 2
|
||||
|
||||
- Visually the lab works fine today because the conflation produces
|
||||
plausible-looking output. Refactoring is **architectural cleanup**,
|
||||
not a user-visible bug.
|
||||
- The Wave A–E pipeline already implicitly does substrate (tectonics)
|
||||
→ climate → flora (ecology selector) — the data model lags the
|
||||
pipeline. This objective reconciles them.
|
||||
- Doing it pre-EA prevents lock-in of the wrong contract — every
|
||||
subsequent Game-2 mechanic (leylines, soil g2-06, lifecycle g2-07,
|
||||
population dynamics g2-08) inherits whatever shape ships with EA.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- ◻ **New `substrate.json`** at `public/games/age-of-dwarves/data/terrain/`
|
||||
authoring 8–10 substrate types: `bedrock`, `soil`, `sand`,
|
||||
`permafrost`, `peat`, `water`, `seawater`, `ice`, `lava`. Each with
|
||||
fields: `albedo`, `evapotranspiration_max`, `drainage`, `fertility_base`.
|
||||
- ◻ **TileState refactor** — `TileState::terrain_id` deprecated;
|
||||
replaced by `TileState::{substrate_id, flora_cover_id, biome_label_id}`
|
||||
where `biome_label_id` is *derived* (read-only, computed from the
|
||||
three independent fields).
|
||||
- ◻ **Flora `biomes[]` rewrite** — every species's `biomes[]` array
|
||||
becomes a list of `(substrate, climate_band)` pairs. Migration
|
||||
script + visual diff to confirm equivalence.
|
||||
- ◻ **Whittaker classifier consumes substrate** —
|
||||
`mc-climate::derive::classify_terrain_whittaker(t_band, p_band,
|
||||
substrate)` returns a `(biome_label, flora_cover_id)` pair. The
|
||||
current single-output signature is replaced.
|
||||
- ◻ **terrain_blends.json restructured** into two tables:
|
||||
`substrate_blends.json` (substrate-edge ecotones like `coast+soil`)
|
||||
and `flora_cover_blends.json` (e.g. `closed_canopy + open_grass →
|
||||
forest_edge`). The renderer composes them.
|
||||
- ◻ **Renderer composition** — Lab.tsx + Godot tile renderer fill
|
||||
substrate base → flora cover overlay → biome decorations, each
|
||||
driven by the matching field.
|
||||
- ◻ **Backward-compat removed** — no aliasing of old `forest`/`jungle`
|
||||
IDs to new substrate+cover combos. Per Zero Tech Debt, the old IDs
|
||||
are gone, not shimmed.
|
||||
- ◻ **Migration test** — for one frozen seed, before/after
|
||||
comparison: every tile's *visual* output (substrate + flora cover
|
||||
rendered) matches the pre-refactor render to within tolerance.
|
||||
Determinism preserved.
|
||||
- ◻ **Doc updates** — `CLIMATE.md` Whittaker section rewritten to
|
||||
show 3-axis lookup; `ECOLOGY_BINDING.md` species index keyed on
|
||||
`(substrate, t_band, p_band)`; new `SUBSTRATE.md` canonical doc
|
||||
authored.
|
||||
|
||||
## Dependencies / risks
|
||||
|
||||
- p1-46 (Wave-E lab integration) should land FIRST, locking the
|
||||
current visual baseline before the refactor.
|
||||
- Touches `mc-climate`, `mc-mapgen`, `mc-ecology`, `api-gdext`,
|
||||
`api-wasm`, all 6 lab pages, all flora/fauna species JSON, and
|
||||
Godot tile renderer. High blast radius — coordinate carefully.
|
||||
- Risk: post-EA save format must migrate (or refuse to load) old
|
||||
worlds. Coordinate with `p2-50`'s save-format pin.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- Adding new substrate types beyond the ~10 above (g2-05 / g2-06
|
||||
expand into lithology + soil orders for Game 2).
|
||||
- Restructuring fauna `biomes[]` similarly — fauna mostly cluster
|
||||
around flora cover anyway, lower priority. Possibly follow-up
|
||||
objective.
|
||||
- A "Substrate" page in the design lab — covered by the
|
||||
per-substrate inspector on the Tectonics page (already authored
|
||||
in p1-53).
|
||||
|
|
@ -15,6 +15,7 @@ objectives:
|
|||
- p2-49
|
||||
- p2-50
|
||||
- p2-51
|
||||
- p2-52
|
||||
---
|
||||
|
||||
## Mandate
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
{
|
||||
"generated_at": "2026-05-01T05:05:59Z",
|
||||
"generated_at": "2026-05-01T05:07:45Z",
|
||||
"totals": {
|
||||
"stub": 1,
|
||||
"done": 115,
|
||||
"partial": 19,
|
||||
"missing": 22,
|
||||
"oos": 26,
|
||||
"in_progress": 1,
|
||||
"missing": 21,
|
||||
"total": 183
|
||||
"stub": 1,
|
||||
"done": 115,
|
||||
"total": 184
|
||||
},
|
||||
"objectives": [
|
||||
{
|
||||
|
|
@ -1610,6 +1610,16 @@
|
|||
"updated_at": "2026-04-30",
|
||||
"summary": "The terraformer pipeline now exposes ~15 internal parameters\n(plate count, tectonic strength, fbm octaves, sea level, latitude\ngradient, continentality decay, rain-shadow factor, erosion\niterations, drainage threshold, etc.). Designers tune these in the\nforest lab; **players see none of them**. The new-game screen ships\n\"Map Size\" and not much else.\n\nIndustry baseline (Civ 6, Old World, Songs of Conquest) exposes 4–6\nhigh-level shape knobs. Each knob is a *preset* that derives several\ninternal parameters at once. This objective wires that surface from\nJSON presets through `mc-mapgen` parameters into the Godot game-setup\nscene."
|
||||
},
|
||||
{
|
||||
"id": "p2-52",
|
||||
"title": "Split terrain enum into substrate × flora-cover layers (resolve biome ontology)",
|
||||
"priority": "p2",
|
||||
"status": "missing",
|
||||
"scope": "game1",
|
||||
"owner": "terraformer",
|
||||
"updated_at": "2026-05-01",
|
||||
"summary": "The current `terrain.json` enum (16 IDs) conflates three orthogonal\necological layers into a single field:\n\n| Layer | Examples currently in terrain enum | Should live where |\n|---|---|---|\n| **Substrate** (geological / hydrological) | `mountains`, `hills`, `ocean`, `coast`, `lake`, `inland_sea`, `volcano`, `ice`, `snow` | terrain (correct) |\n| **Flora-cover** (emergent from species) | `forest`, `jungle`, `boreal_forest`, `grassland`, `swamp` | derived from flora selector |\n| **Substrate × climate composite** | `desert`, `tundra`, `plains` | derived label, not authored |\n\nThe `feature_type: \"foliage\"` field on `forest`/`jungle`/`boreal_forest`\nin `public/games/age-of-dwarves/data/terrain/land_forest.json` is the\ndata layer admitting these are flora cover masquerading as terrain.\n\nThis conflation propagates everywhere:\n- Flora species `biomes[]` arrays list flora-cover types as locking\n conditions (a beech tree's `biomes = [temperate_forest, forest]` —\n both are flora-cover labels, not substrates)\n- Climate classifier (`mc-climate::derive::classify_terrain_whittaker`)\n emits flora-cover names from T/P bands directly, skipping the\n substrate axis\n- Terrain blends (`terrain_blends.json`) mix substrate edges\n (`coast+plains → shore`) with flora-cover edges\n (`forest+plains → grass_fringe`) on equal footing\n\nThis objective restructures the data model into three independent layers\nthat the renderer composes into a final visual:\n\n```\nSubstrate ← Tectonics + Hydrology output\n × Climate ← (t_band, p_band, riparian_distance)\n × Flora-cover ← Ecology selector output (canopy/understory/ground/bare)\n = Biome label ← Display name only, derived not stored\n```"
|
||||
},
|
||||
{
|
||||
"id": "g2-01",
|
||||
"title": "Ley lines — Game 2 (Age of Kzzykt)",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue