feat(@projects/@magic-civilization): ✨ add terraforming objectives and team leads
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
1e431d389f
commit
d00a3a61be
11 changed files with 617 additions and 15 deletions
|
|
@ -15,10 +15,10 @@
|
|||
| Priority | ✅ | 🔵 | 🟡 | 🔴 | ❌ | ⚫ | Total |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| **P0** | 43 | 0 | 0 | 0 | 0 | 0 | 43 |
|
||||
| **P1** | 33 | 1 | 8 | 0 | 14 | 1 | 57 |
|
||||
| **P2** | 32 | 0 | 2 | 1 | 7 | 0 | 42 |
|
||||
| **P1** | 33 | 1 | 9 | 0 | 17 | 1 | 61 |
|
||||
| **P2** | 33 | 0 | 2 | 1 | 7 | 2 | 45 |
|
||||
| **P3 (oos)** | 3 | 0 | 0 | 0 | 1 | 19 | 23 |
|
||||
| **total** | **111** | **1** | **10** | **1** | **22** | **20** | **165** |
|
||||
| **total** | **112** | **1** | **11** | **1** | **25** | **22** | **172** |
|
||||
|
||||
</td><td valign='top' style='padding-left:2em'>
|
||||
|
||||
|
|
@ -29,6 +29,7 @@
|
|||
| [warcouncil](../team-leads/warcouncil.md) | 7 |
|
||||
| [asset-sprite](../team-leads/asset-sprite.md) | 6 |
|
||||
| [shipwright](../team-leads/shipwright.md) | 5 |
|
||||
| [terraformer](../team-leads/terraformer.md) | 5 |
|
||||
| [combat-dev](../team-leads/combat-dev.md) | 1 |
|
||||
| [simulator-infra](../team-leads/simulator-infra.md) | 1 |
|
||||
| [asset-audio](../team-leads/asset-audio.md) | 1 |
|
||||
|
|
@ -134,6 +135,10 @@
|
|||
| [p1-43](p1-43-building-stacking-upgrade.md) | ❌ missing | Building stacking — per-category upgrade chains (military / science / culture / production / etc.) | — | 2026-04-29 |
|
||||
| [p1-44](p1-44-buildings-as-producers.md) | ❌ missing | Buildings produce units, not the city center — per-building production queues | — | 2026-04-29 |
|
||||
| [p1-45](p1-45-batch-binary-freshness.md) | ❌ missing | "Batch binary freshness: rebuild GDExt before every autoplay batch" | [simulator-infra](../team-leads/simulator-infra.md) | 2026-04-30 |
|
||||
| [p1-46](p1-46-design-lab-terrain-dimensions.md) | 🟡 partial | Terrain Dimensions Lab — fix ridginess, bind 149 flora species, add Whittaker plot | [terraformer](../team-leads/terraformer.md) | 2026-04-30 |
|
||||
| [p1-47](p1-47-river-hydrology-network.md) | ❌ missing | River hydrology — D6 flow analysis, multi-hex lakes, cross-tile rivers | [terraformer](../team-leads/terraformer.md) | 2026-04-30 |
|
||||
| [p1-48](p1-48-flora-species-renderer.md) | ❌ missing | Flora species renderer — bind 149 species to world-map tile rendering | [terraformer](../team-leads/terraformer.md) | 2026-04-30 |
|
||||
| [p1-49](p1-49-fauna-species-renderer.md) | ❌ missing | Fauna species renderer — 61 Game-1 species visible on encounter and lair tiles | [terraformer](../team-leads/terraformer.md) | 2026-04-30 |
|
||||
| [p2-06](p2-06-export-pipeline.md) | ✅ done | Export pipeline for Windows / macOS / Linux | [shipwright](../team-leads/shipwright.md) | 2026-04-25 |
|
||||
| [p2-16](p2-16-audio-assets.md) | 🔵 in_progress | Audio assets — in-theme OSS launch pack + source ledger | [asset-audio](../team-leads/asset-audio.md) | 2026-04-27 |
|
||||
| [p2-22](p2-22-sprite-generation-pipeline.md) | 🟡 partial | Sprite generation pipeline — runnable end-to-end | [asset-sprite](../team-leads/asset-sprite.md) | 2026-04-25 |
|
||||
|
|
@ -185,12 +190,13 @@
|
|||
| [p2-37](p2-37-react-calculator-metadata-surface.md) | ✅ done | "React calculator UI — surface flavor, lore, clan_affinity, archetype filter" | [tourguide](../team-leads/tourguide.md) | 2026-04-27 |
|
||||
| [p2-38](p2-38-unit-audio-cues-stubs.md) | ✅ done | "Unit audio_cues stub strings — selection/move/attack lines for the dwarven roster" | [asset-audio](../team-leads/asset-audio.md) | 2026-04-27 |
|
||||
| [p2-39](p2-39-chronicle-hall-phantom-unlock.md) | ✅ done | Resolve `chronicle_hall` phantom unlock in `chronicle_keeping` culture tech | — | 2026-04-27 |
|
||||
| [p2-43](p2-43-culture-research-completion-event.md) | ❌ missing | "Culture research completion event — wire `culture_researched` from Rust to GDScript" | — | 2026-04-30 |
|
||||
| [p2-43](p2-43-culture-research-completion-event.md) | ❌ missing | "Culture research live-game pipeline — per-turn GDExt bridge + `culture_researched` emit" | — | 2026-04-30 |
|
||||
| [p2-44](p2-44-ai-promotion-selection.md) | ❌ missing | "AI promotion selection — auto-pick + emit unit_promoted for AI units" | — | 2026-04-30 |
|
||||
| [p2-45](p2-45-elimination-reconciliation.md) | ❌ missing | "Player elimination reconciliation — emit `player_eliminated` on every transition" | — | 2026-04-30 |
|
||||
| [p2-45](p2-45-elimination-reconciliation.md) | ✅ done | "Player elimination reconciliation — emit `player_eliminated` on every transition" | — | 2026-04-30 |
|
||||
| [p2-46](p2-46-past-games-archive-replay-viewer.md) | ❌ missing | Past-games archive & replay viewer — `mc-replay` crate, on-disk archive, projection-based playback | [shipwright](../team-leads/shipwright.md) | 2026-04-30 |
|
||||
| [p2-47](p2-47-in-game-statistics-screens.md) | ❌ missing | In-game statistics screens — Civ-style 5-tab modal (Demographics / Graphs / Rankings / Replay / Histories) | [shipwright](../team-leads/shipwright.md) | 2026-04-30 |
|
||||
| [p2-48](p2-48-end-of-game-summary-screen.md) | ❌ missing | End-of-game summary screen — outcome banner, standings, score graph, awards, timeline, footer actions | [shipwright](../team-leads/shipwright.md) | 2026-04-30 |
|
||||
| [p2-49](p2-49-climate-axes-latitude-continentality.md) | ❌ missing | Climate axes refactor — latitude + continentality as first-class per-hex inputs | [terraformer](../team-leads/terraformer.md) | 2026-04-30 |
|
||||
|
||||
## Out of Scope (Game 2 / Game 3)
|
||||
|
||||
|
|
@ -199,6 +205,8 @@
|
|||
| ID | Status | Title | Owner | Updated |
|
||||
|---|---|---|---|---|
|
||||
| [p1-14](p1-14-guide-magic-school-scope-drift.md) | ⚫ oos | Gate Game 2/3/4 magic-school content behind EpisodeGate (future-game scope) | — | 2026-04-17 |
|
||||
| [g2-05](g2-05-tectonics-lithology-oos.md) | ⚫ oos | Tectonics + lithology axes for procedural map generation (Game 2) | — | 2026-04-30 |
|
||||
| [g2-06](g2-06-soil-derivation-oos.md) | ⚫ oos | Soil derivation layer — emergent soil order from rock + climate + slope (Game 2) | — | 2026-04-30 |
|
||||
| [g2-01](g2-01-leylines-oos.md) | ⚫ oos | Ley lines — Game 2 (Age of Kzzykt) | — | 2026-04-17 |
|
||||
| [g2-02](g2-02-additional-races-oos.md) | ⚫ oos | Kzzykt playable race — Game 2 (Age of Kzzykt) | — | 2026-04-17 |
|
||||
| [g2-03](g2-03-green-school-oos.md) | ⚫ oos | Kzzykt Green school of magic — Game 2 (Age of Kzzykt) | — | 2026-04-17 |
|
||||
|
|
|
|||
40
.project/objectives/g2-05-tectonics-lithology-oos.md
Normal file
40
.project/objectives/g2-05-tectonics-lithology-oos.md
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
id: g2-05
|
||||
title: Tectonics + lithology axes for procedural map generation (Game 2)
|
||||
priority: p2
|
||||
status: oos
|
||||
scope: game2
|
||||
updated_at: 2026-04-30
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Game 1 ships with elevation as the single geological axis. Game 2's
|
||||
expanded scope (additional races, leylines, planet-scale events) calls
|
||||
for plate-tectonic simulation:
|
||||
|
||||
- Per-hex `plate_id`, `plate_type`
|
||||
(cratonic / passive_margin / active_margin / volcanic_arc / rift /
|
||||
hotspot)
|
||||
- `lithology` (granite / basalt / limestone / sandstone / volcanic /
|
||||
metamorphic)
|
||||
|
||||
Drives mountain shape, mineral suite filtering, soil-order derivation
|
||||
(g2-06), and volcanic-event placement.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- ◻ Plate boundary network generated from a Voronoi seed pattern.
|
||||
- ◻ Lithology assigned per hex from plate type + age + erosion.
|
||||
- ◻ Mineral deposits in `public/resources/deposits/*.json` filtered by
|
||||
`terrains[]` ∩ `lithology` (currently terrain-only filter).
|
||||
- ◻ Mountain shape varies by plate type: arc volcanoes (Cascadia),
|
||||
collision ranges (Himalaya), rift escarpments (East Africa).
|
||||
- ◻ Soil derivation (g2-06) consumes lithology as upstream input.
|
||||
- ◻ Lab Tier-0 sliders expose plate type + lithology selectors.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- Real-time plate motion (geological time-scale).
|
||||
- Earthquake events as gameplay mechanics — separate objective.
|
||||
- Continent-scale plate reconstruction (paleo-climate).
|
||||
48
.project/objectives/g2-06-soil-derivation-oos.md
Normal file
48
.project/objectives/g2-06-soil-derivation-oos.md
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
---
|
||||
id: g2-06
|
||||
title: Soil derivation layer — emergent soil order from rock + climate + slope (Game 2)
|
||||
priority: p2
|
||||
status: oos
|
||||
scope: game2
|
||||
updated_at: 2026-04-30
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Game 1's biome classifier has no soil layer; tile yield depends on
|
||||
biome + deposits only. Real ecological behaviour requires soil — a
|
||||
Mollisol grassland is far more productive than an Aridisol grassland.
|
||||
|
||||
Soil is emergent from
|
||||
`lithology + mean_T + mean_P + slope + flora_succession_stage + time`
|
||||
and outputs one of the 8 USDA soil orders (or simplified subset):
|
||||
|
||||
- Mollisol (grassland, deep dark, fertile)
|
||||
- Spodosol (boreal, acidic, leached)
|
||||
- Oxisol (tropical, ancient, weathered, low nutrient)
|
||||
- Aridisol (desert, calcium-rich, shallow)
|
||||
- Histosol (peat, saturated)
|
||||
- Andisol (volcanic, light, exceptional)
|
||||
- Inceptisol (young, weakly developed)
|
||||
- Entisol (very young, alluvial)
|
||||
|
||||
Game 2 adds the soil layer as a drop-in fold over yield, fertility, and
|
||||
flora `growth_rate`.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- ◻ `mc-ecology::soil::derive(lithology, T, P, slope, succession)`
|
||||
returns a `SoilOrder` enum.
|
||||
- ◻ Tile yield in `mc-city` multiplied by soil-fertility coefficient
|
||||
per soil order.
|
||||
- ◻ Flora `growth_rate` per species multiplied by soil suitability
|
||||
(each species lists tolerated soil orders; schema extension
|
||||
required).
|
||||
- ◻ Lab "Soil" overlay toggle shows soil-order tint per hex.
|
||||
- ◻ Determinism golden vector.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- Soil weathering / drift over turns — static derivation.
|
||||
- Player-modifiable soil (terraform building) — Game 3+ only.
|
||||
- Soil chemistry per element (N, P, K) — too granular.
|
||||
68
.project/objectives/p1-46-design-lab-terrain-dimensions.md
Normal file
68
.project/objectives/p1-46-design-lab-terrain-dimensions.md
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
---
|
||||
id: p1-46
|
||||
title: Terrain Dimensions Lab — fix ridginess, bind 149 flora species, add Whittaker plot
|
||||
priority: p1
|
||||
status: partial
|
||||
scope: game1
|
||||
owner: terraformer
|
||||
updated_at: 2026-04-30
|
||||
evidence:
|
||||
- .project/designs/app/src/pages/WorldGen/ForestLab.tsx
|
||||
- .project/designs/app/src/pages/WorldGen.tsx
|
||||
- .project/designs/app/src/utils/worldGen/terrain.ts
|
||||
- .project/designs/app/src/utils/worldGen/hexCanvas.ts
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
The Terrain Dimensions Lab at `/world-gen/forest-lab` (lab tab) currently
|
||||
classifies the 17 base biomes and renders cross-tile flora/minerals/fauna
|
||||
overlays driven by 4 biome sliders + 3 toggleable overlay layers. Three
|
||||
known gaps:
|
||||
|
||||
1. **Ridginess slider has zero effect at default elevation 0.65.** The
|
||||
classifier (`terrain.ts:118`) only consults ridginess when
|
||||
`elevation > 0.85 ∧ ridginess > 0.92` for the volcano case. Anywhere
|
||||
else, the slider does nothing — the user verified this on the live
|
||||
lab and flagged it.
|
||||
2. **The lab loads 0 of 149 flora species.** Trees / shrubs / ground
|
||||
cover are generic per terrain. The 149 species in
|
||||
`public/resources/ecology/flora/species/*.json` carry rich schema
|
||||
(`biomes[]`, `lineage`, `tags` with layer info, `quality_tier`,
|
||||
`canopy_contribution`) that the lab ignores entirely.
|
||||
3. **No Whittaker T×P plot inset** — the user can move sliders but has
|
||||
no visual map of where they are in biome space.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- ◻ **Ridginess works at all elevations** — repurpose as a
|
||||
cross-elevation modifier: at `elevation < 0.70 ∧ ridginess > 0.5`
|
||||
upgrade plains/grassland → hills; at any elevation, increase rocky-
|
||||
stipple density and reduce flora density by `(1 - 0.6 * ridginess)`.
|
||||
Visible side-by-side screenshot at low / mid / high ridginess.
|
||||
- ◻ **149 flora species bound** — load
|
||||
`public/resources/ecology/flora/species/*.json` via `import.meta.glob`,
|
||||
build `TERRAIN_FLORA: Map<terrainId, FloraEntry[]>` filtered by
|
||||
`biomes[]` ∩ alias-normalised current biome. Render canopy via lineage
|
||||
tag (`conifers` → `drawConifer3Layer`, `broadleaf_trees` →
|
||||
`drawTree3Layer(temperate)`, `tropical_broadleaf` →
|
||||
`drawTree3Layer(tropical)`, `cacti` → cactus glyph, `palms` → palm,
|
||||
`aquatic_plants` → water-lily). Layer selection by `tags`
|
||||
(`layer_canopy`/`layer_understory`/`layer_ground`/`layer_fungal`).
|
||||
- ◻ **Info card shows top-3 species per layer** — canopy / understory /
|
||||
ground each with up to 3 species names + `quality_tier`, sorted by
|
||||
contribution weight.
|
||||
- ◻ **Whittaker plot inset** — small 200×160 SVG at right of the canvas
|
||||
showing biome regions in T (x) × P (y) space with a focus dot at
|
||||
current (T, P). Colours match terrain colour palette.
|
||||
- ◻ **Visual proof** — screenshot of the lab at 4 distinct slider
|
||||
configurations (forest, jungle, boreal, desert) committed to
|
||||
`.project/screenshots/p1-46-*.png`, each showing flora species names
|
||||
in info card.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- New flora species authoring — schema is owned elsewhere.
|
||||
- Hydrology rendering — that's p1-47.
|
||||
- Tectonics / lithology axes — that's g2-05.
|
||||
- Climate refactor (latitude, continentality) — that's p2-49.
|
||||
80
.project/objectives/p1-47-river-hydrology-network.md
Normal file
80
.project/objectives/p1-47-river-hydrology-network.md
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
---
|
||||
id: p1-47
|
||||
title: River hydrology — D6 flow analysis, multi-hex lakes, cross-tile rivers
|
||||
priority: p1
|
||||
status: missing
|
||||
scope: game1
|
||||
owner: terraformer
|
||||
updated_at: 2026-04-30
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Water bodies in the current map are per-hex terrain types
|
||||
(`ocean`, `coast`, `lake`, `inland_sea`) with no connectivity. Real
|
||||
geographic water is **topological**: rivers are DAGs from headwaters to
|
||||
ocean, lakes are multi-hex polygons, coastlines are polylines along
|
||||
land/water borders.
|
||||
|
||||
The data already encodes this in:
|
||||
|
||||
- `public/games/age-of-dwarves/data/terrain/terrain_blends.json` —
|
||||
`riverside_forest`, `shore`, `cliff`, `bog_edge` ecotones (cross-tile)
|
||||
- 10+ fauna species with `river` / `lake` / `wetland` biomes
|
||||
(bald_eagle, alligator, otter, kingfisher, beaver, etc.)
|
||||
- 4 riparian flora species: `lotus`, `papyrus`, `giant_water_lily`,
|
||||
`pioneer_sedge`
|
||||
|
||||
But there is **no rendering pass** that uses the topology. This
|
||||
objective adds D6 flow-direction analysis on the elevation grid,
|
||||
drainage-area accumulation, lake-basin filling, and a cross-tile
|
||||
renderer that draws rivers as bezier paths through hex edges and lakes
|
||||
as multi-hex continuous fills.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- ◻ **D6 flow analysis in mc-mapgen** — new module
|
||||
`src/simulator/crates/mc-mapgen/src/hydrology.rs`: per-hex
|
||||
`flow_out: Option<HexDir>`, `drainage_area: u32`,
|
||||
`stream_order: u8`, `lake_id: Option<u32>`. Topological sort
|
||||
produces a deterministic order; drainage accumulates bottom-up;
|
||||
closed basins fill to overflow.
|
||||
- ◻ **GDExtension surface** — `api-gdext/src/lib.rs` exposes
|
||||
`GdGridState::tile_hydrology(col, row)` returning a struct with the
|
||||
four hydrology fields. Read by Godot tile tooltip + design-lab via
|
||||
cargo-built artifact.
|
||||
- ◻ **Design lab renders rivers** — new module
|
||||
`.project/designs/app/src/utils/worldGen/hydrology.ts` reproduces the
|
||||
D6 algorithm in TS for the synthetic 7×5 grid; new render pass
|
||||
between minerals and flora draws bezier curves through hex edges
|
||||
with width = `1 + log2(drainage_area + 1)` and stroke colour
|
||||
interpolated from light to dark blue by stream order.
|
||||
- ◻ **Multi-hex lakes** — connected components of `lake`/`coast`/
|
||||
`ocean` cells render as one continuous fill; internal hex borders
|
||||
suppressed; surface wave glyphs respect the body's overall shape,
|
||||
not the tile's.
|
||||
- ◻ **Coastline ecotone strokes** — for each land/water hex edge,
|
||||
draw a styled stroke using `terrain_blends.json` lookup:
|
||||
`coast+plains` → sandy stipple, `coast+mountains` → cliff dark
|
||||
jagged, `coast+forest` → riverside green, `coast+desert` → cracked
|
||||
tan.
|
||||
- ◻ **Riparian feedback into flora** — within 1 hex of a river edge or
|
||||
lake border: flora density bumped by 1.4×; riparian flora species
|
||||
(lotus / papyrus / black_alder / silver_birch / bald_cypress)
|
||||
preferred in canopy/understory selection. Verified by toggling river
|
||||
overlay off and counting trees within riparian band.
|
||||
- ◻ **Determinism test** —
|
||||
`src/simulator/crates/mc-mapgen/tests/hydrology.rs`: same seed
|
||||
produces same flow graph + drainage areas + lake_ids over 5
|
||||
different map sizes. Frozen golden vector for one seed.
|
||||
- ◻ **Visual proof** — screenshot showing connected river system
|
||||
across 5+ hexes with multi-hex lake at the bottom committed to
|
||||
`.project/screenshots/p1-47-*.png`.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- Naval movement / pathfinding on rivers — that's `g6-01-naval-combat`.
|
||||
- Aquifer / groundwater modelling — too granular for Game 1.
|
||||
- Glacier / sea-ice flow — only static frozen tiles for now.
|
||||
- River EROSION feedback to elevation — one-shot computation, not
|
||||
multi-step simulation.
|
||||
68
.project/objectives/p1-48-flora-species-renderer.md
Normal file
68
.project/objectives/p1-48-flora-species-renderer.md
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
---
|
||||
id: p1-48
|
||||
title: Flora species renderer — bind 149 species to world-map tile rendering
|
||||
priority: p1
|
||||
status: missing
|
||||
scope: game1
|
||||
owner: terraformer
|
||||
updated_at: 2026-04-30
|
||||
coordinates_with:
|
||||
- p1-46
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
`public/resources/ecology/flora/species/*.json` defines **149 species**
|
||||
with rich schema:
|
||||
|
||||
- `biomes[]` — which terrain types support the species
|
||||
- `tags[]` including layer (`layer_canopy` / `layer_understory` /
|
||||
`layer_ground` / `layer_fungal`) and structure (`structure_woody` /
|
||||
`conifer` / `broadleaf` / `evergreen`)
|
||||
- `lineage` — taxonomic group (`conifers`, `broadleaf_trees`,
|
||||
`tropical_broadleaf`, `cacti`, `palms`, `aquatic_plants`,
|
||||
`mosses_lichens`, etc.)
|
||||
- `quality_tier` (0–10), `canopy_contribution`,
|
||||
`undergrowth_contribution`, `fungi_contribution`
|
||||
- `drought_tolerance`, `fire_resistance`, `growth_rate`
|
||||
|
||||
But the world-map renderer (`mc-render` or Godot tilemap layer) draws
|
||||
generic green circles for forest tiles. This objective wires the 149
|
||||
species data into the canvas / TileMap rendering so a "forest" tile in
|
||||
temperate Europe shows oak / beech / birch and a "forest" tile in
|
||||
tropical climate shows mahogany / teak / strangler_fig — each instance
|
||||
picked from the species pool that lists this terrain in its `biomes[]`.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- ◻ **Species pool builder** — new module
|
||||
`src/simulator/crates/mc-ecology/src/species.rs` builds
|
||||
`TerrainFloraIndex: HashMap<TerrainId, Vec<FloraId>>` at startup
|
||||
from species JSONs, indexed by biome alias.
|
||||
- ◻ **Per-tile species selection** — deterministic pick of N species
|
||||
per tile (N driven by tile quality + `canopy_contribution` weights),
|
||||
seeded by `(map_seed, col, row)`. Same tile yields same species set
|
||||
across loads.
|
||||
- ◻ **Lineage → glyph mapping** — `conifers` → `drawConifer3Layer`,
|
||||
`broadleaf_trees` → `drawTree3Layer(temperate)`,
|
||||
`tropical_broadleaf` → `drawTree3Layer(tropical)`, `cacti` → cactus
|
||||
glyph, `palms` → palm glyph, `aquatic_plants` → water-lily,
|
||||
`mosses_lichens` → ground stipple.
|
||||
- ◻ **Layer stratification** — `layer_canopy` species rendered first,
|
||||
`layer_understory` smaller / behind, `layer_ground` smallest; visible
|
||||
vertical ordering side-by-side.
|
||||
- ◻ **Tooltip integration** — world-map tile tooltip shows top-3 flora
|
||||
species names with `quality_tier` per stratum.
|
||||
- ◻ **Design-lab uses same module** — lab and shipped renderer share
|
||||
the same `mc-ecology::species` selection logic; not two
|
||||
implementations. (Couples to p1-46.)
|
||||
- ◻ **Determinism gate** —
|
||||
`src/simulator/crates/mc-ecology/tests/species_selection.rs`: golden
|
||||
vector for 10 seeds × 5 biomes; same input → same species set.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- Per-species animation / sway — static icons only.
|
||||
- Successional drift over turns — one-shot pick at map gen, not
|
||||
dynamic.
|
||||
- Custom sprite assets per species — procedural canvas glyphs only.
|
||||
62
.project/objectives/p1-49-fauna-species-renderer.md
Normal file
62
.project/objectives/p1-49-fauna-species-renderer.md
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
---
|
||||
id: p1-49
|
||||
title: Fauna species renderer — 61 Game-1 species visible on encounter and lair tiles
|
||||
priority: p1
|
||||
status: missing
|
||||
scope: game1
|
||||
owner: terraformer
|
||||
updated_at: 2026-04-30
|
||||
coordinates_with:
|
||||
- p0-17
|
||||
- p1-47
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
`public/games/age-of-dwarves/data/manifests/fauna.json` whitelists **61
|
||||
Game-1 species** with rich JSON schema in
|
||||
`public/resources/ecology/fauna/species/*.json`:
|
||||
|
||||
- `domain` (land / air / marine / freshwater)
|
||||
- `trophic_level` (apex_predator / predator / herbivore / omnivore)
|
||||
- `biomes[]`
|
||||
- `prey[]` — actual food-web edges
|
||||
- `ecology_tier` (1–10 rarity / strength)
|
||||
- `forms_lairs` + `lair_type`
|
||||
- `lineage` (canines, ursids, cervids, raptors, etc.)
|
||||
- `traits[]` including `size_*`
|
||||
|
||||
But the world-map renderer draws abstract icons for lairs and no
|
||||
overlay at all for ambient fauna. This objective wires the species
|
||||
data into the renderer so a wolf lair shows a wolf silhouette, a bear
|
||||
cave shows a bear, a harpy nest shows a winged figure.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- ◻ **Species glyph table** — per-species canvas glyph in
|
||||
`src/simulator/crates/mc-ecology/src/fauna_glyphs.rs` (or TS twin in
|
||||
design-lab) keyed by `lineage` + `domain` + `size_class`. 61 species
|
||||
→ ~12 distinct glyphs after lineage clustering.
|
||||
- ◻ **Lair tiles render species silhouette** — Godot side
|
||||
`wild_creature_lair_*.gd` tile sprite swap to use species-specific
|
||||
glyph instead of generic icon.
|
||||
- ◻ **Ambient fauna overlay** — design-lab fauna toggle picks species
|
||||
from `TerrainFaunaIndex` (built from manifest + species JSONs)
|
||||
weighted by `ecology_tier`. Up to 5 silhouettes per tile.
|
||||
- ◻ **Aquatic species only on water-adjacent tiles** — couples to
|
||||
p1-47: fauna with `domain ∈ {marine, freshwater}` only spawn on
|
||||
water cells or hexes adjacent to lakes / rivers.
|
||||
- ◻ **Tooltip integration** — world-map tile tooltip lists matching
|
||||
fauna species with trophic level + ecology_tier.
|
||||
- ◻ **Determinism gate** — same seed → same species per tile.
|
||||
- ◻ **Visual proof** — screenshot of a forest tile with 3+ species
|
||||
silhouettes (e.g. red_deer + brown_bear + grey_wolf) committed to
|
||||
`.project/screenshots/p1-49-*.png`.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- Combat behaviour scripting (lair AI) — that's p0-17.
|
||||
- Per-species call sounds / audio — out of scope.
|
||||
- Migration paths over turns — static placement.
|
||||
- Schema additions (e.g. new `glyph_override` field) — bind to
|
||||
existing fields only.
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
---
|
||||
id: p2-49
|
||||
title: Climate axes refactor — latitude + continentality as first-class per-hex inputs
|
||||
priority: p2
|
||||
status: missing
|
||||
scope: game1
|
||||
owner: terraformer
|
||||
updated_at: 2026-04-30
|
||||
coordinates_with:
|
||||
- p0-31
|
||||
- p0-32
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
`mc-mapgen::sampleCell` (and the design-lab twin in `terrain.ts:213`)
|
||||
derives `cold` from
|
||||
`abs(row/rows - 0.5) * 2 * (1 - climate)` — an implicit latitude proxy
|
||||
that doesn't expose:
|
||||
|
||||
- **Continentality** — distance from ocean, drives seasonal swing and
|
||||
base aridity (Siberia vs Ireland)
|
||||
- **Seasonality** — latitude amplitude (tropic vs arctic)
|
||||
- **Rain shadow** — windward / leeward of mountains (wet Pacific NW
|
||||
vs dry Great Basin)
|
||||
- **Elevation lapse rate** — ~6.5°C/km cooling
|
||||
|
||||
The classifier consumes the collapsed `cold` value, producing biomes
|
||||
that don't differentiate maritime temperate from continental temperate,
|
||||
or windward rainforest from leeward rain shadow.
|
||||
|
||||
This objective decomposes the climate input into independent per-hex
|
||||
fields — `latitude`, `continentality`, `prevailing_wind_dir` — then
|
||||
derives mean T, mean P, seasonality, evapotranspiration deficit. The
|
||||
biome classifier consumes the derived values, exposing
|
||||
maritime / continental and rain-shadow distinctions at last.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- ◻ **Per-hex climate fields** — `mc-mapgen::TileMeta` extended with
|
||||
`latitude: f32 (0..1)`, `continentality: f32 (0..1)`,
|
||||
`wind_dir: HexDir`. Computed deterministically from `map_seed`.
|
||||
- ◻ **Derived fields** — `mean_temp`, `mean_precip`, `seasonality`,
|
||||
`aridity_index` computed in `mc-climate::derive` from
|
||||
(latitude, continentality, elevation, wind_dir, mountain_proximity).
|
||||
- ◻ **Rain-shadow logic** — windward of a mountain ridge:
|
||||
`mean_precip *= 1.5`; leeward: `*= 0.4`. Visible as desert / steppe
|
||||
in lee of major ranges.
|
||||
- ◻ **Classifier rewrite** — `classifyTerrain` consumes derived (T, P)
|
||||
instead of (moisture, cold). Whittaker-style boundaries.
|
||||
- ◻ **Lab exposes 5 climate sliders** — Latitude, Continentality,
|
||||
Wind, Precipitation, Elevation Lapse Adjustment. Old "Humidity" +
|
||||
"Temperature" sliders reframed as derived display.
|
||||
- ◻ **Backwards-compat** — existing `mc-climate` tile_sync invariants
|
||||
(verified in p0-31's batch tests) still hold; canopy/undergrowth
|
||||
evolves consistently with the refactored climate inputs.
|
||||
- ◻ **Determinism + golden** —
|
||||
`src/simulator/crates/mc-mapgen/tests/climate_decomposition.rs`
|
||||
freezes derived fields for one seed; subsequent runs match.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- Multi-year climate cycles — static per-map.
|
||||
- Ocean current modelling — `wind_dir` is a hex-direction proxy; no
|
||||
Gulf Stream simulation.
|
||||
- Dynamic climate change — static.
|
||||
- Latitude-driven day-length effects on flora growth — Game 2+.
|
||||
|
|
@ -71,3 +71,4 @@ specialist does not own any objective.
|
|||
| [testwright](testwright.md) | Testwright | Regression-test coverage across Rust + GDScript + data validators — seeds the evidence substrate for the Objective Status Integrity rule | p1-09, p2-10 |
|
||||
| [tourguide](tourguide.md) | Tourguide | Developer experience of the guide web app — dev server boots on plum, route coverage e2e, dev-tier deploy at mc.next.black.local, sim-cache baked on apricot, welcome→HomePage→theme alignment, and the "no build output in src" rule stays enforced | p1-11, p1-12, p1-13, p1-15, p1-17, p2-20, p2-21, p2-29 |
|
||||
| [envoy](envoy.md) | Envoy | Post-EA diplomacy depth — courier-gated information trade, open-borders agreements, courier unit family + building chain + severable route infrastructure. Parked until Shipwright ships EA. | p3-01 |
|
||||
| [terraformer](terraformer.md) | Terraformer | Procedural terrain generation, ecology rendering, and the Earth-systems layered model — biome classifier, hydrology network, flora/fauna species binding, and the design-app Terrain Dimensions Lab at /world-gen/forest-lab | p1-46, p1-47, p1-48, p1-49, p2-49 |
|
||||
|
|
|
|||
90
.project/team-leads/terraformer.md
Normal file
90
.project/team-leads/terraformer.md
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
---
|
||||
id: terraformer
|
||||
name: Terraformer
|
||||
specialization: Procedural terrain generation, ecology rendering, and the Earth-systems layered model — biome classifier, hydrology network, flora/fauna species binding, and the design-app Terrain Dimensions Lab at /world-gen/forest-lab.
|
||||
objectives:
|
||||
- p1-46
|
||||
- p1-47
|
||||
- p1-48
|
||||
- p1-49
|
||||
- p2-49
|
||||
---
|
||||
|
||||
## Mandate
|
||||
|
||||
Own the world-generation stack from tectonics through ecology rendering.
|
||||
Game 1 ships with `mc-mapgen`'s `classifyTerrain` producing 17 base
|
||||
biomes from elevation + moisture + cold + ridginess. The Terraformer
|
||||
extends this in two directions:
|
||||
|
||||
1. **Make the existing system EXPRESSIVE.** Bind the 149 flora species
|
||||
and 61 Game-1 fauna species in `public/resources/ecology/` to the
|
||||
renderer so the world looks like its data — not generic green
|
||||
circles.
|
||||
2. **Add the missing TIER between topography and climate** — connected
|
||||
hydrology (rivers as DAGs, lakes as multi-hex polygons, coastlines
|
||||
as ecotone polylines) computed by D6 flow analysis on the elevation
|
||||
field.
|
||||
|
||||
The Terrain Dimensions Lab at `/world-gen/forest-lab` is the canonical
|
||||
playground where designers validate biome distinctions. The Terraformer
|
||||
keeps it honest: every slider must do something visible at default
|
||||
parameters, and every species in the data must be reachable through the
|
||||
lab's overlays.
|
||||
|
||||
## Owned surface
|
||||
|
||||
Files / crates this lead may modify:
|
||||
|
||||
- `.project/designs/app/src/pages/WorldGen/` — design lab pages
|
||||
- `.project/designs/app/src/utils/worldGen/` — terrain classifier, hex
|
||||
rendering, and new modules: `flora.ts`, `hydrology.ts`, `ridginess.ts`
|
||||
- `src/simulator/crates/mc-mapgen/src/` — procedural map generation,
|
||||
hydrology (`hydrology.rs` to add), flow-direction analysis
|
||||
- `src/simulator/crates/mc-ecology/src/` — species binding modules
|
||||
(`species.rs`, `fauna_glyphs.rs`)
|
||||
- `src/simulator/crates/mc-climate/src/` — climate inputs to the biome
|
||||
classifier (latitude, continentality, rain shadow) — coordinate with
|
||||
shipwright before mutating climate spec
|
||||
- `src/simulator/api-gdext/src/` — exposing hydrology + species fields
|
||||
to Godot
|
||||
- `public/games/age-of-dwarves/data/terrain/*.json` — terrain
|
||||
definitions including blends/ecotones
|
||||
- `src/game/engine/src/generation/` — Godot-side generation glue
|
||||
- `src/game/engine/src/map/` — Godot tile renderer integration
|
||||
|
||||
## Boundaries — read but do NOT modify
|
||||
|
||||
- `public/resources/ecology/flora/species/*.json` — flora schema. Bind
|
||||
to renderer; never alter species records.
|
||||
- `public/resources/ecology/fauna/species/*.json` — fauna schema. Same.
|
||||
- `public/games/age-of-dwarves/data/manifests/fauna.json` — Game 1
|
||||
fauna whitelist. Read only.
|
||||
- `public/games/age-of-dwarves/data/deposits/manifest.json` — deposit
|
||||
whitelist. Read only.
|
||||
- `mc-city` / `mc-economy` — terrain yields. Terraformer ensures
|
||||
classification is correct; how a city extracts food/prod/trade is
|
||||
shipwright's call (p1-38).
|
||||
- `mc-combat` — `defense_bonus` and `movement_cost` consumers.
|
||||
- `wild_creature_lair_*.gd` AI — fauna behaviour is shipwright's
|
||||
(p0-17). Renderer-only changes here.
|
||||
|
||||
## Escalation
|
||||
|
||||
- **Climate spec rewrites** (e.g. switching from `cold` to derived T
|
||||
from latitude+altitude) → coordinate with shipwright before merging:
|
||||
changes `mc-climate` invariants validated by p0-31's batch tests.
|
||||
- **Ecology schema additions** (new flora/fauna fields) → coordinate
|
||||
with whoever owns ecology authoring; currently no claimed lead.
|
||||
- **Headless rendering breakage** — if hydrology/flora rendering
|
||||
crashes the headless GUT pipeline → escalate to simulator-infra.
|
||||
- **Game 2 / Game 3 scope creep** — `g2-05` (tectonics-lithology) and
|
||||
`g2-06` (soil derivation) STAY UNOWNED until Game 1 ships. The
|
||||
Terraformer's mandate ends at the Game-1 ecology surface.
|
||||
|
||||
## Cron loop
|
||||
|
||||
Terraformer does NOT run a cron loop initially. The owned objectives
|
||||
get a single `/experts-team` parallel sweep to drive p1-46 + p1-47 +
|
||||
p1-48 + p1-49 to done. p2-49 follows after climate refactor lands.
|
||||
Subsequent work invoked on demand.
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
{
|
||||
"generated_at": "2026-04-30T14:25:49Z",
|
||||
"generated_at": "2026-04-30T22:05:58Z",
|
||||
"totals": {
|
||||
"partial": 10,
|
||||
"oos": 20,
|
||||
"missing": 22,
|
||||
"stub": 1,
|
||||
"done": 111,
|
||||
"in_progress": 1,
|
||||
"total": 165
|
||||
"partial": 11,
|
||||
"stub": 1,
|
||||
"done": 112,
|
||||
"missing": 25,
|
||||
"oos": 22,
|
||||
"total": 172
|
||||
},
|
||||
"objectives": [
|
||||
{
|
||||
|
|
@ -910,6 +910,46 @@
|
|||
"updated_at": "2026-04-30",
|
||||
"summary": "Autoplay batches (`tools/autoplay-batch.sh`) run Godot against the installed GDExtension binary\n(`engine/addons/magic_civ_physics/libmagic_civ_physics.x86_64.so`). When multiple agents or\ndevelopers land Rust changes between batches, the `.so` silently goes stale — the GDScript wrappers\ncall methods that don't exist yet in the binary, producing cryptic errors like:\n\n```\nInvalid call. Nonexistent function 'process_culture_with_modifier' in base 'RefCounted (City)'.\n```\n\nThis was observed on 2026-04-30 during the p1-29 anti-snowball batch cycle when the culture-port\nteammate's `process_culture_with_modifier` and p1-30's `set_map`/`update_tile` GDExt methods were\nlanded after the last build, causing R12 test failures at T22."
|
||||
},
|
||||
{
|
||||
"id": "p1-46",
|
||||
"title": "Terrain Dimensions Lab — fix ridginess, bind 149 flora species, add Whittaker plot",
|
||||
"priority": "p1",
|
||||
"status": "partial",
|
||||
"scope": "game1",
|
||||
"owner": "terraformer",
|
||||
"updated_at": "2026-04-30",
|
||||
"summary": "The Terrain Dimensions Lab at `/world-gen/forest-lab` (lab tab) currently\nclassifies the 17 base biomes and renders cross-tile flora/minerals/fauna\noverlays driven by 4 biome sliders + 3 toggleable overlay layers. Three\nknown gaps:\n\n1. **Ridginess slider has zero effect at default elevation 0.65.** The\n classifier (`terrain.ts:118`) only consults ridginess when\n `elevation > 0.85 ∧ ridginess > 0.92` for the volcano case. Anywhere\n else, the slider does nothing — the user verified this on the live\n lab and flagged it.\n2. **The lab loads 0 of 149 flora species.** Trees / shrubs / ground\n cover are generic per terrain. The 149 species in\n `public/resources/ecology/flora/species/*.json` carry rich schema\n (`biomes[]`, `lineage`, `tags` with layer info, `quality_tier`,\n `canopy_contribution`) that the lab ignores entirely.\n3. **No Whittaker T×P plot inset** — the user can move sliders but has\n no visual map of where they are in biome space."
|
||||
},
|
||||
{
|
||||
"id": "p1-47",
|
||||
"title": "River hydrology — D6 flow analysis, multi-hex lakes, cross-tile rivers",
|
||||
"priority": "p1",
|
||||
"status": "missing",
|
||||
"scope": "game1",
|
||||
"owner": "terraformer",
|
||||
"updated_at": "2026-04-30",
|
||||
"summary": "Water bodies in the current map are per-hex terrain types\n(`ocean`, `coast`, `lake`, `inland_sea`) with no connectivity. Real\ngeographic water is **topological**: rivers are DAGs from headwaters to\nocean, lakes are multi-hex polygons, coastlines are polylines along\nland/water borders.\n\nThe data already encodes this in:\n\n- `public/games/age-of-dwarves/data/terrain/terrain_blends.json` —\n `riverside_forest`, `shore`, `cliff`, `bog_edge` ecotones (cross-tile)\n- 10+ fauna species with `river` / `lake` / `wetland` biomes\n (bald_eagle, alligator, otter, kingfisher, beaver, etc.)\n- 4 riparian flora species: `lotus`, `papyrus`, `giant_water_lily`,\n `pioneer_sedge`\n\nBut there is **no rendering pass** that uses the topology. This\nobjective adds D6 flow-direction analysis on the elevation grid,\ndrainage-area accumulation, lake-basin filling, and a cross-tile\nrenderer that draws rivers as bezier paths through hex edges and lakes\nas multi-hex continuous fills."
|
||||
},
|
||||
{
|
||||
"id": "p1-48",
|
||||
"title": "Flora species renderer — bind 149 species to world-map tile rendering",
|
||||
"priority": "p1",
|
||||
"status": "missing",
|
||||
"scope": "game1",
|
||||
"owner": "terraformer",
|
||||
"updated_at": "2026-04-30",
|
||||
"summary": "`public/resources/ecology/flora/species/*.json` defines **149 species**\nwith rich schema:\n\n- `biomes[]` — which terrain types support the species\n- `tags[]` including layer (`layer_canopy` / `layer_understory` /\n `layer_ground` / `layer_fungal`) and structure (`structure_woody` /\n `conifer` / `broadleaf` / `evergreen`)\n- `lineage` — taxonomic group (`conifers`, `broadleaf_trees`,\n `tropical_broadleaf`, `cacti`, `palms`, `aquatic_plants`,\n `mosses_lichens`, etc.)\n- `quality_tier` (0–10), `canopy_contribution`,\n `undergrowth_contribution`, `fungi_contribution`\n- `drought_tolerance`, `fire_resistance`, `growth_rate`\n\nBut the world-map renderer (`mc-render` or Godot tilemap layer) draws\ngeneric green circles for forest tiles. This objective wires the 149\nspecies data into the canvas / TileMap rendering so a \"forest\" tile in\ntemperate Europe shows oak / beech / birch and a \"forest\" tile in\ntropical climate shows mahogany / teak / strangler_fig — each instance\npicked from the species pool that lists this terrain in its `biomes[]`."
|
||||
},
|
||||
{
|
||||
"id": "p1-49",
|
||||
"title": "Fauna species renderer — 61 Game-1 species visible on encounter and lair tiles",
|
||||
"priority": "p1",
|
||||
"status": "missing",
|
||||
"scope": "game1",
|
||||
"owner": "terraformer",
|
||||
"updated_at": "2026-04-30",
|
||||
"summary": "`public/games/age-of-dwarves/data/manifests/fauna.json` whitelists **61\nGame-1 species** with rich JSON schema in\n`public/resources/ecology/fauna/species/*.json`:\n\n- `domain` (land / air / marine / freshwater)\n- `trophic_level` (apex_predator / predator / herbivore / omnivore)\n- `biomes[]`\n- `prey[]` — actual food-web edges\n- `ecology_tier` (1–10 rarity / strength)\n- `forms_lairs` + `lair_type`\n- `lineage` (canines, ursids, cervids, raptors, etc.)\n- `traits[]` including `size_*`\n\nBut the world-map renderer draws abstract icons for lairs and no\noverlay at all for ambient fauna. This objective wires the species\ndata into the renderer so a wolf lair shows a wolf silhouette, a bear\ncave shows a bear, a harpy nest shows a winged figure."
|
||||
},
|
||||
{
|
||||
"id": "p2-06",
|
||||
"title": "Export pipeline for Windows / macOS / Linux",
|
||||
|
|
@ -1010,6 +1050,26 @@
|
|||
"updated_at": "2026-04-27",
|
||||
"summary": "`AudioManager` (`p0-21`, done) ships 10 SFX events and 6 era-keyed music\ntracks. The current manifest is one stream per id, no variation, no\nfallback chain, and no story for the 91 units / 65 buildings / 600\nfauna species the game ships with — every entity that ever wants a\ndistinct sound has to add a hand-authored entry, which doesn't scale to\nlaunch.\n\nThis objective extends the manifest schema and `audio_manager.gd` so\nthe asset pack tracked by `p2-16` can land cleanly:\n\n* **Variant pools** — an entry can list `streams[]` with 2-3 paths;\n the player picks one uniformly to break repetition.\n* **Pitch jitter** — optional ±X% pitch randomisation per play.\n* **Categorical fallback ladder** — `play_for_entity(entity_id,\n event_kind)` resolves `<entity>.<event>` → `<category>.<event>` →\n `<event>`, so a fresh unit with no bespoke sound automatically routes\n to its category bucket (`unit.melee.attack`, `building.production.complete`,\n `fauna.apex.roar`, etc.). The category is read from existing JSON\n fields (`unit_type` / `category` / `trophic_class`) — no new schema\n fields on units / buildings / wilds.\n* **EventBus expansion** — wire the additional signals that already\n exist on `event_bus.gd` but aren't routed to audio yet\n (`combat_started`, `unit_destroyed`, `unit_promoted`, `city_grew`,\n `city_starved`, `golden_age_started`, `golden_age_ended`,\n `border_expanded`, `culture_researched`, `wild_creature_spawned`,\n `weather_event`, `tech_research_started`).\n\nThis is a **schema-and-code** objective. No `.ogg` files land here —\nthose are `p2-16`'s responsibility, which is `blockedBy: [p2-33]` so\nthe dependency-aware ordering surfaces this work first."
|
||||
},
|
||||
{
|
||||
"id": "g2-05",
|
||||
"title": "Tectonics + lithology axes for procedural map generation (Game 2)",
|
||||
"priority": "p2",
|
||||
"status": "oos",
|
||||
"scope": "game2",
|
||||
"owner": null,
|
||||
"updated_at": "2026-04-30",
|
||||
"summary": "Game 1 ships with elevation as the single geological axis. Game 2's\nexpanded scope (additional races, leylines, planet-scale events) calls\nfor plate-tectonic simulation:\n\n- Per-hex `plate_id`, `plate_type`\n (cratonic / passive_margin / active_margin / volcanic_arc / rift /\n hotspot)\n- `lithology` (granite / basalt / limestone / sandstone / volcanic /\n metamorphic)\n\nDrives mountain shape, mineral suite filtering, soil-order derivation\n(g2-06), and volcanic-event placement."
|
||||
},
|
||||
{
|
||||
"id": "g2-06",
|
||||
"title": "Soil derivation layer — emergent soil order from rock + climate + slope (Game 2)",
|
||||
"priority": "p2",
|
||||
"status": "oos",
|
||||
"scope": "game2",
|
||||
"owner": null,
|
||||
"updated_at": "2026-04-30",
|
||||
"summary": "Game 1's biome classifier has no soil layer; tile yield depends on\nbiome + deposits only. Real ecological behaviour requires soil — a\nMollisol grassland is far more productive than an Aridisol grassland.\n\nSoil is emergent from\n`lithology + mean_T + mean_P + slope + flora_succession_stage + time`\nand outputs one of the 8 USDA soil orders (or simplified subset):\n\n- Mollisol (grassland, deep dark, fertile)\n- Spodosol (boreal, acidic, leached)\n- Oxisol (tropical, ancient, weathered, low nutrient)\n- Aridisol (desert, calcium-rich, shallow)\n- Histosol (peat, saturated)\n- Andisol (volcanic, light, exceptional)\n- Inceptisol (young, weakly developed)\n- Entisol (very young, alluvial)\n\nGame 2 adds the soil layer as a drop-in fold over yield, fertility, and\nflora `growth_rate`."
|
||||
},
|
||||
{
|
||||
"id": "p2-01",
|
||||
"title": "Minimap — fog reflection and unit markers",
|
||||
|
|
@ -1372,13 +1432,13 @@
|
|||
},
|
||||
{
|
||||
"id": "p2-43",
|
||||
"title": "\"Culture research completion event — wire `culture_researched` from Rust to GDScript\"",
|
||||
"title": "\"Culture research live-game pipeline — per-turn GDExt bridge + `culture_researched` emit\"",
|
||||
"priority": "p2",
|
||||
"status": "missing",
|
||||
"scope": "game1",
|
||||
"owner": null,
|
||||
"updated_at": "2026-04-30",
|
||||
"summary": "`EventBus.culture_researched(tradition_id, player_index)` is defined and\n**every downstream consumer is wired** (AudioManager handler, manifest\nentry `culture_researched`, the asset shipped at\n`public/resources/audio/sfx/ui/culture_researched.ogg`). What's missing is\nthe upstream emit.\n\nThe Rust simulator (`src/simulator/crates/mc-turn/src/processor.rs:636-652`)\nalready detects tradition completion via\n`mc_culture::CultureResearchResult::Completed { tech_id, .. }` and writes\nto `player.researched_traditions`. But it does **not** surface a per-event\nrecord on the per-turn result the way tech does\n(`research_events: [{type: \"tech\", id: ...}]`).\n\nConsequence: when an AI player or the human completes a tradition, the\naudio handler `AudioManager._on_culture_researched` never fires. Verified\nby `grep -rn 'culture_researched\\.emit' src/` — zero hits in production\ncode."
|
||||
"summary": "`EventBus.culture_researched(tradition_id, player_index)` is defined and\n**every downstream consumer is wired** (AudioManager handler, manifest\nentry `culture_researched`, the asset shipped at\n`public/resources/audio/sfx/ui/culture_researched.ogg`). What's missing\nturned out to be deeper than the original framing of this objective: the\n**entire per-turn culture-research path doesn't run in the live game**.\n\n### Trace\n\n- `turn_manager.gd:246` calls `_process_culture(player, game_map)`\n- `turn_processor.gd:360 _process_culture` only handles **border\n expansion** via `city.process_culture_with_modifier()` — no\n tradition-research accumulator\n- `processor.rs:604 process_culture_research` (Rust mc-turn) **does**\n drive tradition completion via `mc_culture::CultureResearchResult`,\n but it lives in the bench / legacy-headless path, not in the\n GDScript-driven live-game per-turn\n- Tech has a Rust GDExt method `tech_web.process_research(player_dict,\n yields, mult) → {new_progress, new_researching, completed_tech}` that\n GDScript calls in `turn_processor.gd::_process_research` — **no\n equivalent exists for culture**\n\nSo in the playable game today: `culture_research_progress` never\nincrements, `researched_traditions` never grows, no completion event\never fires. `p1-28` shipped the UI and the data graph but not the\nruntime accumulator."
|
||||
},
|
||||
{
|
||||
"id": "p2-44",
|
||||
|
|
@ -1394,7 +1454,7 @@
|
|||
"id": "p2-45",
|
||||
"title": "\"Player elimination reconciliation — emit `player_eliminated` on every transition\"",
|
||||
"priority": "p2",
|
||||
"status": "missing",
|
||||
"status": "done",
|
||||
"scope": "game1",
|
||||
"owner": null,
|
||||
"updated_at": "2026-04-30",
|
||||
|
|
@ -1430,6 +1490,16 @@
|
|||
"updated_at": "2026-04-30",
|
||||
"summary": "Full-screen summary triggered when the game ends — by victory condition, last-clan-standing, turn-limit, or player resignation. Replaces the world-map HUD with:\n\n- **Hero strip** — outcome banner + winning-clan card + player's-clan card (player-second slot stable across victory/defeat).\n- **Section 1 — Final standings** — Demographics table from p3-06 frozen at final turn, plus `Outcome` and `Score breakdown` columns.\n- **Section 2 — Score graph** — full-game chart from p3-06's Graphs widget with event markers forced on.\n- **Section 3 — Awards** — JSON-driven per-category superlatives.\n- **Section 4 — Timeline** — Histories from p3-06 with fog lifted (every clan visible).\n- **Footer** — View Map · Watch Replay · Save to Archive · Export JSON · Main Menu.\n\nDesign doc: [.project/designs/end-game-summary.md](../designs/end-game-summary.md)."
|
||||
},
|
||||
{
|
||||
"id": "p2-49",
|
||||
"title": "Climate axes refactor — latitude + continentality as first-class per-hex inputs",
|
||||
"priority": "p2",
|
||||
"status": "missing",
|
||||
"scope": "game1",
|
||||
"owner": "terraformer",
|
||||
"updated_at": "2026-04-30",
|
||||
"summary": "`mc-mapgen::sampleCell` (and the design-lab twin in `terrain.ts:213`)\nderives `cold` from\n`abs(row/rows - 0.5) * 2 * (1 - climate)` — an implicit latitude proxy\nthat doesn't expose:\n\n- **Continentality** — distance from ocean, drives seasonal swing and\n base aridity (Siberia vs Ireland)\n- **Seasonality** — latitude amplitude (tropic vs arctic)\n- **Rain shadow** — windward / leeward of mountains (wet Pacific NW\n vs dry Great Basin)\n- **Elevation lapse rate** — ~6.5°C/km cooling\n\nThe classifier consumes the collapsed `cold` value, producing biomes\nthat don't differentiate maritime temperate from continental temperate,\nor windward rainforest from leeward rain shadow.\n\nThis objective decomposes the climate input into independent per-hex\nfields — `latitude`, `continentality`, `prevailing_wind_dir` — then\nderives mean T, mean P, seasonality, evapotranspiration deficit. The\nbiome classifier consumes the derived values, exposing\nmaritime / continental and rain-shadow distinctions at last."
|
||||
},
|
||||
{
|
||||
"id": "g2-01",
|
||||
"title": "Ley lines — Game 2 (Age of Kzzykt)",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue