docs(architecture): amend D-229 with the zone-type selection table (#957)

Record the (ZoningType × economic_role × setting) → ZoneTypeId selection table
for the planetary cascade: base candidate slices per ZoningType refined by
economic_role, a setting tweaker (Maritime/Agricultural/Wilderness — planetary
variants only), and the gap-fill rules (entry-class U-curve at the D-217 Broken
band <2300bps; era per founding_age+prosperity+seed; FloorExtent from D-220
density midpoints; doors deferred to #979). Station-only zone ids are excluded —
they belong to a separate cascade (Q-109).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-05 22:15:56 +02:00
co-authored by Claude Opus 4.8
parent 1909e15edb
commit aaa94152d0
+5 -1
View File
@@ -1603,7 +1603,11 @@ Technical foundation decisions that constrain implementation: engine, client-ser
- `initial_condition: TileCondition` — frozen-amber snapshot from `prosperity_baseline` (D-197/D-217). The rolling condition overlay (D-198) paints *over* this; it never mutates the tag.
- **`FloorExtent { base_floor: i8, floor_count: u8, heights: FloorHeightProfile }`** where `FloorHeightProfile = Uniform(u8) | Variable(Vec<u8>)`. **Q-104 resolution (the D-110 ↔ D-227 bridge):** two pure functions — `floor_at_voxel_z(z) -> Option<i8>` and `voxel_range_for_floor(f) -> Option<(i32,i32)>` — map D-110 floor-index addressing onto D-227 physical voxel-z. Default `Uniform(3)` (3 voxels ≈ 3 m/floor, per Jeroen); a cathedral/hangar is `Uniform(10)`; a mixed-use stack is `Variable([5,3,3,3,3])`. The `Variable` branch carries per-floor memory only when floors actually differ.
- **Rationale:** A typed tag is the single contract that lets the atlas render a building, the guarantee audit validate a district, and Phase 6 seed an interior — all from one frozen object. String stubs cannot carry any of that. Orthogonal fields (what / where / how-tall / who-may-enter / cultural / era / condition) compose without a combinatorial enum explosion, matching D-228's axis discipline at the building scale.
- **Implementation:** Phase 4+ (epic forthcoming). Replaces the stub fields on `BlockSkeleton`/`DistrictSkeleton` in `server/src/simulation/generator.rs`.
- **Implementation:** Phase 4+ (epic forthcoming). Replaces the stub fields on `BlockSkeleton`/`QuarterSkeleton` in `server/src/simulation/generator.rs`.
- **Amended 2026-06-05 (#957 — authored zone-type selection table):** the `(ZoningType + economic_role + seed) → ZoneTypeId` lookup is made concrete for the **planetary** cascade. A third input, **`setting` (SettingType)**, is added as a *tweaker* (not a surface/station switch — station & orbital bodies run a separate cascade per [Q-109](questions-architecture.md#q-109) and own the station-only ids `residential_station`/`extraction_space`/`port_space`/`rural_orbital`, which this table never selects). `zone_type_for(zoning, role, setting, seed)` builds a candidate slice from the base table below, applies the setting tweaker, then deterministically seed-picks one id. Every base cell is non-empty (no empty slices — mirrors D-195's no-zero rule); an unknown role falls back to the ZoningType default.
- **Base table (planetary variants):** Commercial → `[commercial_market, entertainment_hospitality]` (financial→`[diplomatic_elite, commercial_market]`; transit_hub→`[commercial_transit, commercial_market]`; service_mixed→ +`entertainment_venue`). Residential → `[residential_surface]` (agricultural→`[rural_agricultural, rural_pastoral]`; extraction→`[residential_dispersed, residential_surface]`). Industrial → `[industrial_manufacturing, industrial_freight]` (manufacturing→`[industrial_manufacturing, industrial_processing]`; extraction→`[extraction_surface, industrial_processing]`; agricultural→`[industrial_processing]`). Administrative → `[administrative_civil]` (institutional→ +`administrative_judicial, diplomatic_elite`; research→`[research_station, administrative_civil]`; service_mixed→ +`medical_facility`). Transit → `[port_surface]` (transit_hub→`[commercial_transit, port_surface]`; manufacturing|extraction→`[industrial_freight, port_surface]`). Recreational → `[entertainment_venue, entertainment_hospitality]` (research|institutional→ +`archaeological_site`). Restricted → `[security_checkpoint]` (military→`[military_garrison, security_checkpoint, detention_facility]`; research→`[research_station, security_checkpoint]`; institutional→`[detention_facility, security_checkpoint]`). Mixed → `[residential_surface, commercial_market, administrative_civil]`.
- **`setting` tweaker (post-pass):** Maritime/Water → `port_surface``port_maritime` (+`port_fishing` for Transit), `rural_*``rural_aquaculture`, `extraction_surface``extraction_platform`. Agricultural → bias `rural_agricultural`/`rural_pastoral` into Residential/Mixed. Wilderness → surface `wilderness_frontier`/`residential_dispersed` at the frontier. Urban/other → base unchanged.
- **Entry-class U-curve threshold (gap fill):** the "low prosperity on a Commercial zone → BreachOnly" degrade uses the D-217 bands — `prosperity_baseline_bps < 2300` (the D-217 Broken band) → `BreachOnly`. **Era** follows this record as written (`founding_age_years + prosperity_baseline + seed`); the round-3 "distance-to-origin" note is dropped (not in the data model). **FloorExtent** uses the D-220 density-class floor midpoints with seed-jitter within the class range. **Doors** are **not** populated here — `doors: Vec::new()`; door derivation (D-231) is #979.
- **Raised by:** Tyre (schema + FloorExtent/Q-104), Gestalt (BuildingEntryClass, derivation), Miri (flavor_ref), economic-built-world workshop round 2, 2026-05-25.
- **Cross-reference:** [D-142](content.md#d-142) (zone-type taxonomy), [D-096](#d-096) (layout mode), [D-197](#d-197) (prosperity baseline), [D-217](#d-217) (tile condition), [D-110](#d-110) (signed z-levels), [D-227](#d-227) (voxel substrate), [D-101](#d-101) (ZonePalette), [D-028](#d-028) (dialogue access — name disambiguated), [D-230](#d-230), [D-231](#d-231), [D-232](#d-232), [Q-104](questions-architecture.md#q-104) (resolved here)
- **Dissent:** None