Merge remote-tracking branch 'origin/main' into visual
# Conflicts: # docs/design/wireframes/menus/v01-save-load.png
This commit is contained in:
+26
-10
@@ -13,7 +13,7 @@ decisions/ Decision domain files (source of truth for all D/Q/R entri
|
||||
.config/ Configuration files (linters, formatters, CI)
|
||||
.cache/ Local caches for testing/linting (gitignored)
|
||||
docs/ Design, architecture, briefings, workshops
|
||||
db/ SQLite ticketing + decisions database and connectors
|
||||
db/ SQLite schema + seed data (connectors at tooling/db/)
|
||||
```
|
||||
|
||||
Unit tests live inside their respective projects (`server/` uses `#[cfg(test)]` inline + `tests/` directory per D-030). The top-level `tests/` directory is for integration tests that cross the client-server boundary (IPC round-trip, serialization fixtures, divergence tests).
|
||||
@@ -62,11 +62,27 @@ The server must be running before the client connects (subprocess launch will be
|
||||
### Test
|
||||
|
||||
```bash
|
||||
make test # Run all tests
|
||||
make test-server # cargo test in server/
|
||||
make test-client # gdUnit4 tests (headless runner pending)
|
||||
make test # Run all tests (test-server + test-client)
|
||||
make test-server # Rust tests via tests/run-rust (cargo nextest, JSON summary)
|
||||
make test-client # Godot tests via tests/run-godot (gdUnit4 headless, JSON summary)
|
||||
```
|
||||
|
||||
The IPC test layers (D-030) have dedicated targets:
|
||||
|
||||
```bash
|
||||
make test-ipc-fixtures # Layer 1: serialization round-trip fixtures
|
||||
make test-ipc-protocol # Layer 2: mock LocalBridge protocol tests
|
||||
make test-ipc-integration # Layer 3: real subprocess round-trip (+ benchmark when ready)
|
||||
make test-ipc-benchmark # IPC latency benchmark (blocked: #555/#556 handshake)
|
||||
```
|
||||
|
||||
Each `tests/run-*` script outputs a JSON summary to stdout and streams progress to stderr:
|
||||
```json
|
||||
{"suite":"rust","total":42,"passed":42,"failed":0,"duration_ms":1230}
|
||||
```
|
||||
|
||||
All scripts accept `--filter <name>` to run a subset of tests. They are whitelistable for agent use (no TTY prompts, no interactive input).
|
||||
|
||||
Server tests use Rust's built-in test framework with `#[cfg(test)]` inline tests and `tests/` integration tests (D-030). Client tests use gdUnit4 (D-030).
|
||||
|
||||
### Cross-Encoder Fixtures
|
||||
@@ -253,17 +269,17 @@ Key components:
|
||||
|
||||
Use wrapper scripts:
|
||||
```bash
|
||||
db/connectors/sqlite-query "SELECT * FROM tickets WHERE status='open'"
|
||||
db/connectors/sqlite-exec "UPDATE tickets SET status='done' WHERE id=1"
|
||||
tooling/db/sqlite-query "SELECT * FROM tickets WHERE status='open'"
|
||||
tooling/db/sqlite-exec "UPDATE tickets SET status='done' WHERE id=1"
|
||||
```
|
||||
|
||||
## Qdrant / Document Search
|
||||
|
||||
```bash
|
||||
db/connectors/qdrant-search "asymmetric information design"
|
||||
db/connectors/qdrant-index docs/briefings/tyre.md
|
||||
db/connectors/qdrant-health
|
||||
db/connectors/qdrant-count
|
||||
tooling/db/qdrant-search "asymmetric information design"
|
||||
tooling/db/qdrant-index docs/briefings/tyre.md
|
||||
tooling/db/qdrant-health
|
||||
tooling/db/qdrant-count
|
||||
```
|
||||
|
||||
## Decisions System
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,100 @@
|
||||
# Line ID Authoring Guide
|
||||
|
||||
**Decision:** D-084 (dual-namespace line ID scheme)
|
||||
**Resolves:** Q-028 (collision-resistant IDs for auto-generated NPCs)
|
||||
**Ticket:** #544
|
||||
|
||||
---
|
||||
|
||||
## The Short Version
|
||||
|
||||
- **Role pool lines:** Use `{role-slug}_d_{###}` — e.g., `dock-worker_d_001`. These lines are shared by all NPCs with that role. This is the default for all auto-generated NPC content.
|
||||
- **Named NPC lines:** Use `{npc-slug}_d_{###}` — e.g., `kael-davan_d_001`. Unchanged from current practice.
|
||||
- **Instance-specific lines (rare):** Use `{role-slug}-{counter}_d_{###}` — e.g., `dock-worker-07_d_001`. Only needed when a specific generated NPC needs content different from the role pool.
|
||||
|
||||
---
|
||||
|
||||
## How Line IDs Work
|
||||
|
||||
A line ID identifies **content**, not speaker. The speaker is identified by their `StableId` in the history log. So `dock-worker_d_001` being said by 40 different dock workers is correct: the log records `(StableId: 12, dock-worker_d_001)`, `(StableId: 37, dock-worker_d_001)`, etc. No collision.
|
||||
|
||||
This means the role pool approach already handles most cases — the "collision problem" is mainly a concern for the rare case where you want a specific generated NPC to say something *different* from others of the same role.
|
||||
|
||||
---
|
||||
|
||||
## Namespace Reference
|
||||
|
||||
### Named NPC lines (Tier 1 and Tier 2 authored NPCs)
|
||||
|
||||
```
|
||||
Format: {npc-slug}_{content-type}_{###}
|
||||
Example: kael-davan_d_001 (Kael's dialogue line 1)
|
||||
sera-venn_d_015 (Sera's dialogue line 15)
|
||||
pc-smuggler_m_s_001 (Smuggler monologue line 1)
|
||||
```
|
||||
|
||||
File location: One file per NPC (e.g., `dialogue/maintenance-corridors/kael-davan.yaml`)
|
||||
|
||||
Numbering: Sequential within the file. Gaps are acceptable (deleted lines leave permanent gaps). Never reuse a number.
|
||||
|
||||
---
|
||||
|
||||
### Role pool lines (auto-generated NPCs, Tier 3 flat, Tier 2 mundane)
|
||||
|
||||
```
|
||||
Format: {role-slug}_{content-type}_{###}
|
||||
Example: dock-worker_d_001 (any dock worker, dialogue line 1)
|
||||
bar-regular_d_008 (any bar regular, dialogue line 8)
|
||||
transit-worker_d_003 (any transit worker, dialogue line 3)
|
||||
```
|
||||
|
||||
File location: One file per role-at-location (e.g., `dialogue/the-terminal/dock-worker.yaml`)
|
||||
|
||||
These lines are shared by **all instances** of the role. Write them to suit any dock worker, not a specific one.
|
||||
|
||||
---
|
||||
|
||||
### Instance-specific lines (opt-in, rare)
|
||||
|
||||
Use only when the generation system has flagged a specific NPC as needing content that differs from the role pool. Examples: a generated dock worker who is also a triangle member with a specific tell; a generated bar regular who witnessed a specific event.
|
||||
|
||||
```
|
||||
Format: {role-slug}-{zero-padded counter}_{content-type}_{###}
|
||||
Example: dock-worker-07_d_001 (instance 7 of dock-worker role, line 1)
|
||||
bar-regular-02_d_005 (instance 2 of bar-regular role, line 5)
|
||||
```
|
||||
|
||||
The counter (01, 02, ... N) is assigned by the generation system in world-seed-deterministic order. The NPC's generated profile file will tell you which counter to use.
|
||||
|
||||
File location: Same directory as the role pool file, separate file with instance slug as name (e.g., `dialogue/the-terminal/dock-worker-07.yaml`)
|
||||
|
||||
---
|
||||
|
||||
## Quick Decision Guide
|
||||
|
||||
| Situation | ID format to use |
|
||||
|-----------|------------------|
|
||||
| Named authored NPC (Kael, Sera, Voss...) | `{npc-slug}_d_{###}` |
|
||||
| Lines any dock worker can say | `dock-worker_d_{###}` |
|
||||
| Lines any bar regular can say | `bar-regular_d_{###}` |
|
||||
| Generated NPC with specific triangle role | `{role-slug}-{counter}_d_{###}` |
|
||||
| Generated NPC who's just background | `{role-slug}_d_{###}` — no instance ID needed |
|
||||
|
||||
---
|
||||
|
||||
## Schema Compatibility
|
||||
|
||||
The existing ID regex `^[a-z][a-z0-9-]*_[dme]_\d{3}$` accepts all three formats. No schema change is required. The content validator (`make validate-content`) checks for duplicate IDs across all files in a district.
|
||||
|
||||
---
|
||||
|
||||
## Numbering Rules
|
||||
|
||||
1. Start at `001`, increment by 1 for each new line.
|
||||
2. Never reuse a number, even if a line is deleted. Gaps are fine.
|
||||
3. Lines within a single file have a contiguous prefix — `dock-worker_d_001` through `dock-worker_d_042`, etc.
|
||||
4. Cross-file: `kael-davan.yaml` at the terminal and `kael-davan.yaml` at maintenance corridors both use the `kael-davan_d_###` namespace. Continue numbering from where the other file left off (check the existing files first, use a fresh sequence if the NPC is new to a location).
|
||||
|
||||
---
|
||||
|
||||
*D-084 — authored by Gestalt, Sprint 18*
|
||||
@@ -626,7 +626,7 @@ In a world where everyone is hiding something, the one person who isn't becomes
|
||||
**End Pattern Specification.**
|
||||
|
||||
**Files referenced:**
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/copy/wiki/npcs/naia-tamm.md` — Reference implementation
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/copy/decisions/content.md` — D-024 (10-axis model), D-028 (dialogue architecture), D-029 (entanglement ratio), D-032 (separate monologue pools), D-034 (THE FRIEND pattern), D-035 (tag taxonomy)
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/copy/docs/workshops/v01-content-scoping/round2-gestalt.md` — Pattern definitions and NPC mapping
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/copy/docs/workshops/v01-gap-analysis/round2-gestalt.md` — Unified observation system, character identity integration
|
||||
- `/var/mnt/data/projects/settled-reach/copy/wiki/npcs/naia-tamm.md` — Reference implementation
|
||||
- `/var/mnt/data/projects/settled-reach/copy/decisions/content.md` — D-024 (10-axis model), D-028 (dialogue architecture), D-029 (entanglement ratio), D-032 (separate monologue pools), D-034 (THE FRIEND pattern), D-035 (tag taxonomy)
|
||||
- `/var/mnt/data/projects/settled-reach/copy/docs/workshops/v01-content-scoping/round2-gestalt.md` — Pattern definitions and NPC mapping
|
||||
- `/var/mnt/data/projects/settled-reach/copy/docs/workshops/v01-gap-analysis/round2-gestalt.md` — Unified observation system, character identity integration
|
||||
|
||||
@@ -144,7 +144,9 @@ NPCs may reference locations and entities beyond Sova Station. These are real bu
|
||||
|
||||
**Other Krenn System stations:** The Krenn System has two other smaller orbital facilities (mining support station and an administrative relay). They're referenced occasionally in news tickers and operational scheduling. Not relevant to v0.1.
|
||||
|
||||
**The horizon gate:** Sova Station has a connection to the Reach's horizon gate network — the interstellar transport infrastructure. The horizon gate terminal is in the Administrative Hub district, not the Transit District. Characters with legitimate need can book transit to other systems. This connection is what makes Sova relevant to a larger smuggling network; contraband doesn't originate in-system, it comes from elsewhere via horizon gate and moves through Sova's span gate to Velen.
|
||||
**The Krenn Ring (horizon station):** The Krenn System's interstellar connection is the Krenn Ring — a horizon station at approximately 800 AU from the Krenn star, accessible by system vessel (~4–6 days from Station Sova). Horizon stations are ancient orbital installations of unknown origin, self-maintaining, each containing multiple gate apertures connecting to other star systems. The Krenn Ring is not on Station Sova; it is a separate installation in the outer system.
|
||||
|
||||
**The Administrative Hub's interstellar transit facility:** Sova Station's Administrative Hub district houses the transit processing facility for interstellar travel — customs clearance, booking offices, and the shuttle dock for vessels heading to the Krenn Ring. When NPCs or documents refer to "the horizon gate terminal," they mean this processing facility, not a gate aperture on the station itself. Characters with legitimate need book transit here, then travel by shuttle to the Krenn Ring to board. This connection is what makes Sova relevant to a larger smuggling network; contraband doesn't originate in-system, it comes from elsewhere via horizon gate and moves through Sova's span gate to Velen.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -0,0 +1,316 @@
|
||||
# Spatial Layout: Gate Cluster (Span Gate Processing Facility)
|
||||
|
||||
**Ticket:** #153
|
||||
**Date:** 2026-02-25
|
||||
**Author:** Araminta (Visual Designer)
|
||||
**Status:** v0.1 — wireframe quality, unblocks copy and gate cluster NPC authoring
|
||||
|
||||
**Grid:** 1 cell = 1m visual tile (visual grammar §2.1). Simulation operates at 0.5m; each visual tile = 2×2 sim tiles.
|
||||
**Map area:** 40m wide × 32m deep (40×32 visual tiles) + observation gallery on z=2
|
||||
**Zone palette:** Cool institutional grey — Era 3 construction, Commission-grade maintenance (visual grammar §1.1)
|
||||
|
||||
---
|
||||
|
||||
## Spatial Character
|
||||
|
||||
The gate cluster is the newest structure in the Transit District. Era 3 construction: clean sightlines, uniform LED-white overhead lighting, minimal accumulated grime. Commission-monitored and Commission-maintained. Where the Terminal reads as institutional but worn, and the Bar as warm and accumulated, the gate cluster reads as **administered**. The architecture communicates that someone is watching.
|
||||
|
||||
The building is a funnel. The span gate aperture (~15–20m diameter ring) determines the widest point; the passenger and freight flows narrow through processing stages; they emerge into the gate concourse, which opens outward as public space. The spatial logic is deliberate: volume at intake, compression through customs, expansion at public exit.
|
||||
|
||||
Dual-use scheduling is the spatial and operational premise (D-095): freight windows and passenger windows share the single aperture. The "flicker" (90-second mode transition between sequences) is legible to experienced travelers — different lighting cues on the aperture chamber walls mark which mode is active.
|
||||
|
||||
**G-11 entry note:** The detective arrives via this cluster from a Commission shuttle. Workers arrive via the transit platform on the bar side. These are structurally separated entry vectors. The gate cluster is the detective's first experience of the district.
|
||||
|
||||
---
|
||||
|
||||
## Floor Plan
|
||||
|
||||
### z=1 (Ground Floor)
|
||||
|
||||
```
|
||||
N (span gate aperture — external, connects to The Ring)
|
||||
|
|
||||
1111111111222222222233333333334444444
|
||||
1234567890123456789012345678901234567890
|
||||
|
||||
############[APERTURE RING]######### row 01 <- span gate ring (structural boundary)
|
||||
# . . . APERTURE CHAMBER . . . # row 02
|
||||
# . . . . . . . . . . . . . . # row 03 ACCESS: RESTRICTED
|
||||
# . . . . . . . . . . . . . . # row 04 (airlock/transition zone)
|
||||
########[D]##########[D]############ row 05 <- chamber exit doors (freight W, passenger E)
|
||||
|
||||
############################[D]###### row 06 <- freight staging north wall (east door = PAB)
|
||||
# FREIGHT STAGING # PAB # row 07
|
||||
# [FK][FK] [FK][FK] . # . # row 08 ACCESS: private (freight) / semi-public (PAB)
|
||||
# [FK][FK] [FK][FK] . # . # row 09 PAB = Passenger Arrival Buffer
|
||||
# [FK][FK] [FK][FK] . # . # row 10
|
||||
# . . . . . . . . [CT][CT] # . # row 11 <- CT = cargo transporter dock points
|
||||
# . . . . . . . . [CT][CT] # . # row 12 <- PAB merges south into customs at row 13
|
||||
#####[D]####################[D]###### row 13 <- into customs lanes
|
||||
|
||||
###################[D]############### row 14 <- freight customs north entry
|
||||
# FCL | FCL | FCL | FCL | FCL # row 15 ACCESS: semi-private (freight customs)
|
||||
# [TS] | [TS] | [TS] | [TS] | [TS] # row 16 FCL = freight customs lane (5 lanes × 4vt)
|
||||
# || | || | || | || | || # row 17 TS = terminal/scanner station per lane
|
||||
# || | || | || | || | || # row 18 || = cargo lane (4vt wide, column breaks Q4)
|
||||
# [P] | [P] | [P] | [P] | [P] # row 19 P = pillar/LOS anchor (4-tile interval)
|
||||
# . . .|. . . |. . . |. . . |. . . # row 20 <- inspection floor
|
||||
#######|#######[D]####[D]###|######## row 21 <- customs south wall; PCL entry
|
||||
# PCL PCL PCL PCL PCL # row 22 ACCESS: semi-public (pedestrian customs)
|
||||
# [TS] [TS] [TS] [TS] [TS] . . # row 23 PCL = pedestrian customs lanes (3 lanes × 2vt)
|
||||
# [P] . . [P] . . [P] . . # row 24 <- queue markers + pillar anchors
|
||||
# . . . . . . . . . . . . . . . # row 25
|
||||
# . . . . . . . . . . . . . . . # row 26
|
||||
############[D]####[D]############### row 27 <- customs south doors to concourse
|
||||
|
||||
#################################### row 28 <- concourse north wall
|
||||
# . . [B] [B] . . [NT][NT] # row 29 ACCESS: public
|
||||
# . . . . . . . . . . # row 30 B = bench, NT = news ticker
|
||||
# . . [B] [B] . . . . . # row 31
|
||||
# . . . . . . . . [D]SC # row 32 <- staircase (SC) east end; Commission entry
|
||||
#################################### row 33 <- concourse south wall (district entry facade)
|
||||
|
||||
|
|
||||
S (district interior — Terminal forecourt, transition corridor)
|
||||
```
|
||||
|
||||
**Legend:**
|
||||
```
|
||||
# Wall (solid, blocks LOS and movement)
|
||||
. Open walkable floor
|
||||
[D] Doorway (traversable)
|
||||
[APERTURE RING] Span gate ring structure (impassable during transit; open between sequences)
|
||||
FCL Freight customs lane
|
||||
PCL Pedestrian customs lane
|
||||
[TS] Terminal/scanner station (customs clerk workstation)
|
||||
[FK] Freight staging kiosk / forwarder terminal
|
||||
[CT] Cargo transporter dock point (loading/unloading position)
|
||||
[B] Bench (public seating)
|
||||
[NT] News ticker display (wall-mounted)
|
||||
[P] Structural pillar (LOS anchor, column break, gallery support above)
|
||||
SC Staircase to z=2 observation gallery (east end of concourse)
|
||||
PAB Passenger Arrival Buffer (east of freight staging, rows 06–12)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### z=2 (Observation Gallery) — Commission-only
|
||||
|
||||
```
|
||||
N
|
||||
|
|
||||
(above customs lanes — rows 14–27 below)
|
||||
1111111111222222222233333333334444
|
||||
1234567890123456789012345678901234567
|
||||
|
||||
[GALLERY NORTH RAIL — partial glass/grating]
|
||||
################################# <- gallery west and east walls
|
||||
# . . . . GALLERY FLOOR . . . # Commission-only: pristine near-white
|
||||
# [DK][DK] . . . [DK][DK] # DK = observation desk / surveillance kit
|
||||
# . . . . . . . . . . . . . . # floor: #d4d8dc
|
||||
# . . . . . . . . . . . . . . # walls: #e0e4e8
|
||||
# [DK][DK] . . . [DK][DK] #
|
||||
# . . . . . . . . . . . . . . #
|
||||
# . . . . . . . . . . . . . . #
|
||||
# . . . . . . . . . . . . . . #
|
||||
################################# <- gallery south rail (partial glass/grating)
|
||||
|
|
||||
[SC] staircase descends to z=1 concourse east end
|
||||
|
|
||||
S
|
||||
```
|
||||
|
||||
**Gallery dimensions:** 32m wide × 10m deep (32×10 visual tiles). Positioned above the customs lanes (z=1 rows 14–27) and NOT above the concourse or staging zones.
|
||||
|
||||
**Cross-z LOS:** Gallery rail is transparent low wall (glass or metal grating). Observer on z=2 has LOS downward to z=1 customs lanes. Upward LOS from z=1 is blocked except at the staircase opening. Players cannot see gallery occupants from the customs floor unless standing at the staircase.
|
||||
|
||||
**Gallery floor is the customs ceiling** — approximately 4m structural clearance below.
|
||||
|
||||
---
|
||||
|
||||
## Zone Breakdown
|
||||
|
||||
### Zone 1 — Aperture Chamber (rows 01–05)
|
||||
**Dimensions:** 40×4 visual tiles
|
||||
**Access tier:** Restricted (Commission control + gate authority; no public entry)
|
||||
**Purpose:** The transition space between the span gate aperture and the main processing facility. All passengers and freight pass through here immediately after emerging from the span gate. The aperture ring is the physical gate structure — when a transit sequence is active, the ring glows with transit residue (lighting cue for mode). Between sequences, the ring is dark and cold.
|
||||
**NPC traffic:** Gate authority staff (2–3 stationed here per sequence). Arrivals flow through continuously during an active sequence; zero traffic between sequences.
|
||||
**LOS notes:** The chamber is enclosed. No LOS to any other zone except the two exit doors (row 05). Gate authority staff can observe the full chamber volume. No LOS from the staging zones into the chamber.
|
||||
**Key feature:** The "flicker" — the 90-second mode transition between freight and passenger sequences — is physically visible here. Lighting shifts, personnel rotate, cargo equipment is cleared or staged. An observer in the gate concourse (south) can hear the mode change but not see it.
|
||||
|
||||
### Zone 2 — Freight Staging (rows 06–13, west 24 tiles)
|
||||
**Dimensions:** 24×8 visual tiles
|
||||
**Access tier:** Private (authorized freight operators and customs personnel only)
|
||||
**Purpose:** Where inbound freight is offloaded, registered, and staged for the customs inspection lanes. [FK] forwarder terminals are where freight agents log their manifest declarations before the cargo moves to the lanes. [CT] dock points are active during freight windows; they are dormant (low power, no staff) during passenger windows.
|
||||
**NPC traffic:** Busy during freight windows. The operations manager (Triangle NPC) is typically here during active freight sequences — their role is coordinating flow from aperture to customs. Senior freight handlers work the dock points. Sparse during passenger windows.
|
||||
**LOS notes:** Full LOS across the staging floor from the forwarder terminals. The freight customs entry door (row 13) is visible from the staging area. The PAB door (east) is visible but the PAB interior is not.
|
||||
**Key feature:** The operations manager's position here — with LOS to the aperture chamber exits, the staging floor, and the customs entry — is the spatial expression of their authority. They see everything that comes in.
|
||||
|
||||
### Zone 3 — Passenger Arrival Buffer (rows 06–12, east 12 tiles)
|
||||
**Dimensions:** 12×8 visual tiles
|
||||
**Access tier:** Semi-public (arriving passengers only; no unauthorized entry from district side)
|
||||
**Purpose:** Where passengers emerging from the span gate are held in a staging queue before processing through pedestrian customs. Separate from freight staging — the physical separation is the architectural enforcement of D-095's dual-use windows. During a freight window, the PAB is closed; during a passenger window, it fills.
|
||||
**NPC traffic:** Moderated by gate sequence. Full during a passenger window; empty between or during freight windows.
|
||||
**LOS notes:** LOS within the PAB is full. No direct LOS from the district concourse into the PAB — the customs lanes form a visual barrier. A player in the concourse sees only the south face of the customs lane structure.
|
||||
**Key feature:** The detective's entry experience begins here (G-11). Arriving via Commission shuttle during a passenger window, they queue briefly before being waved through customs (or escorted directly to the observation gallery — see staircase at z=1 east end).
|
||||
|
||||
### Zone 4 — Freight Customs Lanes (rows 14–21, west 20 tiles)
|
||||
**Dimensions:** 20×10 visual tiles (5 lanes × 4vt each, within a 20vt-wide zone, rows 14–21)
|
||||
**Access tier:** Semi-private (freight operators entering the district; customs clerk staff)
|
||||
**Purpose:** Processing incoming freight through customs inspection. Five lanes, each 4 visual tiles wide, each staffed by a customs clerk at a [TS] terminal station. [P] pillars at 4-tile intervals serve dual purpose: LOS anchors for the customs floor and structural supports for the observation gallery above.
|
||||
**NPC traffic:** Customs clerks (5, one per lane) are stationed here during freight windows. The Commission inspector (Triangle NPC) circulates among lanes — their social dynamic with the clerks is expressed spatially by where they position themselves during inspections. During passenger windows, lanes are closed (screens down, no staff).
|
||||
**LOS notes:** Clear LOS along each lane from north wall to south wall. The pillar breaks ([P]) interrupt cross-lane LOS at 4-tile intervals — an observer cannot see continuously across all 5 lanes. The gallery rail above (z=2) allows the Commission inspector to observe all lanes simultaneously from elevation. This is the critical asymmetry: floor-level observers have partial LOS; gallery observers have full LOS.
|
||||
**Observation note:** The social triangle's power dynamic is visible in sightlines. The Commission inspector from the gallery sees the customs clerks in their entirety, including which freight forwarders are waved through vs. searched. The floor-level operations manager sees individual lanes but not the full picture. The detective, arriving from the gallery, can observe the customs floor before descending.
|
||||
|
||||
### Zone 5 — Pedestrian Customs Lanes (rows 22–27, east 12 tiles)
|
||||
**Dimensions:** 12×10 visual tiles (3 lanes × 2vt each, with queue space to east, rows 22–27)
|
||||
**Access tier:** Semi-public (arriving passengers processing into the district)
|
||||
**Purpose:** Processing arriving passengers through customs. Three lanes, each 2 visual tiles wide, each with a [TS] scanner station. Queue space runs east of the lane structure. Simpler operation than freight customs — personal items scan, biometric check, manifest tag if applicable.
|
||||
**NPC traffic:** Active only during passenger windows. During freight windows, the customs clerks from PCL rotate to assist with FCL overflow. The Commission inspector may operate from PCL during passenger windows if intelligence suggests surveillance value.
|
||||
**LOS notes:** Narrower lanes mean LOS is more constrained. An observer in the queue can see only the lane directly ahead. From the gate concourse (south), the south face of the customs structure presents as a low partition — passengers emerging from customs are visible from the concourse immediately on exit.
|
||||
**Key feature:** This is where observable inequity happens. The Commission inspector (or a directive they issue) results in one class of traveler being waved through while another is searched. This is visible to anyone in the concourse queue area — including the detective. The spatial proximity of the PCL south wall to the concourse benches [B] means concourse passengers witness the processing of arrivals.
|
||||
|
||||
### Zone 6 — Gate Concourse (rows 28–33)
|
||||
**Dimensions:** 40×8 visual tiles (full building width)
|
||||
**Access tier:** Public (all district residents, workers, and new arrivals)
|
||||
**Purpose:** The public-facing terminus of the gate cluster. Benches [B] for waiting passengers, news ticker [NT] on the east wall for transit schedules and general news, and the primary facade opening to the district south. The staircase (SC) at the east end is the access point to the observation gallery — it is Commission-coded at the base (a discreet panel, not a visible barrier).
|
||||
**NPC traffic:** Variable. Busy when a passenger sequence has just completed (arrivals dispersing). Sparse during freight windows (only workers and officials). The concourse is the natural convergence zone for all district-side personnel who have business at the gate cluster.
|
||||
**LOS notes:** Full east-west LOS across the concourse. The [P] pillars from the customs lanes above do not extend to the concourse floor — the south edge of the customs structure is a visual wall at row 27. From the benches, observers can see the customs exit doors (row 27) and watch arrivals emerge. Cannot see into customs lanes from bench positions.
|
||||
**Key feature:** The social reading zone on arrival. New arrivals (including the detective on their first visit) experience the concourse before moving into the district. The news ticker is a topic generator. The Commission staircase (east end) is present but low-key — coded access does not broadcast itself in Commission-grade facilities.
|
||||
|
||||
### Zone 7 — Observation Gallery (z=2, above zones 4–5)
|
||||
**Dimensions:** 32×10 visual tiles (above the full customs lane section)
|
||||
**Access tier:** Commission-only (staircase coded at z=1 east end of concourse)
|
||||
**Purpose:** The gallery is where the Commission inspector works during active processing sequences. From here, all freight and pedestrian customs lanes are simultaneously observable. Observation desks [DK] with surveillance kit allow real-time customs monitoring, camera feed access, and communication with gate authority staff below. This is the institutional oversight position — the spatial embodiment of Commission authority over district entry.
|
||||
**NPC traffic:** The Commission inspector during work hours. Possibly a second Commission observer (junior) — but sparse. This is not a social space; it is a surveillance position.
|
||||
**LOS notes:** Full LOS down to all customs lanes (z=2 → z=1, through gallery rail). Partial LOS to freight staging (row 13 door visible from gallery north rail). NO LOS to aperture chamber (wall blocks), NO LOS to concourse (gallery south rail is opaque below rail height). Gallery interior has no LOS from the customs floor below — the cross-z asymmetry is deliberate and complete.
|
||||
**Key feature:** The detective's first introduction to this space is via escort through the staircase. The experience of descending from gallery (full picture) to concourse (partial picture) is the spatial tutorial for the information asymmetry theme.
|
||||
|
||||
---
|
||||
|
||||
## Key Observation Positions
|
||||
|
||||
| Position | Code | LOS coverage | Why it matters |
|
||||
|----------|------|-------------|----------------|
|
||||
| Observation gallery (z=2, center) | POS-G1 | All freight + pedestrian customs lanes simultaneously | Commission inspector's domain. Highest-information position in the gate cluster. Asymmetric — not visible from below. |
|
||||
| Freight staging floor (center) | POS-G2 | Aperture chamber exits, freight staging, customs entry door | Operations manager's natural position. Sees intake and output but not gallery or pedestrian lanes. |
|
||||
| Gate concourse benches (rows 29-30, west) | POS-G3 | Customs exit doors (row 27), staircase base (east), full concourse | Player's first investigation position. Passive observation of arrivals emerging from customs and who accesses the staircase. |
|
||||
| Pedestrian customs queue (row 22, east) | POS-G4 | PCL lanes, customs exit direction | Observer in queue can watch the customs clerks processing arrivals. Visible inequity in who is waved through vs. searched. |
|
||||
| Concourse east end (near staircase) | POS-G5 | Staircase access panel, anyone ascending/descending | Monitoring staircase access reveals Commission movement. Coded panel is discreet but observable. |
|
||||
| Gallery north rail (z=2) | POS-G6 | Freight staging floor through rail, customs lane north entries | Extended north-viewing position from gallery — tracks cargo from aperture exit to lane entry. |
|
||||
|
||||
---
|
||||
|
||||
## Sightline Analysis
|
||||
|
||||
```
|
||||
FROM → Aperture Frt.Stg. PAB Frt.Cust. Ped.Cust. Concourse Gallery
|
||||
TO ↓
|
||||
Aperture SELF via door via door NO NO NO NO
|
||||
Frt.Staging via door SELF via door via door NO NO NO
|
||||
PAB via door via door SELF NO NO NO NO
|
||||
Frt.Customs NO via door NO SELF NO via door rail(z2→z1)
|
||||
Ped.Customs NO NO NO NO SELF via door rail(z2→z1)
|
||||
Concourse NO NO NO via door via door SELF NO
|
||||
Gallery NO rail(N) NO rail(full) rail(full) NO SELF
|
||||
|
||||
rail(z2→z1) = LOS from gallery down through transparent rail/grating
|
||||
rail(N) = gallery north rail has partial LOS to freight staging floor
|
||||
NO = wall or z-gap blocks
|
||||
via door = LOS when door open
|
||||
```
|
||||
|
||||
**Critical sightline: Gallery → all customs lanes**
|
||||
The Commission inspector on z=2 has full LOS over every freight and pedestrian customs lane simultaneously. No position on the z=1 customs floor achieves equivalent coverage. This asymmetry is the spatial expression of institutional oversight.
|
||||
|
||||
**Critical sightline gap: Concourse → customs interior**
|
||||
The concourse benches are south of the customs structure. The customs south wall (rows 14–21 for freight, 22–27 for pedestrian) presents as a visual barrier. A player on the benches sees the customs exit doors and emerging arrivals — but not what happens inside the lanes. Investigation of customs behavior requires entering the lanes or reaching the gallery.
|
||||
|
||||
**Critical sightline gap: Gallery → concourse**
|
||||
The gallery south rail is opaque below the rail height. The Commission inspector cannot observe the concourse from the gallery without descending. The gallery is a surveillance position for entry processing, not for the public space.
|
||||
|
||||
---
|
||||
|
||||
## Access Tier Map
|
||||
|
||||
```
|
||||
RESTRICTED PRIVATE SEMI-PRIVATE SEMI-PUBLIC PUBLIC
|
||||
────────── ─────── ──────────── ─────────── ──────
|
||||
Aperture Freight staging Freight customs Ped. customs Concourse
|
||||
chamber (auth. operators) lanes lanes (all)
|
||||
(clerks + (arriving
|
||||
[Gallery z=2: freight ops) passengers)
|
||||
Commission-only]
|
||||
```
|
||||
|
||||
Sequential access enforcement (H-06): A freight operator moving from aperture to district must pass through freight staging → freight customs → concourse. No spatial path skips a tier. Pedestrian arrivals pass through PAB → pedestrian customs → concourse. The two flows are physically separated (west half vs. east half of the building) and join only at the concourse.
|
||||
|
||||
---
|
||||
|
||||
## NPC Traffic Density Annotations
|
||||
|
||||
| Time | Aperture | Frt. Staging | PAB | Frt. Customs | Ped. Customs | Concourse | Gallery |
|
||||
|------|----------|-------------|-----|-------------|-------------|-----------|---------|
|
||||
| Dawn (05-07) | very sparse | very sparse | closed | closed | closed | very sparse | — |
|
||||
| Freight window 1 (07-12) | busy (freight) | busy | closed | busy | closed | moderate | inspector |
|
||||
| Passenger window (12-14) | moderate (pax) | sparse | moderate | closed | moderate | busy | inspector |
|
||||
| Freight window 2 (14-19) | busy (freight) | busy | closed | busy | closed | moderate | inspector |
|
||||
| Passenger window (19-20) | moderate (pax) | sparse | moderate | closed | moderate | busy | inspector |
|
||||
| Evening sparse (20-23) | sparse | sparse | closed | sparse | closed | sparse | varies |
|
||||
| Night (23-05) | very sparse | very sparse | closed | closed | closed | very sparse | — |
|
||||
|
||||
**Flicker windows:** 90-second transition between freight and passenger modes. During this window:
|
||||
- Aperture chamber resets (personnel exchange, lighting shifts, cargo equipment cleared or staged)
|
||||
- All customs lanes briefly closed
|
||||
- Concourse becomes transiently busier as travelers waiting for mode completion gather
|
||||
- The operations manager is most exposed — coordinating the reset, moving between staging and customs entry
|
||||
|
||||
**Detective entry:** Commission shuttles arrive during passenger windows as a matter of protocol. First contact with the district begins in the aperture chamber, proceeds to the PAB, and typically diverts to the gallery staircase before customs processing is required.
|
||||
|
||||
---
|
||||
|
||||
## Narrative Triangle Service Notes
|
||||
|
||||
### Triangle 5 — Gate Authority (Operations Manager – Senior Freight Handler – Commission Inspector)
|
||||
|
||||
This is an institutional-oversight triangle, structurally different from the Terminal's knowledge-and-leverage triangles (1–2) and the Bar's social-loyalty triangles (3–4).
|
||||
|
||||
- **Operations manager:** Their domain is the freight flow — aperture to staging to customs. They have private-tier access everywhere on the z=1 floor. They are measured by throughput: how much cargo clears customs in a window. They have an accommodation relationship with certain freight forwarders (see customs inequity below).
|
||||
- **Senior freight handler:** The forwarder who benefits from that accommodation. They know what they get, they know why, and they know the operations manager knows they know. This is the stable complicity leg of the triangle.
|
||||
- **Commission inspector:** Their domain is the gallery. They watch the customs floor from above. They may know about the accommodation, or may be about to discover it, or may be using it as leverage already. Their relationship to the operations manager is formally collaborative, actually adversarial.
|
||||
|
||||
**Spatial expression:** The operations manager never goes to the gallery. The Commission inspector rarely comes to the floor. The senior freight handler is on the floor. The triangle's tension is mediated by the cross-z sightline — the inspector can see the forwarder being waved through, and the operations manager knows the inspector is watching, but neither will acknowledge it in the same zone at the same time.
|
||||
|
||||
**Observable inequity (investigation entry point):** A player watching from the concourse benches (POS-G3) or from the pedestrian customs queue (POS-G4) can observe a freight forwarder being waved through freight customs without search while a commuter on the pedestrian side receives a full scan. This is not dramatic — it reads as normal. The player has to make the connection: waved through = known cargo = manifested incorrectly = this is where the lattice components enter.
|
||||
|
||||
**Tension staging locations:**
|
||||
- Freight staging floor (operations manager's ground; conversations here are authority-neutral)
|
||||
- Gallery (inspector's ground; a summons to the gallery is pressure)
|
||||
- Customs lane (the observable action space; what clerks actually do is determined by unspoken directives from above)
|
||||
- Concourse east end near staircase (the transition space; anyone ascending the staircase must pass anyone watching the staircase)
|
||||
|
||||
---
|
||||
|
||||
## Z-Level Notes
|
||||
|
||||
**z=0:** Not present in the gate cluster. Maintenance access to the gate cluster, if any, is via the district maintenance spine (z=0 elsewhere in district) and does not extend into the gate cluster interior. Era 3 construction has no maintenance corridor integration — maintenance occurs from above via service panels.
|
||||
|
||||
**z=1:** All gate cluster zones: aperture chamber, freight staging, PAB, freight customs, pedestrian customs, concourse. All NPCs and player movement on this level.
|
||||
|
||||
**z=2:** Observation gallery only. Staircase is the sole connection point (z=1 concourse east end ↔ z=2 gallery). Commission-coded access panel at base of staircase is present but low-profile (no visible lock, no visible panel labeling in Era 3 style — access is granted by insertion of Commission neural-tag proximity, not a key).
|
||||
|
||||
**Cross-z visibility rules:**
|
||||
- Gallery → customs lanes: full downward LOS through transparent rail/grating
|
||||
- Customs lanes → gallery: no upward LOS (gallery floor solid except rail; rail height above standing head height)
|
||||
- Staircase opening: local LOS only (see who is at the staircase base or top, not into gallery interior)
|
||||
|
||||
---
|
||||
|
||||
## Notes for Copy Team
|
||||
|
||||
1. **Aperture chamber is the in-world ritual.** Arriving via span gate is Commonwealth-mundane but the aperture ring has residual energy effects — ambient hum, slight color temperature shift as light normalizes from transit. Monologue lines for the detective's arrival should note this. Standard sensory detail for immersive-world arrivals.
|
||||
2. **The customs inequity is not dramatic.** When the senior freight handler is waved through, it should read as routine from NPC behavior — a nod, a scan confirmed, the lane opens. Overheard dialogue, if any, should be procedural: manifest check language, not conversational. The player learns that something is wrong from the pattern, not from a flagrant scene.
|
||||
3. **The Commission inspector's gallery is their professional comfort zone.** Dialogue set in the gallery (if the detective accesses it) should reflect this — the inspector is at ease up here, slightly less guarded. On the floor, they are performing authority. In the gallery, they are just watching.
|
||||
4. **The operations manager on the freight staging floor.** This is their element. Logistics language, shorthand with the senior freight handler. Any casual conversation with the detective here is the operations manager on home turf — helpful enough, not forthcoming.
|
||||
5. **The flicker is an ambient event.** Travelers who know the schedule stop and wait. Travelers who don't know find themselves in a 90-second limbo — nothing is moving, customs is closed. The concourse fills briefly. Use this as a social compression beat: forced proximity, idle waiting, overheard conversations that wouldn't happen mid-flow.
|
||||
6. **The staircase is visible, not obvious.** In Era 3 design language, it is clean, architectural, slightly more refined than the surrounding fittings. It doesn't broadcast Commission. Players who are paying attention will notice it; players who aren't will miss it. Second visit = "wait, I didn't see that last time."
|
||||
@@ -0,0 +1,450 @@
|
||||
# Tier 1 Drama Module — Authoring Guide
|
||||
|
||||
**Schema:** `content/schemas/drama_module.schema.yaml`
|
||||
**Module pool:** `content/modules/tier1/*.yaml`
|
||||
**Decisions:** D-023 (three-tier model), D-027 (vertical slice), D-029 (30/50/20 population), D-034 (FRIEND pattern)
|
||||
**Vertical slice reference:** `content/modules/tier1/smuggling_ring_v0_1.yaml`
|
||||
|
||||
---
|
||||
|
||||
## What Is a Tier 1 Drama Module?
|
||||
|
||||
Tier 1 is the authored conspiracy layer of D-023. Drama modules are the things that can go wrong — or go very right, or simply happen — beneath the surface of daily life in Sova Transit. They are:
|
||||
|
||||
- **Hand-authored.** Every event sequence, every NPC role, every outcome was written by a person.
|
||||
- **Pool-based.** Multiple modules exist. The storyteller draws from the pool at game start and activates a subset based on the district and the storyteller's pacing decisions.
|
||||
- **Optional from the player's perspective.** The player can play 60 minutes without engaging the ring. The ring happens anyway. D-027 criterion #4: the observe→notice→follow→discover sequence must emerge from *systems*, not *scripts*.
|
||||
- **Dual-lens.** Every module must be experienced differently by the smuggler and detective characters. Same world, different keyholes.
|
||||
|
||||
What they are **not:**
|
||||
- Not quests with markers or objectives.
|
||||
- Not scripted cutscenes.
|
||||
- Not balanced challenge encounters.
|
||||
|
||||
The storyteller uses the module as a *schedule* — a series of world events it will fire, and conditions it monitors to determine how the world resolves. The player is a witness and agent in a world that moves with or without them.
|
||||
|
||||
---
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
content/
|
||||
schemas/
|
||||
drama_module.schema.yaml ← Schema reference (this file validates against it)
|
||||
modules/
|
||||
tier1/
|
||||
smuggling_ring_v0_1.yaml ← The v0.1 vertical slice module
|
||||
future_module_v0_1.yaml ← Future modules go here
|
||||
```
|
||||
|
||||
One `.yaml` file per drama module. The storyteller's content loader scans `content/modules/tier1/` at startup and adds all valid modules to the pool.
|
||||
|
||||
---
|
||||
|
||||
## Field Reference
|
||||
|
||||
### Identity Fields
|
||||
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| `module_id` | Yes | Stable slug: `{name}_v{major}_{minor}`. Never reuse. Increment on breaking structural change. |
|
||||
| `display_name` | Yes | Human-readable title for dev tooling. Not shown in-game. |
|
||||
| `version` | Yes | Authoring version: `{major}.{minor}`. |
|
||||
| `tier` | Yes | Always `1`. |
|
||||
| `description` | No | One-paragraph design summary. Authoring-only. |
|
||||
| `notes` | No | Design rationale, cross-references. Ignored at load time. |
|
||||
| `dual_lens` | No | How smuggler vs detective experience this module. Authoring-only. **Write this first** — it disciplines the design. |
|
||||
|
||||
---
|
||||
|
||||
### Pool Metadata
|
||||
|
||||
Controls how the storyteller samples this module.
|
||||
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| `pool.weight` | Yes | Selection probability 1–10. Higher = more likely per playthrough. Default 5. |
|
||||
| `pool.compatible_districts` | No | District slugs. Omit for "any". |
|
||||
| `pool.incompatible_with` | No | Module IDs that can't run concurrently. |
|
||||
| `pool.max_concurrent` | No | Almost always 1. |
|
||||
|
||||
**Design note on weight:** Use weight to tune narrative variety, not difficulty. A weight-1 module is a rare playthrough surprise. A weight-8 module like the smuggling ring is "this is usually what's happening in Sova Transit."
|
||||
|
||||
---
|
||||
|
||||
### Entry Conditions
|
||||
|
||||
Defines when the module becomes eligible for activation. ALL world-state conditions must be true. The activation trigger determines *how* it fires.
|
||||
|
||||
#### World-State Condition Types
|
||||
|
||||
| Type | Required Fields | Use When |
|
||||
|------|----------------|----------|
|
||||
| `npc_present` | `role` | The module requires a specific NPC to be in the district. |
|
||||
| `location_accessible` | `location` | The module requires a location the player can physically reach. |
|
||||
| `fact_not_known` | `fact_id` | Module shouldn't activate if a precondition has already been discovered. |
|
||||
| `no_active_module` | `module_id` | Prevents two incompatible modules running at once. |
|
||||
| `fact_known` | `fact_id`, `known_by` | Module requires prior knowledge to make sense. |
|
||||
|
||||
#### Player Conditions (Optional)
|
||||
|
||||
Player conditions are *optional* — modules can and should activate without player engagement as a prerequisite. Use player conditions sparingly, only when the module literally cannot function without a minimum relationship state.
|
||||
|
||||
#### Activation Triggers
|
||||
|
||||
| Trigger | When to Use |
|
||||
|---------|-------------|
|
||||
| `storyteller_push` | Default. Storyteller activates on its own pacing. Most Tier 1 modules. |
|
||||
| `proximity` | Module activates when player wanders near a key location. Useful for "stumble-upon" conspiracies. |
|
||||
| `player_action` | Reserved for modules that require player initiation. Use rarely. |
|
||||
|
||||
**The `min_play_ticks` field is load-bearing for D-027 criterion #1.** At approximately 1 tick/second, 30 minutes of play ≈ 1800 ticks. Set `min_play_ticks` to at least 1800. The vertical slice uses 2100 to give extra breathing room.
|
||||
|
||||
---
|
||||
|
||||
### NPC Requirements
|
||||
|
||||
Each module specifies its NPC slots. Roles are internal slugs used throughout the rest of the document.
|
||||
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| `role` | Yes | Module-internal slug. Kebab-case. Used in event triggers and outcome conditions. |
|
||||
| `display_hint` | No | Authoring note: who this role is narratively. |
|
||||
| `binding` | Yes | `named` (specific authored NPC) or `generated` (any matching NPC). |
|
||||
| `named_npc` | Conditional | Required when `binding: named`. Short-form canonical ID: `npc:{slug}`. |
|
||||
| `axes` | Conditional | Required when `binding: generated`. Axis constraints the NPC must satisfy. |
|
||||
| `must_have_pattern` | No | Optional NPC pattern (D-024 System A). |
|
||||
| `must_have_motivation` | No | Optional NPC motivation (D-024 System B). |
|
||||
| `is_optional` | No | Default false. If true, module runs without this slot filled (degraded experience). |
|
||||
|
||||
#### Named vs. Generated Bindings
|
||||
|
||||
**Named bindings** reference specific hand-authored NPCs from the district. All v0.1 roles are named. This is the right choice for:
|
||||
- THE FRIEND NPCs (D-034) — they have authored arcs, not generic behavior
|
||||
- NPCs with unique relationships in the 5-triangle web
|
||||
- Roles where voice, history, and moral weight matter
|
||||
|
||||
**Generated bindings** are for future modules set in different districts or using procedurally generated NPCs. They use axis constraints:
|
||||
|
||||
```yaml
|
||||
axes:
|
||||
- axis: secret
|
||||
constraint: has_major_secret
|
||||
- axis: contentment
|
||||
constraint: min_contentment_-3 # Discontented, susceptible to opportunity
|
||||
```
|
||||
|
||||
Constraint conventions: `has_{value}`, `min_{N}`, `not_{value}`. The server's NPC filter system interprets these.
|
||||
|
||||
#### What "Roles" Are Not
|
||||
|
||||
NPC roles in a drama module are **not** the same as NPC patterns (FRIEND, MIRROR, etc.) or motivations (HANDLER, WITNESS, etc.). Module roles are:
|
||||
- Functional slots within the module's narrative (ring-leader, witness, evidence-holder)
|
||||
- Module-local: "ring-leader" in the smuggling ring module ≠ "ring-leader" in any other module
|
||||
- Used to reference the same NPC across events and outcomes without hardcoding the NPC slug
|
||||
|
||||
#### NPC Pattern and Motivation Reference
|
||||
|
||||
Patterns (System A, `must_have_pattern`) encode the NPC's thematic function in the player's experience:
|
||||
|
||||
| Pattern | What It Means |
|
||||
|---------|---------------|
|
||||
| `FRIEND` | Emotionally complex anchor; the contradiction arc lives here (D-034) |
|
||||
| `MIRROR` | Reflects the player character's own path back at them |
|
||||
| `ANCHOR` | Reliable presence; stability the player can always return to |
|
||||
| `GHOST` | Presence felt more than seen; past hangs over current events |
|
||||
| `CATALYST` | Actions cause cascading effects on other NPCs |
|
||||
| `THRESHOLD` | Gatekeeper; controls access to deeper information or relationships |
|
||||
| `REMNANT` | Survivor of a prior event; carries knowledge others want buried |
|
||||
| `SYSTEM` | Embodies an institution or faction rather than personal stakes |
|
||||
| `NOBODY` | Genuinely flat; texture and atmosphere, no arc |
|
||||
|
||||
Motivations (System B, `must_have_motivation`) encode why the NPC acts within the module's conspiracy:
|
||||
|
||||
| Motivation | What It Means |
|
||||
|------------|---------------|
|
||||
| `HANDLER` | Organizes or directs others; the operational center |
|
||||
| `WITNESS` | Knows something they haven't decided to act on |
|
||||
| `TURNCOAT` | Wants out, or has already switched allegiance |
|
||||
| `CIVILIAN` | No conspiracy involvement; proximity creates moral weight |
|
||||
| `OPERATOR` | Executes tasks; functional cog in the system |
|
||||
| `SKEPTIC` | Doubts the conspiracy exists; useful foil for investigation |
|
||||
|
||||
**Full definitions and canonical usage:** `decisions/content.md` D-024.
|
||||
|
||||
---
|
||||
|
||||
### Events
|
||||
|
||||
Events are world-state changes the storyteller fires. They are not scripted player experiences — they happen in the world, and the player may or may not observe them.
|
||||
|
||||
#### Sequences vs. Pools
|
||||
|
||||
| Structure | Use For |
|
||||
|-----------|---------|
|
||||
| **Sequence** | Ordered narrative beats. Step N+1 becomes eligible only after step N fires. Use for character arcs. |
|
||||
| **Pool** | Unordered ambient activity. The storyteller fires any eligible event at any time. Use for texture and background. |
|
||||
|
||||
The vertical slice uses:
|
||||
- `kael_exit_arc` (sequence) — Kael's ordered character arc
|
||||
- `investigation_pressure` (sequence) — Parallel pressure escalation
|
||||
- `ambient_ring_activity` (pool) — Background ring business that runs throughout
|
||||
|
||||
Most modules should have 1-2 sequences plus 1 pool.
|
||||
|
||||
#### Event Step Fields
|
||||
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| `event_id` | Yes | Unique within module. Used in outcome conditions and `ticks_since_event` triggers. |
|
||||
| `label` | No | Short human-readable label for dev tooling. |
|
||||
| `description` | No | What happens narratively. Write this first — events should have a clear observable presence. |
|
||||
| `triggers` | Yes | ANY trigger being true fires the event. Multiple triggers = OR logic. |
|
||||
| `effects` | No | What changes in the world. |
|
||||
| `once` | No | Default `true`. Set `false` for repeating events (ambient discrepancies, etc.). |
|
||||
| `sets_flag` | No | Module-internal flag set when event fires. Used in outcome conditions. |
|
||||
|
||||
#### Trigger Types
|
||||
|
||||
| Type | Fires When | Key Fields |
|
||||
|------|-----------|------------|
|
||||
| `ticks_since_activation` | N ticks after module activated | `ticks` |
|
||||
| `ticks_since_event` | N ticks after a previous event fired | `after_event`, `ticks` |
|
||||
| `player_proximity` | Player near NPC/location | `target_type`, `target`, `radius_tiles` |
|
||||
| `player_action` | Player interacts with target | `action`, `target_role` |
|
||||
| `fact_known_by_player` | Player has discovered a fact | `fact_id` |
|
||||
| `flag_set` | A module flag has been set | `flag` |
|
||||
| `npc_mood` | NPC enters a mood state | `npc_role`, `mood` |
|
||||
|
||||
**Design principle: events should fire without the player.** Every event must have at least one tick-based trigger (`ticks_since_activation` or `ticks_since_event`). Proximity and action triggers are secondary paths that fire the event *earlier* if the player engages. The world moves at its own pace; the player accelerates or delays, not controls.
|
||||
|
||||
#### Effect Types
|
||||
|
||||
| Type | Use For |
|
||||
|------|---------|
|
||||
| `npc_routine_deviation` | Visible NPC behavior change. Write this descriptively — it's what the player sees. |
|
||||
| `fact_becomes_discoverable` | Gates a fact into the knowledge graph at Rumoured confidence. |
|
||||
| `tell_intensify` | NPC's tell behavior becomes more frequent/pronounced. |
|
||||
| `flag_set` | Internal state tracking. Not visible to player. |
|
||||
| `location_state` | Something visible changes in a location. |
|
||||
| `npc_knowledge_update` | An NPC learns something new. |
|
||||
|
||||
**On `fact_becomes_discoverable`:** This makes a fact discoverable, not known. The player still has to find it — through proximity, examination, dialogue, or observation. The `discovery_method` field is an authoring note for how: be specific enough that a Mellanie can write the dialogue or monologue that surfaces it, and a Gestalt can define the trigger condition in the fact catalog.
|
||||
|
||||
**Fact ID convention:** Use `{module-slug}.{fact_name}` — e.g., `ring.kael_unauthorized_corridor_access`. The module slug prefix namespaces the fact to avoid collisions across modules. Before creating a new fact ID, check `content/global/knowledge/` to see if an equivalent fact already exists; reuse it rather than creating a duplicate.
|
||||
|
||||
**Mapping `discovery_method` to D-035 trigger types:** The `discovery_method` note should describe exactly how the player triggers fact discovery. This maps directly to the D-035 monologue trigger taxonomy (full list in `decisions/content.md` D-035 and `content/global/enums/triggers.yaml`):
|
||||
|
||||
| If discovery happens via… | D-035 trigger type | What to author |
|
||||
|--------------------------|-------------------|----------------|
|
||||
| Player enters the location where something is visible | `enter_location` | Monologue line flagging the anomaly on arrival |
|
||||
| Player watches an NPC doing something unusual | `observe_npc` | Monologue line on NPC observation; dialogue option unlocks |
|
||||
| Player examines an object or terminal | `observe_anomaly` | Examine verb interaction; monologue on result |
|
||||
| Player witnesses two NPCs interacting | `witness_interaction` | Monologue line; trust-gated gossip unlock |
|
||||
| Player finishes a conversation with the relevant NPC | `post_conversation` | Monologue beat after talking to the NPC |
|
||||
| Player discovers a physical object (cargo, message) | `discover_evidence` | Examine verb; monologue on discovery |
|
||||
| Player returns to a location they've been before | `return_visit` | Monologue on changed state vs. prior visit |
|
||||
|
||||
Write the `discovery_method` note to specify which of these applies — ideally two methods for redundancy (e.g., `enter_location` plus `observe_anomaly`) so players aren't funneled into a single approach.
|
||||
|
||||
---
|
||||
|
||||
### Outcomes
|
||||
|
||||
Outcomes are resolution states. The storyteller checks all outcome conditions each tick after the module activates. The first matching outcome is applied.
|
||||
|
||||
**Every module must include:**
|
||||
- At least one terminal outcome that represents "the investigation succeeded"
|
||||
- At least one terminal outcome that represents "the conspiracy ran its course"
|
||||
- Exactly one expiry outcome (`is_expiry: true`) for quiet player non-engagement
|
||||
|
||||
#### Outcome Fields
|
||||
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| `outcome_id` | Yes | Unique slug. |
|
||||
| `label` | Yes | Short label. |
|
||||
| `is_terminal` | Yes | `true` = module ends. `false` = transitional state (module can continue evolving). |
|
||||
| `is_expiry` | No | `true` = this is the quiet-exit outcome. One per module. |
|
||||
| `conditions` | No | ALL conditions must be true. See below. |
|
||||
| `effects` | No | World changes when outcome is reached. |
|
||||
|
||||
**On `is_terminal: false`:** A non-terminal outcome fires its effects and applies its label, but the module remains active — the storyteller keeps checking for the next matching outcome. Use this for intermediate states where the world has visibly shifted but the situation hasn't resolved: the `ring_splinters` outcome in the vertical slice is non-terminal because the ring going quiet is a change of state, not a conclusion. A module with only non-terminal outcomes will run forever; always ensure there is a reachable terminal outcome (or expiry) downstream.
|
||||
|
||||
#### Outcome Conditions
|
||||
|
||||
| Condition | Description |
|
||||
|-----------|-------------|
|
||||
| `facts_known` | Player must know all listed facts. |
|
||||
| `facts_not_known` | Player must NOT know any listed facts. |
|
||||
| `flags_set` | All listed module flags must be set. |
|
||||
| `flags_not_set` | None of listed flags may be set. |
|
||||
| `events_fired` | All listed events must have fired. |
|
||||
| `ticks_since_activation` | Module has been running for at least N ticks. |
|
||||
|
||||
#### Outcome Effects
|
||||
|
||||
| Type | Description |
|
||||
|------|-------------|
|
||||
| `npc_disposition` | NPC's relationship state with player shifts. |
|
||||
| `faction_reaction` | Faction reputation change. |
|
||||
| `location_access_change` | Location becomes restricted, locked, or open. |
|
||||
| `fact_state` | Fact is permanently known, hidden, or destroyed. |
|
||||
| `npc_exit` | NPC leaves the district or becomes inaccessible. |
|
||||
|
||||
---
|
||||
|
||||
## Design Principles for Tier 1 Modules
|
||||
|
||||
### 1. The World Moves First
|
||||
|
||||
Events happen on a tick schedule. The player is a witness who can accelerate, delay, or redirect — not a trigger. If your module can only function if the player takes specific actions, it's a quest, not a drama module.
|
||||
|
||||
### 2. Both Characters Must Have a Story
|
||||
|
||||
Every event and outcome must mean something different to the smuggler and the detective. Write the `dual_lens` authoring field first. If you can't write both lenses, the module is character-agnostic filler — not Tier 1.
|
||||
|
||||
### 3. No Clean Resolutions
|
||||
|
||||
D-034 and D-027 both require moral ambiguity. The smuggling ring doesn't have a "good" ending. The detective arresting Kael is not obviously better than letting him go. Every outcome must have a cost. If one outcome is obviously correct, you've failed the design.
|
||||
|
||||
### 4. THE FRIEND Contradiction Is the Pivot
|
||||
|
||||
If your module involves a FRIEND-pattern NPC, the observable contradiction (D-034) must be:
|
||||
- **Observable from spatial positioning** — not from dialogue, not from menus
|
||||
- **Ambiguous before context** — the player sees the behavior before they understand what it means
|
||||
- **Irreversible once witnessed** — seeing changes the relationship, even if the player does nothing
|
||||
|
||||
The secret meeting in corridor B-7 is the canonical example. After witnessing it, neither character can pretend they don't know what they saw.
|
||||
|
||||
### 5. Expiry Is Not Failure
|
||||
|
||||
The `module_abandoned` expiry outcome should feel like a natural ending, not a penalty. The world closes around this conspiracy without the player. That's the 70% mundane reality (D-029): most conspiracies don't get protagonists. Write the expiry description to feel melancholy but not punitive.
|
||||
|
||||
### 6. Facts, Not Flags, Drive Investigation
|
||||
|
||||
Facts (from `global/knowledge/`) are the player's knowledge graph. Flags are the storyteller's internal state tracking. The key design question: "Is this something the player knows, or is this something the storyteller tracks?" If the player knows it, it's a fact. If the storyteller tracks it, it's a flag.
|
||||
|
||||
Facts should be discoverable through multiple methods (observation, dialogue, examination, proximity). Never require a single specific action to surface a critical fact.
|
||||
|
||||
---
|
||||
|
||||
## Validation and Format Rules (Gestalt)
|
||||
|
||||
These rules cover the schema's format constraints and the validation gaps that JSON Schema cannot enforce. All of these are also caught by Tier 2 build-time validation (`make validate-content`), but catching them during authoring saves a pipeline run.
|
||||
|
||||
### ID and Slug Formats
|
||||
|
||||
| Field | Regex | Example |
|
||||
|-------|-------|---------|
|
||||
| `module_id` | `^[a-z][a-z0-9-]*_v[0-9]+_[0-9]+$` | `smuggling_ring_v0_1` |
|
||||
| `sequence_id`, `pool_id` | `^[a-z][a-z0-9_-]*$` | `kael_exit_arc` |
|
||||
| `event_id` | `^[a-z][a-z0-9_-]*$` | `kael_goes_cold` |
|
||||
| `outcome_id` | `^[a-z][a-z0-9_-]*$` | `ring_exposed` |
|
||||
| `sets_flag` / flag references | `^[a-z][a-z0-9_-]*$` | `kael_behavior_changed` |
|
||||
| `role` (npc slot) | `^[a-z][a-z0-9-]*$` | `ring-member-exiting` |
|
||||
| `named_npc` | `^npc:[a-z][a-z0-9-]*$` | `npc:kael-davan` |
|
||||
| `version` | `^[0-9]+\\.[0-9]+$` | `0.1` |
|
||||
|
||||
Note the difference: `event_id`, `outcome_id`, `sequence_id`, and flags use underscores and hyphens (`[a-z0-9_-]*`). NPC `role` slugs use hyphens only (`[a-z0-9-]*`). Mixing them in wrong fields will fail schema validation.
|
||||
|
||||
### Flag Naming Convention
|
||||
|
||||
Flags are module-internal state. Every flag name that appears in `sets_flag` on an event **must** also appear in at least one outcome's `flags_set` or `flags_not_set` condition — or the flag serves no purpose. Convention:
|
||||
|
||||
- Use `snake_case` with underscores: `kael_behavior_changed`, `voss_pressure_applied`
|
||||
- Name by what happened, not what it enables: `handler_pressure_applied` not `kael_ready_to_flee`
|
||||
- Flags set by events accumulate — they are never automatically cleared
|
||||
- A flag set by a time-triggered event (not player-triggered) cannot be used as an expiry gate (see "Common Mistakes" below)
|
||||
|
||||
### Axis Constraint Syntax (Generated NPC Bindings)
|
||||
|
||||
The `constraint` field in `axes` is a freeform string. The storyteller's NPC filter interprets it. Convention (author responsibility — schema does not enforce):
|
||||
|
||||
| Prefix | Example | Meaning |
|
||||
|--------|---------|---------|
|
||||
| `has_` | `has_major_secret` | NPC axis value includes this descriptor |
|
||||
| `min_contentment_` | `min_contentment_-3` | Contentment axis value ≤ N (more discontented) |
|
||||
| `not_` | `not_combat_trained` | Axis value does NOT include this descriptor |
|
||||
| `is_` | `is_ring_member` | Boolean flag set on NPC profile |
|
||||
|
||||
### What JSON Schema Cannot Validate (Tier 2 Catches These)
|
||||
|
||||
| Issue | Where to Look | Impact |
|
||||
|-------|--------------|--------|
|
||||
| `fact_id` not defined in `global/knowledge/` | Effect `fact_becomes_discoverable`, outcome `facts_known` | Fact silently never becomes discoverable |
|
||||
| `sets_flag` name not referenced in any outcome condition | Event `sets_flag` | Flag is set but never meaningful |
|
||||
| `flags_set`/`flags_not_set` reference flag never set by any event | Outcome conditions | Condition permanently true or false |
|
||||
| `ticks_since_event.after_event` references unknown event_id | Event trigger | Trigger never fires |
|
||||
| `named_npc` ID doesn't exist in district NPC profiles | NPC requirements | Load-time failure |
|
||||
| Multiple outcomes have `is_expiry: true` | Outcomes list | Undefined storyteller behavior |
|
||||
| `faction` in outcome effects not in `global/factions/` | Outcome effects | Effect silently ignored |
|
||||
|
||||
### The Expiry Condition Pitfall
|
||||
|
||||
This is the most common authoring mistake for expiry outcomes. **The expiry condition must use `facts_not_known`, not `flags_not_set`.** Reason:
|
||||
|
||||
Events with `ticks_since_activation` triggers fire automatically without player engagement. If an auto-firing event sets a flag, and your expiry checks `flags_not_set: [that_flag]`, the expiry condition becomes permanently false after the event fires — the module can never expire quietly.
|
||||
|
||||
**Wrong:**
|
||||
```yaml
|
||||
# kael_goes_cold fires automatically at tick 300, sets kael_behavior_changed
|
||||
# This expiry can never fire after tick 300
|
||||
- outcome_id: module_abandoned
|
||||
is_expiry: true
|
||||
conditions:
|
||||
flags_not_set:
|
||||
- kael_behavior_changed # This flag is always set by tick 300
|
||||
ticks_since_activation: 5400
|
||||
```
|
||||
|
||||
**Correct:**
|
||||
```yaml
|
||||
# facts_not_known gates on player investigative action, not auto-fired events
|
||||
- outcome_id: module_abandoned
|
||||
is_expiry: true
|
||||
conditions:
|
||||
facts_not_known:
|
||||
- "ring.cargo_discrepancy_pattern" # Only known if player examined terminal
|
||||
- "ring.kael_unauthorized_corridor_access" # Only known if player observed Kael
|
||||
ticks_since_activation: 5400
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Checklist Before Submitting a New Module
|
||||
|
||||
- [ ] `module_id` uses correct format and doesn't collide with existing modules
|
||||
- [ ] `dual_lens` is written and shows clearly different experiences per character
|
||||
- [ ] `min_play_ticks` ≥ 1800 (30 minutes at 1 tick/second)
|
||||
- [ ] Every event sequence step has at least one tick-based trigger
|
||||
- [ ] Every `fact_becomes_discoverable` effect has a `discovery_method` note
|
||||
- [ ] The module includes at least one named FRIEND-pattern NPC (for v0.1 modules)
|
||||
- [ ] Expiry outcome is present (`is_expiry: true`) with conditions gated on `facts_not_known`, NOT `flags_not_set`
|
||||
- [ ] All outcomes have been reviewed for moral ambiguity — no "obviously correct" resolution
|
||||
- [ ] `npc_requirements` covers every role referenced in events and outcomes
|
||||
- [ ] All fact IDs used in effects/conditions exist in `global/knowledge/`
|
||||
- [ ] All `sets_flag` names appear in at least one outcome condition
|
||||
- [ ] All `flags_set`/`flags_not_set` names are set by at least one event's `sets_flag`
|
||||
- [ ] `make validate-content` passes
|
||||
|
||||
---
|
||||
|
||||
## Cross-References
|
||||
|
||||
| Topic | Location |
|
||||
|-------|----------|
|
||||
| Three-tier content model | `decisions/content.md` D-023 |
|
||||
| NPC 10-axis model | `decisions/content.md` D-024 |
|
||||
| Vertical slice scope | `decisions/scope.md` D-027 |
|
||||
| Population ratios | `decisions/content.md` D-029 |
|
||||
| THE FRIEND pattern | `decisions/content.md` D-034 |
|
||||
| Smuggling ring module | `content/modules/tier1/smuggling_ring_v0_1.yaml` |
|
||||
| Drama module schema | `content/schemas/drama_module.schema.yaml` |
|
||||
| Fact catalog | `content/global/knowledge/` |
|
||||
| NPC profiles (v0.1) | `content/campaigns/main/systems/krenn/` |
|
||||
| Storyteller stub | `server/src/storyteller/mod.rs` |
|
||||
|
||||
---
|
||||
|
||||
*Ticket #158 — Tier 1 drama module schema. Paula (dramatic structure), Gestalt (schema format), Mellanie (authoring review).*
|
||||
@@ -60,7 +60,7 @@ Main menu, pause, save/load, options.
|
||||
|-----------|---------|-------------------|
|
||||
| [v01-main-menu](menus/v01-main-menu.png) | v0.1 | [D-043](../../../decisions/perception.md#d-043-art-direction--visual-style-functional-warmth) (functional warmth style), [D-027](../../../decisions/scope.md#d-027-vertical-slice--smuggler--detective-two-character-proof) (two-character proof — character select) |
|
||||
| [v01-pause-menu](menus/v01-pause-menu.png) | v0.1 | [D-043](../../../decisions/perception.md#d-043-art-direction--visual-style-functional-warmth) (visual style) |
|
||||
| [v01-save-load](menus/v01-save-load.png) | v0.1 | [D-027](../../../decisions/scope.md#d-027-vertical-slice--smuggler--detective-two-character-proof) (vertical slice), [D-043](../../../decisions/perception.md#d-043-art-direction--visual-style-functional-warmth) (visual style) |
|
||||
| [v01-save-load](menus/v01-save-load.png) | v0.1 | [D-085](../../../decisions/architecture.md#d-085-per-game-save-directory-structure) (per-game save dirs), [D-043](../../../decisions/perception.md#d-043-art-direction--visual-style-functional-warmth) (visual style), [D-027](../../../decisions/scope.md#d-027-vertical-slice--smuggler--detective-two-character-proof) (vertical slice) |
|
||||
| [v10-main-menu](menus/v10-main-menu.png) | v1.0 | [D-043](../../../decisions/perception.md#d-043-art-direction--visual-style-functional-warmth) (visual style), [D-036](../../../decisions/content.md#d-036-sova-transit-district--krenn-system-as-v01-setting) (setting — Sova Transit District), [D-013](../../../decisions/scope.md#d-013-diegetic-insertpoi-navigation-system) (diegetic insert — in-fiction menu) |
|
||||
| [v10-options-full](menus/v10-options-full.png) | v1.0 | [D-043](../../../decisions/perception.md#d-043-art-direction--visual-style-functional-warmth) (visual style), [D-068](../../../decisions/architecture.md#d-068-5-bus-audio-architecture) (5-bus audio — per-bus volume controls), [D-069](../../../decisions/perception.md#d-069-audio-dip-profiles-for-dialogue-and-confrontation) (audio dip profiles) |
|
||||
|
||||
|
||||
@@ -37,156 +37,220 @@
|
||||
"tab-save": {
|
||||
"type": "Rectangle",
|
||||
"left": 140, "top": 116, "width": 120, "height": 32,
|
||||
"fillColor": "#1a2030",
|
||||
"strokeColor": "#c8d0e0",
|
||||
"fillColor": "#0d1018",
|
||||
"strokeColor": "#333340",
|
||||
"corners": [2, 2, 0, 0]
|
||||
},
|
||||
"tab-save-text": {
|
||||
"type": "Text",
|
||||
"left": 156, "top": 125,
|
||||
"text": "SAVE",
|
||||
"fontColor": "#c8d0e0",
|
||||
"fontColor": "#556677",
|
||||
"fontSize": 13
|
||||
},
|
||||
"tab-load": {
|
||||
"type": "Rectangle",
|
||||
"left": 264, "top": 116, "width": 120, "height": 32,
|
||||
"fillColor": "#0d1018",
|
||||
"strokeColor": "#333340",
|
||||
"fillColor": "#1a2030",
|
||||
"strokeColor": "#c8d0e0",
|
||||
"corners": [2, 2, 0, 0]
|
||||
},
|
||||
"tab-load-text": {
|
||||
"type": "Text",
|
||||
"left": 280, "top": 125,
|
||||
"text": "LOAD",
|
||||
"fontColor": "#556677",
|
||||
"fontColor": "#c8d0e0",
|
||||
"fontSize": 13
|
||||
},
|
||||
"save-slot-1-active": {
|
||||
|
||||
"game-1-header": {
|
||||
"type": "Rectangle",
|
||||
"left": 140, "top": 156, "width": 860, "height": 72,
|
||||
"left": 140, "top": 156, "width": 860, "height": 32,
|
||||
"fillColor": "#151a24",
|
||||
"strokeColor": "#333340",
|
||||
"corners": [2, 2, 0, 0]
|
||||
},
|
||||
"game-1-title": {
|
||||
"type": "Text",
|
||||
"left": 152, "top": 165,
|
||||
"text": "\u25bc DETECTIVE \u2014 Day 3 // Sova Transit // last played: today",
|
||||
"fontColor": "#c8d0e0",
|
||||
"fontSize": 12
|
||||
},
|
||||
"game-1-count": {
|
||||
"type": "Text",
|
||||
"left": 920, "top": 165,
|
||||
"text": "3 saves",
|
||||
"fontColor": "#556677",
|
||||
"fontSize": 11
|
||||
},
|
||||
|
||||
"qs-row": {
|
||||
"type": "Rectangle",
|
||||
"left": 158, "top": 192, "width": 842, "height": 62,
|
||||
"fillColor": "#1a2030",
|
||||
"strokeColor": "#c8d8f0",
|
||||
"corners": [2, 2, 2, 2]
|
||||
},
|
||||
"save-slot-1-accent": {
|
||||
"qs-accent": {
|
||||
"type": "Rectangle",
|
||||
"left": 140, "top": 156, "width": 3, "height": 72,
|
||||
"left": 158, "top": 192, "width": 3, "height": 62,
|
||||
"fillColor": "#c8d8f0",
|
||||
"strokeColor": "#c8d8f0"
|
||||
},
|
||||
"slot-1-date": {
|
||||
"qs-label": {
|
||||
"type": "Text",
|
||||
"left": 152, "top": 162,
|
||||
"text": "AUTOSAVE // Day 1, 07:42",
|
||||
"left": 170, "top": 200,
|
||||
"text": "QUICKSAVE // Day 3, 14:22",
|
||||
"fontColor": "#c8d0e0",
|
||||
"fontSize": 13
|
||||
},
|
||||
"qs-location": {
|
||||
"type": "Text",
|
||||
"left": 170, "top": 218,
|
||||
"text": "The Terminal \u2014 afternoon shift",
|
||||
"fontColor": "#8899aa",
|
||||
"fontSize": 12
|
||||
},
|
||||
"qs-timestamp": {
|
||||
"type": "Text",
|
||||
"left": 170, "top": 234,
|
||||
"text": "saved: 2026-02-25 16:31",
|
||||
"fontColor": "#556677",
|
||||
"fontSize": 11
|
||||
},
|
||||
"qs-actions": {
|
||||
"type": "Text",
|
||||
"left": 840, "top": 212,
|
||||
"text": "[Enter] Load\n[F6] Quickload",
|
||||
"fontColor": "#c8d8f0",
|
||||
"fontSize": 11
|
||||
},
|
||||
|
||||
"auto-row": {
|
||||
"type": "Rectangle",
|
||||
"left": 158, "top": 260, "width": 842, "height": 62,
|
||||
"fillColor": "#0e1118",
|
||||
"strokeColor": "#333340",
|
||||
"corners": [2, 2, 2, 2]
|
||||
},
|
||||
"auto-label": {
|
||||
"type": "Text",
|
||||
"left": 170, "top": 268,
|
||||
"text": "AUTOSAVE // Day 3, 13:45",
|
||||
"fontColor": "#8899aa",
|
||||
"fontSize": 13
|
||||
},
|
||||
"auto-location": {
|
||||
"type": "Text",
|
||||
"left": 170, "top": 286,
|
||||
"text": "Corridor B-7",
|
||||
"fontColor": "#556677",
|
||||
"fontSize": 12
|
||||
},
|
||||
"auto-timestamp": {
|
||||
"type": "Text",
|
||||
"left": 170, "top": 302,
|
||||
"text": "saved: 2026-02-25 16:15",
|
||||
"fontColor": "#3a4455",
|
||||
"fontSize": 11
|
||||
},
|
||||
|
||||
"slot-1-row": {
|
||||
"type": "Rectangle",
|
||||
"left": 158, "top": 328, "width": 842, "height": 62,
|
||||
"fillColor": "#0e1118",
|
||||
"strokeColor": "#333340",
|
||||
"corners": [2, 2, 2, 2]
|
||||
},
|
||||
"slot-1-label": {
|
||||
"type": "Text",
|
||||
"left": 170, "top": 336,
|
||||
"text": "SLOT 1 // Day 2, 22:10",
|
||||
"fontColor": "#8899aa",
|
||||
"fontSize": 13
|
||||
},
|
||||
"slot-1-location": {
|
||||
"type": "Text",
|
||||
"left": 152, "top": 180,
|
||||
"text": "The Terminal — morning shift // Detective",
|
||||
"fontColor": "#8899aa",
|
||||
"left": 170, "top": 354,
|
||||
"text": "Hab quarters \u2014 evening",
|
||||
"fontColor": "#556677",
|
||||
"fontSize": 12
|
||||
},
|
||||
"slot-1-timestamp": {
|
||||
"type": "Text",
|
||||
"left": 152, "top": 198,
|
||||
"text": "saved: 2026-02-23 14:31",
|
||||
"fontColor": "#556677",
|
||||
"left": 170, "top": 370,
|
||||
"text": "saved: 2026-02-25 14:48",
|
||||
"fontColor": "#3a4455",
|
||||
"fontSize": 11
|
||||
},
|
||||
"slot-1-actions": {
|
||||
"type": "Text",
|
||||
"left": 860, "top": 175,
|
||||
"text": "[Enter] Overwrite / Load",
|
||||
"fontColor": "#c8d8f0",
|
||||
"fontSize": 12
|
||||
},
|
||||
"save-slot-2": {
|
||||
|
||||
"game-2-header": {
|
||||
"type": "Rectangle",
|
||||
"left": 140, "top": 236, "width": 860, "height": 72,
|
||||
"fillColor": "#0e1118",
|
||||
"left": 140, "top": 404, "width": 860, "height": 32,
|
||||
"fillColor": "#111520",
|
||||
"strokeColor": "#333340",
|
||||
"corners": [2, 2, 2, 2]
|
||||
},
|
||||
"slot-2-date": {
|
||||
"game-2-title": {
|
||||
"type": "Text",
|
||||
"left": 152, "top": 250,
|
||||
"text": "SLOT 2 // Day 1, 06:15",
|
||||
"left": 152, "top": 413,
|
||||
"text": "\u25b6 SMUGGLER \u2014 Day 1 // The Terminal // last played: yesterday",
|
||||
"fontColor": "#8899aa",
|
||||
"fontSize": 13
|
||||
},
|
||||
"slot-2-location": {
|
||||
"type": "Text",
|
||||
"left": 152, "top": 268,
|
||||
"text": "Arrival — entering Sova Transit // Detective",
|
||||
"fontColor": "#556677",
|
||||
"fontSize": 12
|
||||
},
|
||||
"slot-2-timestamp": {
|
||||
"game-2-count": {
|
||||
"type": "Text",
|
||||
"left": 152, "top": 286,
|
||||
"text": "saved: 2026-02-23 13:10",
|
||||
"left": 920, "top": 413,
|
||||
"text": "2 saves",
|
||||
"fontColor": "#3a4455",
|
||||
"fontSize": 11
|
||||
},
|
||||
"save-slot-3": {
|
||||
|
||||
"game-3-header": {
|
||||
"type": "Rectangle",
|
||||
"left": 140, "top": 316, "width": 860, "height": 72,
|
||||
"fillColor": "#0e1118",
|
||||
"left": 140, "top": 444, "width": 860, "height": 32,
|
||||
"fillColor": "#111520",
|
||||
"strokeColor": "#333340",
|
||||
"corners": [2, 2, 2, 2]
|
||||
},
|
||||
"slot-3-date": {
|
||||
"game-3-title": {
|
||||
"type": "Text",
|
||||
"left": 152, "top": 330,
|
||||
"text": "SLOT 3 // Day 1, 07:30",
|
||||
"left": 152, "top": 453,
|
||||
"text": "\u25b6 DETECTIVE \u2014 Day 7 // Sova Transit // last played: Feb 20",
|
||||
"fontColor": "#8899aa",
|
||||
"fontSize": 13
|
||||
},
|
||||
"slot-3-location": {
|
||||
"type": "Text",
|
||||
"left": 152, "top": 348,
|
||||
"text": "Corridor B-7 — Kael spotted // Smuggler",
|
||||
"fontColor": "#556677",
|
||||
"fontSize": 12
|
||||
},
|
||||
"slot-3-timestamp": {
|
||||
"game-3-count": {
|
||||
"type": "Text",
|
||||
"left": 152, "top": 366,
|
||||
"text": "saved: 2026-02-23 12:48",
|
||||
"left": 920, "top": 453,
|
||||
"text": "5 saves",
|
||||
"fontColor": "#3a4455",
|
||||
"fontSize": 11
|
||||
},
|
||||
"empty-slots-label": {
|
||||
|
||||
"footer-note": {
|
||||
"type": "Text",
|
||||
"left": 140, "top": 400,
|
||||
"text": "SLOTS 4-8 — empty",
|
||||
"fontColor": "#2a3040",
|
||||
"fontSize": 12
|
||||
},
|
||||
"save-note": {
|
||||
"type": "Text",
|
||||
"left": 140, "top": 660,
|
||||
"text": "Autosave on: zone transitions, conversation ends, significant events",
|
||||
"left": 140, "top": 660, "width": 860,
|
||||
"text": "Autosave: zone transitions, conversation ends, significant events // F5 quicksave // F6 quickload",
|
||||
"fontColor": "#3a4455",
|
||||
"fontSize": 11
|
||||
"fontSize": 11,
|
||||
"wordWrap": true
|
||||
},
|
||||
"annotation-title": {
|
||||
"type": "Text",
|
||||
"left": 16, "top": 720,
|
||||
"text": "v0.1 SAVE / LOAD SCREEN",
|
||||
"text": "v0.1 SAVE / LOAD \u2014 LOAD TAB (D-085)",
|
||||
"fontColor": "#556677",
|
||||
"fontSize": 11
|
||||
},
|
||||
"annotation-notes": {
|
||||
"type": "Text",
|
||||
"left": 16, "top": 734, "width": 1100,
|
||||
"text": "Tab UI: Save / Load. Slots show: timestamp, in-game time+location, character. Autosave shown separately. Active slot has accent bar. No screenshots in v0.1.",
|
||||
"text": "Games grouped by directory (D-085). Expand to see saves. QUICKSAVE + AUTOSAVE are system slots; manual slots below. SAVE tab shows current game only. F5/F6 global hotkeys for quicksave/quickload.",
|
||||
"fontColor": "#3a4455",
|
||||
"fontSize": 10,
|
||||
"wordWrap": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
# District Topology — Sova Transit District
|
||||
# D-093 spatial layout. D-094 hierarchy: 256×256 vt (4×4 blocks).
|
||||
# North = span gate entry. South-east = tram entry.
|
||||
|
||||
direction: down
|
||||
|
||||
vars: {
|
||||
bg: "#1a1e24"
|
||||
txt: "#c8d0e0"
|
||||
acc: "#c8d8f0"
|
||||
|
||||
pub: "#1a3320"
|
||||
spub: "#2e2a10"
|
||||
spriv: "#2e1a08"
|
||||
priv: "#2a0e0e"
|
||||
comm: "#0e1a2e"
|
||||
neut: "#1e2228"
|
||||
|
||||
s-pub: "#3a8a50"
|
||||
s-spub: "#b8a020"
|
||||
s-spriv: "#c86010"
|
||||
s-priv: "#c02020"
|
||||
s-comm: "#3060c0"
|
||||
s-neut: "#4a5060"
|
||||
}
|
||||
|
||||
# ── LEGEND ──
|
||||
|
||||
legend: Legend {
|
||||
style.fill: ${bg}
|
||||
style.stroke: ${acc}
|
||||
style.font-color: ${txt}
|
||||
style.font-size: 11
|
||||
direction: right
|
||||
|
||||
l1: Public { style.fill: ${pub}; style.stroke: ${s-pub}; style.font-color: ${txt} }
|
||||
l2: Semi-pub { style.fill: ${spub}; style.stroke: ${s-spub}; style.font-color: ${txt} }
|
||||
l3: Semi-priv { style.fill: ${spriv}; style.stroke: ${s-spriv}; style.font-color: ${txt} }
|
||||
l4: Private { style.fill: ${priv}; style.stroke: ${s-priv}; style.font-color: ${txt} }
|
||||
l5: Commission { style.fill: ${comm}; style.stroke: ${s-comm}; style.font-color: ${txt} }
|
||||
}
|
||||
|
||||
# ── NORTH ENTRY: SPAN GATE ──
|
||||
|
||||
span_gate: The Ring\n(span gate aperture) {
|
||||
shape: hexagon
|
||||
style.fill: ${comm}
|
||||
style.stroke: ${s-comm}
|
||||
style.font-color: ${txt}
|
||||
}
|
||||
|
||||
# ── GATE CLUSTER ──
|
||||
|
||||
gate: Gate Cluster · 40×32 vt {
|
||||
style.fill: ${bg}
|
||||
style.stroke: ${s-comm}
|
||||
style.font-color: ${txt}
|
||||
style.border-radius: 4
|
||||
|
||||
aperture: Aperture\n8×4 {
|
||||
style.fill: ${priv}; style.stroke: ${s-priv}; style.font-color: ${txt}
|
||||
}
|
||||
staging: Freight Staging\n24×8 {
|
||||
style.fill: ${priv}; style.stroke: ${s-priv}; style.font-color: ${txt}
|
||||
}
|
||||
pab: Passenger Arrival\n12×8 {
|
||||
style.fill: ${spub}; style.stroke: ${s-spub}; style.font-color: ${txt}
|
||||
}
|
||||
customs: Customs Lanes\n(freight 5×4vt + ped 3×2vt) {
|
||||
style.fill: ${spriv}; style.stroke: ${s-spriv}; style.font-color: ${txt}
|
||||
}
|
||||
concourse: Concourse\n40×8 · PUBLIC {
|
||||
style.fill: ${pub}; style.stroke: ${s-pub}; style.font-color: ${txt}
|
||||
}
|
||||
gallery: Gallery · z=2\n32×10 · COMMISSION {
|
||||
style.fill: ${comm}; style.stroke: ${s-comm}; style.font-color: ${txt}
|
||||
}
|
||||
|
||||
aperture -> staging: freight { style.stroke: ${s-priv} }
|
||||
aperture -> pab: passenger { style.stroke: ${s-spub} }
|
||||
staging -> customs { style.stroke: ${s-spriv} }
|
||||
pab -> customs { style.stroke: ${s-spub} }
|
||||
customs -> concourse { style.stroke: ${s-pub} }
|
||||
concourse -> gallery: "staircase (Commission)" {
|
||||
style.stroke: ${s-comm}; style.stroke-dash: 4
|
||||
}
|
||||
gallery -> customs: "LOS z=2 down" {
|
||||
style.stroke: ${s-comm}; style.stroke-dash: 4
|
||||
}
|
||||
}
|
||||
|
||||
span_gate -> gate.aperture: "dual-use transit\n(90s flicker)" {
|
||||
style.stroke: ${s-comm}
|
||||
}
|
||||
|
||||
# ── TERMINAL ──
|
||||
|
||||
terminal: Terminal · 44×28 vt {
|
||||
style.fill: ${bg}
|
||||
style.stroke: ${s-spriv}
|
||||
style.font-color: ${txt}
|
||||
style.border-radius: 4
|
||||
|
||||
forecourt: Forecourt\n44×4 {
|
||||
style.fill: ${spub}; style.stroke: ${s-spub}; style.font-color: ${txt}
|
||||
}
|
||||
cargo: Cargo Floor + Main Corridor {
|
||||
style.fill: ${spriv}; style.stroke: ${s-spriv}; style.font-color: ${txt}
|
||||
}
|
||||
storage: Restricted Storage\n(single coded door) {
|
||||
style.fill: ${priv}; style.stroke: ${s-priv}; style.font-color: ${txt}
|
||||
}
|
||||
hatch_t: M-HATCH-T {
|
||||
shape: diamond
|
||||
style.fill: ${priv}; style.stroke: ${s-priv}; style.font-color: ${txt}
|
||||
}
|
||||
|
||||
forecourt -> cargo { style.stroke: ${s-spriv} }
|
||||
cargo -> storage: "coded door" { style.stroke: ${s-priv} }
|
||||
storage -> hatch_t { style.stroke: ${s-priv} }
|
||||
}
|
||||
|
||||
gate.concourse -> terminal.forecourt: "district spine (south)" {
|
||||
style.stroke: ${s-pub}
|
||||
}
|
||||
|
||||
# ── TRANSITION CORRIDOR ──
|
||||
|
||||
corridor: Transition Corridor\n~40×6 vt {
|
||||
style.fill: ${spub}
|
||||
style.stroke: ${s-spub}
|
||||
style.font-color: ${txt}
|
||||
style.border-radius: 4
|
||||
}
|
||||
|
||||
terminal.cargo -> corridor: "public route" {
|
||||
style.stroke: ${s-spub}
|
||||
}
|
||||
|
||||
# ── BAR ──
|
||||
|
||||
bar: The Last Shift · 28×22 vt {
|
||||
style.fill: ${bg}
|
||||
style.stroke: ${s-pub}
|
||||
style.font-color: ${txt}
|
||||
style.border-radius: 4
|
||||
|
||||
approach: Bar Approach\n28×3 {
|
||||
style.fill: ${spub}; style.stroke: ${s-spub}; style.font-color: ${txt}
|
||||
}
|
||||
floor: Main Floor\n(corner booth · card table) {
|
||||
style.fill: ${pub}; style.stroke: ${s-pub}; style.font-color: ${txt}
|
||||
}
|
||||
bathroom: Bathroom Corridor\n(east ext.) {
|
||||
style.fill: ${spriv}; style.stroke: ${s-spriv}; style.font-color: ${txt}
|
||||
}
|
||||
backroom: Back Room\n(Lera) {
|
||||
style.fill: ${priv}; style.stroke: ${s-priv}; style.font-color: ${txt}
|
||||
}
|
||||
hatch_b: M-HATCH-B {
|
||||
shape: diamond
|
||||
style.fill: ${priv}; style.stroke: ${s-priv}; style.font-color: ${txt}
|
||||
}
|
||||
|
||||
approach -> floor { style.stroke: ${s-pub} }
|
||||
floor -> bathroom: "east door" { style.stroke: ${s-spriv} }
|
||||
floor -> backroom: "staff only" { style.stroke: ${s-priv} }
|
||||
bathroom -> hatch_b { style.stroke: ${s-priv} }
|
||||
}
|
||||
|
||||
corridor -> bar.approach: "bar-side decompression" {
|
||||
style.stroke: ${s-spub}
|
||||
}
|
||||
|
||||
# ── MAINTENANCE CORRIDOR (z=0) ──
|
||||
|
||||
maint: Maintenance Corridor\n(z=0 · Era 1 · 2vt wide)\nzero public traffic {
|
||||
style.fill: ${priv}
|
||||
style.stroke: ${s-priv}
|
||||
style.font-color: ${txt}
|
||||
style.border-radius: 4
|
||||
style.stroke-dash: 5
|
||||
}
|
||||
|
||||
junc: JUNC-1 {
|
||||
shape: diamond
|
||||
style.fill: ${priv}; style.stroke: ${s-priv}; style.font-color: ${txt}
|
||||
}
|
||||
|
||||
terminal.hatch_t -> maint: "z=1 down z=0" {
|
||||
style.stroke: ${s-priv}; style.stroke-dash: 5
|
||||
}
|
||||
maint -> junc { style.stroke: ${s-priv}; style.stroke-dash: 5 }
|
||||
junc -> bar.hatch_b: "z=0 up z=1" {
|
||||
style.stroke: ${s-priv}; style.stroke-dash: 5
|
||||
}
|
||||
|
||||
# ── SOUTH-EAST ENTRY: TRAM ──
|
||||
|
||||
the_loop: The Loop\n(station tram · 6 districts) {
|
||||
shape: hexagon
|
||||
style.fill: ${neut}
|
||||
style.stroke: ${s-neut}
|
||||
style.font-color: ${txt}
|
||||
}
|
||||
|
||||
platform: Transit Platform\n~12×8 vt · bar-side\n(encounter node) {
|
||||
style.fill: ${pub}
|
||||
style.stroke: ${s-pub}
|
||||
style.font-color: ${txt}
|
||||
style.border-radius: 4
|
||||
}
|
||||
|
||||
the_loop -> platform: "workers arrive here (G-11)" {
|
||||
style.stroke: ${s-neut}
|
||||
}
|
||||
platform -> bar.approach: "adjacent" {
|
||||
style.stroke: ${s-pub}
|
||||
}
|
||||
|
||||
# ── SECTOR 3 ──
|
||||
|
||||
sector3: Sector 3 Residential\n~15×12 vt · Drin/Naia {
|
||||
style.fill: ${spub}
|
||||
style.stroke: ${s-spub}
|
||||
style.font-color: ${txt}
|
||||
style.border-radius: 4
|
||||
}
|
||||
|
||||
sector3 -> terminal.forecourt: "near Terminal" {
|
||||
style.stroke: ${s-spub}; style.stroke-dash: 3
|
||||
}
|
||||
sector3 -> maint: "adjacent to spine" {
|
||||
style.stroke: ${s-neut}; style.stroke-dash: 3
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1006 KiB |
@@ -23,3 +23,4 @@ Historical discussion rounds from the Commonwealth game design process.
|
||||
| 17 | Content Architecture | D-023, D-024, D-025, D-026, D-027, D-028, D-029 | [round-17](round-17-content-architecture.md) |
|
||||
| 18 | v0.1 Gap Analysis Workshop | D-030, D-031, D-032, D-033, D-034, D-035, D-036, D-037, D-038, D-039, D-040 | [round-18](round-18-v01-gap-analysis-workshop.md) |
|
||||
| 19 | Knowledge Graph & Information Boundaries Workshop | D-041, Q-016 resolved, Q-019 partially resolved, Q-024, Q-025, Q-026 | [workshop brief](../workshops/knowledge-graph-information-boundaries/workshop-brief.md), [synthesis](../workshops/knowledge-graph-information-boundaries/round2-synthesis.md) |
|
||||
| 20 | Station District Layout Design (Workshop #153) | D-093, D-094, D-095; Q-040–Q-044 resolved/partially resolved | [round-20](round-20-station-district-layout.md) |
|
||||
|
||||
@@ -791,7 +791,7 @@ This path reduces risk by deferring sync tooling until domain split is validated
|
||||
**End of analysis.**
|
||||
|
||||
**File locations:**
|
||||
- Analysis: `/var/home/jeroenschweitzer/Projects/commonwealth/docs/discussions/decisions-restructure-si.md`
|
||||
- Current monolith: `/var/home/jeroenschweitzer/Projects/commonwealth/DECISIONS.md` (474 lines)
|
||||
- Current schema: `/var/home/jeroenschweitzer/Projects/commonwealth/db/schema.sql`
|
||||
- Analysis: `/var/mnt/data/projects/commonwealth/docs/discussions/decisions-restructure-si.md`
|
||||
- Current monolith: `/var/mnt/data/projects/commonwealth/DECISIONS.md` (474 lines)
|
||||
- Current schema: `/var/mnt/data/projects/commonwealth/db/schema.sql`
|
||||
- Current tickets: 273 total (24 initiatives, 33 epics, 200 stories, 15 tasks, 1 bug)
|
||||
|
||||
@@ -461,12 +461,12 @@ Assign me the sync script, schema additions, and Makefile targets. I can have Ph
|
||||
---
|
||||
|
||||
**File locations referenced:**
|
||||
- This review: `/var/home/jeroenschweitzer/Projects/commonwealth/docs/discussions/decisions-restructure-tyre.md`
|
||||
- Si's analysis: `/var/home/jeroenschweitzer/Projects/commonwealth/docs/discussions/decisions-restructure-si.md`
|
||||
- Qatux's analysis: `/var/home/jeroenschweitzer/Projects/commonwealth/docs/discussions/decisions-restructure-qatux.md`
|
||||
- Current schema: `/var/home/jeroenschweitzer/Projects/commonwealth/db/schema.sql`
|
||||
- Current decisions: `/var/home/jeroenschweitzer/Projects/commonwealth/DECISIONS.md`
|
||||
- Makefile: `/var/home/jeroenschweitzer/Projects/commonwealth/Makefile`
|
||||
- SQLite connector: `/var/home/jeroenschweitzer/Projects/commonwealth/db/connectors/sqlite_connector.py`
|
||||
- This review: `/var/mnt/data/projects/commonwealth/docs/discussions/decisions-restructure-tyre.md`
|
||||
- Si's analysis: `/var/mnt/data/projects/commonwealth/docs/discussions/decisions-restructure-si.md`
|
||||
- Qatux's analysis: `/var/mnt/data/projects/commonwealth/docs/discussions/decisions-restructure-qatux.md`
|
||||
- Current schema: `/var/mnt/data/projects/commonwealth/db/schema.sql`
|
||||
- Current decisions: `/var/mnt/data/projects/commonwealth/DECISIONS.md`
|
||||
- Makefile: `/var/mnt/data/projects/commonwealth/Makefile`
|
||||
- SQLite connector: `/var/mnt/data/projects/commonwealth/db/connectors/sqlite_connector.py`
|
||||
|
||||
**End of technical review.**
|
||||
|
||||
@@ -0,0 +1,663 @@
|
||||
# Round 20: Station District Layout Design — Ticket #153
|
||||
|
||||
**Sprint:** 20 (Shape)
|
||||
**Date:** 2026-02-25
|
||||
**Ticket:** #153 — Station district layout design
|
||||
**Participants:** Gestalt, Miri, Araminta, Tyre, Paula, Ozzie, Qatux (documenter)
|
||||
**Output target:** D-record in `decisions/content.md` or `decisions/architecture.md`
|
||||
**Blocks:** #155, #188
|
||||
|
||||
---
|
||||
|
||||
## Internal Round Structure
|
||||
|
||||
| Internal Round | Topic | Status |
|
||||
|----------------|-------|--------|
|
||||
| Round 1 | Inventory and constraints | Complete — see §1 below |
|
||||
| Round 2 | Topology proposals | Pending |
|
||||
| Round 3 | Convergence and D-record draft | Pending |
|
||||
|
||||
---
|
||||
|
||||
## §1 — ROUND 1: Constraints Summary
|
||||
|
||||
*Compiled by Qatux. Derived from 6 agent contributions: Ozzie, Gestalt, Miri, Tyre, Araminta, Paula.*
|
||||
|
||||
**Lead note (pre-round):** The spatial patterns decided here establish the district template that Q-036's generator will eventually use. Decisions here become architectural precedent — not just v0.1 configuration.
|
||||
|
||||
**Qatux framing:** Constraints below are tagged:
|
||||
- `[v0.1]` — specific to the hand-authored Sova Transit District
|
||||
- `[template]` — generalisable to any future generated district of this type
|
||||
- `[both]` — applies at both levels
|
||||
|
||||
Cross-reference: Q-036 (district skeleton as generator output) tracks where template decisions need formal specification.
|
||||
|
||||
---
|
||||
|
||||
### 1. Hard Constraints
|
||||
*Non-negotiable: confirmed decisions, confirmed technical facts, Paula's structural requirements that block narrative arcs if violated.*
|
||||
|
||||
| # | Constraint | Source | Tag | Cross-ref |
|
||||
|---|------------|--------|-----|-----------|
|
||||
| H-01 | Dual-scale grid: 0.5m sim tiles, 1m visual tiles. All tile counts in this document are **visual tiles** unless noted. | D-066 | both | D-066 |
|
||||
| H-02 | Tile-based movement. All spatial reasoning is discrete. Corridors must be ≥1 visual tile wide; functional spaces ≥2 tiles wide. | D-054 | both | D-054 |
|
||||
| H-03 | Fog zone temperature tint is already decided: Terminal = cool dark, Bar = warm dark, corridors = neutral dark. The gate cluster adds a fourth zone requiring a tint assignment. | D-059 | v0.1 | D-059 |
|
||||
| H-04 | Local map budget: ~150×150 tiles. Tyre confirms current layouts use ≤10% of this budget. Performance is not a binding constraint at current scope. | D-014, Tyre | both | D-014 |
|
||||
| H-05 | Social sites must be connected spaces of 15–40 tiles. | D-025 | template | D-025 |
|
||||
| H-06 | Access tiers must be traversed **sequentially** — public → semi-public → restricted. No spatial path may allow skipping a tier. | Gestalt | template | D-025 |
|
||||
| H-07 | Restricted storage has exactly **one** entrance (the coded door from the cargo floor). No second entrance, no back exit. | Paula | v0.1 | #311 |
|
||||
| H-08 | Maintenance corridor has **zero LOS** from all other spaces. Its interior is not visible from any public or semi-public zone. Detection requires: sound propagation (footsteps on grating) or witness at hatch entry/exit points only. | Paula, smuggling layout | v0.1 | #313 |
|
||||
| H-09 | No third route between Terminal and Bar. Exactly two routes exist: (a) the public transition corridor and (b) the maintenance corridor (ring-only, private). A third route would dissolve the ring's movement asymmetry. | Paula | v0.1 | #313 |
|
||||
| H-10 | Bathroom corridor interior has **zero LOS** from the bar floor. Observer at bar can see only the door, not the interior. | Paula, bar layout | v0.1 | #312 |
|
||||
| H-11 | No private path between manifest processing and supervisor's office. Maret's crossing of the main corridor is a public act with narrative cost — visibility is the spatial mechanism. | Paula, terminal layout | v0.1 | #311 |
|
||||
| H-12 | Chunk size decision required. Tyre recommends **32×32 sim tiles** (= 16×16 visual tiles) as the generation unit. Zone and access-tier boundaries should align to chunk edges where possible. | Tyre | template | D-073, Q-036 |
|
||||
| H-13 | Z-level allocation decision required. Tyre recommends maintenance corridor on **z=0**, bar/terminal structures on **z=1**. No additional z-levels without gameplay justification. | Tyre, Araminta | both | D-049 |
|
||||
|
||||
---
|
||||
|
||||
### 2. Setting Constraints
|
||||
*What the Sova station profile and worldbuilding require.*
|
||||
|
||||
| # | Constraint | Source | Tag |
|
||||
|---|------------|--------|-----|
|
||||
| S-01 | Span gate at Terminal's **north face**. Freight enters from north (inbound cargo from span gate); maintenance exits south. This is directional — north = external transit, south = district interior. | Miri, terminal layout | v0.1 |
|
||||
| S-02 | **Two separate entry vectors** into the district: (a) freight span gate and (b) commuter transit connection. Passengers and freight do not share the same entry point. | Miri | template |
|
||||
| S-03 | Sealed hull-section boundary. The district has a **finite, countable number of choke-point exits** — not open-ended. The player can know all exits. | Miri | template |
|
||||
| S-04 | Sector 3 is a named sub-area of the district with an unresolved ventilation issue. Must be referenced spatially — it has a location, even if not a full social site. | Miri | v0.1 |
|
||||
| S-05 | Maintenance spine is **Era 1 construction** — it predates the current buildings. The spine's route is fixed; buildings were placed around it. This explains: grating floors, cold-white sparse lighting, no Meridian coverage, and why the ring chose it. | Miri | v0.1 |
|
||||
| S-06 | Meridian coverage follows construction era gradient: new construction (gate cluster) = good coverage, mixed era (Terminal, Bar area) = degraded, Era 1 (maintenance spine) = none. | Miri | template |
|
||||
| S-07 | 800 permanent population = compact district. Walking distances are short. Everything is known. | Miri | v0.1 |
|
||||
| S-08 | Back room alley exit leads to the **district edge** (maintenance alley). It is not an interior district route — it accesses the hull boundary, enabling exit without crossing public district space. | Paula, bar layout | v0.1 |
|
||||
| S-09 | Voss does not appear at the bar. The spatial separation of Triangles 1/2 (Terminal-based) from Triangles 3/4 (Bar-adjacent) is architecturally enforced by Voss's absence from the bar. | Paula | v0.1 |
|
||||
| S-10 | Maintenance corridor carries **zero regular traffic**. It must be architecturally believable that no worker has reason to enter — it connects restricted storage to the bar's bathroom corridor. That route has no legitimate use. | Paula | v0.1 |
|
||||
|
||||
---
|
||||
|
||||
### 3. Gameplay Constraints
|
||||
*What the four gameplay loops require from the spatial layout.*
|
||||
|
||||
| # | Constraint | Source | Tag |
|
||||
|---|------------|--------|-----|
|
||||
| G-01 | District must support **four gameplay loops** simultaneously: investigation, social observation, smuggling, daily life. Each loop requires distinct spatial affordances that do not conflict. | Gestalt | template |
|
||||
| G-02 | **Minimum 4–6 social sites** in the district. Confirmed: Terminal (1), Bar (1), Gate cluster (to design, 1). Remaining 1–3 sites are unspecified. | Gestalt | template |
|
||||
| G-03 | **Minimum 2 NPC route convergence points** outside Terminal and Bar — locations where NPCs from different social sites share a path, enabling observation of cross-site relationships. | Gestalt | template |
|
||||
| G-04 | Gate cluster requires its own **social triangle** (≥3 NPCs with conflicting interests). This is not just a transit hub — it is a social site with investigation affordances. | Gestalt | template |
|
||||
| G-05 | **District entry = fork**. Player's first spatial decision is directional: left or right, Terminal or Bar side. Both directions are legitimate from moment one. No forced tutorial path. | Ozzie | template |
|
||||
| G-06 | Transition corridor crossing: **20–25 seconds** at Walk stance. Long enough to be a temporal beat; short enough not to become friction. At Walk (1 tile / 2 ticks, 10 tps) = 5 tiles per second = 100–125 tiles at 20–25s. The corridor as designed (~40m = 40 visual tiles) achieves ~8 seconds — **this is a gap that needs resolving in Round 2** (see Open Tensions T-08). | Ozzie, smuggling layout | v0.1 |
|
||||
| G-07 | Maintenance corridor is a **gradual unlock**, not a sudden discovery. Player should be able to infer its existence (sound, NPC behavior anomaly, spatial hint) before accessing it physically. | Ozzie | template |
|
||||
| G-08 | Every ring-associated location must **read as mundane on first pass**. "Nothing looks wrong" must be achievable without prior knowledge. The ring's spatial design principle (from smuggling layout): same physical space, different player understanding. | Ozzie, smuggling layout | template |
|
||||
| G-09 | Generator district skeleton = **social site positions + access tier topology + traffic routing + observation position set + chokepoint designation**. This is the minimum specification for a generated district to be functional for all four gameplay loops. | Gestalt | template |
|
||||
| G-10 | Zone-chunk alignment: audio zone transitions (D-073) and access tier transitions should coincide with chunk boundaries where possible, enabling the generator to reason about zones at chunk granularity. | Tyre | template |
|
||||
|
||||
---
|
||||
|
||||
### 4. Narrative Constraints
|
||||
*What the five triangle arcs require from the spatial layout.*
|
||||
|
||||
| # | Constraint | Source | Tag |
|
||||
|---|------------|--------|-----|
|
||||
| N-01 | Triangle 4 (Drin–System–Ring) **spans both buildings**. Sera Venn needs a Commission inspection presence at the Terminal — a legitimate reason to be there that doesn't read as suspicious. The spatial layout must provide a Commission inspection point in the Terminal district. | Paula | v0.1 |
|
||||
| N-02 | No private path between manifest processing and supervisor's office (see H-11). Reiterated here: the spatial cost of Maret choosing to act is the *visibility* of crossing the main corridor. | Paula | v0.1 |
|
||||
| N-03 | No second entrance to restricted storage (see H-07). The ring's chokepoint is architectural — not a character choice. | Paula | v0.1 |
|
||||
| N-04 | Bathroom corridor interior zero LOS from bar floor (see H-10). Private ring exchanges in the corridor must be invisible to observers on the bar floor. | Paula | v0.1 |
|
||||
| N-05 | Exactly two routes between Terminal and Bar (see H-09). The public corridor is the ring's exposure; the maintenance corridor is their bypass. A third route dissolves this asymmetry. | Paula | v0.1 |
|
||||
| N-06 | Back room alley exit to district edge (see S-08). Enables ring operational flow from bar side without re-crossing bar floor. | Paula | v0.1 |
|
||||
| N-07 | Voss stays in Terminal spatial zone (see S-09). Triangle 1 and Triangle 2 are Terminal dramas; Triangle 3 is a Bar drama. Voss's absence from the bar is what keeps them separate. | Paula | v0.1 |
|
||||
| N-08 | Maintenance corridor must be genuinely zero-traffic (see S-10). If workers ever had legitimate reason to use it, the ring's use would not be anomalous. | Paula | v0.1 |
|
||||
| N-09 | **Path B discovery** (exploration-heavy investigation path) requires the maintenance hatch to be **discoverable from the break room area**. The terminal layout shows break room (southwest) and restricted storage (south-center) as adjacent structures, but the hatch (M-HATCH-T) opens inside restricted storage, not the break room. This is Paula's key topological issue — see Open Tensions T-01. | Paula | v0.1 |
|
||||
|
||||
---
|
||||
|
||||
### 5. Player Experience Constraints
|
||||
*What feel and navigation require.*
|
||||
|
||||
| # | Constraint | Source | Tag |
|
||||
|---|------------|--------|-----|
|
||||
| P-01 | **Fork at district entry.** First decision is spatial. Terminal to the left, Bar to the right (or some equivalent directionality). The fork must be immediate and legible — no single entry corridor that forces the player through one building first. | Ozzie | template |
|
||||
| P-02 | Transition corridor is a **tonal between-space** — not dead space. Moving through it is a beat of reflection: leaving one social temperature (Terminal = institutional cool), entering another (Bar = warm amber). 20–25s at Walk stance is the target duration. | Ozzie | template |
|
||||
| P-03 | Main corridor at the Terminal must **feel dangerous**. Not literally — no combat threat — but the player should feel observed and out of place if they linger. NPC density, the supervisor's window, the chokepoint geometry all combine to produce this. | Ozzie | v0.1 |
|
||||
| P-04 | Corner booth in the Bar is the **primary investigation observation post**. It must maintain LOS to: entrance, news ticker cluster, bar counter, card table, and back room door. Confirmed by bar layout. Any district modification that disrupts this LOS set breaks the investigation hub. | Ozzie, bar layout | v0.1 |
|
||||
| P-05 | Maintenance corridor discovery should follow an **inference arc**: player hears something, notices NPC timing anomaly, finds the hatch, enters. Discovery should feel like a reveal, not a stumble. | Ozzie | template |
|
||||
| P-06 | The "nothing looks wrong" moment — when the player first realizes the mundane spaces are the criminal infrastructure — should emerge from **accumulated observation**, not a single clue. Spatial design must support layered discovery: visit 1 = normal, visit 2 = curious, visit 3 = understood. | Ozzie | template |
|
||||
|
||||
---
|
||||
|
||||
### 6. Visual / Spatial Constraints
|
||||
*What the tilemap, art direction, and zone palette require.*
|
||||
|
||||
| # | Constraint | Source | Tag |
|
||||
|---|------------|--------|-----|
|
||||
| V-01 | Terminal facade (44m wide) requires a **forecourt** — breathing space between the building face and the transition corridor or district spine. The facade cannot abut a corridor directly. | Araminta | v0.1 |
|
||||
| V-02 | Bar east extension (bathroom corridor, 6m) **faces north**. This fixes the bar's relative orientation: the bathroom corridor opens northward toward the main transit area. The alley exit (south door, row 20 in bar layout) faces the district edge. | Araminta | v0.1 |
|
||||
| V-03 | Transition corridor requires **widening zones** at both ends — spatial decompression before entering the Terminal forecourt and before entering the Bar entry. Narrow corridor expanding to wide forecourt reads as "arrival." | Araminta | template |
|
||||
| V-04 | Gate cluster zone palette: **coolest and newest** in district. Era 3 construction, Commission-grade maintenance. Visually distinct from Terminal (cool grey-navy) and Bar (warm amber). Exact palette TBD in Round 2. | Araminta | v0.1 |
|
||||
| V-05 | **Minimum corridor widths** by type (exact values to be specified in Round 2): maintenance corridor = 2m (confirmed, smuggling layout), transition corridor = 6m (confirmed, smuggling layout), internal building corridors and secondary public corridors = TBD. | Araminta | template |
|
||||
| V-06 | **LOS anchors every ~4 visual tiles** in open spaces. Large open areas (forecourt, cargo floor, bar main floor) need furniture, pillars, kiosks, or fixtures at regular intervals. These serve dual purpose: visual rhythm and gameplay cover/observation points. | Araminta | template |
|
||||
| V-07 | No additional **physical z-levels** unless gameplay-justified. Maintenance corridor on z=0, bar/terminal on z=1. Multi-floor structures require a gameplay reason (investigation access to a floor, combat routing). Cosmetic vertical variation is not sufficient justification. | Araminta, Tyre | both |
|
||||
| V-08 | Zone temperature tints (D-059) must be **distinct and non-overlapping at transition boundaries**. Crossfade handled by D-073 (1.5–2s audio tween at hard tile boundary). Visual fog tint transition should use the same boundary — player should not be in two zone temperatures simultaneously. | D-059, D-073 | template |
|
||||
| V-09 | Generator parameterization: minimum viable generator parameters for spatial layout include **facade width ratio** (building width : forecourt depth), **corridor width minimums by type**, **LOS anchor interval** (tiles between anchor objects in open spaces). | Araminta | template |
|
||||
|
||||
---
|
||||
|
||||
### 7. Open Tensions
|
||||
*Where constraints conflict or are underspecified — these are Round 2 discussion topics.*
|
||||
|
||||
---
|
||||
|
||||
#### T-01 — PRIORITY: Break Room Adjacency / Path B Discovery
|
||||
**What's at stake:** The detective's exploration-heavy investigation path (Path B from smuggling layout) begins with a floor worker in the break room mentioning Kael's odd hours, then the detective physically discovering the maintenance hatch. But the hatch (M-HATCH-T) opens inside *restricted storage*, not the break room. The break room (terminal layout rows 22–26, west) is southwest; restricted storage (rows 27–30, south-center) is south-center. They are adjacent but not connected.
|
||||
|
||||
**Paula's three options:**
|
||||
- **Option A — Shared wall with sound propagation.** Break room and restricted storage share an interior wall. A worker in the break room can hear sounds through the wall that hint at activity in the maintenance corridor (footsteps on grating). Player hears anomaly → investigates restricted storage → discovers hatch.
|
||||
- **Option B — Disused side passage.** A disused (non-traversable) side passage between break room and restricted storage area gives physical proximity to the hatch area without creating a second route to restricted storage.
|
||||
- **Option C — Path B starts on cargo floor.** A worker hears sounds near restricted storage while on the cargo floor (not the break room). Path B's starting location shifts from break room to cargo floor.
|
||||
|
||||
**Why it needs resolving before Round 3:** The option chosen affects the terminal layout (wall topology between zones) and the district layout (is the break room at the southwest corner, or does it need repositioning?). **This is the highest-priority Round 2 discussion item.**
|
||||
|
||||
**Generator implication [template]:** Which option generalizes? Option A (shared wall + sound propagation) is generalisable — it establishes "investigation paths can start with audio anomaly from adjacent zone." Options B and C are more specific to this layout.
|
||||
|
||||
---
|
||||
|
||||
#### T-02 — Gate Cluster Scope and Triangle
|
||||
**What's at stake:** Gestalt requires the gate cluster to be a full social site with its own triangle (≥3 NPCs). Miri requires freight/commuter flow separation at the gate. Together these imply the gate cluster is substantial — a fourth major location, not just a corridor junction. But no scope has been defined: how large? How many zones? What triangle roles?
|
||||
|
||||
**The tension:** A large gate cluster is more content work than a small one. The district tile budget has room, but the content authoring budget (triangles, NPC lines) may not. Round 2 needs a concrete proposal for gate cluster size and triangle composition, or a decision to scope it down.
|
||||
|
||||
**Generator implication [template]:** Gate cluster = entry node in district skeleton. Every freight district has one. The question is whether entry nodes always carry a social triangle or whether that's optional. If Q-036's district skeleton requires a triangle at every social site (Gestalt's minimum is 4–6 sites with triangles), entry nodes need triangle support.
|
||||
|
||||
---
|
||||
|
||||
#### T-03 — Commuter Transit Entry Point Placement
|
||||
**What's at stake:** Miri requires a separate commuter transit connection (not the span gate). This creates a second district entry point. Where it sits relative to the Terminal and Bar has large implications for NPC traffic patterns and ring exposure.
|
||||
|
||||
**Two principal options:**
|
||||
- **Option A — Gate-cluster-integrated.** Commuter transit is adjacent to the span gate — same spatial cluster, separate lanes. All inbound traffic (freight and passenger) arrives in the same zone, then fans out. This simplifies district topology but creates a single convergence point that's easier to monitor.
|
||||
- **Option B — Separate entry point, Bar-side.** Commuter transit hub is on the bar side of the district (near the bar, away from the terminal). Workers arrive near their social space, not their workplace. This produces two active entry zones and richer NPC traffic routing — but complicates ring exposure analysis.
|
||||
|
||||
**Generator implication [template]:** Two-vector entry is Miri's universal freight-district template. The generator needs to know whether the two vectors are co-located (same cluster) or distributed (separate district zones). This is a structural parameter.
|
||||
|
||||
---
|
||||
|
||||
#### T-04 — Remaining Social Sites (1–3 Unidentified)
|
||||
**What's at stake:** Gestalt requires 4–6 social sites. Confirmed: Terminal, Bar, gate cluster = 3. One to three more sites are unspecified.
|
||||
|
||||
**Candidates from existing documentation:**
|
||||
- Commuter transit hub (if Option B from T-03 — separate location with its own social dynamics)
|
||||
- Sector 3 (Miri — named area with ventilation issue; has a location but no defined social site yet)
|
||||
- Maintenance junction node (a secondary gathering point in the maintenance spine? Non-obvious)
|
||||
- A commissary, clinic, or administrative sub-office (generic service space with resident NPCs)
|
||||
|
||||
**What Round 2 needs:** Names and rough positions for the remaining social sites, or a decision to scope to 3 (Terminal + Bar + gate cluster) and justify why that satisfies Gestalt's minimum. Note: 3 may be sufficient if the gate cluster is large enough to function as 1.5 sites.
|
||||
|
||||
**Generator implication [template]:** Social site count is a generator parameter (minimum: 4). The template needs named social site types and their relationship requirements (which types must be adjacent, which must be separated).
|
||||
|
||||
---
|
||||
|
||||
#### T-05 — Transition Corridor Crossing Time
|
||||
**What's at stake:** Ozzie requires 20–25 seconds at Walk stance for the corridor crossing. At Walk (1 tile / 2 ticks, 10 tps = 5 tiles/sec), 20–25 seconds = 100–125 visual tiles. The transition corridor in the smuggling layout is ~40m = 40 visual tiles, achieving only ~8 seconds.
|
||||
|
||||
**Options:**
|
||||
- **Option A — Extend the corridor.** Make the physical transition corridor 100–125 tiles. This is very long (100–125m) and may not fit the station profile ("compact district, 800 population").
|
||||
- **Option B — Accept 8 seconds.** Adjust Ozzie's target to match the physical reality. 8 seconds at Walk is not nothing — it's still a beat. Ozzie's 20–25s may be aspirational rather than hard.
|
||||
- **Option C — Add intermediate spaces.** The transition route includes the forecourt (Terminal side) and entry zone (Bar side). If total route = corridor + forecourt + bar entry area, total walking distance may reach 60–80 tiles (~12–16 seconds). Closer to the target without an implausibly long corridor.
|
||||
|
||||
**Generator implication [template]:** Inter-site transit time is a gameplay parameter. The template should specify minimum/maximum transit time between major social sites, not corridor length directly.
|
||||
|
||||
---
|
||||
|
||||
#### T-06 — Maintenance Spine Route (Era 1 vs. Efficient Path)
|
||||
**What's at stake:** Miri says the maintenance spine predates the buildings (Era 1 construction). If the spine's route is fixed and buildings were placed around it, the maintenance corridor between Terminal and Bar may not run in the most direct path. But the smuggling layout shows a relatively direct corridor connection. Is the route direct (efficient) or wandering (Era 1 authentic)?
|
||||
|
||||
**The tension:** A wandering Era 1 corridor is setting-authentic but adds tile complexity and may not fit cleanly in the district layout. A direct corridor is simpler to lay out but slightly undermines Miri's historical rationale.
|
||||
|
||||
**Generator implication [template]:** Maintenance spine routing is a generator parameter. The template should specify whether maintenance corridors follow the shortest path or use a historically-layered routing algorithm.
|
||||
|
||||
---
|
||||
|
||||
#### T-07 — Corridor Width Minimums (Unspecified)
|
||||
**What's at stake:** Araminta flagged minimum corridor widths by type but did not provide values. Confirmed: maintenance corridor = 2m (2 visual tiles), transition corridor = 6m (6 visual tiles). Unspecified: internal building corridors, secondary public corridors, service alcoves.
|
||||
|
||||
**Round 2 needs:** Explicit minimum widths for each corridor type. These become V-05's specified values and feed into the generator's spatial layout rules.
|
||||
|
||||
---
|
||||
|
||||
#### T-08 — Gate Cluster Zone Temperature Tint
|
||||
**What's at stake:** D-059 assigns zone temperature tints to Terminal (cool dark), Bar (warm dark), corridors (neutral dark). The gate cluster is a fourth zone type requiring a tint. Araminta says it's the "coolest and newest" — suggesting a colder tint than the Terminal. But D-059 already uses "cool dark" for the Terminal. The gate cluster needs a distinct value.
|
||||
|
||||
**Options:** Very cool (near-white institutional), clinical blue-white, or a Commission-grey that reads as "newer" than Terminal's grey-navy.
|
||||
|
||||
**Generator implication [template]:** Zone temperature tint is a per-zone-type parameter. The template needs a tint for each of: logistics-hub, social-venue, transit-corridor, entry-gate. Currently only the first three are decided.
|
||||
|
||||
---
|
||||
|
||||
## §2 — ROUND 2: Cross-Examination and Lead Feedback
|
||||
|
||||
*Compiled by Qatux. Sources: 6 agent Round 2 contributions + lead feedback that resolved T-01 and T-05.*
|
||||
|
||||
---
|
||||
|
||||
### Lead Feedback (resolved before agents responded)
|
||||
|
||||
**Chunk size direction:** Lead prefers larger chunks with a sub-chunk quarter system. Chunks divide into 4 quarters that can merge into one edifice or remain separate. Large civic structures (train stations, government buildings) span multiple chunks. Generator must be top-down: geography → infrastructure → amenities → population → zoning → chunk generation → individual fill. Separate generator architecture workshop required — this is architectural precedent, not v0.1 configuration.
|
||||
|
||||
**Z-level PoC:** Lead mandates one building in the district with a staircase as z-level proof-of-concept. Gate cluster observation gallery selected by consensus — the only unconfirmed location, setting-authentic, investigation-valuable, clean implementation test case. Overrides V-07's "no z-levels without justification" — the PoC IS the justification.
|
||||
|
||||
**T-01 resolved — Option C:** "Hearing through walls is a flimsy core proposition. We don't build out of cardboard." Sound-through-walls is an exception, not a pattern. Detection toolkit is cameras, drones, bugs, maintenance shafts/vents/tunnels. Path B starts on the cargo floor, not the break room. Terminal layout #311 unchanged.
|
||||
|
||||
**T-05 resolved — Careful stance:** Confirmed. Full route at Careful (3.33 tiles/sec per D-053) ≈ 80 tiles = ~24 seconds. Constraint is stance-dependent, not corridor-length-dependent. No layout change needed.
|
||||
|
||||
**Gate/transport lore clarification (S-02 revision):** System gates serve only freight externally. "Commuter transit" = internal station transit (train/tram) from Residential Core. One external entry (span gate). One internal transit stop within the district. T-03 reframed as T-03b: where does the internal transit stop sit?
|
||||
|
||||
**Transport lore questions:** Captured as Q-040–Q-044. All assigned to Miri.
|
||||
|
||||
---
|
||||
|
||||
### Agent Round 2 Positions
|
||||
|
||||
**Ozzie (Player Experience)**
|
||||
- Confirmed T-05 can be satisfied by Careful stance measurement — accepts this resolution
|
||||
- "Strong yes" on G-11 (gate cluster observation gallery as player investigation vantage point)
|
||||
- Flagged V-06 exception: Terminal main corridor should be bare of LOS anchors — the exposure is the gameplay mechanic, not a design oversight. Open spaces that are *meant* to feel dangerous are exempt from the anchor rule
|
||||
- Requested G-08 receive an official name in the D-record (the "nothing looks wrong" principle — mundane face on criminal infrastructure)
|
||||
|
||||
**Gestalt (Systems Design)**
|
||||
- Gate cluster triangle composition: customs officer + freight forwarder + waiting commuter (3 NPCs, distinct interests, credible spatial conflict)
|
||||
- 4th social site = **transit hub** (bar-side internal transit stop has its own NPC population, social dynamics, and convergence function). This resolves T-04 — site count: Terminal + Bar + Gate cluster + Transit hub = 4, satisfying G-02 minimum
|
||||
- G-11 confirmed: observation gallery at z=2 is a valid **investigation vantage point** — qualifies as a gameplay-justified z-level (H-13 / V-07 condition satisfied by lead's PoC directive)
|
||||
|
||||
**Miri (Worldbuilding)**
|
||||
- [PENDING Round 3 — horizon station revision, T-04 position, Commission overlap resolution]
|
||||
- Internal transit stop: bar-side position accepted (workers commute to bar district, then walk to Terminal for shift)
|
||||
- Transport lore model submitted — see Q-040–Q-044 for captured questions
|
||||
|
||||
**Tyre (Technical)**
|
||||
- [PENDING Round 3 — chunk size technical confirmation at 64×64 visual, z-level validation, cross-z shadowcasting spec]
|
||||
|
||||
**Araminta (Visual/Spatial)**
|
||||
- **Corridor width minimums (V-05 now specified):**
|
||||
|
||||
| Corridor type | Width (visual tiles) | Width (meters) |
|
||||
|--------------|---------------------|----------------|
|
||||
| Maintenance corridor | 2 | 2m |
|
||||
| Internal building corridors | 2 | 2m |
|
||||
| Secondary public corridors | 4 | 4m |
|
||||
| Transition corridor | 6 | 6m |
|
||||
| Gate customs lanes | 2 | 2m (per lane) |
|
||||
| Gate concourse | 8 | 8m |
|
||||
| Service alcoves | 1 | 1m |
|
||||
|
||||
- **Gate cluster zone temperature tint:** `#0a1520` — deep institutional cold, distinct from Terminal's cool-grey-navy. Coldest zone in the district
|
||||
- **Gate observation gallery spec:** 4 tiles wide × lane-length, Commission grey-white palette. Gallery floor is z=2; same zone tint as gate cluster ground floor (elevation ≠ new zone)
|
||||
- **Outlier on chunk size:** Araminta prefers 64×64 sim (32×32 visual). Rationale: visual tile is the authoring unit; generator should reason at visual-tile scale. Noted as minority position
|
||||
|
||||
**Paula (Narrative)**
|
||||
- **Gate cluster triangle revised:** operations manager + senior freight handler + Commission inspector (3 NPCs). Rationale: Commission inspector is Sera Venn's institutional peer — this creates the Commission overlap (N-01) without requiring Sera to be permanently stationed at Terminal. Inspector visits = legitimate, scheduled, observable
|
||||
- **T-01 revised:** Path B via restricted storage door, not break room wall. The anomalous sound is footsteps on the maintenance grating, heard through the (imperfect) seal around the restricted storage access door on the cargo floor — not sound through a solid wall. The door is the weak point, not the wall. This preserves Option C without invoking cardboard-wall physics
|
||||
- **Path C confirmed:** A third investigation approach for the detective — the Commission inspection overlap. The Commission inspector (gate cluster triangle NPC) has access to the same manifest anomalies as Maret but reads them as institutional compliance failures, not criminal ones. Detective PC who befriends the inspector gets a different angle on the evidence: institutional rather than human
|
||||
- **Sector 3:** Supports Miri's framing — sub-area adjacent to maintenance spine, ventilation complaint is ambient NPC dialogue, not a full social site
|
||||
- **6 narrative constraints for D-record:** Commission inspector has access to gate cluster AND Terminal (inspection authority crosses building boundaries); inspector's Terminal visits are scheduled (visible, predictable — ring can route around them); Sera is a bar regular who knows the inspector professionally (Triangle 4 cross-link); no NPC in the gate cluster triangle has social connection to Voss (Terminal triangle separation maintained); transit hub NPCs are socially isolated from the Terminal workers (two distinct working cultures); back room alley exit connects to maintenance alley which connects to district edge, NOT to the transit hub service area
|
||||
|
||||
---
|
||||
|
||||
### Round 2 Tension Status
|
||||
|
||||
| Tension | Status after Round 2 | Resolution |
|
||||
|---------|---------------------|------------|
|
||||
| T-01 Break room adjacency | **RESOLVED** | Option C: cargo floor + restricted storage door acoustic gap |
|
||||
| T-02 Gate cluster scope | **RESOLVED** | Two competing triangle compositions (Gestalt vs. Paula) — Round 3 to pick one |
|
||||
| T-03b Transit stop placement | **RESOLVED** | Bar-side — consensus |
|
||||
| T-04 4th social site | **RESOLVED** | Transit hub (bar-side) |
|
||||
| T-05 Corridor crossing time | **RESOLVED** | Careful stance ~24s on ~80-tile route |
|
||||
| T-06 Maintenance spine routing | **RESOLVED** | Direct path for v0.1; wandering routing deferred to generator workshop |
|
||||
| T-07 Corridor widths | **RESOLVED** | Araminta's table (see above) |
|
||||
| T-08 Gate cluster tint | **RESOLVED** | `#0a1520` deep institutional cold |
|
||||
| NC-01 Transit stop placement | **RESOLVED** | Same as T-03b |
|
||||
| NC-02 G-10 chunk alignment | **PARTIALLY RESOLVED** | At 64×64 visual chunks, chunk ≈ zone; G-10 revised accordingly |
|
||||
| NC-03 Gallery tint (z=2) | **RESOLVED** | Same tint as gate cluster ground floor |
|
||||
| NC-04 Sector 3 / maintenance spine | **RESOLVED** | Adjacent; ventilation = ambient NPC dialogue |
|
||||
|
||||
**Remaining for Round 3:** Gate cluster triangle — pick Gestalt's composition or Paula's. Chunk size — confirm 64×64 visual (Tyre analysis pending). Miri's horizon station revision and Commission overlap resolution.
|
||||
|
||||
---
|
||||
|
||||
## §3 — ROUND 3: Convergence
|
||||
|
||||
*Compiled by Qatux. All 6 agents delivered Round 3. All tensions resolved. D-records filed: D-093, D-094, D-095.*
|
||||
|
||||
---
|
||||
|
||||
### Confirmed Consensus
|
||||
|
||||
**T-01 (break room / Path B):** Option C confirmed by lead. Sound anomaly at restricted storage door (cargo floor) → Path B. Paula's refinement accepted: acoustic gap is the door seal, not a wall. No modification to terminal layout #311.
|
||||
|
||||
**T-03b (transit stop):** Bar-side. Unanimous. Creates NPC convergence point at bar entry (satisfies G-03).
|
||||
|
||||
**T-04 (4th social site):** Sector 3 residential (Drin/Naia anchor). Miri's Round 3 revision supersedes the interim Transit Hub consensus. The transit platform (The Loop stop) is reclassified as an encounter node (bar-side convergence point). Site count = 4 (Terminal, Bar, Gate cluster, Sector 3 residential). G-02 minimum satisfied.
|
||||
|
||||
**T-05 (crossing time):** Walk ~13–14s on ~65–70 tile route; Careful stance ~24s. Ozzie confirms. No layout change.
|
||||
|
||||
**T-06 (maintenance spine routing):** Direct path for v0.1. Generator-level concern deferred.
|
||||
|
||||
**T-07 (corridor widths):** Araminta's table confirmed. Filed as V-05 specified values.
|
||||
|
||||
**T-08 (gate cluster tint):** `#0a1222` deep institutional cold (Araminta final). Gallery at z=2 shares ground-floor tint.
|
||||
|
||||
**G-11 (observation gallery as investigation vantage):** Confirmed by Gestalt + Ozzie. The gate cluster observation gallery at z=2 is a designated investigation position — the player can observe arriving cargo from elevation. This is the gameplay justification for the z-level PoC.
|
||||
|
||||
**G-08 naming:** Confirmed name: **"Invisible infrastructure principle"** — every ring location serves a mundane purpose; criminal function is only apparent if you know what to look for. This is the spatial design principle stated in the smuggling layout and now formally named.
|
||||
|
||||
**V-06 exception (main corridor):** The Terminal main corridor is explicitly exempt from the LOS anchor rule. The bare, unobstructed corridor is the gameplay mechanic — exposure IS the design. Araminta confirmed.
|
||||
|
||||
**Gate cluster triangle:** Paula's composition selected — operations manager + senior freight handler + Commission inspector. Rationale: Commission inspector creates the narrative bridge (N-01, Path C, Sera's institutional peer) that Gestalt's commuter-based composition cannot provide.
|
||||
|
||||
**Path C (Commission inspection overlap):** Confirmed. The Commission inspector at the gate cluster has institutional access to Terminal manifest data. Detective PC who builds relationship with inspector gains a third, institutional angle on the evidence. Non-confrontational. Sera Venn cannot access gate cluster customs records without a formal Commission request — separate institutional chains.
|
||||
|
||||
**Sector 3 residential (S-04):** Sub-area adjacent to maintenance spine. 4th confirmed social site (D-025). Anchor NPCs: Drin and Naia (ongoing ventilation dispute). Industrial Sector jurisdiction. Ambient dialogue provides local texture without plot relevance.
|
||||
|
||||
**Commission overlap resolution (N-01):** Gate cluster customs zone is Commission-jurisdictioned space. Commission inspector has scheduled inspection authority crossing into Terminal. This explains Sera's legitimate Terminal presence without requiring her to be stationed there.
|
||||
|
||||
**Chunk size (confirmed):** Chunk = 64×64 sim (32×32 visual, 32m) — streaming unit. Block = 128×128 sim (64×64 visual, 64m) — generator planning unit, 4 chunks. District = 4×4 blocks = 512×512 sim (256×256 visual, 256m). Quarter = 32×32 visual within a block (sub-block unit for generator fill). Araminta dissent (preferred 32×32 visual chunk) noted, overruled. Amends D-012; supersedes D-014 estimate. Filed as D-094.
|
||||
|
||||
**Z-level scheme (confirmed):** z=0 maintenance corridor (Era 1), z=1 all main district structures (Terminal, Bar, Gate cluster ground, transit platform), z=2 Gate cluster observation gallery only. Cross-z LOS: gallery rail = transparent low wall; player on z=2 sees z=1 below; z=1 cannot see upward unless at staircase. Confirmed by Tyre.
|
||||
|
||||
**Transport lore (Miri — confirmed):** Span gates: human-built, single aperture, dual-use windows (freight/passenger). Horizon stations: alien-built, 4–8 apertures, Oort-cloud distance, "The Ring" per-system. Sequential hop travel only. The Loop: 6-district internal tram, 4min Residential Core → Transit District. Station profile correction: Sova's horizon gates at The Ring, not Admin Hub. Q-040/Q-041/Q-043/Q-044 resolved → D-093/D-095. Q-042 partially resolved. Filed as D-095.
|
||||
|
||||
---
|
||||
|
||||
### Round 3 — All Items Resolved
|
||||
|
||||
All tensions and open items from Rounds 1 and 2 resolved. D-records filed: D-093 (`decisions/content.md`), D-094 (`decisions/architecture.md`), D-095 (`decisions/content.md`). No pending items.
|
||||
|
||||
---
|
||||
|
||||
## §4 — D-RECORDS FILED
|
||||
|
||||
*Filed by Qatux, 2026-02-25. D-093 (Sova Transit District spatial layout), D-094 (District spatial hierarchy), D-095 (Horizon stations and gate infrastructure). See `decisions/content.md` and `decisions/architecture.md`.*
|
||||
|
||||
---
|
||||
|
||||
### D-093: Sova Transit District — Spatial Layout and District Topology
|
||||
|
||||
**Decision file:** `decisions/content.md`
|
||||
**Date:** 2026-02-25
|
||||
**Source:** Station District Layout Workshop, Ticket #153 (Sprint 20)
|
||||
**Raised by:** Full team (Gestalt, Miri, Araminta, Tyre, Paula, Ozzie). Compiled by Qatux.
|
||||
**Dissent:** Araminta on chunk size (prefers 32×32 visual chunk; overruled by lead and team majority). No other dissent.
|
||||
|
||||
---
|
||||
|
||||
#### Decision
|
||||
|
||||
The Sova Transit District spatial layout is confirmed as follows.
|
||||
|
||||
---
|
||||
|
||||
#### 1. District Topology
|
||||
|
||||
```
|
||||
N (external — span gate, horizon station connection)
|
||||
↑
|
||||
┌─────────────────────────────────────────┐
|
||||
│ GATE CLUSTER │ ~40×32 visual tiles [T-02 est.]
|
||||
│ z=1: gate floor, customs lanes (2m ea),│ Tint: #0a1222 (institutional cold)
|
||||
│ concourse (8m), processing zone │ Access: PUBLIC (concourse)
|
||||
│ z=2: observation gallery (4 tiles wide)│ SEMI-PRIVATE (customs lanes)
|
||||
│ Commission grey-white palette │ PRIVATE (inspection booths)
|
||||
└────────────────┬────────────────────────┘
|
||||
│ forecourt (~8–10 tiles deep)
|
||||
┌────────────────┴────────────────────────┐
|
||||
│ TERMINAL (Sova Logistics Hub) │ 44×28 visual tiles (confirmed #311)
|
||||
│ z=1. Tint: cool grey-navy │ Access: PUBLIC (entry lobby)
|
||||
│ Entry lobby → scanner bays → │ SEMI-PUBLIC (main corridor)
|
||||
│ main corridor → cargo floor / │ SEMI-PRIVATE (cargo floor,
|
||||
│ manifest processing / break room → │ manifest proc., break room)
|
||||
│ restricted storage (coded, 1 door) │ PRIVATE (supervisor office,
|
||||
│ Supervisor office: [=] window south │ restricted storage)
|
||||
└────────────────┬────────────────────────┘
|
||||
│ ← maintenance corridor z=0 branches east here
|
||||
│ (restricted storage → M-HATCH-T → 40m → M-HATCH-B)
|
||||
│
|
||||
TRANSITION CORRIDOR
|
||||
~40m × 6m (6 visual tiles wide) Tint: neutral dark
|
||||
Surveillance camera at T=24m Access: SEMI-PUBLIC
|
||||
Widening zones at both ends
|
||||
(forecount N-side, bar entry S-side)
|
||||
│
|
||||
│ ← maintenance corridor z=0 terminates at M-HATCH-B
|
||||
│ (opens into bar bathroom corridor)
|
||||
┌────────────────┴────────────────────────┐
|
||||
│ TRANSIT PLATFORM (encounter node) │ [dimensions TBD — ~12×8 visual est.]
|
||||
│ z=1. The Loop tram stop (bar-side) │ Tint: neutral-warm (transitional)
|
||||
│ (tram from Residential Core) │ Access: PUBLIC
|
||||
│ NPC population: commuters, workers. │
|
||||
│ Convergence point #2 (G-03). │
|
||||
└────────────────┬────────────────────────┘
|
||||
│ (bar entry zone, ~5 tiles)
|
||||
┌────────────────┴────────────────────────┐
|
||||
│ BAR — THE LAST SHIFT │ 28×22 + 6m east extension visual (confirmed #312)
|
||||
│ z=1. Tint: warm dark amber │ Access: PUBLIC (main floor, card table)
|
||||
│ East extension (bathroom corridor) │ SEMI-PRIVATE (serving south,
|
||||
│ faces north toward transit hub. │ bathroom corridor)
|
||||
│ Alley door (south) → maintenance │ PRIVATE (back room)
|
||||
│ alley → district edge. │
|
||||
└─────────────────────────────────────────┘
|
||||
↓
|
||||
S (maintenance alley — district edge)
|
||||
|
||||
─────────────────────────────────────────────────────────────────────
|
||||
|
||||
MAINTENANCE CORRIDOR (z=0, runs parallel to transition corridor)
|
||||
|
||||
[RESTRICTED STORAGE north wall / cargo floor door]
|
||||
→ M-HATCH-T (locked hatch, restricted storage interior)
|
||||
→ EAST SERVICE SPINE (~15m, narrow, dim)
|
||||
→ JUNCTION-1 (DD-2 dead-drop location)
|
||||
→ [side branch west] SECTOR 3 RESIDENTIAL (~15×12 visual)
|
||||
Drin/Naia (ventilation dispute anchor)
|
||||
4th social site (D-025). Access: PUBLIC
|
||||
→ DISTRICT SPINE (~25m, grating floor)
|
||||
→ DD-3 "The Mark" (go/no-go signal, mid-corridor)
|
||||
→ M-HATCH-B (locked hatch, bar bathroom corridor)
|
||||
|
||||
Era 1 construction. No Meridian coverage. Grating floors.
|
||||
Zero LOS from all other spaces. Zero regular NPC traffic.
|
||||
Access: PRIVATE (ring members only in practice).
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 2. Zone Dimensions
|
||||
|
||||
| Zone | Visual tiles | Sim tiles | Notes |
|
||||
|------|-------------|-----------|-------|
|
||||
| Gate cluster (z=1) | 40×32 | 80×64 | Araminta confirmed — 7 zones (see §4.2 zone spec) |
|
||||
| Gate observation gallery (z=2) | 32×10 | 64×20 | Commission grey-white; Araminta confirmed |
|
||||
| Terminal | 44×28 | 88×56 | Confirmed (#311) |
|
||||
| Forecourt (Terminal N-face) | ~44×10 | ~88×20 | Estimate |
|
||||
| Transition corridor | ~40×6 | ~80×12 | Confirmed (#313) |
|
||||
| Transit platform | ~12×8 | ~24×16 | Encounter node — The Loop stop; bar-side |
|
||||
| Sector 3 residential | ~15×12 | ~30×24 | 4th social site (D-025); maintenance spine adjacent |
|
||||
| Bar entry zone | ~28×5 | ~56×10 | Estimate |
|
||||
| Bar (Last Shift) | 28×22 (+6m E ext.) | 56×44 (+12 E ext.) | Confirmed (#312) |
|
||||
| Maintenance corridor | ~40×2 | ~80×4 | Confirmed (#313) |
|
||||
| **Total district bounding box** | **~256×256 visual** | **~512×512 sim** | 4×4 blocks per D-094; D-014 estimate superseded |
|
||||
|
||||
---
|
||||
|
||||
#### 3. Access Topology
|
||||
|
||||
Sequential. No tier skipping (H-06).
|
||||
|
||||
```
|
||||
PUBLIC → SEMI-PUBLIC → SEMI-PRIVATE → PRIVATE
|
||||
────── ─────────── ──────────── ───────
|
||||
Gate concourse Transition corridor Terminal cargo floor Supervisor office
|
||||
Gate floor Terminal main corridor Terminal manifest proc. Restricted storage
|
||||
Terminal lobby Gate customs entry Terminal break room Maintenance corridor
|
||||
Transit hub Bar serving south Bar back room
|
||||
Bar main floor Bar bathroom corridor
|
||||
Bar card table
|
||||
Bar counter (cust. side)
|
||||
```
|
||||
|
||||
Movement across tiers requires: worker role (trivial), authority (badge → semi-private), access code (private), ring membership (maintenance corridor/restricted storage).
|
||||
|
||||
---
|
||||
|
||||
#### 4. Spatial Hierarchy (Confirmed Naming)
|
||||
|
||||
- **Chunk** = 64×64 sim (32×32 visual, 32m) — streaming and serialization unit
|
||||
- **Block** = 128×128 sim (64×64 visual, 64m) — generator planning unit; composed of 2×2 chunks (4 chunks per block)
|
||||
- **District** = 4×4 blocks = 512×512 sim (256×256 visual, 256m); 16 blocks, 64 chunks per z-level
|
||||
- **Chunk merge rules:** Adjacent chunks within a block can merge into one large edifice, remain separate (small buildings, gardens, cafes, shacks), or form L-shaped buildings across chunk boundaries
|
||||
- **Large civic structures:** Span multiple blocks (gate cluster, horizon station installations, stadiums, parks)
|
||||
- **District skeleton:** Each major social site occupies approximately one chunk (32×32 visual) within its block
|
||||
|
||||
**Generator architecture note:** The full top-down generator model (geography → infrastructure → amenities → population → zoning → block generation → chunk fill) requires a dedicated workshop brief. This chunk/block/district specification is the spatial primitive for that future system. Q-036 tracks district skeleton design.
|
||||
|
||||
---
|
||||
|
||||
#### 5. Z-Level Scheme
|
||||
|
||||
| Level | Contents | Notes |
|
||||
|-------|----------|-------|
|
||||
| z=0 | Maintenance corridor (Era 1) | Full district. Dim cold-white lighting. Grating floors. No Meridian. |
|
||||
| z=1 | All main district structures | Terminal, Bar, Gate cluster ground, transit platform, Transition corridor |
|
||||
| z=2 | Gate cluster observation gallery only | 4 tiles wide × lane-length. Commission grey-white palette. Access via staircase in gate cluster. |
|
||||
|
||||
**Cross-z LOS (confirmed, Tyre):** Vertical LOS propagates only through designated transparent floor/window tiles. Opaque floor tile = full LOS block. Gallery rail = transparent floor tile, designer-placed. Player on z=2 has LOS downward through transparent rail to gate floor (z=1); LOS does not propagate upward from z=1 except at staircase opening. Performance cost: ~100–150µs per additional FOV pass — trivial. Gallery observation capability is architecturally controlled by designer tile placement, not a special case.
|
||||
|
||||
**Inter-z sound (confirmed, Tyre):** Sound propagates across z-levels only through open hatches and designated vent tiles. The maintenance corridor (z=0) is inaudible from z=1 except at hatch locations (M-HATCH-T inside restricted storage, M-HATCH-B in bar bathroom corridor). This makes the acoustic gap at the cargo floor door (Path B) mechanically coherent — it is a z=1 surface feature, not a z=0 leak.
|
||||
|
||||
**Memory (confirmed, Tyre):** Three z-levels for this district = ~1.35MB. Trivial.
|
||||
|
||||
**Z-level PoC purpose:** The gate cluster observation gallery proves the z-level rendering stack (D-049) and cross-z shadowcasting (D-035) for all future development. This is the only z=2 space in v0.1.
|
||||
|
||||
---
|
||||
|
||||
#### 6. Key Sightline Relationships
|
||||
|
||||
*Across the full district:*
|
||||
|
||||
| From | To | LOS | Notes |
|
||||
|------|----|-----|-------|
|
||||
| Gate observation gallery (z=2) | Gate floor below (z=1) | ✓ downward | Player sees cargo off-loading from above |
|
||||
| Transition corridor (any position) | Terminal exterior / Bar exterior | ✗ | Buildings are opaque from outside |
|
||||
| Transit hub | Bar entry zone | ✓ | Convergence point — workers arriving see bar entrance |
|
||||
| Maintenance corridor | Anywhere | ✗ | Zero LOS in or out. Sound only. |
|
||||
| Maintenance hatch (M-HATCH-T) | Cargo floor | ✗ | Hatch opens inside restricted storage — only visible to someone already in restricted storage |
|
||||
|
||||
*Within Terminal (from #311 — unchanged):*
|
||||
- Main corridor → all four south-facing doors: ✓
|
||||
- Supervisor window [=] → cargo floor + restricted storage door: ✓
|
||||
- Break room → anything: ✗ (isolated)
|
||||
- Manifest processing → main corridor (door open): ✓
|
||||
|
||||
*Within Bar (from #312 — unchanged):*
|
||||
- Corner booth (NW deepest) → entrance, bar counter, card table, back room door: ✓
|
||||
- Bathroom corridor interior → main bar: ✗ (door only)
|
||||
|
||||
---
|
||||
|
||||
#### 7. NPC Routes and Convergence Points
|
||||
|
||||
Two confirmed convergence points outside Terminal and Bar (satisfies G-03):
|
||||
|
||||
1. **Terminal main corridor** — all Terminal workers cross here. Every person moving between scanner bays (north) and cargo floor / manifest processing / supervisor office (south) passes through. Semi-public; lingering is suspicious.
|
||||
|
||||
2. **Transit platform / bar entry zone** — workers arriving from Residential Core via The Loop tram. Some walk north to Terminal, some enter bar directly. NPCs from different social sites share this arrival space. Encounter node, not social site.
|
||||
|
||||
Additional convergence: **Transition corridor** — ring members and workers both use this corridor. The surveillance camera at T=24m records all transits. Pattern analysis reveals ring operational schedule.
|
||||
|
||||
---
|
||||
|
||||
#### 8. Investigation Paths (confirmed)
|
||||
|
||||
**Path A — Pattern Recognition (insert-heavy):**
|
||||
Corridor camera logs → Kael's deep-night transit pattern → manifest database access (manifest processing) → restricted storage access timing → ring identified.
|
||||
|
||||
**Path B — Physical Traversal (exploration-heavy):**
|
||||
Cargo floor: anomalous sound at restricted storage door (acoustic gap around coded door seal) → floor worker conversation → physical discovery of maintenance hatch → corridor traversal → dead-drops discovered. *Note: sound propagation through door seal, not wall. Door is the weak point.*
|
||||
|
||||
**Path C — Commission Inspection Overlap (institutional):**
|
||||
Detective builds relationship with Commission inspector (gate cluster triangle NPC) → inspector shares institutional read of manifest anomalies (compliance framing, not criminal) → detective gains third angle on same evidence. Non-confrontational. Complements Paths A and B.
|
||||
|
||||
---
|
||||
|
||||
#### 9. Transport Lore
|
||||
|
||||
*Captured from workshop discussion:*
|
||||
|
||||
**Span gates (Q-040 — resolved → D-093):** Human-built. Single aperture. Near-instantaneous transit. Scheduled dual-use windows: freight (bulk of operating hours) and passenger (scheduled slots). Physical layout reflected in gate cluster zone spec (§4.2).
|
||||
|
||||
**Horizon stations (Q-041 — resolved → D-095):** Alien-built (no identified builder species). Self-maintaining. 4–8 apertures per station. Located at Oort-cloud distance. Per-system canonical name: "The Ring." Sequential hop travel only (A→B→C through intermediate systems; no direct long-range transit). Per-system variation across 4 access tiers. Station Sova's horizon gates are at The Ring — Admin Hub contains booking offices only.
|
||||
|
||||
**Intra-system transport (Q-042 — partially resolved):** Span gates at star/planetary level plus horizon stations at Oort distance. Details of intra-system hab-to-hab transit remain open.
|
||||
|
||||
**Station internal transit (Q-043 — resolved → D-095):** "The Loop" — internal station tram, 6 districts, 4-minute Residential Core → Transit District run. Workers arrive at transit platform (bar-side) and disperse to Terminal or bar.
|
||||
|
||||
**Gate-train integration (Q-044 — resolved → D-093/D-095):** Arriving passengers exit span gate → aperture chamber → freight/passenger customs lanes → gate concourse (public) → transition corridor → transit platform (The Loop). No direct gate-to-tram connection; transition corridor is the linking space.
|
||||
|
||||
---
|
||||
|
||||
#### 10. Gate Cluster Social Triangle
|
||||
|
||||
**Composition:** Operations manager + senior freight handler + Commission inspector
|
||||
|
||||
**Spatial staging:**
|
||||
- Operations manager: works the gate floor (supervises cargo processing, knows every shipment)
|
||||
- Senior freight handler: works customs lanes (clears cargo for transit; knows what should and shouldn't be there)
|
||||
- Commission inspector: scheduled inspection visits (legitimate authority, reads anomalies institutionally)
|
||||
|
||||
**Triangle tension:** Operations manager and freight handler have an established working relationship — and a shared interest in not attracting Commission attention. Commission inspector is an outside force disrupting their equilibrium. Investigation opportunity: the inspector sees things the manager and handler want invisible.
|
||||
|
||||
**Commission overlap (N-01, Path C):** Inspector has institutional access to Terminal manifest data. Sera Venn's professional peer. Detective who builds relationship with inspector gains Path C.
|
||||
|
||||
---
|
||||
|
||||
#### 11. Invisible Infrastructure Principle (G-08, now named)
|
||||
|
||||
Every ring location serves a mundane purpose. Criminal function is only apparent if you know what to look for. The player (smuggler PC) knows. The detective PC can learn. An NPC observing in isolation sees nothing unusual. Same physical space — different player understanding.
|
||||
|
||||
This is the core spatial design principle for the district. All investigation paths are designed around it. The principle is generalisable: it applies to any district in the Reach that hosts a Tier 1 module.
|
||||
|
||||
---
|
||||
|
||||
#### 12. Narrative Constraints (Paula — all confirmed)
|
||||
|
||||
1. Commission inspector has inspection authority crossing gate cluster AND Terminal — schedules are publicly known
|
||||
2. Inspector's Terminal visits are scheduled and predictable — ring can route around them; gives ring temporal structure
|
||||
3. Sera Venn is a bar regular who knows the inspector professionally — Triangle 4 cross-link
|
||||
4. No NPC in the gate cluster triangle has social connection to Voss — Terminal and gate cluster triangle separation maintained
|
||||
5. Transit hub NPCs are socially isolated from Terminal workers — two distinct working cultures; they share the transition corridor but not social space
|
||||
6. Back room alley exit connects to maintenance alley → district edge; does NOT connect to transit hub service area
|
||||
|
||||
---
|
||||
|
||||
#### Rationale
|
||||
|
||||
The district layout emerged from three rounds of cross-domain synthesis:
|
||||
- Round 1 established 52 constraints across 6 domains and 8 open tensions
|
||||
- Round 2 resolved 10 of 11 tensions; lead feedback resolved T-01 (cargo floor) and T-05 (Careful stance)
|
||||
- Round 3 achieved consensus on all remaining items
|
||||
|
||||
The layout satisfies: D-025 (social sites as atomic template units), D-036 (Sova Transit District setting), D-054 (tile-based movement), D-059 (fog zone temperature tints), D-066 (dual-scale grid), D-011 (fog of perception), D-018 (sound model), D-027 (vertical slice success criteria).
|
||||
|
||||
The chunk/quarter system and top-down generator model establish architectural precedent for Q-036 (district skeleton as generator output).
|
||||
|
||||
---
|
||||
|
||||
#### Cross-References
|
||||
|
||||
- Terminal layout: `docs/design/spatial-layout-terminal-v01.md` (#311)
|
||||
- Bar layout: `docs/design/spatial-layout-bar-v01.md` (#312)
|
||||
- Smuggling corridors: `docs/design/spatial-layout-smuggling-corridors-v01.md` (#313)
|
||||
- Station profile: `docs/design/sova-station-profile.md` (#320)
|
||||
- Gate cluster layout: `docs/design/spatial-layout-gate-v01.md` (to be authored — blocks #157)
|
||||
- Transit hub layout: TBD (new ticket required)
|
||||
- Transport lore open questions: Q-040–Q-044
|
||||
- Generator architecture workshop: pending brief
|
||||
|
||||
---
|
||||
|
||||
*D-records filed: D-093 (decisions/content.md), D-094 (decisions/architecture.md), D-095 (decisions/content.md). Gate cluster full layout to be authored as #157. District bounding box (256×256 visual) supersedes D-014 estimate per D-094.*
|
||||
@@ -0,0 +1,122 @@
|
||||
# Sprint 19: Persist — CI Tasks
|
||||
|
||||
**Goal:** The player can save and resume a game session with per-game directories; the simulation tier system gains eviction and scope pinning; and the first test infrastructure ships with information boundary validation and IPC hardening.
|
||||
|
||||
**Branch:** `ci`
|
||||
**Agents:** Hoshe (QA/CI), Oscar (networking)
|
||||
|
||||
## Carry-over from Sprint 18
|
||||
|
||||
None.
|
||||
|
||||
## New Tickets
|
||||
|
||||
| # | Title | Blocked by |
|
||||
|---|-------|------------|
|
||||
| #270 | Test runner bash scripts | — |
|
||||
| #556 | Protocol version handshake: client | #555 (server) |
|
||||
| #342 | IPC round-trip timing benchmark | #555, #556 |
|
||||
| #271 | IPC serialization fixture files | #270 |
|
||||
|
||||
Use `db/connectors/ticket show <id>` for full details.
|
||||
|
||||
## Key Decisions
|
||||
|
||||
- `decisions/architecture.md` — D-020 (IPC architecture, MessagePack codec, SimBridge trait), D-030 (three-layer test architecture: fixture / mock-protocol / real-subprocess)
|
||||
|
||||
## Notes
|
||||
|
||||
### #270 — Test runner bash scripts
|
||||
|
||||
The test infrastructure has no standardized entry points for CI or agents to invoke. This ticket ships the runner layer.
|
||||
|
||||
What this ticket must deliver:
|
||||
Six scripts at `tests/`:
|
||||
1. `tests/run-rust` — runs `cargo test` in `server/`, exits 0/non-zero, JSON stdout summary
|
||||
2. `tests/run-godot` — runs GUT headlessly (`godot --headless -s client/tests/run_gut.gd`), exits 0/non-zero
|
||||
3. `tests/run-ipc-fixtures` — Layer 1: reads fixture files from `tests/fixtures/`, validates via Rust + GDScript, exits 0/non-zero
|
||||
4. `tests/run-ipc-protocol` — Layer 2: runs mock subprocess protocol state machine tests
|
||||
5. `tests/run-ipc-integration` — Layer 3: starts real server subprocess, runs full round-trip, kills it
|
||||
6. `tests/run-all` — invokes all five in order, collects exit codes, reports JSON summary
|
||||
|
||||
Script requirements per ticket description: exit code 0/non-zero, structured JSON stdout, accepts filter arguments (`--filter test_name`), no interactive input, whitelistable for Claude Code agents (no TTY prompts).
|
||||
|
||||
JSON stdout format (consistent across all scripts):
|
||||
```json
|
||||
{"suite": "rust", "total": 42, "passed": 42, "failed": 0, "duration_ms": 1230}
|
||||
```
|
||||
|
||||
These scripts are the entry points that `make ci-server`, `make ci-client`, and future CI pipelines call. Coordinate with Makefile targets in `docs/DEVOPS.md`.
|
||||
|
||||
### #556 — Protocol version handshake: client
|
||||
|
||||
Blocked by #555 (server must send `HandshakeMessage` first).
|
||||
|
||||
What this ticket must deliver:
|
||||
- `client/scripts/protocol/local_bridge.gd` (or `server_process.gd`): after starting the server subprocess, read the first framed message from the IPC channel
|
||||
- Validate it is a `HandshakeMessage` with `protocol_version == Protocol.PROTOCOL_VERSION` (14)
|
||||
- If mismatch: log error "Protocol version mismatch: server=%d, client=%d", emit a `handshake_failed` signal, shut down the server process gracefully
|
||||
- If match: emit `handshake_complete`, begin normal tick loop
|
||||
- Add a timeout: if no handshake message received within 5 seconds of process start, treat as mismatch
|
||||
|
||||
Current state: `client/scripts/protocol/protocol.gd` already checks `version` in `decode_snapshot()` and logs a mismatch. That check is per-snapshot. The handshake is the startup-time equivalent — validate once at connection, not per tick.
|
||||
|
||||
Files: `client/scripts/protocol/local_bridge.gd`, `client/scripts/protocol/server_process.gd`.
|
||||
|
||||
### #342 — IPC round-trip timing benchmark
|
||||
|
||||
Sprint exit criterion. Measures the complete latency path from server serialization to client scene update.
|
||||
|
||||
What this ticket must deliver:
|
||||
- A benchmark script `tests/run-ipc-benchmark` that:
|
||||
1. Starts the server subprocess
|
||||
2. Waits for handshake (#555/#556)
|
||||
3. Sends N `PlayerInput` messages (N = 100 by default)
|
||||
4. Measures from `rmp_serde::to_vec` (server) to scene update completion (client)
|
||||
5. Reports p50/p95/p99 latencies in milliseconds
|
||||
6. Flags if any percentile exceeds 5ms threshold
|
||||
- Output JSON: `{"p50_ms": 1.2, "p95_ms": 2.8, "p99_ms": 4.1, "threshold_ms": 5, "passed": true}`
|
||||
- The benchmark is run as part of `tests/run-ipc-integration` in Layer 3
|
||||
|
||||
Implementation approach: server-side timestamps in `ObserverSnapshot` (add `server_emit_tick_ms` field, stripped in production builds), client records receive timestamp via `Time.get_ticks_msec()`. Delta = client receive - server emit.
|
||||
|
||||
Blocked by #555 and #556 — benchmark requires a working handshake before timing can start cleanly.
|
||||
|
||||
### #271 — IPC serialization fixture files
|
||||
|
||||
Layer 1 test data: pre-generated `.msgpack` fixture files that both Rust and GDScript can read to verify cross-language serialization compatibility.
|
||||
|
||||
What this ticket must deliver:
|
||||
- A Rust binary (or test in `server/src/`) that generates fixtures to `tests/fixtures/`:
|
||||
- `snapshot_minimal.msgpack` — minimal valid `ObserverSnapshot` (version=14, tick=0, one entity)
|
||||
- `snapshot_full.msgpack` — all optional fields populated (monologue, dialogue, inventory, POIs, KG dump)
|
||||
- `player_input_move.msgpack` — `PlayerInput { tick: 1, action: MoveNorth }`
|
||||
- `player_input_interact.msgpack` — `PlayerInput { tick: 2, action: Interact { target: 99, verb: "Talk" } }`
|
||||
- `malformed.msgpack` — intentionally truncated bytes (tests error handling)
|
||||
- A GDScript test `client/tests/test_ipc_fixtures.gd` that reads each `.msgpack` fixture file, decodes via `Protocol.decode_snapshot()` / `Protocol.decode_player_input()`, and asserts expected field values
|
||||
- Cross-language verification: the same byte stream decoded by both Rust and GDScript must produce identical field values
|
||||
|
||||
The fixture generator is run once (manually or in CI pre-step) to produce the committed `.msgpack` files. The files live at `tests/fixtures/` and are committed to the repo.
|
||||
|
||||
Blocked by #270 — fixture tests are invoked by `tests/run-ipc-fixtures`.
|
||||
|
||||
## Dependency Chain
|
||||
|
||||
```
|
||||
#555 (server: protocol handshake) → #556 (ci: protocol handshake: client)
|
||||
#555 + #556 → #342 (IPC benchmark: requires working handshake)
|
||||
|
||||
#270 (test runner scripts) → #271 (fixture files: invoked by run-ipc-fixtures)
|
||||
|
||||
Parallel starts: #270, #555 (server-side) — both unblocked week 1
|
||||
#556 starts after #555 is at review
|
||||
#271 starts after #270 merges
|
||||
#342 starts after #555 + #556 both land
|
||||
```
|
||||
|
||||
## PR Workflow
|
||||
|
||||
When ready to submit, create a PR with `tea` CLI. **All flags are required** to avoid TTY prompts (see CLAUDE.md "Gitea access" section):
|
||||
```bash
|
||||
tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "feat(ci): description" --description "body" --base main --head ci
|
||||
```
|
||||
@@ -0,0 +1,128 @@
|
||||
# Sprint 19: Persist — Client Tasks
|
||||
|
||||
**Goal:** The player can save and resume a game session with per-game directories; the simulation tier system gains eviction and scope pinning; and the first test infrastructure ships with information boundary validation and IPC hardening.
|
||||
|
||||
**Branch:** `client`
|
||||
**Agents:** Stig (UI), Oscar (networking)
|
||||
|
||||
## Carry-over from Sprint 18
|
||||
|
||||
None. Sprint 18 closed clean.
|
||||
|
||||
## New Tickets
|
||||
|
||||
| # | Title | Blocked by |
|
||||
|---|-------|------------|
|
||||
| #554 | Save/load: client UI | #553 (server) |
|
||||
| #258 | Game session management | — |
|
||||
| #205 | GDScript test framework setup | — |
|
||||
| #206 | Scene testing utilities | #205 |
|
||||
| #348 | Debug visualization overlay | — |
|
||||
|
||||
Use `db/connectors/ticket show <id>` for full details.
|
||||
|
||||
## Key Decisions
|
||||
|
||||
- `decisions/architecture.md` — D-020 (IPC architecture, MessagePack), D-085 (per-game save directory structure)
|
||||
- `decisions/questions.md` — Q-029 (save file format design — open, Sprint 19 uses MessagePack quick-and-dirty format)
|
||||
|
||||
## Open Questions to Resolve Early
|
||||
|
||||
- **Q-029: Save file format design** — Sprint 19 ships MessagePack quick-and-dirty format. Do not over-engineer the loading screen metadata. A readable directory name (`<timestamp>-<seed>/`) per D-085 is sufficient for v0.1. The full versioning/migration design is tracked in Q-029 for a later sprint.
|
||||
|
||||
## Notes
|
||||
|
||||
### #554 — Save/load: client UI
|
||||
|
||||
Blocked by #553 (server must implement `SaveCommand`/`LoadCommand` IPC messages before client can wire F5/F6).
|
||||
|
||||
What this ticket must deliver:
|
||||
- F5 key mapped in `client/scripts/autoloads/input_mapper.gd` to send a `SaveGame` IPC action to the server with the active game directory path (`user://saves/<game-id>/quicksave.sav`)
|
||||
- F6 key mapped to send `LoadGame` IPC action with the same path
|
||||
- Server responds with `SaveComplete`/`LoadComplete` — client shows a brief HUD notification ("Saved" / "Loading...")
|
||||
- Loading screen scene: reads `user://saves/` directory, lists subdirectories sorted by last-modified (most recent first), shows most recent save filename per game directory per D-085
|
||||
- F6 from the main menu opens the loading screen
|
||||
- The active `game-id` is tracked in `GameState` autoload (add `current_game_id: String`)
|
||||
|
||||
Integration points: `client/scripts/autoloads/input_mapper.gd` (key bindings), `client/scripts/autoloads/game_state.gd` (current_game_id field), `client/scripts/protocol/` (new IPC message encoding), `client/scripts/ui/` (loading screen scene).
|
||||
|
||||
Save directory path per D-085: `user://saves/<timestamp>-<seed>/` where game-id is created on New Game (#258). F5 quicksave writes to `user://saves/<game-id>/quicksave.sav`. Loading screen lists directories sorted by `FileAccess.get_modified_time()`.
|
||||
|
||||
Wireframe reference: `docs/design/wireframes/menus/v01-save-load.png`.
|
||||
|
||||
### #258 — Game session management
|
||||
|
||||
New Game creates the per-game save directory before any save occurs (D-085 requirement: "directory created on New Game — even before the first save, so the path exists for quicksave/autosave").
|
||||
|
||||
What this ticket must deliver:
|
||||
- `GameState.current_game_id: String` — format `<timestamp>-<seed>` (e.g. `20260225-143022-a7b3f1`)
|
||||
- On "New Game": generate game-id (timestamp + RNG hex suffix), create `user://saves/<game-id>/` directory via `DirAccess.make_dir_recursive()`
|
||||
- On "Continue" / loading screen selection: set `current_game_id` from the selected directory name
|
||||
- "Quit to menu" flow: prompt "Save before quitting?" — F5 save if confirmed
|
||||
- Wire the game-id into the `SimBridge` startup: server subprocess launched with `--game-id <id>` argument (or equivalent) so server can log with the same ID
|
||||
|
||||
Integration points: `client/scripts/autoloads/game_state.gd` (new fields), `client/scripts/protocol/server_process.gd` (subprocess launch args), `client/scripts/ui/` (main menu scene: New Game / Continue buttons).
|
||||
|
||||
Note: `game_state.gd` is already the largest autoload with 300+ lines. Keep game session logic in a thin wrapper on `GameState` — do not add another 100-line block directly. Consider a `session_manager.gd` helper if the logic exceeds 40 lines.
|
||||
|
||||
### #205 — GDScript test framework setup
|
||||
|
||||
The project has no GDScript test infrastructure yet. The Godot client has no equivalent of `cargo test`.
|
||||
|
||||
What this ticket must deliver:
|
||||
- Install and configure **GUT (Godot Unit Test)** as the GDScript test framework — it has the best Godot 4 support and is actively maintained
|
||||
- Create `client/tests/` as the test root directory
|
||||
- `client/tests/run_gut.gd`: the GUT runner script that CI can invoke headlessly (`godot --headless -s client/tests/run_gut.gd`)
|
||||
- Exit code 0 = all pass, non-zero = failures — required for CI integration (#270 test runner scripts)
|
||||
- A single smoke test `client/tests/test_protocol.gd`: verifies `Protocol.decode_snapshot(bytes)` returns non-null for a minimal valid msgpack fixture
|
||||
|
||||
GUT installation: add as a Godot addon. Check if there is already an `addons/` directory in `client/`.
|
||||
|
||||
### #206 — Scene testing utilities
|
||||
|
||||
Blocked by #205 (GUT must be installed first).
|
||||
|
||||
What this ticket must deliver:
|
||||
- `client/tests/util/scene_helper.gd`: loads a scene file by path, instantiates it into a temporary viewport, provides `assert_node_exists(path)`, `assert_signal_emitted(node, signal_name)`, and `get_node_at(path)` helpers
|
||||
- `client/tests/test_game_state.gd`: tests for `GameState.apply_snapshot()` — verify that a snapshot dictionary with known fields updates the correct `GameState` fields
|
||||
- `client/tests/test_protocol.gd` (extend from #205 smoke test): add roundtrip test for `Protocol.encode_player_input()` and `Protocol.decode_player_input()`
|
||||
|
||||
These utilities are the scaffolding for all future client tests. Keep them minimal and dependency-free — do not require a running server.
|
||||
|
||||
### #348 — Debug visualization overlay
|
||||
|
||||
Dev tool (F3 toggle). The stub `client/scripts/ui/debug_overlay.gd` already exists.
|
||||
|
||||
What this ticket must deliver:
|
||||
- Extend `debug_overlay.gd` to draw on a `CanvasLayer` above the game world:
|
||||
- **Pathfinding waypoints**: draw lines between waypoint positions from `GameState.visible_entities` (entities with kind `Npc` — estimate waypoints from position delta between ticks)
|
||||
- **Line-of-sight rays**: draw lines from player position to each visible entity
|
||||
- **Vision cone boundary**: draw the forward/peripheral arc boundary using `GameState.visibility_sectors`
|
||||
- **Information state tags**: draw confidence label (Suspects/KnowsOf/KnowsDetails/Direct) above each visible NPC from `GameState.player_knowledge`
|
||||
- **Tick timing graph**: small line chart in corner showing tick delta over the last 30 ticks
|
||||
- F3 toggle: connected to `InputMapper` action `toggle_debug_overlay`
|
||||
- Debug overlay is **dev-only**: compiled out in export builds via `OS.is_debug_build()` check
|
||||
|
||||
Integration points: `client/scripts/autoloads/game_state.gd` (data source), `client/scripts/autoloads/input_mapper.gd` (F3 action), `client/scripts/ui/debug_overlay.gd` (extend existing stub).
|
||||
|
||||
## Dependency Chain
|
||||
|
||||
```
|
||||
#205 (GDScript test framework) → #206 (scene testing utilities)
|
||||
|
||||
#258 (game session management) → #554 (save/load client UI: needs current_game_id)
|
||||
#553 (server, ECS extraction) → #554 (save/load client UI: needs IPC commands)
|
||||
|
||||
#348 (debug overlay) → standalone, parallel track
|
||||
```
|
||||
|
||||
Parallel starts: #258, #205, #348 all unblocked week 1.
|
||||
#554 starts after #553 (server) reaches review stage and #258 lands.
|
||||
#206 starts after #205 merges.
|
||||
|
||||
## PR Workflow
|
||||
|
||||
When ready to submit, create a PR with `tea` CLI. **All flags are required** to avoid TTY prompts (see CLAUDE.md "Gitea access" section):
|
||||
```bash
|
||||
tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "feat(client): description" --description "body" --base main --head client
|
||||
```
|
||||
@@ -0,0 +1,97 @@
|
||||
# Sprint 19: Persist — Joint Briefing
|
||||
|
||||
**Goal:** The player can save and resume a game session with per-game directories; the simulation tier system gains eviction and scope pinning; and the first test infrastructure ships with information boundary validation and IPC hardening.
|
||||
|
||||
**Sprint:** 19
|
||||
**Status:** planning → active
|
||||
|
||||
## Pre-Sprint
|
||||
|
||||
Before implementation begins, no schema work is needed — `SaveStateV1` is already defined (#256, done). However, the following IPC protocol additions must be agreed between server and client **before either side implements**:
|
||||
|
||||
| Item | Owner | Needed by |
|
||||
|------|-------|-----------|
|
||||
| `HandshakeMessage` wire format | server (#555) | client (#556) |
|
||||
| `SaveCommand` / `LoadCommand` IPC message variants | server (#553) | client (#554) |
|
||||
| `SaveComplete` / `LoadComplete` response format | server (#553) | client (#554) |
|
||||
| Fixture file format and field names | ci (#271) | all teams |
|
||||
|
||||
Server team: define these in `server/src/bridge/types.rs` first (as Rust structs + serde). CI team + client team: implement against the published definitions. Do not start #556 or #554 until #555 and #553 respectively reach review.
|
||||
|
||||
## Team Allocation
|
||||
|
||||
| Team | Tickets | Count |
|
||||
|------|---------|-------|
|
||||
| server | #553, #96, #97, #98, #200, #272, #555 | 7 |
|
||||
| client | #554, #258, #205, #206, #348 | 5 |
|
||||
| ci | #270, #556, #342, #271 | 4 |
|
||||
|
||||
## Cross-Team Dependencies
|
||||
|
||||
```
|
||||
server #555 (handshake: server)
|
||||
→ ci #556 (handshake: client)
|
||||
→ ci #342 (IPC benchmark)
|
||||
|
||||
server #553 (ECS extraction)
|
||||
→ client #554 (save/load UI)
|
||||
|
||||
server #200 (test module org)
|
||||
→ server #272 (info boundary tests)
|
||||
|
||||
client #205 (GDScript test framework)
|
||||
→ client #206 (scene testing utilities)
|
||||
→ ci #271 (fixture files need GDScript reader)
|
||||
|
||||
ci #270 (test runner scripts)
|
||||
→ ci #271 (fixture tests invoked by run-ipc-fixtures)
|
||||
```
|
||||
|
||||
## Sprint Completion Proof
|
||||
|
||||
When Sprint 19 is done, the following must all be observable:
|
||||
|
||||
1. **Save/load round-trip**: Press F5 in-game → file appears at `user://saves/<game-id>/quicksave.sav` in MessagePack format. Press F6 → game state restored from file (tick, entities, player knowledge match pre-save state).
|
||||
|
||||
2. **Per-game directory**: Starting a New Game creates `user://saves/<timestamp>-<seed>/` before any save occurs. The loading screen lists this directory.
|
||||
|
||||
3. **Tier eviction**: Spawn 90+ NPCs (above Active cap of 80). `ActiveSim` count stabilizes at ≤80 with the excess evicted to `BackgroundSim`/`StateSaved`. Scope-tagged NPCs (KnownContact, Colleague) remain Active regardless.
|
||||
|
||||
4. **Protocol handshake**: Starting the server subprocess: first IPC message is a `HandshakeMessage`. Version mismatch (force by temporarily changing server `PROTOCOL_VERSION`) produces an error and clean shutdown — no crash.
|
||||
|
||||
5. **Test infrastructure**: `tests/run-all` exits 0 with all suites passing. `tests/run-ipc-fixtures` reads committed `.msgpack` files and validates both Rust and GDScript decode them identically. `cargo test` in `server/` includes information boundary negative tests that assert absence of leakage.
|
||||
|
||||
6. **Debug overlay**: F3 in-game toggles the debug canvas showing vision cone arcs, entity LOS rays, NPC knowledge confidence labels, and tick timing graph.
|
||||
|
||||
## Test Plan (D-030)
|
||||
|
||||
| Layer | Runner | Tickets | When |
|
||||
|-------|--------|---------|------|
|
||||
| Layer 1: Fixture serialization | `tests/run-ipc-fixtures` | #271, #200 | Every edit |
|
||||
| Layer 1: Unit tests (Rust) | `tests/run-rust` | #272, #96, #97, #98 | Every edit |
|
||||
| Layer 1: Unit tests (GDScript) | `tests/run-godot` | #205, #206 | Every edit |
|
||||
| Layer 2: Mock protocol | `tests/run-ipc-protocol` | #555, #556 | Every PR |
|
||||
| Layer 3: Real subprocess | `tests/run-ipc-integration` | #342, #553/#554 | Daily/pre-merge |
|
||||
|
||||
All layers must pass before any PR merges. `make ci` invokes `tests/run-all`.
|
||||
|
||||
## Key Decisions Reference
|
||||
|
||||
| Decision | Domain file | Relevant to |
|
||||
|----------|------------|-------------|
|
||||
| D-010: Determinism + info boundaries | architecture.md | #272, #96, #553 |
|
||||
| D-020: IPC architecture, MessagePack | architecture.md | #553, #554, #555, #556, #342, #271 |
|
||||
| D-026: Simulation tiers, timestamp eviction, scope tags | architecture.md | #96, #97, #98 |
|
||||
| D-030: Three-layer test architecture | architecture.md | #200, #270, #271, #272, #342 |
|
||||
| D-085: Per-game save directory structure | architecture.md | #554, #258, #553 |
|
||||
| Q-029: Save file format (open) | questions.md | #553 (quick-and-dirty MessagePack for now) |
|
||||
|
||||
## Risk Register
|
||||
|
||||
| Risk | Probability | Impact | Mitigation |
|
||||
|------|------------|--------|------------|
|
||||
| ECS extraction misses components (#553) | Medium | High | #272 info boundary tests catch leakage; fixture roundtrip (#271) catches missing fields |
|
||||
| IPC protocol mismatch between #555 and #556 | Low | High | Define wire types in Rust first, share definition doc before client implements |
|
||||
| GUT framework incompatible with Godot 4.x version in use (#205) | Low | Medium | Verify GUT version before full installation; fallback to hand-rolled test runner |
|
||||
| Save file bloat (SaveStateV1 larger than ~1-2 KB/NPC) | Low | Low | Q-029 tracks compression — deferred. Profile with #342 benchmark if flagged |
|
||||
| Scope tag assignment races with eviction (#97/#98) | Low | Medium | Eviction runs after scope tag system in schedule order; schedule ordering test in #97 |
|
||||
@@ -0,0 +1,152 @@
|
||||
# Sprint 19: Persist — Server Tasks
|
||||
|
||||
**Goal:** The player can save and resume a game session with per-game directories; the simulation tier system gains eviction and scope pinning; and the first test infrastructure ships with information boundary validation and IPC hardening.
|
||||
|
||||
**Branch:** `server`
|
||||
**Agents:** Dudley (simulation), Tyre (architecture), Hoshe (QA)
|
||||
|
||||
## Carry-over from Sprint 18
|
||||
|
||||
None. Sprint 18 closed clean.
|
||||
|
||||
## New Tickets
|
||||
|
||||
| # | Title | Blocked by |
|
||||
|---|-------|------------|
|
||||
| #553 | Save/load: server ECS extraction | #256 (done) |
|
||||
| #96 | State serialization system | — |
|
||||
| #97 | Timestamp-based eviction | — |
|
||||
| #98 | Scope tag system | — |
|
||||
| #200 | Test module organization | — |
|
||||
| #272 | Information boundary negative test suite | #200 |
|
||||
| #555 | Protocol version handshake: server | — |
|
||||
|
||||
Use `db/connectors/ticket show <id>` for full details.
|
||||
|
||||
## Key Decisions
|
||||
|
||||
- `decisions/architecture.md` — D-010 (determinism + info boundaries), D-020 (IPC architecture, MessagePack), D-026 (simulation tiers: Active/Background/State-saved/Ungenerated, timestamp eviction, scope tags), D-030 (three-layer test architecture), D-041 (knowledge graph data model, StableId)
|
||||
- `decisions/questions.md` — Q-029 (save file format design — Sprint 19 ships quick-and-dirty, Q-029 tracks the thorough design pass for later)
|
||||
|
||||
## Open Questions to Resolve Early
|
||||
|
||||
- **Q-029: Save file format design** — Sprint 19 uses MessagePack from `SaveStateV1`. Resolution of full versioning/migration strategy is deferred. Do not block #553 on Q-029; proceed with MessagePack format as specified.
|
||||
|
||||
## Notes
|
||||
|
||||
### #553 — Save/load: server ECS extraction
|
||||
|
||||
`server/src/simulation/save_state.rs` already defines `SaveStateV1` (done in #256). The data model is complete: tick, seed, RNG, `player_knowledge: KnowledgeGraph`, `relationship_graph: RelationshipGraph`, `npc_states: Vec<NpcSaveState>`. Roundtrip tests pass.
|
||||
|
||||
What this ticket must deliver:
|
||||
- A `save_to_file(path: &Path, world: &World) -> Result<()>` function: queries ECS for all relevant components, builds a `SaveStateV1`, calls `state.to_bytes()`, writes to disk. Per-game directory path is provided by the client via a new `IpcCommand::SaveGame { path: String }` variant.
|
||||
- A `load_from_file(path: &Path, world: &mut World) -> Result<()>` function: reads bytes, calls `SaveStateV1::from_bytes`, re-spawns entities, injects `KnowledgeGraph`, `RelationshipGraph`, and `SimulationTime` as resources, reseeds the RNG.
|
||||
- A `SaveCommand` and `LoadCommand` IPC message pair wired through `server/src/bridge/` — server receives save/load triggers from the client, executes, sends `SaveComplete`/`LoadComplete` response.
|
||||
- Format version check on load: reject files with `format_version != SAVE_FORMAT_VERSION` with a clear error.
|
||||
|
||||
Integration points: `server/src/simulation/save_state.rs` (data model), `server/src/bridge/types.rs` (new IPC commands), `server/src/bridge/local.rs` or `tcp.rs` (command dispatch), `server/src/knowledge/graph.rs` (KG re-injection), `server/src/npc/relationships.rs` (RelationshipGraph re-injection).
|
||||
|
||||
Gotcha: ECS entity IDs are generational — do not save bevy `Entity` handles. `SaveStateV1` already uses `StableId(u64)` throughout. On load, re-spawn entities and re-register `StableId -> Entity` in `EntityRegistry`.
|
||||
|
||||
### #96 — State serialization system
|
||||
|
||||
Complement to #553. Where #553 handles whole-game ECS extraction, #96 implements the per-NPC serialization primitive for tier transitions.
|
||||
|
||||
What this ticket must deliver:
|
||||
- A `serialize_npc_to_frozen(entity: Entity, world: &World) -> NpcSaveState` function producing the frozen struct (~1-2 KB per NPC per D-026)
|
||||
- A `deserialize_npc_from_frozen(state: &NpcSaveState, commands: &mut Commands)` that re-spawns a full NPC entity with the correct component set
|
||||
- Used by the tier system when evicting to `StateSaved`: instead of keeping ECS components live, serialize to `NpcSaveState` and despawn. On reactivation: deserialize and re-spawn.
|
||||
- Unit tests: serialize + deserialize produces an entity with identical component values
|
||||
|
||||
Existing shape: `NpcSaveState` in `save_state.rs` captures position, `SecretSeverity`, `Relationships`, stress, tolerance, contentment, and optional `KnowledgeGraph`. Verify this covers all components needed for Background/Active reconstruction. Flag any missing axis (D-024) in a code comment for follow-up.
|
||||
|
||||
### #97 — Timestamp-based eviction
|
||||
|
||||
`server/src/simulation/tier.rs` has the tier marker components (`ActiveSim`, `BackgroundSim`, `StateSaved`) and the distance-based `update_tier_markers` system. What is missing: the LRU eviction when sim-space fills up.
|
||||
|
||||
What this ticket must deliver:
|
||||
- A `LastInteractionTick(u64)` component on all NPCs, updated whenever the player interacts with or observes an NPC
|
||||
- A `SimSpacePressure` resource tracking current `ActiveSim` count vs. capacity (cap: 80 per D-026)
|
||||
- An `evict_excess_active` system: when `ActiveSim` count exceeds capacity, demote the N oldest-by-`LastInteractionTick` entities to `BackgroundSim` (or `StateSaved` if beyond background radius)
|
||||
- Uses a priority queue (BinaryHeap keyed by `LastInteractionTick`) for O(log N) eviction selection
|
||||
|
||||
Gotcha: eviction must not demote entities with active scope tags (see #98). The eviction system runs after #98's `ScopeTag` check.
|
||||
|
||||
### #98 — Scope tag system
|
||||
|
||||
Scope tags are the mechanism by which certain NPCs stay pinned to `ActiveSim` regardless of distance or LRU pressure (D-026: "neighborhood, active-quest, colleague, known-contact").
|
||||
|
||||
What this ticket must deliver:
|
||||
- A `ScopeTag` component (or enum-tagged component) with variants: `Neighborhood`, `ActiveQuest`, `Colleague`, `KnownContact`
|
||||
- A `ScopePinned` marker component: attached to any NPC carrying a `ScopeTag`, removed when no scope tags remain
|
||||
- The eviction system (#97) skips entities with `ScopePinned`
|
||||
- Scope tags are assigned by gameplay systems: `Neighborhood` from proximity at session start, `KnownContact` from `KnowledgeGraph` entries with confidence >= `KnowsOf`, `Colleague` from `RelationshipGraph` edges with `Friend` or `Colleague` kind, `ActiveQuest` reserved for future quest system
|
||||
|
||||
Integration: `server/src/simulation/tier.rs` (eviction exclusion), `server/src/knowledge/graph.rs` (KnownContact assignment trigger), `server/src/npc/relationships.rs` (Colleague assignment trigger).
|
||||
|
||||
### #200 — Test module organization
|
||||
|
||||
`server/src/test_world/` already exists with `constants.rs`, `invariants.rs`, `mod.rs`, `reset.rs`, and `rooms/`. This is the foundation.
|
||||
|
||||
What this ticket must deliver:
|
||||
- Establish the external test module pattern for the server crate: `#[cfg(test)] mod tests` in each module, plus a top-level `tests/` directory alongside `src/` for integration tests that run against the full simulation
|
||||
- Document the three-layer test architecture (D-030): Layer 1 = fixture-based serialization (fast), Layer 2 = mock subprocess protocol state machine (medium), Layer 3 = real subprocess integration (slow)
|
||||
- Create `tests/integration/mod.rs` as the entry point for Layer 3 tests
|
||||
- Ensure `cargo test` in `server/` runs all layers correctly
|
||||
- No-ops are fine for Layer 2 and 3 stubs — the important deliverable is the directory structure and entry points
|
||||
|
||||
#272 is blocked by this ticket — the information boundary tests land in the new structure.
|
||||
|
||||
### #272 — Information boundary negative test suite
|
||||
|
||||
The core asymmetric information claim of the game: entity X cannot see what entity Y knows, unless the observation system explicitly grants it.
|
||||
|
||||
What this ticket must deliver:
|
||||
- A suite of negative tests asserting that information does NOT cross boundaries:
|
||||
1. Player's `KnowledgeGraph` does not contain NPC data that was not observed (no passive leakage)
|
||||
2. `ObserverSnapshot` for the player does not include entities outside LOS (fog of perception holds)
|
||||
3. Background-tier NPC `KnowledgeGraph` is not updated by Active-tier systems (tier boundary holds)
|
||||
4. `SaveStateV1` for one NPC does not serialize another NPC's `KnowledgeGraph`
|
||||
- Uses `test_world/` for scenario setup — reuse existing helpers
|
||||
- These tests live in Layer 1 (pure unit) and Layer 2 (mock world) of D-030
|
||||
|
||||
Gotcha: "negative tests" means asserting absence. Use `assert!(kg.entities.get(&id).is_none())` patterns — not just "test passed because nothing happened."
|
||||
|
||||
### #555 — Protocol version handshake: server
|
||||
|
||||
`server/src/bridge/types.rs` defines `PROTOCOL_VERSION: u8 = 14`. The version is already included in `ObserverSnapshot` as `pub version: u8`.
|
||||
|
||||
What this ticket must deliver:
|
||||
- Verify the first `ObserverSnapshot` emitted after subprocess startup includes `version: PROTOCOL_VERSION`
|
||||
- Add a handshake phase: before normal tick loop begins, server emits a minimal `HandshakeMessage { protocol_version: PROTOCOL_VERSION }` as the very first framed message on the IPC channel
|
||||
- Client reads this message and validates before sending any `PlayerInput`
|
||||
- If the server receives a `PlayerInput` before completing handshake, log a warning and process normally (forward-compatible)
|
||||
- Integration point: `server/src/bridge/local.rs` (startup sequence), `server/src/bridge/framing.rs` (message framing)
|
||||
|
||||
Coordinate with ci team (#556) — the client-side validation is their ticket.
|
||||
|
||||
## Dependency Chain
|
||||
|
||||
```
|
||||
#555 (protocol handshake: server) → #556 (ci: protocol handshake: client)
|
||||
|
||||
#200 (test module organization) → #272 (information boundary tests)
|
||||
|
||||
#98 (scope tag system) → feeds into #97 (eviction respects scope pins)
|
||||
|
||||
#256 (done: save state data model) → #553 (server ECS extraction)
|
||||
#553 (server ECS extraction) → #554 (client: save/load UI)
|
||||
|
||||
#96 (state serialization) → feeds into #553 (used during ECS extraction)
|
||||
|
||||
Parallel starts: #555, #97, #98, #96, #200 — all unblocked week 1
|
||||
#553 starts after #96 is at review stage (needs serialize_npc_to_frozen)
|
||||
#272 starts after #200 merges
|
||||
```
|
||||
|
||||
## PR Workflow
|
||||
|
||||
When ready to submit, create a PR with `tea` CLI. **All flags are required** to avoid TTY prompts (see CLAUDE.md "Gitea access" section):
|
||||
```bash
|
||||
tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "feat(simulation): description" --description "body" --base main --head server
|
||||
```
|
||||
@@ -0,0 +1,115 @@
|
||||
# Sprint 20: Shape — Client Tasks
|
||||
|
||||
**Goal:** The social site template system gains its foundational schema; triangles become generatable and observable as escalating tensions; the client gains save/load UI and code quality improvements.
|
||||
|
||||
**Branch:** `client`
|
||||
**Agents:** Stig (UI/rendering), Tyre (architecture), Hoshe (QA)
|
||||
|
||||
## Carry-over from Sprint 19
|
||||
|
||||
None — Sprint 19 complete. #554 (save/load client UI) is finishing in Sprint 19.
|
||||
|
||||
## New Tickets
|
||||
|
||||
| # | Title | Blocked by |
|
||||
|---|-------|------------|
|
||||
| #557 | Refactor: game_state.gd derived state in apply_snapshot() | — |
|
||||
| #558 | Refactor: dialogue_box.gd direct GameState mutation and AudioManager coupling | — |
|
||||
| #559 | Refactor: main.gd god coordinator — extract SnapshotEventRouter | — |
|
||||
| #560 | Refactor: unify duplicate YAML parsers | — |
|
||||
|
||||
Use `db/connectors/ticket show <id>` for full details.
|
||||
|
||||
## Key Decisions
|
||||
|
||||
- `decisions/architecture.md` — D-020 (Godot is a pure renderer: no game logic in GDScript; GameState reflects server-authoritative data, not derived behavior), D-085 (per-game save directory structure: `user://saves/<timestamp>-<seed>/`, F5=quicksave, F6=quickload, loading screen lists dirs by last-modified), D-088 (3-state pause system: client sends pause requests, server is authoritative)
|
||||
- `decisions/scope.md` — D-027 (vertical slice success criteria: game session must be resumable for 30-min playthroughs)
|
||||
|
||||
## Notes
|
||||
|
||||
### #557 — Refactor: game_state.gd derived state in apply_snapshot()
|
||||
|
||||
Code review finding: `apply_snapshot()` in `client/scripts/autoloads/game_state.gd` computes two derived values inline:
|
||||
- `stationary_ticks` (increments when player position hasn't changed) — line 99 / ~line 131-133
|
||||
- `current_zone_id` (derived from tile iteration) — line 105 / ~line 286
|
||||
|
||||
Per D-020, the Godot client is a pure renderer. Behavior-driving computations (stationary tick counting, zone identification) belong in the server, not in `apply_snapshot()`. The server already sends `zone_id` per tile — the client should read it directly rather than re-deriving it.
|
||||
|
||||
What this ticket must deliver:
|
||||
- Move `stationary_ticks` accumulation out of `apply_snapshot()`. The server sends `stationary_ticks` (or equivalent) in the snapshot — if not yet present, add the field to `ObserverSnapshot` in `client/scripts/protocol/protocol.gd` and mark with a TODO for the server team to populate it. Client reads the server value directly.
|
||||
- Move `current_zone_id` resolution to a simple property read from the snapshot (`player_tile.zone_id`), removing the tile iteration loop from `apply_snapshot()`.
|
||||
- After: `apply_snapshot()` contains only direct field assignments from the snapshot dictionary — no conditional logic, no accumulation.
|
||||
- Add a comment citing D-020 on each removed computation to document the rationale.
|
||||
- Unit tests: `apply_snapshot()` with a snapshot missing the new fields should degrade gracefully (default values, no crash).
|
||||
|
||||
Integration points: `client/scripts/autoloads/game_state.gd` only. Protocol fields may need a minor extension in `client/scripts/protocol/protocol.gd` — coordinate with server team if new snapshot fields are required.
|
||||
|
||||
Gotcha: `stationary_ticks` drives `ListeningFocus` (D-071) — confirm the server already tracks and sends this value before removing client-side accumulation. If the server does not yet send it, add a feature-flagged fallback that keeps the old behavior with a deprecation comment.
|
||||
|
||||
### #558 — Refactor: dialogue_box.gd direct GameState mutation and AudioManager coupling
|
||||
|
||||
Code review finding: `client/ui/dialogue_box.gd` directly mutates `GameState.dialogue_active` at 3 call sites (lines ~289, ~321, ~334) and calls `AudioManager.apply_dip()` / `AudioManager.clear_dip()` directly.
|
||||
|
||||
Per D-020, UI components should not mutate shared state or call sibling autoloads directly — they should emit signals and let a coordinator (main.gd or a future SnapshotEventRouter) manage cross-component state.
|
||||
|
||||
What this ticket must deliver:
|
||||
- Replace the 3 `GameState.dialogue_active = true/false` assignments with a signal: `signal dialogue_state_changed(active: bool)`. `main.gd` connects to this signal and updates `GameState.dialogue_active`.
|
||||
- Replace `AudioManager.apply_dip("dialogue")` and `AudioManager.apply_dip("confrontation")` / `AudioManager.clear_dip()` calls with signals: `signal audio_dip_requested(profile: String)` and `signal audio_dip_cleared()`. `main.gd` connects to these and calls `AudioManager`.
|
||||
- Result: `dialogue_box.gd` has zero references to `GameState` or `AudioManager`.
|
||||
- Unit tests: mock signal receivers capture the emitted signals with correct arguments; no direct autoload calls remain.
|
||||
|
||||
Integration points: `client/ui/dialogue_box.gd` (source), `client/scripts/main.gd` (connects to new signals in `_ready()`). No server changes.
|
||||
|
||||
Gotcha: `InputMapper` checks `GameState.dialogue_active` to suppress movement. The signal path adds one frame of latency — verify that the signal fires synchronously within the same frame (use `call_immediate` or connect with `CONNECT_DEFERRED` depending on timing requirements). The `is_dialogue_active()` method on `dialogue_box.gd` (line 337) can remain as a local query without touching `GameState`.
|
||||
|
||||
### #559 — Refactor: main.gd god coordinator — extract SnapshotEventRouter
|
||||
|
||||
Code review finding: `client/scripts/main.gd` is 517 lines and dispatches to 15+ child nodes through a set of `consume_*` methods that all follow the same pattern: read field from snapshot, call method on child node.
|
||||
|
||||
What this ticket must deliver:
|
||||
- Extract a `SnapshotEventRouter` class (`client/scripts/snapshot_event_router.gd`): takes the snapshot dictionary and routes each field to the correct child node via a registered handler map.
|
||||
- Registration pattern: `router.register("monologue", monologue_display.consume_monologue)` — callable-based dispatch. Handlers are registered in `main.gd`'s `_ready()`.
|
||||
- `main.gd` `_process()` calls `router.dispatch(snapshot)` instead of 15+ individual `if snapshot.has("X"): child.consume_X()` blocks.
|
||||
- `main.gd` retains scene tree ownership (`@onready` node references), camera logic, and input handling — the router only handles snapshot dispatch.
|
||||
- After: `main.gd` should be under 350 lines.
|
||||
- Unit tests: construct a `SnapshotEventRouter` with mock handlers, dispatch a snapshot, assert each handler received the correct field value.
|
||||
|
||||
Integration points: `client/scripts/main.gd` (refactor target), new file `client/scripts/snapshot_event_router.gd`. No server changes, no protocol changes.
|
||||
|
||||
Gotcha: Some consume methods in `main.gd` have cross-field dependencies (e.g., camera position depends on both `player_position` and `_camera_anchored` state). Identify these upfront and keep them in `main.gd` directly — only pure per-field dispatch moves to the router. Do not force all logic into the router pattern.
|
||||
|
||||
### #560 — Refactor: unify duplicate YAML parsers
|
||||
|
||||
Code review finding: `client/scripts/checklist/checklist_evaluator.gd` contains its own YAML parser that partially duplicates `client/scripts/autoloads/ui_strings.gd`'s `_parse_yaml()` method.
|
||||
|
||||
What this ticket must deliver:
|
||||
- Extract a shared `YamlParser` utility class at `client/scripts/util/yaml_parser.gd` (create the `util/` directory).
|
||||
- `YamlParser` exposes a static method `parse(text: String) -> Dictionary` that handles the common subset of YAML used across both call sites (key: value pairs, nested maps, arrays).
|
||||
- Replace `checklist_evaluator.gd`'s inline parser with `YamlParser.parse()`.
|
||||
- Replace `ui_strings.gd`'s `_parse_yaml()` with `YamlParser.parse()` (or delegate to it, keeping the method signature stable).
|
||||
- Unit tests: parse a sample YAML string with nested keys, arrays, and string values; assert round-trip correctness.
|
||||
|
||||
Integration points: `client/scripts/checklist/checklist_evaluator.gd`, `client/scripts/autoloads/ui_strings.gd`, new `client/scripts/util/yaml_parser.gd`. No server changes.
|
||||
|
||||
Gotcha: The two existing parsers may handle edge cases differently. Write the unit tests first against both parsers to document their current behavior, then unify. Prioritize correctness for existing content files (`client/data/ui-strings.yaml` and any checklist YAML files) — do not break live content.
|
||||
|
||||
## Dependency Chain
|
||||
|
||||
```
|
||||
#557 (game_state derived state) ─┐
|
||||
#558 (dialogue_box coupling) ├─ all parallel, no inter-dependency
|
||||
#559 (main.gd SnapshotEventRouter)│ #558 feeds into #559 (signal wiring in main.gd)
|
||||
#560 (unify YAML parsers) ─┘
|
||||
```
|
||||
|
||||
#558 should complete before #559 so that the new signals from dialogue_box are wired into `main.gd` as part of the router work, not as a separate pass. Otherwise all four tickets run in parallel.
|
||||
|
||||
## PR Workflow
|
||||
|
||||
When ready to submit, create a PR with the `tea` CLI. All flags are required to avoid TTY prompts:
|
||||
|
||||
```bash
|
||||
tea pr create --repo jpmschweitzer/settled-reach --login schweitz \
|
||||
--title "feat(client): save/load UI and code quality refactors" \
|
||||
--description "body" --base main --head client
|
||||
```
|
||||
@@ -0,0 +1,74 @@
|
||||
# Sprint 20: Shape — Joint Coordination
|
||||
|
||||
**Goal:** The social site template system gains its foundational schema; triangles become generatable and observable as escalating tensions; the client gains save/load UI and code quality improvements.
|
||||
|
||||
## Pre-Sprint Decisions
|
||||
|
||||
No blocking pre-sprint decisions are required. All selected tickets have their upstream decisions confirmed.
|
||||
|
||||
| Decision | Status | Impact |
|
||||
|----------|--------|--------|
|
||||
| D-087 (v0.1 triangle configuration) | Confirmed | Server #106/#107/#250 must produce T1-T5 triangle types |
|
||||
| D-089 (self-contained forks, no cascade) | Confirmed | No cross-triangle state in `TriangleDef` or `TriangleState` |
|
||||
| D-025 (social site as atomic template unit) | Confirmed | Server #163/#164/#165 schema shapes |
|
||||
| D-020 (Godot = pure renderer) | Confirmed | Client refactors #557-#560 are motivated by this |
|
||||
|
||||
**One open question to monitor:**
|
||||
- **Q-028 (line ID collision)** — resolved by D-084 (dual-namespace scheme), but the `RoleCounter` implementation is referenced in D-084 as a requirement for `server/src/content/npc_slug.rs`. Ticket #163 (role definition schema) should create the `server/data/templates/` directory structure; confirm with server team whether the slug counter module belongs in this sprint or the next.
|
||||
|
||||
## Sprint Completion Proof
|
||||
|
||||
The sprint is done when all of the following are observable:
|
||||
|
||||
1. **Template schema compiles and round-trips**: `cargo test -p server -- template` passes. A YAML file at `server/data/templates/sample_role.yaml` deserializes cleanly into a `RoleSchema` struct and re-serializes with identical content.
|
||||
|
||||
2. **Triangle generation produces valid state**: `cargo test -p server -- triangle` passes. A 4-NPC test world with 2 `TriangleDef` entries produces 2 `TriangleState` components with valid role assignments and tension values within the configured range.
|
||||
|
||||
3. **Triangle escalation fires events**: A unit test simulates 60 ticks on a triangle configured to escalate at tick 50, asserts `TriangleCrisisEvent` was emitted at the correct tick.
|
||||
|
||||
4. **Single-ownership model serializes**: A world with 2 templates and a cross-reference survives a save/load round-trip: `TemplateOwnership` components and `TemplateReferenceMap` entries are identical before and after.
|
||||
|
||||
5. **Refactors don't regress tests**: `make ci-client` passes with #557-#560 merged. `game_state.apply_snapshot()` contains no conditional accumulation logic. `dialogue_box.gd` has zero direct references to `GameState` or `AudioManager`. `main.gd` is under 350 lines.
|
||||
|
||||
6. **District layout design decided**: #153 produces a confirmed D-record specifying: complete district topology (how terminal, bar, smuggling corridors, and gate connect), tile dimensions per zone, access topology, and sightline constraints. Unblocks #155 (hand-crafted location authoring) and #188 (triangle instantiation).
|
||||
|
||||
## Test Plan Alignment (D-030)
|
||||
|
||||
Sprint 20 is Phase 3+ territory (D-030 sub-decision #8: Phase 3 = sprint 5+: CauseChain verification + divergent snapshots). The new template/triangle system introduces the first simulation structures that will eventually require CauseChain verification.
|
||||
|
||||
| Ticket | Test scope | Priority |
|
||||
|--------|------------|----------|
|
||||
| #163 | Unit: YAML round-trip, constraint validation | High |
|
||||
| #164 | Unit: spec validation, tile count range | High |
|
||||
| #165 | Unit: ownership component, reference map | High |
|
||||
| #106 | Unit: triangle YAML round-trip, conflict validation | High |
|
||||
| #107 | Unit: constraint satisfaction, minimum 2 triangles | High |
|
||||
| #250 | Unit: escalation timing, crisis event emission, resolve command | High |
|
||||
| #557-#560 | Regression: existing test suite must remain green | Medium |
|
||||
| #153 | Design discussion: district layout confirmed as D-record | High |
|
||||
|
||||
The triangle system's `TriangleCrisisEvent` is the first event candidate for CauseChain integration. Do not wire CauseChain this sprint — but structure the event type so it can carry a `CauseChain` field in a future sprint without breaking callsites.
|
||||
|
||||
## Cross-Team Integration Points
|
||||
|
||||
| Server ticket | Client dependency | Notes |
|
||||
|---------------|-------------------|-------|
|
||||
| #165 (`TemplateOwnership` serialization) | None this sprint | Adds fields to `SaveStateV1` — no client protocol change needed until template data is rendered |
|
||||
| #250 (`TriangleCrisisEvent` in `ObserverSnapshot`) | None this sprint | Event added to snapshot schema as stub — client rendering of triangle state is Sprint 21+ |
|
||||
|
||||
| Planning ticket | Downstream impact | Notes |
|
||||
|-----------------|-------------------|-------|
|
||||
| #153 (district layout design) | Unblocks #155, #188 | Layout decisions feed into Sprint 21 hand-crafted location authoring and triangle instantiation |
|
||||
|
||||
No live cross-team protocol dependencies this sprint. Server and client work in parallel.
|
||||
|
||||
## Deferred to Sprint 21
|
||||
|
||||
The following tickets are natural Sprint 21 candidates once this sprint's foundation lands:
|
||||
|
||||
- **#166** (Template-to-instance mapping) — instantiate templates into the world; requires #163+#164+#165
|
||||
- **#161** (Template instantiation engine) — full NPC spawn from template; requires #163+#164+#165+#166
|
||||
- **#159** (Tier 2 template definition format) — YAML schema for the full template document; blocked by #163
|
||||
- **#108** (Cross-template triangle generation) — requires #106+#107
|
||||
- **#109** (Triangle validation) — quality checks on generated triangles; requires #107
|
||||
- **#155** (Hand-crafted location authoring) — requires #153 (station district layout design), which is being resolved this sprint on the planning branch
|
||||
@@ -0,0 +1,82 @@
|
||||
# Sprint 20: Shape — Planning Tasks
|
||||
|
||||
**Goal:** Resolve the station district layout design through structured discussion, producing a confirmed D-record that unblocks Sprint 21 location authoring and triangle instantiation.
|
||||
|
||||
**Branch:** `planning`
|
||||
**Agents:** Gestalt (systems design), Miri (worldbuilding), Araminta (visual/spatial), Tyre (technical feasibility), Paula (narrative), Ozzie (player experience), Qatux (documenter), SI (project manager)
|
||||
|
||||
## Tickets
|
||||
|
||||
| # | Title | Type | Blocks |
|
||||
|---|-------|------|--------|
|
||||
| #153 | Station district layout design | design discussion | #155, #188 |
|
||||
|
||||
## Discussion Format
|
||||
|
||||
Ticket #153 is a **design discussion** — workshop-style, run on the planning branch. The output is a confirmed decision record (D-record) in `decisions/content.md` or `decisions/architecture.md`.
|
||||
|
||||
### Context: What Already Exists
|
||||
|
||||
Three spatial layouts have been authored (all by Araminta, Sprint 17):
|
||||
- **The Terminal** (logistics hub): `docs/design/spatial-layout-terminal-v01.md` — 44×28 tiles, cool grey-navy
|
||||
- **The Last Shift** (bar): `docs/design/spatial-layout-bar-v01.md` — 28×22 tiles, warm dark amber
|
||||
- **Smuggling corridors**: `docs/design/spatial-layout-smuggling-corridors-v01.md` — overlay on terminal + bar + maintenance corridors
|
||||
|
||||
Station profile: `docs/design/sova-station-profile.md` — defines 6 districts, only Transit District is playable in v0.1.
|
||||
|
||||
Key decisions already confirmed:
|
||||
- D-025: Social site / functional cluster as atomic template unit
|
||||
- D-036: Sova Transit District / Krenn System as v0.1 setting
|
||||
- D-050: Velen naming and climate
|
||||
|
||||
Open question: Q-036 (district skeleton as generator output) — relevant but not blocking; the v0.1 district is hand-authored.
|
||||
|
||||
### What #153 Must Decide
|
||||
|
||||
The individual locations exist as standalone layouts. What's missing is **how they connect** — the district as a whole:
|
||||
|
||||
1. **District topology**: How do the terminal, bar, gate corridor cluster, and smuggling hideout spaces relate spatially? What corridors connect them? What's the walking distance/time between key locations?
|
||||
|
||||
2. **Gate corridor cluster** (#157): The span gate area — customs, cargo staging, commuter flow. This is the district's entry point and a social chokepoint. Needs spatial spec at the same fidelity as the terminal and bar.
|
||||
|
||||
3. **Access topology**: Public → semi-restricted → restricted zones. How does the access gradient map across the whole district? Where are the boundaries the player must navigate?
|
||||
|
||||
4. **Sightline constraints**: Which locations have line-of-sight to which? This is gameplay-critical — the player's observation opportunities depend on where they can see from where.
|
||||
|
||||
5. **NPC traffic patterns**: How do NPCs flow through the district? Shift changes, commuter routes, social gathering patterns. The spatial layout determines what the player can observe by being in the right place at the right time.
|
||||
|
||||
6. **Total district dimensions**: What's the bounding box? How does tile count affect performance (server spatial queries, client rendering)?
|
||||
|
||||
### Discussion Rounds
|
||||
|
||||
**Round 1 — Inventory and constraints**
|
||||
Each agent reviews the existing layouts and states what their domain requires from the district layout. Gestalt: gameplay loops that need spatial support. Miri: setting consistency, what the station profile implies. Araminta: visual continuity across zones, tilemap feasibility. Tyre: performance constraints, tilemap size limits. Paula: narrative beats that need specific spatial staging. Ozzie: navigation feel, does the district feel explorable and readable.
|
||||
|
||||
**Round 2 — Topology proposals**
|
||||
Propose concrete district maps (ASCII or description). How do the existing layouts connect? Where does the gate corridor go? What fills the space between authored locations?
|
||||
|
||||
**Round 3 — Convergence**
|
||||
Resolve conflicts, pick a topology, specify dimensions. Draft the D-record.
|
||||
|
||||
### Output
|
||||
|
||||
- A confirmed D-record specifying:
|
||||
- District topology diagram (which locations connect to which, via what corridors)
|
||||
- Approximate tile dimensions per zone and total district
|
||||
- Access topology (public/semi-restricted/restricted gradient)
|
||||
- Key sightline relationships
|
||||
- Gate corridor cluster spatial spec (or a separate ticket if too large)
|
||||
- Updated `decisions/` domain file
|
||||
- Gate corridor layout doc at `docs/design/spatial-layout-gate-v01.md` if produced
|
||||
|
||||
### Reference Files
|
||||
|
||||
Read before starting:
|
||||
- `docs/design/spatial-layout-terminal-v01.md`
|
||||
- `docs/design/spatial-layout-bar-v01.md`
|
||||
- `docs/design/spatial-layout-smuggling-corridors-v01.md`
|
||||
- `docs/design/sova-station-profile.md`
|
||||
- `decisions/content.md` — D-025 (social sites), D-036 (Sova setting)
|
||||
- `decisions/architecture.md` — D-014 (tile-based movement)
|
||||
- `decisions/perception.md` — D-059 (fog layers, zone temperature)
|
||||
- `decisions/questions.md` — Q-036 (district skeleton as generator output)
|
||||
@@ -0,0 +1,147 @@
|
||||
# Sprint 20: Shape — Server Tasks
|
||||
|
||||
**Goal:** The social site template system gains its foundational schema; triangles become generatable and observable as escalating tensions; the client gains save/load UI and code quality improvements.
|
||||
|
||||
**Branch:** `server`
|
||||
**Agents:** Dudley (simulation), Tyre (architecture), Hoshe (QA)
|
||||
|
||||
## Carry-over from Sprint 19
|
||||
|
||||
None. Sprint 19 treated as complete.
|
||||
|
||||
## New Tickets
|
||||
|
||||
| # | Title | Blocked by |
|
||||
|---|-------|------------|
|
||||
| #163 | Role definition schema | — |
|
||||
| #164 | Spatial requirement specification | — |
|
||||
| #165 | Single-ownership model | — |
|
||||
| #106 | Triangle definition schema | — |
|
||||
| #107 | Intra-template triangle generation | — |
|
||||
| #250 | Triangle escalation system | — (#103, #105 done) |
|
||||
|
||||
Use `db/connectors/ticket show <id>` for full details.
|
||||
|
||||
## Key Decisions
|
||||
|
||||
- `decisions/content.md` — D-023 (three-tier content model: Tier 1 drama modules, Tier 2 templates, Tier 3 procedural), D-024 (NPC generation model: 10 axes, triangles as atomic social unit — 2 per template minimum), D-025 (social site / functional cluster as atomic template unit: 4-8 NPCs, 15-40 tiles, single-ownership with reference links), D-029 (population entanglement ratio: 30/50/20 — triangles are the 50% mundane layer)
|
||||
- `decisions/scope.md` — D-087 (v0.1 triangle configuration: T1 Kael-Smuggler-Ring, T2 Sera-Detective-Commission, T4 Drin-System-Ring as active forks; T3 and T5 as passive tensions), D-089 (self-contained triangle forks for v0.1, no cross-triangle cascade)
|
||||
- `decisions/architecture.md` — D-010 (deterministic simulation: BTreeMap for all collections, no HashMap), D-026 (simulation tiers: Active-tier NPCs are fully simulated; template instantiation populates Active tier), D-041 (KnowledgeGraph: per-entity component — template instantiation must assign KnowledgeGraph to each spawned NPC)
|
||||
|
||||
## Notes
|
||||
|
||||
### #163 — Role definition schema
|
||||
|
||||
The `RoleDefinition` struct already exists in `server/src/npc/generate.rs` as a procedural generation input — it defines `name`, location pool entries, and per-axis ranges. This ticket extends that to become the canonical Tier 2 role schema.
|
||||
|
||||
What this ticket must deliver:
|
||||
- A `RoleSchema` type (new, distinct from `RoleDefinition`) in a new `server/src/content/template/` module (or `server/src/content/types.rs` extended). Fields: `role_id: RoleId` (newtype over String), `required_traits: Vec<PersonalityTrait>`, `skill_focus: Vec<Skill>`, `relationship_constraints: Vec<RelationshipConstraint>`, `routine_template: Vec<RoutineEntry>` — these are constraints fed into the NPC generator, not hardcoded values.
|
||||
- A `RelationshipConstraint` type: `{ with_role: RoleId, kind: RelationshipKind, required_trust: TrustRange }`. Constrains who this role must be in relationship with within the same template.
|
||||
- YAML deserialization via `serde`. Schema files will live at `server/data/templates/` (create the directory).
|
||||
- Unit tests: round-trip YAML serialize/deserialize a sample role schema. Validate constraint logic (no self-referential constraints, no duplicate role_id within a template).
|
||||
|
||||
Integration points: `server/src/npc/generate.rs` (`RoleDefinition` → becomes a builder derived from `RoleSchema`), `server/src/content/types.rs` (existing content type infrastructure), `server/src/knowledge/types.rs` (`StableId`, `RelationshipKind`).
|
||||
|
||||
Gotcha: `RoleId` must be stable across save/load — it's a string slug, not a bevy `Entity`. Keep it a newtype over `String` so it serializes cleanly with `StableId`.
|
||||
|
||||
### #164 — Spatial requirement specification
|
||||
|
||||
No existing spatial specification type exists. This is greenfield within the template system.
|
||||
|
||||
What this ticket must deliver:
|
||||
- A `SpaceSpec` type: `{ tile_count_min: u32, tile_count_max: u32, sightline_zones: Vec<SightlineZone>, privacy_level: PrivacyLevel, traffic_pattern: TrafficPattern }`.
|
||||
- `SightlineZone`: a named sub-area with a coverage radius in sim tiles (0.5m each, per D-066). Example: `{ name: "bar_counter", radius: 4 }` — 4 sim tiles = 2m clear sightline.
|
||||
- `PrivacyLevel` enum: `Public`, `SemiPrivate`, `Private`. Governs NPC behavior (NPCs are less likely to disclose secrets in Public spaces).
|
||||
- `TrafficPattern` enum: `Thoroughfare`, `Destination`, `Restricted`. Governs procedural NPC routine routing through this space.
|
||||
- YAML deserialization. Schema files co-locate with role schemas at `server/data/templates/`.
|
||||
- Unit tests: sample spec round-trip, validation that min <= max tile count.
|
||||
|
||||
Integration points: `server/src/content/template/` (new module or extended `server/src/content/types.rs`), future chunk generation (`server/src/simulation/` — spatial specs will inform where templates are placed in the map). No simulation code changes needed this sprint — spec types only.
|
||||
|
||||
Gotcha: Tile counts are in sim tiles (0.5m). A 15-40 visual tile space (per D-025) = 30-80 sim tiles. Document this conversion explicitly in code comments to prevent future confusion.
|
||||
|
||||
### #165 — Single-ownership model
|
||||
|
||||
NPCs are owned by exactly one template, with reference links to others (D-025). No existing ownership component exists.
|
||||
|
||||
What this ticket must deliver:
|
||||
- A `TemplateOwnership` ECS component: `{ template_id: TemplateId, role_id: RoleId }`. Assigned at template instantiation, never reassigned.
|
||||
- A `TemplateId` newtype over `u64` — deterministic from world seed + template slug hash.
|
||||
- A `TemplateReference` struct: `{ from_template: TemplateId, to_template: TemplateId, via_role: RoleId, relationship_metadata: RelationshipKind }`. Stored in a `TemplateReferenceMap` resource (a `BTreeMap<TemplateId, Vec<TemplateReference>>`).
|
||||
- Logic for lifecycle coordination: when a template is unloaded (NPC tier drops to State-saved or Ungenerated per D-026), `TemplateReference` links are preserved in the serialized state, not destroyed.
|
||||
- Unit tests: spawn two templates with cross-references, verify `TemplateReferenceMap` entries, verify `TemplateOwnership` components.
|
||||
|
||||
Integration points: `server/src/simulation/tier.rs` (tier transitions must preserve `TemplateOwnership`), `server/src/simulation/save_state.rs` (serialize `TemplateOwnership` and `TemplateReferenceMap` as part of `SaveStateV1` — add fields), `server/src/npc/generate.rs` (generator receives `TemplateId` + `RoleId` at spawn time).
|
||||
|
||||
Gotcha: `TemplateId` from seed + slug hash must be deterministic across save/load — use `StdHasher` is prohibited (non-deterministic), use a seeded hash (e.g., `std::hash::Hasher` from a fixed algorithm) or simply hash the slug string bytes with a fixed polynomial. Log the `TemplateId` computed value in tests for debugging.
|
||||
|
||||
### #106 — Triangle definition schema
|
||||
|
||||
The D-024 spec says triangles are the atomic unit of social intrigue — 2 per template minimum, 1 cross-template. No `TriangleDef` type exists anywhere in the codebase.
|
||||
|
||||
What this ticket must deliver:
|
||||
- A `TriangleDef` type: `{ triangle_id: TriangleId, roles: [RoleId; 3], conflict_type: ConflictType, interest_axes: [NpcAxis; 3], relationship_constraints: Vec<RelationshipConstraint> }`. Three roles, each with a conflicting axis (Want, Secret, Tolerance, etc.).
|
||||
- `ConflictType` enum based on D-087 active fork patterns: `ResourceCompetition`, `LoyaltyConflict`, `SecretExposure`, `AuthorityChallenge`. Passive tensions use `LatentTension` variant.
|
||||
- `TriangleId` newtype over `u64` — deterministic from template seed + role triple.
|
||||
- Validation: all three roles must be distinct within the template; the conflict type must map to at least one axis divergence (no conflict on identical axis values).
|
||||
- YAML deserialization. Triangle definitions are authored as part of a template file or as a standalone `triangles.yaml` per template — Dudley to decide the co-location approach.
|
||||
- Unit tests: sample triangle round-trip, validation for duplicate roles, validation for self-consistent conflict.
|
||||
|
||||
Integration points: `server/src/content/template/` (lives alongside `RoleSchema` and `SpaceSpec`), `server/src/npc/generate.rs` (the generator will consume `TriangleDef` in #107 to assign axis values that produce the desired conflict), `decisions/content.md` D-087 (v0.1 triangles T1-T5 should be expressible in this schema).
|
||||
|
||||
Gotcha: D-089 — self-contained triangles for v0.1, no cross-triangle cascade. Do not add cross-triangle state fields to `TriangleDef`. Cross-template triangles are expressed by a `TriangleDef` that references a `RoleId` from a different `TemplateId` — the cross-template link is in the role, not a special triangle type.
|
||||
|
||||
### #107 — Intra-template triangle generation
|
||||
|
||||
The template system can now describe triangles (#106). This ticket generates them from the description.
|
||||
|
||||
What this ticket must deliver:
|
||||
- A `generate_intra_template_triangles(world: &mut World, template_id: TemplateId, defs: &[TriangleDef], rng: &mut SimRng) -> Vec<TriangleState>` function.
|
||||
- `TriangleState` ECS component: `{ triangle_id: TriangleId, role_assignments: BTreeMap<RoleId, StableId>, tension: u8, phase: TrianglePhase }`. `tension` starts at a seeded value within a configured range. `TrianglePhase` enum: `Dormant`, `Simmering`, `Active`, `Resolved`.
|
||||
- Constraint satisfaction: for each `TriangleDef`, assign generated NPCs (by `StableId`) to the three roles. Validate that the NPC's axis values satisfy the conflict (e.g., for a `LoyaltyConflict`, the NPC filling the `loyalty_torn` role must have a Relationships axis with entries for both of the other two roles).
|
||||
- Minimum 2 triangles per template — emit an error (not a panic) if the template definition provides fewer than 2 `TriangleDef` entries.
|
||||
- Unit tests: spawn a 4-NPC template, generate 2 triangles, assert `TriangleState` components exist and role assignments are valid, assert constraint satisfaction.
|
||||
|
||||
Integration points: `server/src/npc/generate.rs` (NPC generation runs first; triangle generation consumes the generated NPCs' axis values), `server/src/content/template/` (#106 types), `server/src/simulation/rng.rs` (`SimRng` for determinism).
|
||||
|
||||
Gotcha: Constraint satisfaction can fail if the NPC pool doesn't provide a suitable candidate for a role. Implement a fallback: if no NPC satisfies the strict constraint, pick the closest match and log a warning. Do not panic — world generation must be robust to imperfect seeds.
|
||||
|
||||
### #250 — Triangle escalation system
|
||||
|
||||
Blockers #103 (relationship dynamics) and #105 (tolerance threshold triggers) are done. `TriangleState` from #107 is available this sprint.
|
||||
|
||||
What this ticket must deliver:
|
||||
- An ECS system `tick_triangle_escalation` that runs once per game-minute (every 10 ticks per D-031). For each `TriangleState` in `Simmering` or `Active` phase: increment `tension` by a seeded per-triangle rate (drawn from `SimRng` at world-gen time, stored on `TriangleState`). When `tension` exceeds the lowest `ToleranceThreshold` among the triangle's three NPCs, transition `phase` from `Simmering` to `Active`.
|
||||
- Observable events: when a triangle enters `Active`, emit a `TriangleCrisisEvent` (new event type) containing `triangle_id`, `role_assignments`, and `trigger_npc: StableId`. The monologue system and knowledge system can subscribe to this event — but do not wire those subscribers this sprint. Emit the event; downstream consumption is future work.
|
||||
- `Resolved` transition: when the player resolves an active fork (mechanism TBD — stub a `ResolveTriangle(TriangleId)` command for now), set `phase = Resolved`. D-089: resolution does not cascade.
|
||||
- Unit tests: simulate 60 ticks on a triangle with a known tension rate, assert `Active` transition at the expected tick. Test `Resolved` command sets phase correctly.
|
||||
|
||||
Integration points: `server/src/simulation/tier.rs` (`tick_triangle_escalation` only runs on Active-tier NPCs per D-026), `server/src/simulation/time.rs` (game-minute scheduler — 10-tick interval), `server/src/npc/tolerance.rs` (`ToleranceThreshold` component), `server/src/npc/relationships.rs` (`RelationshipGraph` — tension rate influenced by relationship stress), `server/src/bridge/types.rs` (add `TriangleCrisisEvent` to `ObserverSnapshot` for future client rendering).
|
||||
|
||||
Gotcha: Different seeds produce different tolerance thresholds — the same triangle template can escalate in 5 minutes or 30 minutes depending on the seed. This is intentional (D-087). Do not hardcode a tension rate — it must come from `SimRng` at world-gen time and be stored on the component.
|
||||
|
||||
## Dependency Chain
|
||||
|
||||
```
|
||||
#163 (Role definition schema) ─┐
|
||||
#164 (Spatial requirement spec) ├─ parallel, no inter-dependency
|
||||
#165 (Single-ownership model) ─┘
|
||||
│
|
||||
└─ feeds #166 (Template-to-instance mapping, Sprint 21)
|
||||
|
||||
#106 (Triangle definition schema) ──► #107 (Intra-template generation) ──► #250 (Escalation system)
|
||||
│
|
||||
└─ feeds #108 (Cross-template generation, Sprint 21)
|
||||
```
|
||||
|
||||
#163/#164/#165 and #106/#107/#250 are two parallel tracks. All six tickets can begin in week 1; #107 and #250 gate on #106 completing first.
|
||||
|
||||
## PR Workflow
|
||||
|
||||
When ready to submit, create a PR with the `tea` CLI. All flags are required to avoid TTY prompts:
|
||||
|
||||
```bash
|
||||
tea pr create --repo jpmschweitzer/settled-reach --login schweitz \
|
||||
--title "feat(simulation): social site template schema and triangle system" \
|
||||
--description "body" --base main --head server
|
||||
```
|
||||
@@ -0,0 +1,49 @@
|
||||
# Sprint 21: Instantiate — CI Tasks
|
||||
|
||||
**Goal:** The template system becomes executable — templates spawn NPCs, assign triangles, and place them in world space; cross-template triangles link social sites; the client gains save/load game flow; and the generator pipeline gets its architectural design.
|
||||
|
||||
**Branch:** `ci`
|
||||
**Agents:** Justine (build/deploy)
|
||||
|
||||
## New Tickets
|
||||
|
||||
| # | Title | Blocked by |
|
||||
|---|-------|------------|
|
||||
| #274 | Move connector scripts from db/connectors/ to tooling/db/ | — |
|
||||
|
||||
Use `db/connectors/ticket show <id>` for full details.
|
||||
|
||||
## Key Decisions
|
||||
|
||||
- `decisions/process.md` — tooling conventions and project structure
|
||||
|
||||
## Notes
|
||||
|
||||
**#274 — Move connector scripts from db/connectors/ to tooling/db/**
|
||||
- Current location: `db/connectors/` — contains `sqlite_connector.py`, `qdrant_connector.py`, `config.json`, and all wrapper scripts (`sqlite-query`, `sqlite-exec`, `sqlite-init`, `sqlite-seed`, `qdrant-search`, `qdrant-index`, `qdrant-health`, `qdrant-count`, `ticket`, `sprint`, `decision`).
|
||||
- Target location: `tooling/db/` — consolidates all tooling under `tooling/` per project structure conventions. The `db/` directory retains schema and seed data only.
|
||||
- Steps:
|
||||
1. Create `tooling/db/` directory.
|
||||
2. Move all scripts and `config.json`. Preserve executable bits (`chmod +x` on wrapper scripts).
|
||||
3. Update `CLAUDE.md` table ("CLI tools" section) to reference new paths.
|
||||
4. Update `docs/DEVOPS.md` if it references `db/connectors/` paths.
|
||||
5. Update any `Makefile` targets that call `db/connectors/` directly.
|
||||
6. Update agent briefings and skill files that reference `db/connectors/` paths — check `.claude/skills/` and `.claude/agents/`.
|
||||
7. Leave a `db/connectors/` stub or symlink pointing to `tooling/db/` if any external scripts depend on the old path. Remove after one sprint.
|
||||
- Do NOT move `db/schema.sql`, `db/seed.sql`, or `settledreach.db` — those stay in `db/`.
|
||||
- The `settledreach.db` lives in the parent directory (`../settledreach.db` relative to the worktree root) and is not tracked in git — no change needed there.
|
||||
- Acceptance: `make ci` passes. `db/connectors/ticket list` either works via symlink or has been replaced by `tooling/db/ticket list` everywhere it is referenced.
|
||||
|
||||
## Dependency Chain
|
||||
|
||||
```
|
||||
#274 (connector script move) — standalone
|
||||
```
|
||||
|
||||
## PR Workflow
|
||||
|
||||
When ready to submit, create a PR with `tea` CLI:
|
||||
|
||||
```bash
|
||||
tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "chore(ci): move db/connectors/ to tooling/db/" --description "body" --base main --head ci
|
||||
```
|
||||
@@ -0,0 +1,56 @@
|
||||
# Sprint 21: Instantiate — Client Tasks
|
||||
|
||||
**Goal:** The template system becomes executable — templates spawn NPCs, assign triangles, and place them in world space; cross-template triangles link social sites; the client gains save/load game flow; and the generator pipeline gets its architectural design.
|
||||
|
||||
**Branch:** `client`
|
||||
**Agents:** Stig (dev), Hoshe (QA)
|
||||
|
||||
## New Tickets
|
||||
|
||||
| # | Title | Blocked by |
|
||||
|---|-------|------------|
|
||||
| #257 | Save/load game flow | — (#256 done) |
|
||||
| #561 | Housekeeping: move debug_overlay.gd to ui/ directory | — |
|
||||
|
||||
Use `tooling/db/ticket show <id>` for full details on any ticket.
|
||||
|
||||
## Key Decisions
|
||||
|
||||
- `decisions/architecture.md` — D-020 (Godot = pure renderer, no game logic in GDScript), D-085 (per-game save directories under `user://saves/<game-id>/`), D-088 (3-state pause: Normal/Overlay/Paused, server-authoritative)
|
||||
- `decisions/scope.md` — D-027 (vertical slice: smuggler + detective, two-character proof)
|
||||
|
||||
## Notes
|
||||
|
||||
**#257 — Save/load game flow**
|
||||
- Server-side serialization (`SaveStateV1`, `SaveLoadCommand`) landed in Sprint 19 (#553, #553). The client `SessionManager` autoload (`client/scripts/autoloads/session_manager.gd`) already creates per-game directories and tracks `current_game_id`. The `input.rs` server-side hook for `SaveLoadCommand::Save` and `SaveLoadCommand::Load` is in place.
|
||||
- What's missing: the client UI flow — save-to-file and load-from-file screens, and F5/F6 quicksave/quickload keybinds wired to `PlayerInput`.
|
||||
- `client/ui/main_menu.gd` exists. Add a "Load Game" screen that calls `SessionManager.list_game_dirs()` and lets the player select a save.
|
||||
- F5 quicksave flow: send `PlayerInput { action: QuickSave }` → server responds with serialised save data → client writes to `user://saves/<game-id>/quicksave.sav`. F6 quickload: reverse.
|
||||
- Loading screen: a minimal full-screen overlay ("Resuming...") during the round-trip to prevent input during load. No elaborate animation needed for v0.1.
|
||||
- D-020 constraint: no game logic in client. The client never constructs save data — it only sends the command and receives the file bytes from the server.
|
||||
- Existing stub in `session_manager.gd` line 71 notes: "The actual F5 save will be wired here once server supports SaveCommand." Server supports it now — wire it.
|
||||
- Acceptance: (1) F5 in-game triggers quicksave, file appears at correct path. (2) F6 reloads it, player position and NPC state match save. (3) Main menu "Load Game" lists existing saves sorted by date.
|
||||
|
||||
**#561 — Housekeeping: move debug_overlay.gd to ui/ directory**
|
||||
- `client/scripts/ui/debug_overlay.gd` is the odd one out — all 17 other UI components live in `client/ui/`. This was flagged in a code review.
|
||||
- Steps: move `client/scripts/ui/debug_overlay.gd` (and its `.uid` file) to `client/ui/debug_overlay.gd`. Update any `preload()` or `load()` references. Update the `.tscn` that instances it if one exists.
|
||||
- Check `client/scripts/rendering/` and `client/scripts/autoloads/` for any imports of the old path.
|
||||
- If moving would break more than 3 references and the distinction is intentional (debug overlay is a script, not a scene-based UI), document the distinction in a comment at the top of the file instead, and close the ticket as "documented not moved."
|
||||
- Acceptance: `make ci-client` passes with the file at its new location, or the distinction is documented in-file.
|
||||
|
||||
## Dependency Chain
|
||||
|
||||
```
|
||||
#257 (save/load game flow) — standalone
|
||||
#561 (debug_overlay housekeeping) — standalone, parallel
|
||||
```
|
||||
|
||||
Both tickets are independent and can be developed in parallel.
|
||||
|
||||
## PR Workflow
|
||||
|
||||
When ready to submit, create a PR with `tea` CLI:
|
||||
|
||||
```bash
|
||||
tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "feat(client): Sprint 21 save/load game flow" --description "body" --base main --head client
|
||||
```
|
||||
@@ -0,0 +1,116 @@
|
||||
# Sprint 21: Instantiate — Joint Coordination
|
||||
|
||||
**Goal:** The template system becomes executable — templates spawn NPCs, assign triangles, and place them in world space; cross-template triangles link social sites; the client gains save/load game flow; and the generator pipeline gets its architectural design.
|
||||
|
||||
## Pre-Sprint Decisions
|
||||
|
||||
No blocking pre-sprint decisions are required. All selected implementation tickets have their upstream decisions confirmed.
|
||||
|
||||
| Decision | Status | Impact |
|
||||
|----------|--------|--------|
|
||||
| D-025 (social site as atomic template unit) | Confirmed | Server #159/#166/#161 schema and instantiation shapes |
|
||||
| D-024 (NPC 10-axis model, 2 triangles minimum per template, 1 cross-template) | Confirmed | Server #108/#109 triangle requirements |
|
||||
| D-087 (v0.1 triangle config: 3 active forks, 2 passive tensions) | Confirmed | #108 must produce triangle types consistent with T1-T5 fork taxonomy |
|
||||
| D-089 (self-contained forks, no cross-triangle cascade) | Confirmed | #108 cross-template triangle uses reference links, not shared state |
|
||||
| D-085 (per-game save directories) | Confirmed | Client #257 save/load flow writes to `user://saves/<game-id>/` |
|
||||
| D-020 (Godot = pure renderer) | Confirmed | Client #257 never constructs save data — sends command, receives file bytes |
|
||||
| D-059 (fog: five layers, shader-based) | Confirmed | Visual #564 tuning target — alpha values must match D-059 layer specs |
|
||||
| D-066 (dual-scale grid, 6-8 sim tile fog gradient) | Confirmed | Visual #564 must not alter `CLEAR_THRESHOLD`/`PERIPHERAL_LOW` constants that define gradient width |
|
||||
|
||||
**One open question to monitor:**
|
||||
- **Q-036 (district skeleton as generator output)** — actively being resolved in #562 this sprint. Resolution will gate #144 (Chunk generation system) and shape the Sprint 22 map pipeline tickets. SI will create follow-up tickets once #562 closes.
|
||||
|
||||
## Planning Ticket
|
||||
|
||||
| # | Title | Team | Agents |
|
||||
|---|-------|------|--------|
|
||||
| #562 | Generator architecture workshop — district/block/chunk pipeline | planning | Gestalt, Tyre, Miri, Araminta, Nigel, Qatux, SI |
|
||||
|
||||
**#562 — Generator architecture workshop**
|
||||
|
||||
Workshop brief: `docs/workshops/generator-architecture/workshop-brief.md`
|
||||
|
||||
**Purpose:** Establish the top-down procedural generator pipeline architecture — from geography down to individual chunk fill — that will power the 300-world model. The v0.1 Transit District is hand-authored; this workshop defines what the generator must be able to reproduce and what stub interfaces v0.1 must leave behind.
|
||||
|
||||
**Context documents to read before the discussion:**
|
||||
- `decisions/content.md` — D-025 (social site template as atomic unit)
|
||||
- `decisions/scope.md` — D-012 (chunk-based map system), D-036 (Sova as v0.1 setting)
|
||||
- `decisions/questions.md` — Q-036 (district skeleton as generator output), Q-037 (generator pipeline phases), Q-039 (gate topology generation)
|
||||
- `docs/design/sova-station-profile.md` — district types and 6-district layout
|
||||
- `docs/design/spatial-layout-terminal-v01.md`, `docs/design/spatial-layout-bar-v01.md` — hand-authored chunk cluster examples
|
||||
- `decisions/architecture.md` — D-093/D-094 (Sova spatial hierarchy: chunk/block/district naming and sizes)
|
||||
|
||||
**Three rounds:**
|
||||
1. **Domain Inventory** — each participant states what their domain requires from the generator (Gestalt: gameplay loop guarantees; Tyre: technical constraints on chunk size and hierarchy depth; Miri: cultural/economic variation inputs for 300 worlds; Araminta: visual coherence constraints on chunk fill and sub-chunk quarter system; Nigel: variation and replayability guarantees).
|
||||
2. **Pipeline Proposals** — propose pipeline stages, name the spatial hierarchy levels with tile dimensions, describe the district skeleton data structure.
|
||||
3. **Convergence** — resolve conflicts, lock spatial hierarchy, define district skeleton output format, set v0.1/generator boundary, draft D-record.
|
||||
|
||||
**Required outputs:**
|
||||
- D-record in `decisions/architecture.md`: pipeline stages, spatial hierarchy, sub-chunk quarter rules, multi-block reservation protocol, district skeleton data structure, v0.1/generator boundary
|
||||
- Resolution of Q-036 (district skeleton as atomic output — yes/no + formal definition)
|
||||
- Resolution of Q-037 scope (which phases land in which version window)
|
||||
- Follow-up implementation tickets: chunk data structure update (#143), district skeleton schema, zoning pass stub, block generation stub
|
||||
|
||||
**SI role in this workshop:** Create follow-up tickets from the D-record outputs and assign to Sprint 22 candidates. Update Q-036 and Q-037 status in `decisions/questions.md`.
|
||||
|
||||
## Sprint Completion Proof
|
||||
|
||||
The sprint is done when all of the following are observable:
|
||||
|
||||
1. **Template instantiation pipeline end-to-end:** Load a Tier 2 YAML from `server/data/templates/`, call the instantiation engine, assert NPCs spawn with correct roles, `TemplateOwnership` set, and 2+ `TriangleState` components generated. `cargo test -p server -- instantiation` passes.
|
||||
|
||||
2. **Cross-template triangle produced:** A test world with two instantiated templates (logistics hub + bar) generates exactly 1 cross-template `TriangleState` with role assignments spanning both templates. `cargo test -p server -- cross_template_triangle` passes.
|
||||
|
||||
3. **Triangle validation catches bad inputs:** Unit tests confirm that a triangle failing conflict viability, relationship coherence, or interest divergence returns a typed `ValidationError`, not a panic.
|
||||
|
||||
4. **Save/load round-trip works end-to-end:** F5 in-game writes a quicksave file to `user://saves/<game-id>/quicksave.sav`. F6 reloads it. Player position and NPC state (including open doors from #246) match the save. `make ci-client` passes.
|
||||
|
||||
5. **Environmental interaction:** A Door entity in a test world toggles walkability on player interaction. An Examinable entity returns examine text. Door state survives a save/load round-trip (open_doors persists in `SaveStateV1`).
|
||||
|
||||
6. **Error handling does not crash:** Sending a malformed IPC message mid-session produces a structured `SimError` response and leaves the server running. Integration test asserts this.
|
||||
|
||||
7. **Fog shader tuned:** Fog Theater gauntlet room — entities in peripheral zone are visibly dimmed but not opaque; deep fog shows a readable zone temperature tint; vision cone edge is soft. `make ci-client` passes.
|
||||
|
||||
8. **Generator architecture decided:** #562 closes with a confirmed D-record, Q-036 marked resolved, Q-037 scope defined. SI creates Sprint 22 candidate tickets for the chunk/district pipeline implementation.
|
||||
|
||||
## Test Plan Alignment (D-030)
|
||||
|
||||
Sprint 21 is Phase 3+ territory. The template instantiation system introduces the first simulation structures that compose content from YAML definitions into live ECS entities.
|
||||
|
||||
| Ticket | Test scope | Priority |
|
||||
|--------|------------|----------|
|
||||
| #159 | Unit: YAML round-trip, full Tier 2 document | High |
|
||||
| #166 | Unit: spawn + TemplateOwnership, TemplateReferenceMap entries | High |
|
||||
| #161 | Integration: YAML → instantiation engine → ECS entities + triangles | High |
|
||||
| #108 | Unit: cross-template role assignment, reference link creation | High |
|
||||
| #109 | Unit: all three validation failure modes + passing case | High |
|
||||
| #85 | Integration: malformed input → SimError, server survives | High |
|
||||
| #246 | Unit: Door walkability toggle, examine text return | High |
|
||||
| #257 | End-to-end: F5 save → F6 load → state match | High |
|
||||
| #561 | Regression: `make ci-client` passes at new file path | Medium |
|
||||
| #564 | Visual: Fog Theater gauntlet room manual check | High |
|
||||
| #274 | Regression: `make ci` passes with scripts at new paths | High |
|
||||
|
||||
## Cross-Team Integration Points
|
||||
|
||||
| Server ticket | Client dependency | Notes |
|
||||
|---------------|-------------------|-------|
|
||||
| #246 (`open_doors` in `SaveStateV1`) | #257 (save/load round-trip) | Server must add `open_doors: Vec<StableId>` to save struct before client can verify state restored correctly |
|
||||
| #85 (`SimError` message type) | #257 (loading screen) | Loading screen should handle `SimError` gracefully — show error state, not spinner forever |
|
||||
|
||||
| Planning ticket | Downstream impact | Notes |
|
||||
|-----------------|-------------------|-------|
|
||||
| #562 (generator architecture) | #143, #144 (chunk system) | D-record output gates Sprint 22 chunk pipeline work |
|
||||
|
||||
The #246/#257 dependency is soft — client can stub the door state verification in save/load tests until #246 lands.
|
||||
|
||||
## Deferred to Sprint 22
|
||||
|
||||
Natural Sprint 22 candidates once this sprint's foundation lands:
|
||||
|
||||
- **#155** (Hand-crafted location authoring) — build the v0.1 Transit District locations in Godot tilemap; requires #153 (done) and the district topology from that D-record
|
||||
- **#188** (Triangle instantiation in v0.1 content) — wire the 5 v0.1 triangles into the instantiation engine; requires #161
|
||||
- **#162** (Storyteller module activation) — draw Tier 1 modules from pool at game start; requires #161
|
||||
- **#143** (Chunk data structure) — blocked until #562 workshop defines the spatial hierarchy
|
||||
- **#176** (NPC pool generation: flat/mundane/entangled ratio) — requires #161 instantiation engine
|
||||
- Generator pipeline tickets — created by SI from #562 D-record outputs
|
||||
@@ -0,0 +1,91 @@
|
||||
# Sprint 21: Instantiate — Server Tasks
|
||||
|
||||
**Goal:** The template system becomes executable — templates spawn NPCs, assign triangles, and place them in world space; cross-template triangles link social sites; the client gains save/load game flow; and the generator pipeline gets its architectural design.
|
||||
|
||||
**Branch:** `server`
|
||||
**Agents:** Dudley (simulation dev), Tyre (arch), Hoshe (QA)
|
||||
|
||||
## New Tickets
|
||||
|
||||
| # | Title | Blocked by |
|
||||
|---|-------|------------|
|
||||
| #159 | Tier 2 template definition format | — (#158 done) |
|
||||
| #166 | Template-to-instance mapping | — (#163, #164, #165 done) |
|
||||
| #161 | Template instantiation engine | #166 |
|
||||
| #108 | Cross-template triangle generation | — (#106, #107 done) |
|
||||
| #109 | Triangle validation | — (#107 done) |
|
||||
| #85 | Error handling & recovery | — |
|
||||
| #246 | Basic environmental interaction | — |
|
||||
|
||||
Use `tooling/db/ticket show <id>` for full details on any ticket.
|
||||
|
||||
## Key Decisions
|
||||
|
||||
- `decisions/content.md` — D-023 (three-tier content model), D-024 (NPC generation model, 10 axes), D-025 (social site as atomic template unit), D-028 (dialogue tagged pools), D-029 (population entanglement ratio)
|
||||
- `decisions/architecture.md` — D-020 (Godot + Rust IPC, ObserverSnapshot), D-010 (deterministic simulation), D-087 (v0.1 triangle configuration), D-088 (3-state pause, server-authoritative), D-089 (self-contained forks, no cascade)
|
||||
|
||||
## Notes
|
||||
|
||||
**#159 — Tier 2 template definition format**
|
||||
- `server/src/content/template.rs` already defines `RoleSchema`, `SpaceSpec`, `TriangleDef` (Sprint 20). `#158` (Tier 1 drama module schema) is done — use it as a reference for YAML conventions.
|
||||
- This ticket extends that to the full Tier 2 document: roles, spaces, triangles, dialogue pool references, NPC routines, and spatial spec in one YAML document.
|
||||
- `server/data/templates/` directory exists (created by #385). Place the canonical Tier 2 schema definition and at least one authored example template here.
|
||||
- Acceptance: a complete Tier 2 template YAML round-trips cleanly through `RoleSchema` / `SpaceSpec` deserialization.
|
||||
|
||||
**#166 — Template-to-instance mapping**
|
||||
- Depends on the schema from #159, but #159 is partially stubbed already — Dudley can start here in parallel if schema is stabilising.
|
||||
- Core task: given a loaded `TemplateOwnership` + `SpaceSpec`, spawn NPC entities for each role slot, assign relationships, and record the mapping in `TemplateReferenceMap`.
|
||||
- Existing hook: `server/src/content/spawn.rs`. The `TemplateOwnership` component (Sprint 20) already tracks which template owns an entity. This ticket wires spawning to that system.
|
||||
- Instance lifecycle: entities spawned from a template must be tagged such that they can be despawned/reset cleanly (gauntlet room reset pattern in `server/src/test_world/` is a reference).
|
||||
- Acceptance: unit test spawns a 4-NPC template, asserts all role slots filled, `TemplateOwnership` set correctly on each entity, `TemplateReferenceMap` entries present.
|
||||
|
||||
**#161 — Template instantiation engine**
|
||||
- Blocked by #166. Once mapping works, this ticket wires the full pipeline: load YAML → deserialize → call spawn → generate triangles via `server/src/content/template.rs:assign_triangle_roles()` → register ownership.
|
||||
- Instance lifecycle management: track active instances, support unloading (for zone transitions and save/load).
|
||||
- Integration point with #166: the instantiation engine calls the mapping layer, not the raw spawn functions.
|
||||
- Acceptance: end-to-end test — load `server/data/templates/` logistics_hub YAML, instantiate it, assert NPCs exist with correct roles and 2+ `TriangleState` components generated.
|
||||
|
||||
**#108 — Cross-template triangle generation**
|
||||
- Sprint 20 landed intra-template triangles (#107). This ticket adds the 1 cross-template triangle required by D-024 ("2 per template minimum, 1 cross-template").
|
||||
- The existing `assign_triangle_roles()` in `server/src/content/template.rs` takes `&[TriangleDef]` — extend to accept role slots from two different `TemplateOwnership` sources.
|
||||
- D-025 ownership model: NPCs are owned by one template but can hold reference roles in another. The cross-template triangle uses `TemplateReferenceMap` reference links (carrying relationship metadata) not direct ownership links.
|
||||
- Acceptance: test world with two instantiated templates (logistics hub + bar) produces 1 cross-template `TriangleState` with role assignments spanning both templates.
|
||||
|
||||
**#109 — Triangle validation**
|
||||
- Quality checks on generated triangles. Three checks minimum: (1) conflict viability — the three role slots have at least one opposing Want axis, (2) relationship coherence — at least one Relationships entry links the three roles, (3) interest divergence — no two roles share identical Want+Secret combination.
|
||||
- Validation runs at instantiation time (not a separate pass). Return `Result<Vec<TriangleState>, ValidationError>` from `assign_triangle_roles()`.
|
||||
- Hoshe: unit tests for each failure mode — triangle that fails conflict viability, triangle that fails coherence, triangle that fails divergence.
|
||||
- Acceptance: `cargo test -p server -- triangle_validation` passes, covering all three failure modes plus a valid triangle that passes all checks.
|
||||
|
||||
**#85 — Error handling & recovery**
|
||||
- Handle three categories: (1) simulation panics / process crashes, (2) protocol deserialization errors, (3) desync detection between client state and server state.
|
||||
- Server side: `server/src/bridge/local.rs` is the IPC entry point. Add a supervision layer that catches panics from the tick loop and sends a structured `SimError` message to the client before dying, rather than an abrupt disconnect.
|
||||
- Protocol errors: `server/src/bridge/types.rs` — ensure malformed input returns a typed error response, not a panic. The existing `malformed_input_in_batch_rejects_entire_batch` test (#479, done) is the baseline.
|
||||
- Desync: add a `state_hash` field to `ObserverSnapshot` (a fast hash of key mutable state — player position, NPC count, tick number). Client logs hash mismatches for debugging. No automatic recovery in v0.1 — detect and report only.
|
||||
- Acceptance: integration test sends a deliberately malformed message mid-session, asserts the server emits a `SimError` message and continues running (does not exit).
|
||||
|
||||
**#246 — Basic environmental interaction**
|
||||
- `ObjectType` enum is already in `server/src/bridge/types.rs` (extended by #421, #422). `Interactable` component is in `server/src/simulation/interaction.rs`.
|
||||
- Currently `ObjectType::Door`, `ObjectType::Terminal`, `ObjectType::Readable`, `ObjectType::Container`, `ObjectType::Furniture` exist with verb sets.
|
||||
- This ticket: implement the _behaviour_ behind Door (toggle `walkable` on the blocking tile(s), emit a zone-crossable notification), Examinable objects (return examine text from content), and usable Terminals (trigger a `TerminalInteracted` event for future dialogue hook).
|
||||
- Door state must be tracked in `SaveStateV1` (currently a field gap — add `open_doors: Vec<StableId>` to the save struct in `server/src/simulation/save_state.rs`).
|
||||
- Acceptance: unit test — player interacts with a Door entity, asserts walkability flips; interacts again, asserts it flips back. Examine on a Readable entity returns non-empty text.
|
||||
|
||||
## Dependency Chain
|
||||
|
||||
```
|
||||
#159 (Tier 2 template format) → #166 (template-to-instance mapping) → #161 (instantiation engine)
|
||||
#107 (done: intra-template triangles) → #108 (cross-template triangles) → #109 (triangle validation)
|
||||
#85 (error handling) — standalone
|
||||
#246 (environmental interaction) — standalone
|
||||
```
|
||||
|
||||
Parallel tracks: #159→#166→#161 and #108→#109 can run concurrently. #85 and #246 are independent.
|
||||
|
||||
## PR Workflow
|
||||
|
||||
When ready to submit, create a PR with `tea` CLI:
|
||||
|
||||
```bash
|
||||
tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "feat(simulation): Sprint 21 template instantiation" --description "body" --base main --head server
|
||||
```
|
||||
@@ -0,0 +1,66 @@
|
||||
# Sprint 21: Instantiate — Visual Tasks
|
||||
|
||||
**Goal:** The template system becomes executable — templates spawn NPCs, assign triangles, and place them in world space; cross-template triangles link social sites; the client gains save/load game flow; and the generator pipeline gets its architectural design.
|
||||
|
||||
**Branch:** `visual`
|
||||
**Agents:** Araminta (art direction)
|
||||
|
||||
## New Tickets
|
||||
|
||||
| # | Title | Blocked by |
|
||||
|---|-------|------------|
|
||||
| #564 | Fog shader too opaque — tune alpha for semi-transparent layers per D-059 | — |
|
||||
|
||||
Use `tooling/db/ticket show <id>` for full details.
|
||||
|
||||
## Key Decisions
|
||||
|
||||
- `decisions/perception.md` — D-059 (fog: shader-based, five layers, knowledge-graph-driven), D-011 (fog of perception non-negotiable, same system for NPCs and player)
|
||||
- `decisions/architecture.md` — D-066 (dual-scale grid: 0.5m sim tiles, 1m visual tiles; fog gradient edge = 6-8 sim tiles = 3-4 visual tiles), D-043 (visual style: "functional warmth", Godot Light2D pipeline, sprites are shape templates the lighting completes)
|
||||
|
||||
## Notes
|
||||
|
||||
**#564 — Fog shader too opaque — tune alpha for semi-transparent layers per D-059**
|
||||
|
||||
The fog shader is implemented and structurally correct. The issue is that the alpha values for Layer 2 (peripheral) and Layer 3 (deep fog) are heavier than D-059 specifies, making the fog feel like a dark wall rather than limited visibility.
|
||||
|
||||
**File to edit:** `client/shaders/fog.gdshader`
|
||||
|
||||
**Current alpha values (reference fog_shader.gd for context):**
|
||||
- Layer 2 (peripheral, `vis` between `PERIPHERAL_LOW=0.55` and `CLEAR_THRESHOLD=0.85`): alpha `mix(0.55, 0.25, coverage) + noise * 0.1` — peaks at 0.55–0.65 at the peripheral edge
|
||||
- Layer 3 (deep fog, `explored > 0.3`): alpha `mix(0.78, 0.90, noise_val)` — near-fully opaque
|
||||
|
||||
**D-059 intent:**
|
||||
- Layer 2 (light fog / peripheral): "desaturated 40–50%, brightness -30%". This implies entities and world geometry are still partially visible — something in the 30–45% alpha range at the peripheral boundary, fading smoothly toward clear.
|
||||
- Layer 3 (deep fog / previously explored): "near-monochrome with ~10% zone temperature tint". The zone tint (`zone_tint_tex`) must be readable through the fog. The current 0.78–0.90 alpha buries it. Targeting 0.60–0.75 range should let tint breathe without revealing too much detail.
|
||||
- Layer 1 (clear, vision cone): the soft gradient edge should span 6-8 sim tiles = 3-4 visual tiles (D-066). Verify the `smoothstep(CLEAR_THRESHOLD, 1.0, vis)` range still produces this after alpha changes. `CLEAR_THRESHOLD = 0.85` and `PERIPHERAL_LOW = 0.55` are the knobs — do not change these unless the gradient edge width breaks.
|
||||
|
||||
**What to tune:**
|
||||
1. Layer 2: reduce the heavy-end alpha from 0.55 → ~0.38, keep the light-end at 0.25. Adjust noise contribution proportionally. Entities behind peripheral fog should be dimmed and desaturated, but recognisable in silhouette.
|
||||
2. Layer 3: reduce the alpha range from `mix(0.78, 0.90, noise_val)` → `mix(0.62, 0.76, noise_val)`. Zone tint (10% contribution via `mix(vec3(0.04), zone_tint, 0.1)`) should now be faintly visible as a colour cast. The "fog breathes" effect is preserved — keep the noise animation as-is.
|
||||
3. Verify that Layer 5 (unexplored, no maps, `#12141a`, alpha 1.0) remains fully opaque — information zero, no change.
|
||||
|
||||
**How to test:**
|
||||
- The Fog Theater gauntlet room (accessible via the Gauntlet hub in the running game) exercises all five fog layers in a single space.
|
||||
- Observable pass criteria:
|
||||
1. An NPC standing in the peripheral zone (Layer 2) is visibly dimmed and slightly desaturated — their D-033 relationship colour is still readable.
|
||||
2. A previously-explored room (Layer 3) shows a faint zone temperature tint (bar zone = warm, hub zone = cool, corridor = neutral) rather than uniform near-black.
|
||||
3. The vision cone edge is soft — no visible hard line between clear and peripheral.
|
||||
4. Unexplored tiles remain fully black.
|
||||
- Also run `make ci-client` to confirm no shader compilation regressions.
|
||||
|
||||
**Note:** `client/scripts/rendering/fog_shader.gd` (the GDScript controller) does not need changes — it sets uniforms, not alpha values. `client/scripts/autoloads/fog_state.gd` generates the textures fed to the shader — verify the zone tint texture is being populated correctly if Layer 3 tint still doesn't show after alpha reduction.
|
||||
|
||||
## Dependency Chain
|
||||
|
||||
```
|
||||
#564 (fog alpha tuning) — standalone
|
||||
```
|
||||
|
||||
## PR Workflow
|
||||
|
||||
When ready to submit, create a PR with `tea` CLI:
|
||||
|
||||
```bash
|
||||
tea pr create --repo jpmschweitzer/settled-reach --login schweitz --title "fix(visual): tune fog shader alpha per D-059" --description "body" --base main --head visual
|
||||
```
|
||||
@@ -119,7 +119,7 @@ None. All design decisions confirmed. If blockers arise during implementation, e
|
||||
|
||||
## Files Written
|
||||
|
||||
- /var/home/jeroenschweitzer/Projects/settled-reach/main/docs/sprints/sprint-8/server.md
|
||||
- /var/home/jeroenschweitzer/Projects/settled-reach/main/docs/sprints/sprint-8/client.md
|
||||
- /var/home/jeroenschweitzer/Projects/settled-reach/main/docs/sprints/sprint-8/audio.md
|
||||
- /var/home/jeroenschweitzer/Projects/settled-reach/main/docs/sprints/sprint-8/joint.md
|
||||
- /var/mnt/data/projects/settled-reach/main/docs/sprints/sprint-8/server.md
|
||||
- /var/mnt/data/projects/settled-reach/main/docs/sprints/sprint-8/client.md
|
||||
- /var/mnt/data/projects/settled-reach/main/docs/sprints/sprint-8/audio.md
|
||||
- /var/mnt/data/projects/settled-reach/main/docs/sprints/sprint-8/joint.md
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
# Test Plan: Sprint 18 — Touch (Client)
|
||||
|
||||
- **Date**: 2026-02-25
|
||||
- **Sprint**: 18 (Touch)
|
||||
- **Spec references**: D-013, D-041, D-042, D-049, D-061, D-062, D-063, D-064, D-078
|
||||
- **Tickets**: #151 (minimap rendering), #174 (dialogue UI hardening + examine result), #264 (knowledge/journal display)
|
||||
- **QA Engineer**: Hoshe
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Sprint 18 client scope delivers three UI features:
|
||||
1. **#151** — Minimap overlay rendering POIs from snapshot
|
||||
2. **#174** — Dialogue UI hardening (D-062/D-063/D-064) + examine result display overlay
|
||||
3. **#264** — Knowledge/journal panel displaying accumulated KG facts
|
||||
|
||||
Automated tests: `client/tests/test_dialogue_sprint18.gd`, `client/tests/test_journal_sprint18.gd`
|
||||
Manual tests: this document (section §Manual Test Procedures)
|
||||
|
||||
---
|
||||
|
||||
## #151: Minimap Rendering
|
||||
|
||||
### Spec reference
|
||||
D-013 (diegetic insert/POI system), D-015 (fixed-north, player-centered), D-049 (z-layer 6)
|
||||
|
||||
### Automated (unit-testable)
|
||||
- `GameState.poi_list` accessible via snapshot or `current_snapshot.poi_list`
|
||||
→ Covered: `test_journal_sprint18.gd::test_gamestate_poi_list_field_exists_or_in_entities`
|
||||
- `CANVAS_INSERT = 10` sanity check
|
||||
→ Covered: `test_journal_sprint18.gd::test_canvas_insert_constant_is_10`
|
||||
|
||||
### Edge cases
|
||||
- **Empty POI list**: minimap frame still renders (frame is always present per D-013)
|
||||
- **POI beyond minimap radius**: renders as directional arrow at border, not dot
|
||||
- **POI at exactly player position**: dot at center
|
||||
- **All POI categories**: `NavPoint`, `PersonOfInterest` — distinct colors/shapes
|
||||
|
||||
### Manual test procedure
|
||||
1. Start game with a clean save (no discovered POIs)
|
||||
2. **Verify**: minimap insert frame is visible, empty, no dots/arrows
|
||||
3. Move player near a NavPoint POI; trigger discovery
|
||||
4. **Verify**: colored dot appears on minimap at correct compass position
|
||||
5. **Verify**: dot color/shape matches expected category visual (see `data/ui-strings.yaml`)
|
||||
6. Move player so a POI is beyond minimap radius
|
||||
7. **Verify**: directional arrow appears at minimap border pointing toward POI
|
||||
8. **Verify**: player dot remains centered; minimap does not rotate or scroll
|
||||
9. Open dialogue box; **verify**: minimap remains visible (not hidden by dialogue)
|
||||
|
||||
### Performance check
|
||||
- 150×150 map, 15 NPCs, 8+ discovered POIs → minimap renders without visible frame drop
|
||||
|
||||
---
|
||||
|
||||
## #174: Dialogue UI Hardening + Examine Result Display
|
||||
|
||||
### Spec reference
|
||||
D-061 (box spec), D-062 (invisible locked options), D-063 (confrontation), D-064 (walk-away), D-078 (overheard log)
|
||||
|
||||
### Automated coverage
|
||||
Test file: `client/tests/test_dialogue_sprint18.gd`
|
||||
|
||||
| Test | D-ref | Status |
|
||||
|------|-------|--------|
|
||||
| D-062: rendered options have mouse_filter=STOP | D-062 | Written |
|
||||
| D-062: no lock icon children on options | D-062 | Written |
|
||||
| D-062: MAX_OPTIONS = 3 | D-061 | Written |
|
||||
| D-062: 4 options → only 3 render | D-061/D-062 | Written |
|
||||
| D-063: CONFRONTATION_BEAT_DURATION in [1.0, 2.0] | D-063 | Written |
|
||||
| D-063: CONFRONTATION_DIM_ALPHA < 1.0 | D-063 | Written |
|
||||
| D-063: confrontation_monologue signal fires | D-063 | Written |
|
||||
| D-063: standard option does NOT fire beat signal | D-063 | Written |
|
||||
| D-064: _WALK_AWAY_ACTIONS not empty | D-064 | Written |
|
||||
| D-064: cardinal directions in walk-away list | D-064 | Written |
|
||||
| D-064: dialogue_dismissed signal exists | D-064 | Written |
|
||||
| GameState current_dialogue set from snapshot | D-061 | Written |
|
||||
| GameState current_dialogue null when absent | D-061 | Written |
|
||||
| GameState current_examine_result field exists | #174 | Written (test-first) |
|
||||
| GameState current_examine_result set from snapshot | #174 | Written (test-first) |
|
||||
| GameState current_examine_result null when absent | #174 | Written (test-first) |
|
||||
| BBCode escape brackets in server text | — | Written |
|
||||
| _log_dirty flag optimization | — | Written |
|
||||
| D-061 max height ratio = 0.2 | D-061 | Written |
|
||||
| D-064 FADE_OUT = 0.3s | D-064 | Written |
|
||||
| D-078 passive glyph = ┃ | D-078 | Written |
|
||||
|
||||
### Items requiring Stig implementation (test-first stubs will fail until done)
|
||||
- `GameState.current_examine_result` field + `apply_snapshot()` handler
|
||||
- Examine result overlay scene (`res://ui/examine_overlay.tscn` or similar)
|
||||
- Auto-dismiss timer: 4–6 seconds (wire `current_examine_result` to overlay)
|
||||
|
||||
### Manual test procedure — D-062 (invisible locked options)
|
||||
1. Enter dialogue with an NPC that has some filtered options (server omits locked ones)
|
||||
2. **Verify**: dialogue box shows only the options the server sent — no grayed-out entries, no lock icons
|
||||
3. **Verify**: all visible options respond to click/key press
|
||||
4. **Verify**: pressing 1, 2, 3 selects the corresponding option (key bindings active)
|
||||
5. **Red flag**: if you see any visual element that appears "disabled" or "locked" — that is a D-062 violation
|
||||
|
||||
### Manual test procedure — D-063 (confrontation beat)
|
||||
1. Enter dialogue with an NPC that has a confrontation option (italic monologue beat)
|
||||
2. **Verify**: confrontation option renders identically to standard options (same style — no bold, no icon)
|
||||
3. Select the confrontation option
|
||||
4. **Verify**: a first-person internal monologue appears (italic, MonologueDisplay)
|
||||
5. **Verify**: dialogue box dims for ~1.5 seconds during beat
|
||||
6. **Verify**: after beat, option is sent and conversation ends normally
|
||||
7. **Verify**: audio dip applies during confrontation beat
|
||||
|
||||
### Manual test procedure — Examine result display (#174 new feature)
|
||||
1. Stand adjacent to an NPC; press Examine key (TBD — coordinate with server team)
|
||||
2. **Verify**: a brief text overlay appears (non-interactive, no response options)
|
||||
3. **Verify**: overlay is diegetically styled (insert layer, not a dialogue box)
|
||||
4. **Verify**: overlay auto-dismisses after 4–6 seconds without player input
|
||||
5. **Verify**: different characters (detective vs smuggler) receive different text for the same NPC
|
||||
6. **Verify**: overlay does not appear over a dialogue box (mutual exclusion)
|
||||
|
||||
---
|
||||
|
||||
## #264: Knowledge/Journal Display
|
||||
|
||||
### Spec reference
|
||||
D-041 (knowledge graph data model), D-042 (UIStrings), D-013 (insert layer)
|
||||
|
||||
### Automated coverage
|
||||
Test file: `client/tests/test_journal_sprint18.gd`
|
||||
|
||||
| Test | D-ref | Status |
|
||||
|------|-------|--------|
|
||||
| GameState.player_knowledge field exists | D-041 | Written (test-first) |
|
||||
| GameState.player_knowledge set from snapshot | D-041 | Written (test-first) |
|
||||
| GameState.player_knowledge null when absent | D-041 | Written (test-first) |
|
||||
| Facts array survives snapshot roundtrip | D-041 | Written (test-first) |
|
||||
| KnowledgeConfidence levels documented | D-041 | Written |
|
||||
| Fact state values documented | D-041 | Written |
|
||||
| Journal scene exists at path | #264 | Written (test-first) |
|
||||
| UIStrings has journal section | D-042 | Written (test-first) |
|
||||
| CANVAS_INSERT = 10 | D-013 | Written |
|
||||
| POI list accessible for minimap | #151 | Written |
|
||||
|
||||
### Items requiring Stig implementation (test-first stubs will fail until done)
|
||||
- `GameState.player_knowledge` field + `apply_snapshot()` handler
|
||||
- Journal panel scene (`res://ui/journal_panel.tscn`)
|
||||
- Journal panel `refresh()` or `_refresh()` method
|
||||
- UIStrings keys: `journal.title`, `journal.confidence.*`, `journal.no_facts`
|
||||
- Toggle key (likely `J`) wired to panel visibility
|
||||
- Mutual exclusion: journal closes when dialogue opens and vice versa
|
||||
|
||||
### Manual test procedure
|
||||
1. Accumulate KG facts by examining NPCs and participating in dialogue
|
||||
2. Press the journal toggle key (likely `J`)
|
||||
3. **Verify**: journal panel opens as an insert-layer overlay (diegetic styling)
|
||||
4. **Verify**: entities are listed with header ("What I know about Kael Davan")
|
||||
5. **Verify**: each fact shows: fact text, confidence level, source, game-time timestamp
|
||||
6. **Verify**: `Direct` confidence facts are most prominent (visually)
|
||||
7. **Verify**: `Stale` facts appear dimmer than `Active` facts
|
||||
8. **Verify**: `Contradicted` facts are visually distinct (strikethrough or amber tint)
|
||||
9. Open dialogue box; **verify**: journal panel closes automatically
|
||||
10. Close dialogue; re-open journal; **verify**: state preserved
|
||||
11. Press `J` again; **verify**: journal panel closes
|
||||
|
||||
### Edge cases
|
||||
- **Empty journal**: no facts accumulated → journal shows "No data" message (UIStrings key)
|
||||
- **Many facts**: 20+ facts → scroll works, panel stays within insert layer bounds
|
||||
- **Contradicted + Stale**: a fact can be both — verify combined visual treatment
|
||||
- **Game time 00:00**: timestamp displays correctly (midnight edge case)
|
||||
|
||||
---
|
||||
|
||||
## Test Coverage Summary
|
||||
|
||||
| Ticket | Automated tests | Manual procedure documented | Ready to run |
|
||||
|--------|----------------|----------------------------|--------------|
|
||||
| #151 minimap | 2 (structural) | Yes | Blocked on Stig (#151 in_progress) |
|
||||
| #174 dialogue hardening | 25 | Yes | All pass today (code exists) |
|
||||
| #174 examine result | 5 (test-first) | Yes | Blocked (GameState field missing) |
|
||||
| #264 journal display | 8 (test-first) | Yes | Blocked (scene + field missing) |
|
||||
|
||||
### Test files to run
|
||||
```bash
|
||||
# gdUnit4 headless (see docs/DEVOPS.md for full command)
|
||||
# test_dialogue_sprint18.gd — expect: 25 pass (dialogue), 5 fail (examine, test-first)
|
||||
# test_journal_sprint18.gd — expect: 3 pass (constants), 8 fail (test-first)
|
||||
```
|
||||
|
||||
### Sprint 18 completion criteria (client)
|
||||
Per `sprint-18/joint.md`:
|
||||
- [ ] Minimap renders POIs — discovered POI shows dot; player centered; at least one distant POI shows arrow
|
||||
- [ ] Journal panel opens — at least one KG fact with confidence, source, game-time visible
|
||||
- [ ] Examine result displays — overlay fires on Examine, auto-dismisses, differs by character
|
||||
- [ ] No locked/grayed dialogue options anywhere in the UI (D-062)
|
||||
@@ -17,12 +17,12 @@ The core protocol implementation is sound and test coverage is strong for the ha
|
||||
## Files Reviewed
|
||||
|
||||
### Core Implementation
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/main/client/scripts/protocol/protocol.gd` (new, 114 lines)
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/main/client/scripts/autoloads/sim_bridge.gd` (modified, +51 lines)
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/main/server/tests/gen_fixtures.rs` (new, 63 lines)
|
||||
- `/var/mnt/data/projects/settled-reach/main/client/scripts/protocol/protocol.gd` (new, 114 lines)
|
||||
- `/var/mnt/data/projects/settled-reach/main/client/scripts/autoloads/sim_bridge.gd` (modified, +51 lines)
|
||||
- `/var/mnt/data/projects/settled-reach/main/server/tests/gen_fixtures.rs` (new, 63 lines)
|
||||
|
||||
### Tests
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/main/client/tests/test_protocol.gd` (new, 137 lines, 9 tests)
|
||||
- `/var/mnt/data/projects/settled-reach/main/client/tests/test_protocol.gd` (new, 137 lines, 9 tests)
|
||||
|
||||
### Vendor Library (noted, not reviewed)
|
||||
- `client/addons/messagepack/messagepack.gd` (368 lines, third-party)
|
||||
|
||||
@@ -0,0 +1,375 @@
|
||||
# Workshop: Character Creation & Game Setup
|
||||
|
||||
**Date:** 2026-02-25
|
||||
**Facilitator:** Team Leader (Jeroen)
|
||||
**Participants:** Nigel (replayability), Paula (narrative), Gestalt (systems), Miri (worldbuilding), Tyre (architecture), Qatux (documenter)
|
||||
**Status:** Not started
|
||||
|
||||
---
|
||||
|
||||
## Purpose
|
||||
|
||||
Define what the character creation / new game screen actually does. This
|
||||
is the most fundamental unresolved design question in the project: what
|
||||
does the player choose, what does the seed control, and what does that
|
||||
combination produce?
|
||||
|
||||
This workshop resolves **Q-011** (character selection and playable
|
||||
characters) and establishes the boundary between player agency, character
|
||||
archetype, and world seed. Everything downstream — quest generation, gate
|
||||
activation, difficulty, replayability — flows from getting this table right.
|
||||
|
||||
## Context
|
||||
|
||||
### What's decided
|
||||
|
||||
- **D-005:** Single character per playthrough. Character choice determines
|
||||
starting location, starting knowledge, available levers, personal goals.
|
||||
"Same conspiracy, different character, completely different game."
|
||||
- **D-027:** v0.1 vertical slice ships with 2 characters: smuggler and
|
||||
detective. Inverted perspectives on the same world.
|
||||
- **D-023:** Three-tier content model. Tier 1 (authored drama) drawn from
|
||||
a pool at game start. Tier 2 (templated). Tier 3 (procedural filler).
|
||||
- **D-029:** Population entanglement ratio 30/50/20, varies per seed.
|
||||
- **D-010:** Deterministic simulation. Same seed + same content = identical
|
||||
world state.
|
||||
- **D-039:** Wow moment 4 is the Divergence Reveal — same room, different
|
||||
character, different everything. This is THE replayability payoff.
|
||||
- **D-041:** Knowledge graph is per-entity. Characters start with different
|
||||
knowledge.
|
||||
- **D-032:** Separate monologue pools per character.
|
||||
- **Seed config schema** (ticket #394): Records seed value, character
|
||||
selection, pool draws, template assignments, starting knowledge.
|
||||
|
||||
### What's open
|
||||
|
||||
- **Q-011:** Character selection and playable characters — not yet discussed.
|
||||
Which characters? How different are starting positions? Canon or original?
|
||||
- **Q-010:** Storyteller AI design — pacing rules, structural vs dramatic
|
||||
randomness. Adjacent to this workshop but NOT in scope to fully resolve.
|
||||
|
||||
### What's NOT in scope
|
||||
|
||||
- Full character roster beyond v0.1 (two characters first, prove it works)
|
||||
- Endgame quest design (no endgame exists yet — note toggles, defer design)
|
||||
- Storyteller pacing algorithm (Q-010 is a separate workshop)
|
||||
- Character naming edge cases (namespace collisions with NPCs — note, defer)
|
||||
- Full quest system architecture (scope to: what quest SHAPES are seeded at
|
||||
creation, not the full quest pipeline)
|
||||
|
||||
### Design guardrail
|
||||
|
||||
Character selection determines your starting **information position** and
|
||||
**social graph**, not your capabilities. Characters have different verbs
|
||||
available, not different success probabilities for the same verbs. The
|
||||
smuggler doesn't get "+5% to cargo inspection" — the smuggler gets "Slip
|
||||
Manifest" as a verb the detective never sees. This is D-005's intent and
|
||||
D-028's access tier system in practice. Do not drift toward stat sheets.
|
||||
|
||||
## Key Questions
|
||||
|
||||
### Q1: What does character selection actually select?
|
||||
|
||||
Three possible models — the workshop must pick one (or a hybrid):
|
||||
|
||||
**A. Fixed archetype roster.** Player picks "smuggler" or "detective" from a
|
||||
list. Each is a fully pre-authored starting position. Knowledge from
|
||||
playthrough 1 fully transfers — you know exactly where the smuggler starts.
|
||||
|
||||
**B. Archetype + generated instance.** Player picks "smuggler" but YOUR
|
||||
smuggler is procedurally placed in the social web. Different starting
|
||||
coworkers, different shift schedule, different corridor assignment. Knowledge
|
||||
partially transfers — you know smuggler life, but not this smuggler's life.
|
||||
|
||||
**B2. Archetype + curated instance.** Player picks "smuggler," sees 2-3
|
||||
procedurally generated social configurations, and picks one. RimWorld's
|
||||
colonist reroll mechanic — curation from a generated pool rather than full
|
||||
specification. Middle path between A and B.
|
||||
|
||||
**C. Fully custom.** Player picks background axes (profession, social
|
||||
tier, faction affinity). No pre-authored archetype. Maximum variation,
|
||||
maximum authoring cost.
|
||||
|
||||
For each model: what are the replayability implications? What's the
|
||||
authoring cost? What does this mean for the Divergence Reveal (D-039)?
|
||||
|
||||
Also consider: does the player configure starting knowledge weights, or
|
||||
is starting knowledge fully determined by archetype? (DF's embark skill
|
||||
point system lets players shape starting capability within constraints.)
|
||||
|
||||
### Q2: The seed boundary — what varies by what?
|
||||
|
||||
Produce a canonical three-column table:
|
||||
|
||||
| Determined by world seed | Determined by character choice | Player-configured |
|
||||
|--------------------------|-------------------------------|-------------------|
|
||||
| ? | ? | ? |
|
||||
|
||||
Examples to place: NPC relationships, which NPCs are compromised,
|
||||
starting location, starting knowledge graph state, access tiers,
|
||||
gate activation timing, conspiracy shape, population entanglement
|
||||
ratio, THE FRIEND identity, starting inventory...
|
||||
|
||||
Include a fourth implicit column: **what information exists in the world
|
||||
but is inaccessible to this character?** Not locked behind a mechanic —
|
||||
just absent from their information space entirely. The gap between what
|
||||
the world contains and what the character can see IS the replayability.
|
||||
(See: Obra Dinn in Reference Games.)
|
||||
|
||||
This table IS the workshop's primary deliverable. Get it right and every
|
||||
downstream system knows its inputs.
|
||||
|
||||
### Q3: How does gate activation relate to character choice?
|
||||
|
||||
The contamination/conspiracy discovery trigger — the moment the game shifts
|
||||
from daily life to investigation. Two sub-questions:
|
||||
|
||||
**A.** Does character choice change WHEN you discover contamination, or only
|
||||
HOW you experience it? (Detective flags cargo anomalies early via lattice
|
||||
analysis. Smuggler witnesses something directly. Same world-state, different
|
||||
discovery paths.)
|
||||
|
||||
Consider Pentiment's model: the murder happens near you, not TO you. You're
|
||||
pulled in by proximity and relationship, not by being the assigned
|
||||
investigator. Is gate activation something that happens to the world (and
|
||||
the character stumbles into it), or something the character triggers through
|
||||
their specific access?
|
||||
|
||||
**B.** Are discovery paths authored per character (detective always discovers
|
||||
via X) or emergent (character knowledge graph + storyteller pacing = different
|
||||
discovery window per playthrough)? What's the minimum authored content needed
|
||||
per character to make gate activation feel character-specific?
|
||||
|
||||
Explicit RimWorld check: is contamination timing a player-configurable
|
||||
"storyteller" choice, fixed per character, or emergent from play? Don't
|
||||
collapse pacing control into archetype selection.
|
||||
|
||||
### Q4: Quest seeding — templates vs randomization
|
||||
|
||||
The user's directive: "the quest system should offer relevant randomized
|
||||
quests based on creation instead of going fully scripted." Scope this to:
|
||||
|
||||
- What quest SHAPES (not specific quests) are determined at character
|
||||
creation? (e.g., smuggler gets logistics-flavored side quests, detective
|
||||
gets investigation-flavored ones)
|
||||
- How do Tier 2 templates (D-023) interact with character choice? Does the
|
||||
smuggler's template pool differ from the detective's?
|
||||
- What is authored (main quest templates, scripted quality) vs generated
|
||||
(side content, character-relevant variations)?
|
||||
- How many quest templates are needed per character for v0.1 to feel varied?
|
||||
- Does the character have visible long-term goals the game tracks? Does the
|
||||
smuggler TELL you what they want (goals screen) or do wants emerge from
|
||||
play? (The Sims' wants/aspirations system as reference.)
|
||||
|
||||
### Q5: Game conditions and toggles
|
||||
|
||||
The user wants players to be able to configure their experience. But some
|
||||
toggles destroy the game's core tension. Define:
|
||||
|
||||
- **What CAN be toggled:** Challenge intensity, optional content modules,
|
||||
timer pressure, specific life-sim subsystems
|
||||
- **What CANNOT be toggled:** Core conspiracy simulation, investigator
|
||||
faction presence, information asymmetry. These exist whether the player
|
||||
sees them or not.
|
||||
- **Starting location selection:** Is this a player choice or determined
|
||||
by archetype? If player choice, what does it mean for authored content?
|
||||
- **Enable/disable endgame quests:** Note for future design. What's the
|
||||
minimum we need to decide NOW vs what can wait until endgame exists?
|
||||
|
||||
### Q6: The playthrough 2 test
|
||||
|
||||
Concrete synthesis test. Nigel presents the following scenario to the room:
|
||||
|
||||
> You've played the smuggler on seed X. You now know: Kael is trying to
|
||||
> exit the ring. Sera Venn is protecting Naia. The detective flagged your
|
||||
> manifest on Day 2. The contamination hit during the evening shift at
|
||||
> The Last Shift. You pick the detective on the SAME seed. Minute 1: you
|
||||
> arrive at the Commission office. Minute 5: your first assignment.
|
||||
> Minute 10: you walk into The Terminal where you spent 30 hours as the
|
||||
> smuggler.
|
||||
|
||||
Against the combined design from Rounds 1-4, each participant answers:
|
||||
|
||||
1. What does the detective see in The Terminal that the smuggler never saw?
|
||||
2. What does the detective's monologue say about Kael — whom the smuggler
|
||||
considered a friend?
|
||||
3. Does the contamination trigger differently, or at the same moment via
|
||||
a different path?
|
||||
4. Name one thing the player LEARNED in playthrough 1 that changes how
|
||||
they PLAY playthrough 2 — not metagaming, but genuine new understanding.
|
||||
|
||||
If participants can't answer these concretely, the design has a gap.
|
||||
Find it and fix it before the workshop closes.
|
||||
|
||||
## Reference Games
|
||||
|
||||
### Dwarf Fortress — the fossil record
|
||||
|
||||
World generation creates centuries of invisible history. The player never
|
||||
reads a history log — they excavate its consequences. A collapsed
|
||||
civilization left ruins. A grudge between two species shapes who attacks
|
||||
your fort. The history is SUBSTRATE, not content.
|
||||
|
||||
The lesson for us: the world seed should produce CONSTRAINTS and RESIDUES
|
||||
that make the current situation feel inevitable. How long has this smuggling
|
||||
ring been operating? What's its history of near-discovery? Which institutional
|
||||
figures already have kompromat on them? The player never sees this directly
|
||||
but feels its weight on every NPC relationship state they encounter.
|
||||
|
||||
Also relevant: the embark skill point system — players shape starting
|
||||
capability within constraints rather than receiving a fixed loadout. Consider
|
||||
for Q1: does the player configure starting knowledge within their archetype?
|
||||
|
||||
### RimWorld — the separation principle
|
||||
|
||||
Storyteller selection (Cassandra/Phoebe/Randy) controls pacing, not content.
|
||||
Scenario defines starting resources and constraints. Colonist generation is
|
||||
partially random, partially player-curated (reroll, choose skills).
|
||||
|
||||
**Key lesson 1:** The storyteller and starting conditions are SEPARATE
|
||||
choices. Our gate activation / contamination pacing (Q3) maps to storyteller
|
||||
selection. Our character archetype maps to scenario. Don't collapse them.
|
||||
|
||||
**Key lesson 2:** Player CURATION from a procedurally generated set is
|
||||
different from player SPECIFICATION of a custom set. RimWorld's colonist
|
||||
reroll is a point-buy system hidden behind a reroll interface. For us:
|
||||
model B2 — see 2-3 generated social configurations for "your smuggler" and
|
||||
pick one. This is a viable middle path that deserves to be on the table.
|
||||
|
||||
### The Sims — verbs, not stats
|
||||
|
||||
Traits in The Sims are PERMISSION SYSTEMS for social interactions, not stat
|
||||
modifiers. The Outgoing Sim doesn't get +20% to social checks — they get
|
||||
access to DIFFERENT VERBS. They can autonomously initiate conversations the
|
||||
Introvert Sim cannot. This is exactly our access tier system (D-028 Layer 1).
|
||||
|
||||
**Key lesson 1:** Character creation changes which verbs you have, not how
|
||||
well you perform shared verbs. The smuggler gets "Slip Manifest." The
|
||||
detective gets "Pull Records." Neither is better — they're different
|
||||
information-gathering tools for the same world.
|
||||
|
||||
**Key lesson 2:** Neighborhood placement as replayability driver. The lot
|
||||
you choose positions you relative to neighbor NPCs, which determines which
|
||||
relationships bootstrap organically through proximity. Early relationships
|
||||
form through proximity, not player initiative. The smuggler starts embedded
|
||||
in The Terminal — relationships with ring members bootstrap before the
|
||||
player does anything. The detective starts at the Commission — different
|
||||
organic relationships form. THIS is the structural driver that makes the
|
||||
same seed play differently.
|
||||
|
||||
### Disco Elysium — observation filters, not capabilities
|
||||
|
||||
D-005 already cites Disco Elysium as a design reference. The Thought
|
||||
Cabinet is a permission system for new dialogue options and monologue lines.
|
||||
Building a character in DE doesn't give you stats — it gives you access to
|
||||
different OBSERVATIONS of the same world. Intellect doesn't make you
|
||||
smarter — it makes your character say different things to themselves when
|
||||
they see the same evidence.
|
||||
|
||||
**Key lesson:** Character build determines what your character NOTICES, not
|
||||
what they can DO. This is D-032 (separate monologue pools) and D-041
|
||||
(per-entity knowledge graph) in one reference. If participants are thinking
|
||||
about Q1 models without DE on the table, they'll drift toward stat-system
|
||||
thinking. DE keeps them on the observation-filter track.
|
||||
|
||||
### Return of the Obra Dinn — information gap as presence
|
||||
|
||||
Obra Dinn demonstrates that information asymmetry can be the ENTIRE game.
|
||||
You piece together events from fragments. The information gap feels like
|
||||
presence, not absence — you FEEL the weight of what you can't see yet.
|
||||
|
||||
**Key lesson for Q2:** The seed boundary table needs to account for what
|
||||
exists in the world but is invisible to this character. Not locked behind a
|
||||
mechanic — just absent from their information space. Character A's world
|
||||
contains things that are simply not in Character B's world. That gap is
|
||||
the pull that drives playthrough 2.
|
||||
|
||||
### Pentiment — gate activation by proximity
|
||||
|
||||
Pentiment commits to a single-character perspective. The gate activation
|
||||
question it answers: "what triggers the player from daily life into
|
||||
investigation?" A murder happens near you, not TO you. You're pulled in
|
||||
by proximity and relationship, not by institutional assignment. The player
|
||||
character is NOT the assigned detective — they're a witness with skills.
|
||||
|
||||
**Key lesson for Q3:** Same discovery timing, but character-dependent tools
|
||||
for responding to it. The contamination doesn't care who you are — it
|
||||
happens. But your character's position determines whether you see it as
|
||||
threat, opportunity, or puzzle.
|
||||
|
||||
### The common thread
|
||||
|
||||
In all six games, the setup screen generates ASYMMETRIC STARTING CONDITIONS.
|
||||
The same world, entered from different positions, produces different
|
||||
information access, different social proximity, and different verb
|
||||
availability. The asymmetry IS the replayability. Our character creation
|
||||
should produce a starting POSITION in an information landscape — not a
|
||||
stat block, not a story, not a difficulty setting.
|
||||
|
||||
## Participants and Roles
|
||||
|
||||
| Agent | Role | Why they're here |
|
||||
|-------|------|-----------------|
|
||||
| Nigel | Replayability lead | Structural randomness, seed design, "what happens on playthrough 10?" |
|
||||
| Paula | Narrative lead | Starting NPC relationships, character-specific story hooks, social web implications |
|
||||
| Gestalt | Systems lead | How character choice propagates through mechanics (KG, dialogue tiers, movement, perception) |
|
||||
| Miri | Worldbuilding | Which archetypes fit the Krenn System, canon constraints, lore accuracy |
|
||||
| Tyre | Architecture | Implementation cost reality check. "That's 4 new ECS components — is it worth it?" |
|
||||
| Qatux | Documenter | Track decisions, cross-references, dissent. Maintain running reference list. |
|
||||
|
||||
## Round Structure
|
||||
|
||||
### Round 1 — The Lens Question (Nigel leads)
|
||||
|
||||
Single question: what does character selection actually select? (Q1)
|
||||
|
||||
Nigel opens with a replayability scoring of each model (A/B/B2/C) — 3
|
||||
bullet points per model on the replayability axis. This is a BASELINE, not
|
||||
a verdict. Participants then argue from their domain against that baseline.
|
||||
This converges faster than open advocacy.
|
||||
|
||||
Target: agree on the model by end of round.
|
||||
|
||||
### Round 2 — The Seed Boundary (Gestalt leads)
|
||||
|
||||
Given the model from Round 1: draw the exact line between world seed,
|
||||
character choice, and player customization. Produce the three-column
|
||||
table (Q2). Each participant fills in their domain's rows.
|
||||
|
||||
### Round 3a — Gate Activation (Paula leads)
|
||||
|
||||
How does contamination trigger work per character? (Q3)
|
||||
This flows directly from Round 1's model decision. Paula leads because
|
||||
gate activation is fundamentally a narrative question — when does the
|
||||
story shift?
|
||||
|
||||
### Round 3b — Quest Seeding (Nigel leads, Tyre has implementation floor)
|
||||
|
||||
How do quest templates interact with character choice? (Q4)
|
||||
Nigel leads because quest variation is the replayability engine. Tyre gets
|
||||
explicit authority to reject quest template proposals that require new
|
||||
architecture — every template decision has an implementation cost that
|
||||
spirals without active checking.
|
||||
|
||||
### Round 4 — Conditions, Toggles & Synthesis (all)
|
||||
|
||||
Game conditions and what's toggleable (Q5). Then run the concrete
|
||||
playthrough 2 test (Q6). Nigel presents the scenario. Each participant
|
||||
must answer the four concrete questions. If they can't, the design has
|
||||
a gap — find it and fix it before closing.
|
||||
|
||||
## Required Reading for Participants
|
||||
|
||||
- `decisions/scope.md` — D-005, D-013, D-027, D-029, D-053
|
||||
- `decisions/content.md` — D-023, D-028, D-032, D-034
|
||||
- `decisions/architecture.md` — D-041 (knowledge graph)
|
||||
- `decisions/questions.md` — Q-010, Q-011
|
||||
|
||||
## Expected Outputs
|
||||
|
||||
- **D-record:** Character creation model (resolves Q-011)
|
||||
- **D-record:** Seed boundary table (what varies by seed vs character vs player)
|
||||
- **D-record:** Gate activation trigger design
|
||||
- **D-record or Q:** Quest seeding model (may produce a Q if full design deferred)
|
||||
- **D-record:** Game condition toggles (what's configurable, what isn't)
|
||||
- Ticket updates for Sprint 19+ backlog as needed
|
||||
@@ -0,0 +1,82 @@
|
||||
# Workshop Outcomes: v0.1 Content Gap Analysis
|
||||
|
||||
**Workshop:** v0.1 Content Gap Analysis
|
||||
**Date:** 2026-02-11
|
||||
**Rounds:** 2 (Analysis + Synthesis)
|
||||
**Participants:** Mellanie, Paula, Araminta, Miri, Gestalt, Ozzie
|
||||
**Facilitator:** Jeroen
|
||||
**Documenter:** Qatux
|
||||
**Status:** DONE — all decisions actioned, tickets created
|
||||
**Full notes:** `docs/workshops/content-gap-analysis_v0_1/SUMMARY.md`
|
||||
|
||||
---
|
||||
|
||||
## What the Workshop Accomplished
|
||||
|
||||
Six agents independently analyzed 9 content layers across the vertical slice (D-027), then synthesized across all outputs. The project lead issued 9 directive decisions between rounds. Remarkable cross-agent convergence: the Dual Lens Guide, monologue as primary carrier, and the tag taxonomy were independently identified by multiple agents without coordination. THE FRIEND concept evolved from Ozzie's emotional instinct to Paula's structural design to Mellanie's authoring plan in a single workshop.
|
||||
|
||||
---
|
||||
|
||||
## Decisions Produced
|
||||
|
||||
| ID | Decision | Domain | Source |
|
||||
|----|----------|--------|--------|
|
||||
| D-032 | Separate monologue pools per character | content.md | Lead directive #1 |
|
||||
| D-033 | Entity color = relationship to player | perception.md | Araminta R1 + lead directive #2 |
|
||||
| D-034 | THE FRIEND production-level NPC pattern | content.md | Ozzie concept + lead directive #4 + Paula design |
|
||||
| D-035 | Converged tag taxonomy for line pools (6+3 tags) | content.md | Gestalt + Mellanie convergence |
|
||||
| D-036 | Sova Transit District / Krenn System as v0.1 setting | content.md | Miri R1 + lead directive #6 |
|
||||
| D-037 | Contraband specification | content.md | Miri R1/R2 |
|
||||
| D-038 | Audio in v0.1 scope via Stable Audio Open (8 files) | scope.md | Lead directives #3 + #9 |
|
||||
| D-039 | v0.1 wow moment scope — all 6 moments | scope.md | Ozzie R1/R2 + lead directive #8 |
|
||||
| D-040 | Wiki taxonomy structure | process.md | Miri R2 + lead directive #5 |
|
||||
|
||||
All 9 decisions confirmed by project lead between rounds as non-negotiable directives.
|
||||
|
||||
---
|
||||
|
||||
## Open Questions Identified
|
||||
|
||||
| ID | Question | Owner | Status |
|
||||
|----|----------|-------|--------|
|
||||
| Q-012 | How does the generation expansion pass work? LLM, template-based, or rule-based? | Gestalt, Mellanie | Raised this workshop |
|
||||
| Q-013 | How does the line previewer handle THE FRIEND's temporal progression? | Gestalt, Dudley | Raised this workshop |
|
||||
| Q-014 | Audio timing with monologue — when does the chime fire relative to text? | Gestalt, Ozzie | Raised this workshop |
|
||||
| Q-015 | Does 4x generation expansion apply to THE FRIEND's custom lines? | Mellanie, Gestalt | Raised this workshop |
|
||||
| Q-016 | Knowledge hierarchy for monologue prerequisites | Gestalt, Paula | Raised this workshop |
|
||||
| Q-017 | Triangle pressure threshold — what events trigger escalation? | Gestalt, Paula | Raised this workshop |
|
||||
|
||||
---
|
||||
|
||||
## Tickets Created
|
||||
|
||||
48 total tickets (42 new + 6 updates). See `docs/workshops/content-gap-analysis_v0_1/TICKETS.md` for full list.
|
||||
|
||||
**Critical (9 new):** #297 Kael Davan full profile, #298 Sera Venn full profile, #299 Opening hook (smuggler), #300 Opening hook (detective), #301 Wiki taxonomy, #302 Sova Texture Appendix, #303 v0.1 Visual Grammar, #304 Entity Color System Spec, #305 Dialogue selection pipeline.
|
||||
|
||||
**High (23 new):** Content and narrative (#306, #307, #310, #328), visual and spatial layouts (#311-318), worldbuilding (#319-322), systems and implementation (#308, #309, #323-327).
|
||||
|
||||
**Medium (10 new):** Mirror moments, tutorial content, environmental standards, tell derivation (#329-338).
|
||||
|
||||
**Updated (6):** #261 promoted to critical with expanded scope; #189, #168, #124, #90, #193 updated.
|
||||
|
||||
---
|
||||
|
||||
## Key Flags
|
||||
|
||||
- Detective's FRIEND confirmed as Sera Venn (Paula, not Mellanie's Lera proposal). Lera Sessik remains the bar owner.
|
||||
- NPC triangle count: Paula reconciled from 7 to 5 triangles in Round 2. Five-triangle model is canonical.
|
||||
- Tag taxonomy convergence was independent: Mellanie and Gestalt proposed nearly identical structures without coordination.
|
||||
- Dual Lens Guide (#261) is the single highest-risk dependency — everything downstream blocks on it.
|
||||
|
||||
---
|
||||
|
||||
## Critical Path Produced
|
||||
|
||||
Dual Lens Guide (#261) → Voice Kits → THE FRIEND Content Packs → Validation → Content at Scale.
|
||||
|
||||
Three parallel tracks: narrative (Paula), setting (Miri), systems (Gestalt + Araminta) — converging at content pack production.
|
||||
|
||||
---
|
||||
|
||||
*Compiled by Qatux. Source: `docs/workshops/content-gap-analysis_v0_1/SUMMARY.md`, `TICKETS.md`. Decisions in `decisions/content.md` (D-032 through D-040 excl. D-033 in perception.md, D-038/D-039 in scope.md, D-040 in process.md).*
|
||||
@@ -0,0 +1,316 @@
|
||||
# Generator Architecture Workshop — Round 1: Araminta
|
||||
## Visual Coherence Constraints for Chunk Fill
|
||||
|
||||
**Author:** Araminta (Visual Designer)
|
||||
**Date:** 2026-02-27
|
||||
**Workshop:** Generator Architecture (Ticket #562)
|
||||
**Source documents:** visual-grammar-v01.md, spatial-layout-terminal-v01.md, spatial-layout-bar-v01.md, spatial-layout-gate-v01.md, spatial-layout-smuggling-corridors-v01.md, decisions/content.md (#153 D-record = D-093/D-094), decisions/architecture.md
|
||||
|
||||
---
|
||||
|
||||
## What the Visual Domain Requires from the Generator
|
||||
|
||||
The visual grammar (visual-grammar-v01.md) establishes a system where the **environment communicates location, not drama** (D-045). This places a strong constraint on the generator: every piece of generated content must resolve to a zone palette, a zone era, and an access tier. Without those three anchors, generated chunks will look random regardless of how technically correct the spatial math is.
|
||||
|
||||
My domain requirement is simple: **the generator must produce chunks that a player can read at a glance**. Read = know where they are, know what tier of access they're in, know where the walls and cover are, and know where people might be watching from. Everything below serves that requirement.
|
||||
|
||||
---
|
||||
|
||||
## 1. Visual Coherence Constraints for Chunk Fill
|
||||
|
||||
### 1.1 Zone Palette Is the Primary Coherence Anchor
|
||||
|
||||
Each chunk inherits a single zone palette. Zone boundaries are set at block level (64×64 visual tiles), not chunk level. A chunk does not have a mixed palette. If two zones meet at a block boundary, the visual transition happens between chunks, never within a chunk.
|
||||
|
||||
**Locked zone palettes (D-093, visual grammar §1):**
|
||||
|
||||
| Zone | Floor hex | Ambient | Fixture color | Era |
|
||||
|------|-----------|---------|---------------|-----|
|
||||
| Gate cluster | `#b8bec4` (surface) | `#0a1222` fog tint | `#f2f4ff` cold LED | Era 3 |
|
||||
| Terminal | `#1a1e24` | `#0d1520` | `#c8d8f0` cool institutional | Era 1/2 |
|
||||
| Bar | `#1e1912` | `#200c04` | `#f0b840` amber | Era 3 |
|
||||
| Maintenance | `#181818` | `#101214` | `#d0d8e0` cold dim | Era 1 |
|
||||
| Transition corridor | `#181818` (neutral industrial) → `#1e1912` gradient over 40m | varies | sparse cool | Era 1 |
|
||||
|
||||
**Rule:** The generator applies the zone palette to every floor tile and wall face in the chunk. It cannot introduce off-palette materials without an "era modification" flag (see §1.3). An institutional zone chunk with warm amber flooring is a visual error.
|
||||
|
||||
### 1.2 Lighting Fixture Placement Determines Room Scale
|
||||
|
||||
This is the most underappreciated visual constraint: **room width is functionally constrained by fixture radius**.
|
||||
|
||||
From the visual grammar:
|
||||
- Terminal (institutional): fixture radius 8–10 visual tiles. A room wider than ~20 visual tiles needs a second fixture row.
|
||||
- Bar (social): fixture radius 5–6 visual tiles. Rooms wider than ~12 visual tiles go dark between pools — which is intentional for private zones, but not for public ones.
|
||||
- Maintenance: fixture radius 4–5 visual tiles. Gaps between pools are expected and desirable (abandoned, sparse aesthetic).
|
||||
|
||||
**Generator rule:** Chunk fill must place at minimum 1 lighting fixture per zone-appropriate coverage radius². Rooms that exceed 2× coverage radius without a fixture read as broken infrastructure in institutional zones and as suspicious in any zone. The generator's room-dimension choices must respect fixture-coverage budgets for the zone.
|
||||
|
||||
### 1.3 Era Tags Produce Material Variation Without Palette Violation
|
||||
|
||||
Buildings within a block share an era tag. The era tag modifies surface materials while staying within the zone palette range:
|
||||
|
||||
- **Era 1:** Base palette. Older composite panels, original construction.
|
||||
- **Era 2:** Retrofit elements. Same floor tile base; surface-mounted conduits, junction boxes, modified partitions in `#6d7178` (slightly warmer than Era 1's `#7a7f85`, different production run). Visible as overlay elements on layer 4.
|
||||
- **Era 3:** Newer construction. Cleaner materials, Commission-grade or commercial finish. Gate cluster is pure Era 3: `#b8bec4` surfaces, uniform LED-white overhead. Bar is Era 3 built by an individual (Lera): same era code, but density of accumulated modifications distinguishes it from institutional Era 3.
|
||||
|
||||
**Generator rule:** Assign era at block generation time, not chunk fill time. Chunk fill inherits era from block. Adjacent blocks can have different eras; the visual transition manifests at block boundary chunks via setbacks, service alleys, or material seams.
|
||||
|
||||
### 1.4 Saturation Hierarchy Must Be Preserved
|
||||
|
||||
D-044 visual hierarchy: entity (40–60% saturation) > objects (15–30%) > structure (5–15%).
|
||||
|
||||
The generator cannot introduce decorative or accent materials that approach entity saturation. Generated floor markings, zone signage, and accent walls must stay in the 5–15% structure tier. If the generator places anything in the 15–30% object tier as environmental decoration (painted walls, colored service doors), it must not exceed D-052 favorite color saturation rules.
|
||||
|
||||
**Hard constraint:** No generated structural or decorative element uses a hex color with saturation above 30%. This is not a style preference — it's a system requirement. If the environment reaches entity saturation levels, the player loses the ability to read NPCs by color (D-033 system breaks).
|
||||
|
||||
### 1.5 Outline Consistency Is Absolute
|
||||
|
||||
`#333340` is the universal outline for all sprites, all zones, all layers. Non-negotiable. Generated content inherits this. The generator does not produce zone-specific outlines or context-specific outlines. Consistency is what makes the visual grammar feel like a coherent world rather than a patchwork of assets.
|
||||
|
||||
### 1.6 LOS Anchor Interval Constraint
|
||||
|
||||
From locked spatial rules (V-05, Workshop #153): structural breaks (walls, pillar clusters) must occur at maximum 16 visual tile intervals in open spaces, with quarter boundaries as the primary anchor points.
|
||||
|
||||
**Why this matters for chunk fill:** Without LOS anchor placement rules, the generator can produce open-floor chunks that are visually incoherent and gameplay-broken simultaneously. A 32×32 visual tile chunk filled with open floor provides no cover, no investigation positions, no spatial drama. The LOS anchor rule is both a visual coherence rule (prevents visual emptiness) and a gameplay rule (prevents cover-free spaces).
|
||||
|
||||
**Generator rule:** Every quarter (16×16 visual tiles) must contain at minimum one structural break that interrupts east-west or north-south LOS across the quarter. This can be a wall partition, a pillar cluster, a furniture arrangement, or a zone transition boundary. The break does not need to be at the exact quarter boundary — it can be within 4 visual tiles of it.
|
||||
|
||||
---
|
||||
|
||||
## 2. How the Sub-Chunk Quarter System Produces Plausible Streetscapes
|
||||
|
||||
### 2.1 Quarter Dimensions and Their Spatial Meaning
|
||||
|
||||
A chunk is 32×32 visual tiles (32m). Divided into 4 quarters: each quarter is 16×16 visual tiles (16m).
|
||||
|
||||
16m × 16m is a meaningful spatial unit:
|
||||
- A small shop or office fits in one quarter (with walls and a narrow corridor)
|
||||
- The Terminal's scanner bay cluster (rows 6–9, ~16×4 visual tiles) is a functional sub-quarter
|
||||
- The bar's corner booth zone (NW, rows 1–5, ~8×5) occupies roughly one-third of a quarter
|
||||
|
||||
The quarter is the minimum viable building unit. A single-quarter building has room for one social zone, one access entry, and minimal interior subdivision. Two-quarter buildings have room for a public face and a semi-private back. Four-quarter buildings (full chunk) support the complexity of the Terminal or Gate Cluster.
|
||||
|
||||
### 2.2 Street Generation Must Precede Quarter Fill
|
||||
|
||||
Streetscapes are coherent only if streets are determined before buildings. The generator sequence for visual coherence:
|
||||
|
||||
1. **Block level:** Determine street network (which block edges are street-facing, which are back-of-block)
|
||||
2. **Chunk level:** Determine which chunks within the block contain buildings vs. open space vs. street continuation
|
||||
3. **Quarter level:** Determine which quarters are filled (building footprint) vs. empty (courtyard, alley, service access)
|
||||
4. **Fill level:** Place zone-appropriate floor, wall, furniture, and overhead elements within filled quarters
|
||||
|
||||
**Rule:** Building facades must face the nearest street edge. The generator never places a primary building entrance on the back-of-block side. This is what makes a block look like a block rather than a random cluster of structures.
|
||||
|
||||
### 2.3 Facade Rhythm Along a Block Face
|
||||
|
||||
Adjacent filled quarters on a street-facing block edge cannot have identical facade treatments. The visual grammar requires variation without chaos:
|
||||
|
||||
- Vary doorway position (west side / center / east side of facade) between adjacent buildings
|
||||
- Vary facade depth: some buildings set back 2–3 visual tiles from the block edge, others flush
|
||||
- Alternate overhead element density (pipes, signage) between adjacent quarters
|
||||
|
||||
**What the hand-authored examples tell us:**
|
||||
- The Terminal's entry facade (row 01): two doorways spread across 44 visual tiles, with solid wall between them. Rhythm: solid | door | long solid | door | solid.
|
||||
- The Gate Cluster's concourse south wall (row 33): the primary district-facing facade is essentially unbroken, with the district entry at ground level. Scale communicates institutional weight.
|
||||
- The Bar's main entrance (row 01): one primary door (west) + one emergency exit (east). Asymmetric, which reads as organic (functional warmth).
|
||||
|
||||
**Generator rule:** Randomly placing doorways produces facades that look like generated content. The generator should select from a small set of facade templates per zone/era/access-tier combination, then apply allowed variation parameters (doorway count, setback, overhead density). Do not treat facade generation as free parameter space.
|
||||
|
||||
### 2.4 Access Tier Gradient Is Spatial, Not Random
|
||||
|
||||
Hand-authored locations consistently follow a gradient: public street face → semi-public entry zone → semi-private interior → private back zones. This is not just a gameplay rule; it's what produces plausible architecture.
|
||||
|
||||
Terminal: Entry lobby (PUBLIC) → Scanner bays (PUBLIC MONITORED) → Main corridor (SEMI-PUBLIC) → Work zones (SEMI-PRIVATE/PRIVATE)
|
||||
Bar: Entry (PUBLIC) → Main tables (PUBLIC) → Bar counter zone (SEMI-PRIVATE) → Back room (PRIVATE)
|
||||
Gate cluster: Concourse (PUBLIC) → Customs lanes (SEMI-PRIVATE) → Staging (PRIVATE) → Aperture (RESTRICTED)
|
||||
|
||||
**Generator rule:** The access tier gradient runs north-south or from the street-facing edge inward. The public face is always the face with the most exterior exposure. The private back is always the face furthest from public circulation. Quarters are tagged with access tiers before fill content is selected. Fill content must be appropriate to the tier (no open seating in private zones, no locked doors in public zones without authority-gated reason).
|
||||
|
||||
---
|
||||
|
||||
## 3. Quarter Merge Rules: What Decides Fill vs. Empty, and Shape
|
||||
|
||||
### 3.1 Three Merge Types and Their Visual Logic
|
||||
|
||||
**2×2 merge (full chunk = 32×32 visual tiles):**
|
||||
Used for major institutions: primary logistics hubs, government facilities, large commercial buildings. The Terminal is roughly this scale (44×28 — slightly larger than a single chunk, suggesting it spans into a second chunk or uses a non-standard block configuration). The Gate Cluster (40×32) is essentially a full-chunk structure.
|
||||
Visual requirement: 2×2 merges need a legible building boundary on all four sides. The generator must place a clear facade (wall + doorway treatment) on each exposed edge, not just the street-facing side.
|
||||
|
||||
**1×2 merge (half chunk = 16×32 or 32×16 visual tiles):**
|
||||
Used for medium-scale spaces: medium offices, workshops, larger commercial venues. This is the most common merge type in a working-class district.
|
||||
Visual requirement: The long edge of a 1×2 merge is the primary facade. The short edges are either party walls (shared with adjacent building, no exterior treatment) or service edges (minimal, utilitarian). The generator must determine which axis is the long facade axis from the street orientation.
|
||||
|
||||
**L-shape merge (3 quarters):**
|
||||
This is the "functional warmth" shape — the building that grew organically. The Bar's bathroom corridor extension is a real-world example of L-shape emergence: original rectangular structure + later addition that breaks the rectangle.
|
||||
Visual requirement: L-shapes need a visual explanation for the notch. Options:
|
||||
- The notch is a service alley (narrow, maintenance-access, darker floor)
|
||||
- The notch is a courtyard or outdoor area (open, possibly furniture)
|
||||
- The notch is a later-era addition seam (visible material change at the join)
|
||||
|
||||
The generator cannot produce L-shapes where the notch is simply empty floor with no visual or functional justification. The notch must be assigned a purpose type.
|
||||
|
||||
### 3.2 Empty Quarter Types
|
||||
|
||||
An empty quarter is not just "no building here." It must be one of:
|
||||
|
||||
| Empty type | Visual treatment | Lighting | Access tier |
|
||||
|------------|-----------------|----------|-------------|
|
||||
| Open plaza | Open floor, zone palette, possibly benches | Zone-appropriate fixtures | Public |
|
||||
| Service alley | Narrow (4–6 visual tiles wide), dark floor, minimal fixtures | Sparse, cold | Semi-private to restricted |
|
||||
| Courtyard / garden | Open floor, overhead vegetation (layer 4), possibly planters | Natural or warm ambient | Semi-private (enclosed), public (open) |
|
||||
| Vehicle / cargo staging | Open floor with [CT]-type dock markers, sparse overhead | Industrial, zone palette | Semi-private |
|
||||
| Structural gap (undeveloped) | Bare floor, no furniture, possibly temporary barriers | No fixtures = very dark | Restricted by default |
|
||||
|
||||
**Generator rule:** Assign empty type at quarter planning time. Use zone and access tier to constrain the available empty types. A gate cluster zone cannot have a courtyard/garden (wrong era, wrong function). A residential zone cannot have cargo staging.
|
||||
|
||||
### 3.3 Fill vs. Empty Ratio by District Density
|
||||
|
||||
The generator needs a "density" parameter per block, derived from zoning and economic tier inputs:
|
||||
|
||||
| Density | Filled quarters per block | Expected visual character |
|
||||
|---------|--------------------------|--------------------------|
|
||||
| High (industrial/commercial core) | 12–16 of 16 | Dense block faces, few gaps, tall overhead layers |
|
||||
| Medium (mixed-use, working class) | 8–12 of 16 | Regular gaps (alleys, small plazas), varied building scales |
|
||||
| Low (residential fringe, transitional) | 4–8 of 16 | Open courtyards, gardens, undeveloped quarters common |
|
||||
|
||||
**No block should have all 16 quarters filled.** There is always at least one empty quarter per block for service access. This is the generator's hard floor rule: a block with no alleys is architecturally implausible and breaks NPC routing for maintenance-tier characters.
|
||||
|
||||
---
|
||||
|
||||
## 4. How Multi-Block Structures Read at Their Edges
|
||||
|
||||
Multi-block structures (gate terminals, horizon station access points, government complexes, stadiums, parks) span multiple chunks and must resolve their edges differently from single-chunk buildings.
|
||||
|
||||
### 4.1 The Scale Communication Problem
|
||||
|
||||
A multi-block structure must communicate its scale before the player reaches it. At a glance, it must read as "larger than a single building." The mechanisms:
|
||||
|
||||
1. **Unbroken facade length:** A single-chunk building facade is max 32 visual tiles wide. A multi-block structure has a facade spanning 64, 96, or 128 visual tiles. This length reads as institutional weight. The generator must not break this facade with building-scale interruptions (separate doorways that read as separate buildings). Long facades with wide-spaced feature doorways.
|
||||
|
||||
2. **Elevated overhead layer (layer 4):** Multi-block structures can have overhead elements that span chunk boundaries — roof structures, elevated walkways, ducts — that signal continuity. A single-chunk building has overhead elements bounded by its chunk. A multi-block structure's overhead layer crosses chunk seams.
|
||||
|
||||
3. **Setback buffer zone:** Multi-block structures almost always have a setback from the street — a cleared zone, a plaza, or a service perimeter. This setback is part of the block reservation at the zoning pass. The setback communicates "this building doesn't need to compete for street frontage."
|
||||
|
||||
### 4.2 Edge Chunk Treatment
|
||||
|
||||
The chunks at the edges of a multi-block structure face a specific visual challenge: they're part of a large building but they're adjacent to the district circulation system.
|
||||
|
||||
**Required edge treatments:**
|
||||
|
||||
- **Corner chunks:** Special facade treatment. Not a flat wall turning a 90° corner. Options: angled setback, corner feature (pillar, commission emblem, material accent in zone palette), or service access recessed into the corner.
|
||||
|
||||
- **Entry chunks:** The chunk containing the primary entrance to a multi-block structure. Entry facade must be ≥ 3× the width of the connecting corridor (from V-05). For a district street connecting at 4–6 visual tiles wide, the entry facade must be 12–18+ visual tiles wide with at minimum 2 access doors. The Gate Cluster's concourse south wall (40 visual tiles wide with 2+ entry points) demonstrates this correctly.
|
||||
|
||||
- **Party wall chunks:** Chunks on the boundary between a multi-block structure and adjacent single-chunk buildings. The multi-block structure's wall on this edge needs no decorative treatment — it reads as a party wall, which is architecturally correct and visually clean.
|
||||
|
||||
- **Back-of-building chunks:** Maintenance access for multi-block structures. These chunks face the service spine or maintenance corridors. Visual treatment: utilitarian, dark, Era 1 base materials, minimal lighting. Do not apply the public-facing material treatment to service edges.
|
||||
|
||||
### 4.3 Zone Continuity Across Chunk Boundaries
|
||||
|
||||
A multi-block structure has one zone palette for its entire footprint. The generator must not allow zone-palette variation between the chunks of a single multi-block structure. The Gate Cluster is uniformly `#b8bec4` / cold LED throughout all 40×32 visual tiles. No amber warmth creeps in from the adjacent transit corridor.
|
||||
|
||||
**Hard rule:** Chunk seams within a multi-block structure are invisible at the visual grammar level. Floor tiles, wall materials, and lighting temperature are continuous. The only things that can change at a chunk seam within a building are: functional zones (staging vs. customs vs. concourse) with their associated furniture and overhead elements, not base materials.
|
||||
|
||||
---
|
||||
|
||||
## 5. Visual Consistency Rules to Prevent Districts from Looking Random
|
||||
|
||||
### 5.1 The Three Consistency Anchors
|
||||
|
||||
A generated district avoids looking random if every chunk can be traced back to three consistent sources: its **zone palette**, its **era**, and its **access tier gradient**. These three together determine:
|
||||
- What materials appear on the floor and walls
|
||||
- What modifications and overlays exist
|
||||
- What kind of furniture and overhead elements are placed
|
||||
- How light is distributed
|
||||
|
||||
If the generator maintains consistency on these three anchors across all chunks in a district, visual coherence follows automatically. Randomness appears when chunks are filled without reference to these anchors.
|
||||
|
||||
### 5.2 Street Network as Visual Spine
|
||||
|
||||
The district's street network is the visual skeleton. Every building facades toward it; every service access routes away from it. The street network determines orientation for the entire district.
|
||||
|
||||
Visual rules for generated streets:
|
||||
- Street floor tile uses a dedicated transitional material (not the adjacent building's floor palette — streets are shared infrastructure, not zone-specific)
|
||||
- Street width by type: maintenance corridor 2vt, internal building 2–4vt, district street 4vt, transition corridor 6vt, gate concourse 8vt (locked in V-05)
|
||||
- Street lighting: zone-appropriate fixtures placed at regular intervals (every 8–12 visual tiles for primary streets, every 16–20 for secondary)
|
||||
- Street intersection treatment: clear visual signal that two streets meet (material change at the crossing tile, or a pillar/feature at the corner)
|
||||
|
||||
### 5.3 Landmark Anchors and District Readability
|
||||
|
||||
Hand-authored districts have visual landmarks that orient the player: the terminal's institutional facade, the bar's amber light spill, the gate cluster's administered cold white. Generated districts need the same.
|
||||
|
||||
**Generator rule:** Each district should have minimum 1 landmark structure per block cluster (4 blocks = 1 district quadrant). A landmark structure is a multi-block structure or a building with distinctive visual treatment. The generator reserves landmark slots at the district planning pass, before block generation. Landmark structures get the full multi-block edge treatment (§4).
|
||||
|
||||
Without landmark anchors, generated districts produce visual monotony where every block looks like every other block. The landmark is not about decoration — it's about navigation and spatial orientation.
|
||||
|
||||
### 5.4 Facade Variation Budget
|
||||
|
||||
Adjacent buildings on the same block face must vary in at least 2 of these 5 parameters:
|
||||
1. Primary entry position (west / center / east of facade)
|
||||
2. Facade depth (flush / 1–2vt setback / 3–4vt setback)
|
||||
3. Overhead element density (sparse / moderate / dense)
|
||||
4. Building height expression (single overhead layer / double overhead layer with structural bridge)
|
||||
5. Era modification markers (none / minor / heavy)
|
||||
|
||||
If adjacent buildings vary in only 1 or 0 parameters, the block face looks copy-pasted. The generator's facade parameter selection must check the adjacent quarter's choices before committing.
|
||||
|
||||
### 5.5 Lighting Temperature Is Zone-Specific, Not Building-Specific
|
||||
|
||||
The lighting temperature in the visual grammar is set by zone, not by individual buildings. A bar inside an institutional zone gets institutional lighting, not amber. The only exception is player-facing hand-authored social sites where lighting is an authored decision (The Last Shift's amber is Lera's decision, not the zone's character).
|
||||
|
||||
**Generator rule:** Generated buildings inherit their lighting temperature from the zone palette. The generator does not assign lighting temperatures at the building level. Lighting is a zone property.
|
||||
|
||||
This is important because the palette gradient rule (locked in Workshop #153) creates visual territory:
|
||||
- Gate/official: cool white → cargo/functional: grey-navy → transit neutral: dark → social warm: amber
|
||||
|
||||
A player walking through a generated district should feel the temperature gradient shift as they move from institutional zones into residential or social zones. This gradient is the district's visual fingerprint.
|
||||
|
||||
### 5.6 The "Settled" Principle — Placement Density Communicates Character
|
||||
|
||||
D-051 ("settling is placement"): spaces feel inhabited when they have accumulated objects, not when they have large open areas. Empty space reads as abandoned or transitional. Filled space reads as active.
|
||||
|
||||
For the generator, this translates to a **placed-object density** budget per quarter:
|
||||
|
||||
| Zone type | Objects per quarter (typical) | Notes |
|
||||
|-----------|-------------------------------|-------|
|
||||
| Institutional (terminal, gate) | High: 8–14 large objects (terminals, cargo containers, desks) | Functional accumulation |
|
||||
| Social (bar, market) | Medium-high: 6–10 objects (tables, seating, service equipment) | Personal accumulation |
|
||||
| Residential | Medium: 4–8 objects (furniture, personal items) | Domestic accumulation |
|
||||
| Maintenance / service | Low: 1–4 objects (utility equipment, sparse) | Functional minimum |
|
||||
| Transit / corridor | Very low: 0–2 objects (signage, benches only) | Movement spaces stay clear |
|
||||
|
||||
**The generator must not produce empty rooms.** An empty room is an authored decision (the restricted storage room is sparse by design — contraband doesn't advertise itself). A generated empty room is an unfinished room. If the zone/access tier combination doesn't justify a sparse object count, the generator adds zone-appropriate clutter.
|
||||
|
||||
---
|
||||
|
||||
## Summary: What the Generator Must Guarantee from a Visual Perspective
|
||||
|
||||
The following visual properties are non-negotiable outputs of any generator pipeline:
|
||||
|
||||
1. **Every chunk belongs to exactly one zone palette.** No mixed-palette chunks. Zone boundaries are block-level decisions.
|
||||
|
||||
2. **Every block has an era tag.** Era modifies surface materials within zone palette bounds. Adjacent blocks may have different eras; the visual transition is handled at block boundary chunks.
|
||||
|
||||
3. **Access tier gradient runs from street face inward.** Public front, private back. This determines facade treatment, interior subdivision, and furniture selection.
|
||||
|
||||
4. **Corridor widths are enforced by type** (V-05): maintenance 2vt, internal building 2–4vt, district street 4vt, transition 6vt, gate concourse 8vt. The generator cannot produce corridors narrower than these minimums.
|
||||
|
||||
5. **LOS anchors exist at max 16vt intervals.** Every quarter contains at minimum one structural break.
|
||||
|
||||
6. **No generated element exceeds structure-tier saturation (15%).** Entity visual hierarchy is inviolable.
|
||||
|
||||
7. **All outlines are `#333340`.** No exceptions.
|
||||
|
||||
8. **Empty quarters have assigned types.** Empty is not null — it is plaza, alley, courtyard, staging, or undeveloped, each with specific visual treatment.
|
||||
|
||||
9. **Multi-block structure facades are unbroken and wide.** Entry facade ≥ 3× connecting corridor width, minimum 2 access doors.
|
||||
|
||||
10. **Lighting temperature is zone-assigned, not building-assigned.** The zone palette determines fixture color temperature. Buildings do not override this.
|
||||
|
||||
11. **Adjacent filled quarters on a street face vary on at minimum 2 facade parameters.** Facade variation is enforced, not random.
|
||||
|
||||
12. **Every district quadrant has at minimum 1 visual landmark.** Landmark slots are reserved at district planning pass before block generation.
|
||||
|
||||
---
|
||||
|
||||
*These constraints are derived from the hand-authored v0.1 content (Terminal, Bar, Gate Cluster, Smuggling Corridors), the confirmed visual grammar (visual-grammar-v01.md), the locked spatial rules from Workshop #153 (V-05), and the D-records cited throughout. Any generator proposal that violates these constraints will produce visually incoherent output regardless of how correct the spatial math is.*
|
||||
@@ -0,0 +1,468 @@
|
||||
# Generator Architecture Workshop — Round 2: Araminta
|
||||
## Visual Coherence for Edge Bleed and Non-Urban Terrain
|
||||
|
||||
**Author:** Araminta (Visual Designer)
|
||||
**Date:** 2026-02-27
|
||||
**Workshop:** Generator Architecture (Ticket #562)
|
||||
**Responding to:** Round 1 notes (Qatux), Nigel-round1.md (OQ-8 on flavor vocabulary), Ozzie-round1.md (anti-grid, historical palimpsest), Lead Directive (edge bleed, non-urban terrain, multi-playstyle support)
|
||||
|
||||
---
|
||||
|
||||
## Acknowledging the Lead Directive
|
||||
|
||||
The lead says this is a game about **the inherent asymmetry of human awareness** — not specifically a detective game. I want to say directly: the visual grammar I've built already serves this. Entity colors (D-033) encode the player's *subjective* relationship to every NPC, not the NPC's objective status. Access tier gradients encode social topology, not investigation routes. Lighting temperature communicates "who inhabits this space," not "who the suspect is."
|
||||
|
||||
What I need to do in Round 2 is make explicit that these visual systems serve **all playstyles simultaneously**:
|
||||
- The investigator reads access tiers as information about where evidence could be hidden
|
||||
- The career-builder reads access tiers as information about where their workplace authority extends
|
||||
- The relationship-seeker reads lighting temperature as information about where warmth is
|
||||
- The explorer reads LOS asymmetry as information about what's worth investigating
|
||||
- The trader reads object density as information about economic activity
|
||||
|
||||
The grammar doesn't favor the detective. It reads *space as social reality*. That already supports all playstyles. What changes in Round 2 is that the grammar needs to extend to district boundaries and natural terrain — both of which the current spec treats as edge cases.
|
||||
|
||||
---
|
||||
|
||||
## 1. District Edge Bleed — Gradient Rules and Visual Ambiguity
|
||||
|
||||
### The Core Problem
|
||||
|
||||
A hard district boundary at the 256×256 visual tile line would produce visible seams. A player crossing from an institutional district into a residential one would see the palette snap. That's the grid made visible at district scale — exactly what the lead directive prohibits.
|
||||
|
||||
### The Transitional Block System
|
||||
|
||||
**Rule:** The outermost 1-block ring (64×64 visual tiles wide, the entire perimeter) of every district is a **transitional zone**. It is not fully committed to either the district's zone palette or the adjacent district's zone palette. It blends.
|
||||
|
||||
The blend is not random — it is **directional and material-specific**:
|
||||
|
||||
| Element | Transition rule |
|
||||
|---------|----------------|
|
||||
| Floor tiles | Interpolate toward adjacent district over the 64vt block width. At block center (32vt), halfway blend. |
|
||||
| Wall materials | Do NOT interpolate — walls remain in the building's home district palette. Walls are structural; inconsistent wall materials read as a construction error, not a cultural gradient. |
|
||||
| Lighting fixture color | Interpolate toward adjacent district temperature over the 64vt block. Fixtures in the edge block use a temperature midway between zone A and zone B. |
|
||||
| Ambient (CanvasModulate) | Interpolate: the screen-space ambient at the district boundary is the average of both zones' ambient values. |
|
||||
| Overhead elements (layer 4) | Follow the building's home palette — no interpolation. The overhead layer is attached to structures, not geography. |
|
||||
|
||||
**Example:** Terminal (cool grey `#1a1e24`, fixture `#c8d8f0`) meets Bar zone (warm `#1e1912`, fixture `#f0b840`). The transitional block between them gets floor `#1c1b1b` (average) and fixture temperature `#e0c090` (average — a neutral warm-cool white). The player feels themselves moving between temperature zones. They don't see a line.
|
||||
|
||||
### Shared Infrastructure as Grid Dissolvers
|
||||
|
||||
Infrastructure doesn't respect district lines. The maintenance spine continues across boundaries. Street network continues across boundaries. Power conduits continue.
|
||||
|
||||
**Visual rule:** Any infrastructure element that crosses a district boundary maintains its own visual identity regardless of which zone's palette it passes through. A maintenance corridor that runs through both zones is uniformly `#181818` floor and `#d0d8e0` dim fixtures throughout — the zone doesn't color the infrastructure.
|
||||
|
||||
This produces a specific effect: the player navigating via maintenance corridors and service spines experiences district transitions as gradual warmth or coolness changes in the main spaces they pass through, not as clear demarcation. The maintenance route is the same everywhere; what changes is the ambient leaking through doorways.
|
||||
|
||||
### Palette Gradient Sequence (The Visual Spine of a Planet-Side District)
|
||||
|
||||
From my memory — and now formalized: the palette gradient rule should operate at district scale, not just within a district.
|
||||
|
||||
**The canonical gradient for a settlement:**
|
||||
|
||||
```
|
||||
Gate/Official (cool white, high Meridian)
|
||||
→ Cargo/Functional (grey-navy, medium Meridian)
|
||||
→ Transit/Neutral (dark, degraded Meridian)
|
||||
→ Social/Warm (amber, minimal Meridian)
|
||||
→ Residential (deeper warm, very sparse)
|
||||
→ Industrial periphery (cool-neutral, Era 1)
|
||||
→ Agricultural edge / Wilderness (natural ambient)
|
||||
```
|
||||
|
||||
A player moving from the gate cluster outward should feel this sequence of temperature changes. Each district boundary is a step along the gradient. No step should be abrupt. The transitional block system produces smooth steps.
|
||||
|
||||
### Visual Ambiguity at the Boundary — The Test
|
||||
|
||||
**Test:** A player who has walked into a space and stopped moving should not be able to say with certainty "I'm in District A" vs. "I'm in District B." They should be able to say "I'm somewhere between institutional and residential." That ambiguity is correct. District boundaries are social constructs; they should feel like zones of contested identity.
|
||||
|
||||
**Mechanism:** Beyond the transitional block palette blend, the boundary zone should contain:
|
||||
- At least one building whose aesthetic reads ambiguously (a residential building with institutional materials — "this was built during the corporate ownership period")
|
||||
- At least one infrastructure element that belongs to neither palette (a public bench, a civic planter, a notice board — neutral civic-grey)
|
||||
- Faction presence that differs from either zone's dominant faction (the boundary is where power is ambiguous)
|
||||
|
||||
---
|
||||
|
||||
## 2. Non-Urban Terrain Visual Grammar
|
||||
|
||||
### The Problem with the Current Visual Grammar
|
||||
|
||||
My Round 1 grammar assumed fixture-based lighting throughout. Natural terrain has no light fixtures — it has ambient daylight, weather, and time-of-day. The zone palette system needs a natural terrain extension.
|
||||
|
||||
The key difference is not the palette — it's the **lighting model**. Urban zones use `PointLight2D` with defined fixture radii and specific color temperatures. Natural terrain uses **global ambient light** (CanvasModulate adjusted by time-of-day and weather) with local shadow patches (tree canopy, rock shadows, terrain occluders) rather than light pools.
|
||||
|
||||
This is a different visual regime, but it's compatible with the same grammar: it just uses different sources for the same properties (floor color, ambient, lighting temperature, LOS anchors).
|
||||
|
||||
### Natural Zone Palettes
|
||||
|
||||
#### Farmland
|
||||
|
||||
Character: human-worked earth, seasonal rhythm, functional machinery. Warm earth tones crossed with metal and worn wood.
|
||||
|
||||
| Element | Hex | Notes |
|
||||
|---------|-----|-------|
|
||||
| Floor — open soil | `#1a1510` | Dark warm brown, turned earth |
|
||||
| Floor — crop cover (summer) | `#0e1408` | Deep green-dark, living crops overhead |
|
||||
| Floor — crop cover (dormant) | `#1c1610` | Pale straw-brown, cut stalks |
|
||||
| Surface structures | `#2a2010` | Dried wood, weathered metal, fence posts |
|
||||
| Ambient (daylight) | `#0e0c08` | Warm near-black ground shadow |
|
||||
| Ambient (dusk) | `#120810` | Deep dusty purple-rose |
|
||||
| Lighting (nocturnal) | `#f0b840` (amber, very sparse) | Oil lamp, generator-powered work light |
|
||||
| Overhead (canopy) | `#0a1006` at 60% opacity | Crop overhead layer — partial occlusion |
|
||||
|
||||
LOS anchors in farmland: tree lines, fencing, equipment rows, barn structures, irrigation channels. Interval still max 16vt — the open field is broken by these.
|
||||
|
||||
**Object density:** 4–8 per quarter. Crops are floor elements (z=0/1), not objects. Objects are equipment (tractors, plows, silos), structures (barns, sheds, irrigation heads), and markers (fence posts, gate structures).
|
||||
|
||||
#### Wilderness / Forest
|
||||
|
||||
Character: ambient darkness, dense occlusion, no human pattern. This is where both Ozzie's "place I'm not supposed to be" fantasy and the stealth/exploration loop live.
|
||||
|
||||
| Element | Hex | Notes |
|
||||
|---------|-----|-------|
|
||||
| Floor — forest floor | `#0e120e` | Dark organic green-brown |
|
||||
| Floor — undergrowth | `#141a14` | Slightly lighter, mossy texture |
|
||||
| Floor — clearings | `#181c14` | Open patches, warmer |
|
||||
| Surface (exposed rock) | `#141618` | Cool grey-blue stone |
|
||||
| Ambient | `#080a08` | Near-black, very dark |
|
||||
| Canopy overhead (z=4) | `#0a1008` at 55–75% opacity | Dense forest blocks: variable opacity by canopy thickness |
|
||||
| Lighting (sparse, nocturnal) | `#c0d8e8` (moonlight) | Cold ambient, from gaps in canopy, not fixture-based |
|
||||
|
||||
LOS in forest: extremely broken. 3–5 visual tile clear vision before a tree line interrupts. The forest is a zone where the player has naturally degraded visibility — not from the fog shader, from dense overhead layer occlusion.
|
||||
|
||||
**Key visual rule for wilderness:** The overhead layer (z=4) does the work that walls do in urban spaces. Dense forest canopy at 70% opacity is the wilderness equivalent of a building interior. The player sees ground-level detail but loses the mid-range LOS that urban spaces provide.
|
||||
|
||||
**Object density:** 0–3 per quarter. Terrain features (fallen logs, rock outcroppings), occasional structures (an abandoned hut, a collapsed wall remnant), natural water features. Never furniture or organized equipment.
|
||||
|
||||
#### Ocean / Coastal Water
|
||||
|
||||
Character: open, reflective, dark, directional light from surface.
|
||||
|
||||
| Element | Hex | Notes |
|
||||
|---------|-----|-------|
|
||||
| Deep water floor | `#060c14` | Near-black deep blue |
|
||||
| Shallow coastal | `#0e1820` | Slightly lighter, sand visible through water |
|
||||
| Tidal zone | `#181c1a` | Wet rock, dark neutral |
|
||||
| Ambient | `#060810` | Cold near-black |
|
||||
| Surface reflection | `#c0c8d8` (specular at 20% opacity, animated) | Starlight/sunlight reflection — visual grammar's water treatment |
|
||||
|
||||
For ocean shores: the "shore" is a transitional band 4–12 visual tiles wide between the natural-water floor palette and the land/beach palette.
|
||||
|
||||
**LOS in water:** Characters on water have dramatically extended LOS (no urban occlusion). Characters observing *from land looking at water* have similar extension — open water is a surveillance dead zone for urban investigations but a clear field for coastal ones. A player on a dock watching boats has long-range LOS that urban environments never permit.
|
||||
|
||||
#### Beach / Coastal
|
||||
|
||||
Character: warm sand tones, open flat, tidal variation.
|
||||
|
||||
| Element | Hex | Notes |
|
||||
|---------|-----|-------|
|
||||
| Dry sand | `#2a2218` | Dark warm tan |
|
||||
| Wet sand | `#201a10` | Darker, where tide has been |
|
||||
| Dune vegetation | `#121610` | Sparse dark grass |
|
||||
| Ambient | `#0c0a06` | Warm near-black |
|
||||
| Lighting | Global ambient, no fixtures in beach zones | Daylight is the light source |
|
||||
|
||||
**Object density:** 0–3 per quarter. Drift material (logs, seaweed, debris), tidal structures (rock pools, seawall sections), human presence markers where applicable (a boat mooring, a net-drying frame). Beach is one of the lowest-density natural zones.
|
||||
|
||||
#### Mountain / High Terrain / Snow
|
||||
|
||||
Character: cold, bright surfaces, compressed atmospheric light, vertically dramatic.
|
||||
|
||||
| Element | Hex | Notes |
|
||||
|---------|-----|-------|
|
||||
| Rock face | `#181c22` | Dark blue-grey stone |
|
||||
| Snow surface | `#c8d8e8` | Pale blue-white — deliberately HIGH brightness contrast |
|
||||
| Ice | `#aab8c8` | Slightly darker than snow, more specular |
|
||||
| Ambient | `#10141a` | Cold dark blue-grey |
|
||||
| Lighting | Global ambient, blue-white shifted (`#d0e4f8` at dawn, `#a8c0e0` at dusk) | Mountain light is directional and cold |
|
||||
|
||||
**Visual grammar challenge:** Snow is bright. It's the only natural terrain type where the floor tile is significantly lighter than the ambient — which inverts the typical relationship (dark floor, lighter fixture pools). This needs special handling: snow tiles have an inherent luminosity value that the ambient doesn't reduce to black. They glow passively.
|
||||
|
||||
**LOS in mountain terrain:** Extremely variable. Cliff faces create absolute LOS walls. Ridgelines create elevation-differential LOS (attacker on ridge sees down; defender below cannot see up). The vertical surprise that Ozzie specifically named as a key spatial experience is native to this terrain type.
|
||||
|
||||
#### Secluded Town / Rural Settlement
|
||||
|
||||
Character: warm residential, low institutional density, personal accumulation (functional warmth at architectural scale).
|
||||
|
||||
This is the planet-side analog of the Bar's aesthetic: human habitation that accumulated rather than was planned. Zone palette:
|
||||
|
||||
| Element | Hex | Notes |
|
||||
|---------|-----|-------|
|
||||
| Floor | `#1a1612` | Dark warm brown-grey, worn stone/composite |
|
||||
| Wall face | `#28201a` | Warm brown — between maintenance and bar zone |
|
||||
| Ambient | `#0e0c0a` | Warm near-black |
|
||||
| Lighting | `#f0b840` amber (social, local) + `#d8c890` neutral-warm (commercial, streets) | Mix of fixture temperatures by building type |
|
||||
| Overhead | Very sparse institutional; high personal accumulated objects | Signs, laundry lines, planters, awnings |
|
||||
|
||||
Secluded towns have higher personal overhead density than any urban zone. Individual character expressed through what's placed on z=4: awnings, potted plants on window ledges, a sign written by hand, a rope stretched between buildings. The institutional overhead layer (pipes, ducts, service equipment) is rare. This is the visual grammar of *individual choices at human scale*.
|
||||
|
||||
### Natural Terrain LOS Anchors
|
||||
|
||||
In natural terrain, the max 16vt LOS anchor interval rule still applies, but anchors are:
|
||||
|
||||
| Anchor type | Visual tile width | Notes |
|
||||
|-------------|-------------------|-------|
|
||||
| Single tree | 1–2vt (trunk) | Canopy extends 3–5vt on z=4 |
|
||||
| Tree cluster | 4–8vt | Full LOS break at floor level |
|
||||
| Rock formation | 2–4vt | Hard LOS break, permanent |
|
||||
| Terrain elevation change | 0vt (invisible at floor) | Creates vertical LOS asymmetry |
|
||||
| Fence/wall | 1vt | Partial cover; human-placed |
|
||||
| Building | 4–32vt | Full LOS break |
|
||||
| Water feature (river, stream) | 2–6vt | Not a LOS block but a movement constraint |
|
||||
|
||||
The generator must place natural LOS anchors at the same interval rules as structural elements. A forest clearing that's 30+ visual tiles wide with no trees in it is both visually wrong (natural clearings have fallen logs, undergrowth, isolated trees) and gameplay wrong (no cover in either direction for 30m).
|
||||
|
||||
---
|
||||
|
||||
## 3. Anti-Grid Techniques
|
||||
|
||||
Ozzie is right: "the grid will show." The block grid is 64×64 visual tiles. Even with quarter variation inside blocks, if block edges always align and streets always run at 90°, the skeleton is perceptible. Here are the visual techniques that break it.
|
||||
|
||||
### Technique 1: Diagonal Connectors
|
||||
|
||||
Streets don't have to run perpendicular. A 45° diagonal connector between two otherwise-gridded streets reads as older than the grid (it predates the block layout, it follows a natural path).
|
||||
|
||||
Visual constraints on diagonals:
|
||||
- Must be at minimum 4vt wide (same as district street minimum, to handle tile-based movement)
|
||||
- Floor material is distinct from both connected street systems — diagonal connectors use the transitional corridor palette (`#181818` neutral dark) regardless of what they connect, because they read as "infrastructure that predates the current layout"
|
||||
- Cannot exceed 45° from grid axis — steeper angles produce tile-movement awkwardness
|
||||
- LOS along a diagonal is blocked at the two ends by the street network it connects — the diagonal is a slot, not an open approach
|
||||
|
||||
One diagonal connector per 4–6 blocks is sufficient. Too many diagonals produce a different regularity.
|
||||
|
||||
### Technique 2: Irregular Setbacks at Block Faces
|
||||
|
||||
Buildings don't need to be flush with the block edge. Setback variation per building along a block face:
|
||||
|
||||
| Setback | Visual result | What it communicates |
|
||||
|---------|--------------|----------------------|
|
||||
| 0vt (flush) | Building wall at block edge | Institutional, dense, planned |
|
||||
| 1–2vt | Narrow threshold space | Semi-private front threshold, step/stoop |
|
||||
| 3–4vt | Small garden/forecourt | Residential, some space claimed outside |
|
||||
| 5–8vt | Significant forecourt | Commercial frontage, civic |
|
||||
| Recessed door | Door 2–3vt inside flush facade | Industrial — the approach is exposed |
|
||||
|
||||
**Rule:** No two adjacent buildings on the same block face should have identical setbacks. The variation is not random — it's driven by access tier (public buildings set back more) and era (Era 1 buildings are flush, Era 3 buildings have planned setbacks). But within those constraints, the setback varies.
|
||||
|
||||
The aggregated effect of setback variation is a block face that is not a straight wall. The building line is irregular. The player's visual experience of the block's edge is broken into a series of small spatial events rather than a continuous surface.
|
||||
|
||||
### Technique 3: Overhead Extension Past Block Boundaries
|
||||
|
||||
On z=4 (overhead layer), buildings can extend past their ground-floor footprint:
|
||||
- Awnings and overhangs: 1–3vt extension into the street
|
||||
- External staircases: 2–4vt extension, adds vertical element
|
||||
- Second-story or gallery bridges: structural extensions that visually connect two adjacent buildings across the street or alley between them
|
||||
|
||||
Overhead extensions do not block movement (the player moves on z=1 floor). But they change the visual experience of the street: it is partially covered, has variable ceiling height, and — critically — it makes the block edge ambiguous. The building's overhead presence is larger than its footprint.
|
||||
|
||||
**At block seams:** An awning or overhead element that spans a block seam reads as a single building structure regardless of which block generates it. The block seam disappears beneath the visual overhead.
|
||||
|
||||
### Technique 4: Infrastructure Routing at Angle to Grid
|
||||
|
||||
A power conduit, a water pipe, an old rail line that pre-dates the current block layout — if it runs at a slight angle to the street grid, it reads as older than the layout it crosses.
|
||||
|
||||
Visual treatment:
|
||||
- Infrastructure that runs at angle to grid uses the maintenance corridor palette (`#181818` + `#4e5054` markers)
|
||||
- It appears on z=4 where it crosses buildings (overhead routing), z=0 where it's underground
|
||||
- Where it emerges at z=1, it creates small visual events: a junction box, a pressure valve, an access hatch
|
||||
|
||||
The diagonal infrastructure is the generator's primary tool for producing "historical palimpsest" in urban districts. It encodes a simple history: "this predates the current layout." The player doesn't need to be told — they see the conduit cutting diagonally across three blocks and understand that something was here before the current plan.
|
||||
|
||||
### Technique 5: Light Territories vs. Grid Territories
|
||||
|
||||
Light pools from `PointLight2D` are circular. They don't respect block edges. A fixture placed near a block edge casts light into both blocks. The player reads the lit area as a single spatial unit regardless of which block generates it.
|
||||
|
||||
**Exploiting this:** Place fixtures deliberately near block edges, particularly at street intersections, to create light territories that span blocks. The bright zone at an intersection reads as a town square, a gathering point, a visible moment — even if it's just two block corners meeting.
|
||||
|
||||
The grid says: this is the corner of Block 3 and Block 7. The light says: this is *the corner*, a single social fact with meaning. Players navigate by light, not by block IDs.
|
||||
|
||||
### Technique 6: Vegetation Overflow and Organic Intrusion
|
||||
|
||||
In planet-side settings, natural elements can cross block boundaries:
|
||||
- A tree planted at the edge of a courtyard extends its canopy (z=4) into the adjacent street
|
||||
- A drainage channel follows gravity rather than block edges — it cuts diagonally through two blocks
|
||||
- Ivy or climbing vegetation on a building facade extends toward an adjacent building
|
||||
|
||||
These organic elements are generation-time decisions: the generator tags certain building edge quarters as "vegetation boundary permitted" and places the appropriate z=4 elements. The visual result is plant matter that doesn't respect the invisible block lines — exactly what makes planet-side settlements feel like they've been there a while.
|
||||
|
||||
### Technique 7: Street Width Variation
|
||||
|
||||
Streets don't have to be uniform width. The same street can narrow where buildings press in and widen where they set back. This produces the visual impression of a street that *evolved* — some merchants built closer to the edge, others further.
|
||||
|
||||
Implementing within the minimum corridor width rules:
|
||||
- Minimum 4vt for district streets (V-05) — this is the floor
|
||||
- Maximum is unconstrained upward — a street can be 8, 12, or 16vt wide at plazas
|
||||
- The width changes happen at building boundaries (where one building's facade gives way to another's)
|
||||
|
||||
A street that varies from 4vt to 8vt to 6vt along its length reads as human-built. A street that is consistently 4vt everywhere reads as designed.
|
||||
|
||||
---
|
||||
|
||||
## 4. Unified Empty Quarter Taxonomy
|
||||
|
||||
Qatux correctly flagged that my Round 1 taxonomy (spatial types) and Nigel's taxonomy (content categories) are at different abstraction levels. Here's the unified version.
|
||||
|
||||
### The Two-Layer Model
|
||||
|
||||
Every empty/unclaimed quarter gets:
|
||||
1. **A spatial type** — the physical geometry and access tier of the space
|
||||
2. **A content category** — the social/economic activity that inhabits it
|
||||
|
||||
These are assigned independently but have compatibility constraints.
|
||||
|
||||
### Layer 1: Spatial Types (5 canonical)
|
||||
|
||||
| Spatial type | Floor width | Access tier | Ambient character |
|
||||
|-------------|-------------|-------------|-------------------|
|
||||
| **Open plaza** | Full quarter (16×16) | Public | Zone palette floor, fixture density normal |
|
||||
| **Service alley** | 2–6vt wide, full quarter depth | Semi-private → restricted | Dark, sparse fixtures, maintenance palette |
|
||||
| **Courtyard** | Full quarter interior (enclosed by adjacent buildings) | Semi-private | Reduced ambient, personal-scale objects |
|
||||
| **Staging ground** | Full quarter, some permanent markers | Semi-private → private | Industrial floor markings, cargo markers |
|
||||
| **Undeveloped gap** | Any width | Restricted by default | Bare floor, no fixtures, very dark |
|
||||
|
||||
### Layer 2: Content Categories (Nigel's 4 + structural baseline)
|
||||
|
||||
| Content category | Who placed it | Economic signal | Faction signal |
|
||||
|----------------|---------------|-----------------|----------------|
|
||||
| **Civic baseline** | No one — it's just maintained infrastructure | Neutral | Neutral (Commission maintains public space) |
|
||||
| **Informal economy** | Individuals, self-organized | Active trade, self-reliance | Low faction control or contested |
|
||||
| **Settlement** | Community, long-term residents | Community investment, stability | High community cohesion, low institutional |
|
||||
| **Economic stress** | Necessity, not choice | Insufficient formal economy | Institutional failure or neglect |
|
||||
| **Faction presence** | Institutional actor | Faction extending influence | High faction control, normalizing presence |
|
||||
|
||||
### Compatibility Matrix
|
||||
|
||||
| | Open plaza | Service alley | Courtyard | Staging ground | Undeveloped gap |
|
||||
|---|-----------|--------------|-----------|----------------|-----------------|
|
||||
| Civic baseline | ✓ primary | ✓ (access infrastructure) | ✓ | ✗ | ✗ |
|
||||
| Informal economy | ✓ primary | ✓ (side-alley stalls) | ✓ secondary | ✗ | ✓ (squatter use) |
|
||||
| Settlement | ✓ (public garden) | ✗ | ✓ primary | ✗ | ✓ (shacks) |
|
||||
| Economic stress | ✓ (abandoned plaza) | ✓ (unauthorized storage) | ✓ | ✓ (mothballed staging) | ✓ primary |
|
||||
| Faction presence | ✓ primary | ✗ | ✗ | ✓ (checkpoint infrastructure) | ✗ |
|
||||
|
||||
### The Full Unified Taxonomy
|
||||
|
||||
Combining both layers produces the specific fill elements:
|
||||
|
||||
**Open Plaza + Civic baseline:** Benches, news ticker (if near transit), waste receptacles, civic signage. Neutral floor (zone palette). Normal fixture density. Zone: public face of a district.
|
||||
|
||||
**Open Plaza + Informal economy:** Market stalls (temporary awning structures, z=4), vendor cart positions, cluster of seating near central stall. Floor markings from stall activity. Slightly warmer fixture temperature than zone baseline (vendors bring their own lights). Access: nominally public but stall arrangement creates semi-private pockets.
|
||||
|
||||
**Open Plaza + Settlement:** Community garden planters, improvised seating clusters (salvaged furniture, not purchased), a shrine or memorial marker (small z=2 object). Warm, low-tech. The garden has overhead crop layer at z=4. Lighting: minimal, personal-scale.
|
||||
|
||||
**Open Plaza + Economic stress:** Abandoned stalls (awning frames without cloth), cracked floor (visual floor tile variant with cracks — same palette, different texture), no functioning fixtures (dark), possibly a temporary windbreak (partial barrier). Reads as: there used to be activity here.
|
||||
|
||||
**Open Plaza + Faction presence:** Commission kiosk (small structure, institutional-grey palette, z=4 signage in neutral Michroma labels), checkpoint barrier positions (can be raised or lowered), public notice board with official announcements. Cold LED lighting regardless of zone.
|
||||
|
||||
**Service alley + Civic baseline:** Drainage channel, access hatches to z=0 maintenance. Narrow, dark, maintenance palette. Objects: conduit runs, junction boxes.
|
||||
|
||||
**Service alley + Informal economy:** Vendor carts staged here between market hours. Informal repair shop set into an alcove (small bench, tools, spare parts on shelving). Lighting: one additional fixture hung by the vendor, slightly warmer than alley baseline.
|
||||
|
||||
**Service alley + Economic stress:** Unauthorized storage — cargo containers pushed against one wall, none of them labeled correctly. Possibly a temporary shelter structure. Very dark. Access: technically public but social convention says otherwise.
|
||||
|
||||
**Courtyard + Settlement:** Private gardens, seating built into the courtyard walls, personal decorations on the surrounding building faces (z=4 neighbor additions: window boxes, hanging fabric, a clothesline). This is the warmest non-social-site space the generator produces. Enclosed, personal, warm.
|
||||
|
||||
**Courtyard + Informal economy:** Small informal workshop at one end (tools, a bench), goods laid out for inspection or trade. Semi-regular social gathering space — these become recurring NPC locations.
|
||||
|
||||
**Staging ground + Civic baseline:** Vehicle bay positions (dock marker lines on floor), cargo transporter docking points, maintained by the district authority. Clean industrial palette.
|
||||
|
||||
**Staging ground + Economic stress:** Mothballed staging. Old dock points, defunct equipment left in place, no active use. The generators are off — no lighting except ambient bleed from adjacent zones.
|
||||
|
||||
**Staging ground + Faction presence:** Faction-controlled logistics checkpoint. Corporate branded equipment, manifest scanners, branded service vehicles. If Commission-aligned: grey and cold LED. If Syndic-aligned: corporate colors (within saturation rules — muted versions of faction identity).
|
||||
|
||||
**Undeveloped gap + Economic stress:** Primary use. Shack structures (makeshift, Era 0 materials — salvaged, pre-palette), unauthorized occupation. Narrow footprint. Reads as: the gap between buildings that someone decided to live in.
|
||||
|
||||
**Undeveloped gap + Informal economy:** Squatter market — the gap between two buildings has become a covered passage lined with informal trade. Narrow, overhead covered with salvaged material (z=4), dim personal lighting.
|
||||
|
||||
---
|
||||
|
||||
## 5. Visual Vocabulary for Nigel's Flavor Categories
|
||||
|
||||
Nigel asked specifically for the visual vocabulary that distinguishes his four flavor categories. Here it is — the visual signal the player reads at a glance, before they're close enough to see detail.
|
||||
|
||||
### Category 1: Informal Economy Indicators
|
||||
|
||||
**At-a-glance signal:** Warm irregular lighting against the zone baseline. Awning structures on z=4 that don't align with building facades — they're temporary additions. Goods on the ground (floor-level objects, z=2) in clusters that suggest display, not storage.
|
||||
|
||||
**Visual vocabulary:**
|
||||
- **Awning material:** Worn fabric or salvaged panel on z=4, at 65% opacity (semi-transparent — you can see through worn fabric). Color: zone-warm variant (amber or dusty orange-brown, staying below 20% saturation).
|
||||
- **Goods display:** Small objects in regular low-grid patterns (z=2), 0.5–1vt spacing, muted warm-adjacent colors (dried goods, second-hand items — nothing vivid).
|
||||
- **Vendor lighting:** One additional small PointLight2D per stall, radius 3–4vt, temperature `#f0d090` (warm yellow — warmer than zone fixtures). Creates warm pooling that doesn't match zone's fixture grid.
|
||||
- **Floor wear:** A visually-distinct floor tile variant in front of each stall — foot-traffic-worn version of the zone palette floor, slightly lighter/warmer. Marks where people stand.
|
||||
- **Sound indicators (visual grammar §317):** High foot traffic = dense sound ping patterns at market hours.
|
||||
|
||||
**Distinction from faction commercial:** Informal economy has no signage (or handwritten signage in environmental text spec). Faction commercial has printed, standardized signage.
|
||||
|
||||
### Category 2: Settlement Indicators
|
||||
|
||||
**At-a-glance signal:** Organic overhead elements where no overhead elements should be (container gardens on z=4, non-institutional). Seating that's clearly brought from somewhere else (non-matching furniture). The zone palette floor is correct but something on z=4 is soft, plant-based, or personal.
|
||||
|
||||
**Visual vocabulary:**
|
||||
- **Container gardens:** Rectangular planter objects on z=2 (1×1 or 2×1 visual tiles), with dark soil `#0e1008` top and trailing vegetation on z=4 (`#0a1006` leaf cluster at 60% opacity). Distinctly organic among industrial/institutional surroundings.
|
||||
- **Improvised seating clusters:** Mismatched furniture objects on z=2. In a zone where all furniture is institutional (same material, same design), non-matching furniture is immediately readable. Warmer material tone than zone standard.
|
||||
- **Shrine/memorial:** Small z=2 object with accumulated small items around it (the accumulation is visual — a cluster of tiny objects with personal-scale z=4 elements above). No lighting fixture — lit by candle (tiny PointLight2D, radius 1vt, `#ffb040` very warm, dim).
|
||||
- **Overall ambient:** Warmer than zone baseline in this quarter — the accumulated human presence and personal lighting offsets the institutional zone character.
|
||||
|
||||
**Distinction from informal economy:** Settlement indicators are about residence and community, not trade. No awnings. No goods-on-display floor patterns. The warmth comes from plants and personal objects, not from commercial activity.
|
||||
|
||||
### Category 3: Economic Stress Indicators
|
||||
|
||||
**At-a-glance signal:** Lower lighting than zone baseline (fixtures removed or failed). Structural elements in worse condition (visual tile variants with damage or decay). Objects in wrong positions — cargo pushed against a wall, equipment abandoned mid-task.
|
||||
|
||||
**Visual vocabulary:**
|
||||
- **Failed/missing fixtures:** Where the zone expects a fixture, there is none (or only a stub — a mounting bracket with no lamp). The area around the gap is darker than zone baseline. This is the clearest single signal of economic stress: lights are out.
|
||||
- **Damaged floor tile variant:** Same hex values as zone floor, but with crack pattern overlay (z=1 layer, 50% opacity crack texture). The palette is correct; the *condition* is wrong.
|
||||
- **Abandoned equipment:** Objects in positions that suggest mid-task abandonment — a cargo loader parked at an angle, not docked; a door propped open with a crate; tools left on a workbench with no NPC. Object placement is irregular relative to how the zone normally functions.
|
||||
- **Temporary shelter construction:** Makeshift wall sections (z=2, non-palette materials — warm salvaged brown or neutral salvaged grey, outside normal zone material set) forming a partial enclosure within the quarter.
|
||||
- **Sparse foot-traffic floor wear:** Fewer wear marks than zone standard — fewer people use this space than its design intended.
|
||||
|
||||
**Distinction from undeveloped gap:** Economic stress has attempted use. The undeveloped gap has no attempted use — it's raw material. Stress indicators show a space that was used and is now failing.
|
||||
|
||||
### Category 4: Faction Presence Indicators
|
||||
|
||||
**At-a-glance signal:** Standardized signage (printed, institutional) where informal signage would otherwise be. Cold LED lighting regardless of zone temperature. Objects that look like they belong to a larger system — they have the same aesthetic as other faction objects elsewhere.
|
||||
|
||||
**Visual vocabulary:**
|
||||
- **Commission presence:** Cold institutional grey objects (`#b8bec4` surface material, same as gate cluster). Cold LED fixture on a mounted post (`#f2f4ff` temperature). A notice board with official announcements (environmental text in Michroma, 11px, 70% opacity, properly aligned). The kiosk/checkpoint structure is clearly manufactured, not improvised.
|
||||
- **Corporate/Syndic presence:** Branded objects — the material is still within zone palette range (corporate entities use zone-appropriate materials but with branded applications). Corporate marking appears as a subtle logo on z=4 or as branded signage. Lighting: slightly cooler and more uniform than zone standard (corporate spaces are *maintained*).
|
||||
- **Union hall / labor presence:** Notice board with text (layer 4, higher-opacity than Commission notices — these have been posted by people who want them read). Seating arranged for meeting (chairs in a deliberate cluster, not scattered). Informal but organized.
|
||||
- **Absence of faction presence (readable as absence):** A quarter where there WERE Commission markers and they've been removed — stub mount points visible on z=4, blank walls where signage was. The absence of faction presence is as readable as presence.
|
||||
|
||||
**Distinction from civic baseline:** Civic baseline is neutral, maintained, no faction signage. Faction presence is cold and standardized (Commission) or branded (corporate) or organized-informal (labor). If you see a sign, you're in faction territory.
|
||||
|
||||
---
|
||||
|
||||
## 6. Responding to OQ-3: Do Quarters Have Social Meaning?
|
||||
|
||||
Ozzie asked whether the choice of quarter fill content has downstream social consequences. The answer from a visual perspective: **yes, and the visual grammar is what makes those consequences legible.**
|
||||
|
||||
When a quarter is assigned "Settlement — Container gardens," the visual output is:
|
||||
- Container planters in a semi-private courtyard
|
||||
- Slightly warmer ambient than zone baseline
|
||||
- Non-institutional overhead elements
|
||||
|
||||
But the *social meaning* that Ozzie wants requires the visual to *communicate* something about who lives here and what kind of space this is. Here's what the visual grammar tells a player who reads it:
|
||||
|
||||
- **Container gardens in an industrial district** → people have been here long enough to invest in food independence. This is a mature community. Slow trust, deep roots.
|
||||
- **Abandoned equipment (economic stress)** → something changed. People were here, now less so. Ask why.
|
||||
- **Commission kiosk in a residential zone** → surveillance normalizing in a space it didn't previously reach. Something triggered this expansion.
|
||||
- **Informal market stalls in a previously-staged zone** → the official function of this space has been displaced by informal economy. Power is contested here.
|
||||
|
||||
These readings are available to any player — not just the investigator. The relationship-seeker reads the container gardens as "warm community, worth investing in." The trader reads the market stalls as "economic activity, possible contacts." The explorer reads the abandoned equipment as "something happened here, worth investigating."
|
||||
|
||||
The visual grammar doesn't point the way. It describes the social reality. The player applies their own lens.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
**District edge bleed:** Transitional blocks using palette interpolation, shared infrastructure that ignores district lines, light pools that span boundaries. The player feels district changes as gradual temperature shifts, not lines.
|
||||
|
||||
**Non-urban terrain:** Five natural zone palettes (farmland, wilderness, ocean/beach, mountain, secluded town) using global ambient instead of fixture pools. Natural LOS anchors (trees, rocks, terrain features) at the same 16vt max interval rule. Wilderness uses overhead layer density (canopy) to create the occlusion that walls provide in urban spaces.
|
||||
|
||||
**Anti-grid techniques:** Seven techniques. Diagonals as historical infrastructure, irregular setbacks at block faces, overhead extension past block edges, angled infrastructure as palimpsest, light territories that span blocks, vegetation overflow in planet-side settings, street width variation. The visual grammar never aligns perfectly with the block grid — it uses the grid as an invisible scaffold.
|
||||
|
||||
**Unified taxonomy:** Two-layer model — spatial type (my 5 types) × content category (Nigel's 4 + civic baseline) = 25 possible combinations, with a compatibility matrix that constrains illogical assignments. Every quarter is assigned both a type and a category.
|
||||
|
||||
**Flavor visual vocabulary:** Each of Nigel's four categories has a distinct at-a-glance signal: warm irregular lighting (informal economy), organic overhead elements (settlement), failed lighting + damage tiles (stress), cold standardized objects (faction presence).
|
||||
|
||||
**Multi-playstyle acknowledgment:** The visual grammar communicates social reality, not investigation routes. Every player reads the same space through their own lens. The grammar serves them all because it describes who inhabits a space and on whose terms — which is the information that all playstyles need.
|
||||
@@ -0,0 +1,490 @@
|
||||
# Generator Architecture Workshop — Round 3: Araminta
|
||||
## Palette Granularity, Organic Streets, Vertical Visuals, Destruction, Horizon, and What's Behind the Wall
|
||||
|
||||
**Author:** Araminta (Visual Designer)
|
||||
**Date:** 2026-02-27
|
||||
**Workshop:** Generator Architecture (Ticket #562)
|
||||
**Responding to:** Round 2 outputs (all participants), Qatux Round 2 notes, Lead Round 3 directives
|
||||
**Status:** Round 3 — convergence
|
||||
|
||||
---
|
||||
|
||||
## Opening: This Round Is About Decisions
|
||||
|
||||
Round 1 was constraints. Round 2 was extension. Round 3 is convergence. I'm going to be more prescriptive here than in previous rounds — these are my recommendations, not open explorations. Where I say "Rule:", that's a proposal for locking. Where I say "open", I'm flagging it for the room.
|
||||
|
||||
One fast note before I start: Ozzie's partial dissent on the grid (OQ-R3-A) is legitimate. My seven anti-grid techniques from Round 2 are visual camouflage, not structural change. I'll address organic/non-rectilinear districts directly in Section 2 and give her an actual answer, not a deflection.
|
||||
|
||||
---
|
||||
|
||||
## 1. Palette Granularity — The Modifier System
|
||||
|
||||
### The Problem with Six Fixed Palettes
|
||||
|
||||
The lead is right. "Industrial farming ≠ rustic farming" isn't solved by adding more base palettes. If I add a 9th base palette for every agricultural variant, I end up with dozens of fixed entries that still fail to capture the combinatorial variety Miri's cultural ingredients system produces. The correct architecture is a **modifier system** layered on a smaller base palette set.
|
||||
|
||||
The base palettes define floor, ambient, and water (the ground you stand on and the light that falls on it). The modifiers define everything humans have added to that ground. That's the right separation.
|
||||
|
||||
### The Base Terrain Palettes (Revised: 8 Types)
|
||||
|
||||
I'm expanding from 6 to 8 to cover terrain types Round 2 left underspecified:
|
||||
|
||||
| ID | Name | Floor base | Ambient | Water/reflective |
|
||||
|----|------|------------|---------|-----------------|
|
||||
| T1 | Temperate farmland | `#1a1510` dark warm brown | `#0e0c08` warm near-black | n/a |
|
||||
| T2 | Industrial/greenhouse | `#141618` grey-green dark | `#0c0e0c` flat cool | n/a |
|
||||
| T3 | Forest/wilderness | `#0e120e` organic dark | `#080a08` near-black | n/a |
|
||||
| T4 | Grassland/plains | `#141810` muted green-grey | `#0c0e08` cool-warm | n/a |
|
||||
| T5 | Coastal water | `#060c14` deep near-black blue | `#060810` cold near-black | `#c0c8d8` specular animated |
|
||||
| T6 | Beach/coastal margin | `#2a2218` warm dark tan | `#0c0a06` warm near-black | n/a |
|
||||
| T7 | Mountain/high terrain | `#181c22` dark blue-grey stone / `#c8d8e8` snow | `#10141a` cold dark | n/a |
|
||||
| T8 | Desert/arid | `#221c12` dusty warm dark | `#10100c` warm-neutral | n/a |
|
||||
|
||||
T1 and T2 are the two farmland base types — they differ at the floor and ambient level. Industrial farms (T2) have a distinctly greyer ambient because they operate under artificial light even outdoors. Rustic farms (T1) have warm organic ground.
|
||||
|
||||
This is the only place where I'm adding two entries for the same terrain category — because the lead specifically called out this distinction, and it genuinely affects the ambient regime (natural light vs. artificial) not just the structures on top.
|
||||
|
||||
### The Three Modifier Axes
|
||||
|
||||
Every non-urban terrain district gets three modifier assignments, drawn from the society profile:
|
||||
|
||||
**Modifier A: Structure Material Character** (from heritage root)
|
||||
|
||||
| Heritage root | Structure material | Surface treatment | Overhead character |
|
||||
|---------------|--------------------|-------------------|-------------------|
|
||||
| Iron | Corrugated metal, welded joints | Cold precise | Functional metal (ducts, conduits exposed) |
|
||||
| Stone | Carved stone, thick masonry | Cool solid | Low overhead, heavy permanent structures |
|
||||
| Frost | Sparse insulated panel, minimal | Cold minimal | Very sparse; exposure-resistant |
|
||||
| Vine | Timber, organic fibers, woven | Warm organic | Dense personal overhead (drying racks, planters) |
|
||||
| Tide | Weathered timber, rope, marine metal | Salt-worn neutral | Maritime: nets, moorings, tackle |
|
||||
| Dust | Rammed earth, fired clay | Warm-brown dry | Low; heat-efficient, minimal projection |
|
||||
| Salt | Preserved wood, sealed containers | Neutral functional | Practical personal (salt storage, preservation apparatus) |
|
||||
| Arc | Mixed-material, jury-rigged | Variable | Dense improvised overhead (whatever was available) |
|
||||
| Jade | Refined composite, polished | Cool refined | Deliberate aesthetic overhead (trellises, decorative structures) |
|
||||
| Spice | Vivid dyed textile over standard base | Warm + accent | Dense fabric overhead, colorful within saturation rules |
|
||||
|
||||
**Rule:** Heritage root is the primary modifier for structure material. In a two-root heritage blend, the dominant root (highest weight) determines material; the secondary root adds accent elements in the overhead layer.
|
||||
|
||||
**Modifier B: Economic Tier** (from economic function + economic pressure combination)
|
||||
|
||||
| Tier | Condition | Object density | Lighting presence |
|
||||
|------|-----------|----------------|-------------------|
|
||||
| Prosperous | Maintained, new materials | High (full budget) | Full fixtures, maintained |
|
||||
| Standard | Functional, showing age | Moderate | Fixtures present, some failed |
|
||||
| Subsistence | Worn, improvised repairs | Low | Minimal; improvised warm sources |
|
||||
| Failing | Degraded, abandoned sections | Very low | Failed fixtures; dark |
|
||||
|
||||
**Rule:** Economic tier modifies *condition* and *density*, not palette. A Stone-heritage prosperous farm and an Iron-heritage prosperous farm have different materials but similar density and maintenance. Economic tier crosses material character cleanly.
|
||||
|
||||
**Modifier C: Era** (from block era tag)
|
||||
|
||||
| Era | Material generation | Structural scale | Infrastructure visible? |
|
||||
|-----|---------------------|------------------|------------------------|
|
||||
| Era 1 | Hand-built; organic/natural construction | Human-scale, small | None visible |
|
||||
| Era 2 | Standardized; mixed natural and fabricated | Intermediate | Some surface-mounted |
|
||||
| Era 3 | Modern/industrial; fabricated, uniform | Large-scale possible | Integrated, less visible |
|
||||
|
||||
Era affects the GENERATION of structures within the chosen material character. An Iron-heritage farm that was built in Era 3 has precisely welded industrial metal structures. An Iron-heritage farm built in Era 1 has hammered metal over stone foundations. Same heritage root, different era expression.
|
||||
|
||||
### Faction Overlay (Optional, Additive)
|
||||
|
||||
Applied on top of any base palette + modifier combination:
|
||||
|
||||
| Faction | Overlay effect |
|
||||
|---------|---------------|
|
||||
| Commission | Cold LED work lights replace warm sources; institutional grey secondary structures (checkpoint posts, monitoring equipment); Michroma signage |
|
||||
| Syndic-corporate | Branded secondary structures; slightly colder, more uniform lighting than zone standard; corporate marking on z=4 |
|
||||
| Independent (labor) | Personal accumulated objects; union notice boards; warm improvised fixtures |
|
||||
| None | No overlay; pure heritage + economic tier + era |
|
||||
|
||||
### How Many Distinct Visual Feels?
|
||||
|
||||
Rough count:
|
||||
- 8 base terrain types
|
||||
- 10 heritage modifiers (functionally 6–8 meaningfully distinct groups)
|
||||
- 4 economic tiers
|
||||
- 3 eras
|
||||
- 5 faction overlays (including none)
|
||||
|
||||
**Strongly differentiated** (a player would name them differently): ~40–50. "Industrial greenhouse farm under Commission control," "subsistence Stone-heritage farmstead, old," "prosperous Tide-heritage coastal village, Era 2" — these feel like distinct places.
|
||||
|
||||
**Meaningfully distinct** (a player would perceive as different): ~200+. The granularity at which heritage blend ratios differ (a 70/30 Frost/Iron vs. 50/50) is subtle but present.
|
||||
|
||||
**The important bound:** A player going through 300 worlds encounters each combination at most a few times. The template library (D-025) remains the practical ceiling on variety, as Miri noted — but the modifier system ensures that two farmland districts with the same template read completely differently when one is a prosperous Vine-heritage settlement and the other is a failing Iron-heritage industrial operation.
|
||||
|
||||
---
|
||||
|
||||
## 2. Organic Streets and Grid Breathing
|
||||
|
||||
### Direct Answer to Ozzie's Demand
|
||||
|
||||
Ozzie: "Tell me the grid can breathe."
|
||||
|
||||
**It can. Here is what that means and what it requires visually.**
|
||||
|
||||
There are three street/district layout modes. The visual grammar needs rules for all three.
|
||||
|
||||
### Layout Mode 1: Grid Districts
|
||||
|
||||
What we've been designing until now. Perpendicular streets, regular block footprints. Institutional, industrial, corporate, station interior. The grid communicates: this was planned, authority made this.
|
||||
|
||||
Visual rules: as specified in Rounds 1 and 2. No changes.
|
||||
|
||||
### Layout Mode 2: Relaxed Grid (Breathing Grid)
|
||||
|
||||
Adjacent districts can have **different orientations** (rotated grid). A residential quarter at 15° off the main station grid reads as "built before the main plan was established, or outside its authority." The visual grammar's rules are **direction-agnostic** — corridor width minimums, LOS anchor intervals, zone palette assignments — all apply regardless of street orientation. The only additional rule needed:
|
||||
|
||||
**Grid-rotation boundary treatment:** Where two districts with different orientations share an edge, the transition strip must handle the angular discontinuity. The floor tiles in the transition strip use the "angled transition" variant (see below). Street connections between the two grids happen through **diagonal connectors** (my Round 2 Technique 1), which are now read not as historical infrastructure but as the literal connection point between two urban grids of different orientation.
|
||||
|
||||
Visual rule: the transition strip between a 0° grid and a 15° grid uses **the older era** of the two districts (as Tyre's transition block logic specifies), reinforcing the reading that one grid predates the other.
|
||||
|
||||
### Layout Mode 3: Organic Districts
|
||||
|
||||
Streets that curve. Block shapes that are L, T, or irregular polygon. This is what Ozzie is really asking for.
|
||||
|
||||
**What "organic" means in a tile-based system:**
|
||||
|
||||
The game uses a tile grid. True curves don't exist — but the *visual impression* of curves does. Organic streets are produced by a specific tile vocabulary.
|
||||
|
||||
**Organic street visual rules:**
|
||||
|
||||
1. **Curve mechanism**: Curves happen as 45° jogs in the street direction. A street that runs north for 6 tiles, then jogs northeast for 4 tiles, then returns north — from 16+ visual tiles away, this reads as a gentle curve. The jog is a visual feature, not a defect.
|
||||
|
||||
2. **Angled wall tile variants**: Buildings on organic streets need wall faces at 45° and 135°. These are specific tile variants with the same zone palette material but a diagonal face. A building that presents a 45° corner to a diagonal street reads as organic — it was built to fit the street, not placed on a grid.
|
||||
|
||||
3. **Street-width variability increases in organic districts**: In a grid district, street width might vary from 4–8 vt. In an organic district, it varies from 4–14 vt without feeling wrong. A street that opens into a piazza-width as it bends is the correct shape for an organic settlement.
|
||||
|
||||
4. **Intersection treatment for non-90° intersections:**
|
||||
- Obtuse intersection (>90°): the corner building uses a recessed setback, presenting a smooth face. The wider angle makes the building appear to "anchor" the intersection.
|
||||
- Acute intersection (<90°): the corner building has a wedge-shaped setback or a chamfered corner (45° wall face). The wedge building is a classic organic settlement marker.
|
||||
- These require "wedge corner" and "chamfered corner" floor tile variants.
|
||||
|
||||
5. **Block boundaries in organic districts are building faces, not coordinates**: The visual grammar stops using block edges as generation hints. What the player reads as a "block" is defined by the street network on three or four sides. This block might be irregular in every dimension. The generator knows the block as a data structure; the player reads it as "the cluster of buildings between these streets."
|
||||
|
||||
6. **Landmark density increase**: Without a grid, players lose orientation easily. Organic districts require **mandatory landmark placement every 12 visual tiles** (vs. 16 in grid districts). These landmarks are distinctive buildings (unusual rooftop shape, unusual material), significant trees in planet-side settings, or prominent corner objects. The navigator's landmarks replace the navigator's grid.
|
||||
|
||||
7. **LOS anchor relaxation**: Organic irregularity IS the LOS anchor. A street that bends creates a sightline break at the bend. The max 16 vt anchor interval still applies, but in organic districts, the street geometry itself contributes to anchor count. A block with three irregular protrusions needs fewer interior anchors than a perfectly rectangular block.
|
||||
|
||||
### Organic vs. Grid Visual Grammar Summary
|
||||
|
||||
The core visual grammar rules **do not change** for organic districts. Zone palettes, lighting temperature, entity hierarchy, z-layer stack — all identical. What changes is:
|
||||
|
||||
| Rule | Grid district | Organic district |
|
||||
|------|---------------|-----------------|
|
||||
| Corner tile variants | 90° only | 90°, 45°, 135°, chamfered |
|
||||
| Landmark interval | 16 vt | 12 vt |
|
||||
| Street width range | 4–8 vt | 4–14 vt |
|
||||
| Block boundary | Coordinate-aligned | Face-defined by street network |
|
||||
| LOS anchor source | Structural elements | Structural elements + street geometry |
|
||||
| Setback variation | ±3 vt from baseline | ±6 vt (wider range) |
|
||||
|
||||
The visual grammar is orientation-agnostic and curvature-extensible. This is the right answer to Ozzie.
|
||||
|
||||
---
|
||||
|
||||
## 3. Vertical Visuals — Height in 2D Top-Down
|
||||
|
||||
### The Problem
|
||||
|
||||
In top-down view, a 50-floor skyscraper and a 3-floor office building have the same roof footprint. They're the same from above unless the visual grammar does work to differentiate them.
|
||||
|
||||
### The Height Tier System
|
||||
|
||||
I propose four height tiers, each with a defined visual signature:
|
||||
|
||||
| Tier | Floors | Roof material complexity | Shadow length | Shadow hardness |
|
||||
|------|--------|--------------------------|---------------|-----------------|
|
||||
| S1 (Low-rise) | 1–3 | Simple parapet, zone material | 2–4 vt | Soft (gradient falloff) |
|
||||
| S2 (Mid-rise) | 4–10 | HVAC units, ventilation stacks visible | 5–10 vt | Medium |
|
||||
| S3 (High-rise) | 11–30 | Mechanical arrays, access structures, antenna | 12–20 vt | Hard (defined edge) |
|
||||
| S4 (Extreme) | 30+ | Minimal — antenna farm, sensor cluster, landing area | 25–40 vt | Very hard |
|
||||
|
||||
**The primary visual signal is shadow.** Shadow length scales with height. A 50-floor building casts a 30+ tile shadow. Players learn this grammar naturally — they see a long shadow and understand: something tall is nearby.
|
||||
|
||||
### Shadow Direction
|
||||
|
||||
Shadow direction is constant within a district and set at generation time. It represents the primary light source angle (the local star's position for planet-side; the orbital station's artificial sun angle for stations).
|
||||
|
||||
**Rule:** Shadow falls in one consistent direction per district. This direction is recorded in the DistrictSkeleton (as a simple angle, 0–359°). All buildings in the district cast their shadow at that angle. This creates coherent lighting across the district.
|
||||
|
||||
**Station exception:** In sealed station environments, the light strips run along the "ceiling" of the station, creating a diffuse downward illumination with no directional shadow. In station interiors, building height is communicated through **penumbra width** (ambient occlusion at the building base) rather than directional shadow. Taller station buildings have a wider soft-dark band at their ground level.
|
||||
|
||||
### Shadow Visual Treatment
|
||||
|
||||
Shadow tiles are **floor-layer overlays** (a slight darkening of the floor material beneath the shadow). They're not z=1 objects — they're a tint pass on the floor tiles in the shadow footprint.
|
||||
|
||||
| Shadow type | Visual treatment |
|
||||
|-------------|-----------------|
|
||||
| S1 soft shadow | 2–4 tile gradient fade, max opacity 25% darkening |
|
||||
| S2 medium shadow | Defined edge with 2-tile softening, max opacity 35% |
|
||||
| S3 hard shadow | 1-tile softening, max opacity 45% |
|
||||
| S4 extreme | No softening on long edge, max opacity 50% |
|
||||
|
||||
**The shadow as gameplay element:** Hiding in a tall building's shadow reduces the caster's ambient lighting, which affects the fog-reveal properties and visual detectability. This is a natural gameplay consequence of the height communication system, not an engineered feature.
|
||||
|
||||
### Rooftop Visual Vocabulary by Tier
|
||||
|
||||
The roof of a building is visible from above. It should communicate what the building IS, not just how tall it is.
|
||||
|
||||
**S1 (Low-rise):** Zone-palette roof material. A residential building has a simple flat roof or slight parapet. An industrial building has vent stacks (small z=4 objects). No structural complexity visible.
|
||||
|
||||
**S2 (Mid-rise):** HVAC clusters (irregular z=4 groupings, dark metal, 2–4 vt wide), stairwell access structures (small box on one corner), possibly a loading bay indicator if commercial. The roof is busy in a functional way.
|
||||
|
||||
**S3 (High-rise):** Complex mechanical array on z=4. Communications masts. Access platforms. If commercial: possible rooftop-level signage visible from above. If residential tower: rooftop garden elements (plant objects, seating). The roof reads as a separate zone with its own function.
|
||||
|
||||
**S4 (Extreme — skyscraper):** Sparse but distinctive. The building's footprint at this height is functional rather than comfortable. Antenna farm or sensor cluster (thin vertical structures on z=4). Possibly a landing platform (helipad equivalent). The roof is visually minimal because at this height, only essential infrastructure is maintained.
|
||||
|
||||
### Neural Insert Integration
|
||||
|
||||
In **perception mode** (insert overlay, z=6), building heights are tagged. The insert displays a small elevation indicator adjacent to buildings — a bar graph scaled to height tier. This is the only time building height is explicitly labeled; outside perception mode, the player reads height through shadow and roof complexity.
|
||||
|
||||
---
|
||||
|
||||
## 4. Destruction Visuals
|
||||
|
||||
### The Visual Grammar of Destruction
|
||||
|
||||
**Core principle:** Destruction does not create new palette colors. It corrupts the existing palette. A destroyed gate cluster area still uses gate cluster materials — just in their broken, exposed, or burned variants. This keeps destroyed areas visually coherent with their zone and prevents destruction from looking like a generic "brown rubble" overlay.
|
||||
|
||||
### Destruction Stages
|
||||
|
||||
**Stage 1 — Active (event in progress)**
|
||||
|
||||
This stage is brief — active fire/explosion. Visual markers:
|
||||
- Fire glow: `#ff6010` point lights at maximum intensity (far exceeding any zone palette fixture)
|
||||
- Smoke layer (z=5, above fog): dark grey-brown particles, animated, at 70–90% opacity in affected area
|
||||
- Structural instability indicator: flickering of any remaining fixture lights in affected area (the lighting phase-shifts, a sign of power disruption)
|
||||
|
||||
**Stage 2 — Fresh Aftermath (0–48 in-game hours)**
|
||||
|
||||
The smoke clears. The damage is visible.
|
||||
|
||||
| Visual element | Specification |
|
||||
|----------------|--------------|
|
||||
| Scorched floor | Zone floor hex value, saturation reduced 60%, brightness reduced 15%, slight red-shift (add `#0c0402` to RGB) |
|
||||
| Rubble objects | Zone wall/structure material, irregular shapes on z=2, 40% opacity — they're still there but partially blasted away |
|
||||
| Debris scatter | Small fragments (1×1 tile z=2 objects) at radial distribution from blast center |
|
||||
| Emergency barriers | Commission-grey `#787e84` temporary fencing on z=2; bright orange `#e05c20` site marking tape |
|
||||
| Emergency lighting | Small PointLight2D, `#ff9040` warm orange (emergency lanterns), at 50% normal radius |
|
||||
| Exposed infrastructure | Infrastructure layer becomes visible (see Section 6 — this is the same exposure mechanism as wall breach) |
|
||||
| Missing overhead (z=4) | Roof elements removed in blast radius — sky/ambient fully visible |
|
||||
|
||||
**Stage 3 — Stabilized**
|
||||
|
||||
48h+ after event. No active emergency. The area is safe but not repaired.
|
||||
|
||||
| Visual element | Specification |
|
||||
|----------------|--------------|
|
||||
| Cold rubble | Same rubble objects as Stage 2, now at 80% opacity (solidified) |
|
||||
| Permanent barriers | Concrete block or heavy fencing (`#4a5058`) replacing emergency barriers |
|
||||
| Dark zone | No fixture lighting in affected area — standard darkness |
|
||||
| Reconstruction markers | Site markers (`#e05c20` orange, standard shapes) — 3–5 per affected block |
|
||||
|
||||
**Stage 4 — Reconstruction**
|
||||
|
||||
Active repair in progress.
|
||||
|
||||
| Visual element | Specification |
|
||||
|----------------|--------------|
|
||||
| Construction scaffolding | Metal scaffolding on z=4, `#505458` grey, partial opacity 80% |
|
||||
| Material mix | New-era floor tiles adjacent to old-era tiles — visible seam where old and new meet |
|
||||
| Worker spawns | NPC spawn points in affected area (construction workers as NOBODY pattern) |
|
||||
| Partial roof return | z=4 elements return to chunks where repair is complete |
|
||||
|
||||
**Stage 5 — Healed Scar**
|
||||
|
||||
Reconstruction complete but history visible.
|
||||
|
||||
| Visual element | Specification |
|
||||
|----------------|--------------|
|
||||
| Era mismatch | The repaired area uses a newer era material than surroundings (same palette, visibly cleaner) |
|
||||
| Floor seam | Subtle grout/joint pattern difference at the repair boundary |
|
||||
| Memorial marker | Optional z=2 object if the event was significant — same specification as Settlement shrine |
|
||||
|
||||
### The Destruction Palette (Summarized)
|
||||
|
||||
These are the corruption values applied to any zone palette material:
|
||||
|
||||
| Element | Modification |
|
||||
|---------|-------------|
|
||||
| Scorched floor | Desaturate 60%, darken 15%, add `#0c0402` red-tint |
|
||||
| Charred structure | Base material, opacity 40–80% (varies by blast proximity) |
|
||||
| Fire glow | `#ff6010` high intensity — NOT zone palette, always the same |
|
||||
| Exposed infrastructure — power | `#c8b840` yellow-gold (standardized regardless of zone) |
|
||||
| Exposed infrastructure — water/coolant | `#4888c8` mid blue |
|
||||
| Exposed infrastructure — data/comm | `#b8b8b8` light grey, thin |
|
||||
| Exposed structure core (rebar/beam) | `#3a3e42` dark metal |
|
||||
| Open sky/void (where roof removed) | `#c8d8f0` sky ambient at 100% — deliberately bright |
|
||||
|
||||
**The open sky tile** deserves special attention. It's the only floor-layer element in the game that glows brighter than the surrounding ambient (other than snow terrain). A destroyed building with its roof removed shows a bright sky-colored floor where the ceiling was. This is visually striking and communicates "open to sky" instantly. It's also a gameplay cue: line-of-sight changes dramatically in open-roofed areas.
|
||||
|
||||
### Gas Explosion Specifically
|
||||
|
||||
The lead's example: a gas explosion destroys part of a district.
|
||||
|
||||
Gas explosions are hot, fast, and clean — no lingering fire. Visual signature:
|
||||
1. Circular scorch pattern on floor tiles, centered on explosion point
|
||||
2. Radial debris distribution (rubble objects scattered at 45°, 90°, 135°, etc. intervals for regularity)
|
||||
3. Structural deformation: wall stub objects at irregular heights at the blast boundary
|
||||
4. Exposed infrastructure: any walls within blast radius expose their infrastructure layer
|
||||
5. Cleared zone: the explosion center is OPEN — no furniture, no objects, debris pushed outward not piled at center
|
||||
|
||||
---
|
||||
|
||||
## 5. Horizon as Landmark (OQ-R3-E)
|
||||
|
||||
### The Answer: Both Palette AND Landmark Reservation
|
||||
|
||||
The ocean zone palette handles how the water looks and feels to be near. The landmark reservation system handles whether the discovery moment is guaranteed.
|
||||
|
||||
**Rule: Coastal districts must include a "horizon view" landmark reservation** in the DistrictSkeleton. This is a mandatory constraint: one block on the coastal edge of the district must have an unobstructed view corridor of minimum 8 visual tiles from the street to the water.
|
||||
|
||||
The landmark reservation is not a structure. It is **negative space** — an instruction to the generator that no building, tree, or z=4 element may be placed in a defined corridor oriented toward the water. The view must exist.
|
||||
|
||||
### Why This Can't Be Left to the Palette
|
||||
|
||||
Without an explicit reservation, the generator could place a warehouse right at the water's edge. The ocean palette would still be present beneath the warehouse floor. The player would walk through dock infrastructure, never see the water, and miss the moment entirely.
|
||||
|
||||
The reservation guarantees the VIEW. The palette guarantees the FEELING when the view arrives.
|
||||
|
||||
### The Visual Moment — Step by Step
|
||||
|
||||
As the player moves from urban interior toward a coastal edge:
|
||||
|
||||
**Distance 24+ vt from waterfront (still in district interior):**
|
||||
Normal zone palette. Warm amber or institutional grey. Standard ceiling height (z=4 overhead present).
|
||||
|
||||
**Distance 16–24 vt (transitional block begins):**
|
||||
Transitional floor palette: zone floor gradually shifts toward coastal neutral. Lighting temperature begins to cool. The sound design (Inigo's domain) changes here — urban noise begins to yield. Buildings begin to lower (S1 height tier at transitional zone).
|
||||
|
||||
**Distance 8–16 vt (coastal margin begins):**
|
||||
T6 beach palette or dock palette begins. Timber, weathered material. The overhead layer (z=4) starts to thin. Dock structures, low bollards, the hardware of the water interface. Glimpses of water visible in gaps between structures.
|
||||
|
||||
**Distance 0–8 vt (the view corridor):**
|
||||
The overhead layer *opens*. Buildings stop. The z=4 layer is empty ahead. Full ambient sky exposure (if planet-side), or the station's curved hull visible overhead (if orbital coastal equivalent exists).
|
||||
|
||||
**The moment:**
|
||||
- LOS extends to 20+ visual tiles (limited only by fog shader)
|
||||
- T5 coastal water floor tiles begin
|
||||
- The animated specular reflection layer (`#c0c8d8` at 20% opacity) starts
|
||||
- The ambient becomes cold deep blue
|
||||
- No walls or overhead in the view direction
|
||||
- A low z=2 element marks the spot: a railing, a bench, a bollard — not much, but enough to say "people come here to look"
|
||||
|
||||
**What makes it hit:** The combination of LOS extension (the player's vision suddenly triples in the water direction) and ambient inversion (warmth to cold, enclosed to open) creates a sensory discontinuity. The player has been navigating by local landmarks and wall proximity. Suddenly neither applies. The rules of navigation change.
|
||||
|
||||
**Station-interior equivalent (if applicable):** A station's "observation window" looking onto space works the same way. The overhead opens, the ambient goes deep black/star-field, and LOS extends to the window face. The landmark reservation mechanism is identical — just the palette differs.
|
||||
|
||||
---
|
||||
|
||||
## 6. What's Behind the Wall
|
||||
|
||||
### Three Cases, Three Visual Grammars
|
||||
|
||||
When a player breaches a wall, one of three spatial conditions exists on the other side. The visual grammar needs to handle all three clearly.
|
||||
|
||||
**Case 1: Adjacent Occupied Space (another room)**
|
||||
|
||||
The most common case. The breach reveals the floor and contents of the adjacent room.
|
||||
|
||||
Visual grammar:
|
||||
- Breach indicator: a **ragged wall edge** tile variant — same zone material as the wall, but with a torn/blasted face. The opening is shown as a gap in the wall tile at the breach location.
|
||||
- Debris pile: rubble objects (z=2, same material as wall) placed within 1–2 tiles of breach on both sides
|
||||
- Revealed floor: z=1 floor tiles of the adjacent space become visible through the opening (they were there all along, obscured by the wall's tile width)
|
||||
- LOS extension: the player's sightline now passes through the breach at reduced cone width (the opening is narrower than a door)
|
||||
- Objects visible: any furniture or objects in the adjacent space become visible if within the narrowed LOS cone
|
||||
|
||||
**Case 2: Interior Cavity (wall contains infrastructure)**
|
||||
|
||||
Large buildings (4+ visual tiles wide as structural dimension) have internal wall cavities. A breach into a cavity reveals the building's "nervous system."
|
||||
|
||||
This is the most visually interesting case.
|
||||
|
||||
Visual grammar:
|
||||
- The cavity is 1–2 tiles wide (enough to be visible through the breach, not enough to enter)
|
||||
- Infrastructure layer visible: **color-coded conduits and pipes** at z=1.5 (between floor and furniture layers in the z-stack):
|
||||
|
||||
| Infrastructure type | Color | Width |
|
||||
|---------------------|-------|-------|
|
||||
| Power conduit | `#c8b840` yellow-gold | 1 tile |
|
||||
| Water/coolant pipe | `#4888c8` mid blue | 1–2 tiles |
|
||||
| Data/comm line | `#b8b8b8` light grey | 0.5 tile (thin) |
|
||||
| Structural beam | `#3a3e42` dark metal | 2–3 tiles |
|
||||
| Ventilation | `#585e60` dark grey, wider | 2–4 tiles |
|
||||
|
||||
- Structural material cross-section visible: the interior face of the wall shows its core material (darker than the face material; `#181c20` dark stone or `#20242a` dark composite)
|
||||
- Era indicates infrastructure density:
|
||||
- Era 1: minimal (power only, stone structure)
|
||||
- Era 2: mixed (power + water + comm lines)
|
||||
- Era 3: full bundle (all infrastructure types, more densely bundled)
|
||||
|
||||
**Case 3: Building Perimeter Breach (exterior wall)**
|
||||
|
||||
The player has breached from inside a building to outside, or vice versa.
|
||||
|
||||
Visual grammar:
|
||||
- The outside space becomes visible through the breach (street, alley, exterior zone)
|
||||
- The exterior face of the wall was the visible face; the breach now shows the building's interior face (different material tone — slightly warmer/lighter for interior finishing versus exterior facing)
|
||||
- A **floor underwall strip**: a 1-tile-wide strip of floor tile that was hidden by the wall's footprint becomes visible. This strip often contains pushed-against objects: crates, gear, things stored against the wall. If the building has hidden objects near that wall, they're now partially revealed.
|
||||
- If something was being deliberately hidden against this wall, the breach may expose it visually before the player has crossed the threshold
|
||||
|
||||
### The Wall Infrastructure Layer — A Generator Rule
|
||||
|
||||
**Rule:** Every building with a structural footprint ≥4 vt in any dimension has a wall infrastructure layer generated at block planning time. This layer is:
|
||||
- Invisible during normal gameplay (hidden by wall tile rendering)
|
||||
- Visible when the wall tile is breached (z=1.5 reveal)
|
||||
- Consistent with the building's era tag (controls which infrastructure types are present)
|
||||
- Consistent with the zone (a residential building has water and power; a data center has redundant comm lines)
|
||||
|
||||
The infrastructure layer is pre-generated but not pre-rendered. It exists in the ChunkData but only draws when the corresponding wall tile is in a "breached" state. Generation cost is trivial (it's a pattern draw, not procedural generation).
|
||||
|
||||
### The Visual Grammar Principle: Walls Are Not Void
|
||||
|
||||
The key design principle behind this section: **walls are not empty.** They have thickness, content, and history. When a player breaches a wall, they don't find nothing. They find one of three things: another room, the building's infrastructure, or the outside. Any of those is a discovery.
|
||||
|
||||
The visual grammar should make that discovery feel earned — the ragged edge, the revealed pipes, the sudden view of the street or the next room. A breach is a spatial event. It changes what the player can see and where they can go.
|
||||
|
||||
This connects to Ozzie's "what I need is a place I'm not supposed to be." The place you're not supposed to be is not always a special room. Sometimes it's the space inside the wall. The infrastructure cavity. The under-floor route. The generator produces these spaces naturally as a consequence of how buildings are built, not as marked secrets.
|
||||
|
||||
---
|
||||
|
||||
## 7. Additional: OQ-R3-A — Can the Grid Breathe?
|
||||
|
||||
I addressed organic streets in Section 2, but I want to give Tyre a concrete visual grammar answer for what needs to change in the data structures to support grid rotation.
|
||||
|
||||
The visual grammar is already orientation-agnostic. Every rule I've written specifies distances and relationships (16 vt LOS interval, 4 vt minimum corridor width, 2-tile softening on shadows) rather than absolute directions. Rotating a grid district by 15° and applying the same rules produces a valid, coherent space.
|
||||
|
||||
What the visual grammar requires from Tyre's data structures:
|
||||
1. A `grid_orientation: f32` field on `DistrictSkeleton` (angle in degrees, 0 = standard N/S/E/W alignment)
|
||||
2. That angle propagates to block and chunk generation as a rotation parameter for template stamping
|
||||
3. The transition strip between two differently-oriented grids uses diagonal connector tile vocabulary (defined in my Round 2 Technique 1) at the rotation seam
|
||||
|
||||
There is one additional visual rule needed for multi-orientation districts:
|
||||
|
||||
**Rule:** At the boundary between two districts with different grid orientations, the transition strip must contain at least one **angular landmark** — a building or structure that reads as occupying the angular seam. This is typically a triangular or trapezoidal building footprint placed at the angular intersection. It communicates "this is where the two grids meet" through shape rather than explicit labeling.
|
||||
|
||||
The diagonal connector palette (maintenance corridor neutral `#181818`) applies to these angular landmarks regardless of zone, reinforcing their reading as "infrastructure that navigates between two spatial systems."
|
||||
|
||||
**My recommendation for Tyre:** `grid_orientation` is a simple f32 on DistrictSkeleton. Template stamping with a rotation matrix is standard geometry. This is lower implementation complexity than most of what's been proposed. Ozzie should get her grid-breathing answer in Round 3 rather than deferred.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
**Palette granularity:** The modifier system (3 axes: heritage root → material character, economic tier → condition/density, era → material generation) layered on 8 base terrain types produces 40–50 strongly differentiated visual feels and 200+ meaningfully distinct combinations. Industrial farming and rustic farming differ at the base palette level (T1 vs. T2 for ambient regime) AND at the heritage/economic modifiers. The modifier system is the correct architecture — not more fixed palettes.
|
||||
|
||||
**Organic streets / grid breathing:** The visual grammar is orientation-agnostic. Organic districts require: 45° and angled wall tile variants, higher landmark density (12 vt vs. 16 vt interval), wider street width range (4–14 vt), and face-defined blocks. Grid rotation requires `grid_orientation` on DistrictSkeleton and angular landmarks at rotation seams. Ozzie's demand is satisfiable without new visual grammar rules — just additional tile variants and a data structure field.
|
||||
|
||||
**Vertical visuals:** Four height tiers (S1–S4). Primary signal is shadow length (2–40 vt), which scales with height and creates a natural gameplay shadow system. Rooftop material complexity increases with height. In station interiors, penumbra width replaces directional shadow. Neural insert perception mode displays explicit height tags.
|
||||
|
||||
**Destruction:** Corruption-based palette system — no new colors, existing materials in broken/scorched/exposed states. Five destruction stages from active fire to healed scar. The open-sky tile (bright `#c8d8f0` at 100%) is the visual flag for "roof removed." Infrastructure exposure uses standardized color codes that apply regardless of zone, making piping and conduits identifiable anywhere in the game.
|
||||
|
||||
**Horizon as landmark:** Both palette and explicit landmark reservation required. The coastal district DistrictSkeleton must include a mandatory negative-space view corridor (8+ vt unobstructed) at the waterfront. The discovery moment is produced by the combination of LOS extension, animated specular reflection, ambient inversion (warm → cold), and the absence of overhead obstruction.
|
||||
|
||||
**What's behind the wall:** Three cases — adjacent room (floor and contents visible), infrastructure cavity (color-coded pipes and conduits at z=1.5), exterior breach (outside revealed, floor underwall strip exposed). The wall infrastructure layer is generated at block planning time, invisible until breach, consistent with building era. Walls are not void — they're discoveries waiting to be opened.
|
||||
|
||||
**OQ-R3-A addendum:** `grid_orientation: f32` on DistrictSkeleton, angular landmarks at rotation seams. This is buildable. Recommend locking it in Round 3.
|
||||
|
||||
---
|
||||
|
||||
*Araminta — Round 3 complete. Standing by for convergence decisions.*
|
||||
@@ -0,0 +1,431 @@
|
||||
# Generator Architecture Workshop — Round 4: Araminta
|
||||
## Heritage Grammar Authoring, Vessel Visual Grammar, Rooftop Bar Clause, D-Record Sign-off
|
||||
|
||||
**Author:** Araminta (Visual Designer)
|
||||
**Date:** 2026-02-27
|
||||
**Workshop:** Generator Architecture (Ticket #562)
|
||||
**Responding to:** Round 3 notes (Qatux), OQ-R4-D, vessel architecture, lead directives
|
||||
**Status:** Round 4 — final convergence
|
||||
|
||||
---
|
||||
|
||||
## Opening: Four Items, All Closeable
|
||||
|
||||
This is my shortest round by design. Three of my four assignments are new specification work; the fourth is a review pass. I'm not going to repeat the grammar I established in Rounds 1–3. I'll reference it and move forward.
|
||||
|
||||
---
|
||||
|
||||
## 1. OQ-R4-D: Heritage Grammar Overlay — Authoring Workflow and Runtime Pipeline
|
||||
|
||||
### The Core Question
|
||||
|
||||
Miri asks: per-heritage modifier objects that chunk fill applies, or lookup tables within terrain palette assets?
|
||||
|
||||
**Neither exclusively. The right answer is data-driven modifier objects — structured like per-heritage objects (typed, blendable) but stored as content files (TOML/YAML), not hardcoded in the palette assets or the code.**
|
||||
|
||||
Here's why each pure option fails:
|
||||
- **Lookup tables in palette assets**: Heritage grammar gets duplicated across every terrain type that uses it. A Vine heritage modifier rule gets written once for farmland, again for wilderness, again for coastal, again for urban. Inconsistency accumulates. Updating "all Vine farms" means touching every terrain palette.
|
||||
- **Hardcoded per-heritage modifier objects**: Changing a modifier or adding a new heritage variant requires a code change and rebuild.
|
||||
|
||||
The hybrid: `HeritageModifier` structs defined in TOML/YAML content files, loaded at startup, blended at chunk fill time.
|
||||
|
||||
### The Data Structures
|
||||
|
||||
**Content file (TOML — designer-authored, one file per heritage root):**
|
||||
|
||||
```toml
|
||||
# content/heritage/vine.toml
|
||||
[heritage_modifier]
|
||||
root = "Vine"
|
||||
applicable_terrain = ["T1_farmland", "T2_industrial_farm", "T3_wilderness",
|
||||
"T4_grassland", "T6_beach", "T8_desert", "Urban", "Orbital"]
|
||||
# Modifiers below are overrides/additions to the base terrain palette defaults.
|
||||
|
||||
[floor]
|
||||
variant_preference = ["worn_path", "mossy_edge", "pressed_earth"]
|
||||
# "worn_path" is a floor tile variant in the terrain asset library
|
||||
|
||||
[objects]
|
||||
object_set = "vine_heritage_outdoor"
|
||||
# Identifies a named set in the object asset library.
|
||||
# The object set contains: trellises, planters, outdoor seating clusters,
|
||||
# seasonal decoration markers, communal fire infrastructure, door frame plants.
|
||||
arrangement = "organic_cluster"
|
||||
# "organic_cluster" is an arrangement algorithm identifier, not hardcoded.
|
||||
# Valid values: grid, organic_cluster, edge_accent, radial, scattered
|
||||
|
||||
[overhead]
|
||||
density_factor = 0.65 # 0.0-1.0 relative to terrain type's max overhead budget
|
||||
character = "personal_organic"
|
||||
# Valid values: institutional, personal_organic, personal_functional, seasonal, sparse, none
|
||||
|
||||
[gathering]
|
||||
space_probability = 0.40 # chance of a gathering space in any outdoor quarter
|
||||
|
||||
[lighting]
|
||||
temperature_adjustment_k = 800 # Kelvin added to zone baseline (positive = warmer)
|
||||
fixture_character = "personal" # personal | functional | institutional | absent
|
||||
|
||||
[boundaries]
|
||||
fence_type = "trellis_wood" # references fence asset set
|
||||
boundary_height = "low" # low | medium | high | wall
|
||||
|
||||
[social]
|
||||
# How this heritage root modifies the social texture visible in the space
|
||||
exterior_welcome_signal = true # buildings present welcoming elements toward the street
|
||||
privacy_orientation = "outward" # outward | inward | neutral
|
||||
accumulation_character = "warm_organic" # warm_organic | functional | austere | ordered
|
||||
```
|
||||
|
||||
A designer writes this file. No code changes for new heritage variants or adjustments.
|
||||
|
||||
**The full 10-root modifier table, summarized as authoring targets:**
|
||||
|
||||
| Root | Object set | Arrangement | Overhead character | Temp adj. (K) | Gathering prob. | Boundary | Exterior signal |
|
||||
|------|-----------|-------------|-------------------|--------------|----------------|----------|----------------|
|
||||
| Frost | `frost_heritage` | `grid` | `sparse` | -600 | 0.10 | `low_wire` | false |
|
||||
| Vine | `vine_heritage` | `organic_cluster` | `personal_organic` | +800 | 0.40 | `trellis_wood` | true |
|
||||
| Stone | `stone_heritage` | `edge_accent` | `personal_functional` | 0 | 0.25 | `permanent_stone` | false |
|
||||
| Tide | `tide_heritage` | `radial` | `seasonal` | +200 | 0.55 | `low_open` | true |
|
||||
| Iron | `iron_heritage` | `grid` | `institutional` | -200 | 0.30 | `shared_infra` | false |
|
||||
| Dust | `dust_heritage` | `scattered` | `functional` | 0 | 0.20 | `weatherproof` | false |
|
||||
| Spice | `spice_heritage` | `zone_divided` | `personal_organic` | +400 | 0.25 | `medium_defined` | true |
|
||||
| Salt | `salt_heritage` | `grid` | `sparse` | -100 | 0.15 | `functional` | false |
|
||||
| Arc | `arc_heritage` | `grid` | `functional` | -100 | 0.30 | `labeled_markers` | false |
|
||||
| Jade | `jade_heritage` | `edge_accent` | `personal_organic` | +100 | 0.20 | `refined_low` | true |
|
||||
|
||||
**Arrangement algorithm summary:**
|
||||
- `grid`: Evenly spaced, parallel orientations. Objects align to grid.
|
||||
- `organic_cluster`: Grouped irregular spacing, varied orientations. Objects face each other.
|
||||
- `edge_accent`: Objects placed at spatial boundaries (building edges, path margins, corners).
|
||||
- `radial`: Objects arranged relative to a central gathering point.
|
||||
- `scattered`: Low-correlation positions, minimal clustering.
|
||||
- `zone_divided`: Objects define distinct spatial sub-zones within the quarter.
|
||||
|
||||
### Runtime Pipeline — What Chunk Fill Looks Up
|
||||
|
||||
```
|
||||
Chunk fill receives:
|
||||
ChunkFillSpec {
|
||||
zone_id,
|
||||
era,
|
||||
chunk_seed,
|
||||
society_profile: SocietyProfileRef ← includes heritage blend
|
||||
}
|
||||
|
||||
Step 1: Load base terrain palette
|
||||
palette = load_base_palette(zone_id.terrain_type)
|
||||
|
||||
Step 2: Blend heritage modifiers
|
||||
For each (root, weight) in society_profile.heritage.roots:
|
||||
modifier = load_heritage_modifier(root)
|
||||
blended = blend_modifiers(modifiers_with_weights)
|
||||
// Blending rules:
|
||||
// Continuous values (temperature_adjustment_k, density_factor, gathering_probability):
|
||||
// weighted average
|
||||
// Discrete values (object_set, arrangement, fence_type):
|
||||
// weighted probabilistic selection (dominant root wins most of the time)
|
||||
// Boolean values (exterior_welcome_signal):
|
||||
// weighted probability (60% Frost / 40% Vine: 40% chance of welcome signal)
|
||||
|
||||
Step 3: Apply blended modifier to palette
|
||||
working_palette = apply_modifier(palette, blended)
|
||||
|
||||
Step 4: Fill quarter using working_palette + era + chunk_seed
|
||||
(existing fill logic — place floor tiles, objects, overhead elements, lighting)
|
||||
```
|
||||
|
||||
**Blend example: 60% Frost / 40% Vine farmland**
|
||||
- `temperature_adjustment_k`: (0.6 × -600) + (0.4 × +800) = -360 + 320 = -40K (barely cooler than baseline — the two largely cancel)
|
||||
- `density_factor`: (0.6 × sparse_default) + (0.4 × 0.65) = moderate overhead
|
||||
- `arrangement`: Frost wins probabilistically (60%). Grid arrangement, but some organic cluster elements from Vine's 40% share appear in the overhead layer.
|
||||
- `exterior_welcome_signal`: 40% chance — the farm presents a slightly inviting exterior, but the Frost efficiency still dominates the floor plan.
|
||||
|
||||
**The output is a farm that's functional and ordered (Frost dominant) but with a few organic touches — a trellis here, an informal seating corner there — that tell you Vine heritage is also present.**
|
||||
|
||||
### What an Artist/Designer Authors
|
||||
|
||||
Three asset types feed the heritage modifier system:
|
||||
|
||||
**1. Object sets** (artist-authored, tagged by heritage root)
|
||||
An object set is a named collection of placeable objects in the asset library. The artist creates objects appropriate to each heritage root's aesthetic and tags them. Adding new Vine heritage objects to the base game means adding them to the `vine_heritage_outdoor` object set — no modifier file change needed.
|
||||
|
||||
**2. Heritage modifier files** (designer-authored TOML, one per root)
|
||||
The ten files described above. A designer can adjust behavior by editing these files. No code changes. If a heritage modifier is added (future expansion), one new TOML file is all that's needed.
|
||||
|
||||
**3. Terrain palette base files** (artist-authored, one per terrain type)
|
||||
The base terrain palette with default object density, lighting, and floor tiles. The heritage modifier overrides these defaults — anything not overridden uses the terrain palette default. This means a terrain type only needs to specify its own defaults; heritage grammar is applied on top.
|
||||
|
||||
### The One Design Rule That Must Be Stated Explicitly
|
||||
|
||||
**Rule:** The heritage modifier is applied at chunk fill time (Phase 2), not at district skeleton time (Phase 1). The DistrictSkeleton carries `society_profile: SocietyProfileRef`. Phase 2 chunk fill reads the heritage blend from the profile and applies the modifier. This means the heritage grammar is visible in the tiles but never stored as a structural generator decision — it's a visual expression, not a spatial constraint.
|
||||
|
||||
**Exception:** `gathering_probability` from the heritage modifier can influence Phase 1 quarter pre-assignment (whether a quarter is pre-assigned as "outdoor gathering space"). If so, the heritage modifier must be partially evaluated at block planning time for that specific parameter. All other modifier parameters apply at Phase 2 only.
|
||||
|
||||
---
|
||||
|
||||
## 2. Vessel Visual Grammar
|
||||
|
||||
### The Answer: Modifiers, Not New Base Palettes
|
||||
|
||||
Vessels use existing zone palettes. What distinguishes a vessel visually is not a different material vocabulary — it's a different **spatial grammar**. The material inside a luxury cabin is the same amber-warm bar palette. The material inside a cargo hold is the same maintenance-grey. What's different is the envelope, the proportion, and the bounded-environment signals.
|
||||
|
||||
**Rule: vessels are existing-palette spaces with five additional visual grammar rules.**
|
||||
|
||||
### The Five Vessel Visual Grammar Rules
|
||||
|
||||
**Rule V-1: Exterior hull is vessel-identity material, not zone palette.**
|
||||
|
||||
The outer hull/skin of any vessel uses a specific material that identifies the vessel as a vessel:
|
||||
- Spacecraft: `#2a2e32` (dark cold metal, Era-appropriate surface texture — Era 1 = riveted plate, Era 2 = welded panels, Era 3 = smooth composite)
|
||||
- Trains: livery color applied to the exterior — muted version of the operating company's identity color, within saturation rules
|
||||
- Ships/boats: `#2a2820` (weathered dark hull, salt-worn)
|
||||
|
||||
The exterior hull material applies only to the outermost layer visible from outside. Interior spaces use zone palettes normally.
|
||||
|
||||
**Rule V-2: Window tiles provide exterior context.**
|
||||
|
||||
Where a vessel has windows (train windows, porthole, cockpit view), the window tile is a special element:
|
||||
- On the floor layer, the window gap shows a z=0 background buffer — a scrolling or static exterior visual
|
||||
- In transit: the exterior buffer shows appropriate passing environment (stars, landscape, water)
|
||||
- Docked: the exterior buffer shows the dock environment (warehouse wall, station hull)
|
||||
- The window frame is vessel-hull material, the opening is the contextual reveal
|
||||
|
||||
**Rule V-3: Vessel spaces use a compression modifier.**
|
||||
|
||||
The same zone palette, but proportionally tighter:
|
||||
- Overhead height budget reduced by 30% (same z=4 elements, but lower effective ceiling)
|
||||
- Object density increased within the same floor area (the space is used intensively)
|
||||
- Corridor minimums still apply (V-05 rules), but vessel corridors bias toward minimum width
|
||||
|
||||
This compression modifier communicates "bounded mobile environment" without requiring new palettes.
|
||||
|
||||
**Rule V-4: Section transitions use vessel-identity threshold elements.**
|
||||
|
||||
Where one vessel section (train car, ship compartment) connects to another, the threshold is:
|
||||
- Door frame in vessel-hull material (not zone palette)
|
||||
- A visible width reduction at the threshold (the door opening is narrower than the corridor)
|
||||
- The threshold material is constant across the vessel — it marks every internal boundary
|
||||
|
||||
This makes internal navigation feel like moving through a vessel, not a building.
|
||||
|
||||
**Rule V-5: Class stratification is expressed through proportion, not palette.**
|
||||
|
||||
In a passenger vessel with multiple service classes:
|
||||
- First class: higher overhead clearance (+20% overhead budget), wider aisles (+2 vt), warmer lighting temperature (+400K)
|
||||
- Standard class: base compression modifier
|
||||
- Economy/crew: maximum compression (-10% further from standard), colder lighting (-200K)
|
||||
|
||||
Same palette. Different proportions. A player who knows the grammar can read service class instantly from spatial feel.
|
||||
|
||||
### Vessel-Specific Surface Cases
|
||||
|
||||
**Train cars (BoundedLinear):** Each car is a short, rectangular interior space. The key visual grammar element is the **visible car sequence** — the window at each car end shows the next car, creating a visual depth cue (you can see through multiple cars from the right position). This is implemented as a window tile facing the coupling direction showing the next car's interior.
|
||||
|
||||
**Spaceship corridors (InterSystem):** No exterior context visible during transit — black void or star-field through windows. Artificial lighting dominant (no ambient from outside). Institutional palette for working spaces; residential palette for crew quarters. The compression modifier is strongest here — corridors are minimal-width, spaces are used entirely.
|
||||
|
||||
**Ship cabins (BoundedMaritime):** Port-side windows show harbor environment when docked; ocean/sky when at sea. The marine weathering texture (visible on hull material) is the primary "you're on a ship" signal. The rocking motion (client-side animation) is Inigo's domain, not mine.
|
||||
|
||||
---
|
||||
|
||||
## 3. Rooftop Bar Clause — Public vs. Restricted Rooftop Visual Grammar
|
||||
|
||||
### The Tension and Its Resolution
|
||||
|
||||
Gestalt's guarantee: every tall structure (z_band_count ≥ 3) must have a roof zone classified `Insider` or `BreachOnly` accessible by non-obvious route.
|
||||
|
||||
The lead wants rooftop bars: public social destinations on tall buildings.
|
||||
|
||||
**These are not in conflict if we amend the guarantee correctly.**
|
||||
|
||||
**Amended guarantee:** Every tall structure must have a roof zone that constitutes a *discovery* — something worth reaching the top for. That discovery can be:
|
||||
- **A public destination** (rooftop bar, garden, observation deck) — accessed via obvious route, classified `Public` or `Semi-Public`
|
||||
- **A restricted discovery** (operational rooftop, private access) — accessed via non-obvious route, classified `Insider` or `BreachOnly`
|
||||
|
||||
Both satisfy the intent: the top of the building is not just mechanical infrastructure. The access tier varies; the discovery does not.
|
||||
|
||||
**Structural rule:** A building can have both. A skyscraper with a public rooftop bar at z_band top AND a restricted antenna/comms level above it satisfies both playstyle needs. The rooftop bar is the destination for social/tycoon/investigation players. The above-the-bar maintenance level is the discovery for the breach/assassin player.
|
||||
|
||||
### Rooftop Bar Visual Grammar (S3 and S4 Height Tiers)
|
||||
|
||||
A rooftop bar at S3 (11-30 floors) or S4 (30+) is visible from above and must communicate "social destination, open to arrival."
|
||||
|
||||
**Floor material:** Warm pavers or composite decking — lighter and warmer than the industrial-default rooftop. Not the zone palette floor — this is a curated outdoor surface. Hex: `#2a2018` (warm dark slate/composite), visually distinct from the `#181c22` cold building roof tiles.
|
||||
|
||||
**Perimeter barrier (z=2):** A designed railing or low wall around the outdoor area — thin (1-tile), warm material (matching the bar zone palette's furniture material). The barrier communicates "this is a social edge, not a fall hazard." Visually distinguishable from the functional parapet of an institutional rooftop by material and continuity (it's a designed feature, not a structural necessity).
|
||||
|
||||
**Seating clusters (z=2):** Small furniture objects — tables and chairs at human scale. At S3/S4 heights, these are small enough that from the ground-level view they're just warm texture. From the adjacent building observation deck or elevator approach, they're readable as social furniture. High-value visual cue: the seat arrangement creates clusters (2-4 chairs around a table), not rows.
|
||||
|
||||
**Service structure (z=2):** A bar counter, or a small pavilion structure housing the service area. This is the anchor of the rooftop social space — the visible sign that this was designed to serve people, not just stand on.
|
||||
|
||||
**Lighting signature (z=4):** Warm pendant fixtures or string lights — the most visually distinctive element. Temperature `#f0b840` (amber, the bar zone palette) with 80% radius of a ground-floor bar fixture. From a nearby elevated position (adjacent building, observation floor), this warm lighting cluster at height is readable as "social gathering above."
|
||||
|
||||
**Access indicator:** A visible stairhouse or elevator shaft entrance at z=2/4 — not hidden, not service-hatch scale. The access is designed as part of the social space, not an afterthought.
|
||||
|
||||
### Restricted Rooftop Visual Grammar (Contrast)
|
||||
|
||||
The restricted rooftop must read as *not-welcome* at a glance:
|
||||
|
||||
**Floor material:** Zone-standard cold industrial roof tile (`#181c22` blue-grey). No warm deviation.
|
||||
|
||||
**Perimeter barrier (z=2):** Functional parapet — same material as building structure, no warmth, no design intent beyond preventing falls. Or absent (exposed edge with safety mesh).
|
||||
|
||||
**z=2 objects:** Mechanical equipment (HVAC clusters, antenna bases, sensor arrays, junction boxes). These objects face away from a human observer — they're not oriented to be seen, they're oriented to function.
|
||||
|
||||
**Lighting (z=4):** Cold work lights only, if present — or absent. Temperature `#c0d0e0` (cold), directed down. No ambient warmth.
|
||||
|
||||
**Access indicator:** Service hatch, maintenance door — small, flush with the floor, visually minimized. Or a locked stairway access door marked with institutional signage.
|
||||
|
||||
### The Visual Grammar Test
|
||||
|
||||
A player approaching a tall building from the street should be able to read, from the roof's visible lighting signature at night:
|
||||
- **Warm amber cluster, designed railing visible** = rooftop bar / social destination
|
||||
- **Cold/dark, mechanical silhouette** = restricted / breach route
|
||||
|
||||
At S4 heights, the warm glow of a rooftop bar is visible from 12+ tiles away as a warm point-light cluster elevated against the dark building mass. That visual signal is navigation — a player who wants a social destination looks for the warm light at height.
|
||||
|
||||
---
|
||||
|
||||
## 4. Final Visual Sign-off — 12 D-Ready Items
|
||||
|
||||
Reading through each item and flagging wording, additions, or changes needed before the D-record is written.
|
||||
|
||||
---
|
||||
|
||||
**D-READY-1: DistrictLayoutMode — Grid and Organic Support**
|
||||
|
||||
✓ Correctly captured. Visual grammar confirmed: 45° wall variants, 12 vt landmark interval, 4–14 vt street width range, face-defined blocks.
|
||||
|
||||
**Wording flag:** The D-record must state the 45° rotation cap as a **hard technical constraint**, not a design preference. Language: "Maximum block rotation is ±45° from district grid orientation. This limit is non-negotiable — beyond 45°, tile-based pathfinding produces unacceptable movement artifacts. Organic districts produce the visual impression of curved streets through angular jogs, not smooth curves."
|
||||
|
||||
---
|
||||
|
||||
**D-READY-2: Guarantee Tier System — Universal / Full-Only / Conditional**
|
||||
|
||||
✓ Visual grammar correctly captured. The horizon view corridor is confirmed as a Tier 2 guarantee for coastal districts.
|
||||
|
||||
**Wording addition needed:** Add the rooftop destination clause (Section 3 above) as a Tier 2 guarantee: "Every tall structure (z_band_count ≥ 3) must contain a roof zone that constitutes a discovery — either a public destination (Public/Semi-Public access tier) or a restricted discovery (Insider/BreachOnly access tier, accessible by non-obvious route). Both types are valid; neither is mandatory over the other."
|
||||
|
||||
---
|
||||
|
||||
**D-READY-3: TrianglePurpose Enum**
|
||||
|
||||
No visual grammar implications. ✓ No changes.
|
||||
|
||||
---
|
||||
|
||||
**D-READY-4: WallBackside / TileBehindState**
|
||||
|
||||
✓ Three visual cases confirmed: adjacent room, infrastructure cavity, perimeter breach.
|
||||
|
||||
**Wording addition:** "Infrastructure cavity contents are Era-tagged: Era 1 = power conduit only; Era 2 = power + water/coolant + comm lines; Era 3 = full bundle (all types, more densely bundled). The infrastructure color codes are standardized across all zones — power `#c8b840`, water/coolant `#4888c8`, comm/data `#b8b8b8`, structural beam `#3a3e42`. These colors apply regardless of zone palette."
|
||||
|
||||
---
|
||||
|
||||
**D-READY-5: Dynamic Modification via Overlay**
|
||||
|
||||
✓ Five-stage destruction visual correctly captured.
|
||||
|
||||
**Addition needed — trauma event → visual stage mapping:**
|
||||
|
||||
The D-record should include the mapping from `ModificationType::TraumaEvent` subtypes to starting destruction stage:
|
||||
|
||||
| Trauma event subtype | Starting visual stage | Scope |
|
||||
|----------------------|-----------------------|-------|
|
||||
| `PhysicalDestruction` | Stage 2 (Fresh Aftermath), decaying to Stage 3 over game-time | Area or district |
|
||||
| `ViolenceEvent` | Stage 2 (limited area — 1–4 chunks), stabilizes to Stage 3 quickly | Local |
|
||||
| `EconomicDisruption` | No destruction stage — Economic Stress quarter modifier applied instead | District-wide |
|
||||
| `PoliticalShock` | No destruction stage — Faction presence modifier (overlay) | District-wide |
|
||||
| `MigrationShock` | No destruction stage — Settlement vs. Economic Stress balance shifts | District-wide |
|
||||
|
||||
**The rule:** Destruction stages apply only to events that physically alter structures. Economic/political/migration trauma is expressed through the quarter fill modifier system (D-READY-6), not through destruction stages.
|
||||
|
||||
---
|
||||
|
||||
**D-READY-6: ZonePalette Modifier System**
|
||||
|
||||
✓ 8 base terrain types, 3 modifier axes confirmed.
|
||||
|
||||
**Wording addition needed:** Explicitly name T1 and T2 as the two farmland base palettes addressing the industrial/rustic distinction:
|
||||
|
||||
"T1 (Temperate Farmland): warm organic ground ambient, natural lighting regime. T2 (Industrial/Greenhouse Farmland): cool grey-green ambient, artificial lighting regime. The ambient regime difference (natural vs. artificial) is the primary visual distinction between rustic and industrial farming at the base palette level. Heritage root modifiers further differentiate them at the grammar level."
|
||||
|
||||
---
|
||||
|
||||
**D-READY-7: Horizon View Corridor as Coastal Guarantee**
|
||||
|
||||
✓ Fully confirmed. ≥8 vt unobstructed view corridor. Mandatory negative space reservation.
|
||||
|
||||
**Wording clarification:** The view corridor is **negative space** — an instruction to not place blocking structures, not a placed object. "The generator reserves a view corridor of minimum 8 visual tiles from the nearest public street to the water's edge. No building, tree, or z=4 element may occupy this corridor. A low z=2 element (railing, bench, bollard) marks the waterfront point as a designed viewing location."
|
||||
|
||||
---
|
||||
|
||||
**D-READY-8: Assassin Lens Spatial Guarantees (A-1 through A-4)**
|
||||
|
||||
✓ Correctly captured. The spatial guarantees don't require new visual elements — existing grammar serves the assassin.
|
||||
|
||||
**Wording note:** Guarantee A-1 (Elevated Vantage) requires clarification about what "clear LOS cone" means visually. Add: "An elevated vantage position must have a direct sightline — no z=4 overhead elements within the LOS cone between the vantage point and the Traffic Chokepoint. The generator ensures this by tagging the LOS corridor as an overhead-clear zone during block planning."
|
||||
|
||||
---
|
||||
|
||||
**D-READY-9: Heritage Grammar Overlay for Non-Urban Palettes**
|
||||
|
||||
**Status: Not yet lockable — this round provides the authoring workflow that was missing.**
|
||||
|
||||
See Section 1 above for the full specification. The D-record needs:
|
||||
1. The `HeritageModifier` struct definition (from Section 1)
|
||||
2. The 10-root modifier table (from Section 1)
|
||||
3. The authoring workflow description (from Section 1)
|
||||
4. The rule: heritage modifier applied at Phase 2 chunk fill, with one exception (gathering_probability for Phase 1 pre-assignment)
|
||||
|
||||
**With Section 1 above, this item is now lockable.**
|
||||
|
||||
---
|
||||
|
||||
**D-READY-10: Non-Urban Informal Zone Typology**
|
||||
|
||||
✓ Correctly captured. Miri's three types resolved.
|
||||
|
||||
**Addition — visual grammar for each informal zone type:**
|
||||
|
||||
The D-record should include how each type reads visually:
|
||||
|
||||
| Informal zone type | Visual signature |
|
||||
|-------------------|-----------------|
|
||||
| `social_permission` | Normal zone palette, but gathering infrastructure present (covered space, seating). The space looks designed for use, not abandoned. The signal is the gathering element, not absence of official markers. |
|
||||
| `physical_distance` | Sparse objects, low overhead. Floor tile: terrain-appropriate but less maintained (no worn path markers — the path is made by walking, not cleared). The isolation IS the visual — this space has no design attention. |
|
||||
| `utilitarian_cover` | Functional work objects. Normal zone palette. The informal zone reads as work space — the cover story is the visual appearance. There is no obvious sign that this space serves unofficial purposes; the player must infer from context. |
|
||||
|
||||
---
|
||||
|
||||
**D-READY-11: Vertical Scale Architecture**
|
||||
|
||||
✓ Height tier system (S1–S4), shadow lengths, rooftop vocabulary all confirmed.
|
||||
|
||||
**Addition for the D-record:** The Rooftop Bar Clause from Section 3 above should be incorporated as a sub-rule of the vertical scale architecture decision. Specifically: "The roof zone at tier S3+ must be assigned a social character during block planning: `PublicDestination | RestrictedDiscovery`. This character determines the visual grammar applied at chunk fill time."
|
||||
|
||||
---
|
||||
|
||||
**D-READY-12: Trauma Events as EraModification Subtypes**
|
||||
|
||||
✓ Correctly captured from Miri's work.
|
||||
|
||||
**Addition — visual stage mapping already provided in D-READY-5 wording above.** The two D-records cross-reference.
|
||||
|
||||
**One wording clarification:** The "active modification state" that decays toward baseline — this decay is visual. As time passes (in-game hours/days), the destruction stage advances from Stage 2 → Stage 3 → Stage 4 → Stage 5. The decay rate is heritage-root-dependent (Frost: faster visible recovery; Tide: faster social recovery; Arc: lingers institutionally). This decay schedule should be in the D-record as a visual parameter: `trauma_visual_decay_rate: slow | medium | fast` per heritage root, defaulting to `medium`.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
**OQ-R4-D (Heritage Grammar Overlay):** Resolved. Authoring workflow: ten TOML modifier files (one per heritage root), each specifying object sets, arrangement algorithm, overhead character, lighting temperature adjustment, and gathering probability. Runtime: blend modifiers at chunk fill time by heritage weight (continuous values: weighted average; discrete values: weighted probabilistic selection). Phase 1 exception: gathering_probability evaluated at block planning for quarter pre-assignment. Item D-READY-9 is now lockable.
|
||||
|
||||
**Vessel Visual Grammar:** Vessels use existing zone palettes with five additional rules: (1) exterior hull is vessel-identity material; (2) window tiles reveal exterior context; (3) compression modifier tightens proportions; (4) section transitions use vessel-identity threshold elements; (5) service class is expressed through proportion, not palette change. No new base palettes required.
|
||||
|
||||
**Rooftop Bar Clause:** Gestalt's guarantee amended — "discovery zone at the top" replaces "Insider/BreachOnly" as the mandatory requirement. Public rooftop destinations (rooftop bar, garden) satisfy the guarantee equally with restricted ones. Visual distinction: warm amber lighting + social furniture (public) vs. cold mechanical silhouette (restricted). Both readable at a glance from adjacent elevation.
|
||||
|
||||
**D-record sign-off:** All 12 items reviewed. Five wording additions/clarifications flagged. D-READY-9 was the only item not previously lockable — it is now, with Section 1 providing the missing authoring workflow. The trauma → visual stage mapping (D-READY-5/12) is new and must be included in the D-records.
|
||||
|
||||
---
|
||||
|
||||
*Araminta — Round 4 complete. All four assignments closed. Standing by for D-record production.*
|
||||
@@ -0,0 +1,116 @@
|
||||
# Generator Architecture Workshop — Round 5 (Final Review): Araminta
|
||||
|
||||
**Role:** Visual Designer
|
||||
**Date:** 2026-02-27
|
||||
**Workshop:** Generator Architecture (#562)
|
||||
|
||||
---
|
||||
|
||||
## Sign-Off
|
||||
|
||||
The outcomes document accurately captures the visual design domain. All five wording additions and clarifications I flagged in Round 4 are incorporated correctly:
|
||||
|
||||
- **D-READY-1**: 45° cap stated as "non-negotiable" hard technical constraint — correct wording, correct framing.
|
||||
- **D-READY-2**: Rooftop Discovery Zone listed as Tier 2 Full-complexity guarantee — correct.
|
||||
- **D-READY-4**: Era-tagged infrastructure color codes present (`#c8b840` / `#4888c8` / `#b8b8b8`) — correct.
|
||||
- **D-READY-5**: Trauma event → visual stage mapping present. Physical events → Stage 2, economic/political/migration → quarter fill modifier. Correct.
|
||||
- **D-READY-6**: T1 (warm organic, natural lighting) / T2 (cool grey-green, artificial lighting) explicitly distinct — correct.
|
||||
- **D-READY-7**: "Negative-space reservation" framing — correct.
|
||||
- **D-READY-9**: Data-driven TOML modifier files (10 per heritage root), Phase 2 chunk fill blend, Phase 1 gathering_probability exception, authoring domain separation (Miri = spatial grammar, Araminta = visual expression + TOML files) — all correct.
|
||||
- **D-READY-10**: References `araminta-round4.md` for visual grammar per informal zone type — acceptable approach, avoids duplication.
|
||||
- **D-READY-11**: Rooftop Bar Clause present. Discovery layer mandatory in both configs. Correct.
|
||||
- **D-READY-12**: `trauma_visual_decay_rate: slow | medium | fast` per heritage root, default medium — correct.
|
||||
- **Q-NNN-e**: ObjectTag co-maintenance flagged as open question — correct.
|
||||
|
||||
I also confirm Ozzie's correction on D-READY-11: "Heritage root determines which config is assigned" is wrong and I should have been more precise in my R4 language. Heritage root should *weight the probability*, not *determine the outcome*. Ozzie is right — full determination kills the discovery moment. A Frost building with a rooftop bar is memorable precisely because it is unexpected. The correction stands.
|
||||
|
||||
---
|
||||
|
||||
## Corrections — Three Items
|
||||
|
||||
### Correction 1 (Critical): T5/T7 Terrain Palette Numbering Wrong
|
||||
|
||||
D-READY-6 lists the 8 base terrain types as: T1 temperate farmland / T2 industrial farmland / T3 wilderness / T4 grassland / **T5 mountain** / T6 beach / **T7 wetland** / T8 desert.
|
||||
|
||||
My Round 3 specification was:
|
||||
|
||||
| ID | Name |
|
||||
|----|------|
|
||||
| T5 | Coastal water |
|
||||
| T6 | Beach/coastal margin |
|
||||
| T7 | Mountain/high terrain |
|
||||
| T8 | Desert/arid |
|
||||
|
||||
The outcomes document has T5 and T7 transposed, and **"wetland" is not in my original 8 types at all** — it replaced mountain. This is a factual error.
|
||||
|
||||
Correct T5 = **Coastal water** (deep near-black blue, animated specular reflection, the terrain type referenced by D-READY-7's horizon view corridor guarantee). Correct T6 = **Beach/coastal margin** (warm dark tan). Correct T7 = **Mountain/high terrain** (dark blue-grey stone, snow at elevation). Wetland was never specified — if it needs to be added, it requires design work as a 9th type, not a silent replacement.
|
||||
|
||||
**This error matters because:** T5 (Coastal water) is the terrain type that triggers the D-READY-7 horizon view corridor guarantee. If T5 is mountain, the coastal guarantee has no palette to reference.
|
||||
|
||||
**Required fix in D-READY-6:** Correct the T5/T6/T7/T8 labels to match my Round 3 specification. Remove "wetland." If wetland terrain is needed for the game, file it as a new type with a new T-number.
|
||||
|
||||
---
|
||||
|
||||
### Correction 2: D-READY-9 — Araminta's Authoring Domain Listed Incomplete
|
||||
|
||||
D-READY-9 describes my authoring domain as: *"object sets, arrangement algorithms, lighting temperature (TOML modifier files, one per heritage root)".*
|
||||
|
||||
My Round 4 TOML schema included additional sections not captured here. The full domain covers:
|
||||
|
||||
- `[floor].variant_preference` — floor surface texture (worn_path, pressed_earth, etc.) — part of visual expression, not organizational grammar
|
||||
- `[overhead].density_factor` — flora/canopy density, a continuous visual parameter
|
||||
- `[overhead].character` — overhead object character (personal_organic, industrial_grid, etc.)
|
||||
- `[structure].primary_material` / `material_tone_shift` — wall material character and color temperature shift
|
||||
- `[boundaries].fence_type` — boundary/fence material (trellis_wood, stone_wall, wire_mesh, etc.)
|
||||
|
||||
Wall material character and boundary material are part of my domain — not Miri's. An implementer reading D-READY-9 would assign structural material selection to Miri (organizational principles) when these visual expression fields belong with me.
|
||||
|
||||
**Required fix in D-READY-9:** Update Araminta's domain to: *"object sets, arrangement algorithms, floor surface variants, overhead flora density and character, wall/structure material character, boundary material type, lighting temperature (TOML modifier files, one per heritage root)."*
|
||||
|
||||
---
|
||||
|
||||
### Correction 3: D-READY-13 — Vessel Visual Grammar Not Referenced
|
||||
|
||||
The MobileChunk section correctly captures structural fields, movement states, cultural grammar (via `TransitSocialModifier`), and departure schedules. It references Miri's canonical spec for cultural grammar.
|
||||
|
||||
It does not reference the vessel visual grammar I specified in Round 4 — five rules that apply to all MobileChunk-type spaces:
|
||||
|
||||
1. Exterior hull uses vessel-identity material (not zone palette)
|
||||
2. Window tiles reveal exterior context (docked vs. in transit)
|
||||
3. Compression modifier tightens proportions throughout
|
||||
4. Section transitions use vessel-identity threshold elements
|
||||
5. Class stratification expressed through proportion, not palette change
|
||||
|
||||
An implementer reading D-READY-13 in isolation has no source for how vessels look different from buildings. The compression modifier and hull-identity threshold material are required for correct chunk fill.
|
||||
|
||||
**Required fix:** Add to D-READY-13: *"Vessel visual grammar: see `docs/workshops/generator-architecture/araminta-round4.md` §2. Five rules govern visual distinction of MobileChunk interiors from static zone spaces."*
|
||||
|
||||
---
|
||||
|
||||
### Correction 4: D-READY-5 — Destruction Stage Sequence Not Enumerated; Destruction Palette Absent
|
||||
|
||||
D-READY-5 references "Stage 2 (Fresh Aftermath)" and "Stage 3" in the trauma event mapping but never enumerates the full stage sequence. The destruction palette constraint is also absent.
|
||||
|
||||
**Required addition — stage sequence:**
|
||||
|
||||
| Stage | Name | Visual state |
|
||||
|-------|------|-------------|
|
||||
| 1 | Active | Event in progress; DamageOverlay rendering live |
|
||||
| 2 | Fresh Aftermath | Structure breached; scorch, rubble, debris tiles visible |
|
||||
| 3 | Stabilized | Debris cleared; structural state permanent |
|
||||
| 4 | Reconstruction | Scaffolding tiles, incomplete floor sections |
|
||||
| 5 | Healed Scar | Functional again; residual visual tells remain |
|
||||
|
||||
**Required addition — destruction palette constraint:**
|
||||
|
||||
> Destruction palette is **corruption-only**: no new colors are introduced by destruction. Existing zone palette tiles are darkened, desaturated, or replaced with structural-damage variants drawn from the same palette family. Single exception: `#c8d8f0` (open-sky tile) appears at 100% intensity when a roofed structure has its roof removed — the only color that destruction introduces. Implementers must not create a separate destruction color set.
|
||||
|
||||
This constraint is needed in the D-record to prevent implementers from adding freestanding destruction palette colors. Without it, different implementations will diverge on whether destruction has its own visual language or borrows from zone palettes.
|
||||
|
||||
---
|
||||
|
||||
## Sign-Off (Updated)
|
||||
|
||||
With the four corrections above applied, the document is accurate for the visual design domain. The 14 D-records are ready to file.
|
||||
|
||||
*Araminta — Round 5 complete.*
|
||||
@@ -0,0 +1,261 @@
|
||||
# Generator Architecture Workshop — Round 1: Gestalt
|
||||
|
||||
**Role:** Systems Design / Gameplay Loop Requirements
|
||||
**Date:** 2026-02-27
|
||||
**Workshop:** Generator Architecture (#562)
|
||||
|
||||
---
|
||||
|
||||
## Framing Statement
|
||||
|
||||
The generator must produce spaces that create **information asymmetry** — not just visually plausible locations, but locations where what you know, who you know, and where you can go produce fundamentally different gameplay experiences. Every spatial guarantee below is ultimately a guarantee about asymmetric information production.
|
||||
|
||||
Let me break down what the generator actually needs to produce, mechanically.
|
||||
|
||||
---
|
||||
|
||||
## 1. What Gameplay Loops Does the Generator Need to Support?
|
||||
|
||||
The game has five confirmed gameplay loops (D-007 five pillars). The generator must support all five with spatial affordances.
|
||||
|
||||
### Loop 1: Observation Loop
|
||||
**Mechanic:** Player moves through space, maintains Careful/Walk stances (D-053), observes NPC tells, detects anomalies, fires monologue recognition events.
|
||||
**Generator requirement:** Every district needs spaces where NPCs are observable from cover — chokepoints, corridors, elevated positions, furniture arrangements that create natural sightline asymmetry. The functional cluster (D-025: 15-40 tile connected space with internal sightlines) is the atomic observable unit. The generator must instantiate these; it cannot produce districts where all spaces are either completely open or completely enclosed.
|
||||
|
||||
### Loop 2: Investigation Loop
|
||||
**Mechanic:** observe → notice → follow → discover. Three confirmed path types from D-093 (Path A: pattern/digital, Path B: physical/spatial, Path C: institutional/social). Each path yields unique evidence inaccessible to the other paths.
|
||||
**Generator requirement:** Every generated district must support all three path types. This means the spatial hierarchy must guarantee: (A) a zone with Meridian/camera log access (Path A), (B) a physical traversal corridor with acoustic gaps or spatial quirks (Path B), and (C) a social venue where institutional relationships develop (Path C). These are spatial guarantees, not content guarantees — the generator places the slots; templates fill them.
|
||||
|
||||
### Loop 3: Social Manipulation Loop
|
||||
**Mechanic:** Player builds rapport, climbs trust tiers (D-075), unlocks dialogue options (D-062 — invisible until unlocked), triggers unprompted disclosures. Social sites (D-025: 4-8 NPCs within 15-40 tile cluster) are the primary stage.
|
||||
**Generator requirement:** Every district needs at least one social venue (bar-type social site) that is publicly accessible without authority credentials, AND at least one workplace social site where insider access is required. These are not the same space. The generator must distinguish them at the zoning/amenity stage.
|
||||
|
||||
### Loop 4: Stealth/Exposure Loop
|
||||
**Mechanic:** Player manages their own information exposure — who saw them, where they went, what was recorded. Meridian dead spots (D-093: maintenance corridors, z=0 layer) are critical for both archetypes.
|
||||
**Generator requirement:** Every district must have at least one zone with degraded Meridian coverage where private exchanges can occur. The smuggler needs it for ring operations. The detective needs it for confidential source contact. Without this guarantee, both archetypes lose a core tool.
|
||||
|
||||
### Loop 5: Daily Life / Routine Loop (Substrate)
|
||||
**Mechanic:** Player witnesses NPC routines, builds complacency, creates emotional attachment that makes contamination hit harder (D-023: "daily life is the substrate; conspiracies are weather"). D-031 day phases drive NPC routine transitions.
|
||||
**Generator requirement:** The district must have transit nodes (encounter nodes where NPC routing creates observable patterns), temporal rhythm affordances (NPC populations change by day phase), and density variation (not all spaces always populated). The transit platform from D-093 is the canonical example — workers arrive bar-side at shift change, the pattern is observable.
|
||||
|
||||
---
|
||||
|
||||
## 2. What Must the Generator Guarantee?
|
||||
|
||||
These are non-negotiable spatial guarantees. If a generated district fails any of these, it cannot support the core gameplay loops.
|
||||
|
||||
### Guarantee 1: Surveillance Chokepoint
|
||||
**Definition:** A spatial bottleneck where NPC traffic must pass and is observable from a fixed position by a player in Walk or Careful stance.
|
||||
**Why mandatory:** The observation loop (Loop 1) requires this. Without at least one chokepoint, the player has no reliable observation position. Evidence gathered here feeds Path A and Path B investigation.
|
||||
**Example from D-093:** Gate concourse (40×8 sim tiles, public zone) + transit platform (bar-side encounter node, ~12×8 visual). These are chokepoints by geometry — narrow corridors NPCs must traverse.
|
||||
**Generator mechanism:** Infrastructure stage must place at least one high-traffic corridor connecting the transit ingress to the district's social sites. Block generation must not route NPCs around it.
|
||||
|
||||
### Guarantee 2: Quiet Zone (Meridian Dead Spot)
|
||||
**Definition:** A zone with low or absent Meridian coverage and low ambient NPC traffic, suitable for private exchanges.
|
||||
**Why mandatory:** The stealth/exposure loop (Loop 4) requires this for both archetypes. The ring (and its analog in any generated district) needs operational dead spots. Without this, the 30/50/20 entanglement model (D-029) has nowhere to put the entangled 20%.
|
||||
**Example from D-093:** Maintenance corridors at z=0 (minimal Meridian, no general NPC traffic). Restricted storage corridor (acoustic gap, accessible only via specific physical path).
|
||||
**Generator mechanism:** Infrastructure stage assigns Meridian coverage per zone. Zoning stage marks these zones. At least one zone per district must be flagged `meridian_coverage: degraded` or `minimal`.
|
||||
|
||||
### Guarantee 3: Social Manipulation Hub (Public Social Site)
|
||||
**Definition:** A social venue with D-025 cluster properties (4-8 NPCs, 15-40 tile connected space, internal sightlines) that is publicly accessible — no access credentials required.
|
||||
**Why mandatory:** Social manipulation loop (Loop 3) requires a space where both archetypes can build relationships. Bar-type social sites are the canonical form. Without this, trust tier progression has no natural stage.
|
||||
**Example from D-093:** The Last Shift / "Lera's" (bar). Public access, established regulars, D-025-compliant cluster.
|
||||
**Generator mechanism:** Amenities stage must instantiate at least one bar/social venue type. Its chunk fill must satisfy D-025 sightline requirements — the quarter system cannot fragment this into isolated enclosed rooms.
|
||||
|
||||
### Guarantee 4: Insider Access Zone (Workplace Social Site)
|
||||
**Definition:** A functional cluster where employment/membership (not authority) grants access that the detective archetype cannot obtain through institutional credentials.
|
||||
**Why mandatory:** Asymmetric access between archetypes (D-007 pillar 1) requires at least one zone where the smuggler's insider knowledge is an advantage. This is what makes two-character play produce fundamentally different games (D-027 criterion 2).
|
||||
**Example from D-093:** The Terminal (logistics hub) — freight workers have insider access, detective requires Commission warrant to access operational areas.
|
||||
**Generator mechanism:** Zoning stage marks `access_tier: insider` zones that require employment/social credentials, not authority credentials.
|
||||
|
||||
### Guarantee 5: Institutional Authority Zone (Restricted Access)
|
||||
**Definition:** A zone where authority credentials (detective archetype) provide access that the insider (smuggler archetype) cannot obtain through social rapport.
|
||||
**Why mandatory:** Mirror of Guarantee 4. Both archetypes must have at least one access advantage the other lacks. This is the mechanical expression of "two keyholes on the same world" (D-027).
|
||||
**Example from D-093:** Gate cluster restricted zones — Commission inspector access; gate aperture chamber (8×4 restricted); observation gallery (z=2, Commission-only).
|
||||
**Generator mechanism:** Zoning stage marks `access_tier: restricted/authority` zones. At least one per district.
|
||||
|
||||
### Guarantee 6: Triangle Social Geometry
|
||||
**Definition:** The district's NPC population must form at least 2 active triangles (D-024 minimum: "2 per template minimum, 1 cross-template"). Triangles require NPCs with conflicting interests positioned in overlapping spatial zones.
|
||||
**Why mandatory:** Triangles are "the atomic unit of social intrigue" (D-024). Without them, investigation and social manipulation loops have no payoff. The 30/50/20 model (D-029) requires triangles to exist across all tiers.
|
||||
**Generator mechanism:** Population stage assigns NPCs with conflicting Want/Secret/Relationship axes. District skeleton output must include at minimum: 2 triangles whose members' daily routines bring them into shared spatial zones. Cross-template triangle (D-024 minimum) means members must span at least 2 social sites.
|
||||
|
||||
### Guarantee 7: Three-Path Investigation Structure
|
||||
**Definition:** Three distinct evidence chains, each requiring different spatial access or social credentials.
|
||||
**Why mandatory:** Path A/B/C structure from D-093 is the mechanical proof-of-concept for investigation gameplay. A single investigation path collapses asymmetric information into a linear puzzle.
|
||||
**Generator mechanism:**
|
||||
- **Path A** (pattern/digital): requires a zone with Meridian/camera access point
|
||||
- **Path B** (physical): requires a physical traversal route with at least one acoustic anomaly or spatial gap
|
||||
- **Path C** (institutional/social): requires a social site where rapport-building yields unique evidence
|
||||
|
||||
Each path must produce at least one piece of evidence not obtainable via the other paths.
|
||||
|
||||
---
|
||||
|
||||
## 3. How Do the Pipeline Stages Map to Gameplay-Relevant Structures?
|
||||
|
||||
Taking the Cities Skylines top-down pipeline as the working model:
|
||||
|
||||
```
|
||||
Geography
|
||||
→ Infrastructure (transport nodes, utilities, Meridian coverage)
|
||||
→ Amenities & Services (social site types, access tiers)
|
||||
→ Population (NPC count, entanglement rate, triangle seeding)
|
||||
→ Zoning (access tier assignment per zone)
|
||||
→ Block generation (multi-block reservations, functional type per block)
|
||||
→ Chunk fill (social site template instantiation, sub-chunk quarter assignment)
|
||||
```
|
||||
|
||||
### Geography → Spatial Affordance Type
|
||||
**Gameplay product:** Determines what kinds of spaces are even possible.
|
||||
- Station → constrained corridors, z-level variation, Meridian infrastructure baked in
|
||||
- Planet-side → open space, variable Meridian coverage, weather effects (D-050: fog degrades vision cones equally)
|
||||
- Orbital → low gravity implications, different spatial scale
|
||||
The generator doesn't need to solve this in v0.1 (one station, one district). But the architecture must accept geography as an input to every downstream stage.
|
||||
|
||||
### Infrastructure → Surveillance + Stealth Topology
|
||||
**Gameplay product:** Where observation is rewarded; where privacy is possible.
|
||||
Critical generator outputs at this stage:
|
||||
- **Transit node placement** → chokepoint geometry (Guarantee 1)
|
||||
- **Meridian coverage assignment per zone** → quiet zone placement (Guarantee 2)
|
||||
- **Utility corridor routing** → maintenance spine, provides physical traversal path for Path B
|
||||
- **Z-level assignment** → which spaces are at ground level vs. elevated vs. sub-level (affects LOS per D-066)
|
||||
|
||||
**Key design requirement:** Infrastructure stage must not be purely functional — it must be evaluated through "does this produce interesting observation positions and interesting private zones?"
|
||||
|
||||
### Amenities & Services → Social Site Type Assignment
|
||||
**Gameplay product:** Which social loops are available and where.
|
||||
Critical generator outputs:
|
||||
- **Social venue (bar-type)** → public social site, social manipulation hub (Guarantee 3)
|
||||
- **Workplace (terminal-type)** → insider access zone (Guarantee 4)
|
||||
- **Institutional space** → authority access zone (Guarantee 5)
|
||||
- **Medical/service** → secondary social contact points, NPC routing attractors
|
||||
|
||||
This is where the D-025 "social site / functional cluster" concept is first instantiated as a type, not yet filled. The amenities stage selects template tags; the chunk fill stage instantiates the template.
|
||||
|
||||
### Population → Triangle and Entanglement Seeding
|
||||
**Gameplay product:** The human drama that investigation reveals.
|
||||
Critical outputs:
|
||||
- **NPC count per zone** → density sufficient for 30/50/20 split (D-029)
|
||||
- **Entanglement rate** → seeded per-game, varies to prevent metagaming (D-029)
|
||||
- **Triangle assignment** → minimum 2 active triangles (D-024), placed across confirmed social sites
|
||||
- **NPC axis rolls** → Want/Secret/Relationship/Routine assigned; these must produce spatial conflicts (NPC A works at the terminal but secretly meets NPC B in the maintenance corridor)
|
||||
|
||||
**Critical relationship with zoning:** Population and Zoning must be jointly optimized. An NPC with a secret that requires access to a restricted zone must be assigned a role that gives them that access. The generator cannot assign secrets that have no plausible staging ground.
|
||||
|
||||
### Zoning → Access Tier Palette
|
||||
**Gameplay product:** The invisible layer of gates that defines what each archetype can see.
|
||||
Zone types required (from D-093 example):
|
||||
- `public` → anyone can enter
|
||||
- `semi-public` → soft social gate (regulars, workers)
|
||||
- `semi-private` → employment/insider required
|
||||
- `private` → insider + relationship required
|
||||
- `restricted` → authority credentials required
|
||||
- `commission-only` → detective-archetype exclusive
|
||||
- `maintenance` → ring-insider exclusive or physical bypass required
|
||||
|
||||
**Key design requirement:** Every district must have at minimum one zone from each end of the spectrum (public ↔ restricted/maintenance). Middle tiers provide the interesting gameplay — they're contestable.
|
||||
|
||||
### Block Generation → Multi-Block Structure Reservation
|
||||
**Gameplay product:** The "large civic structures" (gate terminals, stadiums, gov buildings) that anchor district identity and create mandatory routing patterns.
|
||||
Critical requirements:
|
||||
- Reserve multi-block footprint before chunk fill runs
|
||||
- Multi-block structures create natural chokepoints at their approaches (Guarantee 1)
|
||||
- They contain the institutional access zones (Guarantee 5)
|
||||
- Their internal layout is constrained but not dictated — a gate terminal must have a gate concourse (public) AND a restricted zone; exact dimensions are filled at chunk level
|
||||
|
||||
### Chunk Fill → Social Site Template Instantiation
|
||||
**Gameplay product:** The specific spaces players actually inhabit.
|
||||
This is where D-025 templates are instantiated. The chunk fill stage:
|
||||
1. Selects a social site template tag (assigned at amenities stage)
|
||||
2. Configures sub-chunk quarters for that template's spatial requirements
|
||||
3. Places NPC slots, interaction points, overhearing positions, evidence anchors
|
||||
4. Ensures D-025 sightline requirement within the cluster's tile footprint
|
||||
|
||||
---
|
||||
|
||||
## 4. What Constraints Does the Triangle Template System (D-025) Place on Chunk Fill?
|
||||
|
||||
This is the critical mechanics question. Let me map it precisely.
|
||||
|
||||
### Constraint 1: Connected Space Continuity (15-40 sim tile radius)
|
||||
**D-025 says:** The functional cluster is "15-40 tiles of connected space with internal sightlines."
|
||||
**Constraint on chunk fill:** The sub-chunk quarter system must not produce fully enclosed, sightline-isolated quarters within a single social site's footprint. A 64×64 sim tile chunk (32m) can fit a 40-tile cluster comfortably — BUT the quarter merge/split rules must preserve internal connectivity.
|
||||
**Practical rule:** If a social site spans N quarters, all N quarters must share at least one sightline corridor. A 2×2 quarter full merge (open floor) trivially satisfies this. An L-shaped 3-quarter configuration must not have the interior angle be a solid wall.
|
||||
|
||||
### Constraint 2: Internal Sightline Preservation
|
||||
**D-025 says:** "physical cluster defines spatial identity (sightlines, overhearing, public/private)."
|
||||
**Constraint on chunk fill:** Quarter configurations that fragment a social site into acoustically isolated boxes violate the overhearing mechanic (D-018 sound model). The observation loop (Loop 1) depends on players being able to hear conversations from adjacent positions.
|
||||
**Practical rule:** Social site chunks must have at least one "soft partition" zone — a position where the player can hear adjacent conversations but NPCs have reasonable privacy expectation. This is the eavesdrop sweet spot that rewards Careful stance.
|
||||
|
||||
### Constraint 3: NPC Single-Ownership with Cross-Reference Links
|
||||
**D-025 says:** "NPCs are owned by exactly one template with reference links to others."
|
||||
**Constraint on chunk fill:** When a district has multiple social sites, the chunk fill for each site must assign NPC ownership unambiguously. An NPC cannot "belong" to two filled chunks.
|
||||
**Cross-template contamination** (D-025: "One NPC can hold roles in multiple social sites") is expressed through reference links, not through shared ownership. The chunk fill must represent this as: NPC primary slot in Chunk A, secondary reference appearance in Chunk B (e.g., a bar regular who also works at the terminal).
|
||||
**Practical implication for the generator:** The population stage (upstream) must assign NPC primary templates BEFORE chunk fill runs. Chunk fill uses the population stage output, not the other way around.
|
||||
|
||||
### Constraint 4: The 4-8 NPC Density Window
|
||||
**D-025 says:** "4-8 NPCs who regularly interact."
|
||||
**Constraint on chunk fill:** A social site's chunk cannot be over-filled (>8 regularly interacting NPCs in one cluster) or under-filled (<4 interacting NPCs). Tier 3 background NPCs (D-029: 30% flat wallpaper) pass through but don't "belong" to the cluster.
|
||||
**Quarter implication:** A full 2×2 quarter merge producing a large open floor can host 4-8 NPCs in a social site. A single-quarter configuration (¼ chunk = 32×32 sim tiles = 16m) can host a smaller social site, but may be too small for 8 NPCs with meaningful daily routines. The generator should default: smaller clusters in single quarters (4-5 NPCs), larger clusters in merged quarter configurations (6-8 NPCs).
|
||||
|
||||
### Constraint 5: Public/Private Gradient Within the Cluster
|
||||
**D-025 says:** "Physical cluster defines spatial identity (sightlines, overhearing, public/private)."
|
||||
**Constraint on chunk fill:** Within a single functional cluster, there must be spatial differentiation between public-facing areas and private areas. The bar example from D-093: bar area (public, all access) + back room (private, insider only) + below-bar maintenance access (restricted, ring members only). This tri-zone structure within one cluster must be representable in the quarter system.
|
||||
**Quarter solution:** A 4-quarter chunk representing a bar might configure as:
|
||||
- 2 quarters merged: main bar floor (public)
|
||||
- 1 quarter: back area / staff zone (semi-private)
|
||||
- 1 quarter gap or sub-quarter shack: storage/access point (private/restricted)
|
||||
|
||||
### Constraint 6: The "Invisible Infrastructure" Principle (G-08 from D-093)
|
||||
**D-093 says:** "every ring location reads as mundane; criminal function visible only to those who know."
|
||||
**Constraint on chunk fill:** This is a design constraint on HOW templates are instantiated. The chunk fill cannot place obvious "smuggling room" tiles. The physical arrangement must read as functional for mundane purposes while being usable for criminal ones.
|
||||
**Practical implication:** Templates must have a "surface reading" (manifest function) and a "second reading" (criminal function). Chunk fill must not diverge these visually — the same tile arrangement serves both. The distinction comes from NPC knowledge (D-041 knowledge graph), not from tile art.
|
||||
|
||||
---
|
||||
|
||||
## 5. Open Questions I'm Flagging for Round 2
|
||||
|
||||
### Q-A: Does Population Precede or Follow Zoning in Our Pipeline?
|
||||
The Cities Skylines model puts population after zoning. But our game has a critical dependency: **NPC secrets must have plausible staging grounds in the spatial layout**. An NPC with a secret meeting in a restricted zone requires that restricted zone to exist before the NPC can be validly generated.
|
||||
|
||||
**My position:** Population follows zoning for assignment (zones exist first), but population requirements should CONSTRAIN zoning (a zone must exist that satisfies the minimum secret/access requirements of the triangle configuration). This creates a feedback loop between population and zoning that the pipeline must resolve. Tyre will need to address whether this creates implementation complexity.
|
||||
|
||||
### Q-B: Triangle Template (D-025) Instantiation Stage
|
||||
The workshop brief asks where triangle templates are instantiated in the pipeline. **My position:** Triangle configuration is determined at the population stage (which NPCs exist, which have conflicting interests). Social site templates (D-025) are instantiated at chunk fill. The population stage produces a "social graph" that the chunk fill stage then places into physical space.
|
||||
|
||||
This means: social graph → chunk fill. NOT: chunk fill → social graph. The generator must not produce spatial arrangements and then try to fill them with compatible social graphs. The social graph drives spatial requirements.
|
||||
|
||||
### Q-C: What Is the Minimum Generated District?
|
||||
For v0.1 validation purposes: if we express Sova Transit District as generator output, what is the minimum generator that can reproduce it? I'd propose:
|
||||
- 1 workplace social site (terminal-type)
|
||||
- 1 social venue (bar-type)
|
||||
- 1 maintenance spine (quiet zone)
|
||||
- 1 transit encounter node
|
||||
- 1 restricted zone (authority access)
|
||||
- 2 active triangles across the above sites
|
||||
|
||||
This is the "minimum viable district" that satisfies all seven guarantees. Anything below this fails at least one gameplay loop.
|
||||
|
||||
---
|
||||
|
||||
## Summary: Generator Requirements as a Checklist
|
||||
|
||||
| Requirement | Source | Stage Where Guaranteed |
|
||||
|---|---|---|
|
||||
| Surveillance chokepoint | D-093, Loop 1 | Infrastructure |
|
||||
| Meridian dead spot / quiet zone | D-093, D-029, Loop 4 | Infrastructure |
|
||||
| Public social venue (bar-type, D-025 compliant) | D-025, Loop 3 | Amenities |
|
||||
| Insider access zone (workplace-type) | D-007, Loop 3 | Zoning |
|
||||
| Authority access zone (restricted-type) | D-007, Loop 3 | Zoning |
|
||||
| Triangle social geometry (≥2 active, D-024) | D-024, D-029, Loop 2 | Population |
|
||||
| Three-path investigation structure (A/B/C) | D-093, Loop 2 | Multi-stage |
|
||||
| Transit encounter node | D-093, D-095, Loop 5 | Infrastructure |
|
||||
| Internal sightlines within social sites | D-025, Loop 1 | Chunk fill |
|
||||
| Public/private gradient within clusters | D-025, Loops 1-3 | Chunk fill |
|
||||
| Invisible infrastructure (dual-reading spaces) | D-093 G-08, Loop 4 | Chunk fill |
|
||||
|
||||
Every pipeline stage maps to at least one row. No guarantee is produced "for free" — each requires an explicit generator mechanism.
|
||||
|
||||
---
|
||||
|
||||
*Gestalt — Round 1 complete. Ready to respond to Tyre (technical constraints), Miri (worldbuilding inputs), and Araminta (visual coherence) in Round 2.*
|
||||
@@ -0,0 +1,438 @@
|
||||
# Generator Architecture Workshop — Round 2: Gestalt
|
||||
|
||||
**Role:** Systems Design / Gameplay Loop Requirements
|
||||
**Date:** 2026-02-27
|
||||
**Workshop:** Generator Architecture (#562)
|
||||
|
||||
---
|
||||
|
||||
## Framing: Acknowledging the Lead Directive
|
||||
|
||||
The lead directive lands correctly. My Round 1 analysis was framed entirely through the investigation lens. That was useful for establishing what the generator must never fail to produce — but it was insufficient for a game that promises to support tycoon play, dating sim / social relationship play, and political drama as equally valid first-class experiences.
|
||||
|
||||
Let me break down what this means mechanically, then propose a pipeline that serves all of them.
|
||||
|
||||
The central insight: **the spatial guarantees from Round 1 are not investigation-specific. They're human-social-activity-specific.** A surveillance chokepoint is also a trade route bottleneck, a political rally point, and a serendipitous encounter location. An informal zone is also a grey market space, a tryst location, and a dissident meeting point. The 7 guarantees from Round 1 were named wrong — they were investigation vocabulary for playstyle-agnostic spatial archetypes.
|
||||
|
||||
This round I'm going to rename them, show how they serve every playstyle, add the guarantees that investigation didn't require, and propose a concrete two-phase pipeline that Tyre, Miri, and Ozzie's inputs have informed.
|
||||
|
||||
---
|
||||
|
||||
## 1. The Revised Spatial Guarantee Set: Playstyle-Agnostic Archetypes
|
||||
|
||||
Drop the investigation vocabulary. Here are the 7 spatial archetypes every generated district must contain, with their multi-playstyle readings:
|
||||
|
||||
### Archetype 1: Traffic Chokepoint
|
||||
**Physical definition:** A spatial bottleneck where significant NPC traffic must pass and is observable from a fixed adjacent position.
|
||||
**By playstyle:**
|
||||
| Playstyle | What it does for you |
|
||||
|---|---|
|
||||
| Investigation | Surveillance position — observe tells, track movements, spot anomalies |
|
||||
| Tycoon | Trade route leverage — who controls the choke controls the flow of goods |
|
||||
| Dating / Social | Serendipitous encounter point — this is where you "happen to run into" someone |
|
||||
| Political | Campaign territory — public visibility, speech platform, constituency pressure |
|
||||
|
||||
### Archetype 2: Informal Zone
|
||||
**Physical definition:** A zone with degraded institutional coverage, low ambient traffic, suitable for private or unofficial activity. Includes maintenance corridors, service back-alleys, rooftop access, below-street passages.
|
||||
**By playstyle:**
|
||||
| Playstyle | What it does for you |
|
||||
|---|---|
|
||||
| Investigation | Quiet zone — ring operations, confidential source meetings, dead drops |
|
||||
| Tycoon | Grey market space — off-ledger deals, unofficial distribution, tax-adjacent commerce |
|
||||
| Dating / Social | Privacy space — the rendezvous location, the conversation that can't happen in public |
|
||||
| Political | Back-channel space — the meeting that isn't on the record |
|
||||
|
||||
**Note for the generator:** This archetype must be generated deliberately, not incidentally. It is the space that official documentation doesn't account for (Miri's C-5 insight). Every district must have at least one, and it must be findable without being guided to.
|
||||
|
||||
### Archetype 3: Social Hub
|
||||
**Physical definition:** A D-025-compliant functional cluster (4-8 NPCs, 15-40 tile connected space, internal sightlines) that is publicly accessible without institutional credentials.
|
||||
**By playstyle:**
|
||||
| Playstyle | What it does for you |
|
||||
|---|---|
|
||||
| Investigation | Rapport-building stage — trust tier progression, gossip extraction |
|
||||
| Tycoon | Networking hub — find suppliers, hear rumors of demand, recruit partners |
|
||||
| Dating / Social | Romance venue — relationship initiation, shared leisure, social graph expansion |
|
||||
| Political | Influence gathering — read public mood, identify allies, make your presence felt |
|
||||
|
||||
### Archetype 4: Institutional Space
|
||||
**Physical definition:** A zone where official credentials, position, or authority determine access — and where institutional actors can be leveraged, pressured, or circumvented.
|
||||
**By playstyle:**
|
||||
| Playstyle | What it does for you |
|
||||
|---|---|
|
||||
| Investigation | Authority access zone — show credentials, pull records, compel cooperation |
|
||||
| Tycoon | Licensing / permit space — register trade routes, dispute cargo claims, bribe inspectors |
|
||||
| Dating / Social | Official encounter context — the formal interaction that begins some relationships |
|
||||
| Political | Power center — submit proposals, apply pressure, climb the institutional hierarchy |
|
||||
|
||||
### Archetype 5: Insider Space
|
||||
**Physical definition:** A zone where community membership, employment, or social standing (not official credentials) determines access.
|
||||
**By playstyle:**
|
||||
| Playstyle | What it does for you |
|
||||
|---|---|
|
||||
| Investigation | Insider access zone — ring operations visible only to those who belong |
|
||||
| Tycoon | Guild / union / cooperative — preferred trade terms, insider pricing, loyal suppliers |
|
||||
| Dating / Social | Close network space — the bar where the friend group drinks, the community event |
|
||||
| Political | Party / faction HQ — where the organized power lives |
|
||||
|
||||
### Archetype 6: Economic Node
|
||||
**Physical definition:** A space where goods, services, or information with economic value change hands. Includes markets, logistics points, trade counters, informal exchanges.
|
||||
**By playstyle:**
|
||||
| Playstyle | What it does for you |
|
||||
|---|---|
|
||||
| Investigation | Evidence trail — cargo manifests, transaction logs, the money that follows the crime |
|
||||
| Tycoon | Primary profit opportunity — buy low, sell high, establish routes |
|
||||
| Dating / Social | Shared activity — shopping together, market browsing, the informal economic life |
|
||||
| Political | Leverage point — economic actors are political actors; control trade = control votes |
|
||||
|
||||
**This is the archetype my Round 1 analysis missed.** It's present in v0.1 (the Terminal is an economic node) but I didn't name it as a required generator guarantee. It's non-negotiable for tycoon play.
|
||||
|
||||
### Archetype 7: Encounter Corridor
|
||||
**Physical definition:** A space primarily designed for movement — transit corridors, promenades, public routes — where encounters happen but nobody lingers.
|
||||
**By playstyle:**
|
||||
| Playstyle | What it does for you |
|
||||
|---|---|
|
||||
| Investigation | Observation route — follow NPCs, track patterns, sense when routines break |
|
||||
| Tycoon | Supply chain link — goods move through here; disrupting/controlling it is leverage |
|
||||
| Dating / Social | Casual crossing point — daily routine overlaps, the route you "happen to share" |
|
||||
| Political | Visibility territory — seen being there communicates political alignment |
|
||||
|
||||
**What I'm dropping from Round 1:** "Three-path investigation structure (A/B/C)" as a standalone guarantee. In the multi-playstyle framework, this becomes: **at least 3 distinct engagement vectors must exist for each playstyle**. For investigation these are pattern/physical/social. For tycoon they're supply/demand/regulation. For social/dating they're work-meeting/social-meeting/crisis-meeting. The generator doesn't need to know which playstyle the player chose — it needs to produce enough structural variety that at least 3 paths exist for any approach.
|
||||
|
||||
---
|
||||
|
||||
## 2. New Playstyle-Specific Guarantees
|
||||
|
||||
The 7 archetypes above are the floor. These additional guarantees serve playstyles the 7 archetypes don't fully address:
|
||||
|
||||
### Tycoon-Specific: Economic Asymmetry Signal
|
||||
The district must contain at least one indicator of **economic imbalance** — something being undersupplied, oversupplied, restricted, or priced unequally across zones. This is the tycoon's opening opportunity. In v0.1 terms: aftermarket lattice components are undersupplied because Commission regulation creates artificial scarcity. The generator must produce an analogous economic tension in every district.
|
||||
**Implementation:** The society profile's `economic_pressure` field (Miri's ingredient D) directly determines what the asymmetry is. `tight-margin` + `prohibition-economy` produces the Sova scenario. Different pressure combinations produce different economic tensions. The generator surfaces these as locatable economic nodes with discoverable demand gaps.
|
||||
|
||||
### Social/Dating-Specific: Temporal Encounter Window
|
||||
The district must produce at least one NPC whose daily routine creates **predictable, repeatable encounter opportunities** outside of work context. This is the "regulars at the bar at 1800 every day" pattern. The tycoon has stable trade windows; the romance player needs the equivalent.
|
||||
**Implementation:** This is a property of NPC routine generation (Stage 5), but the generator must guarantee the SPATIAL CONDITION: a social hub with defined temporal peaks (morning rush, evening gathering, night shift crowd). The D-031 day-phase system already provides this — social hubs must be tagged with active phases during skeleton generation.
|
||||
|
||||
### Political-Specific: Power Gradient Visibility
|
||||
The district must make its power topology **spatially legible** — who has authority over whom, and where that authority is exercised, must be readable from the space without metagame knowledge.
|
||||
**Implementation:** Araminta's zone palette and lighting temperature gradient already does this for institutional vs. social zones. The generator must additionally guarantee that at least one NPC occupies a visible authority position (SYSTEM pattern per Q-033) whose institutional relationship to other social sites is observable. The detective already gets this through the Commission; the political player needs the equivalent civic power holder.
|
||||
|
||||
### Non-Urban Specific: Natural Chokepoint
|
||||
**For non-urban templates (farmland, wilderness, maritime, ski resort, beach):** The Traffic Chokepoint archetype takes a different form — a mountain pass, a harbor entrance, a river ford, a seasonal trail. These are geographically determined rather than architecturally determined.
|
||||
**Generator requirement:** When `SettingGeometry = Rural / Maritime / Wilderness`, the infrastructure stage replaces architectural corridor planning with **terrain chokepoint identification**. The spatial archetype is the same; the generator mechanism is different.
|
||||
|
||||
---
|
||||
|
||||
## 3. Two-Phase Pipeline Proposal
|
||||
|
||||
The lead directive specifies: world/district generation is a background prep pass (spare CPU core). Local area generation is the fine-tuned interactive system. These are architecturally separate.
|
||||
|
||||
Here is the concrete two-phase pipeline, integrating Tyre's data structures, Miri's worldbuilding inputs, and the multi-playstyle requirements:
|
||||
|
||||
---
|
||||
|
||||
### PHASE 1 — Background Prep (Asynchronous, no player interaction required)
|
||||
|
||||
These stages can run while the player is already in a different location. Output is cached; player never waits.
|
||||
|
||||
#### Stage 0: World Significance Tier
|
||||
**Input:** Master world seed, galaxy topology
|
||||
**Output:** Per-location `SignificanceTier` + `SettingGeometry`
|
||||
|
||||
| Tier | What gets generated | Social density | Active scenarios |
|
||||
|---|---|---|---|
|
||||
| Center-stage | Full district generation, all phases | High | Multiple |
|
||||
| Regional | 1-4 districts, full phases | Medium | 1-2 |
|
||||
| Backwater | 1 district or partial, condensed | Low | 0-1 |
|
||||
| Waypoint | Tier 3 only — spatial skeleton, no NPCs | Minimal | None |
|
||||
| Insignificant | Not generated until player approaches | — | — |
|
||||
|
||||
This is not a Phase 1 computation — it's the classification that governs how much Phase 1 runs. A waypoint location gets a skeleton only. An insignificant place doesn't exist until the player gets close.
|
||||
|
||||
`SettingGeometry` enum (the lead directive requires this be first-class):
|
||||
```
|
||||
Station → zone-and-level grid
|
||||
Urban → terrain-influenced spread
|
||||
Rural → low-density farmland/town spread
|
||||
Maritime → coastal topology with water interface
|
||||
Wilderness → minimal infrastructure, scattered POIs
|
||||
Specialized → resort, research, military (single economic function)
|
||||
```
|
||||
|
||||
#### Stage 1: Society Profile Assembly
|
||||
**Input:** World seed, system political classification, heritage ingredients (Q-032)
|
||||
**Output:** `SocietyProfile` struct
|
||||
|
||||
This is Miri's full ingredients menu: Heritage Roots (blend weights), Settlement Motivation, Economic Function, Economic Pressure (1-2), Drift Stage, Absence Parameters, Faction Presence tiers, tech-level 3-axis profile.
|
||||
|
||||
Key outputs that feed downstream stages:
|
||||
- `social.privacy_level` → access tier thresholds
|
||||
- `trust.building_rate` → NPC trust progression speed
|
||||
- `economic_pressure` → economic asymmetry type
|
||||
- `meridian_coverage_baseline` → from tech-level axis 1
|
||||
- `active_phases` → which day phases have which social activity (D-031 integration)
|
||||
- `cultural_tags` → for NPC name generation, ambient text flavor
|
||||
|
||||
**On the serde question (Miri's OQ-5):** The society profile YAML must map to a Rust struct via serde. The nested structure (heritage with blend weights, faction presence with per-faction tiers) is manageable — Rust's serde_yaml handles this. The critical requirement is that blend weights sum to 1.0 and absence parameters serialize as `Option<T>` (NULL = None). Tyre should confirm the specific schema contract.
|
||||
|
||||
#### Stage 2: District Skeleton Generation
|
||||
**Input:** Society Profile, SignificanceTier, SettingGeometry, political classification
|
||||
**Output:** `DistrictSkeleton` (Tyre's data structure, extended with `significance_tier` and `setting_geometry` fields)
|
||||
|
||||
This stage is where the multi-playstyle spatial archetypes are guaranteed. The skeleton generator runs a **spatial guarantee audit** after producing a candidate skeleton:
|
||||
|
||||
```
|
||||
For each of the 7 spatial archetypes:
|
||||
Does the candidate skeleton contain at least 1 spatial site of this type?
|
||||
If NO → regenerate or augment the skeleton until the guarantee is satisfied
|
||||
|
||||
Additional per-playstyle checks:
|
||||
Economic node present? (required for significance_tier ≥ backwater)
|
||||
Temporal encounter window in social hub? (active_phases set?)
|
||||
Power gradient visible? (SYSTEM-pattern NPC slot in institutional space?)
|
||||
Informal zone explicitly flagged? (not inferred from access tier)
|
||||
```
|
||||
|
||||
This audit is the enforcement mechanism. Without it, the generator can technically satisfy the schema while producing an unplayable district.
|
||||
|
||||
**On edge bleed (lead directive):** The skeleton's `access_points` and `corridors` must extend to district edges as open connection slots. Neighboring districts resolve these connections when their own skeletons are generated. Blocks at district edges can be tagged `cross_district: true` on their social sites — these sites serve the district but are spatially adjacent to the neighbor. This is what creates the bleeding effect: a bar on the edge of the Transit District and the Residential Core serves both populations. It appears in both skeletons as a shared reference.
|
||||
|
||||
**Historical event modifier pass:** After the base skeleton is generated, Miri's historical events apply as modifications:
|
||||
1. Founding crisis → push drift_stage for affected zones, add blocked/repurposed blocks
|
||||
2. Economic disruption → modify economic_pressure, introduce `abandoned_state` blocks
|
||||
3. Institutional incursion → modify faction_presence_tier, add/remove authority zones
|
||||
|
||||
These modifications produce Ozzie's "historical palimpsest" — the skeleton records not just the current state but the modifications that produced it. When the L-shaped building in ChunkLayout is `LShape { corner: NE, cause: emergency_extension }`, the cause field is available for environmental storytelling at chunk fill time.
|
||||
|
||||
#### Stage 3: Block Planning
|
||||
**Input:** DistrictSkeleton, economic tier, era tags (from era stratification)
|
||||
**Output:** 16 `BlockSkeleton`s with ChunkLayouts, edge contracts, era tags, landmark slots
|
||||
|
||||
Era tags are assigned at block level here (confirming Araminta's rule). The block planning stage also:
|
||||
- Reserves multi-block footprints (gate terminals, parks, government buildings)
|
||||
- Assigns landmark slots (1 per district quadrant, per Araminta's §5.3)
|
||||
- Produces edge contracts for each chunk face (Tyre's Option A recommendation)
|
||||
- Assigns density parameters (filled quarters per block by economic tier, per Araminta's §3.3)
|
||||
|
||||
---
|
||||
|
||||
### PHASE 2 — Local Area Generation (On-Demand, Player-Proximate)
|
||||
|
||||
These stages run as the player enters loading radius. They produce the tile-level and NPC-level content.
|
||||
|
||||
#### Stage 4: Chunk Fill
|
||||
**Input:** BlockSkeleton, edge contracts, D-025 template library, society profile, era tags
|
||||
**Output:** Tile data for each 64×64 sim tile chunk
|
||||
|
||||
This is where Tyre's 500ms budget applies. Template stamping is the mechanism — select a template from the library appropriate to the zone/era/access-tier, stamp it into the quarter configuration, then decorate procedurally within the template's variation space.
|
||||
|
||||
Araminta's visual constraints apply here in full (zone palette, lighting temperature, saturation hierarchy, LOS anchor intervals, facade variation budget).
|
||||
|
||||
**Quarter fill for unclaimed space:** Nigel's flavor structure categories + Araminta's empty quarter types need unification. I'm proposing they're the same system with two vocabularies:
|
||||
|
||||
| Araminta type | Nigel category | Generator selection driver |
|
||||
|---|---|---|
|
||||
| Open plaza | Settlement indicator (seating clusters) | Social/community cultural heritage |
|
||||
| Service alley | — (implicit) | Always present at ratio, not selected |
|
||||
| Courtyard / garden | Settlement indicator (container gardens) | Heritage roots with outdoor-culture tradition |
|
||||
| Vehicle/cargo staging | — (logistics function) | Economic function = logistics/manufacturing |
|
||||
| Structural gap (undeveloped) | Economic stress (abandoned equipment) | Economic pressure = survival-gap or economic disruption event |
|
||||
| — | Informal economy (market stalls) | Economic pressure = tight-margin or prohibition-economy |
|
||||
| — | Faction presence (Commission kiosk) | Faction presence tier = standard or comprehensive |
|
||||
|
||||
**The critical addition:** Flavor structure type does feed NPC generation. A `market_stall` quarter increases the probability of OPERATOR-pattern NPCs in the adjacent social site's population. A `commission_kiosk` quarter increases SYSTEM-pattern NPCs. A `settlement_indicator (shrine)` quarter increases ANCHOR-pattern NPCs. This answers Ozzie's OQ-3 — yes, what fills a quarter has downstream social consequences.
|
||||
|
||||
#### Stage 5: NPC Instantiation
|
||||
**Input:** Chunk fill (role slots), triangle assignments from DistrictSkeleton, society profile, world seed
|
||||
**Output:** Generated NPCs with D-024 10-axis configurations, assigned roles, triangle connections, D-029 entanglement assignments
|
||||
|
||||
NPC instantiation runs after chunk fill because the role slots and their spatial context must exist before NPCs can be validly assigned to them. The role slot (e.g., "this is a HANDLER-pattern position in the logistics hub social site") constrains which axis combinations are generated.
|
||||
|
||||
This resolves my Round 1 OQ-A: **I was wrong about needing full co-resolution of population and zoning.** The feedback loop I identified is already handled by the skeleton stage:
|
||||
- **Skeleton stage:** triangle TOPOLOGY is locked (role types, conflict structure, staging ground requirements) — this ensures staging grounds exist
|
||||
- **Chunk fill stage:** role SLOTS are placed in the correct spatial positions
|
||||
- **NPC instantiation:** axis VALUES are generated to fill role slots
|
||||
|
||||
No feedback loop required. The skeleton guarantees that "a secret-holder NPC needs access to a restricted zone" by including a restricted zone in the skeleton's social site configuration for that template. The NPC instantiation then generates an NPC whose Secret axis is appropriate for that role.
|
||||
|
||||
**REVISED position (OQ-A):** Zoning → Skeleton (triangle topology + role types) → Block Planning → Chunk Fill (role slots in space) → NPC Instantiation (NPC values). Sequential, no feedback loop. The skeleton stage's role-type specification is the mechanism that guaranteed staging grounds without requiring simultaneous resolution.
|
||||
|
||||
#### Stage 6: Scenario Instantiation
|
||||
**Input:** NPC population, Tier 1 module pool draw (D-023), world seed
|
||||
**Output:** Active scenario config, entanglement assignments, evidence placement, active triangle configurations
|
||||
|
||||
This is the final step that makes the district "live" as an investigation/tycoon/social/political space. The entanglement pattern (D-029) is seeded here — which 20% (variable per seed) of NPCs are entangled. Evidence placement is seeded here. Active triangles are activated here.
|
||||
|
||||
For **tycoon play:** the economic asymmetry signals (economic node contents, demand gaps, price differentials) are set in this stage. The "who controls what" question in economic space is answered here.
|
||||
|
||||
For **political play:** the power topology (which institutional NPC reports to which, what's up for contest, where alliances can shift) is configured in this stage.
|
||||
|
||||
---
|
||||
|
||||
## 4. On Seed Architecture (OQ-2 from Round 1 Notes)
|
||||
|
||||
The lead says seeds are solved: single master seed, don't over-engineer. Endorsing this position.
|
||||
|
||||
**Single master seed derives all sub-seeds deterministically.** Same seed + different character = same world with different lenses. This is the correct design — it makes the "two playthroughs of the same seed" comparison a first-class experience (Nigel's comparison test, my D-027 criterion 2 goal). The player chose to play the same world from a different angle. They should discover exactly that.
|
||||
|
||||
For the pipeline: each stage receives `derive_seed(master_seed, stage_id, location_id)` → deterministic sub-seed. No per-stage seed parameters. The seed architecture is solved at the hash function level.
|
||||
|
||||
---
|
||||
|
||||
## 5. Non-Urban Templates and Insignificant Places
|
||||
|
||||
The lead directive requires the architecture to handle: farmland, wilderness, secluded towns, ocean, boats, ski resorts, beaches.
|
||||
|
||||
**These don't break the pipeline — they parameterize it differently.**
|
||||
|
||||
The key parameters that change for non-urban settings:
|
||||
|
||||
| Parameter | Urban (station) | Rural / Wilderness | Maritime |
|
||||
|---|---|---|---|
|
||||
| Block density | High (12-16 filled quarters) | Low (2-6 filled quarters) | Variable (coastal vs. open water) |
|
||||
| Social hub type | Bar, restaurant, forum | Rural tavern, community hall, farm cooperative | Harbor tavern, ship crew quarters, fish market |
|
||||
| Traffic chokepoint | Architectural corridor | Geographical feature (pass, ford, gate) | Harbor mouth, dock access, tide-dependent route |
|
||||
| Meridian coverage | Standard to comprehensive | Sparse to absent | Absent on water, sparse on shore |
|
||||
| NPC routine pattern | Shift-based (industrial) | Seasonal / agricultural | Tide-based / weather-dependent |
|
||||
| Economic node | Logistics terminal, market | Farm output, resource extraction | Harbor trade, catch market |
|
||||
| Informal zone | Maintenance corridor | Forest edge, ravine, cave | Below-deck, hidden cove, underwater |
|
||||
|
||||
**The generator handles all of these through `SettingGeometry` as a first-class input.** The pipeline stages run the same logic; the input parameters shape what's generated at each stage.
|
||||
|
||||
For **specialized settings** (ski resort, beach):
|
||||
- These are `SettingGeometry::Specialized` with a single primary economic function (recreation/tourism)
|
||||
- Social hubs are themed (lodge, beach bar, equipment rental as informal economy)
|
||||
- The institutional space is smaller (ski patrol office, lifeguard station) but must exist
|
||||
- The informal zone is the spaces off the maintained routes (off-piste terrain, after-hours areas)
|
||||
|
||||
**Insignificant places** are handled by the significance tier system (Stage 0). A waypoint gets a Tier 3 spatial skeleton only — traversable space with environmental storytelling baked in, but no NPC simulation. These are the spaces that "exist because the geometry requires them to," not because they host drama. They're the breathing room that makes the center-stage locations feel like islands in a wider world.
|
||||
|
||||
---
|
||||
|
||||
## 6. Responding to Tyre's Technical Constraints
|
||||
|
||||
**On hierarchy depth:** Accepted. Quarters are generation-time layout constraints, not hierarchy levels. Four levels (Region/District/Block/Chunk) is correct.
|
||||
|
||||
**On edge contracts:** Option A (edge contracts) is correct and essential for the district-edge bleed the lead requires. The `CorridorSpine` in the DistrictSkeleton should explicitly model cross-district continuity — a corridor that exits the district boundary records its target access point in the neighboring district.
|
||||
|
||||
**On the district skeleton data structure:** Tyre's `DistrictSkeleton` needs three additions for multi-playstyle support:
|
||||
1. `significance_tier: SignificanceTier` — governs how much of Phase 2 runs
|
||||
2. `setting_geometry: SettingGeometry` — governs what spatial archetypes are appropriate
|
||||
3. `guarantee_audit: GuaranteeAuditResult` — records which of the 7 archetypes are satisfied and where (makes the audit inspectable for validation)
|
||||
|
||||
And a modification: `SocialSitePlacement.triangles` should carry not just `TriangleTemplate` (which NPC types conflict) but `triangle_purpose: TrianglePurpose` — an enum that records what the conflict is FOR (investigation/economic/political/social), allowing the scenario instantiation stage to activate relevant triangles based on active playstyle context.
|
||||
|
||||
**On chunk fill budget:** Template stamping approach is correct for v0.2. One addition: the flavor structure assignment (Stage 4) should be pre-computed at block planning time (Stage 3) and stored in the BlockSkeleton, so chunk fill can read flavor_structure_type from its BlockSkeleton rather than computing it. This reduces per-chunk computation.
|
||||
|
||||
**On the Transit District as ground truth:** Fully endorsed. The validation deliverable is: hand-authored `DistrictSkeleton` + 64 `ChunkData`s for the Transit District, validated against the guarantee audit (all 7 archetypes satisfied, all 3 multi-playstyle engagement vectors verified for investigation, tycoon, and social play simultaneously). If it satisfies all three lenses, the schema is correct.
|
||||
|
||||
---
|
||||
|
||||
## 7. Responding to Miri's Worldbuilding Inputs
|
||||
|
||||
**On society profile as first-class data structure:** Confirmed and extended. The society profile feeds Stage 1 (pre-pipeline) and is passed through the entire Phase 1 pipeline. Every downstream stage receives the society profile as a parameter, not just the abstract outputs from it.
|
||||
|
||||
**On cultural variation producing mechanical variation:** Fully endorsed. The mechanism I'm adding: `social.privacy_level` from Miri's society profile maps directly to `access_tier.*` thresholds in the DistrictSkeleton's social sites. A high-privacy culture (Frost-dominant) produces more semi-private zones and slower trust-building windows at the same social site type. Same "bar" template, different mechanical behavior.
|
||||
|
||||
**On era stratification:** Era tags live at block level (Stage 3), as Araminta confirmed. I'm adding that era tags also record the REASON for era stratification — specifically, whether a block's era differs from the district norm due to a historical event modifier. `era: Era2, era_cause: corporate_merger` tells the chunk fill stage to use era-2 materials AND to place visible seams/contrasts that suggest the building was constructed in two phases.
|
||||
|
||||
**On grey economy as negative space:** The Stage 2 guarantee audit explicitly checks for `informal_zone: present`. This zone is not generated from amenities or zoning — it's generated from the infrastructure stage as an absence in the official map. The generator must model what's missing, not just what's placed.
|
||||
|
||||
---
|
||||
|
||||
## 8. Responding to Ozzie's Fan Concerns
|
||||
|
||||
**On Second Station Syndrome:** The multi-playstyle expansion actually solves this more thoroughly than investigation-only would. If the investigation-only player has learned "bar is always northwest," the tycoon-focused player might have shaped the district's economic node distribution differently. But more importantly: the social topology (who's in conflict, who's in power, what's the grey economy structure) varies by seed more than the spatial topology. The skeleton is never "the same shape wearing a different hat" — the shape is determined by the social topology, not the other way around.
|
||||
|
||||
**On quarters feeling caused, not random:** The `LShapeCause` enum I proposed in Stage 2 is the mechanism. The generator doesn't produce L-shaped buildings randomly — it produces them because `emergency_extension` (an addition was forced by a blocked demolition), `acquisition_boundary` (two buildings merged under new ownership), or `organic_growth` (gradual expansion over time). At chunk fill time, these causes manifest as visual evidence: a material seam in `organic_growth`, a slightly different era tag on the added portion in `acquisition_boundary`. The player may not consciously read the cause, but they feel "this shape makes sense here."
|
||||
|
||||
**On quarters producing social variation:** Confirmed, with the flavor-structure-to-NPC-affinity link I described in §3's chunk fill stage. Market stall quarter → OPERATOR-pattern NPC affinity. This makes the choice of flavor structure have downstream social consequences, not just visual ones.
|
||||
|
||||
**On historical palimpsest:** Miri's era stratification + historical event modifier pass + my `era_cause` addition together produce this. The generator records history as a sequence of modifications, not just a current state. The chunk fill stage can read the full modification history and express it in the tiles.
|
||||
|
||||
**On density contrast (the rhythm: crowded market → narrow corridor → sudden atrium):** This is produced by the combination of Araminta's density parameter (§3.3) and the landmark slot reservation (§5.3). The generator ensures density contrast exists within a district — a landmark multi-block structure is always adjacent to smaller-scale blocks, creating the density inversion Ozzie wants. This must be a *guarantee*, not a coincidence.
|
||||
|
||||
**Generator rule I'm adding:** Adjacent blocks in a district must not all have the same density tier. The block planning stage must enforce density alternation — if block (2,2) is high-density, at least one of its 4 orthogonal neighbors must be medium or low density.
|
||||
|
||||
---
|
||||
|
||||
## 9. Minimum Viable District — Multi-Playstyle Version
|
||||
|
||||
Round 1's MVD was investigation-scoped. Here's the universal MVD that serves all four playstyles simultaneously:
|
||||
|
||||
| Archetype | Physical form | Inv | Tycoon | Social | Politics |
|
||||
|---|---|---|---|---|---|
|
||||
| Traffic Chokepoint | Transit node or architectural corridor | ✓ | ✓ | ✓ | ✓ |
|
||||
| Informal Zone | Maintenance spine or off-route passage | ✓ | ✓ | ✓ | ✓ |
|
||||
| Social Hub | Bar or community gathering space | ✓ | ✓ | ✓ | ✓ |
|
||||
| Institutional Space | Authority access zone | ✓ | ✓ | — | ✓ |
|
||||
| Insider Space | Workplace or community insider zone | ✓ | ✓ | ✓ | ✓ |
|
||||
| Economic Node | Market or logistics point | — | ✓ | — | ✓ |
|
||||
| Encounter Corridor | Promenade or transit route | ✓ | — | ✓ | ✓ |
|
||||
| Plus: ≥2 active social triangles | Seeded social conflict | ✓ | ✓ | ✓ | ✓ |
|
||||
| Plus: ≥1 temporal encounter window | Day-phase social peak | — | — | ✓ | — |
|
||||
| Plus: ≥1 power gradient signal | Visible authority NPC | ✓ | — | — | ✓ |
|
||||
| Plus: ≥1 economic asymmetry signal | Demand/price gap | — | ✓ | — | ✓ |
|
||||
| Plus: Density contrast (adjacent blocks ≠ same tier) | Visual rhythm | ✓ | ✓ | ✓ | ✓ |
|
||||
|
||||
**Count:** 7 archetypes + 4 additional guarantees = 11 total checks in the guarantee audit. If a generated district passes all 11, it is playable for all four primary playstyles.
|
||||
|
||||
---
|
||||
|
||||
## 10. Summary: Pipeline Stages with Multi-Playstyle Outputs
|
||||
|
||||
```
|
||||
[Pre-pipeline]
|
||||
World Significance Tier + Setting Geometry → governs how much generation runs
|
||||
Society Profile (Miri's 6-category ingredients) → feeds everything downstream
|
||||
|
||||
[PHASE 1 — Background Prep]
|
||||
Stage 1: Society Profile Assembly
|
||||
Outputs: privacy_level, trust.building_rate, economic_pressure, meridian_coverage_baseline,
|
||||
active_phases, cultural_tags, faction_presence_tiers
|
||||
Serves: All playstyles (cultural foundation)
|
||||
|
||||
Stage 2: District Skeleton Generation
|
||||
Outputs: DistrictSkeleton + guarantee audit (11 checks passed)
|
||||
Includes: historical event modifier pass, LShape causes, cross-district edge connections
|
||||
Serves: Investigation (surveillance topology), Tycoon (economic nodes),
|
||||
Social (encounter windows), Politics (power gradient)
|
||||
|
||||
Stage 3: Block Planning
|
||||
Outputs: 16 BlockSkeletons + edge contracts + era tags with causes + landmark slots
|
||||
Includes: density alternation enforcement, flavor structure pre-assignment
|
||||
Serves: All playstyles (physical navigation, density contrast)
|
||||
|
||||
[PHASE 2 — Local Area, On-Demand]
|
||||
Stage 4: Chunk Fill
|
||||
Outputs: Tile data, applied flavor structures with NPC-affinity tags
|
||||
Includes: zone palette, era materials, LOS anchors, facade variation
|
||||
Serves: All playstyles (spatial readability)
|
||||
|
||||
Stage 5: NPC Instantiation
|
||||
Outputs: Generated NPCs with 10-axis configs, role assignments, triangles
|
||||
Includes: NPC affinity from flavor structure types, society profile behavioral mods
|
||||
Serves: All playstyles (the human texture)
|
||||
|
||||
Stage 6: Scenario Instantiation
|
||||
Outputs: Active scenarios, entanglement pattern, evidence placement,
|
||||
economic asymmetry specifics, political power topology
|
||||
Serves: Investigation (entanglement), Tycoon (economic opportunity),
|
||||
Social (relationship status), Politics (power configuration)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Open Questions for Round 3
|
||||
|
||||
### OQ-R2-A: Triangle Purpose Taxonomy
|
||||
I proposed `triangle_purpose: TrianglePurpose` (investigation/economic/political/social) in `SocialSitePlacement`. This needs formal definition. Tyre to confirm whether this adds implementation complexity, or whether the existing `TriangleTemplate` struct can carry purpose tags.
|
||||
|
||||
### OQ-R2-B: Guarantee Audit as Formal Schema
|
||||
The 11-check guarantee audit I've proposed should become a validated runtime check, not just a design document item. Every generated `DistrictSkeleton` should serialize its audit results. This supports validation (Tyre's test fixture proposal) and debugging.
|
||||
|
||||
### OQ-R2-C: Maritime and Wilderness Navigation
|
||||
The Traffic Chokepoint archetype works for all setting geometries. But for wilderness/maritime, the "informal zone" mechanic changes — there's no "maintenance corridor." What's the wilderness equivalent? I propose `terrain_informal_zone` (a geography-defined sheltered space — cave, ravine, hidden cove) that satisfies the same guarantee. This needs Miri's input on what wilderness informal zones look like culturally.
|
||||
|
||||
---
|
||||
|
||||
*Gestalt — Round 2 complete. Position is clear: the 7 archetypes serve all four playstyles simultaneously; the pipeline is two-phase with a 6-stage internal structure; population ordering question is resolved (sequential, no feedback loop); the guarantee audit is the enforcement mechanism. Ready for Round 3 convergence.*
|
||||
@@ -0,0 +1,870 @@
|
||||
# Generator Architecture Workshop — Round 3: Gestalt
|
||||
|
||||
**Role:** Systems Design / Gameplay Loop Requirements
|
||||
**Date:** 2026-02-27
|
||||
**Workshop:** Generator Architecture (#562)
|
||||
|
||||
---
|
||||
|
||||
## Framing: Five Lead Directives, One Convergence Document
|
||||
|
||||
Round 3 has five directives: assassin playstyle, universal-vs-conditional guarantees, destructible boundaries, vertical scale, and dynamic world modification. Plus Qatux flagged my own open question (OQ-R3-B: triangle purpose taxonomy) and three overlapping tier concepts that need reconciliation.
|
||||
|
||||
Let me break down what each directive means mechanically, then converge everything into a final pipeline statement.
|
||||
|
||||
---
|
||||
|
||||
## 1. Assassin as Full Playstyle Lens
|
||||
|
||||
Let me map the assassin's spatial needs before touching the archetype table.
|
||||
|
||||
**What the assassin is doing:** Pre-operation intelligence gathering → position staging → execution window → egress. The assassin is an investigator first (must understand the target's pattern), a political actor second (understands whose contract they're operating under), and a precision combatant third. Mechanically, what distinguishes assassination from combat is **timing and position** — not "can I win a fight" but "can I be in this specific place at this specific moment without being observed."
|
||||
|
||||
**The assassin's unique spatial requirements:**
|
||||
|
||||
| Need | Spatial expression |
|
||||
|---|---|
|
||||
| **Elevated vantage** | Any position 1+ z-level above a Traffic Chokepoint with LOS coverage downward |
|
||||
| **Timing window** | A period in the target area's day-cycle when NPC/observer density is reduced enough to act |
|
||||
| **Crowd anonymity** | A Social Hub or Encounter Corridor dense enough to blend into — the assassin needs to be unremarkable |
|
||||
| **Staging approach** | A route from the district edge to the target area that avoids institutional observation (Meridian dead zones, maintenance routes, unofficial paths) |
|
||||
| **Egress multiplicity** | At least 2 independent exits from the target zone that don't share a chokepoint — if one is cut off, the other remains |
|
||||
| **Pattern intelligence** | NPCs on the target's known route — the assassin needs to confirm the schedule before committing |
|
||||
| **No-door access route** | At least one path to the target area that doesn't pass through an institutional access point (guard, checkpoint, scan) |
|
||||
|
||||
Now the updated archetype table. Notice how every assassination archetype serves multiple playstyles — the SPACE is universal, only the USE differs.
|
||||
|
||||
### 1.1 Updated 7 Spatial Archetypes — Assassin Column Added
|
||||
|
||||
| Archetype | Definition | Investigation | Tycoon | Dating Sim | Political | **Assassin** |
|
||||
|---|---|---|---|---|---|---|
|
||||
| **Traffic Chokepoint** | Spatial bottleneck where significant NPC flow passes and is observable from an adjacent fixed position | Surveillance of movements and tells | Control trade flow leverage | Serendipitous encounter, reliable find | Campaign/voter presence, speechmaking | **Timing window — target must pass here; vantage position nearby** |
|
||||
| **Informal Zone** | Degraded institutional coverage, low ambient traffic, unofficial use — grey-area space | Quiet zone, dead drops, private meetings | Grey market exchange, unofficial trade | Private encounter, trysts, earned intimacy | Back-channel negotiation, away from faction eyes | **Staging approach — pre-op cache, equipment stash, unobserved waiting position** |
|
||||
| **Social Hub** | High NPC density, social mixing, multiple access tiers coexisting — the gathering place | Rapport building, information gathering | Networking, trade leads, rumor sourcing | Romance venue, repeated encounter, public ritual | Influence gathering, political reading | **Crowd cover — anonymity in numbers, pattern intelligence via overhearing** |
|
||||
| **Institutional Space** | Formal authority presence, access-tier-enforced, zone palette signals power | Official authority access, procedural leverage | Licensing, formal contracts, regulatory navigation | Formal encounter context (job interviews, official appointments) | Power center — the space authority controls | **Security architecture to map, access points to exploit or avoid** |
|
||||
| **Insider Space** | Non-public access, social proof required, closed group — the back room | Ring access visibility, trusted social network | Guild/cooperative insider, exclusive supplier | Close friend group, earned intimacy depth | Faction HQ, party inner circle | **Target's personal protection circle — and the gap where access might exist** |
|
||||
| **Economic Node** | Visible economic activity, pricing signals, transaction infrastructure | Evidence trail — money follows crime | Primary profit opportunity, arbitrage, deals | Shared activity creates natural encounter | Economic leverage over actors who control resources | **Contract source (who pays for the job), payment receipt, opposition's funding** |
|
||||
| **Encounter Corridor** | NPC daily movement route, traversal path, corridor with observable foot traffic | NPC observation, pattern detection | Supply chain visibility, route control | Daily routine overlap — the street the target of affection always takes at 3pm | Visibility territory, patrol routes, political march | **Target's known route — where and when they're predictably exposed** |
|
||||
|
||||
### 1.2 Assassin-Specific Spatial Guarantees
|
||||
|
||||
The 7 archetypes don't fully cover assassin requirements. The assassin needs additional guarantees that don't reduce to any single archetype:
|
||||
|
||||
**Guarantee A-1: Elevated Vantage Position**
|
||||
Every Full-complexity district must contain at least one position at z-level 1 or above that has a clear LOS cone covering the primary Traffic Chokepoint. This isn't a separate zone — it's a spatial property of the chokepoint's adjacent structures.
|
||||
|
||||
*Other playstyle uses:* Investigation (counter-surveillance vantage), Dating Sim (Ozzie's "vertical surprise — going up when I didn't expect to"), Political (speaking platform that can address the crowd).
|
||||
|
||||
**Guarantee A-2: Egress Multiplicity**
|
||||
Every Entry Point (district boundary access point) must have at least 2 independent egress routes that don't share a secondary chokepoint. "Independent" means: if one route is blocked by an NPC or physical obstacle, the other remains viable. This is a connectivity property of the Encounter Corridor graph.
|
||||
|
||||
*Other playstyle uses:* Investigation (if blown, you need another way out), Tycoon (redundant supply routes), Dating Sim (the ability to leave a scene with dignity).
|
||||
|
||||
**Guarantee A-3: Temporal Opacity Window**
|
||||
Every Full-complexity district must have at least one period in each day-cycle (D-031) where the Traffic Chokepoint's observer density drops below the "crowd cover" threshold. Mechanically: a phase of the day when the chokepoint has fewer than N active NPCs in observation range. This is determined at NPC schedule generation time.
|
||||
|
||||
*Other playstyle uses:* Investigation (dead-of-night investigation access), Tycoon (off-hours deals), Dating Sim (Ozzie's ritual gathering — you know they'll be here at 3pm).
|
||||
|
||||
**Guarantee A-4: Non-Institutional Access Route**
|
||||
At least one path from district entry to the Social Hub must not pass through any access tier above `Semi-Private`. A district where every path to the gathering place requires crossing an institutional checkpoint is inhospitable to any non-credentialed character — including all playstyles.
|
||||
|
||||
*Note: This is not assassination-specific — it's an accessibility guarantee that serves all non-credentialed characters.*
|
||||
|
||||
---
|
||||
|
||||
## 2. Universal vs. Conditional Guarantee System
|
||||
|
||||
**The lead directive correction:** Not every place serves every playstyle. A farmstead doesn't need an assassination sightline.
|
||||
|
||||
This is the right correction, and it resolves a design tension that's been implicit since Round 1. Let me build the formal model.
|
||||
|
||||
### 2.1 Two-Axis Classification
|
||||
|
||||
Every guarantee is classified on two axes:
|
||||
|
||||
**Axis 1: District Complexity Threshold**
|
||||
- `Universal`: applies to all inhabited districts regardless of complexity
|
||||
- `Full-only`: applies to Full-complexity districts only
|
||||
- `Conditional`: applies when specific district parameters (terrain, drama density, playstyle context) warrant
|
||||
|
||||
**Axis 2: Terrain-Agnostic vs. Terrain-Aware**
|
||||
- `Terrain-agnostic`: the guarantee applies regardless of setting geometry (Station/Urban/Rural/Maritime/etc.)
|
||||
- `Terrain-aware`: the guarantee has a terrain-specific expression (a Traffic Chokepoint in wilderness is a mountain pass, not a corridor)
|
||||
|
||||
### 2.2 The Guarantee Tiers
|
||||
|
||||
**TIER 1: Universal Guarantees (all inhabited districts, any terrain)**
|
||||
|
||||
These are not negotiable even for a Minimal-complexity backwater. They're properties of any space where humans live and move.
|
||||
|
||||
| Guarantee | Rationale | Terrain expression |
|
||||
|---|---|---|
|
||||
| **Social Hub** | Any inhabited space has somewhere people gather. Even in a village of 8. | Station: bar. Urban: market. Rural: community hall. Maritime: the dock. Wilderness: the campfire. |
|
||||
| **Informal Zone** | Everywhere humans live has grey-area space that institutional authority doesn't fully penetrate. | Station: maintenance corridor. Urban: back alley. Rural: the back of the barn. Maritime: below deck. Wilderness: the whole thing. |
|
||||
| **Encounter Corridor** | Any connected place has routes people use regularly. Even a settlement of 8 has a path people walk every day. | Station: main transit spine. Urban: high street. Rural: farm road. Maritime: the dock approach. Wilderness: trail. |
|
||||
|
||||
**TIER 2: Full-Complexity Guarantees (Full-complexity districts, terrain-aware)**
|
||||
|
||||
These require sufficient population and infrastructure to produce. They apply when the district is at `ComplexityTier::Full`.
|
||||
|
||||
| Guarantee | Terrain-agnostic? | Terrain-specific expression where needed |
|
||||
|---|---|---|
|
||||
| **Traffic Chokepoint** | Terrain-aware | Urban/Station: architectural chokepoint. Non-urban: natural bottleneck (mountain pass, harbor mouth, river ford, valley entrance) |
|
||||
| **Institutional Space** | Terrain-aware | Urban/Station: formal building with access control. Rural: may be absent (zero faction presence) — if absent, the guarantee is waived. Wilderness: always absent. |
|
||||
| **Insider Space** | Terrain-agnostic | Exists wherever there is a community. The "insider" social geography scales with population size. |
|
||||
| **Economic Node** | Terrain-aware | Urban/Station: commercial infrastructure. Rural: market day, granary, water allocation point. Maritime: harbor trading post. Wilderness: resource extraction site (not economic in the formal sense — gameplay differently). |
|
||||
|
||||
**TIER 3: Conditional Guarantees (apply based on playstyle-context and complexity)**
|
||||
|
||||
These don't apply universally — they activate when the district's complexity, drama density, and active playstyle warrant them.
|
||||
|
||||
| Guarantee | Condition |
|
||||
|---|---|
|
||||
| **Elevated Vantage Position** (A-1) | Full-complexity districts with vertical architecture (z_levels ≥ 2) |
|
||||
| **Egress Multiplicity** (A-2) | Full-complexity districts; applies in all terrains but particularly critical in enclosed settings (Station, Maritime) |
|
||||
| **Temporal Opacity Window** (A-3) | Full-complexity districts with defined NPC schedules |
|
||||
| **Economic Asymmetry Signal** | Full-complexity districts with active economic function (not subsistence/transit-only) |
|
||||
| **Temporal Encounter Window** | Full-complexity districts with active social sites and D-031 day-phase integration |
|
||||
| **Power Gradient Visibility** | Full-complexity districts with faction presence tier ≥ Standard |
|
||||
|
||||
### 2.3 The Guarantee Audit: Conditional Logic
|
||||
|
||||
The 11-check audit from Round 2 needs to be conditional-aware. Here's the revised `GuaranteeAuditResult` logic:
|
||||
|
||||
```
|
||||
For each district being audited:
|
||||
|
||||
1. Check TIER 1 (all inhabited districts):
|
||||
[ ] Social Hub present?
|
||||
[ ] Informal Zone present?
|
||||
[ ] Encounter Corridor present?
|
||||
|
||||
2. IF complexity == Full OR Moderate:
|
||||
[ ] Traffic Chokepoint present (terrain-appropriate form)?
|
||||
[ ] Insider Space present?
|
||||
|
||||
3. IF complexity == Full:
|
||||
[ ] Institutional Space present? (WAIVED if faction_presence == Absent everywhere)
|
||||
[ ] Economic Node present? (WAIVED if economic_function == Subsistence or Wilderness)
|
||||
|
||||
4. IF complexity == Full AND z_levels >= 2:
|
||||
[ ] Elevated Vantage present?
|
||||
|
||||
5. IF complexity == Full AND npc_schedule_density >= threshold:
|
||||
[ ] Temporal Opacity Window exists in at least one day-phase?
|
||||
|
||||
6. IF complexity == Full AND faction_presence >= Standard:
|
||||
[ ] Power Gradient Visibility present?
|
||||
|
||||
7. IF complexity == Full AND economic_function is not Subsistence/Wilderness:
|
||||
[ ] Economic Asymmetry Signal present?
|
||||
```
|
||||
|
||||
A Minimal-complexity farmstead district: only 3 checks. A Full-complexity urban hub: up to 11 checks. The audit scales with district class. **No false positives from applying urban guarantees to rural fields.**
|
||||
|
||||
### 2.4 The Assassin Lens as a Superposition
|
||||
|
||||
Critically: the assassin doesn't add new spaces to the district. The assassin reads EXISTING spaces differently. The Encounter Corridor is the target's known route. The elevated position above the Traffic Chokepoint is the vantage. The Informal Zone is the staging ground.
|
||||
|
||||
The generator doesn't tag spaces "this is for assassins." The generator produces spaces with certain properties (elevated, overlooking chokepoint, low observation) and the assassin system identifies which spaces satisfy which operational requirements. This is Miri's core insight: one information landscape, multiple lenses.
|
||||
|
||||
**Implication for the guarantee audit:** The assassin-specific guarantees (A-1, A-2, A-3) are NOT new checks to add to the 11. They're DERIVED PROPERTIES from the existing spatial configuration. If the Full-complexity district has an elevated vantage position, the assassin has a sightline. If it has route multiplicity, the assassin has egress options. The audit verifies spatial properties; the playstyle systems decide what to do with them.
|
||||
|
||||
---
|
||||
|
||||
## 3. Destructible Boundaries: Generator Rules
|
||||
|
||||
**The question:** What does the generator put behind a wall the player destroys?
|
||||
|
||||
Let me break down what "behind a wall" means in a top-down tile grid.
|
||||
|
||||
### 3.1 Every Tile Is Pre-Generated
|
||||
|
||||
The key insight: the game is a top-down tile grid. A 64×64 chunk is a 64×64 array of tiles. Every tile in that array exists in the data structure, whether the player has access to it or not. **Walls don't create holes in the tile data — they're a tile TYPE that prevents movement and blocks LOS.**
|
||||
|
||||
"What's behind the wall" is already in the `ChunkData`. The question is what TILE TYPE is on the far side of the wall tile, and whether that tile has ever been prepared for player-facing content.
|
||||
|
||||
### 3.2 Three Wall-Behind States
|
||||
|
||||
The generator must produce one of three states for every wall tile's reverse side:
|
||||
|
||||
**Type 1: Structural Void**
|
||||
`TileBehind::StructuralFill`
|
||||
|
||||
Behind this wall is structural material — load-bearing concrete, pressure bulkhead, foundation column. No space. Blowing it open produces rubble and debris at best; at worst, triggers a structural instability cascade affecting adjacent tiles.
|
||||
|
||||
Generator marks these at block planning time based on building structural logic:
|
||||
- Outer walls of a building are always `StructuralFill` on the exterior face
|
||||
- Load-bearing interior walls (every 4th wall in a standard building grid) are `StructuralFill`
|
||||
- Pressure bulkheads in station environments (separating pressurized from vacuum) are `StructuralFill`
|
||||
|
||||
```rust
|
||||
enum TileBehindState {
|
||||
/// No space. Structural material. Breaching is possible but triggers consequences.
|
||||
StructuralFill {
|
||||
material: StructuralMaterial,
|
||||
stability_impact: f32, // how much this wall contributes to building structural integrity
|
||||
},
|
||||
/// A real room that has no player-facing access route in normal play.
|
||||
/// Pre-generated at chunk fill time with full content (may be empty, may have contents).
|
||||
HiddenRoom {
|
||||
room_seed: u64,
|
||||
fill_tag: String, // what kind of room this is
|
||||
},
|
||||
/// Small interstitial void between structures — not a room, not structural.
|
||||
/// A 1-4 tile gap. Can be entered, has nothing in it.
|
||||
Interstitial {
|
||||
width_tiles: u8,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
**Type 2: Hidden Room**
|
||||
`TileBehind::HiddenRoom`
|
||||
|
||||
Behind this wall is a real room that the chunk fill has generated as a complete space — floor, potential contents, potential NPC spawn — but which has no door or access point opening onto the player's side. The room is pre-generated whether the player ever reaches it or not (idempotent from seed).
|
||||
|
||||
This is the mechanical foundation for Ozzie's "place I'm not supposed to be." The generator guarantees:
|
||||
|
||||
> **Every Full-complexity district must contain at least one Hidden Room zone accessible only via breach (no door, no vent, no official access point on the player's side of the wall).**
|
||||
|
||||
Generator implementation:
|
||||
- At chunk fill time, `access_point_count: u8 = 0` marks a `ChunkFillSpec` as breach-only
|
||||
- These are generated with full content — they're rooms that happen to have no door
|
||||
- Contents are seeded based on the room's social context: a private office adjacent to a Institutional Space might contain files; a storage room adjacent to an Informal Zone might contain contraband; a maintenance junction might contain infrastructure controls
|
||||
|
||||
Hidden rooms are how the generator produces secrets that aren't marked "this is a secret." They're just rooms without obvious doors. Players who blow through walls find them; players who don't, don't. No quest marker. Just space with contents and no apparent route.
|
||||
|
||||
**Type 3: Interstitial Void**
|
||||
`TileBehind::Interstitial`
|
||||
|
||||
The gap between two buildings that's 1-4 tiles wide — not a room, not structural. These are produced by the anti-grid techniques (Araminta's setback variation, irregular building footprints). They have nothing in them by default, though NPC procedural placement might use them as informal routes.
|
||||
|
||||
### 3.3 The Player-Facing Contract
|
||||
|
||||
The generator's destructible boundary contract:
|
||||
|
||||
1. **All tile data pre-exists.** Chunk fill generates EVERYTHING in the chunk, including rooms with no player-facing access points. Breaching a wall doesn't require on-the-fly generation.
|
||||
|
||||
2. **Structural walls are marked.** `TileFlag::LoadBearing` identifies walls that cause structural cascades when destroyed. The gameplay system reads this flag to determine breach consequences.
|
||||
|
||||
3. **Hidden rooms have real content.** The generator doesn't produce empty "dead space" behind walls (Ozzie's Generation Sin #3). If the space exists, it pays rent — even if rent is "a small maintenance junction with spare parts and a scratched message someone left on the wall."
|
||||
|
||||
4. **Breach access is a first-class access tier.** `AccessTier::BreachOnly` — a space that requires destructive entry. This is distinct from `Restricted` (which is passable with credentials) and `Insider` (which is passable with social trust).
|
||||
|
||||
### 3.4 Guarantee: At Least One Breach-Only Space per Full District
|
||||
|
||||
> **Guarantee: Every Full-complexity district must contain at least one zone classified `AccessTier::BreachOnly` — a space that has no non-destructive access route.**
|
||||
|
||||
This is the generator's structural implementation of Ozzie's Round 1 demand: "I need to find somewhere that feels like I wasn't meant to find it." The generator doesn't flag these as "secrets." It just makes rooms without doors and leaves the player to find them.
|
||||
|
||||
---
|
||||
|
||||
## 4. Vertical Scale: Multi-Z Architecture
|
||||
|
||||
**The question:** How does a 50-floor skyscraper emerge from the generator? The current 3 z-level model works for station environments. What about planet-side cities with tall buildings?
|
||||
|
||||
### 4.1 What Vertical Means in a Top-Down Game
|
||||
|
||||
First, the mechanical reality: this is a top-down 2D game. The player never sees a cross-section of a building. They see ONE horizontal slice at a time — the floor they're on. Transitioning between floors means traversing a stairwell or lift (which is effectively a corridor connecting two separate map states).
|
||||
|
||||
So "50 floors" doesn't mean the player sees 50 floors simultaneously. It means there are 50 distinct horizontal-slice states the player can transition between via vertical corridors. Each floor is a 2D map. Vertical scale is about the NUMBER of distinct horizontal states and the CONNECTIVITY between them.
|
||||
|
||||
### 4.2 Z-Bands: Grouping Floors into Generator Units
|
||||
|
||||
The generator doesn't need to model every floor independently at the skeleton stage. It models **z-bands** — groups of floors with similar social function. The social content changes at z-band boundaries, not floor-by-floor.
|
||||
|
||||
A 50-floor skyscraper might have 4 z-bands:
|
||||
- **Z-band 0** (floors 1-5): Ground-level commercial/public. Full public access.
|
||||
- **Z-band 1** (floors 6-20): Office/institutional. Semi-private access tier.
|
||||
- **Z-band 2** (floors 21-45): Upper office/restricted functions. Insider/restricted access tier.
|
||||
- **Z-band 3** (floors 46-50): Executive/penthouse. Restricted/breach-only access tier.
|
||||
|
||||
Each z-band is generated as an independent horizontal layer with its own:
|
||||
- `ZoneType` and zone palette
|
||||
- Access tier (the vertical gradient runs highest-to-most-restricted as you go up)
|
||||
- NPC population subset from the district roster
|
||||
- Social sites (a z-band 0 might have a lobby bar; z-band 2 might have a boardroom social site)
|
||||
- Internal floor layout (Phase 2 chunk fill generates each floor's tiles)
|
||||
|
||||
### 4.3 Multi-Block Reservation for Tall Structures
|
||||
|
||||
Tall buildings use `MultiBlockReservation` — the same mechanism that handles large horizontal structures — extended to include `vertical_extent`:
|
||||
|
||||
```rust
|
||||
struct MultiBlockReservation {
|
||||
/// Which blocks this structure occupies (horizontal footprint)
|
||||
block_coords: Vec<(u8, u8)>,
|
||||
|
||||
/// NEW: Vertical extent in z-bands
|
||||
z_band_count: u8,
|
||||
|
||||
/// NEW: Height in visual/sim floors (for rendering and collision)
|
||||
floor_count: u8,
|
||||
|
||||
/// Structure type
|
||||
structure_type: MultiBlockStructureType,
|
||||
|
||||
/// Social site hosted (may span multiple z-bands)
|
||||
hosted_sites: Vec<SocialSiteId>,
|
||||
|
||||
/// NEW: Per-z-band zone assignment
|
||||
z_band_zones: Vec<ZoneDefinition>,
|
||||
|
||||
/// NEW: Vertical corridor spines (lifts, stairs, shafts)
|
||||
vertical_corridors: Vec<VerticalCorridorSpec>,
|
||||
}
|
||||
|
||||
struct VerticalCorridorSpec {
|
||||
/// Which blocks contain this corridor (may be 1 block or span multiple)
|
||||
block_coords: Vec<(u8, u8)>,
|
||||
|
||||
/// Which z-bands this corridor connects
|
||||
z_bands_connected: Vec<u8>,
|
||||
|
||||
/// Access tier required to use this corridor
|
||||
access_tier: AccessTier,
|
||||
|
||||
/// Type (lift, stairwell, service shaft, emergency escape)
|
||||
corridor_type: VerticalCorridorType,
|
||||
}
|
||||
```
|
||||
|
||||
### 4.4 Vertical Access Tier Gradient
|
||||
|
||||
The access tier gradient that Araminta defined running inward from street face — public → semi-private → restricted — has a VERTICAL analog:
|
||||
|
||||
**Vertical gradient:** ground level = most public; upper levels = most restricted
|
||||
|
||||
This is a spatial law that players understand intuitively (penthouses are exclusive; lobbies are open). The generator enforces it: `AccessTier` must be monotonically non-decreasing as z-band index increases, with at least one tier step between z-bands.
|
||||
|
||||
The bottom z-band can be `Public`. The top z-band will typically be `Restricted` or `BreachOnly`.
|
||||
|
||||
**Assassin implication:** Getting to the top of a tall building is an access-tier challenge. The vertical corridor is a chokepoint. The lift is a bottleneck. The stairwell is monitored. Getting UP is the operational problem, more than getting to the target once you're there.
|
||||
|
||||
### 4.5 The Roof as Mandatory Discovery Zone
|
||||
|
||||
> **Guarantee: Every tall structure (z_band_count ≥ 3) must have a roof zone classified `AccessTier::Insider` or `AccessTier::BreachOnly` — accessible by a non-obvious route.**
|
||||
|
||||
The roof isn't a separate district. It's the top of the `MultiBlockReservation`, generated as an additional z-band with open-sky tile properties. The roof:
|
||||
- Has dramatically extended LOS (no walls, elevated position over surrounding blocks)
|
||||
- Is the highest vantage point in the district
|
||||
- Has no official occupants (its own `HiddenRoom` equivalent at building scale)
|
||||
- Must be reachable — but the route is non-obvious (service access, emergency hatch, window ledge)
|
||||
|
||||
The roof is Ozzie's "vertical surprise that reorients my mental map" at building scale.
|
||||
|
||||
### 4.6 What Stays the Same
|
||||
|
||||
The 4-level spatial hierarchy (chunk/block/district/system) doesn't change. Tall buildings are multi-block, multi-z-band structures within an existing district. The chunk size (64×64 sim tiles) doesn't change — each floor of a building is composed of chunks. The streaming model doesn't change — the player's 3×3 loading grid operates in the current z-band, with adjacent z-bands cached.
|
||||
|
||||
---
|
||||
|
||||
## 5. Dynamic World Modification: Delta Layer Model
|
||||
|
||||
**The question:** Gas main explosion in a district the player already visited. Should the generator re-render affected chunks?
|
||||
|
||||
### 5.1 Two Sources of World State
|
||||
|
||||
The core architectural distinction:
|
||||
|
||||
- **Generator State**: The seed-derived, deterministic foundation. `PreparedDistrict` + `ChunkData`. This is IMMUTABLE after generation. Its determinism guarantee is the game's foundation.
|
||||
- **World State Deltas**: Post-generation modifications. Events, player actions, gameplay consequences. These live in a separate structure layered on top of Generator State.
|
||||
|
||||
The gas explosion doesn't change what the generator produced. It creates a `WorldStateDelta` that describes the explosion's effect. When rendering or gameplay processes chunk (x,y), it applies:
|
||||
|
||||
1. Generator `ChunkData` (base state, always deterministic from seed)
|
||||
2. All `WorldStateDelta` entries for this chunk (ordered by tick timestamp)
|
||||
|
||||
Result: the chunk looks like the generated version plus the applied deltas. **The generator never re-runs. The delta layer carries the modification.**
|
||||
|
||||
### 5.2 The Delta Structure
|
||||
|
||||
```rust
|
||||
struct WorldStateDelta {
|
||||
/// Which chunk this delta affects
|
||||
chunk: ChunkCoords,
|
||||
|
||||
/// When this happened (simulation tick)
|
||||
timestamp: SimTick,
|
||||
|
||||
/// What changed
|
||||
delta_type: DeltaType,
|
||||
|
||||
/// Source of the change (gameplay consequence, NPC action, Tier 1 module event, etc.)
|
||||
source: DeltaSource,
|
||||
}
|
||||
|
||||
enum DeltaType {
|
||||
/// Structural damage from explosion, combat, decay
|
||||
StructuralDamage {
|
||||
tiles: Vec<TileCoord>,
|
||||
damage_level: DamageLevel, // Scorched, Damaged, Destroyed, Collapsed
|
||||
},
|
||||
|
||||
/// A wall has been breached (player or NPC action, explosion)
|
||||
WallBreached {
|
||||
wall_tile: TileCoord,
|
||||
breach_type: BreachType, // Blown, Forced, Cut
|
||||
},
|
||||
|
||||
/// A door's state has changed persistently
|
||||
DoorStateChanged {
|
||||
door_id: DoorId,
|
||||
state: DoorState, // Open, Closed, Locked, Breached, Destroyed
|
||||
},
|
||||
|
||||
/// An object has been added or removed
|
||||
ObjectModified {
|
||||
position: TileCoord,
|
||||
modification: ObjectModification, // Added, Removed, Damaged, Moved
|
||||
object_id: ObjectId,
|
||||
},
|
||||
|
||||
/// A tile's traversability changed (collapse reveals new space, explosion creates gap)
|
||||
TileTypeChanged {
|
||||
position: TileCoord,
|
||||
new_type: TileType,
|
||||
},
|
||||
|
||||
/// An access tier changed due to gameplay events (lockdown, faction capture)
|
||||
AccessTierChanged {
|
||||
zone: ZoneId,
|
||||
new_tier: AccessTier,
|
||||
expires_at: Option<SimTick>, // NULL = permanent
|
||||
},
|
||||
|
||||
/// An NPC position has been permanently altered (killed, arrested, moved away)
|
||||
NpcRemoved {
|
||||
npc_id: NpcId,
|
||||
reason: NpcRemovalReason,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 5.3 Handling Large-Scale Events
|
||||
|
||||
For minor events (one gas explosion, a door being kicked in): the `WorldStateDelta` layer handles it cleanly. Tens to hundreds of tile modifications. Lightweight.
|
||||
|
||||
For major events (fire that guts an entire block, a faction takeover that completely rebuilds a zone): the delta layer becomes expensive. Many thousands of tile modifications. For these cases:
|
||||
|
||||
**Soft Re-Generation**: Re-run Phase 2 for affected chunks with an event-modified seed:
|
||||
|
||||
```
|
||||
event_chunk_seed = original_chunk_seed XOR event_seed
|
||||
```
|
||||
|
||||
This produces a consistent, deterministic "post-event" state. The new chunk state is:
|
||||
- Different from the generator's original output (the event happened)
|
||||
- Still deterministic (reproducible from seed + event record)
|
||||
- Cached and saved as a new `ChunkData` snapshot
|
||||
|
||||
The save file maintains a record of which chunks have been "soft re-generated" and their event-modified seeds. This preserves:
|
||||
- **Determinism**: same events → same post-event state
|
||||
- **Persistence**: player returns to find the same damage
|
||||
- **Memory**: the player can understand what was there before (NPCs remember; environmental evidence remains)
|
||||
|
||||
### 5.4 World Modification as Gameplay Consequence
|
||||
|
||||
The delta layer is not just for disaster events. It handles the full range of world modification:
|
||||
|
||||
| Player action | Delta type |
|
||||
|---|---|
|
||||
| Kick down a door | `WallBreached` or `DoorStateChanged` |
|
||||
| Kill an NPC | `NpcRemoved` |
|
||||
| Plant evidence | `ObjectModified::Added` |
|
||||
| Cause an explosion | `StructuralDamage` + `WallBreached` x N |
|
||||
| Commission faction clears a district | `AccessTierChanged` (district-wide) |
|
||||
| Smuggling ring abandons a stash location | `ObjectModified::Removed` x N + `AccessTierChanged` |
|
||||
|
||||
The game's consequence systems write `WorldStateDelta` entries. The rendering and gameplay systems read them when processing chunks. **The generator never needs to know that any of this happened.**
|
||||
|
||||
### 5.5 What the Generator Guarantees vs. What the Delta Layer Guarantees
|
||||
|
||||
| Property | Generator guarantees | Delta layer maintains |
|
||||
|---|---|---|
|
||||
| Spatial structure | Always available | May be modified by events |
|
||||
| NPC roster | Generated deterministically | May shrink as NPCs are removed |
|
||||
| Access tiers | Defined by district skeleton | May change due to faction events |
|
||||
| Room contents | Generated at chunk fill time | May be modified by player/NPC actions |
|
||||
| Tile data | Deterministic from seed | May be overwritten by delta events |
|
||||
|
||||
The generator produces the world as it was. The delta layer describes what has happened to it since. The player experiences the composition.
|
||||
|
||||
---
|
||||
|
||||
## 6. Reconcile SignificanceTier / ComplexityTier / DramaDensity
|
||||
|
||||
Qatux correctly flagged these three overlapping concepts. My Round 2 `SignificanceTier` introduced a redundancy. Here is the clean two-parameter model.
|
||||
|
||||
### 6.1 The Two-Parameter Model
|
||||
|
||||
**I am retiring `SignificanceTier`.** It conflates two orthogonal properties and creates confusion with `ComplexityTier`. Here's the correct model:
|
||||
|
||||
| Parameter | Type | When Set | What It Controls |
|
||||
|---|---|---|---|
|
||||
| **`ComplexityTier`** | Static (generator) | Phase 1 Pre-Pipeline | CAPACITY: what the generator produces |
|
||||
| **`DramaDensity`** | Dynamic (storyteller) | Gameplay, Storyteller | UTILIZATION: what the Storyteller fires |
|
||||
|
||||
These answer different questions:
|
||||
- `ComplexityTier` answers: "What kind of district is this?"
|
||||
- `DramaDensity` answers: "What is happening in this district right now?"
|
||||
|
||||
### 6.2 ComplexityTier (Static, Generator-Determined)
|
||||
|
||||
```rust
|
||||
enum ComplexityTier {
|
||||
/// Full social architecture. 7+ archetypes. 20-80+ NPCs.
|
||||
/// All Tier 1 and Tier 2 guarantees apply.
|
||||
/// Supports: all playstyles at full depth.
|
||||
Full,
|
||||
|
||||
/// Moderate social architecture. 3-5 archetypes. 8-20 NPCs.
|
||||
/// Tier 1 guarantees + Traffic Chokepoint + Insider Space.
|
||||
/// Supports: all playstyles at reduced depth.
|
||||
Moderate,
|
||||
|
||||
/// Minimal social architecture. 1-2 archetypes. 1-8 NPCs.
|
||||
/// Tier 1 guarantees only.
|
||||
/// Supports: background world texture; Ozzie's "density contrast" filler.
|
||||
Minimal,
|
||||
|
||||
/// No social architecture. 0 archetypes. 0 NPCs.
|
||||
/// No guarantees. Pure terrain and traversal.
|
||||
Empty,
|
||||
}
|
||||
```
|
||||
|
||||
**ComplexityTier is determined at Phase 1 Stage 0 (Pre-Pipeline).** It's derived from:
|
||||
- World network position (hub nodes → Full; remote periphery → Minimal/Empty)
|
||||
- Setting geometry (Urban/Station → usually Full; Wilderness → usually Empty)
|
||||
- Storyteller pre-seeding (the Storyteller can override the default for a seed's purposes)
|
||||
|
||||
### 6.3 DramaDensity (Dynamic, Storyteller-Controlled)
|
||||
|
||||
```rust
|
||||
/// Drama Density: what the Storyteller is firing in this district right now.
|
||||
/// This is NOT a generator parameter — it's a runtime game state.
|
||||
enum DramaDensity {
|
||||
/// No Tier 1 modules active. Social fabric stable.
|
||||
/// Backwater guarantee: the Storyteller will not fire modules here.
|
||||
Zero,
|
||||
|
||||
/// One Tier 1 module active at low intensity, or mundane triangle fully active.
|
||||
Low,
|
||||
|
||||
/// One Tier 1 module + active mundane triangle pressure + economic tension.
|
||||
/// Sova Transit District in steady state.
|
||||
Medium,
|
||||
|
||||
/// Multiple modules active, contested faction presence, elevated pressure.
|
||||
High,
|
||||
|
||||
/// Maximum: multiple modules, faction conflict, historical disruption, elevated entanglement.
|
||||
/// Should be rare. Must feel rare. The Storyteller deploys this sparingly.
|
||||
Flashpoint,
|
||||
}
|
||||
```
|
||||
|
||||
### 6.4 The Critical Relationship: Capacity vs. Utilization
|
||||
|
||||
**The Storyteller cannot fire DramaDensity above the ComplexityTier's capacity ceiling.**
|
||||
|
||||
| ComplexityTier | Maximum DramaDensity | Why |
|
||||
|---|---|---|
|
||||
| Full | Flashpoint | Has the population density and social infrastructure to support it |
|
||||
| Moderate | High | Has enough NPCs for conflict, but not full-ring infrastructure |
|
||||
| Minimal | Low | Very few NPCs; even a single active module strains the social fabric |
|
||||
| Empty | Zero | No NPCs, no modules possible |
|
||||
|
||||
A `Minimal`-complexity village can have `Low` DramaDensity — a single personal drama, a domestic dispute with outsider consequences. It cannot have a full political crisis (no faction infrastructure) or a major smuggling ring (too few people to sustain it). The Storyteller respects this ceiling.
|
||||
|
||||
**The "false backwater" (Nigel's concept) is now expressible:**
|
||||
|
||||
> District: `ComplexityTier::Minimal`, `DramaDensity::Zero` — appears to be a quiet unremarkable stop.
|
||||
> BUT: the district is a node in a Tier 1 module (ring transit route) that the Storyteller has flagged as active but not yet surfaced in this location.
|
||||
> RESULT: The tycoon who investigates finds the module. The detective who passes through and doesn't look, doesn't. Same ComplexityTier. Same DramaDensity. Different player perception.
|
||||
|
||||
The false backwater doesn't require high complexity OR active drama. The Tier 1 module exists at a meta-level; the district itself is genuinely quiet. The module activates in response to the player's investigative actions, not as a property of the district.
|
||||
|
||||
### 6.5 Final Disposition
|
||||
|
||||
| Round 2 concept | Round 3 status |
|
||||
|---|---|
|
||||
| `SignificanceTier` (Gestalt) | **RETIRED.** Absorbed into ComplexityTier + DramaDensity + network position metadata |
|
||||
| `ComplexityTier` (Tyre) | **RETAINED.** Static, generator-determined capacity parameter |
|
||||
| `DramaDensity` (Nigel) | **PROMOTED.** Dynamic, storyteller-controlled utilization parameter — formally added to game state |
|
||||
|
||||
---
|
||||
|
||||
## 7. Triangle Purpose Taxonomy (OQ-R3-B: Resolved)
|
||||
|
||||
This is my open question from Round 2. Here's the resolution.
|
||||
|
||||
### 7.1 The Purpose Enum
|
||||
|
||||
```rust
|
||||
/// Why does this triangle exist, and which playstyle activates it?
|
||||
/// Note: a triangle can serve multiple purposes simultaneously.
|
||||
enum TrianglePurpose {
|
||||
/// Three NPCs in conflicting interests around hidden criminal/grey activity.
|
||||
/// Activated by: investigation-related Tier 1 modules, detective archetype engagement.
|
||||
Investigation,
|
||||
|
||||
/// Three NPCs in conflicting economic interests (market, trade, resources, contracts).
|
||||
/// Activated by: tycoon playstyle interaction, economic Tier 1 modules.
|
||||
Economic,
|
||||
|
||||
/// Three NPCs in romantic, family, or social competition.
|
||||
/// Activated by: dating sim playstyle interaction, social-drama modules.
|
||||
/// SAME mechanical structure as Investigation triangle — different content tags.
|
||||
Social,
|
||||
|
||||
/// Three NPCs in institutional power contest (positions, authority, faction allegiance).
|
||||
/// Activated by: political playstyle interaction, faction modules.
|
||||
Political,
|
||||
|
||||
/// Three NPCs structurally relevant to an assassination context:
|
||||
/// the target, their protector/guardian, and the informant or witness.
|
||||
/// Activated by: contract modules, assassination target proximity.
|
||||
Tactical,
|
||||
|
||||
/// Background social tension — never "activated" as player-facing primary drama.
|
||||
/// Workplace rivalries, family disputes, neighborhood dynamics.
|
||||
/// The 50% mundane from D-029. ALWAYS present in any inhabited district.
|
||||
/// Multiple playstyles can NOTICE these but they are not primary drama drivers.
|
||||
Mundane,
|
||||
}
|
||||
```
|
||||
|
||||
### 7.2 Rules for Triangle Composition per District
|
||||
|
||||
- Every Full-complexity district: at minimum 2 triangles, at least 1 `Mundane`
|
||||
- Every Full-complexity district: at minimum 1 non-Mundane triangle whose purpose matches the district's primary gameplay context (derived from district_type and society_profile)
|
||||
- Cross-template triangles (D-024): can span purposes (a `Social` triangle can have an `Economic` dimension — the romantic rival is also a business competitor)
|
||||
|
||||
### 7.3 Tactical Triangle and Assassination Gameplay
|
||||
|
||||
Every potential assassination target NPC is the central node of a `Tactical` triangle:
|
||||
- **Node 1 (Target)**: the NPC with the contract on them
|
||||
- **Node 2 (Protector)**: whoever guards/monitors/knows the target's movements — could be official security, a close friend, a suspicious colleague
|
||||
- **Node 3 (Informant/Witness)**: someone who has useful information about the target's pattern, OR someone who might witness and report the act
|
||||
|
||||
The generator guarantees: if a Tier 1 module with contract assassination potential is placed in a Full-complexity district, that district's triangle pool contains a `Tactical` triangle appropriately configured.
|
||||
|
||||
**Tyre's implementation question:** Does `TrianglePurpose` add meaningful complexity? My assessment: it's a simple `Vec<TrianglePurpose>` field on `TriangleTemplate`. The scenario instantiation system already needs to know which triangles to activate for a given module. This tag just makes that lookup explicit rather than inferential.
|
||||
|
||||
---
|
||||
|
||||
## 8. The Grid Breathing: A Gameplay Position
|
||||
|
||||
Ozzie is asking whether the block grid can rotate, whether streets can curve, whether two adjacent districts can have different orientations. This is primarily Tyre's technical question (D-094 is his to modify or defend). But from a gameplay systems perspective, here is my position:
|
||||
|
||||
**Araminta's seven anti-grid techniques are necessary but not sufficient.**
|
||||
|
||||
Here's why they're necessary: hiding the grid through visual means is cheap and effective for most players most of the time. Diagonal connectors, irregular setbacks, angled infrastructure, light territories — these work. I believe in them.
|
||||
|
||||
Here's why they're not sufficient alone: Ozzie will feel the skeleton. She's right. A systematic player who maps the district on paper will eventually see the 128m block grid. The visual camouflage produces "natural-feeling irregularity" within the grid, not "natural-feeling irregularity OF the grid."
|
||||
|
||||
**My recommendation to Tyre (for his Round 3):** The minimum viable intervention is not full non-rectilinear blocks — that's a major architectural change. The minimum viable intervention is:
|
||||
|
||||
1. **District-level rotation**: Allow districts to be placed at 45° to each other. The grid IS a grid, but adjacent districts can orient differently. A quarter-turn between two adjacent districts produces street angles that feel geological when the streets meet.
|
||||
|
||||
2. **Organic district edge**: Rather than a straight-line boundary between two districts, allow the boundary to follow a jagged line (within 1-2 block tolerance). The transition strip (Tyre's Round 2 solution) already gives us 2 boundary blocks of "neither district" — let that boundary zigzag rather than run straight.
|
||||
|
||||
These two interventions don't change the internal block grid. They change how grids MEET, which is where the visual seam is most dangerous. Ozzie is right that the seam will eventually show — but the seam appears most clearly at district boundaries, and that's what the transition strip is for.
|
||||
|
||||
**What I'm not asking Tyre to do:** Full WFC-style non-rectilinear districts with curved streets. That's V0.5+ territory if it's ever worth the implementation cost. The question for V0.1-V0.3 is whether the visual techniques plus boundary-level interventions get us to "player doesn't feel the grid on the 5th station." I believe they do with the boundary improvements.
|
||||
|
||||
---
|
||||
|
||||
## 9. Final Pipeline Architecture: Canonical Summary
|
||||
|
||||
Convergence from three rounds. This is the definitive pipeline statement.
|
||||
|
||||
```
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
PRE-PIPELINE (Static World Architecture)
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
|
||||
Master Seed (single, from Tyre §3)
|
||||
↓
|
||||
System Generation
|
||||
derives: star type, world count per system, gate connections
|
||||
↓
|
||||
Per-World Significance Assignment
|
||||
├── ComplexityTier: Full / Moderate / Minimal / Empty
|
||||
│ (derived from network position, setting geometry, world role)
|
||||
├── SettingGeometry: Station / Urban / Agricultural / Wilderness /
|
||||
│ Water / Transitional / Orbital
|
||||
└── DramaDensity ceiling: constrained by ComplexityTier
|
||||
(DramaDensity itself is set by Storyteller at runtime)
|
||||
|
||||
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
PHASE 1: WORLD PREP (Background, Async, ~50-500ms per district)
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
|
||||
Stage 1: Society Profile Assembly
|
||||
input: system_seed, world network position, SettingGeometry
|
||||
output: SocietyProfile (serde YAML → Rust struct, Tyre §4)
|
||||
produces: heritage blend, economic function/pressure, drift stage,
|
||||
faction presence, philosophical alignment, meridian coverage
|
||||
skipped for: Wilderness/Empty districts (no society)
|
||||
↓
|
||||
|
||||
Stage 2: District Skeleton Generation
|
||||
input: district_seed, SocietyProfile, ComplexityTier, SettingGeometry
|
||||
output: DistrictSkeleton (canonical struct — Tyre + Gestalt composite)
|
||||
produces:
|
||||
- Zoning (block types, access tiers)
|
||||
- Social site placement (D-025 templates, triangle topology)
|
||||
- Triangle pool (with TrianglePurpose tags — §7)
|
||||
- Multi-block reservations (horizontal + vertical extent — §4)
|
||||
- Vertical corridor spines (for tall structures — §4)
|
||||
- Corridor spines (Encounter Corridors + access points)
|
||||
- Zone palette assignment (Araminta's zone types)
|
||||
- Boundary descriptors (for edge bleed — Tyre §2)
|
||||
- Guarantee audit: conditional on ComplexityTier (§2)
|
||||
- Breach-only zones: at least 1 in Full-complexity (§3)
|
||||
↓
|
||||
VALIDATE spatial prerequisites (Tyre §6.1):
|
||||
check guarantees for this ComplexityTier + SettingGeometry
|
||||
adjust zoning if prerequisites not met
|
||||
check breach-only zone guarantee
|
||||
↓
|
||||
|
||||
Stage 3: Block Planning
|
||||
input: DistrictSkeleton, district_seed
|
||||
output: BlockPlan per block (Tyre §1.3)
|
||||
produces:
|
||||
- ChunkLayout (merge strategy, quarter layout)
|
||||
- Era assignment + era_modifications (with era_cause — §R1 resolved)
|
||||
- Edge contracts (Tyre's Option A)
|
||||
- Quarter form × function assignments (Araminta + Nigel composite)
|
||||
- TileBehindState for all walls in ChunkFillSpec (§3)
|
||||
- For tall structures: z_band_zones, z_band_access_tiers
|
||||
↓
|
||||
|
||||
Stage 4: NPC Population
|
||||
input: DistrictSkeleton (NPC role slots), district_seed
|
||||
output: NpcRoster (Tyre §1.1)
|
||||
produces:
|
||||
- 10-axis NPC generation per role slot
|
||||
- Triangle instantiation with TrianglePurpose (§7)
|
||||
- Entanglement marking (D-029: 20% entangled)
|
||||
- Spawn location preferences (flavor type → NPC pattern weight)
|
||||
- NPC schedule generation (DramaDensity-aware: opaque window timing — §1.2 A-3)
|
||||
↓
|
||||
|
||||
Stage 5: Transition Strip Generation
|
||||
input: adjacent PreparedDistrict pairs
|
||||
output: TransitionStrip per shared edge (Tyre §2.4)
|
||||
produces:
|
||||
- Palette blending (Araminta §1)
|
||||
- Access point alignment
|
||||
- Cultural bleed gradient (Miri §5)
|
||||
↓
|
||||
|
||||
OUTPUT: PreparedDistrict (DistrictSkeleton + BlockPlans + NpcRoster + SeedChain)
|
||||
TransitionStrips (shared between adjacent PreparedDistricts)
|
||||
|
||||
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
PHASE 2: LOCAL AREA GEN (On-Demand, Per Chunk, ~100-500ms)
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
|
||||
Player enters loading radius of chunk
|
||||
↓
|
||||
Chunk Fill (per chunk, derived chunk_seed)
|
||||
input: ChunkFillSpec (from BlockPlan), NpcRoster, SocietyProfile
|
||||
output: ChunkData (64×64 tile array)
|
||||
produces:
|
||||
- Architecture/terrain tiles from template tag
|
||||
- ALL tiles in chunk generated — including breach-only rooms (§3)
|
||||
- TileBehindState applied to wall tiles (§3)
|
||||
- Zone palette + era materials
|
||||
- Furniture from form × function matrix
|
||||
- NPC spawn points (flavor → NPC affinity weights applied)
|
||||
- LOS anchors (urban: walls/pillars; non-urban: trees/terrain features)
|
||||
- Edge contracts validated against loaded neighbors
|
||||
- Per-floor tile generation for tall structures (z-band-aware)
|
||||
↓
|
||||
OUTPUT: ChunkData (cached in memory, saved to save file)
|
||||
|
||||
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
WORLD STATE LAYER (Runtime, Post-Generation)
|
||||
═══════════════════════════════════════════════════════════════════
|
||||
|
||||
WorldStateDelta stream (managed by gameplay systems, not generator)
|
||||
├── StructuralDamage (explosions, combat, decay)
|
||||
├── WallBreached (player/NPC destructive action)
|
||||
├── DoorStateChanged (persistent door states)
|
||||
├── ObjectModified (loot, evidence, planted objects)
|
||||
├── TileTypeChanged (post-damage tile state)
|
||||
├── AccessTierChanged (faction events, lockdowns)
|
||||
└── NpcRemoved (killed, arrested, fled)
|
||||
|
||||
Applied to: ChunkData at render/gameplay-query time
|
||||
Large events: soft re-generation via (original_seed XOR event_seed) — §5.3
|
||||
|
||||
Rendering: Generator ChunkData + ordered WorldStateDeltas = current visible state
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. Canonical DistrictSkeleton Fields
|
||||
|
||||
Addressing D-R2-3 (Tyre and Gestalt adding fields independently). Here is the composite canonical field list for `DistrictSkeleton`. Tyre should author the final Rust struct; this is the field-level specification:
|
||||
|
||||
**Core (Tyre Round 1):**
|
||||
- `district_id: DistrictId`
|
||||
- `seed: u64`
|
||||
- `district_type: DistrictType`
|
||||
- `context: DistrictContext`
|
||||
- `blocks: [[BlockSkeleton; 4]; 4]`
|
||||
- `social_sites: Vec<SocialSitePlacement>`
|
||||
- `reservations: Vec<MultiBlockReservation>` (updated with vertical extent — §4)
|
||||
- `access_points: Vec<AccessPoint>`
|
||||
- `corridors: Vec<CorridorSpine>`
|
||||
- `z_levels: u8` → renamed `z_level_count: u8`
|
||||
- `zone_palette: Vec<ZoneDefinition>`
|
||||
|
||||
**Tyre Round 2 additions:**
|
||||
- `boundaries: DistrictBoundaries`
|
||||
- `society_profile: SocietyProfileRef`
|
||||
- `terrain: TerrainType`
|
||||
- `complexity: ComplexityTier`
|
||||
|
||||
**Gestalt Round 2 additions (revised):**
|
||||
- `setting_geometry: SettingGeometry` ← RETAINED
|
||||
- `guarantee_audit: GuaranteeAuditResult` ← RETAINED (now conditional-aware per §2)
|
||||
- `significance_tier` ← **REMOVED** (retired, absorbed into complexity + network position)
|
||||
|
||||
**Gestalt Round 3 additions:**
|
||||
- `vertical_structure: VerticalStructure` (Flat/Medium/Tall/Skyscraper — §4)
|
||||
- `breach_only_zones: Vec<ZoneId>` (at least 1 for Full-complexity — §3)
|
||||
|
||||
**Modification to SocialSitePlacement:**
|
||||
- `triangles: Vec<TriangleTemplate>` — each `TriangleTemplate` gains `purpose: Vec<TrianglePurpose>` (§7)
|
||||
|
||||
---
|
||||
|
||||
## 11. Open Questions for Implementation
|
||||
|
||||
The workshop has converged. Three architectural decisions should be formally recorded before implementation begins:
|
||||
|
||||
**OQ-R3-A (Grid rotation):** Tyre needs to decide whether district-level rotation is feasible within D-094 constraints, or whether boundary-level interventions (zigzag transition strip + diagonal infrastructure) are the full mitigation. From gameplay perspective: the boundary intervention is the minimum; full rotation would be ideal but is not required for V0.1-V0.3.
|
||||
|
||||
**OQ-R3-C (Wilderness informal zone):** For wilderness/maritime settings, the Informal Zone guarantee still applies (it's Tier 1 Universal), but its terrain expression is different. I've proposed `terrain_informal_zone` (cave, ravine, hidden cove, underdeck hold). Miri should confirm the cultural meaning.
|
||||
|
||||
**OQ-R3-D (Vessel architecture):** Miri's `bounded_mobile` flag for vessels needs architectural resolution before maritime DLC template authoring begins. Tyre's assessment should drive this.
|
||||
|
||||
**OQ-R3-E (Horizon as landmark):** Ozzie's requirement that water's edge is a reserved landmark. Araminta has the visual grammar; the question is whether the district skeleton generator needs an explicit `coastal_landmark_reservation` or whether the natural zone palette transition is sufficient. From guarantee perspective: the horizon should be a Tier 2 guarantee for any district with `TerrainType::Water` on one boundary — ensure it's generated, not filled.
|
||||
|
||||
---
|
||||
|
||||
*Gestalt — Round 3 complete. The pipeline is converged. Five directives addressed. Two redundant concepts retired. Tyre has the canonical struct reconciliation; Miri has the wilderness informal zone; Araminta has the horizon as landmark. These are the three remaining loose threads before architectural specification can be signed off.*
|
||||
|
||||
*Let me break down what this means for implementation sequencing: the delta layer (§5) can be stubbed trivially in V0.1; the breach-only zones (§3) are a chunk fill flag, not a pipeline change; the vertical scale (§4) only matters when a Full-complexity district has a tall structure reservation. None of these require V0.1 implementation. The pipeline is sound for V0.1 with stubs.*
|
||||
@@ -0,0 +1,440 @@
|
||||
# Generator Architecture Workshop — Round 4: Gestalt
|
||||
|
||||
**Role:** Systems Design / Gameplay Loop Requirements
|
||||
**Date:** 2026-02-27
|
||||
**Workshop:** Generator Architecture (#562)
|
||||
**Round:** 4 — Final Convergence
|
||||
|
||||
---
|
||||
|
||||
## Framing
|
||||
|
||||
Four tasks this round. Three open questions to close. One guarantee to amend. Twelve D-records to sign off. The lead has already settled the major architectural splits (WorldTier, entity-carried chunks, DramaDensity as runtime). My job is to close the remaining mechanical questions with concrete answers and lock the D-records.
|
||||
|
||||
Let me crack my knuckles.
|
||||
|
||||
---
|
||||
|
||||
## 1. OQ-R4-C: Assassination Difficulty Descriptor — Definitive Answer
|
||||
|
||||
Miri proposed `assassination_difficulty: low/medium/high/extreme` derived from:
|
||||
**observation density × information liquidity × aftermath engagement**
|
||||
|
||||
The question: where does it live? DistrictSkeleton, SocietyProfile, or computed on demand?
|
||||
|
||||
**Answer: Computed on demand. Never stored.**
|
||||
|
||||
Here's why this is the only defensible answer mechanically:
|
||||
|
||||
### The inputs are not all static
|
||||
|
||||
`assassination_difficulty` is a function of three input streams, only two of which are stable:
|
||||
|
||||
| Input stream | Source | Stability |
|
||||
|---|---|---|
|
||||
| Observation density | SocietyProfile (heritage root, institutional coverage) | Stable (generator output) |
|
||||
| Information liquidity | SocietyProfile (heritage root, settlement density) | Stable (generator output) |
|
||||
| Aftermath engagement | SocietyProfile (heritage root, faction presence) | Stable (generator output) |
|
||||
| Current NPC distribution | Storyteller state (DramaDensity, activated triangles) | **Dynamic** |
|
||||
| Spatial audit satisfaction | A-1 through A-4 guarantee flags | Stable (generator output) |
|
||||
| Active guard state | Simulation tick (faction events, alert level) | **Dynamic** |
|
||||
|
||||
The dynamic inputs mean a stored `assassination_difficulty` on any struct would be stale the moment the storyteller fires an event. A political crisis event spikes guard coverage; aftermath engagement goes from `medium` to `extreme`. A faction purge reduces community observation. The stored value would be wrong within a single session.
|
||||
|
||||
### Storing it causes incorrect player expectations
|
||||
|
||||
If the player sees an `assassination_difficulty` assessment that was baked at district generation, they're reading a stale number. The immersive sim promise is that the world responds. If the player INCREASED guard presence by burning down the safe house two districts over, the difficulty should reflect that. A stored value can't.
|
||||
|
||||
### The correct integration point
|
||||
|
||||
```
|
||||
assassination_difficulty =
|
||||
fn(
|
||||
society_profile: &SocietyProfile, // from SocietyProfile (stable)
|
||||
spatial_audit: &SpatialGuarantees, // from DistrictSkeleton (stable)
|
||||
active_state: &StorytellerState, // from runtime (dynamic)
|
||||
) -> DifficultyDescriptor
|
||||
```
|
||||
|
||||
This function is called:
|
||||
- At contract acceptance (player sees their pre-op assessment)
|
||||
- During pre-op planning phase (player can see how conditions change by day-phase)
|
||||
- NOT stored anywhere persistent
|
||||
|
||||
### What the D-record should specify
|
||||
|
||||
The D-record for `assassination_difficulty` should specify:
|
||||
1. The formula/weighting for the three input components
|
||||
2. The four output levels (`low/medium/high/extreme`) and their thresholds
|
||||
3. The integration points where the computation is invoked
|
||||
4. That it is **explicitly not a struct field on DistrictSkeleton or SocietyProfile** — it is a derived computation
|
||||
|
||||
The reason to canonicalize the formula in a D-record: other systems (NPC routing, faction responses, storyteller module selection) may want to consume the same computation. Having it defined once prevents different systems from computing it differently.
|
||||
|
||||
**Verdict: OQ-R4-C is resolved. No persistent storage. Computed on demand from SocietyProfile + spatial audit + runtime state.**
|
||||
|
||||
---
|
||||
|
||||
## 2. OQ-R4-F: Soft Re-Generation — The Concrete Example
|
||||
|
||||
Ozzie's principle: destruction must be *caused*, not *random*. The question: does `original_seed XOR event_seed` satisfy this, or do we need structured damage parameters?
|
||||
|
||||
I'm going to show you the actual output of both approaches for the same event. Then we'll know.
|
||||
|
||||
### The Scenario
|
||||
|
||||
**District X:** `district_seed = 0xA3F8C21B_7E64D509`
|
||||
- Heritage root: Iron (dense residential, workshop clusters)
|
||||
- Block layout: 4×4 grid, SMALL complexity
|
||||
- Block (2,3): Worker residential block, ~60 tiles
|
||||
- Floors 1-3: apartment units, corridor, shared kitchen
|
||||
- Sub-level (z=-1): utility tunnel, gas line infrastructure
|
||||
- Event: gas line rupture at (tile 2,3,38) at sim tick 47,302
|
||||
|
||||
---
|
||||
|
||||
### Approach A: XOR Reseeding
|
||||
|
||||
```
|
||||
event_seed = hash(EventType::GasExplosion, TilePosition(2,3,38), SimTick(47302))
|
||||
= 0x5B7E349A_1C82A7F3
|
||||
|
||||
reseeded = 0xA3F8C21B_7E64D509 XOR 0x5B7E349A_1C82A7F3
|
||||
= 0xF886F6816AE672FA
|
||||
```
|
||||
|
||||
The chunk fill re-runs on block (2,3) with `reseeded`. What does this produce?
|
||||
|
||||
| Tile position | Before | After (XOR reseed) |
|
||||
|---|---|---|
|
||||
| (2,3,1) — entry corridor | Corridor tile, N-S orientation | **Corridor tile, E-W orientation** |
|
||||
| (2,3,4) — apartment 1A | Residential interior | **Workshop space** (RNG diverged at zone assignment) |
|
||||
| (2,3,12) — shared kitchen | Kitchen fixture cluster | **Storage room** |
|
||||
| (2,3,38) — explosion origin | Gas line junction (sub-level) | **Open floor tile** |
|
||||
| (2,3,40) — adjacent unit | Apartment interior | **Wall** (block subdivision changed) |
|
||||
| (2,3,55) — block corner | Exterior wall | Exterior wall (stable, geometric) |
|
||||
|
||||
**The result:** The block has been *replaced*, not *damaged*. Tile (2,3,4) changed from a residential apartment to a workshop — not because the explosion destroyed residential use and workers moved in; the generator just made different decisions with the new seed. The zone assignment diverged at the first RNG call that governs zone type selection.
|
||||
|
||||
The explosion origin tile (2,3,38) lost its gas line fixture — but so did tiles across the entire block, because the fixture placement logic runs from a different RNG stream now. There's no spatial logic to the changes. The modifications don't radiate from the explosion center.
|
||||
|
||||
**Diagnosis:** XOR reseeding is a blender, not a bomb. It mixes the content uniformly rather than concentrating disruption at a source. The result looks *replaced* rather than *damaged*. This fails Ozzie's test — the destruction has no cause visible in the output.
|
||||
|
||||
**XOR reseeding is appropriate only for era-scale discontinuities**, where the settlement genuinely rebuilt from scratch (decades passed, original structures gone, new generation built different). It is wrong for in-playthrough events.
|
||||
|
||||
---
|
||||
|
||||
### Approach B: Structured Damage Parameters
|
||||
|
||||
```rust
|
||||
struct GasExplosionEvent {
|
||||
origin: TilePosition, // (2, 3, 38)
|
||||
blast_radius: u16, // 8 tiles primary, 14 tiles secondary
|
||||
intensity: f32, // 0.85 (high pressure rupture)
|
||||
propagation_dir: Option<Dir>, // None (omnidirectional rupture)
|
||||
ignition: bool, // true (gas ignites)
|
||||
}
|
||||
```
|
||||
|
||||
Application: the generator output is **unchanged**. The chunk maintains `original_seed = 0xA3F8C21B_7E64D509`. The damage event is appended to the `ChunkMutations` overlay:
|
||||
|
||||
```rust
|
||||
ChunkMutations {
|
||||
structural_changes: [
|
||||
// Primary blast zone (radius ≤ 8 tiles): damage proportional to distance
|
||||
StructuralChange { tile: (2,3,38), change: TileType::Rubble { debris_density: 1.0 } },
|
||||
StructuralChange { tile: (2,3,37), change: TileType::Rubble { debris_density: 0.9 } },
|
||||
StructuralChange { tile: (2,3,39), change: WallState::Breached { gap_size: 3 } },
|
||||
StructuralChange { tile: (2,3,36), change: TileType::Rubble { debris_density: 0.7 } },
|
||||
StructuralChange { tile: (2,3,4), change: TileType::Rubble { debris_density: 0.4 } },
|
||||
// Floor above (if loaded): ceiling collapse
|
||||
StructuralChange { tile: (2,3,38+floor), change: FloorState::PartialCollapse },
|
||||
// Secondary zone (radius 8–14): soot, scorch marks, broken fixtures
|
||||
TileOverride { tile: (2,3,50), visual_state: VisualMod::Scorched },
|
||||
TileOverride { tile: (2,3,51), visual_state: VisualMod::SootLayer },
|
||||
// ...
|
||||
],
|
||||
removed_objects: [gas_line_fixture_38, apartment_door_36, ...],
|
||||
placed_objects: [
|
||||
PlacedObject { pos: (2,3,42), object_type: DebrisPile, seed: derived },
|
||||
PlacedObject { pos: (2,3,35), object_type: FireScorch, seed: derived },
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
**The result:**
|
||||
|
||||
| Tile position | Before | After (structured overlay) |
|
||||
|---|---|---|
|
||||
| (2,3,1) — entry corridor | Corridor, N-S | **Corridor, N-S** (unchanged) |
|
||||
| (2,3,4) — apartment 1A | Residential interior | **Residential interior, debris scattered** (within blast radius but low intensity at distance) |
|
||||
| (2,3,12) — shared kitchen | Kitchen fixtures | **Kitchen fixtures, scorched** (secondary zone) |
|
||||
| (2,3,38) — explosion origin | Gas line junction | **Rubble, debris_density 1.0** |
|
||||
| (2,3,40) — adjacent unit | Apartment interior | **Rubble, debris_density 0.8** |
|
||||
| (2,3,55) — block corner | Exterior wall | **Exterior wall, soot marks** (secondary zone) |
|
||||
|
||||
The block is recognizably itself — a worker residential block that has been damaged. You can see the block's original structure through the destruction. The explosion origin is identifiable. The damage radiates outward. The adjacent block at (2,4) is untouched.
|
||||
|
||||
**This is caused destruction.** The spatial logic is legible.
|
||||
|
||||
---
|
||||
|
||||
### Decision: Regeneration Strategy Enum
|
||||
|
||||
```rust
|
||||
enum RegenerationStrategy {
|
||||
/// For localized in-playthrough events: explosions, fires, structural collapse
|
||||
/// Generator output unchanged; damage applied as ChunkMutations overlay
|
||||
LocalOverlay(DamageParameters),
|
||||
|
||||
/// For district-scale temporal changes: rebuilding after war, years of neglect
|
||||
/// Modify seed slightly; re-run generator for significant structural changes
|
||||
/// Appropriate when player returns to a district 10+ years later (between scenarios)
|
||||
SoftReseed { seed_modifier: u64 },
|
||||
|
||||
/// For era-level discontinuities: orbital strike, catastrophic flood, decades of war
|
||||
/// Appropriate between major time-skip scenarios, not within playthrough
|
||||
FullReseed,
|
||||
}
|
||||
```
|
||||
|
||||
**Rule:** In-playthrough events are ALWAYS `LocalOverlay`. `SoftReseed` and `FullReseed` only apply during scenario setup (between playthroughs or at major time-skip boundaries). The generator never re-runs for events the player witnesses or causes.
|
||||
|
||||
This resolves OQ-R4-F. The D-record should canonicalize these three strategies and explicitly prohibit XOR reseeding for in-playthrough events.
|
||||
|
||||
**Verdict: OQ-R4-F is resolved. LocalOverlay for in-playthrough events. XOR/soft reseed only at scenario boundaries.**
|
||||
|
||||
---
|
||||
|
||||
## 3. Rooftop Bar Clause — Amended Guarantee
|
||||
|
||||
### The Original Guarantee (Round 3)
|
||||
|
||||
> "Every tall structure (z_band_count ≥ 3) must have a roof zone classified `Insider` or `BreachOnly` accessible by non-obvious route."
|
||||
|
||||
### The Problem
|
||||
|
||||
This forces ALL rooftops to be secret or restricted. But the setting has:
|
||||
- Commission-era arcologies with public observation galleries
|
||||
- Commercial towers with rooftop restaurants
|
||||
- Religious structures with sky gardens
|
||||
- A transit hub's roof terrace where residents watch shuttle departures
|
||||
|
||||
The guarantee as written would require the rooftop restaurant to be an unauthorized trespass destination. That's wrong. Some rooftops are meant to be a public destination — a reason to climb, not a secret discovered by climbing.
|
||||
|
||||
What the guarantee was *trying* to protect: the discovery element. Rooftops should never be structurally irrelevant. They should always offer something — either a restricted secret, or a public destination with a hidden layer.
|
||||
|
||||
### The Revised Guarantee — Vertical Discovery
|
||||
|
||||
**For every tall structure (z_band_count ≥ 3), at least one of the following must be true:**
|
||||
|
||||
**Option A — Restricted Rooftop (Discovery Through Access)**
|
||||
The primary roof zone is classified `Insider` or `BreachOnly`, accessible by non-obvious route. The discovery is the access itself.
|
||||
|
||||
**Option B — Public Rooftop with Hidden Layer (Discovery Within Destination)**
|
||||
The primary roof zone is publicly accessible (Social Hub, Economic Node, or equivalent). A secondary zone within the same z-band is classified `Insider` or `BreachOnly`. This could be:
|
||||
- A maintenance level behind an access panel
|
||||
- A restricted transmitter array within the rooftop space
|
||||
- A private penthouse cluster separated by `Semi-Private` partition
|
||||
- A service stairwell to a sub-roof level
|
||||
|
||||
**The inviolable rule across both options:** Every tall structure must have *something* at the top that is not fully accessible from below. The discovery layer is mandatory. The public/private split of the primary space is not.
|
||||
|
||||
### Generator Implementation
|
||||
|
||||
```rust
|
||||
enum RooftopConfig {
|
||||
Restricted {
|
||||
zone_class: AccessTier, // must be Insider or BreachOnly
|
||||
access_route: RouteObviousness, // must be NonObvious
|
||||
},
|
||||
PublicWithHiddenLayer {
|
||||
primary_zone: ZoneType, // Social Hub, Economic Node, etc.
|
||||
secondary_restricted: ZoneSpec, // always present; Insider or BreachOnly
|
||||
},
|
||||
}
|
||||
|
||||
struct MultiBlockReservation {
|
||||
// ... existing fields ...
|
||||
rooftop: RooftopConfig, // replaces the old "roof zone guaranteed restricted" constraint
|
||||
}
|
||||
```
|
||||
|
||||
### The Guarantee Audit Change
|
||||
|
||||
Old check:
|
||||
> "Does this tall structure have a roof zone classified Insider or BreachOnly?"
|
||||
|
||||
New check:
|
||||
> "Does this tall structure have a `RooftopConfig::Restricted` or a `RooftopConfig::PublicWithHiddenLayer` with a non-empty `secondary_restricted`?"
|
||||
|
||||
Both options satisfy the audit. The key: the generator must choose one at district generation time based on the building's zone palette and heritage root. Commission-institutional buildings: `PublicWithHiddenLayer` (observation gallery + restricted records floor). Iron-heritage trade towers: `Restricted` (the roof belongs to the guild leadership). Frost-heritage isolated structures: `Restricted` (the roof is where the heating systems live and no one else goes up).
|
||||
|
||||
**Verdict: Rooftop guarantee amended. Rooftop bars are valid. The discovery layer remains mandatory.**
|
||||
|
||||
---
|
||||
|
||||
## 4. D-Record Sign-Off — All 12
|
||||
|
||||
Going through each. I'm flagging amendments where the D-record needs additional language beyond what the Round 3 notes contain.
|
||||
|
||||
| # | Item | Status | My Position |
|
||||
|---|---|---|---|
|
||||
| D-READY-1 | DistrictLayoutMode: Grid / Organic | **SIGNED OFF** | No amendments. Canonical. |
|
||||
| D-READY-2 | Guarantee Tier System | **SIGNED OFF** | Amendment below. |
|
||||
| D-READY-3 | TrianglePurpose Enum | **SIGNED OFF** | No amendments. |
|
||||
| D-READY-4 | WallBackside / TileBehindState | **SIGNED OFF** | Amendment below. |
|
||||
| D-READY-5 | Dynamic Modification via Overlay | **SIGNED OFF** | Amendment below (from OQ-R4-F). |
|
||||
| D-READY-6 | ZonePalette Modifier System | **SIGNED OFF** | No amendments. |
|
||||
| D-READY-7 | Horizon View Corridor | **SIGNED OFF** | No amendments. |
|
||||
| D-READY-8 | Assassin Lens Spatial Guarantees | **SIGNED OFF** | Amendment below. |
|
||||
| D-READY-9 | Heritage Grammar Overlay | **SIGNED OFF** | No amendments. |
|
||||
| D-READY-10 | Non-Urban Informal Zone Typology | **SIGNED OFF** | No amendments. |
|
||||
| D-READY-11 | Vertical Scale Architecture | **SIGNED OFF** | Amendment below (Rooftop Bar Clause). |
|
||||
| D-READY-12 | Trauma Events as EraModification | **SIGNED OFF** | Amendment below (from OQ-R4-F integration). |
|
||||
|
||||
---
|
||||
|
||||
### D-READY-2 Amendment: Guarantee Tier System
|
||||
|
||||
The D-record should include explicit naming for the three tiers:
|
||||
|
||||
- **Tier 1 — Universal Inhabited Guarantees** (all inhabited districts, any complexity)
|
||||
- Social Hub, Informal Zone, Encounter Corridor
|
||||
- **Tier 2 — Full-Complexity Guarantees** (Full-complexity only)
|
||||
- Traffic Chokepoint, Institutional Space, Insider Space, Economic Node
|
||||
- Horizon View Corridor (coastal Full-complexity)
|
||||
- BreachOnly Zone (≥1 per Full-complexity)
|
||||
- **Tier 3 — Conditional Parameter Guarantees** (depend on district parameter values)
|
||||
- Elevated Vantage, Egress Multiplicity, Temporal Opacity Window (A-1/A-2/A-3)
|
||||
- Non-Institutional Access Route (A-4 — applies to all Full-complexity)
|
||||
- Economic Asymmetry Signal (when `economic_disparity` flag present)
|
||||
- Power Gradient Visibility (when `faction_control` field is non-null)
|
||||
|
||||
The audit runs all applicable checks. A Minimal farmstead gets 3 checks. A Full-complexity coastal urban hub gets up to 12. The D-record should specify which checks are mandatory vs. which are triggered by parameter flags.
|
||||
|
||||
---
|
||||
|
||||
### D-READY-4 Amendment: Dual Classification System
|
||||
|
||||
The D-record should clearly establish that `TileBehindState` and `WallBackside` serve complementary roles and **both** are canonical:
|
||||
|
||||
| Enum | Scope | Purpose |
|
||||
|---|---|---|
|
||||
| `WallBackside` (Tyre) | Structural | What is physically behind this wall tile (for generation and LOS) |
|
||||
| `TileBehindState` (Gestalt) | Gameplay | What kind of space this represents for gameplay systems |
|
||||
|
||||
These are not duplicates. A wall with `WallBackside::ServiceVoid` has `TileBehindState::Interstitial`. A wall with `WallBackside::AdjacentSpace` has `TileBehindState::HiddenRoom` OR `TileBehindState::StructuralFill` depending on access tier configuration. The D-record should canonicalize both enums and document the mapping between them.
|
||||
|
||||
---
|
||||
|
||||
### D-READY-5 Amendment: RegenerationStrategy Integration
|
||||
|
||||
Add to the D-record:
|
||||
|
||||
```rust
|
||||
enum RegenerationStrategy {
|
||||
LocalOverlay(DamageParameters), // in-playthrough events; generator output unchanged
|
||||
SoftReseed { seed_modifier: u64 }, // scenario-boundary temporal changes only
|
||||
FullReseed, // era-level discontinuities only
|
||||
}
|
||||
```
|
||||
|
||||
**Explicit constraint in the D-record:** In-playthrough events must use `LocalOverlay`. `SoftReseed` and `FullReseed` are scenario-setup tools, not event responses. The generator does not re-run for player-witnessed events.
|
||||
|
||||
---
|
||||
|
||||
### D-READY-8 Amendment: A-1 through A-4 as Tier 3 Conditional
|
||||
|
||||
The assassin spatial guarantees (A-1: Elevated Vantage, A-2: Egress Multiplicity, A-3: Temporal Opacity Window, A-4: Non-Institutional Route) should be positioned explicitly as **Tier 3 Conditional Guarantees**, not as an assassin-specific subsystem.
|
||||
|
||||
The D-record language should be:
|
||||
|
||||
> "A-1, A-2, and A-3 are conditional guarantees triggered when `complexity_tier == Full`. A-4 is a mandatory Full-complexity guarantee (all playstyles benefit from non-institutional routes). These are derived properties of the existing spatial configuration, validated by the guarantee audit. They are not spatial features tagged for the assassin — they are properties that any playstyle can discover and exploit."
|
||||
|
||||
This framing prevents scope creep where assassin-specific content gets its own generation budget. The guarantees audit against existing spatial output; they don't add generation cost.
|
||||
|
||||
---
|
||||
|
||||
### D-READY-11 Amendment: Rooftop Bar Clause
|
||||
|
||||
The D-record should replace the original guarantee with the amended `RooftopConfig` model from Section 3 above. Specifically:
|
||||
|
||||
> "Every tall structure (z_band_count ≥ 3) must specify a `RooftopConfig`. If `Restricted`, the roof zone must be `Insider` or `BreachOnly` with a non-obvious access route. If `PublicWithHiddenLayer`, the primary public zone must be accompanied by a secondary restricted zone within the same z-band. The discovery layer is mandatory in both configurations. Heritage root and building zone palette determine which configuration the generator assigns."
|
||||
|
||||
---
|
||||
|
||||
### D-READY-12 Amendment: Trauma Event + RegenerationStrategy
|
||||
|
||||
Trauma events trigger `LocalOverlay`, not reseeding. The D-record should explicitly state:
|
||||
|
||||
> "`ModificationType::TraumaEvent` applies structural changes via `ChunkMutations::LocalOverlay`. The generator output (original_seed) is preserved. Cultural aftermath decays toward baseline at heritage-root-dependent rates, tracked in simulation state. Physical destruction and cultural aftermath are separate tracks — the wall being rubble is a `StructuralChange`; the community's altered NPC weight distribution is simulation state that decays."
|
||||
|
||||
---
|
||||
|
||||
## 5. Lead Decisions — Acknowledged
|
||||
|
||||
The following lead decisions are received and incorporated:
|
||||
|
||||
**WorldTier wins over SignificanceTier**
|
||||
|
||||
Acknowledged. `WorldTier` correctly describes what this parameter measures: the simulation fidelity budget allocated to this location. `SignificanceTier` implied narrative importance, which is wrong — a politically significant backwater still gets Minimal complexity if the generator didn't budget for it. The field is now `world_tier: WorldTier` on the DistrictSkeleton.
|
||||
|
||||
**Entity-carried chunks are CORE architecture**
|
||||
|
||||
Acknowledged. `MobileChunk` as entity-carried `ChunkData`. Vessels exist as persistent world entities — docked at port, visible from the dock, present on the world map. The exterior is a scrolling visual buffer in `InTransit` state. Miri's cultural grammar applies fully to both static and mobile chunk types. The arrival-deadline temporal pressure is core gameplay.
|
||||
|
||||
**DramaDensity is runtime state, NOT on DistrictSkeleton**
|
||||
|
||||
Acknowledged and confirmed from my own Round 3 position. The DistrictSkeleton carries the capacity ceiling. The storyteller carries the current value. The D-records should explicitly state this constraint.
|
||||
|
||||
---
|
||||
|
||||
## Final Pipeline Statement — Locked
|
||||
|
||||
Three-layer model, canonicalized:
|
||||
|
||||
```
|
||||
GENERATOR STATE (immutable after Phase 1)
|
||||
├── Phase 1: DistrictSkeleton
|
||||
│ ├── world_tier: WorldTier (simulation fidelity budget)
|
||||
│ ├── complexity_tier: ComplexityTier (content budget)
|
||||
│ ├── layout_mode: DistrictLayoutMode (Grid | Organic)
|
||||
│ ├── spatial guarantees: Tier 1/2/3 audit flags
|
||||
│ ├── rooftop: RooftopConfig (Restricted | PublicWithHiddenLayer)
|
||||
│ └── society_profile: SocietyProfile (heritage root, institutional coverage, etc.)
|
||||
└── Phase 2: PreparedDistrict
|
||||
├── SocialSitePlacement (triangles with Vec<TrianglePurpose>)
|
||||
├── NpcManifest (seeded from society_profile)
|
||||
├── ZonePalette assignments (base + modifiers)
|
||||
└── ChunkMutations pending (pre-queued from simulation events)
|
||||
|
||||
SIMULATION STATE (runtime storyteller)
|
||||
├── DramaDensity (per-district, storyteller-controlled)
|
||||
├── ActivatedTriangles (subset of SocialSitePlacement)
|
||||
├── assassination_difficulty (computed on demand from SocietyProfile + audit + runtime)
|
||||
└── StorytellerModules (fired events, fragility triggers)
|
||||
|
||||
DELTA LAYER (post-generation)
|
||||
├── ChunkMutations applied (LocalOverlay for in-playthrough)
|
||||
├── NpcRemoved / NpcStateChanged
|
||||
├── AccessTierChanged (factions seal or open zones)
|
||||
└── WorldStateDelta (composed from all active mutations)
|
||||
```
|
||||
|
||||
These three layers compose at render time. The generator never re-runs. The pipeline is locked.
|
||||
|
||||
---
|
||||
|
||||
## Open Questions Remaining
|
||||
|
||||
**None.**
|
||||
|
||||
- OQ-R4-A: Entity-carried chunks selected by lead. Resolved.
|
||||
- OQ-R4-B: WorldTier selected by lead. Resolved.
|
||||
- OQ-R4-C: Computed on demand. Resolved (Section 1).
|
||||
- OQ-R4-D: Heritage grammar overlay — this is OQ-R4-D which is Araminta's domain (representation in chunk fill assets vs. modifier objects). I'm waiting on Araminta's response; it doesn't block D-record production since the *content* of the heritage grammar (Miri) and the *integration point* (modifier system, D-READY-6) are both locked.
|
||||
- OQ-R4-E: One NPC, five lenses — Nigel's domain. Doesn't affect my output.
|
||||
- OQ-R4-F: LocalOverlay for in-playthrough events. Resolved (Section 2).
|
||||
|
||||
**Round 4 closes from my side. Twelve D-records ready. Three open questions resolved. Pipeline locked.**
|
||||
@@ -0,0 +1,95 @@
|
||||
# Generator Architecture Workshop — Round 5: Gestalt (Final Review)
|
||||
|
||||
**Role:** Systems Design / Gameplay Loop Requirements
|
||||
**Date:** 2026-02-27
|
||||
**Workshop:** Generator Architecture (#562)
|
||||
**Round:** 5 — Final Review
|
||||
|
||||
---
|
||||
|
||||
## Review: Does `workshop-outcomes.md` Accurately Capture My Contributions?
|
||||
|
||||
Short answer: **Yes, with two minor corrections.**
|
||||
|
||||
---
|
||||
|
||||
## What Is Accurately Captured
|
||||
|
||||
### Three-Layer Model
|
||||
|
||||
The generator/simulation/delta separation is correctly captured and the pipeline diagram in the outcomes matches my Round 4 locked state. The immutability of generator output post-Phase 1, and the composition of layers at render time, are correct.
|
||||
|
||||
### LocalOverlay Mandate + XOR Prohibition
|
||||
|
||||
The RegenerationStrategy enum is correctly specified with all three tiers:
|
||||
- `LocalOverlay` for in-playthrough events (mandatory)
|
||||
- `SoftReseed` at scenario boundaries only
|
||||
- `FullReseed` at era-level discontinuities only
|
||||
|
||||
The explicit XOR prohibition is correctly recorded under both D-READY-5 and D-READY-14. The separate D-READY-14 records the prohibition as an architectural mandate, which is the right framing — it's bigger than just the overlay mechanics.
|
||||
|
||||
### RooftopConfig: Restricted | PublicWithHiddenLayer
|
||||
|
||||
The amended Rooftop Bar Clause is correctly captured. The key requirement — discovery layer mandatory in both configurations, heritage root drives assignment — is accurate. The guard rails around mandatory hidden layers are preserved.
|
||||
|
||||
### D-READY-4: Dual Classification System
|
||||
|
||||
The `WallBackside` / `TileBehindState` split is correctly framed as complementary, not duplicated. The mapping (ServiceVoid → Interstitial; AdjacentSpace → HiddenRoom or StructuralFill) is accurate.
|
||||
|
||||
### D-READY-8: Assassin Lens as Derived Properties
|
||||
|
||||
Correctly captured: A-1 through A-4 are derived properties of existing spatial configuration, not assassin-tagged features. "They add no generation cost; the audit validates existing output." That is the exact framing from my Round 4 and it is preserved.
|
||||
|
||||
### Assassination Difficulty — Tension Preserved
|
||||
|
||||
The outcomes document correctly notes the minor tension between my "computed entirely on demand" position and Miri's "stored cultural baseline" position, and correctly flags it as Q-NNN-f (open question for sprint work). The recommended synthesis — stored baseline in DerivedDistrictAnalysis + on-demand runtime computation for player-facing assessment — is a reasonable middle ground. I accept this as the forward direction.
|
||||
|
||||
### Open Questions Attributed to Me
|
||||
|
||||
Q-NNN-d (DramaDensity naming) and Q-NNN-f (assassination difficulty synthesis) are correctly attributed and framed.
|
||||
|
||||
---
|
||||
|
||||
## Corrections
|
||||
|
||||
### Correction 1: Guarantee Audit Count — Minor
|
||||
|
||||
**What the outcomes say:** "A Full-complexity coastal urban hub gets up to 13."
|
||||
|
||||
**What my Round 4 said:** "up to 12."
|
||||
|
||||
The discrepancy is one check. Reviewing the Tier 2 and Tier 3 lists in D-READY-2:
|
||||
|
||||
- Tier 2: Traffic Chokepoint, Institutional Space, Insider Space, Economic Node, Horizon View Corridor, BreachOnly Zone, Rooftop Discovery Zone = **7**
|
||||
- Tier 3: A-1, A-2, A-3, A-4, Economic Asymmetry Signal, Power Gradient Visibility = **6**
|
||||
- Tier 1: Social Hub, Informal Zone, Encounter Corridor = **3** (these always run)
|
||||
|
||||
3 + 7 + 6 = 16 potential checks, but most Tier 3 checks are conditional. "Up to 13" vs "up to 12" depends on whether Rooftop Discovery Zone (Tier 2) was included in my count or not. Given that the Rooftop Bar Clause was an amendment I made in Round 4 after the original count was established, it appears the outcomes correctly adds it and reaches 13. **The outcomes document is correct; my Round 4 count of "up to 12" did not yet include the Rooftop Discovery Zone that I myself amended into Tier 2.**
|
||||
|
||||
No change needed to the outcomes document — it has the right number.
|
||||
|
||||
### Correction 2: Field Name — `complexity` vs `complexity_tier`
|
||||
|
||||
**What the outcomes say (pipeline diagram):** `complexity: ComplexityTier`
|
||||
|
||||
**What my Round 4 pipeline diagram said:** `complexity_tier: ComplexityTier`
|
||||
|
||||
The outcomes document uses `complexity` as the field name in the Phase 1 struct. My Round 4 used `complexity_tier`. The outcomes document should use consistent naming — either `complexity` (shorter, idiomatic) or `complexity_tier` (explicit, parallel with `world_tier`).
|
||||
|
||||
**My recommendation:** Use `complexity_tier` to parallel `world_tier`. Both fields identify a tier; both field names should follow the same convention. The outcomes diagram should be corrected to `complexity_tier: ComplexityTier` for consistency.
|
||||
|
||||
**This is a minor point.** If the lead prefers `complexity`, that's also fine — it just needs to be consistent everywhere.
|
||||
|
||||
---
|
||||
|
||||
## Items Added by Other Participants (No Objections)
|
||||
|
||||
**D-READY-13 (MobileChunk)** and **D-READY-14 (DamageOverlay/RegenerationStrategy as separate D-record)** were not in my Round 4 twelve-item sign-off table because they were developed primarily by Tyre/Miri/Nigel and the 14-record count was assembled from the full team's output. I have no objections to either. D-READY-13 is correctly scoped (entity-carried, no Phase 1/Phase 2 split, departure schedules mandatory). D-READY-14 correctly separates the prohibition into its own record.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
The outcomes document accurately represents my Round 4 contributions. One self-correcting count discrepancy (12→13 checks, resolved by my own Rooftop Bar Clause amendment), one minor naming consistency question (`complexity` vs `complexity_tier`). No substantive misrepresentations. No positions attributed to me that I didn't hold.
|
||||
|
||||
**Round 5 review complete from my side.**
|
||||
@@ -0,0 +1,436 @@
|
||||
# Generator Architecture Workshop — Round 1: Miri (Worldbuilder)
|
||||
|
||||
**Topic:** Worldbuilding inputs for the generator pipeline
|
||||
**Date:** 2026-02-27
|
||||
**Source decisions:** D-025, D-036, D-093, D-095, Q-032, Q-036, Q-039
|
||||
**Prior art:** Wiki Review Workshop Round 4 (Miri — ingredients menu, society profile)
|
||||
|
||||
---
|
||||
|
||||
## Orientation: What worldbuilding supplies to the generator
|
||||
|
||||
The generator does not produce setting — it *reproduces* setting from parameters. My role is to define what those parameters are and where in the pipeline they enter. This document organizes my prior work (wiki-review Round 4 ingredients menu, Krenn System brief) into a form the pipeline architecture can consume.
|
||||
|
||||
Everything below connects to the confirmed existence of Q-032 (cultural ingredients menu, approved by lead but not yet formally specified). This workshop is the first place those parameters need to map onto a concrete pipeline. That mapping is what I'm providing here.
|
||||
|
||||
---
|
||||
|
||||
## Question 1: How does the generator reproduce the cultural/economic variation of 300 worlds?
|
||||
|
||||
The short answer: **through a society profile assembled from combinatorial ingredients, not through per-world hand-authoring**.
|
||||
|
||||
The longer answer follows from what I established in Wiki Review Round 4. The Krenn System brief (Rounds 1-2 of that workshop) was a proof of concept — one complete output. Round 4 inverted the question: instead of writing a brief for each world, we design the *ingredient pantry* from which any brief can be generated.
|
||||
|
||||
### The ingredient categories (Q-032 scope, prior work summary)
|
||||
|
||||
I defined six ingredient categories in Wiki Review Round 4. Restating them here as formal generator inputs:
|
||||
|
||||
**A. Heritage Roots** (1-3 selected, blend weights summing to 1.0)
|
||||
|
||||
Ten roots, each a parameter bundle encoding phonetics + social dynamics + trust model:
|
||||
|
||||
| Root | Phonetic Signature | Social Signature | Trust Model |
|
||||
|---|---|---|---|
|
||||
| **Frost** | Compact, consonant-clusters, hard stops | Reserved, privacy-first | Patience — time + shared labor |
|
||||
| **Tide** | Flowing, vowel-rich, soft consonants | Expressive, group-oriented | Hospitality — sharing food/space |
|
||||
| **Iron** | Heavy, rhythmic, gutturals | Communal solidarity, labor-proud | Collective — trust the group |
|
||||
| **Spice** | Layered, precise stress, sibilants | Extended kinship, spiritual undertone | Kinship — blood/marriage networks |
|
||||
| **Jade** | Precise, clean, varied-short | Hierarchical, honor-aware | Competence — skill earns respect |
|
||||
| **Dust** | Rhythmic, open vowels, nasals | Communal decision, oral tradition | Witness — public demonstration |
|
||||
| **Vine** | Warm, soft stops, rolled consonants | Class-conscious, family honor | Family — recognized kinship |
|
||||
| **Salt** | Pragmatic, clipped, dental | Individualist, commercial | Transaction — fair dealing |
|
||||
| **Stone** | Steady, balanced, laterals | Enduring, traditional, land-connected | Tenure — long presence |
|
||||
| **Arc** | Sharp, fricatives, unusual combos | Intellectual, cosmopolitan | Argument — demonstrated reasoning |
|
||||
|
||||
Blend example (confirmed Krenn): `{frost: 0.55, salt: 0.30, iron: 0.15}`. The blend weights produce naming phonetics, social dynamics, and trust parameters. The Krenn System regional brief from wiki-review Rounds 1-2 is the validated output of this blend.
|
||||
|
||||
**B. Settlement Motivation** (one primary)
|
||||
|
||||
Economic-extractive / economic-trade / economic-agricultural / ideological-political / ideological-academic / institutional-military / institutional-administrative / refugee / frontier-adventurist.
|
||||
|
||||
Absence is valid: a world with no ideological motivation has no philosophical frame for its grey economy. People smuggle because they need to, not because they believe anything. That absence IS character.
|
||||
|
||||
**C. Economic Function** (current activity, may differ from founding motivation)
|
||||
|
||||
Extraction / logistics / manufacturing / agriculture / services / research / military-security / administrative / transit / mixed.
|
||||
|
||||
**D. Economic Pressure** (1-2 selected — what makes extra income tempting)
|
||||
|
||||
Tight-margin / debt-trap / status-competition / survival-gap / opportunity-disparity / prohibition-economy / generational-extraction.
|
||||
|
||||
Krenn is `[tight-margin, prohibition-economy]`. That double pressure produces the specific moral texture: economically rational AND ideologically defensible. A different system with `[survival-gap, prohibition-economy]` produces the same contraband type but a more desperate, less principled grey economy. The player feels the difference in NPC motivation.
|
||||
|
||||
**E. Drift Stage** (age modifier on heritage blending)
|
||||
|
||||
Pioneer (0-50yr) / crystallizing (50-150yr) / mature (150-300yr) / ancient (300+yr).
|
||||
|
||||
Drift affects how blended the roots are and how much novel cultural content has emerged from local conditions. At "ancient," the heritage roots are substrate — barely detectable. At "pioneer," the primary root dominates strongly. This is the generator's primary defense against franchise similarity.
|
||||
|
||||
**F. Absence Parameters** (what's missing)
|
||||
|
||||
Any ingredient category can be NULL:
|
||||
- No heritage consciousness → functional naming, no substrate words, no food traditions
|
||||
- No institutional authority → self-governing, Commission-absent, grey economy is the only economy
|
||||
- No community bonds → transient population, no social fabric to investigate
|
||||
- No ideological framework → people survive, they don't philosophize
|
||||
|
||||
NULL values produce distinct societies. A transit hub with high turnover and no heritage consciousness plays completely differently from a mature logistics district.
|
||||
|
||||
### How 300 worlds get variety
|
||||
|
||||
The ingredient space is large but bounded:
|
||||
- 10 roots × 3 blend positions (with weights) = many thousands of phonetic/social combinations
|
||||
- 9 motivation types × NULL option = 10 states
|
||||
- 10 economic functions = 10 states
|
||||
- 7 pressure types × 2 picks × NULL option = combinatorial
|
||||
- 4 drift stages
|
||||
|
||||
Conservative estimate: even constraining the ingredient space heavily, the combination space comfortably exceeds 300 meaningfully distinct societies. The deeper question (for Nigel and Gestalt) is whether the GAMEPLAY variation matches the cultural variation — whether cultural differences translate to meaningfully different investigation experiences. My input: the society profile parameters feed directly into dialogue access thresholds, NPC pattern distributions, and trust-building timelines. Cultural variation produces mechanical variation.
|
||||
|
||||
**The parameter that translates culture to gameplay:** `social.privacy_level` and `trust.building_rate` are the key levers. A Frost-dominant society (high privacy, slow trust) produces patient-observation investigations. A Tide-dominant society (low privacy, fast trust) produces social-network investigations. The same PC archetype plays completely differently across these cultures.
|
||||
|
||||
---
|
||||
|
||||
## Question 2: What lore-level inputs drive the pipeline?
|
||||
|
||||
Breaking this down by the specific categories the brief mentions:
|
||||
|
||||
### Faction identity
|
||||
|
||||
Faction presence enters the pipeline at **two stages**:
|
||||
|
||||
**Stage 1 — System-level (above geography):** Before any geography is generated, the system has a political classification:
|
||||
- Commission presence tier: comprehensive / standard / intermittent / absent
|
||||
- Concord Assembly reach: represented / liaison-only / nominal / beyond-reach
|
||||
- Syndic presence: dominant / significant / minor / absent
|
||||
- Independent governance: none / district / station / system-wide
|
||||
|
||||
These classify who controls the space. They set the baseline Meridian coverage tier (Commission presence = comprehensive coverage; absence = structural gaps). They also determine which faction templates are available for district-level social sites.
|
||||
|
||||
**Stage 2 — District-level (at the skeleton):** Faction control at the district level determines:
|
||||
- Which faction's social sites are instantiated (Commission inspection post vs. independent workers' hall)
|
||||
- Authority NPC pattern distribution (more SYSTEM NPCs under strong faction control, more HANDLER NPCs under faction absence/power vacuum)
|
||||
- What the grey economy structure looks like (ring-style horizontal cooperative vs. cartel-style vertical with handler hierarchy)
|
||||
|
||||
Setting note — faction identity does NOT map to specific named factions at generation time. The system generates "dominant regulatory faction" and "local economic faction" from the political classification. Specific named factions (Commission, Concord Assembly, Talvik/Sova Logistics Consortium) are instantiated in hand-authored content only.
|
||||
|
||||
### Economic function
|
||||
|
||||
Economic function is both a society-level input (what the world does) and a district-level input (what this district specifically does within the world). Sova Transit District's economic function (logistics) differs from the station's overall mix. The district's function determines:
|
||||
|
||||
- **Daily rhythm:** Shift-based / seasonal / project-based / client-based / continuous
|
||||
- **Primary gathering trigger:** Shift-end / market-day / lecture-end / patrol-rotation
|
||||
- **Primary social site type:** Bar (shift-end) / market (commercial) / lab commons (research) / mess hall (military)
|
||||
- **Investigation vector:** Manifest discrepancies (logistics) / land records (agricultural) / research logs (academic) / chain-of-command gaps (military)
|
||||
- **Grey economy structure:** What's being smuggled depends on what flows through legitimately. Logistics = cargo-embedded contraband. Research = stolen data or restricted compounds. Manufacturing = diverted materials.
|
||||
|
||||
### Tech level
|
||||
|
||||
Tech level is not a simple progression tier. It's a **three-axis profile**:
|
||||
|
||||
**Axis 1: Meridian coverage density** (surveillance infrastructure)
|
||||
- Comprehensive (Commission-grade): full public and institutional coverage
|
||||
- Standard: common areas covered, private spaces standard-grade
|
||||
- Degraded: structural gaps, older infrastructure, potentially exploited
|
||||
- Minimal: maintenance corridors, pre-Meridian construction, no effective coverage
|
||||
|
||||
This is already canonized for Sova (D-093 zone palette by coverage tier). The generator must assign coverage tiers per zone/district based on construction era + institutional investment + ring/grey-economy interference.
|
||||
|
||||
**Axis 2: Neural lattice penetration** (how much of the population has lattice)
|
||||
|
||||
Station Sova's working-class logistics district: broad lattice penetration, but regulated to basic-tier. This is what makes aftermarket lattice components valuable — broad desire, restricted supply, economic barriers to legitimate upgrade.
|
||||
|
||||
At 300 worlds, lattice penetration is a society parameter that affects:
|
||||
- What contraband type is in demand (high penetration + strict regulation = aftermarket components; low penetration + no regulation = basic access kits)
|
||||
- PC perception modes available
|
||||
- NPC information-sharing patterns (Meridian-mediated vs. physical word-of-mouth)
|
||||
|
||||
**Axis 3: Infrastructure age / construction era**
|
||||
|
||||
Already canonized in D-093 (Z-level model: z=0 Era 1 maintenance, z=1 operational, z=2 Era 3 gate cluster). Era tagging is the generator's architectural stratification tool. Different eras produce different:
|
||||
- Structural materials (visual coherence input for Araminta)
|
||||
- Meridian coverage gaps (older = less coverage)
|
||||
- Social dynamics (workers in Era 1 maintenance have different relationship to the station than workers in Era 3 institutional spaces)
|
||||
|
||||
### Population density
|
||||
|
||||
Population density is **extrapolated from economic function and capacity**, not input directly. This matches the Cities Skylines model (population follows zoning/capacity). From a worldbuilding perspective:
|
||||
|
||||
- Logistics district: 30-40 workers per shift × shift overlap = ~800 permanent residents on Sova (D-036 confirmed). High transient component (freight crews, visitors).
|
||||
- Transit hub element: adds transient flux. The investigation texture changes when a significant portion of the population is temporary — transients have less community loyalty but also less community protection.
|
||||
|
||||
For the generator, population density should be an OUTPUT of the capacity calculation, then fed back as an input to social site scale (how large a social site needs to be to serve this population).
|
||||
|
||||
### Historical events
|
||||
|
||||
Historical events are the generator's "damage to the initial output" pass. A society profile describes what the world was like at steady state. Historical events modify that:
|
||||
|
||||
- **Founding crisis** (refugee wave, corporate collapse, war): pushes drift_stage forward for that event's effects while leaving broader culture at current drift
|
||||
- **Economic disruption** (resource depletion, trade route change): shifts economic pressure parameters mid-system history
|
||||
- **Institutional incursion** (Commission crackdown, Syndic restructuring): changes faction presence tier, modifies authority attitude parameter
|
||||
|
||||
Sova's relevant historical events:
|
||||
- Original Talvik Logistics founding (~180yr ago): founding motivation = economic-trade, sets initial parameters
|
||||
- Syndic restructuring into Sova Logistics Consortium (~80yr ago): corporate disruption event, modest authority attitude shift
|
||||
- Current ring activity: not a historical event in the generator sense — it's the Tier 1 drama module applied to an otherwise stable logistics district
|
||||
|
||||
For the generator, historical events are a modifier pass AFTER society profile generation. They produce anomalies — places where the current state doesn't match the expected parameters because something happened.
|
||||
|
||||
---
|
||||
|
||||
## Question 3: Station settings vs. planet-side cities vs. orbital installations
|
||||
|
||||
**Recommendation: Same pipeline, different geography topology input.**
|
||||
|
||||
The geography input is the first stage of the pipeline. What differs between setting types is the *geometry of what geography can be*, not the pipeline structure itself.
|
||||
|
||||
### Stations
|
||||
|
||||
Closed-envelope geography. Key characteristics:
|
||||
- **Bounded and layered:** Z-levels are hard separations (D-093). No "outside." Access topology is vertical as much as horizontal.
|
||||
- **Era-stratified:** Older construction is typically the foundation (z=0, maintenance, low coverage); newer construction is the top (z=2, institutional, high coverage). This is reversed from planet-side where old=historic center, new=suburbs.
|
||||
- **Class is expressed spatially:** Upstation = institutional/administrative. Working level = operational. Below = maintenance/grey zone. Players can read social class from Z-level in a way that planet-side maps can't reproduce.
|
||||
- **No natural geography:** Weather is HVAC. "Outdoors" is a viewport. Natural beauty is completely absent unless the station was designed as a habitat (which logistics stations are not).
|
||||
- **Transit-culture possibility:** If the station is a hub (like Sova), a significant fraction of the population is transient. The grey economy can exploit this — unfamiliar faces don't get scrutinized.
|
||||
|
||||
**Generator implication:** Station geography is a *zone-and-level grid*. The block generator produces zones (institutional, operational, maintenance, commercial, residential) arranged in vertical layers rather than geographic gradients.
|
||||
|
||||
### Planet-side cities
|
||||
|
||||
Open-envelope geography. Key characteristics:
|
||||
- **Unbounded and spread:** Natural geography (terrain, water, weather) shapes districts. Investigation can include outdoor traversal. Districts are separated by natural boundaries (river district, hillside administrative quarter, dockyards).
|
||||
- **Weather as gameplay element:** Already canonized for Velen (D-050 — fog degrades vision cones, storyteller times weather for dramatic effect). Planet-side investigations use weather as a genuine mechanical variable.
|
||||
- **Era-stratified differently:** Historic center vs. expansion vs. suburbs. Old is typically the heart of the city. New construction is peripheral. Class is expressed through distance from center and quality of infrastructure.
|
||||
- **Agriculture possible:** Rural surrounding territory. Food culture is stronger. Seasonal rhythms affect NPC schedules.
|
||||
- **Gravity normal:** Station-born visitors notice 1.0g. Gravity is background reality for inhabitants.
|
||||
|
||||
**Generator implication:** Planet-side geography is a *terrain-influenced zone spread*. The district generator places districts according to natural features rather than Z-levels.
|
||||
|
||||
### Orbital installations (non-station)
|
||||
|
||||
Specialized closed-envelope. Key characteristics:
|
||||
- **Smaller and more homogeneous:** Research platforms, military outposts, mining operations. Population is typically 200-1000 rather than 12,000. Smaller population = fewer social sites, tighter community.
|
||||
- **Single-purpose:** One economic function dominates. There's no "upstation commercial quarter" — everything serves the primary function.
|
||||
- **Higher institutional control:** Smaller populations are more supervised. Meridian coverage is usually comprehensive. Grey economies exist but are harder to maintain — everyone knows everyone.
|
||||
- **Mission-temporal:** Installations may have defined operational lifespans. Workers rotate. This pushes toward "pioneer" drift stage even for old installations (constant personnel rotation prevents cultural accumulation).
|
||||
|
||||
**Generator implication:** Orbital installations use the same pipeline but with constraints: single economic function, small social site count, high coverage baseline, low drift stage.
|
||||
|
||||
### The same pipeline handles all three
|
||||
|
||||
The pipeline differences are:
|
||||
1. **Geography topology generator** (first stage): station → zone-and-level grid; planet-side → terrain-influenced spread; orbital → single-zone constrained
|
||||
2. **Heritage drift adjustments:** Station and orbital installations push toward slower drift (no natural anchors, more cosmopolitan mixing); planetary surfaces allow stronger regional drift (geographic isolation)
|
||||
3. **Meridian baseline:** Station and institutional orbital → higher baseline; planet-side rural → lower baseline
|
||||
|
||||
Everything downstream (amenities, zoning, block generation, chunk fill) runs the same logic. The geography input shapes what's available; the downstream stages fill it with culturally-appropriate content.
|
||||
|
||||
---
|
||||
|
||||
## Question 4: What makes Sova's Transit District culturally distinct from a similar district on another station?
|
||||
|
||||
This is the question the ingredients menu directly answers. Let me walk through it concretely.
|
||||
|
||||
### A "similar district" defined
|
||||
|
||||
A freight logistics district on a different station — same economic function (logistics), same setting type (station), same rough population scale (~800), similar construction era.
|
||||
|
||||
### The Sova ingredients (specific)
|
||||
|
||||
```yaml
|
||||
heritage:
|
||||
primary: frost # 0.55 — compact, reserved, patience-trust
|
||||
secondary: salt # 0.30 — pragmatic, transactional, direct
|
||||
tertiary: iron # 0.15 — labor solidarity, communal endurance
|
||||
drift_stage: mature # 180 years
|
||||
settlement_motivation: economic-trade # founded as a logistics contract, not a community
|
||||
economic_function: logistics
|
||||
economic_pressure: [tight-margin, prohibition-economy] # extra income tempting AND
|
||||
# Commission lattice regulation = access-as-contraband
|
||||
faction_presence:
|
||||
commission: intermittent # present but not dominant; gate cluster + Upstation
|
||||
concord: liaison-only # represented but distant
|
||||
syndic: significant # Sova Logistics Consortium controls employment
|
||||
philosophical_alignment: null # absent — pure pragmatism, no ideology
|
||||
meridian_coverage: degraded # structural gaps + ring exploitation of existing gaps
|
||||
```
|
||||
|
||||
### A different station's ingredients (example contrast)
|
||||
|
||||
Call it Station Vareth — also a freight logistics hub, roughly same population:
|
||||
|
||||
```yaml
|
||||
heritage:
|
||||
primary: dust # 0.60 — communal, oral tradition, public trust
|
||||
secondary: vine # 0.40 — warm, class-aware, family-connected
|
||||
drift_stage: crystallizing # 90 years — roots still distinct
|
||||
settlement_motivation: economic-agricultural # farming colony that added a logistics hub
|
||||
economic_function: logistics # same function
|
||||
economic_pressure: [status-competition, generational-extraction] # DIFFERENT pressures
|
||||
faction_presence:
|
||||
commission: standard # more coverage than Sova
|
||||
syndic: minor # smaller Syndic footprint, more independent operators
|
||||
philosophical_alignment: labor-solidarity # workers have ideological framework
|
||||
meridian_coverage: standard # better maintained, fewer gaps
|
||||
```
|
||||
|
||||
### What the player experiences differently at Station Vareth
|
||||
|
||||
**1. Investigation texture:** On Sova, silence is cultural (Frost/Salt = mind your business). On Vareth, silence is suspicious — a Dust/Vine culture talks, so NPC silence signals something specific. The detective reads the same cultural behavior (worker avoidance) as opposite signals.
|
||||
|
||||
**2. Trust-building mechanism:** On Sova, trust requires patience — shared time and shared labor over months. On Vareth, trust requires public demonstration — you earn it by acting in ways the community can see and validate. The same investigation timeline produces different access levels.
|
||||
|
||||
**3. Grey economy motivation:** On Sova, people smuggle because they're economically squeezed AND Commission regulation cuts them off from lattice upgrades they want. On Vareth, people participate in the grey economy because visible inequality (status-competition) creates social pressure to match higher earners, AND Syndic owners extract value from the community (generational-extraction). The contraband type may be similar (luxury goods, restricted equipment) but the moral texture is completely different. The detective's confrontation with ring participants lands differently.
|
||||
|
||||
**4. Social site character:** Same template type (logistics district), different NPC population distribution. Vareth's higher philosophical alignment (labor-solidarity) increases ANCHOR and SYSTEM pattern counts — more community pillars, more institutionalized labor representation. Sova's null philosophical alignment produces more NOBODYs and CIVILIANs — the grey economy is moral shelter, not ideology.
|
||||
|
||||
**5. Naming and ambient text:** Frost/Salt/Iron + mature drift produces Krenn-style compact consonant-heavy names (Kael, Voss, Drin). Dust/Vine + crystallizing drift produces different phonetics — possibly more flowing, more syllables, different stress patterns. The environment text (signs, graffiti, vendor names) sounds different.
|
||||
|
||||
**6. Access topology** (the investigation architecture): Vareth's higher Meridian coverage and better-maintained infrastructure means fewer natural dead zones. The ring (or equivalent grey economy) on Vareth had to BUILD its dead zones rather than exploit existing gaps. This affects which locations are grey-economy-accessible and how the spatial investigation works.
|
||||
|
||||
### The critical insight
|
||||
|
||||
Sova's cultural distinctiveness is not decorative — it's mechanically load-bearing. The Frost/Salt/Iron + mature-drift + tight-margin + prohibition-economy combination produces **specific investigation difficulty, specific NPC behavior patterns, and specific contraband moral texture**. Change any two ingredients and you get a materially different play experience, even in an identically-structured logistics district.
|
||||
|
||||
This is what the generator must preserve: not just that worlds look different, but that they PLAY differently because the cultural parameters drive mechanical parameters.
|
||||
|
||||
---
|
||||
|
||||
## Question 5: Where do political/economic conditions enter the pipeline?
|
||||
|
||||
**Short answer: Multiple stages, but primarily above geography and at the district skeleton.**
|
||||
|
||||
Here is my proposed entry map, following the Cities Skylines pipeline structure from the brief:
|
||||
|
||||
```
|
||||
[PRE-PIPELINE] System political classification
|
||||
→ Commission presence tier
|
||||
→ Concord Assembly reach
|
||||
→ Syndic presence scale
|
||||
→ Independent governance scope
|
||||
→ This sets the baseline institutional envelope for everything downstream
|
||||
|
||||
[GEOGRAPHY] World type + natural constraints
|
||||
→ Station / planetary / orbital determines zone-topology geometry
|
||||
→ Economic function constrains what infrastructure is possible
|
||||
|
||||
[INFRASTRUCTURE] Transport + utilities
|
||||
→ Economic function (logistics) → span gates, tram networks, freight lifts
|
||||
→ Faction presence → which infrastructure is Commission-maintained vs. independent
|
||||
→ Political conditions → maintenance allocation (the Sector 3 ventilation dispute is a
|
||||
political-condition artifact: Industrial Sector queue vs. Transit District priority)
|
||||
|
||||
[AMENITIES & SERVICES] Social site types available
|
||||
→ Faction presence → Commission office vs. workers' hall vs. independent clinic
|
||||
→ Economic pressure → what services the grey economy provides (aftermarket lattice here)
|
||||
→ Tech level (Meridian coverage) → what's surveil-able and what isn't
|
||||
|
||||
[POPULATION] Extrapolated from capacity
|
||||
→ Economic function → shift-based or continuous population flow
|
||||
→ Faction control → how much transient vs. permanent population (Commission areas
|
||||
have higher permanent fraction; transit areas have higher transient fraction)
|
||||
|
||||
[ZONING] District type assignment
|
||||
→ Society profile → what zone types are culturally plausible
|
||||
→ Faction control → which zones are institutionally controlled vs. autonomous
|
||||
→ Grey economy → dead zones and maintenance corridors as informal zoning
|
||||
|
||||
[BLOCK GENERATION] Chunk cluster arrangement
|
||||
→ Economic function → primary block type (freight staging, residential, commercial)
|
||||
→ Era stratification → block construction era affects coverage and condition
|
||||
→ Political conditions → bloc-level faction control (Commission inspection post in
|
||||
the freight block, not the maintenance block)
|
||||
|
||||
[CHUNK FILL — D-025 TEMPLATE INSTANTIATION]
|
||||
→ Society profile → NPC pattern distribution, NPC generation parameters
|
||||
→ Faction presence → which templates are eligible (Commission officer NPC in high-
|
||||
presence zones; no Commission NPCs in grey-economy chunks)
|
||||
→ Economic pressure → moral frame of grey economy participation
|
||||
→ Access tier parameters → how social sites behave toward outsiders
|
||||
```
|
||||
|
||||
### When D-025 templates get instantiated
|
||||
|
||||
The workshop brief asks specifically where triangle templates are instantiated. My recommendation: **at the district skeleton stage, after zoning but before block generation**.
|
||||
|
||||
The district skeleton generator:
|
||||
1. Receives the society profile (from ingredients)
|
||||
2. Receives the zoning output (district type, zone types)
|
||||
3. Selects D-025-compatible social site templates appropriate to this society profile
|
||||
4. Arranges them spatially (access topology)
|
||||
5. Assigns NPC pattern/motivation slots per template
|
||||
6. Establishes cross-template triangle connections (the one cross-template triangle per set, per D-024)
|
||||
|
||||
The skeleton is then handed to block generation, which places the skeleton's abstract social sites into concrete spatial blocks. Chunk fill then populates those blocks tile-by-tile.
|
||||
|
||||
### The Q-036 reconciliation
|
||||
|
||||
Q-036 asks whether the district skeleton is the atomic generator output. My worldbuilding position: **Yes, and here is the key clarification that resolves the tension with D-025:**
|
||||
|
||||
- D-025 defines social site templates as the atoms of *hand-authored* content
|
||||
- The district skeleton is the *generator's composed output* — a configuration of social site slots
|
||||
- The generator SELECTS AND ARRANGES D-025 templates; it doesn't replace them
|
||||
|
||||
Analogy: D-025 templates are bricks. The district skeleton is the architectural plan that determines which bricks go where. The generator writes architectural plans from ingredients; human authors craft the bricks. The generator never touches the bricks themselves.
|
||||
|
||||
The district skeleton as generator output contains:
|
||||
- A list of social site slots (type: logistics-hub / bar / maintenance / residential)
|
||||
- Spatial positions (approximate, for block generation to resolve)
|
||||
- Access topology (which sites are gate-adjacent, which are maintenance-adjacent)
|
||||
- NPC capacity and pattern distribution per site
|
||||
- Triangle assignments (who's in conflict with whom across templates)
|
||||
- Cultural modifier tags (which society profile produced this skeleton, for NPC generation)
|
||||
|
||||
---
|
||||
|
||||
## Summary: What worldbuilding requires of the generator
|
||||
|
||||
Drawing together the above into concrete requirements:
|
||||
|
||||
**1. Society profile as first-class data structure**
|
||||
|
||||
The generator must produce and consume a full society profile (Q-032) before any spatial generation begins. The profile drives NPC names, trust-building timelines, access tier thresholds, grey economy structure, and template selection.
|
||||
|
||||
**2. Political classification above geography**
|
||||
|
||||
Faction presence tier, Commission coverage, Syndic scale, and Concord Assembly reach must be resolved at system level before any district is generated. They constrain the entire downstream pipeline.
|
||||
|
||||
**3. Era stratification as spatial dimension**
|
||||
|
||||
Construction era is not just a visual tag. It determines Meridian coverage, access topology, and grey economy viability. The generator must tag zones and blocks by era and use those tags downstream.
|
||||
|
||||
**4. Grey economy as a negative-space element**
|
||||
|
||||
The grey economy occupies the spaces that official zoning doesn't account for. The generator must model what's NOT in the official map — which corridors are maintenance-only, which zones have dead spots, which blocks have unofficial access routes. This is not flavor; it's where the investigation happens.
|
||||
|
||||
**5. Cultural distinctiveness must be mechanically expressed**
|
||||
|
||||
Setting note — this is my strongest constraint: if cultural variation doesn't translate to mechanical variation (different investigation approach, different access timelines, different NPC behavior patterns), then 300 distinct cultural profiles produce only the illusion of variety. The pipeline must ensure that `privacy_level`, `trust.building_rate`, and `access_tier.*` parameters from the society profile actively modify NPC behavior systems.
|
||||
|
||||
**6. D-025 templates as the atoms; district skeleton as the molecule**
|
||||
|
||||
The generator arranges templates into skeletons. It does not alter the templates themselves. Hand-authored template quality is preserved; generator novelty comes from arrangement, not invention.
|
||||
|
||||
---
|
||||
|
||||
## Open questions I'm flagging for the workshop
|
||||
|
||||
**For Tyre:**
|
||||
- Can the content pipeline consume the society profile YAML format (from wiki-review R4) as a serde-compatible schema? The parameter depth is significant.
|
||||
- How does era-stratification map onto the chunk data structure? The Z-level model (D-093) is confirmed, but does the chunk system have era fields?
|
||||
|
||||
**For Gestalt:**
|
||||
- Does the NPC pattern × motivation distribution (wiki-review R4, Section 3) satisfy the gameplay guarantee requirements? Specifically: can a district skeleton guarantee "always a surveillance chokepoint" and "always a quiet zone" through pattern distribution alone?
|
||||
|
||||
**For Nigel:**
|
||||
- The cultural variation axes I've defined — `privacy_level`, `trust.building_rate`, heritage-root blend — are they sufficient replayability levers? Or do we need additional randomization in the society profile that produces surprise within a cultural type?
|
||||
|
||||
**For Araminta:**
|
||||
- The era-stratification and zone-type parameters should drive visual coherence. Are the era tags (Era 1/2/3) and zone types (logistics/maintenance/institutional/residential) sufficient input for chunk fill visual rules?
|
||||
|
||||
---
|
||||
|
||||
**Status:** Round 1 complete.
|
||||
**Author:** Miri
|
||||
**Date:** 2026-02-27
|
||||
**Cross-reference:** Wiki Review Workshop Round 4 (Miri) — ingredients menu, society profile YAML spec, NPC pattern composition rules
|
||||
@@ -0,0 +1,598 @@
|
||||
# Generator Architecture Workshop — Round 2: Miri (Worldbuilder)
|
||||
|
||||
**Topic:** Worldbuilding for the broadened gameplay lens — multiple playstyles, non-urban terrain, insignificant places, edge bleed, cultural ingredients space size
|
||||
**Date:** 2026-02-27
|
||||
**Source:** Round 1 (all participants), Qatux round notes, lead directive
|
||||
|
||||
---
|
||||
|
||||
## Acknowledging the Lead Directive
|
||||
|
||||
*This is NOT a detective game. It is a game about the inherent asymmetry of human awareness.*
|
||||
|
||||
This reframe changes what the society profile must provide. In Round 1, I designed the society profile primarily through the lens of investigation. Every parameter pointed toward: how does this culture produce different investigation difficulty? What makes the grey economy more or less visible?
|
||||
|
||||
That was too narrow. The society profile must be a **playstyle-agnostic information structure**. What the detective uses as evidence, the tycoon uses as a price advantage, the political actor uses as leverage, and the romantic pursuer uses as emotional vulnerability. The underlying architecture is the same — information asymmetry — but the information TYPE and what it UNLOCKS differs per playstyle.
|
||||
|
||||
I'll work through this systematically.
|
||||
|
||||
---
|
||||
|
||||
## Section 1: The Society Profile as a Playstyle-Agnostic Structure
|
||||
|
||||
The society profile I defined in Round 1 already contains most of what multiple playstyles need. The gap is not the profile itself but **what information categories we're tracking** and **what actions they unlock**.
|
||||
|
||||
The core claim: information asymmetry is the game's universal mechanic. What changes across playstyles is:
|
||||
- **What information is valuable** (evidence, prices, affections, power leverage)
|
||||
- **How it's accessed** (surveillance, market observation, social bonding, institutional positioning)
|
||||
- **What it unlocks** (confrontation options, trade advantages, relationship phases, power leverage)
|
||||
|
||||
The society profile governs HOW information flows (trust model, privacy level, access tiers). What needs to be added are the **information type taxonomies** — what exists to know per playstyle.
|
||||
|
||||
---
|
||||
|
||||
## Section 2: Playstyle-Specific Information Vocabulary
|
||||
|
||||
### 2.1 Investigation (existing — confirmed R1)
|
||||
|
||||
**Information type:** Evidence of hidden activities
|
||||
**Access mechanism:** Observation, physical traversal, social trust, institutional credentials
|
||||
**Unlocks:** Confrontation options, exposure, arrest, exculpation
|
||||
|
||||
Already designed. Society profile provides: `privacy_level`, `trust.building_rate`, `access_tier.*`, `grey_economy.*`.
|
||||
|
||||
### 2.2 Tycoon (economic gameplay)
|
||||
|
||||
**Information type:** Economic intelligence — prices, supply chains, trade routes, competitor knowledge
|
||||
**Access mechanism:** Market observation, supplier relationships, contraband networks, faction briefings
|
||||
**Unlocks:** Trade advantages, supply route control, economic leverage, faction debt
|
||||
|
||||
The society profile parameters that drive tycoon gameplay are already partially present, but economic information needs its own vocabulary:
|
||||
|
||||
```yaml
|
||||
economic_information:
|
||||
trade_flows:
|
||||
surplus: [grain, recycled-metal, processed-protein] # what this world produces in excess
|
||||
deficit: [lattice-components, pharmaceutical-grade, rare-fabrication-stock] # what it imports
|
||||
choke_points: [span-gate-customs, logistics-hub-manifest-processing] # where trade is regulated
|
||||
|
||||
price_differential_drivers:
|
||||
- factor: faction_control # Commission control increases lattice component prices
|
||||
- factor: supply_disruption_risk # isolated world = vulnerability premium on essentials
|
||||
- factor: seasonal_demand # agricultural worlds have harvest-cycle price swings
|
||||
|
||||
economic_actors:
|
||||
dominant: syndic-consortium # sets baseline prices, controls infrastructure
|
||||
independent: [owner-operators, ring-adjacent-traders]
|
||||
absent: guilds # no formal guild structure in this region
|
||||
|
||||
information_barriers:
|
||||
# Who knows what before whom — the tycoon's asymmetric advantage
|
||||
syndic_knows: [upcoming_supply_disruptions, contract_prices, preferred_customs_routes]
|
||||
ring_knows: [actual_manifest_discrepancies, informal_price_tolerance, which_officers_turn_blind]
|
||||
worker_knows: [shift_patterns, cargo_composition, unofficial_storage_locations]
|
||||
outsider_knows: [official_listed_prices, public_trade_statistics, nothing_useful]
|
||||
```
|
||||
|
||||
**What this does for gameplay:** A player in tycoon mode is trying to acquire the SYNDIC KNOWS tier. The ring's knowledge layer is a shortcut — but using it has risk. The outsider layer is useless. The game is about climbing the information ladder before competitors do.
|
||||
|
||||
The cultural heritage profile modifies tycoon gameplay directly:
|
||||
- **Salt-heavy societies**: transactional, information trades happen quickly and at fair rates. "Tell me what the Syndic pays for grain and I'll tell you who the next customs officer rotation is."
|
||||
- **Frost-heavy societies**: information doesn't trade. You earn it through presence. The tycoon must invest time, not favors.
|
||||
- **Iron-heavy societies**: economic information is community property. Hoarding it for personal advantage is a cultural violation. But sharing it within the labor community is expected — which gives organized workers better tycoon information than independent operators.
|
||||
|
||||
### 2.3 Dating Sim (relationship gameplay)
|
||||
|
||||
**Information type:** Social and personal knowledge — what someone wants, what they fear, who they're connected to, what their history is
|
||||
**Access mechanism:** Shared experiences, trust-building, third-party gossip, observing behavior in different contexts
|
||||
**Unlocks:** Relationship phases (warmth → intimacy → vulnerability → declaration), access to private spaces, rival network neutralization
|
||||
|
||||
The society profile already handles the TRUST MECHANISM. What's missing is the **social venue diversity** and **relationship formation norms**:
|
||||
|
||||
```yaml
|
||||
social_venues:
|
||||
# Dating sim needs more social site types than the investigation-centric design assumed
|
||||
primary:
|
||||
- type: communal_meal_space # shared eating, low-stakes interaction, natural conversation
|
||||
- type: recreational_gathering # games, sports, performance — see the person relaxed
|
||||
- type: crisis_support_space # medical, emotional — high-vulnerability, high-trust
|
||||
- type: creative_work_space # collaborative creation, reveals character under pressure
|
||||
- type: private_domestic # invited into someone's home — meaningful social threshold
|
||||
|
||||
relationship_formation_norms:
|
||||
# Heritage-root-dependent — this is one of the strongest cultural variables
|
||||
frost: |
|
||||
Relationships form through proximity and shared endurance, not explicit signals.
|
||||
Expressing affection directly is uncomfortable and slightly aggressive.
|
||||
The romantic signal is: inviting someone to a shared task.
|
||||
"I thought you might want to help with the cargo rotation" = "I want to spend time with you."
|
||||
This plays very differently for a tycoon or detective who misreads it as a work request.
|
||||
|
||||
tide: |
|
||||
Relationships form publicly, through shared food, shared celebration, introductions
|
||||
to family. The romantic signal is inclusion in social gatherings. Introducing someone
|
||||
to your family is serious. Cooking for someone is an explicit statement. The barrier
|
||||
is managing group approval — everyone's opinion matters.
|
||||
|
||||
spice: |
|
||||
Relationships form through family networks. Third-party introduction is required.
|
||||
Direct pursuit is presumptuous or inappropriate. The game is gaining approval
|
||||
from the network before approaching the person directly. This creates an
|
||||
investigation-like social puzzle: map the network, identify the influencer,
|
||||
build the right relationships in the right order.
|
||||
|
||||
salt: |
|
||||
Relationships are transactional at initiation: "this benefits both of us."
|
||||
That sounds cold but isn't — Salt cultures build real intimacy, they just
|
||||
frame it practically. "I want to spend time with you because you're useful
|
||||
to me" evolves into "I want to spend time with you because you're mine."
|
||||
The evolution is the dating sim arc.
|
||||
```
|
||||
|
||||
**Rival networks as triangle structures:** The dating sim's rival relationship is structurally identical to the investigation triangle — three people with conflicting interests. The generator's D-024 triangle model works for romantic competition: NPC A wants X, NPC B wants X, player wants X, each has different leverage. The CONTENT differs (romantic relationship vs. criminal conspiracy) but the mechanical structure is the same.
|
||||
|
||||
This means the generator's triangle instantiation logic handles dating sim mechanics without modification. What changes is the **content tags** on the triangle nodes: `motivation: romantic-rival` vs. `motivation: operator`. The NPC 10-axis model already contains `Want` (relationship goal), `Secret/vulnerability` (what they're hiding), and `Tolerance threshold` (what they'll accept) — these are exactly the dating sim mechanics.
|
||||
|
||||
**Social venue diversity as a generator requirement:** The investigation-centric design produced one primary social site type (bar — shift-end social aggregation). Dating sim gameplay requires more types:
|
||||
- **Communal meal space** (low-stakes, natural conversation — distinct from the bar's crisis-adjacent social drinking)
|
||||
- **Recreational activity venue** (sports, games, performance — see the person under relaxed conditions)
|
||||
- **Domestic invitation threshold** (being invited home is a relationship milestone, requires a distinct spatial primitive)
|
||||
|
||||
These social site types are different TEMPLATES in the D-025 library, not different pipeline stages. The generator needs a richer template pool selection at the amenities stage that includes non-bar social venues. Template pack DLC is the right model here — the base game templates cover the investigation/tycoon cases; a social expansion pack adds the dating sim template library.
|
||||
|
||||
### 2.4 Political Drama (faction gameplay)
|
||||
|
||||
**Information type:** Power intelligence — who controls what, who wants what, what compromises exist, which positions are vulnerable
|
||||
**Access mechanism:** Institutional positioning, network cultivation, leverage acquisition, surveillance of faction actors
|
||||
**Unlocks:** Alliance formation, faction control shifts, position seizure, scandal detonation, reform
|
||||
|
||||
The society profile's faction presence tier gives the LANDSCAPE but not the TEXTURE. Political drama needs the internal dynamics of each faction:
|
||||
|
||||
```yaml
|
||||
political_structure:
|
||||
power_structure_type: oligarchic # few actors with clear but contested hierarchy
|
||||
# alternatives: democratic, feudal, revolutionary, absent
|
||||
|
||||
contested_positions:
|
||||
- position: district_administrator # currently weakly held; incumbent 2 years, insecure
|
||||
competitors: [commission_regional, syndic_consortium]
|
||||
leverage_held: [infrastructure_maintenance_authority, hiring_records]
|
||||
|
||||
faction_relationships:
|
||||
# Not just presence but HOW factions relate
|
||||
commission_to_syndic: pragmatic_alliance # overlapping interests, no deep trust
|
||||
commission_to_independent: surveillance # active suspicion, soft containment
|
||||
syndic_to_workers: extractive_dependency # workers need the jobs; Syndic knows it
|
||||
|
||||
leverage_map:
|
||||
# What each faction needs from others — the political game's resource
|
||||
commission_needs: [local_cooperation, manifest_accuracy, worker_testimony]
|
||||
syndic_needs: [labor_stability, customs_efficiency, Commission_indifference]
|
||||
workers_need: [fair_wages, lattice_access, protection_from_Commission]
|
||||
ring_needs: [blind_spots, trusted_couriers, storage_access]
|
||||
|
||||
destabilizing_information:
|
||||
# Secrets that, if revealed, shift power
|
||||
- secret: "District administrator is on the Syndic's informal payroll"
|
||||
if_revealed_to: commission
|
||||
effect: position_vacancy_plus_investigation
|
||||
- secret: "Commission inspector has been running ring-adjacent favors for 3 years"
|
||||
if_revealed_to: syndic_manager
|
||||
effect: informal_coercion_leverage
|
||||
```
|
||||
|
||||
**What cultural heritage does to political drama:**
|
||||
- **Frost societies**: political conflict is cold and indirect. Faction warfare is bureaucratic, institutional, conducted through records and procedures. A Frost-dominated political drama is about paper trails and procedural capture, not public confrontation.
|
||||
- **Iron societies**: political conflict is collective and labor-organized. Factions map to economic class. Political drama is about strikes, solidarity, collective action. The unit of power is the group, not the individual.
|
||||
- **Arc societies**: political conflict is intellectual and reputational. The weapons are arguments, papers, and public debates. The person who can DEMONSTRATE they're right gains power.
|
||||
|
||||
**The political drama and investigation crossover:** Political drama is investigation with a different goal. Investigation finds truth and decides what to do with it. Political drama is finding leverage and deciding how to deploy it. The knowledge graph (D-041) is the right architecture for both — the difference is what the player chooses to DO with `KnowsDetails`-tier information. The generator doesn't need to produce different spaces for political drama; it produces spaces where power is legible, and the player decides whether to expose or exploit what they find.
|
||||
|
||||
### 2.5 The Universal Layer Beneath All Playstyles
|
||||
|
||||
What I've worked through above reveals a unified structure:
|
||||
|
||||
**Every playstyle is a different reading of the same information landscape.**
|
||||
|
||||
| Playstyle | Reads the landscape as | Primary information type | Uses knowledge to |
|
||||
|---|---|---|---|
|
||||
| Investigation | A crime scene | Evidence of hidden activities | Expose/confront/arrest |
|
||||
| Tycoon | A market | Economic intelligence | Profit/control/leverage |
|
||||
| Dating sim | A social web | Personal knowledge/vulnerability | Form bonds/navigate rivals |
|
||||
| Political drama | A power structure | Leverage points/destabilizing secrets | Shift/seize/reform power |
|
||||
| Daily life (substrate) | A home | Social texture, belonging | Exist, build attachments |
|
||||
|
||||
The generator produces ONE information landscape. What varies is which information the player's archetype seeks and what they do with it. This means:
|
||||
- The society profile doesn't need playstyle-specific fields — it needs a RICHER information taxonomy that all playstyles can draw from
|
||||
- The template library (D-025) needs richer social site variety — not just investigation-optimal spaces
|
||||
- The faction presence model needs to expose internal dynamics, not just presence tiers
|
||||
|
||||
---
|
||||
|
||||
## Section 3: Non-Urban Terrain Types and the Ingredients Menu
|
||||
|
||||
The lead directive identifies: farmland, wilderness, secluded towns, ocean, boats, ski resorts, surf beaches. These are not population hubs. They need the generator, but not the same generator.
|
||||
|
||||
My framework: **same ingredients menu, different terrain grammar, different social site library**.
|
||||
|
||||
### 3.1 Agricultural / Rural Settings
|
||||
|
||||
**Society profile parameters (typical):**
|
||||
```yaml
|
||||
heritage:
|
||||
dominant_root: stone # land-connected, traditional, tenure-trust
|
||||
secondary: tide # or vine — warm community, family bonds
|
||||
drift_stage: ancient # agricultural settlements are often the oldest
|
||||
settlement_motivation: economic-agricultural
|
||||
economic_function: agriculture
|
||||
economic_pressure: [generational-extraction, tight-margin] # landlord-tenant or margin squeeze
|
||||
philosophical_alignment: land-stewardship # or null, or religious-traditional
|
||||
faction_presence:
|
||||
commission: nominal # present in theory, rarely acts
|
||||
syndic: absent_or_minor # or a land-holding corporation (different from logistics Syndic)
|
||||
local_governance: strong # elder councils, family heads, seasonal assemblies
|
||||
```
|
||||
|
||||
**Terrain grammar — different from station/city:**
|
||||
- No Z-levels. The map is ground-level with elevation variation (hills, valleys).
|
||||
- Blocks are farmstead clusters, not building blocks. A "block" might be one farm with outbuildings.
|
||||
- Infrastructure is roads/paths and water systems, not utility corridors.
|
||||
- Social sites are dispersed: farmstead (domestic/work), market town (periodic social aggregation), local tavern/meeting hall (permanent small social site), fields/common land (semi-public work space).
|
||||
|
||||
**Key generator difference:** Population is DISPERSED, not concentrated. The 4-8 NPC cluster radius of D-025 is too tight for agricultural settings. A farmstead's "social cluster" might be 3 people across 80 tiles — the farmer, their partner, their hired hand. The social site template library needs expanded radius limits for low-density settings.
|
||||
|
||||
**The information landscape in agricultural settings:**
|
||||
- Tycoon: land rights, crop prices, water allocation, trade route access to the nearest hub
|
||||
- Investigation: boundary disputes, inheritance conflicts, who the landlord's agent actually reports to
|
||||
- Dating sim: family approval (Spice/Stone/Vine heritage roots = family network gatekeeping)
|
||||
- Political drama: who controls the local assembly, who the landlord's representative is, what the seasonal laborers want
|
||||
|
||||
**Distinctive feature:** Agricultural settings have SEASONS. The game's time system (D-031 day phases) needs a longer-period layer — annual cycles — to fully represent agricultural social dynamics. Harvest festival = the major social aggregation event. Off-season = the grey economy's opportunity window (workers have time and reduced supervision). This is a significant generator parameter that urban settings don't need.
|
||||
|
||||
### 3.2 Wilderness / Uninhabited Terrain
|
||||
|
||||
Wilderness is not a settlement — it's a **terrain type that contains no permanent social sites**.
|
||||
|
||||
**Generator grammar:**
|
||||
- No society profile (no society)
|
||||
- No social site templates
|
||||
- Zone types: forest, mountain, water, open terrain, hazard zones
|
||||
- Structures are: temporary camps, resource extraction points, abandoned installations, natural cover
|
||||
- "Population" is: traversal NPCs (hunters, scouts, lost travelers), not residents
|
||||
|
||||
**What wilderness provides the generator:**
|
||||
- **Physical drama**: terrain hazards, navigation challenges, weather effects, cover and concealment
|
||||
- **Resource nodes**: what can be extracted here — feeding the tycoon pipeline
|
||||
- **Traversal topology**: connecting hub settlements, providing routes that avoid institutional oversight
|
||||
- **Historical markers**: ruins of earlier settlements, abandoned infrastructure, graves — Ozzie's "history encoded in space" without a living community
|
||||
|
||||
**Why wilderness matters for multiple playstyles:**
|
||||
- Investigation: meeting contacts away from Meridian coverage; traversal to reach isolated evidence
|
||||
- Tycoon: resource claims, extraction rights, trade route control
|
||||
- Dating sim: the romantic retreat — being somewhere isolated creates intimacy intensity (and vulnerability)
|
||||
- Political drama: the wilderness is where power vacuums are most complete; what fills them is the political story
|
||||
|
||||
**Generator rule for wilderness:** The absence of a society profile is itself a data point. When the generator produces wilderness chunks, the political condition is "unclaimed" — and unclaimed territory is always contested, because it has no enforcement. Someone is always trying to stake a claim. This is the wilderness's faction dynamic.
|
||||
|
||||
### 3.3 Secluded Towns / Small Settlements
|
||||
|
||||
**The "insignificant place" problem is actually the secluded town problem.** A small settlement (population 50-300) is a full society but very localized. Let me address both together in Section 4. Here, I'll note what the generator needs for small-scale spatial grammar:
|
||||
|
||||
- District = the entire settlement. No sub-districts.
|
||||
- Blocks are individual buildings.
|
||||
- Social sites are the same types but much smaller.
|
||||
- The single bar (or tavern, or meeting hall) IS the entire public social life.
|
||||
|
||||
**Small settlement society profiles:**
|
||||
- High drift novelty (isolated = less cosmopolitan blending, more local invention)
|
||||
- Strong insider/outsider dynamics (everyone knows everyone; a stranger is a social event)
|
||||
- Low faction presence (either completely abandoned by institutions or ruled by a single institution with no competitors)
|
||||
- High information concentration (one person can know everything about a small settlement within a week)
|
||||
|
||||
This last point is a significant generator constraint: **in small settlements, the information asymmetry structure is INVERTED**. In a city, the player struggles to learn what's hidden because information is siloed. In a small settlement, the player potentially learns everything fast — but there's less to learn, and the NPCs know the player knows. The grey economy in a small settlement is more personal, more precarious, and more morally loaded.
|
||||
|
||||
### 3.4 Maritime / Ocean Settings
|
||||
|
||||
**Physical grammar:**
|
||||
- Water tiles as traversal terrain (not walkable by default — requires vessel or swimming)
|
||||
- Vessels as mobile social sites
|
||||
- Ports as node concentrations
|
||||
- Tidal variation (game-time-driven environmental change)
|
||||
|
||||
**Society profile — port town:**
|
||||
```yaml
|
||||
heritage:
|
||||
primary: salt # pragmatic, transactional — all ports are trading nodes
|
||||
secondary: tide # flowing, community — maritime communities are tight-knit
|
||||
tertiary: iron # solidarity — maritime labor culture is historically strong
|
||||
settlement_motivation: economic-trade
|
||||
economic_function: transit # the port exists because of what passes through
|
||||
economic_pressure: [tight-margin, opportunity-disparity] # maritime labor is hard; the cargo wealth flows through, not to
|
||||
```
|
||||
|
||||
**Vessels as special social sites:**
|
||||
|
||||
Boats are bounded, mobile, intimate — and you cannot leave. This is one of the most extreme information asymmetry environments in the game:
|
||||
- **No exit**: you cannot walk away from a conversation. Walk-away consequences (D-064) become literal — "walking away" means going below deck, not leaving.
|
||||
- **Total observation**: everyone on the vessel knows everyone's movements. There are no blind spots on a small boat.
|
||||
- **Time-pressured**: the voyage ends. What happens on the boat is either resolved before arrival or explodes at the dock.
|
||||
|
||||
Vessels require a special social site template tag: `bounded_mobile`. This tag modifies:
|
||||
- Trust-building rate: FASTER (forced proximity accelerates relationship formation — for better or worse)
|
||||
- Privacy level: MUCH LOWER (physical impossibility of privacy on a small vessel)
|
||||
- Access topology: all zones accessible to all residents (no insider/authority separation without physical space)
|
||||
|
||||
**Ocean as wilderness:** Open ocean is wilderness with water terrain. The generator grammar is identical to land wilderness but with different traversal rules and different resource nodes (fishing grounds, salvage sites, submerged infrastructure).
|
||||
|
||||
### 3.5 Tourist Economy Settings (Ski Resorts, Surf Beaches)
|
||||
|
||||
These are structurally distinctive because they have **two simultaneous population profiles**: the service worker layer and the tourist/visitor layer.
|
||||
|
||||
**Dual society profile:**
|
||||
```yaml
|
||||
resident_profile:
|
||||
heritage: [whatever the local roots are]
|
||||
economic_pressure: [tight-margin, status-competition] # service workers watch wealth flow through
|
||||
economic_function: services
|
||||
trust_building_rate: LOW_FOR_TOURISTS # "you're not one of us; you're passing through"
|
||||
|
||||
visitor_profile:
|
||||
heritage: [varies — wherever they come from]
|
||||
economic_pressure: [null] # wealthy tourists have no economic pressure
|
||||
economic_function: leisure
|
||||
trust_building_rate: HIGH_FOR_LOCALS # "I'm here to relax, you're interesting, let's talk"
|
||||
# Visitor trust dynamic INVERTS: tourists are easy to befriend
|
||||
# but the friendship has a countdown (departure date)
|
||||
```
|
||||
|
||||
**The generator implication:** Tourist economy settings need two NPC pools with different social behaviors. Service worker NPCs behave like Iron/Salt/Frost cultural types in the workforce (reserved, labor-solidarity). Tourist NPCs behave like visitors — OPEN, friendly at surface, but with no investment in the place and no loyalty to its community.
|
||||
|
||||
The class contrast is explicit and spatial:
|
||||
- The beach/slope is public territory: tourists and workers briefly co-present
|
||||
- The worker housing and break rooms are insider territory: tourists excluded
|
||||
- The luxury accommodation is restricted territory: workers enter only in service capacity
|
||||
|
||||
This three-zone access structure maps cleanly onto Gestalt's access tier model (public/semi-public/private/restricted). The tourist economy setting is a natural generator case for teaching players about access tier systems — the gradient is visible and experiential.
|
||||
|
||||
**Why this matters for multiple playstyles:**
|
||||
- Tycoon: the money flows between visitor and resident. Who controls the access points controls the money.
|
||||
- Investigation: the impermanence of tourist population makes witness tracking harder. "She was here last week" is meaningless if the witness left on Sunday.
|
||||
- Dating sim: the vacation romance — a relationship with a departure date. Information asymmetry in its most poignant form.
|
||||
- Political drama: the resort's owner/operator versus the workers versus the tourists versus the environmental/planning authority. Classic conflicting interests.
|
||||
|
||||
---
|
||||
|
||||
## Section 4: Insignificant Places — The Worldbuilding of Unremarkable
|
||||
|
||||
*Not every world is center-stage. Backwaters, in-betweens, unremarkable stops. What makes a place insignificant in worldbuilding terms? How does the society profile handle "nothing special happens here"?*
|
||||
|
||||
### 4.1 What "Insignificance" Actually Is
|
||||
|
||||
Insignificance is not a property of the society profile. It's a **relation** — a place is insignificant RELATIVE to the wider network. Sova is insignificant relative to a Core World hub. Sova is enormously significant to Sector 3 residents whose entire lives are bounded by the station.
|
||||
|
||||
Scale of significance:
|
||||
- **Network-significant**: Located at a trade/gate chokepoint; Commission attention; Syndic investment; people come here for reasons
|
||||
- **Regionally significant**: Important within a cluster of nearby worlds; known to adjacent populations; occasionally in regional news
|
||||
- **Locally significant**: The center of its own community's world; matters deeply to the people there; invisible to outsiders
|
||||
- **Marginally located**: Transit stop only; no one lives here by choice; minimal community
|
||||
|
||||
What changes between levels: **Faction pressure**, **economic investment**, and **external attention**.
|
||||
|
||||
### 4.2 The "Insignificant" Society Profile
|
||||
|
||||
A backwater settlement:
|
||||
```yaml
|
||||
network_position: marginal_located # NOT strategically important
|
||||
faction_presence:
|
||||
commission: absent # not worth the budget
|
||||
syndic: absent # nothing to extract at scale
|
||||
local_governance: informal # self-governing by default, not by charter
|
||||
economic_pressure: [null] # no one is squeezing — there's nothing to squeeze
|
||||
economic_function: subsistence # or tourism, if lucky
|
||||
strategic_value: minimal
|
||||
```
|
||||
|
||||
**What this produces culturally:**
|
||||
|
||||
High `drift_novelty` — left alone, the community has developed genuine local quirks that more "significant" places have smoothed out in favor of cosmopolitan legibility. The insignificant place is often the most culturally DISTINCTIVE.
|
||||
|
||||
High `insider_trust_threshold` — strangers rarely come. When one does, everyone notices. The player is an event.
|
||||
|
||||
Low `information_density` — less is happening. But what IS happening is more visible. There are fewer layers of institutional obfuscation. The grey economy, if present, is one person in one back room, not a logistics ring spanning 200 workers.
|
||||
|
||||
**The paradox of the insignificant place:** For gameplay, insignificant places are often MORE dramatically interesting than significant ones. The conspiracy in an insignificant place is:
|
||||
- More personal (it's two or three people, not a network)
|
||||
- More visible (the community is small; secrets can't stay hidden forever)
|
||||
- More morally loaded (the stakes are local — what you do here affects everyone who lives here)
|
||||
- More unique (not the same plot as the big-hub adventure)
|
||||
|
||||
The generator should not treat insignificance as "less content to generate." It should treat it as a different content TYPE: intimate, local, high-stakes-for-small-scale.
|
||||
|
||||
### 4.3 The Significant and the Unremarkable — Contrast Design
|
||||
|
||||
For the 300-world model to avoid Second Station Syndrome (Ozzie's Sin #1), significant and insignificant worlds must feel categorically different, not just scale-adjusted.
|
||||
|
||||
Significant hub:
|
||||
- Multiple social sites
|
||||
- Faction pressure visible in architecture
|
||||
- Strangers are unremarkable
|
||||
- Player can be anonymous
|
||||
|
||||
Insignificant backwater:
|
||||
- One social site (the gathering place) serves all functions
|
||||
- No faction infrastructure
|
||||
- Player is immediately noticed and remembered
|
||||
- Player cannot be anonymous — everyone learns their name within hours
|
||||
|
||||
**Generator constraint from this:** The skeleton must parameterize `anonymity_baseline` — how visible is a new arrival? On Sova Transit District, a new face in the bar is unremarkable; hundreds pass through. In a village of 60 people, a new face is the news of the week. The player's information management challenge INVERTS: not "discover what's hidden" but "manage that you can't hide anything."
|
||||
|
||||
---
|
||||
|
||||
## Section 5: Edge Bleed — Cultural Zones Across Administrative Boundaries
|
||||
|
||||
*Districts are not islands. Cultural zones bleed across administrative boundaries.*
|
||||
|
||||
### 5.1 What Edge Bleed Is
|
||||
|
||||
An administrative boundary is a line on a map. Cultural reality does not respect it.
|
||||
|
||||
- The worker housing district bleeds into the freight district they walk through every day
|
||||
- The Commission-controlled gate cluster's institutional culture bleeds into the adjacent terminal
|
||||
- The market district's merchant culture bleeds into the first two blocks of the residential district
|
||||
- The old maintenance corridor subculture bleeds into any building with basement access
|
||||
|
||||
**Types of bleed:**
|
||||
|
||||
| Type | Direction | Mechanism |
|
||||
|---|---|---|
|
||||
| **Economic bleed** | From economically active to passive zones | Vendors set up just past the zone boundary; commercial behavior follows foot traffic |
|
||||
| **Faction bleed** | From high-control to low-control zones | Informants live in residential; Commission authority diffuses as social norm beyond formal boundary |
|
||||
| **Cultural bleed** | Bidirectional, slow | Heritage practices, language, naming conventions spread gradually into adjacent communities |
|
||||
| **Physical bleed** | From buildings/infrastructure | A building straddling a boundary creates ambiguous jurisdiction |
|
||||
| **Information bleed** | Bidirectional, fast | Gossip, news, rumors don't respect borders; the bar on the edge of two districts is the information exchange |
|
||||
|
||||
### 5.2 How the Generator Models Edge Bleed
|
||||
|
||||
Round 1's society profile describes a district as having one society profile. But real cultural geography is gradients, not flat fills.
|
||||
|
||||
**Proposed model: bleed gradient with decay distance**
|
||||
|
||||
At the center of a district, the society profile applies at 100% intensity. At the boundary, it's blended with adjacent districts. The blend distance is:
|
||||
- Short (2-4 blocks): sharp cultural boundary — different language, different customs, minimal mixing. This happens when the communities have high cultural distance AND the boundary is physically marked.
|
||||
- Medium (5-8 blocks): gradual transition. NPCs near the boundary speak with slight mixing; social norms are flexible; spaces serve both cultures. This is the normal case for adjacent districts with moderate cultural distance.
|
||||
- Long (9-16 blocks): extended transition — one culture is subordinate to the other, or both are very similar. This happens when two districts share heritage roots or when one has been culturally dominant for long enough to colonize the adjacent space.
|
||||
|
||||
**Cultural distance function:**
|
||||
|
||||
Two society profiles are CLOSE if they share: heritage roots, economic function, or similar faction presence tiers.
|
||||
Two society profiles are FAR if they differ on: heritage roots (incompatible social styles), economic function (creates class distance), faction presence (one is under heavy institutional pressure, the other isn't).
|
||||
|
||||
Cultural distance drives bleed distance inversely: HIGH cultural distance = SHORT bleed zone (cultures resist each other). LOW cultural distance = LONG bleed zone (cultures flow together).
|
||||
|
||||
**Example: Sova Station**
|
||||
- Transit District ↔ Residential Core: medium cultural distance (similar heritage, different function). Medium bleed zone. Workers commuting between them carry Transit District culture into the Residential Core gradually; Residential Core's domestic culture bleeds back.
|
||||
- Transit District ↔ Administrative Hub: HIGH cultural distance (Frost-labor culture vs. institutional-authority culture; completely different faction presence tiers). Short bleed zone. The boundary feels hard.
|
||||
- Residential Core ↔ Commercial Quarter: Low cultural distance (similar population, different commerce level). Long bleed zone. The neighborhood-adjacent-to-commercial-district feels like the commercial district in texture.
|
||||
|
||||
### 5.3 Social Sites at Boundaries as Information Exchanges
|
||||
|
||||
The most interesting NPCs in the game are the ones who live on cultural boundaries. They have access to both cultures. They're trusted by neither completely, which makes them interesting for investigation (they see both sides) and dating sim (their dual identity is its own drama).
|
||||
|
||||
**Generator rule:** The boundary bleed zone should contain at least one social site with MIXED cultural access tiers — where both adjacent district cultures feel equally eligible. This is the border bar, the neutral ground café, the market stall that serves both communities.
|
||||
|
||||
These mixed social sites are generators of:
|
||||
- Cross-triangle triangles (D-024 cross-template triangles — the members literally live in different districts)
|
||||
- Translation figures (NPCs who move between cultures — high information value)
|
||||
- Cultural friction (the place where Heritage Root A and Heritage Root B interact, which means their TRUST MODELS interact — and different trust models produce misunderstandings, offenses, and unexpected alliances)
|
||||
|
||||
### 5.4 Faction Bleed vs. Cultural Bleed
|
||||
|
||||
These are distinct types that behave differently:
|
||||
|
||||
**Faction bleed** decays in a radius from faction infrastructure. A Commission checkpoint creates surveillance culture (NPCs modify behavior) for ~3-5 blocks in any direction, regardless of district boundaries. The formal jurisdiction stops; the social norm doesn't.
|
||||
|
||||
**Cultural bleed** follows foot traffic patterns more than distance. Culture flows along the routes people actually walk. A maintenance corridor that connects two districts of very different cultures is a cultural conduit — the workers who use it daily carry elements of each culture to the other.
|
||||
|
||||
**The generator should model both separately:**
|
||||
- Faction bleed: a `radius_effect` from faction infrastructure, decaying by block distance
|
||||
- Cultural bleed: a `flow_path_effect` along actual NPC movement corridors, strongest along high-traffic routes
|
||||
|
||||
This distinction matters for gameplay: the detective can predict faction bleed (it's geometric). Cultural bleed is harder to predict — you have to know how people actually move.
|
||||
|
||||
---
|
||||
|
||||
## Section 6: Answering Nigel's Question — Cultural Ingredients Space Size
|
||||
|
||||
Nigel asked directly: "How large is the cultural ingredients space? The variety payoff depends on how many distinct ingredient combinations produce distinguishable district personalities."
|
||||
|
||||
### 6.1 The Combination Count
|
||||
|
||||
Let me enumerate this properly:
|
||||
|
||||
**Heritage Root blending** (primary driver of cultural feel):
|
||||
- 10 roots available
|
||||
- Select 1-3 (with blend weights at 0.1 granularity for meaningful differences)
|
||||
- Pure single-root: 10
|
||||
- Two-root blends: C(10,2) × ~5 weight distributions = 45 × 5 = 225
|
||||
- Three-root blends: C(10,3) × ~10 weight distributions = 120 × 10 = 1,200
|
||||
- **Total: ~1,435 meaningfully distinct heritage profiles**
|
||||
|
||||
**Settlement Motivation:** 9 types + NULL = 10 states
|
||||
|
||||
**Economic Function:** 11 types (10 + mixed/diversified) + NULL = 12 states
|
||||
|
||||
**Economic Pressure:** 7 types, pick 0-2 = 1 (null) + 7 (single) + 21 (pairs) = **29 states**
|
||||
|
||||
**Drift Stage:** 4 stages (pioneer / crystallizing / mature / ancient)
|
||||
|
||||
**Faction Presence:** 3 institutions (Commission, Syndic, Assembly/local-governance) × 5 presence levels (comprehensive / standard / intermittent / absent / hostile) = 5³ = 125 combinations; realistically ~30-40 plausible combinations
|
||||
|
||||
The raw combination count is astronomical. But "distinct for the player" is a tighter constraint.
|
||||
|
||||
### 6.2 The Gameplay-Distinguishable Space
|
||||
|
||||
Five parameters drive most of the GAMEPLAY FEEL differentiation:
|
||||
|
||||
| Parameter | Distinguishable states | Driver |
|
||||
|---|---|---|
|
||||
| Heritage Root primary + secondary | ~100-150 (blends, accounting for dominance) | Social style, trust mechanism, naming feel |
|
||||
| Economic Pressure combination | ~20 | Grey economy moral texture |
|
||||
| Faction Presence tier | ~12 | Investigation difficulty, access structure |
|
||||
| Drift Stage | 4 | How "foreign" the culture feels |
|
||||
| Economic Function | ~8 (plus 3 terrain types) | Daily rhythm, investigation vector |
|
||||
|
||||
Rough gameplay-distinguishable space: 100 × 20 × 12 × 4 × 8 = 768,000 combinations before overlap. With a generous overlap factor of ~100× (many combinations produce similar GAMEPLAY even if culturally distinct): **~7,700 meaningfully distinct game-mechanical experiences**.
|
||||
|
||||
**My answer to Nigel:** The ingredients space is not a limitation at 300 worlds. Even with aggressive pruning for plausibility (many combinations are impossible or implausible — a Commission-absent world with comprehensive Meridian coverage, for instance), the playable space exceeds 1,000 truly distinct district personalities. At 300 worlds, we're sampling a small fraction of the available space.
|
||||
|
||||
Nigel's calculation (300 × 2 characters × 20 cultural compositions = 12,000 games) was using the conservative "20 distinct compositions" assumption. The actual distinguishable composition space is ~1,000-7,700+. His calculation scales accordingly: **300 × 2 × 100 minimum cultural compositions = 60,000 meaningfully distinct games before factoring seed variation**.
|
||||
|
||||
**One caveat:** The practical limit is not the combination space but the **authored template library depth**. If we only have 10 D-025 templates, the 100th cultural composition will still draw from the same 10 templates. Cultural variety without template variety means the CULTURAL feel changes but the SPATIAL feel repeats. Template library expansion is the binding constraint, not the ingredients space.
|
||||
|
||||
### 6.3 The DLC Model for Template Expansion
|
||||
|
||||
Setting note — the lead directive mentions "Template packs per DLC is a valid expansion model." This is correct and the ingredients menu makes it tractable.
|
||||
|
||||
**How it works:**
|
||||
- The base game ships templates for: logistics, residential, administrative, bar/social, maintenance, gate cluster
|
||||
- DLC pack "Agricultural Worlds" adds: farmstead, granary, rural tavern, market day, seasonal camp, mill complex
|
||||
- DLC pack "Maritime Settlements" adds: fishing dock, harbor bar, vessel interior, lighthouse, chandlery
|
||||
- DLC pack "Leisure Economies" adds: resort lodge, surf shack, mountain chalet, seasonal service housing
|
||||
|
||||
Each DLC pack expands which templates are eligible for each ingredient combination. The ingredients menu and society profile remain unchanged — new DLC just extends the template pool that the generator draws from.
|
||||
|
||||
This is the correct DLC model because: players who don't buy the DLC don't encounter broken world generation. They just don't see those setting types. The generator gracefully falls back to base game templates if a DLC template is selected but unavailable.
|
||||
|
||||
---
|
||||
|
||||
## Summary: What Round 2 Adds to the Generator Architecture
|
||||
|
||||
**New contributions:**
|
||||
|
||||
1. **Playstyle-agnostic information vocabulary** — society profile extended with economic information taxonomy, relationship formation norms (heritage-root-dependent), power structure internals. All playstyles read the same generated landscape through different lenses.
|
||||
|
||||
2. **Non-urban terrain grammar** — same ingredients menu, five new terrain types with different spatial primitives:
|
||||
- Agricultural: dispersed farmstead clusters, seasonal cycles, expanded D-025 radius limits
|
||||
- Wilderness: no society profile; resource nodes, traversal terrain, historical markers only
|
||||
- Small settlements: district = entire settlement; high anonymity risk; inverted information asymmetry
|
||||
- Maritime: water terrain tiles, vessel as bounded-mobile social site, port node concentration
|
||||
- Tourist economy: dual NPC population profiles, explicit class contrast, time-bounded visitor relationships
|
||||
|
||||
3. **Insignificant places** — insignificance as a relational parameter, not a content-reduction parameter. The "insignificant place" society profile produces: high drift novelty, high insider threshold, inverted anonymity, intimate conspiracy scale. Distinct content type, not scaled-down hub.
|
||||
|
||||
4. **Edge bleed** — two distinct types (faction bleed = radius-geometric; cultural bleed = flow-path-along-movement-routes). Bleed distance driven by cultural distance function. Boundary social sites as cross-cultural information exchanges.
|
||||
|
||||
5. **Cultural ingredients space size** (answering Nigel) — raw combination space is hundreds of thousands; gameplay-distinguishable space is ~1,000-7,700+ compositions. 300 worlds uses ~5-30% of the available variety. Binding constraint is template library depth, not ingredients space.
|
||||
|
||||
6. **DLC as template library expansion** — ingredients menu stays stable; DLC adds eligible templates per ingredient combination. Correct model for extending to new setting types.
|
||||
|
||||
---
|
||||
|
||||
**Status:** Round 2 complete.
|
||||
**Author:** Miri
|
||||
**Date:** 2026-02-27
|
||||
**Questions for Round 3:**
|
||||
- Gestalt: Does the playstyle-agnostic information vocabulary require changes to the D-025 template spec, or just content tags on template nodes?
|
||||
- Tyre: Can the `bounded_mobile` social site flag work within the existing chunk architecture? (Vessels move — this might require an entity-carried chunk, which is architecturally complex.)
|
||||
- Nigel: Does cultural ingredients space calculation satisfy your variety guarantee? Does the binding constraint (template library depth) change your replayability architecture?
|
||||
- Araminta: Non-urban terrain types need different visual grammar inputs (no zone palettes for wilderness, different material vocabulary for agricultural settings). Are the era-tag and zone-type inputs sufficient to drive visual coherence in these settings, or do we need new parameters?
|
||||
@@ -0,0 +1,290 @@
|
||||
# Generator Architecture Workshop — Round 3 Supplement: Miri (Worldbuilder)
|
||||
|
||||
**Topic:** Destructible boundaries, vertical social stratification, entity-carried chunks (trains/ships), grid vs. organic by heritage root
|
||||
**Date:** 2026-02-27
|
||||
**Context:** This supplements miri-round3.md, which was filed before the full Round 3 broadcast arrived. Four directives from the broadcast required worldbuilding perspective that the main document didn't address.
|
||||
|
||||
---
|
||||
|
||||
## Supplement 1: Destructible Boundaries — What's Behind the Wall
|
||||
|
||||
*Lead directive: what's behind a wall the player blows open?*
|
||||
|
||||
This is a pure worldbuilding question before it's a technical one. The answer depends on WHAT THAT WALL IS DOING in the cultural and historical context it was built in.
|
||||
|
||||
### 1.1 Wall Typology — Why Walls Exist
|
||||
|
||||
Walls are built for specific reasons, and the reason determines the worldbuilding content on the other side:
|
||||
|
||||
**Privacy walls** — separating domestic/private space from public/semi-public space. Common in Spice, Jade, and Frost heritage settings. What's behind them: domestic life, family space, private arrangements that weren't meant to be observed. The content is intimate, often mundane, occasionally revealing.
|
||||
|
||||
**Authority walls** — defining institutional territory. What Commission jurisdiction looks like physically: reinforced barriers, access control, clearly marked transitions. Behind Commission authority walls: operational infrastructure (records storage, personnel areas, evidence holding). The content is institutional — paperwork, equipment, records of what the Commission has been doing.
|
||||
|
||||
**Security walls** — concealing high-value assets. Syndic logistics operations, grey economy storage, faction caches. These are built to HIDE something. What's behind them is the thing they were hiding. The content is the grey economy made physical: unlicensed inventory, contraband, documentation of prohibited activities, sometimes people.
|
||||
|
||||
**Structural walls** — load-bearing divisions that weren't primarily about separation but became that. What's behind them depends on era tag: Era 1 walls sealed over may contain original infrastructure (utility runs, passages that were blocked when the era changed), sometimes abandoned equipment or materials left in place when the area was repurposed.
|
||||
|
||||
**Cultural/heritage walls** — built for reasons that only make sense in specific heritage contexts. A Spice-heritage compound wall defines family honor territory. A Frost-heritage barrier between residential and operational is about psychological separation (noise, smell, the intrusion of public life). An Iron-heritage wall around the union hall is a claim of territory.
|
||||
|
||||
### 1.2 Heritage Root and What the Breach Means
|
||||
|
||||
Blowing open a wall is not culturally neutral. What matters is not just what's there but **how the community interprets the act of breach**.
|
||||
|
||||
**Frost heritage:** Walls are the physical expression of privacy as a value. Breaking through one is a profound violation regardless of what's found. A Frost community will respond to an unauthorized breach even if the contents are innocent. The breach itself is the offense. For the investigator or assassin: entering a Frost space through a destroyed wall marks them as someone who doesn't respect boundaries — which in a Frost culture is a serious social flag.
|
||||
|
||||
**Iron/Dust heritage:** Walls define collective territory. Breaching a wall into a union hall or communal storage means intruding on the group's shared space — it's an attack on the collective. The community responds collectively. The content behind the wall (collective resources, organizing records, mutual aid supplies) is community property, and damaging access to it is an attack on the community.
|
||||
|
||||
**Spice heritage:** The family compound wall is honor-adjacent. A breach is an insult to the family. What's inside is family-private space — domestic, intimate, potentially containing the family's most protected relationships and secrets. The breach creates a vendetta obligation in some Spice-heritage contexts.
|
||||
|
||||
**Salt heritage:** Walls are contractual, not sacred. If you breach a wall, you owe something for it. The content is commercial inventory, records, assets. A Salt community may tolerate the breach if appropriate compensation is offered. They'll want payment.
|
||||
|
||||
**Arc heritage:** Walls around intellectual/operational spaces contain RECORDS. The Arc community will care intensely about the integrity of what's behind — not the breach itself but the potential disruption to ordered knowledge. Behind an Arc wall: labeled storage, research records, documentation of ongoing work. The content is information in organized form.
|
||||
|
||||
### 1.3 Era Tag and Physical Contents
|
||||
|
||||
The era tag on the wall's block determines what's behind it structurally:
|
||||
|
||||
**Era 1 wall (sealed over time):** The oldest sealed spaces contain the building's original purpose. In a station, this means the infrastructure of earliest construction — original transit passages, the plumbing and electrical paths laid before the upper layers, sometimes abandoned rooms that were simply walled off when the superstructure changed. Content includes original structural materials (different from the visible surface), possibly Era 1 equipment abandoned in place, historical markers (founding dates, workers' marks in the walls, construction refuse).
|
||||
|
||||
**Era 2 wall (intermediate period):** This was sealed during the commercial/operational expansion. Behind it: infrastructure supporting an intermediate-era function that's no longer visible from the current space. A logistics terminal that became a residential corridor — the Era 2 wall might conceal cargo-bay equipment, commercial-grade storage installations, commercial transit systems. Also: the era transition often produced conflict. Era 2 walls may seal spaces that were abandoned during economic disruption — with the contents of that disruption preserved.
|
||||
|
||||
**Era 3 wall (recent):** Recent walls are planned. What's behind them is known — or should be. The absence of official knowledge about Era 3 content is itself suspicious. A recently sealed wall in an active district with no official record of what's there: someone sealed something deliberately and recently.
|
||||
|
||||
### 1.4 Generator Requirement
|
||||
|
||||
**Every block face that can be breached must carry a `behind_boundary` descriptor:**
|
||||
|
||||
```yaml
|
||||
behind_boundary:
|
||||
content_type: private_domestic | authority_operational | economic_storage |
|
||||
structural_original | abandoned_era | active_concealment
|
||||
era: era1 | era2 | era3
|
||||
cultural_sensitivity: low | medium | high | extreme
|
||||
# extreme = Spice family compound; Iron union hall; Frost private residential
|
||||
contents_hint: null | infrastructure | records | inventory | persons | evidence
|
||||
breach_consequence:
|
||||
immediate: null | alarm | NPC_response | environmental_hazard
|
||||
social: none | community_sanction | faction_response | vendetta_trigger
|
||||
```
|
||||
|
||||
The `behind_boundary` descriptor is generated at Phase 1 (district skeleton / block planning) and stored in the `BlockSkeleton`. It is NOT revealed to the player until the wall is breached — but it informs the generation of what gets spawned when the breach occurs.
|
||||
|
||||
---
|
||||
|
||||
## Supplement 2: Vertical Scale — The 50-Floor Skyscraper
|
||||
|
||||
*Lead directive: how does a 50-floor skyscraper emerge from the generator?*
|
||||
|
||||
### 2.1 Why Vertical Space Exists in Specific Cultures
|
||||
|
||||
Vertical architecture is not culturally neutral. Cultures build tall for different reasons, and the reason shapes the internal vertical social organization:
|
||||
|
||||
**Corporate/Syndic cultures** build tall for efficiency and status display. The building is an asset and a symbol. Height signals wealth. This creates the classic vertical hierarchy: lobby (public/commercial), office floors (operational), executive floors (top). Frost + corporate economic function produces this pattern reliably.
|
||||
|
||||
**Institutional/Commission cultures** build tall for administrative organization and security. The building is infrastructure. Height creates defensible institutional core. The pattern is different: lower floors are public-facing (reception, public services), middle floors are operational, upper floors are not executive suites but records and security operations. Access tightens as you go up.
|
||||
|
||||
**Labor/Iron cultures** do NOT build tall by choice. Vertical housing is often imposed by economic constraint (urban density) or by prior ownership (inhabiting a building built by a different cultural actor). Iron-heritage communities in vertical buildings create horizontal solidarity networks across floors — the floor as community unit, not the building as hierarchy.
|
||||
|
||||
**Spice-heritage communities** adapt vertical architecture to family organization. The extended family may occupy multiple floors of the same building with internal connections between floors — a vertical family compound. Outsiders may occupy other floors of the same building with no relationship to the Spice-family floors.
|
||||
|
||||
### 2.2 The Vertical Social Hierarchy
|
||||
|
||||
The Z-level model established in D-093 (z=0 maintenance, z=1 operational, z=2 institutional/gate) maps onto vertical buildings differently than onto the station's broader district structure.
|
||||
|
||||
In a tall building within a station or urban setting:
|
||||
|
||||
| Floor range | Social function | Typical occupants | Cultural variation |
|
||||
|---|---|---|---|
|
||||
| Ground (z=0 equiv.) | Public-facing commerce or passage | Anyone; high traffic | Little — street interface is universal |
|
||||
| Lower floors (z=1-3) | Work functions, commercial operations | Workers, service functions | Heavy — Iron cultures push worker facilities down; Frost cultures push worker facilities down differently (clean separation) |
|
||||
| Mid floors | Administrative, secondary residential | Mixed | Moderate — depends on economic function |
|
||||
| Upper floors | Residential (valuable) OR operational (secure) | Wealth OR security | Strongest cultural variation here |
|
||||
| Top floors | Penthouse OR secure operations | Varies entirely by culture | Frost-corporate = executive; Commission-Jade = secure records; Arc = observatory/library; Iron = reclaimed community |
|
||||
|
||||
**The important conflict:** In station architecture, z=0 is MAINTENANCE (lowest status); z=2 is institutional/gate (highest). In standard tall buildings, the top floor is highest status. When a tall building is grafted onto station spatial logic, these conventions can CONFLICT — creating the visible cultural tension of "who actually has power here?" The building where the maintenance workers are on the same floor as the executive offices (because the executive floor is near the gate infrastructure) tells you something specific about this station's power structure.
|
||||
|
||||
### 2.3 Generator Requirements for Vertical Scale
|
||||
|
||||
The current D-094 hierarchy (region/district/block/chunk) handles z-levels via stacked chunk layers. A 50-floor skyscraper is not 50 district-level z-levels — it's 50 chunk-stack layers within a SINGLE block footprint.
|
||||
|
||||
**Setting note for Tyre:** A skyscraper is a multi-z-level single-block structure with:
|
||||
- One or more block footprints on the ground level
|
||||
- N chunk layers stacked, each 64×64 tiles, each z-level a floor
|
||||
- The social profile of the BUILDING follows the vertical hierarchy rules above
|
||||
- Each z-level chunk inherits era tags from the block but has a separate `floor_function: FloorFunction` field
|
||||
|
||||
The generator needs to know, at block planning time (Phase 1 Stage 3), whether a block is a TOWER BLOCK — flagged to generate multiple z-levels rather than a single operational level. This is a `BlockSkeleton` property: `tower: Option<TowerConfig>` where `TowerConfig` records number of floors, floor function assignments, and the vertical social profile derived from the society profile.
|
||||
|
||||
**The worldbuilding content per floor is derived from the vertical social hierarchy table above.** The generator applies the table with heritage root modifiers. An Iron-heritage corporate building and a Frost-heritage corporate building with the same number of floors will have their social zones distributed differently.
|
||||
|
||||
### 2.4 What Makes the Skyscraper Interesting Gameplay-Wise
|
||||
|
||||
**Vertical information asymmetry:** People on the upper floors have information about what happens on the lower floors (they commissioned it, they receive reports, they ordered it). People on the lower floors have information about the upper floors that upper-floor residents don't know they have (maintenance workers know what equipment is running, what's being shipped, who visits). The skyscraper is a compressed information gradient. The investigator ascending through a corporate tower is climbing the information ladder physically.
|
||||
|
||||
**Cross-floor social triangles:** A triangle where NPC A is on floor 3, NPC B is on floor 17, and NPC C is on floor 42 is a cross-floor triangle. The staging ground challenge is different — the player needs ACCESS to multiple floors to work the triangle. The access tier system maps to floors in a tower, not just horizontal zones.
|
||||
|
||||
**The assassination tower problem:** A high-value target on the 42nd floor has an implied protection architecture: limited vertical access, controlled entry points, security in the vertical corridor. The assassin's problem is a vertical architecture puzzle. Escape routes are the same — you can go down but not sideways until you exit the building. The informal zone in a corporate tower is the maintenance infrastructure (utility shafts, service elevator, roof access).
|
||||
|
||||
---
|
||||
|
||||
## Supplement 3: Entity-Carried Chunks Beyond Vessels — Trains and Spaceships
|
||||
|
||||
I covered maritime vessels in Round 2. Round 3 makes entity-carried chunks CORE and adds trains and spaceships. The worldbuilding differs meaningfully per vehicle type.
|
||||
|
||||
### 3.1 Trains — The Bounded Linear Society
|
||||
|
||||
The maritime vessel is bounded-spherical (you can move throughout the vessel, which is a small total space). A train is **bounded-linear** — you can move through it from end to end, but the ends are as far apart as they are.
|
||||
|
||||
**The train's social grammar:**
|
||||
|
||||
Trains compress multiple social tiers into a physical sequence. The typical car sequence (from front/premium to rear/economy): observation/premium → standard passenger → general class → cargo. This is a PHYSICAL EXPRESSION of the social hierarchy that the player can observe simply by walking through the train.
|
||||
|
||||
Heritage root variation on train social organization:
|
||||
- **Frost heritage passenger car**: minimal interaction, compartmentalized seating, high privacy expectation. Everyone minds their own business. Information is not shared.
|
||||
- **Tide heritage passenger car**: communal orientation, groups eat together, children move between cars, conversation across compartment boundaries is normal. Information flows freely — and includes information about everyone on the train.
|
||||
- **Iron heritage work train** (carrying labor to a site): collective space, political awareness, workers know each other, mutual solidarity active. An outsider on an Iron labor train is immediately noticed.
|
||||
|
||||
**What makes trains distinctive for gameplay:**
|
||||
|
||||
- **Temporal pressure**: the destination is known and approaching. Whatever needs to happen on the train must happen before arrival.
|
||||
- **Witness compactness**: everyone who matters to the scenario is on the same vehicle. No one leaves. Cross-examination and confrontation are possible in ways that aren't in open-world settings.
|
||||
- **Social compression**: the shared experience of travel creates artificial intimacy. Dating sim dynamics accelerate on trains because you're physically in close proximity with the same people for extended periods.
|
||||
- **Information lock**: what happens on the train is sealed until arrival. The investigation play on a train is fully contained — but also can't get outside support.
|
||||
- **Assassination on a train**: a CLASSIC scenario type for a reason. The target can't escape. The witnesses can't leave. The aftermath begins at arrival. The assassin's problem is managing all of this in a confined linear space.
|
||||
|
||||
**Generator requirement for trains:**
|
||||
`SettingType::BoundedLinear` — a variant of the `bounded_mobile` tag. The chunk is mobile, carried by an entity (the train), and has a **linear access topology** (you can progress from one end to the other, with optional locked compartments). The social site tags on a train are car-typed: `premium_car`, `general_car`, `cargo_car`, `service_car`, each with its own social density and access rules.
|
||||
|
||||
### 3.2 Spaceships — The Total Information Environment
|
||||
|
||||
A spaceship in transit is the most extreme information asymmetry environment in the setting. Not because it's bounded (so is a vessel or a train) but because it is **between systems**.
|
||||
|
||||
**What "between systems" means culturally:**
|
||||
|
||||
During interstellar transit via the horizon gate network, the ship is in the gate conduit — physically in neither origin nor destination system. Normal institutional jurisdiction is suspended (which Commission has authority in transit?). Normal communication with external parties is interrupted (no message traffic possible in transit). The crew and passengers are alone in a way that no other setting achieves.
|
||||
|
||||
The sociological effect: **transit strips social roles**. The powerful person on the ship cannot call for backup. The institutional authority figure cannot enforce through external threat. The information bottleneck is total — nothing you know or reveal can exit the ship until arrival.
|
||||
|
||||
Heritage root behavior during spaceship transit:
|
||||
- **Frost**: doubles down on privacy. In a suspended institutional environment, the default is LESS interaction, not more. Information is even more guarded.
|
||||
- **Tide**: expands. The community of the ship becomes the relevant community for the duration. Social bonds form faster. Information flows within the ship-community.
|
||||
- **Arc**: the transit period is time for discourse. The suspended institutional context is an opportunity for conversation that wouldn't happen with normal social stakes present.
|
||||
- **Salt**: commerce that couldn't happen under normal jurisdiction now can. The transit period is a grey-market window.
|
||||
|
||||
**The spaceship social site types:**
|
||||
- **Crew quarters** — insider space (crew only), the social hub of the working community
|
||||
- **Passenger areas** — mixed access, varying by class of ticket
|
||||
- **Bridge/operations** — institutional space, crew credentials required
|
||||
- **Cargo hold** — the informal zone equivalent (no social occasion for most passengers to be there)
|
||||
- **The airlock** — the most extreme "place too small to be safe" (Ozzie's spatial archetype #5)
|
||||
|
||||
**Assassination on a spaceship**: extreme in both directions. The target CANNOT ESCAPE until arrival. But neither can the assassin. Evidence management is impossible — there's nowhere to dispose of evidence that won't be found when the ship docks. Post-arrival institutional scrutiny begins immediately. The spaceship assassination is only viable if the investigation can be controlled at destination, which means the assassin needs assets waiting at the other end.
|
||||
|
||||
### 3.3 The Cultural Grammar of Transit
|
||||
|
||||
Across all entity-carried chunks (vessel, train, spaceship), one cultural constant applies: **transit reveals character**. The normal social infrastructure that regulates behavior (institutional enforcement, community surveillance, professional role performance) is attenuated in transit. What people do when the normal constraints are loosened tells you who they actually are.
|
||||
|
||||
This is the deepest gameplay value of entity-carried chunks: not just bounded space for investigation, but a setting where the information asymmetry becomes especially acute because everyone's masks slip a little.
|
||||
|
||||
**Generator rule:** Entity-carried chunks should have a `transit_social_modifier` that adjusts:
|
||||
- `trust.building_rate`: increases (forced proximity)
|
||||
- `social.privacy_level`: decreases (can't leave)
|
||||
- `cultural_norms.enforcement_level`: decreases (institutional authority attenuated)
|
||||
- `information_flow.internal`: increases (nowhere else to talk)
|
||||
- `information_flow.external`: blocked until arrival
|
||||
|
||||
---
|
||||
|
||||
## Supplement 4: Grid Breathing — Which Cultures Produce Which
|
||||
|
||||
*Lead directive: BOTH grid and organic. Some blocks are grid, some organic chaos. Architecture must support both.*
|
||||
|
||||
This is a worldbuilding question with a clear answer: **grid vs. organic is determined by who built it, when, and under what power conditions**.
|
||||
|
||||
### 4.1 Grid = Power Imposed; Organic = Power Negotiated
|
||||
|
||||
**Grids emerge when:**
|
||||
- A single authority planned the space before construction
|
||||
- The authority had sufficient power to enforce the plan throughout construction
|
||||
- The time pressure was low enough for systematic planning
|
||||
- The cultural value is ORDER as inherently correct
|
||||
|
||||
**Organic patterns emerge when:**
|
||||
- Multiple actors built incrementally over time
|
||||
- No single authority had full control
|
||||
- Time pressure forced immediate construction without planning
|
||||
- The cultural value is FUNCTION over form
|
||||
- The terrain demanded deviation (natural features that planners worked around)
|
||||
|
||||
This means the district's **founding conditions** are the primary driver:
|
||||
|
||||
| Founding condition | Grid tendency | Organic tendency |
|
||||
|---|---|---|
|
||||
| Commission-planned | STRONG | Weak |
|
||||
| Syndic corporate development | Strong | Weak |
|
||||
| Colonial imposition | STRONG | Weak |
|
||||
| Worker/labor organic settlement | Weak | STRONG |
|
||||
| Frontier/pioneer | Weak | STRONG |
|
||||
| Spice family compound networks | — | Medium (family logic, not geometry) |
|
||||
| Arc institutional design | Strong | — |
|
||||
| Gradual accretion over eras | Weak | STRONG |
|
||||
| Single development event (urban planning) | STRONG | — |
|
||||
|
||||
### 4.2 Heritage Root and Grid Preference
|
||||
|
||||
| Heritage Root | Preference | Why |
|
||||
|---|---|---|
|
||||
| **Frost** | Grid (operational zones), organic (residential) | Work is organized; private life doesn't need to be legible to others |
|
||||
| **Tide** | Organic | Community space evolves from social patterns, not planning |
|
||||
| **Iron** | Organic | Workers built their own spaces; no planner controlled the process |
|
||||
| **Spice** | Semi-organic | Follows family network logic — clusters, not grids |
|
||||
| **Jade** | Grid with deliberate irregularity | Order appreciated; but variety is necessary for beauty |
|
||||
| **Dust** | Organic | Survival-driven; build what you need, where you need it |
|
||||
| **Vine** | Organic | Social warmth = built space following relationship patterns |
|
||||
| **Salt** | Grid (commercial zones) | Commercial clarity; buyers need to find sellers |
|
||||
| **Stone** | Semi-grid | Permanence favors planning; but generational accretion adds organic layers |
|
||||
| **Arc** | Grid | Rational organization is a core value |
|
||||
|
||||
### 4.3 The Within-District Grid/Organic Mix
|
||||
|
||||
**This is where it gets interesting for the generator.** A single district can contain BOTH grid and organic sections, because:
|
||||
|
||||
1. **Era stratification**: Era 1 sections are organic (pioneer/frontier construction). Era 3 sections are grid (planned development). The same district has the palimpsest of both.
|
||||
|
||||
2. **Economic function zone differentiation**: Commercial and institutional zones (Syndic, Commission) are grid; residential and maintenance zones are organic. The commercial street is straight; the workers' housing behind it is a warren.
|
||||
|
||||
3. **Cultural overlap**: A district with mixed heritage (Salt-commercial + Iron-residential) has grid commercial blocks and organic residential blocks. The edge bleed between them is the zone where the two grammars fight.
|
||||
|
||||
4. **Power vacuum areas**: Spaces that no authority planned — because no authority wanted them — are organic. The informal zone is almost always organic because it emerged from use, not planning.
|
||||
|
||||
**Generator rule:**
|
||||
The `BlockSkeleton`'s `ChunkLayout` already handles L-shapes and merged footprints. The grid vs. organic distinction is upstream: at block planning time, each block should be assigned a `street_geometry: GridAligned | OrganicDeviation` property. Adjacent blocks can have DIFFERENT street_geometry values, creating the within-district mixing the lead directive requires.
|
||||
|
||||
What drives the assignment:
|
||||
- Era 1 blocks: OrganicDeviation default (unless founded by a specific planning authority — Colony = GridAligned even in Era 1)
|
||||
- Era 2 blocks: weighted by economic function (commercial/institutional → GridAligned; residential/maintenance → OrganicDeviation)
|
||||
- Era 3 blocks: weighted by faction presence (Commission/Syndic presence → GridAligned; absent → depends on drift stage)
|
||||
- Cultural heritage overlay: Arc/Frost-operational/Salt → weight toward GridAligned; Iron/Dust/Tide/Vine → weight toward OrganicDeviation
|
||||
|
||||
**The street grid rotation (Ozzie's persistent demand):**
|
||||
Two adjacent districts with different orientations are plausible when: the districts were planned by different authorities at different times, or when terrain features forced different orientations. A Commission-built district planned along the station's primary axis is GridAligned at 0°. An organically grown district adjacent to it, predating the Commission expansion, may have a street orientation that aligned to the first permanent structure (the original tavern, the first cargo bay), not the Commission's axis. This produces the 15-23° rotation Ozzie is asking for.
|
||||
|
||||
**The generator needs to track not just GridAligned vs. OrganicDeviation but `street_orientation: f32` (rotation in degrees from the district cardinal axis).** GridAligned blocks inherit 0° from the district plan. OrganicDeviation blocks can deviate ±30° based on historical founding conditions.
|
||||
|
||||
---
|
||||
|
||||
## Summary of Supplement
|
||||
|
||||
**Destructible boundaries:** Behind walls is heritage-dependent and era-dependent. Privacy walls (Frost/Spice/Jade) protect social/cultural content; security walls protect economic content; structural walls contain historical content. Each breach has a `cultural_sensitivity` rating and a `social_consequence` that fires based on cultural context, not just what's found. Requires `behind_boundary` descriptor on every block face.
|
||||
|
||||
**Vertical scale:** A 50-floor skyscraper is a multi-z-level single-block tower with a vertical social hierarchy. That hierarchy is heritage-root-derived: corporate culture = bottom labor / mid operations / top executive; Iron-heritage occupation = collective floor reclamation; Commission-institutional = public access at base, secure operations at top (inverted from corporate). Requires `TowerConfig` in `BlockSkeleton`.
|
||||
|
||||
**Entity-carried chunks (trains + spaceships):** Trains are bounded-linear with class-sequence social grammar. Spaceships are institutionally suspended environments — the most extreme information asymmetry because jurisdiction, communication, and social enforcement are simultaneously absent. Both types have a `transit_social_modifier` that adjusts trust-building rate, privacy level, and information flow. What people do when constraints are lifted reveals character.
|
||||
|
||||
**Grid breathing:** Grid = power imposed (Commission/Syndic planning, Arc heritage, Era 3 development). Organic = power negotiated (Iron/Dust/Tide settlement, Era 1 foundations, maintenance/residential zones). Within a district, BOTH can and should appear in different blocks. `street_orientation: f32` enables the inter-district grid rotation Ozzie is demanding — organically-settled districts have orientations inherited from their first permanent structure, not from the Commission's coordinate system.
|
||||
|
||||
---
|
||||
|
||||
**Author:** Miri
|
||||
**Date:** 2026-02-27
|
||||
**Status:** Supplement to Round 3 — filed separately to keep Round 3 focused.
|
||||
@@ -0,0 +1,520 @@
|
||||
# Generator Architecture Workshop — Round 3: Miri (Worldbuilder)
|
||||
|
||||
**Topic:** Assassination playstyle, wilderness informal zones, palette granularity, playstyle affinity per world type, insignificance as social lens, dynamic world modification
|
||||
**Date:** 2026-02-27
|
||||
**Source:** All Round 2 outputs, Qatux Round 2 notes, lead directives
|
||||
|
||||
---
|
||||
|
||||
## Reading the Round 2 Outputs
|
||||
|
||||
The team convergence is solid. The two-phase pipeline is correct. The playstyle-agnostic information landscape framing from my Round 2 held. Gestalt's 11-check guarantee audit is the right enforcement mechanism. Tyre's data structures are handling the extension well.
|
||||
|
||||
The new territory for Round 3 is deeper. Six directives, none of them cosmetic. I'll take them in order.
|
||||
|
||||
---
|
||||
|
||||
## Section 1: Assassination — The Sixth Playstyle
|
||||
|
||||
The lead gives a specific example: Frost cultures make targets harder to track, easier to operate unseen. Dust cultures make strangers visible and targets visible in equal measure. This is the right frame. Let me build it out fully.
|
||||
|
||||
### 1.1 What Assassination Needs From the Information Landscape
|
||||
|
||||
The assassin's information challenge is distinct from all four other playstyles:
|
||||
|
||||
| Playstyle | Primary question | Information goal |
|
||||
|---|---|---|
|
||||
| Investigation | Who did it? | Find the truth |
|
||||
| Tycoon | Where is the value? | Find the opportunity |
|
||||
| Dating sim | Who is this person? | Form the bond |
|
||||
| Political drama | Who controls what? | Find the leverage |
|
||||
| **Assassination** | **Where is the target, when?** | **Find the window** |
|
||||
|
||||
The assassin is not looking for truth or leverage. They're looking for **pattern and vulnerability** — when does the target deviate from their protected routine? What single moment of exposure exists? And critically: what does the aftermath look like, and who investigates it?
|
||||
|
||||
This gives assassination a unique three-phase structure:
|
||||
1. **Pattern acquisition** — learn the target's movements, associations, protection
|
||||
2. **Window identification** — find the gap in protection that can be exploited
|
||||
3. **Aftermath management** — control the information environment after the fact
|
||||
|
||||
Every phase is shaped differently by cultural ingredients.
|
||||
|
||||
### 1.2 Heritage Root Effects on Assassination
|
||||
|
||||
The society profile's heritage roots drive behavioral norms, trust models, and information flow patterns. For assassination, the relevant variables are:
|
||||
|
||||
**Observational density** — how much does this community track strangers and report deviations?
|
||||
**Information liquidity** — how freely does knowledge of the target's movements circulate?
|
||||
**Pattern rigidity** — how predictable are people's routines in this culture?
|
||||
**Aftermath engagement** — how hard does this community investigate when something goes wrong?
|
||||
|
||||
| Heritage Root | Observation density | Information liquidity | Pattern rigidity | Aftermath engagement |
|
||||
|---|---|---|---|---|
|
||||
| **Frost** | Low (people don't watch others) | Very low (information doesn't trade) | HIGH (rigid schedules, functional predictability) | LOW (private grief, informal inquiry) |
|
||||
| **Tide** | High (community awareness is a social virtue) | High (social information flows freely) | Low (fluid schedules, social spontaneity) | HIGH (communal justice demand, collective response) |
|
||||
| **Iron** | Medium-high (labor solidarity = mutual monitoring) | High within group, low to outsiders | Medium (shift patterns are predictable; solidarity gatherings are not) | HIGH (collective accountability culture) |
|
||||
| **Spice** | High within network, zero outside it | Low to strangers, high within family | Medium (family events are predictable; individual movement less so) | VERY HIGH (family networks activate, honor obligations) |
|
||||
| **Jade** | High (aesthetic tradition = careful observation) | Low (discretion is a virtue) | Medium (ritual predictability, but private movements are concealed) | Medium (formal inquiry, institutional channels) |
|
||||
| **Dust** | VERY HIGH (survival = mutual awareness) | High (shared information is survival) | Medium (community events are predictable; individual less so) | High (community protection response) |
|
||||
| **Vine** | High (warmth = social tracking) | Very high (gossip is connection) | Low (social spontaneity, relationship-driven schedules) | Medium-high (personal response, not institutional) |
|
||||
| **Salt** | Low (pragmatic, not nosy) | High IF there's benefit (transactional information) | Medium (deals create predictable windows; personal schedules do not) | Medium (pragmatic inquiry, proportional response) |
|
||||
| **Stone** | Medium (guardianship tradition = watching what matters) | Low (protective silence) | HIGH (traditional rhythms, seasonal predictability) | Medium (steady, persistent, not explosive) |
|
||||
| **Arc** | Low (intellectual focus, not social surveillance) | Medium (ideas traded freely; personal information less so) | LOW (intellectual schedules are chaotic, spontaneous) | VERY HIGH (documentation, inquiry, institutional investigation) |
|
||||
|
||||
**The key assassination matrix:**
|
||||
|
||||
A **Frost-dominant** setting is the assassin's operational paradise but intelligence nightmare:
|
||||
- You can stand in a corridor for an hour and no one will acknowledge you (low observation)
|
||||
- You cannot buy information about the target's movements (low liquidity) — you must observe directly
|
||||
- The target's routine IS reliable once you have it (high pattern rigidity) — patience pays
|
||||
- The aftermath will not mobilize the community (low engagement) — your window to leave is long
|
||||
|
||||
A **Tide-dominant** setting is the assassin's intelligence gift but operational horror:
|
||||
- Everyone notices you've been asking about this person (high liquidity — the information you collected is also shared about you)
|
||||
- The target's movements are discussed openly at the bar — you can learn their schedule in two conversations
|
||||
- Social spontaneity means the schedule shifts around social invitations — the window you identified may not repeat
|
||||
- After the act, the community mobilizes fast and personally — they remember you, your face, your accent
|
||||
|
||||
**Dust** (the lead's example) gives the assassin perfect target information and terrible cover:
|
||||
- Strangers are events in Dust communities — you are visible from the moment you arrive
|
||||
- But so is the target — their deviations from routine are noticed and discussed
|
||||
- The assassination window exists when the target is physically separated from the community (rare in Dust culture, which values collective presence)
|
||||
- The ideal Dust community assassination looks like an accident or external threat — not an insider job, because the community will know every insider
|
||||
|
||||
**Arc** communities produce the most dangerous aftermath:
|
||||
- The community may not notice you much during pattern acquisition (low social surveillance)
|
||||
- But after the act, an Arc community will investigate with INSTITUTIONAL RIGOR — they document everything, they demand explanation, they produce papers
|
||||
- An assassination in an Arc community is an intellectual puzzle that will be solved eventually — the assassin must think three moves ahead on information management
|
||||
|
||||
### 1.3 Economic Pressure and Assassination
|
||||
|
||||
The society profile's economic pressure combination shapes WHO can be hired, who keeps secrets, and what the aftermath looks like.
|
||||
|
||||
**`tight-margin + prohibition-economy`** (Sova-type):
|
||||
- Information CAN be purchased (grey economy includes information brokerage)
|
||||
- Target protection is degraded (enforcement agencies are compromised or underfunded)
|
||||
- Witnesses can be bought off or scared off (economic desperation creates leverage)
|
||||
- Aftermath: Commission investigation is perfunctory unless the target was politically important
|
||||
|
||||
**`survival-gap` economic pressure**:
|
||||
- No one will pay for truth if they need the money for food
|
||||
- Witnesses don't come forward (risk too high, reward too low)
|
||||
- But: the assassin's own expenditure is highly visible (spending above local norms in a survival-gap setting is a red flag)
|
||||
|
||||
**`opportunity-disparity`** (extreme wealth gap):
|
||||
- High-value targets are surrounded by economic resources that buy protection
|
||||
- But also: private security is purchasable, which means it can be bribed or subverted
|
||||
- Information about rich targets circulates among their service class (domestic workers, personal staff) — a different access route
|
||||
|
||||
### 1.4 Faction Presence and the Kill Window
|
||||
|
||||
The faction presence tier directly determines Meridian coverage, patrol patterns, and institutional response capability. For assassination:
|
||||
|
||||
- **Commission comprehensive coverage**: kill window requires understanding the Meridian coverage map, patrol rotation, and response time. Maximum institutional risk but the coverage pattern is ultimately predictable (it's bureaucratic)
|
||||
- **Commission intermittent/absent**: lower monitoring but also lower deterrence of competition — other actors are also operating freely, which means witness control is harder
|
||||
- **No faction presence**: the informal social monitoring (community surveillance via Dust/Tide/Iron norms) is the only enforcement. Can be lower or HIGHER than formal coverage depending on community
|
||||
|
||||
The most dangerous assassination environment: **Commission absent + Dust-dominant culture**. No formal coverage, but 100% community awareness. Every local is an alert system and a potential witness who will talk.
|
||||
|
||||
### 1.5 Generator Requirements for Assassination
|
||||
|
||||
For assassination gameplay to work, the generator must produce:
|
||||
|
||||
1. **Target pattern legibility** — the NPC's routine must be knowable through observation/inquiry. This is already built into the 10-axis NPC model (Pattern axis). The generator needs to ensure the target's routine intersects with observable spaces.
|
||||
|
||||
2. **Window geometry** — at least one location on the target's regular route where institutional coverage gaps, access topology creates opportunity, and witness density drops. This is the "informal zone" of the assassination variant — not a grey market space but a VULNERABILITY WINDOW in the target's pattern.
|
||||
|
||||
3. **Information gradient** — the assassin's intelligence-gathering journey should require working up an information ladder. The right D-025 template placement means: the bar gives you rough schedule (low tier), the insider contact gives you specific route (mid tier), the compromised handler gives you the exact window (high tier).
|
||||
|
||||
4. **Aftermath management geometry** — the route out must exist. The generator's access topology serves this: corridors that exit districts, spans to other zones, the maintenance corridors that aren't on the official map. Assassination requires the same informal zone infrastructure as investigation — for different reasons, but structurally identical.
|
||||
|
||||
**Cultural ingredient playstyle tag for assassination:** `assassination_difficulty: low/medium/high/extreme`
|
||||
|
||||
Driven by: observation density × information liquidity × aftermath engagement. High-Frost/low-community settings = low difficulty. High-Dust/Tide + Iron + Arc community settings = extreme difficulty. This is a single derived value from the society profile, not a new field — but it should be computed and stored as a descriptor.
|
||||
|
||||
---
|
||||
|
||||
## Section 2: Wilderness and Maritime Informal Zones (OQ-R3-C)
|
||||
|
||||
Gestalt raised this question and I'm the right person to answer it: *what does "private space" mean in wilderness without institutional authority?*
|
||||
|
||||
### 2.1 The Redefinition
|
||||
|
||||
In institutionally-governed urban settings, the informal zone is defined by **institutional absence**: spaces outside Meridian coverage, off official maps, not patrolled.
|
||||
|
||||
In non-institutional settings, the informal zone must be redefined. The relevant privacy mechanism is not institutional but **social**: the zone is private not because no camera watches it, but because **social norms give permission for private behavior here** or **community observation doesn't extend here**.
|
||||
|
||||
The shift: from *outside institutional surveillance* to *outside community social field*.
|
||||
|
||||
Every community, regardless of institutional presence, has a **social field** — the range of spaces where community members expect to observe and be observed by others, where social norms apply with full force. The informal zone equivalent is the edge or outside of that field.
|
||||
|
||||
### 2.2 Terrain-Specific Informal Zones
|
||||
|
||||
**Fishing village:**
|
||||
|
||||
The fishing village's social field is strongest at: the dock (arrival/departure, the whole village watches), the meeting hall/tavern (the community gathers here), the boat maintenance area (workers observe each other).
|
||||
|
||||
The informal zone equivalents:
|
||||
- **The boats during active fishing** — out of sight of shore, away from community. What happens on the boat is governed by the crew, not the village. The horizon is the social boundary.
|
||||
- **The smokehouse and drying racks** — utilitarian, smells keep people away, solitary work is normal here. The community doesn't question time spent in the smokehouse.
|
||||
- **The tidal zone before dawn** — the pre-work hours before the village wakes. Low community surveillance because low community presence.
|
||||
- **The processing shed at the edge of settlement** — the "rough work" zone that social convention keeps separate from the community center.
|
||||
|
||||
**On a farm:**
|
||||
|
||||
The farm's social field is strongest at: the communal fields during harvest (many workers present), the farmhouse (family space), the market day gathering.
|
||||
|
||||
The informal zone equivalents:
|
||||
- **The far fields in the off-season** — physically distant, not actively worked, no reason to be there
|
||||
- **The root cellar / storage buildings** — utilitarian storage, no social occasion for lingering
|
||||
- **The property boundary fencerows** — the edges of someone's land that no neighboring farmer has reason to cross
|
||||
- **The barn at night** — animals require tending at night, but it's solitary work. "In the barn late" is not suspicious; it's routine. The barn is the farm's informal corridor.
|
||||
- **The water source / irrigation control point** — critical infrastructure, but visited briefly. Anyone at the sluice gate can claim they're checking the flow.
|
||||
|
||||
**In deep forest:**
|
||||
|
||||
True wilderness has no social field to escape. But within wilderness, informal zones still exist — they're defined by **navigability and customary use**:
|
||||
- The unmaintained path vs. the maintained one — the unmaintained path is not watched because no one has reason to use it
|
||||
- The old-growth stands — superstition, impractical footing, and the absence of resources people want means old growth is often socially avoided
|
||||
- The abandoned structures — the reason for abandonment shapes the avoidance. A burned-out farmhouse is left alone for cultural/emotional reasons. An abandoned mine shaft is avoided for practical safety reasons. Both create informal privacy.
|
||||
- The viewshed reversal — on a hilltop, you can see anyone approaching from a great distance before they see you. In wilderness, HIGH GROUND is the informal zone equivalent because it provides warning rather than concealment.
|
||||
|
||||
### 2.3 Cultural Heritage and Informal Zone Character
|
||||
|
||||
What the community considers "private by convention" varies enormously by heritage root:
|
||||
|
||||
**Frost communities:** The entire individual's domestic space is their informal zone. "Minding your own business" extends to not noticing where neighbors go. In a Frost fishing village, the informal zone is effectively wherever you are when you're not in the communal space — individual movement is private by default.
|
||||
|
||||
**Tide communities:** Community norms actively cover certain behaviors. "The boat is the boat" — what happens on your boat is your crew's business. The informal zone is defined by crew/family/close-trust unit rather than physical space.
|
||||
|
||||
**Iron communities:** The informal zone is often LABOR-ASSOCIATED. "What workers do after the shift" or "what happens in the union hall" is covered by solidarity norms — community members don't inform on each other to outsiders. The informal zone is social rather than geographic.
|
||||
|
||||
**Dust communities:** The informal zone is almost impossible to find because the community's survival-level social awareness covers everything. The most private you can be is "agreed to be unobserved" — a social contract with specific individuals to not see what you're doing. The informal zone is a negotiated privacy, not a geographic one.
|
||||
|
||||
### 2.4 Generator Rule for Non-Urban Informal Zones
|
||||
|
||||
**For every non-urban Full-complexity district:**
|
||||
|
||||
The `terrain_informal_zone` (Gestalt's proposed term) is not just a geographically sheltered space. It is a space where:
|
||||
1. Community norms give permission for private behavior, OR
|
||||
2. Physical distance or conditions reduce community observation without violating social convention, OR
|
||||
3. Utilitarian function provides social cover for presence ("I'm in the barn checking the animals")
|
||||
|
||||
The generator should produce at least one such space per non-urban Full-complexity district, tagged with its informal zone TYPE:
|
||||
- `social_permission` — convention covers this space
|
||||
- `physical_distance` — community observation doesn't reach here without intent
|
||||
- `utilitarian_cover` — normal function provides plausible presence
|
||||
|
||||
The cultural heritage root should weight which type appears:
|
||||
- Frost → `physical_distance` (individual space is respected everywhere)
|
||||
- Tide/Dust → `social_permission` (negotiated privacy within community framework)
|
||||
- Iron → `utilitarian_cover` (labor function covers presence)
|
||||
|
||||
---
|
||||
|
||||
## Section 3: Palette Granularity — Society Profile Within Terrain Types
|
||||
|
||||
The question: is 5 non-urban terrain palettes enough? Should a Frost farm look different from a Vine farm?
|
||||
|
||||
**Setting note — this is a base game concern, not DLC.**
|
||||
|
||||
The cultural ingredients system's entire value proposition is that heritage roots produce distinguishable LIVED ENVIRONMENTS. If all farms look alike regardless of heritage, we've built a system that differentiates culture at the behavioral level but flattens it at the spatial level. That contradiction is visible to players.
|
||||
|
||||
The correct model: **terrain type drives the MATERIAL VOCABULARY** (what materials exist here); **heritage root drives the ORGANIZATIONAL GRAMMAR** (how those materials are arranged, decorated, and related to each other).
|
||||
|
||||
### 3.1 The Two-Layer Palette Model
|
||||
|
||||
**Layer 1 — Terrain Base Palette (from Araminta's 5-6 types)**
|
||||
|
||||
This determines what's available: the substrate materials, the agricultural products, the structural materials indigenous to this terrain and climate. A farmland palette has: dark soil brown, amber grain fields, wood structures, stone foundations. This doesn't change with heritage root.
|
||||
|
||||
**Layer 2 — Heritage Grammar Overlay (from society profile)**
|
||||
|
||||
This determines how the base palette is organized and expressed:
|
||||
|
||||
| Heritage Root | Organizational principle | Visual signature |
|
||||
|---|---|---|
|
||||
| **Frost** | Functional efficiency. No waste, no ornament | Regular spacing, minimal color variation, equipment stored compactly. No decorative elements. Clean lines on structures. |
|
||||
| **Vine** | Social warmth. The human scale matters | Gathering spaces woven into work spaces. Decorative climbing plants on structures. Informal seating clusters. Warm accent colors at door/window frames. |
|
||||
| **Stone** | Permanence. This is built to last | Heavier construction materials. Thick-walled structures. Boundary markers that are permanent (stone walls, not wire fences). Generational accumulation visible. |
|
||||
| **Tide** | Flow and gathering. People move through | Wide paths between buildings. Cleared central areas for assembly. Structures face toward communal center, not away. Seasonal decoration traditions. |
|
||||
| **Iron** | Collective utility. Shared is better | Shared infrastructure (communal granary, shared equipment storage). Buildings of similar scale (no grand farmhouse dominating small workers' quarters — or that contrast IS the political statement). Signs of organized labor. |
|
||||
| **Dust** | Hardship resilience. Nothing wasted | Patched and repaired materials in visible use (not distressed for aesthetics — actually maintained because you can't afford replacement). Water conservation infrastructure prominent. Weatherproofing as primary aesthetic. |
|
||||
| **Spice** | Family honor expressed physically | Family identifier markers on structures. Distinct zones for family/guest/worker (not mixed). Aesthetic investment in the family-facing spaces (the façade toward the road; the interior family court). |
|
||||
| **Salt** | Transactional efficiency | Clear entry/exit points. Storage and sale infrastructure visible and accessible. Pricing/scale equipment present. Minimal personal expression — the space is for business. |
|
||||
| **Arc** | Intellectual order | Things categorized and labeled (even physical objects). Improvement projects visible (new plantings testing yield, experimental plot separate). Written records visible (staked labels, weather logs on walls). |
|
||||
| **Jade** | Refined appreciation | Careful curation of aesthetic elements. Not more material, but better selected. The fence posts are planed smooth. The path is laid with intentional stone selection. Quality over quantity. |
|
||||
|
||||
### 3.2 What This Looks Like in Practice
|
||||
|
||||
**Frost-heritage farm vs. Vine-heritage farm (same terrain palette, different grammar):**
|
||||
|
||||
*Frost farm:*
|
||||
- Low wire fences (functional, minimal material)
|
||||
- Equipment stacked efficiently near work areas, not stored in a dedicated building
|
||||
- No communal spaces outside — why would you gather outside if there's work?
|
||||
- Lighting: work-temperature functional, no ambient warmth
|
||||
- The farmhouse interior has warmth; the exterior presents nothing
|
||||
|
||||
*Vine farm:*
|
||||
- Trellises repurposed as social dividers between plots (boundary AND aesthetic)
|
||||
- A planted-out area near the farmhouse that serves no agricultural purpose — it's for sitting
|
||||
- Communal fire or gathering infrastructure between households if multi-family
|
||||
- Doors and windows decorated with seasonal plantings (tells you the season)
|
||||
- The exterior says "people live here and they'd welcome you"
|
||||
|
||||
**Same farmland terrain palette. Completely different feel. Both immediately readable.**
|
||||
|
||||
### 3.3 Is DLC the Right Model for This?
|
||||
|
||||
Araminta defined the 5-6 terrain palettes in Round 2. The heritage grammar overlay I'm describing above is NOT a new template library — it's a modifier applied AT CHUNK FILL TIME to the existing terrain palette. It needs:
|
||||
|
||||
1. Per-root organizational rules (the table above, encoded as modifier flags)
|
||||
2. Heritage-tagged variant assets for decorative/organizational elements (fences, plantings, gathering spaces, signage)
|
||||
|
||||
The base game MUST ship the heritage grammar overlay rules — they're part of the core cultural differentiation system. What DLC can expand: additional heritage-tagged variant assets for each terrain type (more variety in what "Vine farm aesthetic" looks like). But the grammar rules themselves are base game.
|
||||
|
||||
**Qatux should note:** This is an implicit decision forming — Araminta's terrain palettes need to be specified not just as 5-6 palettes but as (terrain) × (heritage root grammar modifier). That's a cross-domain requirement that needs to be stated explicitly.
|
||||
|
||||
---
|
||||
|
||||
## Section 4: Playstyle Affinity Per World Type
|
||||
|
||||
Not every place serves every playstyle. This should be first-class generator knowledge — the generator needs to know what it's optimizing for when producing a given setting.
|
||||
|
||||
### 4.1 The Affinity Matrix
|
||||
|
||||
I'm defining affinity levels as: **Primary** (this playstyle is naturally strongest here), **Secondary** (playable with adjusted expectations), **Weak** (possible but requires design work), and **Poor** (structurally unsuitable).
|
||||
|
||||
| Setting Type | Investigation | Tycoon | Dating Sim | Political Drama | Assassination |
|
||||
|---|---|---|---|---|---|
|
||||
| **Station transit hub** | Primary | Primary | Secondary | Secondary | Secondary |
|
||||
| **Station administrative/corporate** | Secondary | Secondary | Weak | Primary | Primary |
|
||||
| **Station industrial/freight** | Secondary | Primary | Weak | Secondary | Weak |
|
||||
| **Station residential** | Secondary | Weak | Primary | Secondary | Weak |
|
||||
| **Frontier/pioneer settlement** | Secondary | Secondary | Primary | Secondary | Secondary |
|
||||
| **Agricultural town** | Secondary | Primary | Primary | Secondary | Poor |
|
||||
| **Industrial extraction site** | Secondary | Primary | Weak | Secondary | Weak |
|
||||
| **Maritime port** | Primary | Primary | Secondary | Secondary | Secondary |
|
||||
| **Tourist resort** | Weak | Primary | Primary | Secondary | Secondary |
|
||||
| **Military/security installation** | Secondary | Weak | Secondary | Primary | Primary |
|
||||
| **Research outpost** | Primary | Weak | Secondary | Secondary | Primary |
|
||||
| **Criminal nexus** | Primary | Secondary | Weak | Secondary | Primary |
|
||||
| **Political capital** | Secondary | Secondary | Weak | Primary | Primary |
|
||||
| **Ancient/heritage site** | Primary | Weak | Secondary | Secondary | Secondary |
|
||||
| **Wilderness (no society)** | Weak | Secondary | Weak | Poor | Primary |
|
||||
|
||||
### 4.2 What the Affinity Matrix Means for the Generator
|
||||
|
||||
The significance tier (Center-stage → Insignificant) and the setting type determine the **playstyle content budget**. A military installation shouldn't try hard to generate dating sim content — it should focus its limited content budget on political drama and assassination affordances.
|
||||
|
||||
**Implementation:** The `GuaranteeAuditResult` (Gestalt's 11-check struct) should include a `primary_playstyles: Vec<Playstyle>` field derived from setting type. Full-complexity districts guarantee all 7 archetypes + 4 additional. But the **density** of content per archetype is weighted toward the primary playstyles.
|
||||
|
||||
The economic node is required for all Full districts — but in a military installation, the economic node looks like supply procurement, not a commercial market. In a tourist resort, the economic node is the booking desk, not a freight logistics hub. Same structural requirement, different content expression.
|
||||
|
||||
### 4.3 Assassination-Specific Affinities
|
||||
|
||||
Assassination playstyle has a unique affinity driver that others don't: **target value**. An assassination play doesn't make sense in a poor agricultural village (the target isn't worth the risk) unless that village is specifically flagged as harboring something important.
|
||||
|
||||
The `network_position` parameter I defined in Round 2 (network-significant / regionally significant / locally significant / marginally located) correlates with target value:
|
||||
- Network-significant settings have high-value targets worth assassination
|
||||
- Locally-significant settings have targets whose assassination serves local rather than systemic goals
|
||||
- Marginally located settings have essentially no viable assassination targets — unless a high-value target is visiting (which creates a special scenario type)
|
||||
|
||||
This means: the `assassination_difficulty` descriptor I proposed in Section 1 should be accompanied by `assassination_target_density` — how many viable assassination targets exist in this setting. These together define whether assassination is a viable playstyle here.
|
||||
|
||||
### 4.4 The "Poor" Rating
|
||||
|
||||
A setting rated Poor for a playstyle should not ACTIVELY PREVENT that playstyle — it should just fail to support it well. A wilderness area rated Poor for Political Drama isn't impossible to play politically — it's just that the generator won't produce the spatial affordances that political play needs. A player who insists on playing politics in the wilderness will find sparse, unsatisfying affordances for it.
|
||||
|
||||
This is a design choice: the generator serves the naturally suited playstyles, not all playstyles equally. Players who want deep political gameplay go to political capitals; players who want wilderness assassination go to wilderness. The world has specialization, which is realistic.
|
||||
|
||||
---
|
||||
|
||||
## Section 5: "Insignificant" as Social Lens — Per Playstyle
|
||||
|
||||
Carrying forward CR2-5 (Miri Round 2): insignificance is relational, not absolute. Now I need to show how the SAME backwater reads completely differently depending on what you're there to do.
|
||||
|
||||
### 5.1 The Backwater Through Five Lenses
|
||||
|
||||
**Setting:** A small agricultural settlement, ~150 people. Subsistence farming, one tavern that serves as community center, no faction presence, locally-significant only. Stone/Tide heritage blend. Community has been here 40 years. They know everyone who's ever passed through.
|
||||
|
||||
**Through the investigator's lens:**
|
||||
|
||||
*What's significant here:* Everything is visible. The grey economy, if present, is ONE person in ONE back room. When a crime happens, EVERYONE knows something about it. The investigator's challenge is not finding information — it's that the information knows about THEM. The community will follow their investigation with intense interest and discuss their methods openly.
|
||||
|
||||
*The twist:* The insignificant backwater is where someone goes to HIDE. The most important information in the settlement might be: this person shouldn't be here. A network-significant actor gone to ground in a local-significance settlement. The backwater reads as insignificant — until the investigator notices that one resident has habits that don't fit the Stone/Tide cultural profile.
|
||||
|
||||
*The gameplay:* Not "who committed the murder" but "why is this person here and what are they hiding from." Investigation inversion: the evidence isn't buried, it's too visible. The murder is small (one person). The implications are enormous.
|
||||
|
||||
**Through the tycoon's lens:**
|
||||
|
||||
*What's significant here:* Land rights. Water rights. Agricultural output that flows out through one trading route. Someone owns that route, and they're extracting from everyone who uses it.
|
||||
|
||||
*The opportunity:* The agricultural settlement is CAPTIVE. They can't easily change suppliers or buyers because the infrastructure doesn't support alternatives. The tycoon who finds the single point of leverage (the route, the storage, the equipment) finds a monopoly opportunity.
|
||||
|
||||
*The gameplay:* But the community knows everyone. The tycoon's economic maneuvers are completely visible. Making a quiet deal with the route-owner doesn't stay quiet for long. Economic play in a backwater is conducted entirely in public — which means the community has opinions about what you're doing.
|
||||
|
||||
**Through the dating sim lens:**
|
||||
|
||||
*What's significant here:* This community has 150 people and has had 40 years to develop rich relationship histories. The tavern has regulars who have known each other their entire adult lives. The social graph is dense, fully connected, and intensely aware.
|
||||
|
||||
*The dynamics:* Dating sim in an insignificant place runs at a completely different register from a hub. There is no anonymity phase — you're known from day three. Every relationship you form is visible to everyone else. Third parties have opinions. Family/community approval is inescapable. The cultural heritage (Stone/Tide = community approval as social norm) amplifies this.
|
||||
|
||||
*The gameplay:* The most private thing you can do is become a regular fast — be so present that your presence is unremarkable. The romantic play is not "meet and discover" but "earn belonging." This is a different game. Some players will find it more satisfying than hub romance precisely because the stakes are personal and socially embedded.
|
||||
|
||||
**Through the political drama lens:**
|
||||
|
||||
*What's significant here:* One person runs the community assembly. One trading route operator controls the economic access. Two extended families hold most of the land tenure. The political map is small enough to walk in ten minutes, but the entanglement is complete.
|
||||
|
||||
*The drama:* No institutional mediation. No Commission to appeal to. Political conflict is immediate, personal, and has no legitimate outside arbitration. Political drama in the backwater is INTERPERSONAL in a way that hub political drama is not — you're dealing with the people directly affected by the decisions, not their institutional representatives.
|
||||
|
||||
*The gameplay:* Political drama players in a backwater are playing coalition politics at human scale. Win over Aia's family, lose Torval's approval. This is simultaneously more emotionally intense and more mechanically tractable than hub politics — the actors are knowable.
|
||||
|
||||
**Through the assassin's lens:**
|
||||
|
||||
*What's significant here:* A locally-significant backwater has Poor assassination affinity by default. There are no high-value targets. The entire community knows every movement of every person. The post-act information environment is impossible to control.
|
||||
|
||||
*The exception:* If someone has gone to ground here — someone network-significant hiding as a locally-insignificant person — then the backwater is the IDEAL assassination environment from the target's perspective and the WORST from the assassin's. The target has hidden in the optimal low-surveillance network location. The assassin must penetrate a high-community-awareness setting, work without being remembered, find the disguised target, act, and leave without triggering a community that will talk about the stranger who visited for three days right before someone died.
|
||||
|
||||
*The gameplay:* Assassination in the backwater is the hardest assignment. The assassin who can do this cleanly is elite. The scenario type: "the target has gone to ground here. This world is locally-significant, Stone/Tide heritage, 150 people, everyone knows everyone. Good luck."
|
||||
|
||||
### 5.2 The Generator Implication
|
||||
|
||||
The same backwater world should be generated such that all five lenses can find their specific engagement — even though only 1-2 will be Primary affinity. What changes per lens is not the content but the FRAME through which the player approaches it.
|
||||
|
||||
The generator needs to ensure that even a locally-significant, Moderate-complexity district has:
|
||||
- At least one person whose presence is anomalous (investigation hook)
|
||||
- At least one economic chokepoint that's exploitable (tycoon hook)
|
||||
- At least one sustained social gathering with routine (dating sim hook)
|
||||
- At least one contested allocation decision (political hook)
|
||||
- At least one visitor or newcomer whose identity is uncertain (assassination hook, latent)
|
||||
|
||||
None of these requires separate content — they can all be expressed through the same set of NPCs with appropriately complex profiles. The investigator's "anomalous person" is the same NPC the tycoon recognizes as having unusual resources, the political player sees as holding uncertain allegiance, and the assassin flags as possibly the target.
|
||||
|
||||
**One NPC, five lenses.** That's the design target.
|
||||
|
||||
---
|
||||
|
||||
## Section 6: Dynamic World Modification — Trauma Events
|
||||
|
||||
When a gas explosion destroys part of a district, what changes culturally? This is the question that connects worldbuilding to dynamic simulation.
|
||||
|
||||
### 6.1 The Trauma Event Framework
|
||||
|
||||
A trauma event is a **historical event modifier applied to a living district** rather than to a pre-generated historical record. The architectural system for this already exists (Tyre's `EraModification` + Gestalt's `era_cause` field). What's needed is the **cultural aftermath model** — how does the society profile respond to acute stress?
|
||||
|
||||
The key insight: **trauma reveals the society profile more clearly, not less.** A stressed community doesn't become a different culture — it becomes an intensified version of itself. The heritage roots that were latent become dominant. The trust mechanisms that worked passively become active. The absence parameters (what the community lacks institutionally) become critically felt.
|
||||
|
||||
### 6.2 Trauma Types and Cultural Response
|
||||
|
||||
**Type 1 — Physical Destruction (explosion, collapse, flood)**
|
||||
|
||||
Phases:
|
||||
|
||||
*Immediate (1-7 days):*
|
||||
- Information flow SPIKES: everyone talks about what happened. For 72-96 hours, the normal information siloing is suspended.
|
||||
- Community pattern shift: ANCHOR-type NPCs dominate (the people who hold the community together step forward). CATALYST NPCs (people in crisis) increase. HANDLER NPCs (operators) temporarily reduce activity.
|
||||
- Access topology changes: blocked routes create new informal paths; rubble creates new informal zones.
|
||||
- Faction response matters enormously: who responds first, how, and with whose resources — this shapes community trust for years.
|
||||
|
||||
*Medium-term (1-8 weeks):*
|
||||
- **Heritage root response:**
|
||||
- **Frost**: community closes, rebuilds quietly, does not discuss the trauma publicly. Asks for practical help. Rejects offered emotional support as intrusive. Suspicion of outsiders increases.
|
||||
- **Tide**: community gathers, processes grief publicly, creates ritual around the event. A community mourning becomes a social institution. Outsider sympathy is welcomed.
|
||||
- **Iron**: collective response — mutual aid organized, demands for accountability raised, solidarity demonstrated through shared labor. The community investigates who is responsible.
|
||||
- **Dust**: all hands. Every community member contributes. The social hierarchy flattens in crisis. Leadership goes to the most capable, not the most credentialed.
|
||||
- **Vine**: the social fabric IS the response — meals cooked, children cared for, emotional support structured through existing relationships. The community grieves as a social entity.
|
||||
- **Arc**: documentation, inquiry, accountability. The community produces a record. Someone is writing down what happened and why.
|
||||
|
||||
*Long-term (months to years):*
|
||||
- Era modification is logged with `StructuralDestruction` event type
|
||||
- Drift stage may increase in affected area (forced evolution, reduced cosmopolitan blending as community turns inward)
|
||||
- Some NPCs leave (the destruction is the tipping point for people who were already on the margin)
|
||||
- Memorial markers appear (heritage-root-dependent form)
|
||||
- Trust recovery curve: the community's trust of institutions (Commission response quality) either rebuilds or permanently decays
|
||||
|
||||
### 6.3 The Society Profile Under Stress
|
||||
|
||||
**What changes:**
|
||||
- `trust.building_rate` for STRANGERS decreases (community turns inward)
|
||||
- `insider_trust_threshold` decreases (insiders become more trusted, not less — reciprocal tightening)
|
||||
- `grey_economy` activity shifts: some operators become more visible (mutual aid operates outside formal channels), some go dark
|
||||
- `faction_presence` operational character may shift: Commission may have formal authority but reduced actual cooperation
|
||||
|
||||
**What does NOT change:**
|
||||
- Heritage root identity (this is who we are — it doesn't change under stress, it intensifies)
|
||||
- Economic function (people still need to work)
|
||||
- Settlement motivation (why we're here doesn't change because something broke)
|
||||
|
||||
### 6.4 Trauma as Gameplay Driver
|
||||
|
||||
For each playstyle, a trauma event creates EXCEPTIONAL CONDITIONS:
|
||||
|
||||
**Investigation:** The immediate information spike is a window. For 72 hours, people will talk who wouldn't normally. The community's defenses are down. Evidence that's normally buried becomes surface-level visible. Counter: everyone is also watching the investigator more closely.
|
||||
|
||||
**Tycoon:** Economic disruption creates opportunity gaps. Suppliers for reconstruction materials are needed immediately. The economic void left by destroyed infrastructure is a market opening. Counter: predatory behavior during community tragedy is visible and remembered.
|
||||
|
||||
**Dating sim:** Crisis creates intimacy. Shared trauma is a bonding accelerant. Counter: crisis reveals character — both the player's and the NPCs'. The Frost person who retreats inward during trauma requires a completely different response than the Tide person who needs to process publicly. Reading the heritage root correctly under pressure is a dating sim skill check.
|
||||
|
||||
**Political drama:** The aftermath is a power redistribution event. Who controlled the destroyed infrastructure? Who controls the reconstruction? Who is blamed? Political drama in the aftermath is about exploiting the vacuum or managing the accountability before it resolves against you.
|
||||
|
||||
**Assassination:** Trauma events create TWO opportunity windows:
|
||||
1. The immediate chaos window: high community distraction, institutional focus elsewhere, normal patterns suspended
|
||||
2. The reconstruction vulnerability window: the target may be physically present at the damaged site (overseeing reconstruction, inspecting, attending memorial), reducing normal protection
|
||||
Counter: institutional presence may be ELEVATED during reconstruction, and community attention is heightened.
|
||||
|
||||
### 6.5 The Generator Implementation
|
||||
|
||||
**What the generator needs to support:**
|
||||
|
||||
1. **Trauma events as historical modifiers** (already exists via `EraModification`)
|
||||
- Add `ModificationType::TraumaEvent` with subtypes: PhysicalDestruction, EconomicDisruption, PoliticalShock, ViolenceEvent, MigrationShock
|
||||
- Carry `cultural_aftermath: HeritageRootResponse` — the specific community response derived from dominant heritage root
|
||||
|
||||
2. **Active modification state** for living worlds (distinct from historical record)
|
||||
- The historical record stores what happened; the active modification state stores what's currently different from baseline
|
||||
- Active modification state decays over time (trauma aftermath is temporary — society returns toward baseline)
|
||||
- Rate of return is heritage-root-dependent (Frost: faster private recovery, slower institutional normalization; Tide: faster social recovery; Arc: never returns to pre-inquiry-completion state)
|
||||
|
||||
3. **NPC pattern weight modification** for affected areas
|
||||
- NPC generation in post-trauma areas should weight ANCHOR, WITNESS, REMNANT patterns higher; CATALYST and NOBODY patterns differently
|
||||
- This is the mechanism that makes post-trauma areas FEEL different — the people in them behave differently
|
||||
|
||||
4. **Access topology update**
|
||||
- Blocked routes from structural damage create new informal paths (these become the post-trauma informal zone)
|
||||
- The generator should flag destroyed social sites as `inactive` with an optional `temporary_replacement` pointer
|
||||
|
||||
### 6.6 What I'm Not Solving Here
|
||||
|
||||
Dynamic world modification that happens DURING a playthrough (not historical pre-generation) is a simulation concern more than a worldbuilding concern. Tyre will address whether the server's simulation tick system can handle live trauma events modifying the `PreparedDistrict` or whether these require regeneration.
|
||||
|
||||
My contribution is the **cultural response layer** — the worldbuilding logic that determines what a trauma event MEANS for how a community behaves. The simulation system implements the mechanics; the society profile provides the parameters for how those mechanics are culturally expressed.
|
||||
|
||||
---
|
||||
|
||||
## Summary: Round 3 Contributions
|
||||
|
||||
**1. Assassination as the sixth playstyle** — fully integrated into the society profile. Cultural ingredients drive three variables: observational density (how visible you are), information liquidity (how knowable the target is), and aftermath engagement (how hard they look afterward). The combination defines `assassination_difficulty` as a derived profile descriptor.
|
||||
|
||||
**2. Non-urban informal zones** — redefined from "outside institutional surveillance" to "outside community social field." Each terrain type has specific informal zone equivalents; heritage roots determine which type appears. The generator tag is three-way: `social_permission` / `physical_distance` / `utilitarian_cover`.
|
||||
|
||||
**3. Palette granularity** — two-layer model: terrain base palette (material vocabulary) + heritage grammar overlay (organizational principle). This is a base game requirement, not DLC. All ten heritage roots have distinct organizational grammar rules applicable to any terrain type. DLC expands variant assets; the grammar rules are core.
|
||||
|
||||
**4. Playstyle affinity matrix** — full matrix across 15 setting types and 5 playstyles. Generator knows what it's optimizing for. Poor-affinity playstyles are not blocked but are not budgeted for. One NPC with sufficiently complex profile can provide entry hooks for all five lenses simultaneously.
|
||||
|
||||
**5. Insignificance through five lenses** — same backwater world, five different engagements. Investigation: the anomalous person; Tycoon: the exploitable chokepoint; Dating sim: the belonging-earning; Political drama: personal-scale coalition politics; Assassination: the hardest assignment. Minimum content for even Moderate-complexity insignificant districts: one anomalous presence, one economic chokepoint, one social gathering rhythm, one contested allocation, one visitor of uncertain identity.
|
||||
|
||||
**6. Dynamic world modification** — trauma events as living modifications applied to society profiles. Six trauma subtypes. Response is heritage-root-determined (intensification of existing cultural character, not transformation). Implementation requires `TraumaEvent` modification type, `cultural_aftermath` field with heritage response, NPC pattern weight modification for affected areas, and active modification state with decay rate.
|
||||
|
||||
---
|
||||
|
||||
**Author:** Miri
|
||||
**Date:** 2026-02-27
|
||||
**Status:** Round 3 complete.
|
||||
|
||||
**Questions for Round 4 or implementation:**
|
||||
- Tyre: The active modification state (for living trauma events) — is this a second layer above `PreparedDistrict`, or does it modify the prepared district in place? Decay rates need to map to the simulation tick.
|
||||
- Gestalt: The `assassination_difficulty` descriptor — should this be surfaced in the `GuaranteeAuditResult`, or is it a separate field on `DistrictSkeleton` alongside the playstyle affinity vector?
|
||||
- Araminta: Heritage grammar overlay rules (the ten-row table in Section 3.1) need to be encoded as modifier flags that chunk fill can read. What's the right representation — per-heritage modifier objects that chunk fill applies, or lookup tables within the terrain palette assets?
|
||||
- Nigel: The "one NPC, five lenses" requirement (Section 5.2) — does the NPC's 10-axis model already support this, or does providing five-playstyle hook simultaneously require additional content axes?
|
||||
@@ -0,0 +1,595 @@
|
||||
# Generator Architecture Workshop — Round 4: Miri (Worldbuilder)
|
||||
|
||||
**Topic:** Write the NPC. Close the open questions. Finalize vessel grammar.
|
||||
**Date:** 2026-02-27
|
||||
**Lead decisions acknowledged:** WorldTier wins over SignificanceTier. DramaDensity is runtime state (not on DistrictSkeleton). Entity-carried MobileChunk is CORE.
|
||||
|
||||
---
|
||||
|
||||
## Preamble
|
||||
|
||||
The lead said: write the NPC. Don't discuss whether it could theoretically work. Show the work.
|
||||
|
||||
This is the work.
|
||||
|
||||
---
|
||||
|
||||
## OQ-R4-E: One Character. One Settlement. Five Lenses.
|
||||
|
||||
### The Setting
|
||||
|
||||
**Harrow Drift** — a farming settlement, 40 years established, ~150 permanent residents.
|
||||
|
||||
WorldTier: Backwater. ComplexityTier: Moderate. DramaDensity: Zero (currently).
|
||||
|
||||
Heritage: Stone (0.6) + Tide (0.4). Drift stage: crystallizing (40 years is young for Stone, which wants centuries).
|
||||
Settlement motivation: economic-agricultural — founded by a cohort of families who wanted land tenure they couldn't get in a Commission-managed hub.
|
||||
Economic function: subsistence agriculture + modest surplus trade via one seasonal route.
|
||||
Economic pressure: generational-extraction (the land titles are real but the route operator takes 18% of surplus trade).
|
||||
Faction presence: Commission absent; no Syndic presence; local governance = informal assembly (five founding family heads + elected coordinator).
|
||||
Meridian coverage: none.
|
||||
|
||||
**Community character:** Stone culture means the founding families have territorial memory and protective silence. Tide culture means people eat together, celebrate together, and a stranger is immediately noticed — and discussed. The combination: tight community with a warm surface and a hard interior. You're welcomed at the table on day one. You're trusted at year ten, if you've earned it.
|
||||
|
||||
Forty years in, they know every family secret. Including who belongs and who doesn't quite fit.
|
||||
|
||||
---
|
||||
|
||||
### The NPC
|
||||
|
||||
**Ysabel Vorn**
|
||||
Apparent age: mid-40s. Arrived at Harrow Drift 14 years ago, nominally as a partner of a farmer who left 8 years ago. The farmer left. She stayed. She runs water management.
|
||||
|
||||
---
|
||||
|
||||
#### Full 10-Axis Profile
|
||||
|
||||
**Axis 1 — Behavioral Pattern (Social Archetype)**
|
||||
|
||||
Primary: ANCHOR. Ysabel is one of the five or six people the community would name if asked "who keeps this place running." Her water management role is structurally critical (every farm's viability depends on fair allocation during dry months). She shows up consistently, mediates disputes without taking sides, and participates in community labor beyond her direct responsibilities.
|
||||
|
||||
Secondary: REMNANT. This is the layer that only long observation reveals. She is holding on — not to the past she claims, but to a past she won't name. Something about her patterns suggests someone who has been running and has decided, tentatively, to stop here.
|
||||
|
||||
**Axis 2 — Surface Motivation (Publicly Visible Goal)**
|
||||
|
||||
Keep the water system equitable. Prevent the Fennen family from leveraging their founding-family status into preferential allocation. Maintain the settlement's social cohesion through the one resource that everyone needs and no one can leave without.
|
||||
|
||||
This motivation is REAL. It is not a cover story. She has spent 14 years genuinely trying to be useful here.
|
||||
|
||||
**Axis 3 — Actual Motivation (What She Actually Wants)**
|
||||
|
||||
Stay hidden. Safe. Not found.
|
||||
|
||||
The equitable administration serves the actual motivation: if she is indispensable and trusted, no one asks questions about her origin. A community that needs you doesn't scrutinize you. She has been performing trustworthiness with strategic precision for 14 years, and by now most of it has become genuine — she actually cares about Harrow Drift. But the original reason she chose to care this much was survival.
|
||||
|
||||
Secondary actual motivation: she is watching for Kael Voss. The man who was displaced by the fraud she documented. She's known for three years he lives 40 km east. She hasn't approached him. She tells herself this is because contact would expose her. The truth is more complicated.
|
||||
|
||||
**Axis 4 — Vulnerability/Secret**
|
||||
|
||||
Seven years before she arrived at Harrow Drift, Ysabel was a Commission data analyst specializing in land-grant records — a mid-level position that gave her access to the historical title database across a significant region.
|
||||
|
||||
During a routine audit, she found it: a fabricated land-grant record that had been inserted into the Commission database, dated 22 years prior, displacing a pre-existing title held by the Voss family. The fabrication was clean enough to pass cursory review. It wasn't clean enough to pass her review. She traced it to a Syndic subsidiary acting on behalf of an executive named Pehr Callen, who had needed the land for a private extraction operation. The Voss family — Kael's parents, then — had been compensated under a false legal premise and relocated.
|
||||
|
||||
She made a copy of the file chain. Then she made a mistake: she contacted a ring-adjacent information broker, thinking she could pass the evidence to someone who would use it without exposing her. The broker took the files and disappeared. Three weeks later, a Commission warrant was issued for a data analyst who had accessed restricted historical records without authorization. Her name.
|
||||
|
||||
She ran. She has been running in a single direction (toward places with no Meridian coverage and no Commission presence) for seven years before arriving at Harrow Drift. The warrant is real. The data theft charge is real. The underlying evidence that motivated the theft is also real.
|
||||
|
||||
She doesn't know if the copy she passed to the broker ever reached anyone. She doesn't know if Pehr Callen knows she's alive.
|
||||
|
||||
**Axis 5 — Information Access (What She Knows)**
|
||||
|
||||
Tier 3 (complete): Harrow Drift's water system, seasonal allocation records, every family's land and water claims going back to founding.
|
||||
|
||||
Tier 3 (complete): The interpersonal relationships, grudges, debts, and loyalties of every person in the settlement. Fourteen years of observation. She is the settlement's institutional memory despite being a latecomer.
|
||||
|
||||
Tier 2 (partial, aging): The Commission land-grant system's structure and failure modes. She has been away from Commission data infrastructure for 14 years, but the analytical framework is intact. She can read a land title and identify if something is wrong. She knows this region's historical land grant database well enough to identify additional fabrications if they exist.
|
||||
|
||||
Tier 3 (specific): The Pehr Callen conspiracy file chain. She has a memory copy — she memorized the key document numbers and dates before she ran. She does not have the physical files. But she can reconstruct enough to make an investigator's or legal advocate's job tractable if given access to the right archive.
|
||||
|
||||
Tier 1 (basic): Kael Voss exists, lives 40 km east in a settlement called Vermin's Cross, farms barley. She knows his name and location but nothing about his current life.
|
||||
|
||||
**Axis 6 — Trust Architecture**
|
||||
|
||||
Heritage trust model: Stone (tenure-based, very slow, deep once earned) + Tide (public demonstration, community participation). This is her actual operating model, not a calculated performance — she has absorbed the community's trust norms over 14 years.
|
||||
|
||||
Trusted (deeply): three people. Opal Dun (Cara's grandmother, 70s, has never asked about Ysabel's past and shows by this that she has noticed there's something to not ask about). Lev Fennen (Orik's youngest son, who disagrees with his family's political ambitions; Ysabel has quietly protected his dissent from family pressure). One other who is not significant to this document.
|
||||
|
||||
Trusted (functionally): the approximately 40 people who interact with her regularly through water management and community events. She is warm with them. She is not open.
|
||||
|
||||
Cautious (everyone else): 110 people she is friendly toward and emotionally reserved with.
|
||||
|
||||
Zero trust: strangers. A new arrival triggers her internal threat assessment immediately. She remains warm and welcoming on the surface — this is Stone/Tide culture. Internally, she is reading every detail for signs of Commission connection or Syndic interest.
|
||||
|
||||
Trust-building rate for a player character: slow by default (Stone tenure model). Accelerates via public contributions (Tide model) — help during the water dispute, participate in harvest labor, accept an invitation to a community meal and behave well. Decelerates immediately if the player shows interest in her history.
|
||||
|
||||
**Axis 7 — Routine Pattern (Movement and Schedule)**
|
||||
|
||||
*Dawn:* Solo inspection of the main water channels and reservoir (45 minutes, predictable path, starts at the sluice gate near the east field boundary and ends at the primary storage tank north of the settlement). This is her most private daily interval.
|
||||
|
||||
*Morning:* Available at the water management building (small structure, central location) for allocation queries. Frequent foot traffic. Social but businesslike.
|
||||
|
||||
*Midday:* Eats at the community gathering space with whoever is present. She ensures this visibility consistently — this is both Stone/Tide cultural participation and deliberate cover maintenance.
|
||||
|
||||
*Afternoon:* Variable. Field work with neighbors (she contributes labor across farms, building distributed goodwill). Or: paperwork (the settlement's water records, which she maintains meticulously). Or: if a dispute is active, she meets with involved parties privately.
|
||||
|
||||
*Evening:* Selective community gathering attendance. She is present often enough that absence is unremarkable. She does not attend every event — which prevents over-exposure.
|
||||
|
||||
*Weekly:* Attends every community assembly. Sits in the middle third of seating (neither front-row authority nor back-row disengagement). Speaks rarely, but when she speaks, the room listens.
|
||||
|
||||
*Seasonal:* Pre-harvest water allocation period (approximately six weeks before harvest) is her highest-activity, highest-visibility period. She is present, decisive, and politically exposed during this time. Orik Fennen challenges her allocation decisions every year during this period. She navigates it. The community watches.
|
||||
|
||||
*Anomaly in routine:* Once every six to eight weeks, she makes a solo trip to the property boundary — a walk that takes her approximately 90 minutes and that she does not explain to anyone. No one has asked. She is watching the trade route approach.
|
||||
|
||||
**Axis 8 — Economic Position**
|
||||
|
||||
Direct control: water allocation for every farm in the settlement during the 10–12 week dry-season period. Without her management, the dry season produces disputes that the community's informal governance cannot resolve. She has not monetized this leverage. She is ideologically opposed to doing so — it would make her someone who exploits the community, which contradicts her actual care for it.
|
||||
|
||||
Indirect leverage: the Commission land-grant knowledge she carries. This is not an active economic asset — she cannot sell it without exposing herself. But: it IS the settlement's most valuable economic intelligence asset if anyone knew she had it. Several land claims in this region may rest on false foundations. If the fraudulent land-grant system extends beyond the Voss case (she suspects it does), then whoever controls access to that information controls significant economic leverage across the region.
|
||||
|
||||
Personal economics: modest. She takes no payment for water management (community expectation: the role is a community service). She participates in the community's labor exchange economy. She has small savings, no investment claims, no land title (the farm where she arrived is now owned by a different family).
|
||||
|
||||
**Axis 9 — Relationship Network (Triangle Memberships)**
|
||||
|
||||
*Triangle 1 — Social/Political (Active):*
|
||||
Ysabel (arbiter) ↔ Orik Fennen (senior landholding farmer, Founding Family, believes water allocation should be weighted by land area owned) ↔ Cara Dun (young farmer, third generation, believes allocation should be equal per-household regardless of land size). Purpose: Political + Social.
|
||||
|
||||
Ysabel is the central node. Both parties trust her differently: Orik respects her competence and assumes she's managing the situation toward a status quo that serves everyone; Cara trusts her because she's seen Ysabel resist Orik's pressure. The tension is real, the allocation decision is real, and this triangle activates during every dry-season period. One year it will break and Ysabel's role will be at stake.
|
||||
|
||||
*Triangle 2 — Investigation/Economic (Latent):*
|
||||
Ysabel (holder of evidence) ↔ Pehr Callen (Commission-adjacent Syndic executive, the original conspirator) ↔ Kael Voss (displaced victim, 40 km east). Purpose: Investigation + Economic.
|
||||
|
||||
This triangle is inactive because none of the three nodes knows the other two are in proximity. Kael doesn't know Ysabel exists or has evidence about his family's displacement. Pehr Callen doesn't know Ysabel is alive or where she is. Ysabel knows about both of the others and has chosen not to move.
|
||||
|
||||
The triangle ACTIVATES if: an investigator finds any thread connecting Ysabel to Commission records, or Kael to the land dispute, or Pehr Callen's name surfaces in any adjacent investigation. It also activates if Ysabel crosses her own tolerance threshold and decides to act.
|
||||
|
||||
*Triangle 3 — Tactical (Latent):*
|
||||
Ysabel (target) ↔ Pehr Callen's agents (potential protector/executor) ↔ any investigator or player character who learns Ysabel's significance. Purpose: Tactical + Investigation.
|
||||
|
||||
This triangle exists only from the perspective of someone who knows Ysabel is network-significant. From inside the settlement, Ysabel is an ANCHOR with no visible enemies. The Tactical triangle is invisible until activated by external knowledge.
|
||||
|
||||
**Axis 10 — Tolerance Threshold**
|
||||
|
||||
*For community conflict:* Very high. She has managed 14 years of community disputes without breaking character. She can absorb extended social friction, political challenge, and personal criticism without acting precipitously.
|
||||
|
||||
*For exposure:* Near-zero. If she believes she has been found — by Commission, by Pehr Callen's people, by anyone with hostile intent toward her history — she will leave. She has a pre-prepared exit: she knows which route out of Harrow Drift is fastest, where the first settlement is that she could pass through without being remembered, and what a cover identity looks like. She has not used this exit in 14 years and has added more reasons not to use it each year she stays. But the exit exists.
|
||||
|
||||
*For Kael Voss:* Declining. She is aware her threshold is lowering. Three years ago she accepted she knew where he was. Each passing season she is slightly more aware that the evidence she carries is not helping him while she holds it. She does not know what will push her to act. She suspects something visible — witnessing his situation deteriorate, or meeting him accidentally — would be enough. She avoids the road to Vermin's Cross.
|
||||
|
||||
*For the player character:* Variable based on what they represent. A player who seems to be passing through with no investigative intent gets the warm Stone/Tide welcome and gradually earns trust through community participation. A player who asks specific questions about Commission presence, land records, or her history will find her warmth becomes cautious-correct very quickly. She is not hostile. She is self-preserving.
|
||||
|
||||
---
|
||||
|
||||
### Five Lenses, One NPC
|
||||
|
||||
**The Investigation Lens**
|
||||
|
||||
What the investigator sees at first: a competent, trusted community administrator. No obvious irregularities. Well-liked, stable, clearly not leaving.
|
||||
|
||||
What the investigator eventually sees: the void. Ysabel has no history before arriving at Harrow Drift. No family mentioned (the farmer she arrived with is gone and she doesn't speak of him). No home system. When asked directly, she gives a soft non-answer: "I needed somewhere different." Her knowledge of Commission administrative systems — visible in small details, the specific language she uses about land claims, her taxonomic approach to water allocation records — is more than informal. She has been trained.
|
||||
|
||||
The investigation hook: she is the anomalous presence. Not because she committed a crime here. Because she shouldn't be here at all — someone with her knowledge and capability would not end up in a Backwater/Moderate settlement unless they chose it for reasons that aren't the stated ones.
|
||||
|
||||
The investigation play: not "find the murderer" but "find out who she's hiding from and why." The answer leads off-world — to a Commission warrant, to Pehr Callen, to Kael Voss 40 km east, and to evidence of a land-grant fraud that is not local in scope.
|
||||
|
||||
The information ladder specific to investigation mode:
|
||||
- Low tier: "She doesn't talk about where she came from." (Any community member will say this within a day of asking.)
|
||||
- Mid tier: "Her water management records use Commission administrative notation." (Visible if you look at her actual paperwork.)
|
||||
- High tier: "She made that trip to the property boundary again — she goes every six to eight weeks, alone, and looks down the trade route." (Requires sustained observation or an insider who's noticed.)
|
||||
- Insider tier: Opal Dun says: "I stopped asking seven years ago. Whatever she's carrying, she's carried it longer than she's been here." (Unlocked via deep trust with Opal.)
|
||||
|
||||
**The Tycoon Lens**
|
||||
|
||||
What the tycoon sees: the economic chokepoint. Water allocation controller. Every farmer in the settlement is economically dependent on the seasonal allocation decisions she makes.
|
||||
|
||||
The opportunity: she's not exploiting this. This is immediately unusual to a tycoon sensibility. Someone controlling a mandatory resource in a captive market and not charging above-market rates for it is either naive or principled. In this case: principled. But principled people can be influenced — you just need to find the right currency.
|
||||
|
||||
The tycoon's possible moves:
|
||||
- Offer her a cut of the trade route operation (rejected — she doesn't want money; money creates visibility)
|
||||
- Help formalize the water allocation as a legal structure that protects her role from community vote challenge (interesting to her — reduces her political vulnerability)
|
||||
- Offer access to a secure communication channel outside the settlement (very interesting — she wants to know if the Commission warrant is still active after 14 years)
|
||||
- Offer information about Kael Voss (extremely interesting — this is the tycoon accidentally holding the key)
|
||||
|
||||
The deeper tycoon layer: she holds the evidence of a fraudulent land-grant that likely extends across the region. If the tycoon discovers this (requires significant trust-building or investigation), they have access to an information asset that could: a) be used to challenge existing land titles (disrupting established economic interests), b) be sold to parties who want to restore original titles (Kael Voss, for instance, or his legal advocates), or c) be used as leverage against Pehr Callen (corporate coercion material of significant value). The water management role is the tycoon's entry point. The Callen file chain is the real prize.
|
||||
|
||||
**The Dating Sim Lens**
|
||||
|
||||
What the dating sim player sees: someone who is clearly trusted and clearly closed. The warm Tide exterior is real — she participates in community life, she brings food to gatherings, she knows everyone's name and their children's names. But get her alone and there's a quality of careful control to her openness. She listens more than she speaks. She deflects personal history questions without making you feel deflected.
|
||||
|
||||
The arc: she is not unwilling to connect — she is afraid it's not safe to. The dating sim challenge is not reading her correctly. It's creating enough perceived safety that she stops performing and starts actually trusting.
|
||||
|
||||
Heritage-appropriate trust signals (what earns her):
|
||||
- Participating in community labor without being asked (Tide: public demonstration)
|
||||
- Showing up consistently over time (Stone: tenure earns trust)
|
||||
- Accepting an invitation to a community meal and not asking about her past (both heritages: respecting the social norm)
|
||||
- Helping during the water dispute without trying to position yourself politically (demonstrates you're not there to exploit the community's vulnerabilities)
|
||||
|
||||
The milestone: she lets something slip. A city name she shouldn't know — a reference point for a Commission administrative district that a person who "needed somewhere different" wouldn't have. The player catches it. The choice: press (which opens her up, partially), or let it go (which deepens her trust further). Pressing too hard too early gets the careful-correct Ysabel. Giving her room gets the real one.
|
||||
|
||||
The actual relationship arc: she's been managing her isolation for 14 years. She is genuinely lonely. She has not allowed herself to be seen. A player who gives her consistent, patient, non-invasive attention is offering something she hasn't been able to have for a very long time. When she does open, it's in pieces — not a confession, but a gradual admission that she exists more than she's been letting on.
|
||||
|
||||
The final vulnerable act: she takes the player to the property boundary and watches the trade route without explaining why. This is the closest she gets to showing her actual situation. It's not an explanation. It's a gesture of trust.
|
||||
|
||||
**The Political Drama Lens**
|
||||
|
||||
What the political player sees: the most powerful person in the settlement by functional leverage, who is self-deliberately not using that power for political gain. This is a vacuum that the political game will fill one way or another.
|
||||
|
||||
The active political conflict: Orik Fennen's faction (Founding Family entitlement, believes resource allocation should reflect historical investment) vs. Cara Dun's faction (generational equity, believes resources belong to the current community equally). Ysabel is the tiebreaker. Orik knows this and applies steady social pressure on the allocation decisions. Cara knows this and counts on Ysabel's stated commitment to equity.
|
||||
|
||||
The political play space:
|
||||
- Help Ysabel maintain her role through the community assembly (requires building enough coalition that Orik can't replace her with a sympathetic appointment)
|
||||
- Exploit the conflict by backing one faction (either gets you a powerful local ally but costs you the other half of the settlement)
|
||||
- Use Ysabel's role as leverage to change the allocation rules permanently (requires her cooperation, which requires earning her trust)
|
||||
- Discover that the Fennen family's founding-family entitlement has a land title anomaly in the regional records (Ysabel knows this; she's never said it; she's been protecting community stability by not introducing a land-title challenge into the political mix)
|
||||
|
||||
The deep political layer: the land-grant fraud Ysabel documented wasn't just about the Voss displacement. If she's right that the fraud system was broader, several founding-family land titles in this settlement may also rest on Commission records that were manipulated to favor specific families over others. The political implications are settlement-destabilizing. She has chosen community stability over truth. A political drama player who uncovers this faces the same choice.
|
||||
|
||||
**The Assassination Lens**
|
||||
|
||||
Default assessment of Harrow Drift: locally-significant target pool only. No Commission presence, no Syndic presence, no network-visible actors. Standard assassination play = Poor affinity. Pass through.
|
||||
|
||||
But.
|
||||
|
||||
A player with access to higher-tier intelligence would find: there is a Commission warrant — 14 years old but still active — for a data analyst who accessed restricted land-grant records without authorization and then vanished. The last confirmed sighting was a system away, 14 years ago. The warrant was filed by the Commission. The underlying pressure came from Pehr Callen's Syndic subsidiary.
|
||||
|
||||
Pehr Callen still exists. He is now significantly more powerful. The land-grant fraud is still formally concealed. The analyst who found it is still, technically, evidence of a crime — not because she committed one in any meaningful sense, but because she can testify to what she saw and what documents were altered. Callen has reason to want her permanently unavailable.
|
||||
|
||||
This turns the assassination lens from "no viable targets" to "the highest-difficulty target in the region."
|
||||
|
||||
The assignment (if received): locate and permanently silence a former Commission data analyst, current alias Ysabel Vorn, position water management coordinator, Harrow Drift settlement, population 150, no Commission presence. Mandate: no visible cause of death, no community suspicion, no connection to this contract.
|
||||
|
||||
Operational difficulty: Extreme.
|
||||
|
||||
The factors:
|
||||
- *Community awareness*: Stone/Tide community, 150 people, every face known. A stranger spending more than two days triggers social comment. An assassin needs a cover identity that gives them a reason to be here for long enough to establish a pattern.
|
||||
- *Target observability*: Ysabel has a predictable dawn routine (the solo water inspection) — this is her only extended private interval. It's the obvious window. It's also the only time she is genuinely alone, which means any deviation from her solo status is immediately suspicious.
|
||||
- *Pattern rigidity*: Stone heritage = high pattern rigidity. Her routine is reliable. The assassination window is identifiable. But: she is watching for this. Her 90-minute property boundary checks, her wariness with strangers, her pre-prepared exit — she has been expecting someone to come for 14 years. She will notice surveillance.
|
||||
- *Aftermath*: Tide heritage means communal justice demand if she dies under suspicious circumstances. 150 people who loved her. They will talk. They will remember the stranger. They will ask questions that the Commission eventually hears about. "What happened to Ysabel?" is a question that could, if answered by the right investigator, reopen the original warrant investigation — and lead to Pehr Callen.
|
||||
- *The operational paradox*: Silencing her to prevent her from testifying about Callen requires an operation clean enough that it doesn't spark the investigation that would reach Callen anyway.
|
||||
|
||||
The assassination play is the hardest version of the hardest assignment: an elite target who has been hiding from exactly this for 14 years, embedded in a tight community that will investigate her death with personal intensity, in a settlement with no Meridian coverage (which means no tracking but also no controlled information environment). The assassin who does this cleanly is exceptional.
|
||||
|
||||
---
|
||||
|
||||
### Does the 10-Axis Model Cover All Five Hooks?
|
||||
|
||||
**Verdict: 4.5 of 5. One gap found.**
|
||||
|
||||
The investigation hook lives in Axes 4 (Secret) + 5 (Information Access).
|
||||
The tycoon hook lives in Axes 8 (Economic Position) + 3 (Actual Motivation).
|
||||
The dating sim hook lives in Axes 6 (Trust Architecture) + 10 (Tolerance Threshold).
|
||||
The political hook lives in Axes 9 (Relationship Network) + 2 (Surface Motivation).
|
||||
The assassination hook lives in Axes 7 (Routine Pattern) + 4 (Vulnerability).
|
||||
|
||||
**The gap:** None of the 10 axes explicitly encodes *network-level significance vs. locally-perceived significance*. Ysabel is locally-perceived as an ANCHOR with no enemies — she generates zero `assassination_difficulty` signal from the local society profile alone. The assassination hook only becomes available when a player has access to network-level intelligence (a Commission warrant database, Syndic contractor records, or specific investigation threads that trace back to Callen).
|
||||
|
||||
The 10-axis model as currently specified cannot distinguish between:
|
||||
- An NPC who is genuinely locally insignificant (no network-relevant secrets)
|
||||
- An NPC who is locally insignificant in appearance but carries network-significant information or is network-relevant to external actors
|
||||
|
||||
**Proposed extension: Axis 11 — Network Footprint**
|
||||
|
||||
```
|
||||
network_footprint: Option<NetworkFootprintTag>
|
||||
```
|
||||
|
||||
For most NPCs: `None`. They are exactly what they appear to be in the local context.
|
||||
|
||||
For NPCs like Ysabel: `Some(NetworkFootprintTag)`, which records:
|
||||
- The external actor(s) who consider this NPC significant
|
||||
- The reason (possesses evidence, was witness to event, holds a capability, has a connection)
|
||||
- The access tier required to see this footprint (investigation players reach it via Commission databases; tycoon players reach it via Syndic network intelligence; other playstyles may not reach it at all)
|
||||
|
||||
This axis does not change local behavior. Ysabel is still an ANCHOR. Her routine is still the same. But the generator can now guarantee that the Tactical triangle (Ysabel ↔ Callen's agents ↔ investigating player) is instantiated, even when the district's local `assassination_difficulty` score would not flag it.
|
||||
|
||||
**Implementation note:** The `network_footprint` field should be authored on specific NPCs and not procedurally generated. Procedural NPCs default to `None`. The "false backwater" scenario — where a network-significant actor is hiding in a locally-insignificant setting — is a named scenario type authored by content designers, not a generator output. The generator needs to *support* this scenario type (by providing the field and the Tactical triangle infrastructure), not generate it from scratch.
|
||||
|
||||
---
|
||||
|
||||
## OQ-R4-C: Assassination Difficulty Descriptor — Definitive Placement
|
||||
|
||||
**Answer: DerivedDistrictAnalysis, stored on DistrictSkeleton, computed at Phase 1 (NPC Population stage), not runtime-mutable.**
|
||||
|
||||
The question was: does `assassination_difficulty` live on the DistrictSkeleton, on the SocietyProfile, or is it computed on demand?
|
||||
|
||||
It should NOT live on the SocietyProfile directly — the SocietyProfile describes the cultural parameters, not their derived game-mechanical implications. The SocietyProfile does not know it's being used for game generation.
|
||||
|
||||
It should NOT be computed on demand by the assassination gameplay system — it's used by the Tactical triangle instantiation logic during Phase 1, before the gameplay system ever runs. Computing it late means the Phase 1 skeleton doesn't know whether to instantiate Tactical triangles, produce egress multiplicity guarantees, or budget temporal opacity windows.
|
||||
|
||||
It should NOT be on DramaDensity (runtime storyteller state) — the cultural difficulty of assassination doesn't change because the storyteller elevated the drama. A Dust-dominant community is still a Dust-dominant community regardless of how much drama is currently firing.
|
||||
|
||||
**Canonical placement:**
|
||||
|
||||
```rust
|
||||
struct DistrictSkeleton {
|
||||
// ... existing fields ...
|
||||
guarantee_audit: GuaranteeAuditResult, // existing
|
||||
derived_analysis: DerivedDistrictAnalysis, // NEW: computed from society profile
|
||||
}
|
||||
|
||||
struct DerivedDistrictAnalysis {
|
||||
assassination_difficulty: AssassinationDifficulty,
|
||||
// Computed from: observation_density × information_liquidity × aftermath_engagement
|
||||
// All three derived from society_profile.heritage blend + economic_pressure
|
||||
|
||||
assassination_target_density: u8,
|
||||
// Count of NPCs with network_footprint: Some(_) OR with local significance that makes
|
||||
// them viable local targets. Drives Tactical triangle instantiation budget.
|
||||
|
||||
primary_playstyles: [AffinityLevel; 5],
|
||||
// Per-playstyle rating derived from setting type. Drives content budget weighting.
|
||||
}
|
||||
|
||||
enum AssassinationDifficulty { Low, Medium, High, Extreme }
|
||||
```
|
||||
|
||||
**What "computed from society profile" means concretely:**
|
||||
|
||||
```
|
||||
observation_density = heritage_weighted(frost:low, tide:high, iron:medium_high,
|
||||
dust:very_high, stone:medium, arc:low, vine:high, salt:low,
|
||||
jade:high, spice:high_within_group)
|
||||
|
||||
information_liquidity = heritage_weighted(frost:very_low, tide:high, iron:high_within,
|
||||
dust:high, stone:low, arc:medium, vine:very_high, salt:conditional,
|
||||
jade:low, spice:low_to_outsiders)
|
||||
|
||||
aftermath_engagement = heritage_weighted(frost:low, tide:high, iron:high, dust:high,
|
||||
stone:medium, arc:very_high, vine:medium_high, salt:medium,
|
||||
jade:medium, spice:very_high)
|
||||
|
||||
assassination_difficulty = classify(
|
||||
observation_density × 0.35 +
|
||||
information_liquidity × 0.30 +
|
||||
aftermath_engagement × 0.35
|
||||
)
|
||||
```
|
||||
|
||||
Faction presence modifies the computed value: Commission comprehensive coverage shifts difficulty up one tier (institutional investigation adds aftermath risk). Commission absent with high-Dust community culture = the most dangerous community aftermath without institutional support.
|
||||
|
||||
**Used by:** Tactical triangle instantiation (decides how many Tactical triangles to budget per district, weighted by whether the difficulty makes assassination plausible gameplay). Spatial guarantee audit (Tier 3 conditional checks A-1 through A-4 fire for districts where `assassination_difficulty != Extreme` — Extreme difficulty districts don't need to budget for assassin success, they budget for assassin failure learning). Content balance tools (designer visibility into why a given district is Hard vs. Easy for assassination play).
|
||||
|
||||
---
|
||||
|
||||
## OQ-R4-D: Heritage Grammar Overlay — Concrete Representation for Chunk Fill
|
||||
|
||||
**Answer: Per-heritage HeritageGrammarOverlay structs stored in the generator's authored data, injected into ZonePalette at chunk fill time via weighted blending.**
|
||||
|
||||
The 10-row heritage grammar table from my Round 3 document needs a form chunk fill can consume. Araminta's question was: per-heritage modifier objects, or lookup tables within terrain palette assets?
|
||||
|
||||
Per-heritage modifier objects. The distinction matters for authoring workflow: lookup tables within terrain assets means the heritage grammar is embedded in art assets (Araminta's domain, not mine). Per-heritage modifier objects means the grammar rules are authored in worldbuilding data and consumed by chunk fill as parameters. This is the correct separation — I author the cultural grammar; the terrain palette assets provide the visual vocabulary; chunk fill applies the grammar to the vocabulary.
|
||||
|
||||
**The concrete struct:**
|
||||
|
||||
```rust
|
||||
struct HeritageGrammarOverlay {
|
||||
// For which root this applies
|
||||
heritage_root: HeritageRoot,
|
||||
|
||||
// BLOCK-LEVEL ORGANIZATIONAL PRINCIPLES
|
||||
// These affect block planning decisions, not just chunk fill
|
||||
|
||||
boundary_character: BoundaryCharacter,
|
||||
// What physical form boundaries between properties take
|
||||
// Frost: MinimalFunctional (wire/stake, minimal material)
|
||||
// Stone: PermanentMaterial (stone wall, heavy posts)
|
||||
// Tide: OpenOrNominal (cleared path, no physical barrier)
|
||||
// Iron: CollectivelyMaintained (shared fence line, communally repaired)
|
||||
// Dust: PracticalRepaired (patched material, visibly maintained because replacement is costly)
|
||||
// Vine: OrganicIntegrated (planted hedge, climbing plants as boundary)
|
||||
// Salt: ClearlyDemarcated (clean lines, legible entry points)
|
||||
// Arc: LabeledAndCategorized (marked with notation, documented)
|
||||
// Jade: AestheticlySelected (materials chosen for visual quality)
|
||||
// Spice: HonorAdjacentEnclosure (compound wall, family territory marker)
|
||||
|
||||
open_space_character: OpenSpaceCharacter,
|
||||
// What purpose the open/unclaimed space between structures serves
|
||||
// Functional / Gathering / Ornamental / Buffer / None
|
||||
|
||||
structure_spacing: f32,
|
||||
// Multiplier on base terrain spacing. 0.8 = compact, 1.0 = standard, 1.5 = dispersed
|
||||
|
||||
// CHUNK-FILL LEVEL VISUAL MODIFIERS
|
||||
// These affect which objects from the terrain palette get selected
|
||||
|
||||
decorative_density: f32,
|
||||
// 0.0 (Frost: no decorative elements) to 1.0 (Jade: maximum curation)
|
||||
// Affects: how many decorative object slots are filled from the palette
|
||||
|
||||
gathering_anchor_near_work: bool,
|
||||
// Tide/Vine: true — social spaces woven into work spaces
|
||||
// Frost/Arc: false — social and work spaces are separated
|
||||
|
||||
shared_infrastructure_preference: bool,
|
||||
// Iron/Dust: true — communal granaries, shared equipment storage
|
||||
// Salt/Spice/Frost: false — individual storage and equipment
|
||||
|
||||
repair_visibility: f32,
|
||||
// Dust: high (patched materials in visible use)
|
||||
// Jade: low (replacement preferred over visible repair)
|
||||
// Stone: medium (maintained, not replaced unnecessarily)
|
||||
// Frost: medium-low (functional repair, not displayed)
|
||||
|
||||
facade_investment: f32,
|
||||
// Spice: high (aesthetic investment in public-facing surfaces)
|
||||
// Frost: very low (exterior presents nothing)
|
||||
// Vine: medium-high (exterior says "people live here")
|
||||
// Salt: low (commercial clarity, not personal expression)
|
||||
// Jade: high (careful selection of visible materials)
|
||||
|
||||
signage_density: f32,
|
||||
// Arc: high (things labeled and categorized)
|
||||
// Frost: very low (minimal labeling)
|
||||
// Salt: medium (commercial labels, pricing visible)
|
||||
// Stone: low (land markers but not informational signage)
|
||||
|
||||
// OBJECT POOL MODIFIERS
|
||||
// Heritage-specific weighting of which objects from the terrain palette are preferred
|
||||
|
||||
preferred_enclosure_tags: Vec<ObjectTag>,
|
||||
// Which enclosure objects this heritage preferentially places
|
||||
// Frost: ["functional_stake", "wire_minimal"]
|
||||
// Stone: ["stone_wall", "heavy_post", "stone_foundation_exposed"]
|
||||
// Vine: ["planted_hedge", "climbing_trellis", "woven_stake"]
|
||||
|
||||
accent_object_tags: Vec<ObjectTag>,
|
||||
// Objects that appear more frequently in this heritage's spaces
|
||||
// Tide: ["seasonal_decoration", "gathering_table_outdoor", "shared_fire"]
|
||||
// Arc: ["label_stake", "record_board", "measurement_tool"]
|
||||
// Jade: ["aesthetic_planting", "quality_material_accent", "curated_stone"]
|
||||
|
||||
excluded_object_tags: Vec<ObjectTag>,
|
||||
// Objects this heritage actively avoids
|
||||
// Frost: ["gathering_table_outdoor", "decorative_public_display"]
|
||||
// Iron: ["private_luxury_accent", "status_display_object"]
|
||||
// Arc: ["unlabeled_storage", "disorganized_pile"]
|
||||
}
|
||||
```
|
||||
|
||||
**How chunk fill uses it:**
|
||||
|
||||
```
|
||||
1. Get district's society_profile.heritage (Vec<HeritageEntry> with blend weights)
|
||||
2. For each heritage root in blend:
|
||||
a. Look up its HeritageGrammarOverlay from authored data
|
||||
3. Blend overlay parameters by heritage weight:
|
||||
decorative_density = sum(root.decorative_density × root.blend_weight)
|
||||
repair_visibility = sum(root.repair_visibility × root.blend_weight)
|
||||
[etc. for all scalar fields]
|
||||
4. For categorical fields (boundary_character, etc.): select by dominant heritage weight
|
||||
5. For object tag lists: union of preferred/accent tags, intersection-exclusion of excluded tags
|
||||
6. Apply blended overlay to base ZonePalette:
|
||||
- Modifies object pool selection probabilities
|
||||
- Adjusts spacing and density parameters
|
||||
- Sets facade/interior investment balance
|
||||
7. Proceed with normal chunk fill using modified palette
|
||||
```
|
||||
|
||||
**Authoring workflow:** I maintain the canonical `HeritageGrammarOverlay` data for each of the 10 roots. Araminta expresses these as specific object pool compositions in her visual grammar. The chunk fill pipeline reads my data structures; Araminta's assets populate the object pools that those structures reference. Cross-domain requirement: the `ObjectTag` vocabulary must be shared between my heritage grammar spec and Araminta's asset categorization.
|
||||
|
||||
**Storage:** The `HeritageGrammarOverlay` set (10 roots) is global authored data, not per-district. It is loaded once at generator startup and referenced during chunk fill.
|
||||
|
||||
---
|
||||
|
||||
## Vessel Cultural Grammar — Finalization
|
||||
|
||||
Lead decision: entity-carried MobileChunk is CORE. Tyre's architecture wins. This closes OQ-R4-A for cultural grammar purposes.
|
||||
|
||||
My supplement (Round 3) established the cultural grammar for all vehicle types. Now that the architectural question is settled, I can finalize these as the canonical spec for Tyre's `MobileChunk` cultural layer.
|
||||
|
||||
### transit_social_modifier — Canonical Spec
|
||||
|
||||
```rust
|
||||
struct TransitSocialModifier {
|
||||
// Rate adjustments — multiplicative on base society_profile rates
|
||||
trust_building_multiplier: f32, // 1.5–2.5x (forced proximity accelerates)
|
||||
privacy_level_modifier: f32, // –0.3 to –0.6 (physical impossibility of full privacy)
|
||||
enforcement_level_modifier: f32, // –0.4 to –0.7 (institutional attenuation)
|
||||
|
||||
// Information flow modifiers
|
||||
internal_flow_multiplier: f32, // 1.5–3.0x (nowhere else to direct social energy)
|
||||
external_flow_blocked: bool, // true during interstellar transit
|
||||
|
||||
// Vehicle-type-specific grammar
|
||||
variant: TransitVariant,
|
||||
}
|
||||
|
||||
enum TransitVariant {
|
||||
BoundedLinear {
|
||||
// Train: linear access topology, class-sequence social grammar
|
||||
car_sequence: Vec<SocialCarZone>,
|
||||
// Each SocialCarZone has: access_tier, heritage_norms, dominant_heritage_override
|
||||
// The dominant heritage of each car class can differ from the train's overall profile
|
||||
// Example: premium car may be Arc/Jade-flavored; general car is Iron/Frost/Tide-weighted
|
||||
temporal_pressure: Duration,
|
||||
witness_compactness: WitnessCompactnessLevel, // Low | Medium | High | Maximum
|
||||
},
|
||||
BoundedMobile {
|
||||
// Ship within system: bounded spherical, crew insider threshold applies
|
||||
crew_insider_threshold: f32, // crew members get trust bonus vs. passengers
|
||||
passenger_manifest_seeded: bool, // true = manifest fixed at departure
|
||||
temporal_pressure: Duration,
|
||||
},
|
||||
InterSystem {
|
||||
// Between horizon gates: most extreme information asymmetry
|
||||
jurisdiction_suspended: bool, // true = no Commission enforcement authority
|
||||
external_comms_blocked: bool, // true = no contact with outside until arrival
|
||||
institutional_role_strip: f32, // 0.0–1.0 = degree to which formal roles attenuate
|
||||
// full strip (1.0) = roles are entirely social, no institutional backing
|
||||
// partial strip (0.5) = hierarchy nominally maintained but enforcement is social only
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Cultural Grammar Rules by Vehicle Type
|
||||
|
||||
**Trains (BoundedLinear)**
|
||||
|
||||
The car sequence is a physical expression of social hierarchy. The player can observe the class gradient simply by walking the train from end to end. Heritage roots determine how each class tier behaves socially:
|
||||
|
||||
| Car class | Frost-flavored | Tide-flavored | Iron-flavored |
|
||||
|---|---|---|---|
|
||||
| Premium | Compartmentalized, minimal contact, high privacy | Communal first-class dining, shared tables, conversation expected | Rarely present; if Iron workers are in premium, they are uncomfortable and close-grouped |
|
||||
| Standard | Row seating, neighbors interact minimally, book/screen focus | Groups naturally form, food shared, children move freely between seats | Solidarity cluster: workers know each other, outsider immediately noticeable |
|
||||
| General | Silent efficiency, space maintained, no eye contact | Loud, community atmosphere, information flows freely | Union-aware space: political conversation common, newcomer assessed |
|
||||
|
||||
Temporal pressure characteristic: the journey ends at a known time. This creates a countdown quality that makes every conversation feel slightly more urgent than it would in a fixed district. Social information that would take a week to surface in a bar emerges in four hours on a train.
|
||||
|
||||
Assassination on a train: classic scenario architecture. The target cannot escape. The witnesses cannot leave. The elimination window exists during the one car-class transition moment when crowd density drops and witness configuration changes. Post-action management is compressed: the assassin must establish an alibi and manage evidence during the remaining journey time, with arrival at destination being the hard deadline for investigative exposure.
|
||||
|
||||
**Ships within system (BoundedMobile)**
|
||||
|
||||
Crew insider threshold means: crew members have a distinct trust baseline toward each other and a different baseline toward passengers. The ship has two overlapping social contexts — crew community (stable, long-established) and passenger community (temporary, journey-specific).
|
||||
|
||||
Heritage root behavior for crew:
|
||||
- Iron-heritage crew: high solidarity, newcomers (including player) are assessed by competence and contribution before being trusted
|
||||
- Salt-heritage crew: transactional; they'll exchange information if there's value in it
|
||||
- Tide-heritage crew: the ship becomes their community; they welcome passengers more readily than Iron crew would
|
||||
|
||||
Heritage root behavior for passenger pool (seeded at departure from available NPC pool at origin):
|
||||
- The passenger manifest is the scenario's social content; its heritage composition is seeded from the departure location's population distribution
|
||||
- A ship leaving from a Frost-dominant hub has different passenger social dynamics than one from a Tide/Vine port
|
||||
|
||||
**Interstellar transit (InterSystem)**
|
||||
|
||||
The most extreme case. `jurisdiction_suspended: true` means the ship exists in a legal vacuum. Normal enforcement depends entirely on the crew's own authority, which is social rather than institutional during transit.
|
||||
|
||||
Heritage root behaviors under institutional suspension:
|
||||
|
||||
| Heritage root | Behavior under suspension |
|
||||
|---|---|
|
||||
| Frost | Doubles down on privacy. Less interaction, not more. The individual becomes more contained as external structures relax. |
|
||||
| Tide | The ship-community expands to fill the void. Social bonds form fast. The journey becomes the community. |
|
||||
| Iron | Collective awareness activates. Workers organize informally. Whoever has practical competence gets listened to regardless of formal role. |
|
||||
| Salt | Grey-market window opens immediately. Things that couldn't be traded under normal jurisdiction can now be traded. The Salt-heritage passenger is calculating. |
|
||||
| Arc | Discourse opportunity. The suspended context removes the social penalties for unconventional conversation. The Arc-heritage traveler wants to talk about things they couldn't in normal social context. |
|
||||
| Spice | Family networks become the social unit. Non-family outsiders are on the outside of the primary social structure. |
|
||||
|
||||
`external_comms_blocked: true` means the information environment is sealed. An investigator who reaches an in-transit ship has maximum information opportunity (witnesses can't leave, everyone is accessible) with zero outside support. Whatever they learn, they must act on within the confines of the journey.
|
||||
|
||||
### Setting note on information asymmetry in transit
|
||||
|
||||
Transit is where the game's core mechanic is most exposed. Normal districts allow players to defer: talk to that NPC tomorrow, check the archive next week, come back when you have better access. Transit removes deferral. The pressure is the content.
|
||||
|
||||
Every vehicle type compresses the information landscape. The same NPC who would take three weeks of careful relationship-building in a district may reveal the same information in a 6-hour voyage — because the social pressure of proximity, the absence of external distraction, and the shared condition of confinement change the trust calculus. The transit modifier multipliers are not arbitrary: they reflect what forced proximity does to human social behavior.
|
||||
|
||||
---
|
||||
|
||||
## Summary: Round 4 Deliverables
|
||||
|
||||
**OQ-R4-E (WRITE THE NPC):** Done. Ysabel Vorn, 14 years at Harrow Drift, Stone/Tide farming settlement. Full 10-axis profile. All five lenses demonstrated with specific information ladders, gameplay hooks, and operational details.
|
||||
|
||||
**Finding from the NPC exercise:** The 10-axis model covers 4.5 of 5 lenses fully. The gap: no axis for network-level significance vs. locally-perceived significance. A locally-appearing NPC who is a network-significant target is currently invisible to the assassination lens until a player has network-level access. Proposed: Axis 11 (Network Footprint) as an authored field, defaulting to `None` for procedural NPCs, set explicitly for scenario NPCs like Ysabel.
|
||||
|
||||
**OQ-R4-C (Assassination Difficulty Placement):** `DerivedDistrictAnalysis` struct on `DistrictSkeleton`, computed at Phase 1 from society profile parameters. Not runtime-mutable. Carries `assassination_difficulty: AssassinationDifficulty`, `assassination_target_density: u8`, and `primary_playstyles: [AffinityLevel; 5]`.
|
||||
|
||||
**OQ-R4-D (Heritage Grammar Overlay Encoding):** Per-heritage `HeritageGrammarOverlay` structs in authored global data. Chunk fill blends overlays by heritage weight and applies to base ZonePalette. Authoring domain is mine (cultural rules); visual asset expression is Araminta's (object pool populations). `ObjectTag` vocabulary must be shared.
|
||||
|
||||
**Vessel cultural grammar:** Finalized as `TransitSocialModifier` with `TransitVariant` enum covering BoundedLinear (trains), BoundedMobile (in-system ships), and InterSystem (between horizon gates). Heritage-root behavior tables by vehicle type. All content in my Round 3 supplement is now formalized as a concrete spec ready for Tyre's MobileChunk implementation.
|
||||
|
||||
---
|
||||
|
||||
**Author:** Miri
|
||||
**Date:** 2026-02-27
|
||||
**Status:** Round 4 complete.
|
||||
|
||||
**One item for the D-record stack:** The `HeritageGrammarOverlay` struct should become a D-record (adds to D-READY-9: Heritage Grammar Overlay for Non-Urban Palettes). The NPC Axis 11 finding should be raised as a new Q-record for the next sprint — it is a gap in the current NPC generation model that affects assassination scenario instantiation specifically.
|
||||
@@ -0,0 +1,82 @@
|
||||
# Generator Architecture Workshop — Round 5: Miri (Worldbuilder)
|
||||
|
||||
**Topic:** Final review of workshop-outcomes.md before D-record filing.
|
||||
**Date:** 2026-02-27
|
||||
**Scope:** Sign-off + corrections only. No new proposals.
|
||||
|
||||
---
|
||||
|
||||
## Sign-Off Summary
|
||||
|
||||
Most of the document is accurate. One factual error in D-READY-10 heritage root correlations. All other items I was asked to verify are correct.
|
||||
|
||||
---
|
||||
|
||||
## Verified Correct
|
||||
|
||||
**Ysabel Vorn litmus test (NPC Model section):** Accurate. 4.5/5 stated correctly. 10 axes listed correctly and match my Round 4 document. Axis 11 (Network Footprint) raised correctly as a Q-record, not a confirmed decision. The "authored scenario NPCs" framing is right — this should never be procedurally generated.
|
||||
|
||||
**D-READY-9 (Heritage Grammar Overlay):** Authoring domain separation is correct.
|
||||
- Miri: organizational principles, boundary character, spacing, social grammar (HeritageGrammarOverlay Rust struct)
|
||||
- Araminta: visual expression — object sets, arrangement algorithms, lighting temperature (TOML modifier files)
|
||||
- Shared: ObjectTag vocabulary co-maintenance requirement
|
||||
|
||||
**D-READY-12 (Trauma Events):** Subtypes match my Round 3 specification (PhysicalDestruction, EconomicDisruption, PoliticalShock, ViolenceEvent, MigrationShock). Dual-track model (structural damage via StructuralChange; cultural response via NPC pattern weight shifts) is correct. Heritage-seeded decay rate variation is correct.
|
||||
|
||||
**D-READY-13 (MobileChunk / Vessel):** Correctly points to my Round 4 document for the canonical TransitSocialModifier and TransitVariant spec. BoundedLinear / BoundedMobile / InterSystem enum variants listed correctly.
|
||||
|
||||
**OQ-R4-C synthesis (Q-NNN-f):** The framing — "stored cultural baseline (DerivedDistrictAnalysis on skeleton) + on-demand computation for player-facing assessment" — is an acceptable synthesis. Clarification I want on record: if on-demand computation is added for player-facing use, it is subordinate to the Phase 1 DerivedDistrictAnalysis value. Game logic (Tactical triangle instantiation, guarantee audit) uses the Phase 1 value. Any on-demand computation is display-only. This should be explicit in the formal D-record.
|
||||
|
||||
---
|
||||
|
||||
## Correction Required — D-READY-10
|
||||
|
||||
**Current text:** "Frost/Stone → physical_distance; Tide/Vine → social_permission; Dust/Salt → utilitarian_cover."
|
||||
|
||||
**Error:** Dust is misclassified. Dust should be `social_permission`, not `utilitarian_cover`.
|
||||
|
||||
**Canonical source:** My Round 3 document, Section 2.4:
|
||||
|
||||
> "Frost → physical_distance (individual space is respected everywhere)"
|
||||
> "Tide/Dust → social_permission (negotiated privacy within community framework)"
|
||||
> "Iron → utilitarian_cover (labor function covers presence)"
|
||||
|
||||
**Why this matters:** Dust culture is characterized by maximum communal observation — survival-level social awareness, shared information as a community good. In a Dust community, the only privacy available is **negotiated** ("we agree not to see what you're doing"). There is no privacy via physical distance (everyone sees everything) and no privacy via utilitarian cover (in a Dust community, being in the barn is suspicious precisely because it's isolated from the collective). Dust belongs with Tide in `social_permission`.
|
||||
|
||||
**Iron is missing entirely.** Iron → utilitarian_cover is the clearest mapping: labor function covers presence ("what workers do after the shift" and "what happens in the union hall"). Iron should appear under `utilitarian_cover`.
|
||||
|
||||
**Corrected heritage root correlations:**
|
||||
|
||||
- `physical_distance`: Frost, Stone
|
||||
- `social_permission`: Tide, Vine, **Dust**
|
||||
- `utilitarian_cover`: **Iron**, Salt
|
||||
|
||||
Note: Stone, Vine, and Salt were not mapped in my Round 3 document — these are plausible extensions I accept. The firm corrections are Dust (wrong type) and Iron (missing).
|
||||
|
||||
**Corrected text for D-READY-10:**
|
||||
|
||||
> Heritage root correlation: Frost/Stone → `physical_distance`; Tide/Vine/Dust → `social_permission`; Iron/Salt → `utilitarian_cover`. Location within terrain is seeded independently.
|
||||
|
||||
---
|
||||
|
||||
## One Omission (Not a Factual Error)
|
||||
|
||||
D-READY-12 is technically correct but loses a framing point that has gameplay implications. The design principle underlying trauma event response is:
|
||||
|
||||
**Trauma intensifies culture, it does not transform it.**
|
||||
|
||||
A stressed community becomes a more concentrated version of itself. Frost communities close harder. Tide communities grief more publicly. Iron communities organize more collectively. The heritage root character is amplified under stress, not replaced.
|
||||
|
||||
This matters for gameplay because players who have learned a heritage root's trust model can predict community behavior in the aftermath — and should be able to. It's not in the D-record language anywhere. Suggest adding a one-line note to the D-record: "Cultural response is heritage-root intensification, not transformation. Decay is toward the community's pre-trauma baseline, not toward a new equilibrium."
|
||||
|
||||
---
|
||||
|
||||
## Status
|
||||
|
||||
One correction required (D-READY-10 heritage correlations). One clarification requested (OQ-R4-C on-demand computation is display-only). One framing note suggested for D-READY-12.
|
||||
|
||||
Everything else: confirmed accurate.
|
||||
|
||||
**Author:** Miri
|
||||
**Date:** 2026-02-27
|
||||
**Status:** Round 5 complete.
|
||||
@@ -0,0 +1,308 @@
|
||||
# Generator Architecture Workshop — Round 1: Nigel (Replayability & Procedural Generation)
|
||||
|
||||
**Date:** 2026-02-27
|
||||
**Role:** Replayability Advocate
|
||||
**Task:** What variation and replayability guarantees must the generator provide? What makes two generated districts feel different?
|
||||
|
||||
---
|
||||
|
||||
## Framing: Why This Is the Most Important Design Question in the Whole Project
|
||||
|
||||
Before I get into mechanics, I need to say something bluntly: **the generator is the project's long-term survival mechanism.** The hand-authored v0.1 Transit District is brilliant — it will produce exactly the experience we designed. But that's one playthrough. Maybe two if you swap characters. The 300-world model isn't about 300 unique hand-crafted stories. It's about a generator that produces *600 different stories from 300 different seeds*, with the player discovering that their playthrough of System X bears almost no resemblance to their friend's playthrough of the same system.
|
||||
|
||||
That's the promise. Here's what the generator architecture needs to guarantee to keep it.
|
||||
|
||||
---
|
||||
|
||||
## Section 1: Non-Negotiable Replayability Guarantees
|
||||
|
||||
The generator must provide hard guarantees at three layers. If any of these fail, we're building a content machine that burns through players in a single sitting.
|
||||
|
||||
### Guarantee 1: Structural Non-Repeatability Per Seed
|
||||
|
||||
Every game start must produce a configuration that is *informationally unique*. Two playthroughs on different seeds must differ in:
|
||||
|
||||
- **Who is entangled** with the conspiracy — the 20% entanglement assignment (D-029) must be drawn from a pool large enough that the same NPC is rarely the investigation target across seeds
|
||||
- **Where the evidence is** — manifest discrepancies, corridor access tokens, physical evidence placement must vary in location, not just skin
|
||||
- **Which Tier 1 modules are active** — the pool-draw at game start (D-023) means different conspiracies are running in different seeds. Same district, different crime.
|
||||
- **Which triangles are in what configuration** — the *shape* of the social network (who knows whom, who suspects whom) must vary, not just the NPC portraits
|
||||
|
||||
This is structural randomness. It's decided at game start and baked into the seed state (Q-030). The player's knowledge from playthrough 1 becomes actively misleading in playthrough 2 — because they'll chase the same suspect types and find different people.
|
||||
|
||||
### Guarantee 2: Character-as-Fundamentally-Different-Game
|
||||
|
||||
The smuggler and detective playing in the same generated world must describe *incompatible experiences* of the same district. They're not seeing different parts of the same map. They're constructing entirely different narratives from the same substrate.
|
||||
|
||||
This guarantee is mostly architectural (information boundaries, separate monologue pools per D-032, separate access tier dynamics) but the generator has a role: it must produce districts where **both character lenses yield distinct, valid gameplay**. A generated district that only makes sense from one character perspective breaks the core promise of D-027.
|
||||
|
||||
Concretely: every generated district must contain at minimum one social site that reads as *mundane infrastructure* to the smuggler (their workplace camouflage) and as *institutional checkpoint* to the detective (access-tier gating). Same space. Different game.
|
||||
|
||||
### Guarantee 3: Knowledge Rot Across Playthroughs
|
||||
|
||||
Player knowledge from playthrough 1 must not trivialize playthrough 2. This is the "no metagaming" guarantee. The generator achieves this by varying per seed:
|
||||
|
||||
- **NPC tolerance thresholds** (D-064) — the social calculus is different every run. The walk-away rule you learned last time doesn't apply.
|
||||
- **Entanglement pattern** (D-029) — the 20% rate varies per seed. In some runs, the bartender is clean. In others, they're the second link in the chain.
|
||||
- **Evidence placement** — you can't remember where the manifest is. It moves.
|
||||
- **Triangle configuration** — which investigative path (A, B, or C per D-093) leads somewhere productive depends on which NPCs happen to be in which relationships this run.
|
||||
|
||||
The generator must surface these as *seeded structural choices* — captured in the seed-state.yaml (Q-030) so they're reproducible, but varied enough that two seeds produce genuinely different strategic terrain.
|
||||
|
||||
---
|
||||
|
||||
## Section 2: Variation Axes at Each Pipeline Stage
|
||||
|
||||
Here's where I want to be precise. Every pipeline stage has levers. Some vary the *structure* of the world (high impact, discovered late). Some vary the *surface* of the world (moderate impact, immediately visible). Both matter. Let's name them.
|
||||
|
||||
### Stage 1: Geography
|
||||
|
||||
**Fixed across runs of the same world type:** Planet class, station type, orbital position, climate band (these define the setting type — Transit Hub, Outpost, Capital).
|
||||
|
||||
**Variable per seed:**
|
||||
- **Site topology** — where the district sits on the planet/station surface. Coastal vs. inland. High-orbital vs. close-in. These shape infrastructure routing and therefore access topology.
|
||||
- **Historical event seed** — how old is this settlement? What happened here? A district that survived a civil conflict 50 years ago has repurposed buildings, blocked corridors, uneven maintenance. This is "geology for social spaces."
|
||||
|
||||
**Impact on player:** Shapes the *feeling* of the district before a single NPC spawns.
|
||||
|
||||
### Stage 2: Infrastructure
|
||||
|
||||
**Fixed:** The basic transport logic (gates connect to horizon station, tram connects districts — D-095). The access topology *model* (D-025 functional clusters require connected space with sightlines).
|
||||
|
||||
**Variable per seed:**
|
||||
- **Transport node placement** — where The Loop platform drops players shapes which entry path is natural vs. requires intent. This creates different ambient NPC traffic flows per run.
|
||||
- **Utility routing** — maintenance corridor networks are seeded from infrastructure placement. Same building types, different back-routes. The smuggler's map of "safe passages" varies per run.
|
||||
- **Faction infrastructure presence** — Commission checkpoint density varies by faction weight at the district level. Heavy Commission presence = more formal access barriers. Low presence = more informal, permeable spaces.
|
||||
|
||||
**Impact on player:** Movement grammar changes. The routes you find in one run aren't the safe routes in the next.
|
||||
|
||||
### Stage 3: Amenities and Services (Faction/Economic Layer)
|
||||
|
||||
This is where the *personality* of the district gets determined. I want to emphasize: this stage has the highest variety payoff per authored ingredient.
|
||||
|
||||
**Variable per seed:**
|
||||
- **Faction control weight** — which factions are strong in this district this run? Expressed as power gradient across the six social sites. A Commission-heavy Transit District feels oppressive and procedurally ordered. An independently-weighted district feels informal, chaotic, full of unofficial arrangements.
|
||||
- **Economic tier** — prosperous districts have different building quality, different NPC behavior, different contraband (premium lattice components vs. bulk diverted medical grade). The investigation *texture* changes.
|
||||
- **Historical economic events** — strikes, booms, collapses. A district recovering from an economic shock has half-finished buildings, converted spaces, NPCs with disrupted routines.
|
||||
- **Cultural ingredient composition** (Q-032's 6-category menu) — Heritage Roots + Settlement Motivation + Economic Function + Philosophical Alignment + Corporate/Faction Presence + Drift Stage. These feed into the district's flavor palette. Same zoning type, completely different cultural *atmosphere*.
|
||||
|
||||
**Impact on player:** The investigation surface changes. Different NPCs have different leverage points. Different faction alignments create different institutional blind spots to exploit.
|
||||
|
||||
### Stage 4: Zoning
|
||||
|
||||
**Fixed:** The *type* of zone (residential, commercial, industrial, institutional) defines the template pool to draw from. This is the invariant skeleton.
|
||||
|
||||
**Variable per seed:**
|
||||
- **Zone density** — how many blocks of each type per district? A predominantly industrial district with only one social venue feels different from a mixed-use district with competing social centers.
|
||||
- **Zone boundary placement** — where industrial meets residential creates friction zones (D-051: "settling is placement"). Generator seeds the friction topology.
|
||||
- **Multi-block reservation selection** — which civic structure templates are drawn for this district? A district that rolled "active Commission oversight station" plays very differently from one that rolled "decommissioned processing facility."
|
||||
|
||||
**Impact on player:** The strategic landscape — where to go, what access is blocked by what authority — varies per seed.
|
||||
|
||||
### Stage 5: Block Generation
|
||||
|
||||
This is the sub-chunk quarter system's home. I'll expand this in Section 3.
|
||||
|
||||
**Variable per seed:**
|
||||
- Quarter merge pattern per block (which chunks combine into one building)
|
||||
- Building footprint variety within zoning type
|
||||
- Flavor structure assignment in unclaimed quarters
|
||||
|
||||
**Impact on player:** Physical movement, chokepoints, sightlines. The detective's surveillance positions and the smuggler's shadow routes are never identical across runs.
|
||||
|
||||
### Stage 6: Chunk Fill
|
||||
|
||||
**Variable per seed:**
|
||||
- **Social site template selection from pool** — given the zoning type and district skeleton, which specific templates are instantiated? Pool is larger than draws, so each run draws a subset.
|
||||
- **NPC generation** — 10-axis rolls (D-024) produce different personality configurations within the same role. Same "dock worker" role, different tolerance threshold, different secret, different relationship network.
|
||||
- **Triangle configuration** — which NPCs end up in which triangle positions? The three-NPC conflict topology is seeded, not scripted.
|
||||
- **Entanglement assignment** — which of the generated NPCs are in the 20% entangled group?
|
||||
|
||||
**Impact on player:** The people are different. The social dynamics are different. The investigation is structurally similar (find the manifest discrepancy, follow the social chain) but the *cast* produces different stories.
|
||||
|
||||
---
|
||||
|
||||
## Section 3: The Sub-Chunk Quarter System as Replayability Engine
|
||||
|
||||
This is where I get genuinely excited, because the sub-chunk quarter system is doing *exactly the right thing* without requiring the generator to hand-craft every building.
|
||||
|
||||
### How Quarters Work for Variety
|
||||
|
||||
A block = 2×2 chunks. A chunk = 32×32 visual tiles. Each chunk divides into 4 quarters (16×16 visual each). The quarter merge rules from the workshop brief produce:
|
||||
- **2×2 merge** → full-chunk building (a substantial structure filling the whole chunk)
|
||||
- **1×2 merge** → half-chunk building (corridor-adjacent, compact spaces)
|
||||
- **L-shape** → asymmetric footprint that suggests organic growth / retrofitted structure
|
||||
- **Separate quarters** → small structures with space between them (gardens, stalls, shacks)
|
||||
|
||||
The *replayability payoff*: the same block zoning type can produce five or more distinct physical configurations from the same template pool. A commercial block could be one large market hall (2×2 merge), two competing shops (1×2 merges), or four small stalls with a shared courtyard (separate quarters).
|
||||
|
||||
### What Changes Per Run at the Quarter Level
|
||||
|
||||
The quarter merge decision is seeded from:
|
||||
1. The block's economic tier (wealthy = larger, consolidated footprints; struggling = fragmented, improvised)
|
||||
2. The cultural ingredient composition (certain cultural inputs favor dense/compact; others favor distributed/informal)
|
||||
3. The historical event seed (a bombed district that rebuilt has irregular merge patterns — one full building next to a gap-filled plot)
|
||||
4. Random seed noise within the above constraints (same inputs can produce multiple valid configurations)
|
||||
|
||||
This means: **two players in the same district type, same economic tier, but different seeds will navigate different physical spaces.** The chokepoints move. The sightlines change. The surveillance dead zones are different.
|
||||
|
||||
### The Perceived Variety Effect
|
||||
|
||||
From the player's perspective, they never see "this is a 2×2 chunk merge." They see a loading bay that feels like it was retrofitted from something bigger. Or a row of small workshops with a narrow alley between them. The quarter system produces *architectural intention* — the sense that someone built this for a reason — without requiring hand-authoring every building.
|
||||
|
||||
And crucially: **this variety is consistent within a single playthrough but differs across playthroughs.** The player can learn this run's layout. But they can't memorize a reusable solution because the next run's geometry is different.
|
||||
|
||||
---
|
||||
|
||||
## Section 4: Flavor Structure Assignment to Unclaimed Quarters
|
||||
|
||||
This is where the district gets its texture. When a quarter doesn't merge into a larger building and isn't claimed by a social site template, it becomes *unclaimed space*. This space must feel inhabited, not empty.
|
||||
|
||||
### What Goes in Unclaimed Quarters
|
||||
|
||||
Unclaimed quarters get assigned from a **district flavor palette** — a weighted list of small structures appropriate to the cultural and economic context. I'd propose these palette categories:
|
||||
|
||||
**Informal Economy Indicators:**
|
||||
- Market stalls (active trade, high foot traffic)
|
||||
- Vendor carts (semi-permanent, clusters near transit nodes)
|
||||
- Informal repair shops (tools, spare parts — signals self-reliance)
|
||||
|
||||
**Settlement Indicators:**
|
||||
- Container gardens (food independence, community care)
|
||||
- Improvised seating clusters (social gathering, no institutional oversight)
|
||||
- Personal shrines / memorial spaces (community attachment, time depth)
|
||||
|
||||
**Economic Stress Indicators:**
|
||||
- Shacks / temporary shelters (population overflow, institutional failure)
|
||||
- Abandoned equipment (former economic use, now repurposed or left)
|
||||
- Unauthorized storage (gray-market goods movement)
|
||||
|
||||
**Faction Presence Indicators:**
|
||||
- Commission kiosks / checkpoint remnants (even if unmanned — implies surveillance norm)
|
||||
- Union hall notice boards (organized labor presence)
|
||||
- Corporate branded infrastructure (Syndic, independent operators)
|
||||
|
||||
### Assignment Logic
|
||||
|
||||
Palette composition is driven by cultural ingredients (Q-032) and economic tier:
|
||||
- **Economic tier** determines the ratio of formal/informal and stressed/stable indicators
|
||||
- **Cultural Heritage Roots** determine which specific types appear (some cultures have garden traditions, others don't)
|
||||
- **Faction Presence ingredient** determines which faction-affiliated structures appear
|
||||
- **Drift Stage** (how long since foundation) determines how much improvised vs. planned infrastructure exists
|
||||
|
||||
The key design rule: **unclaimed quarters must always feel *inhabited*, not empty.** A vacant lot is not flavor. A vacant lot with a rusted cargo manifest posted to a pole, someone's coat hanging on a conduit, and a drainage channel someone diverted with a bent plate — that's a space with history. The generator must assign flavor at enough density that every quarter reads as a decision someone made.
|
||||
|
||||
---
|
||||
|
||||
## Section 5: What Makes Two Districts of the Same Zoning Feel Different
|
||||
|
||||
Two Transit Hub districts with the same zoning type should feel like entirely different worlds. Here's the full variety stack:
|
||||
|
||||
### Layer 1: Cultural Personality
|
||||
The cultural ingredients menu (Q-032) is the highest-leverage differentiator. Same "industrial transit hub" zoning, but:
|
||||
- **Heritage Roots A + Philosophical Alignment B** → dense, communal, visible labor culture. Corridors have murals. Shared meal spaces.
|
||||
- **Heritage Roots C + Corporate Presence D** → efficient, branded, transactional. Clean corridors. Everything labeled. Privacy expectations low.
|
||||
|
||||
These produce different NPC naming conventions, different ambient dialogue flavor, different informal behavior patterns. The *feel* of the district is completely different before you've seen a single building footprint.
|
||||
|
||||
### Layer 2: Faction Power Gradient
|
||||
Same zoning, different faction control:
|
||||
- **Commission-heavy** → surveillance cameras visible, security NPCs on patrol routes, formal checkpoint infrastructure at zone transitions
|
||||
- **Syndic-heavy** → corporate logos on infrastructure, trade efficiency in customs processing, information flow controlled by corporate NPC hierarchy
|
||||
- **Weakly controlled** → informal arrangements visible, gray-market activity in open spaces, NPCs with more freelance social relationships
|
||||
|
||||
### Layer 3: Economic Tier
|
||||
- **Prosperous** → larger consolidated buildings (2×2 quarter merges), maintained infrastructure, NPCs with stable routines and higher tolerance thresholds
|
||||
- **Struggling** → fragmented footprints (separate quarters), improvised flavor structures, NPCs with disrupted routines and higher social volatility
|
||||
|
||||
### Layer 4: Historical Event Seed
|
||||
The district's backstory leaves physical traces:
|
||||
- A labor dispute 20 years ago → union hall still present, specific NPCs with long-memory grievances, certain maintenance corridors blocked from an old barricade never fully cleared
|
||||
- A corporate merger 10 years ago → two different architectural styles visible (the original and the acquisition), NPCs from both eras with residual loyalty conflicts
|
||||
|
||||
### Layer 5: Quarter Merge Patterns
|
||||
Same block count, different geometry. The routes the player develops are different. The surveillance chokepoints are different. The safe approach to any given social site varies.
|
||||
|
||||
### Layer 6: Entanglement Pattern
|
||||
Most importantly: *who's in on it is different.* The district's surface can look similar, but the hidden configuration — who knows what, who suspects whom, where the evidence ended up — is the layer the player actually investigates. Two districts with identical exteriors can produce completely different investigative experiences because the entanglement seed is different.
|
||||
|
||||
---
|
||||
|
||||
## Section 6: Preventing Sameyness After 10+ Playthroughs
|
||||
|
||||
The "sameyness problem" is the deepest design challenge. Here's my analysis of what causes it and how each mechanism fights it.
|
||||
|
||||
### Root Cause 1: The Player Has Solved the Puzzle
|
||||
|
||||
If investigation always follows the same sequence — find X, talk to Y, check Z — then playthrough 2 is just playthrough 1 faster. The generator defeats this with:
|
||||
- **Variable evidence placement** — the manifest discrepancy isn't always in the Terminal. The generator places it based on which NPC is entangled with the ring this run.
|
||||
- **Variable investigation paths** — Paths A, B, and C (D-093) are all viable, but which one is *actually open* this run depends on the NPC relationships generated. You can't pre-plan your investigation path.
|
||||
- **Variable NPC knowledge** — which NPC knows what, and when they'll share it, depends on the trust/knowledge graph generated for this run. Your interrogation sequence from last run won't work.
|
||||
|
||||
### Root Cause 2: The Player Knows the Map
|
||||
|
||||
Physical memory of the layout transfers across playthroughs. The sub-chunk quarter system partially defeats this by changing geometry, but it's not enough on its own. The generator must also:
|
||||
- **Vary chokepoint placement** — by varying quarter merge patterns, the location of natural surveillance positions changes per run
|
||||
- **Vary zone boundary placement** — where informal meets formal access creates different barrier topologies
|
||||
- **Vary faction infrastructure** — Commission checkpoints appear in different locations per faction weight seed
|
||||
|
||||
The player should feel *oriented but not certain* on playthrough 2. The district type is familiar (Transit Hub). The specific layout is new.
|
||||
|
||||
### Root Cause 3: The Player Knows the NPCs
|
||||
|
||||
NPC *roles* stay recognizable (dock worker, customs officer, bar regular). But NPC *personalities* — the 10-axis configuration — vary per seed. The dock worker who was the social anchor last time is suspicious and cold this run. The customs officer who was hostile is a potential ally this run. The player recognizes the role. The person is different.
|
||||
|
||||
Combined with invisible locked dialogue (D-062), this means: the player can't replay their successful social script. They have to actually read the new NPCs.
|
||||
|
||||
### Root Cause 4: The Player Knows the Meta-Strategy
|
||||
|
||||
"I know that 20% of NPCs are entangled, so I'll focus on the ones near the obvious crime site." The generator defeats this by:
|
||||
- **Variable entanglement rate** (D-029) — the 20% is an average, not a constant. This run it might be 15%. Or 27%. You can't calibrate.
|
||||
- **Entanglement in unexpected roles** — the generator shouldn't always entangle the obvious suspects. A well-designed generator seeds entanglement toward NPCs whose involvement creates narrative surprise, not pattern-matching.
|
||||
|
||||
### The Comparison Test
|
||||
|
||||
I want to name a specific test this generator must pass: **two players should be able to compare notes and find genuinely different investigation experiences from the same world type.**
|
||||
|
||||
Player A (Smuggler, Seed 42137): "The ring was running through the Gate Cluster customs officer — she was the commission's inside person, but she was also protecting her brother who worked freight. I had to decide whether to expose her or use her."
|
||||
|
||||
Player B (Detective, Seed 81204): "The ring used the maintenance corridor access system — someone had cloned the access tokens. I traced it through the locker room logs to a dock worker who was trying to fund his partner's medical lattice replacement."
|
||||
|
||||
Same district type. Same zoning. Different seeds. Different characters. **Completely different game.**
|
||||
|
||||
If two players can compare notes and their stories are mostly the same — just with different NPC names — the generator has failed.
|
||||
|
||||
---
|
||||
|
||||
## Section 7: What I Need from Other Workshop Participants
|
||||
|
||||
**From Gestalt:** What are the guaranteed gameplay structures every district must contain? (A surveillance chokepoint, a quiet zone, a social hub — confirm the list.) These constraints are my floor. The variation lives above this floor.
|
||||
|
||||
**From Tyre:** How does the seed propagate through the pipeline? Is it a single master seed that derives all sub-seeds deterministically, or does each stage have its own seed parameter? I need to know whether "same seed, different character selection" produces the same world with different lenses, or genuinely different worlds.
|
||||
|
||||
**From Miri:** How large is the cultural ingredients space? (Q-032 specifics.) The variety payoff of the cultural composition layer depends entirely on how many distinct ingredient combinations produce distinguishable district personalities. If there are only 8 valid combinations, we'll see repetition at scale. If there are hundreds, the generator stays fresh.
|
||||
|
||||
**From Araminta:** What visual vocabulary signals distinguish the six flavour categories I proposed? The flavor structure assignment system needs Araminta's palette to produce coherent spaces, not random tile mixtures.
|
||||
|
||||
---
|
||||
|
||||
## Summary: The Variation Axes I'm Proposing
|
||||
|
||||
| Axis | Pipeline Stage | Impact |
|
||||
|---|---|---|
|
||||
| World seed (master) | Game start | Derives all downstream variation |
|
||||
| Character selection | Game start | Fundamentally different information lens |
|
||||
| Tier 1 module pool draw | Game start | Which conspiracies are active |
|
||||
| Cultural ingredient composition | Geography + Economic | District personality and flavor |
|
||||
| Faction power gradient | Economic/Infrastructure | Access topology, NPC power dynamics |
|
||||
| Economic tier | Economic | Building scale, routine stability, social volatility |
|
||||
| Historical event seed | Geography | Physical traces, long-memory NPCs |
|
||||
| NPC 10-axis generation | Chunk fill | Who these people actually *are* |
|
||||
| Quarter merge pattern | Block generation | Physical layout, sightlines, routes |
|
||||
| Entanglement assignment | Chunk fill | Who's actually involved |
|
||||
| Triangle configuration | Chunk fill | Social investigation structure |
|
||||
| Evidence placement | Chunk fill | Where investigation starts |
|
||||
| NPC tolerance thresholds (per seed) | Chunk fill | Social calculus varies per run |
|
||||
|
||||
**Bottom line:** The generator doesn't produce 300 worlds. It produces 300 * (character options) * (cultural ingredient combinations) * (seed entropy) distinct game experiences. At 300 worlds, two playable characters, and a cultural space with even 20 distinct compositions, you're looking at 12,000 meaningfully distinct games before you factor in seed variation. That's the promise. The architecture must deliver it.
|
||||
|
||||
The replayability doesn't come from *more content*. It comes from systems that produce *different configurations of the same content*.
|
||||
@@ -0,0 +1,382 @@
|
||||
# Generator Architecture Workshop — Round 2: Nigel (Replayability & Procedural Generation)
|
||||
|
||||
**Date:** 2026-02-27
|
||||
**Role:** Replayability Advocate
|
||||
**Task:** Expand replayability analysis beyond investigation. Insignificant worlds. Non-urban terrain. Updated variation axes. Reconcile with Araminta's taxonomy. Address Miri's response on cultural space size.
|
||||
|
||||
---
|
||||
|
||||
## Opening: The Lead Directive Changed Everything (In The Best Way)
|
||||
|
||||
The lead's Round 2 brief reframes the entire project. I need to say this clearly before anything else: **"this is not a detective game"** is the most important design principle the lead has stated in this workshop. It's also, I now realize, the thing my Round 1 missed.
|
||||
|
||||
I spent Round 1 analyzing replayability through an investigation lens. Who's entangled. Where the evidence is. Which investigation path is open. All correct — but partial. The generator must support playthroughs where investigation is *background noise*, not the foreground. A tycoon playthrough where the ring is running but the player is building a trading empire and barely notices. A dating sim playthrough where the player is so invested in three NPC relationships that the conspiracy is just context. A political drama playthrough where the player is working factions against each other and the murder investigation is a tool, not a goal.
|
||||
|
||||
AND — this is the part that really expands the design space — the generator must support worlds where NONE of that drama is the foreground, because the world is a backwater. Nothing happens. The transit stop where the tram runs, the fields grow, the fish are caught, and that's the whole story.
|
||||
|
||||
That spectrum — from backwater to epicenter — is itself the replayability lever I missed. Let me rebuild the analysis from scratch.
|
||||
|
||||
---
|
||||
|
||||
## Section 1: Replayability for Non-Investigation Playstyles
|
||||
|
||||
### 1.1 What Replayability Means in a Tycoon Playthrough
|
||||
|
||||
A tycoon player is building economic power. Trading, negotiating, investing, building relationships with the people who control resources. Their investigation is economic: where is value being created or destroyed? Who controls the flow? Where are the arbitrage opportunities?
|
||||
|
||||
**What varies per seed that matters to this player:**
|
||||
|
||||
- **Economic pressure combination** — Miri's D, E parameters (tight-margin, debt-trap, status-competition, survival-gap, opportunity-disparity, prohibition-economy, generational-extraction). These determine WHERE value is being suppressed or diverted. A prohibition-economy world has grey-market premium prices. A debt-trap world has desperate sellers. A status-competition world has conspicuous consumption opportunities. Different economic pressure = different tycoon game.
|
||||
|
||||
- **Faction presence at the district level** — Commission-heavy districts mean higher formal costs (inspections, tariffs, registered goods only). Independent or Syndic-controlled districts mean informal networks that can be exploited but that carry their own risks. The tycoon's first strategic decision — where to operate — is made from the faction presence configuration of the seed.
|
||||
|
||||
- **Which trade routes exist** — infrastructure placement determines which systems are connected, how frequently, and with what bottlenecks. The transit platform that's bar-side (D-093/D-095) means workers arrive before they go to the terminal. That's a captive audience. The tycoon player reads that as: this is where to put the vendor, not over by the gate cluster.
|
||||
|
||||
- **Which NPCs are economically positioned to be useful** — The 10-axis NPC generation produces different economic agents. The dock worker who's 'content' and 'loyal' in one seed is unreachable. In another seed, a dock worker with 'tight-margin pressure' and 'unfulfilled want' is a natural business partner. Same role, different strategic relationship.
|
||||
|
||||
- **Grey economy as a business** — the smuggling ring isn't always the conspiracy the player is investigating. Sometimes it's a business opportunity. Whether the player can participate in, disrupt, or take over a portion of the grey economy depends on their social position AND the ring's structure this seed. The tycoon player might spend three hours negotiating their way into a cut of the manifest discrepancy operation without ever caring about what's being moved.
|
||||
|
||||
**The replayability EXPLODES here when you realize**: a tycoon player and a detective player in the same seed experience the same economic facts of the world through completely different frames. The ring's manifest discrepancies are the detective's evidence and the tycoon's opportunity. SAME GENERATOR OUTPUT. DIFFERENT GAME.
|
||||
|
||||
### 1.2 What Replayability Means in a Dating Sim Playthrough
|
||||
|
||||
A relationship-focused player is building social depth with specific NPCs. Trust, reciprocity, shared history, revelation of secrets. Their investigation is emotional: who is this person? What do they want? What are they hiding that explains why they act this way?
|
||||
|
||||
**What varies per seed that matters to this player:**
|
||||
|
||||
- **Cultural trust-building mechanism** — Miri nailed this. A Frost/Salt culture (patient, transactional, privacy-first) requires entirely different social mechanics than a Tide/Dust culture (expressive, communal, public-demonstration trust). The dating sim player in a Frost-dominant world must invest TIME. The same player in a Tide-dominant world must make PUBLIC GESTURES. Same player intent, completely different strategy.
|
||||
|
||||
- **NPC personality within role** — The dock worker who's the player's primary relationship target is generated fresh each seed. Different Want axis, different Tolerance threshold, different Personality traits. The player can't replay their successful social script because the person is different. The relationship unfolds differently because the same stimuli hit a different emotional profile.
|
||||
|
||||
- **Which NPCs are emotionally available** — The entanglement pattern (20% conspiracy-entangled) affects which NPCs have divided loyalties, secrets from the player, or situational unavailability. In one seed, the bar regular is completely unentangled — she's just a person you meet, and the relationship unfolds with no competing pressure. In another seed, she's the handler for the ring, and her emotional unavailability is a plot point whether or not the player ever discovers why.
|
||||
|
||||
- **Walk-away tolerance varies per seed** — D-064. The social consequences of each interaction are different per run. The player can't memorize "it's safe to push this hard." Each relationship has its own physics.
|
||||
|
||||
- **Relationship web configuration** — D-029 specifies 50% mundane triangles. In the dating sim, THOSE ARE THE GAME. Workplace rivalries, romantic tensions, family disputes — these are the social fabric. The configuration of who's in conflict with whom varies per seed, which means the social politics of becoming close to one person (and the implied distance from others) differs per run.
|
||||
|
||||
**The second playthrough reveal**: on playthrough 2, the player finds THE FRIEND from playthrough 1 is still there (same template, different NPC fill). But now they've been through the relationship arc and know how it ends. The question is: does this new version end the same way? Sometimes yes, sometimes no. The NPC's different trait profile produces different choice points. And it nails replayability without us engineering it.
|
||||
|
||||
### 1.3 What Replayability Means in a Political Drama Playthrough
|
||||
|
||||
A faction-politics player is building institutional power. Aligning themselves with some interests against others, using information asymmetry as a political weapon, positioning themselves in the power structure.
|
||||
|
||||
**What varies per seed that matters to this player:**
|
||||
|
||||
- **Faction power gradient** — which faction is ascending, which is declining, which is under pressure. This changes which alliances are worth building. A Commission-ascendant world rewards institutional proximity. A Syndic-dominant world rewards corporate relationships. The political drama player reads the faction presence parameters as a power map and builds strategy from there.
|
||||
|
||||
- **Which NPCs are the structural nodes of institutional power** — The generator places SYSTEM and HANDLER NPC patterns per Miri's pattern distribution. Where those institutional pillars are, and who fills them, varies per seed. The player can't assume the Commission inspector is corruptible — this one might be Jade-cultural (competence-trust, honor-aware) and completely immune to the approach that worked last time.
|
||||
|
||||
- **Which triangles are hot** — Active social conflicts at the institutional level (the operations manager vs. the senior freight handler vs. the Commission inspector in D-093's gate cluster) vary in their intensity and direction per seed. In one seed, the operations manager is the person to cultivate. In another, the freight handler has leverage nobody's using yet. The political drama player has to read the room afresh each run.
|
||||
|
||||
- **Historical political events** — Miri's institutional incursion events (Commission crackdown, Syndic restructuring) produce political contexts with different winners and losers. The player enters a district with a 10-year-old political scar — who benefited from the last power shift, and can they be reached? Different history = different political game.
|
||||
|
||||
- **What information asymmetry looks like at the political level** — the player might know things the Commission doesn't (from their smuggler contacts), or know things the Syndic doesn't (from their investigation access). What strategic intelligence is available, and who can use it, varies per seed.
|
||||
|
||||
---
|
||||
|
||||
## Section 2: Insignificant Worlds as a Replayability Lever
|
||||
|
||||
The lead is right, and I should have seen this. Let me name the thing properly.
|
||||
|
||||
**The spectrum from backwater to epicenter is a replayability lever.** Not just because some worlds are boring and some are exciting — but because the CONTRAST between them is load-bearing for the player's emotional experience.
|
||||
|
||||
### 2.1 What a Backwater Is, Specifically
|
||||
|
||||
A backwater world has:
|
||||
- Low drama density (one Tier 1 module at most, possibly zero)
|
||||
- Stable social fabric (low economic pressure, high community coherence)
|
||||
- High mundane triangle percentage (from D-029's 50% — but in a backwater, this IS the whole social world)
|
||||
- Low faction contest (one faction controls it comfortably, no power vacuum)
|
||||
- Slow trust-building (because nothing is urgent)
|
||||
- Physical space that's spread out and unhurried
|
||||
|
||||
The investigation vector still exists — people still have secrets, triangles still have pressure — but it's domestic drama, not conspiracy. The farmer whose crop records show something unusual. The fishing cooperative that has an internal dispute over dock rights. The community elder whose relationships are more complicated than they appear.
|
||||
|
||||
**This is a valid, complete playthrough.** Not every game needs a smuggling ring. The backwater is a setting where the game's core mechanic — asymmetric information, you only know what your character knows, other people lie and reveal — plays out at a human scale. The stakes are lower. The meaning is different.
|
||||
|
||||
### 2.2 How Backwaters Contribute to Replayability
|
||||
|
||||
**Contrast effect.** A player who spent two sessions in a logistics hub and then drops into a peaceful farming settlement experiences the farming settlement as RELIEF. The pace change is itself emotional content. Then they leave the farm and go somewhere hot again, and the contrast cuts both ways.
|
||||
|
||||
**Pacing tool.** The Rimworld-style storyteller (D-005) can USE the backwater as breathing room. The storyteller paces events for dramatic tension — a sequence of high-intensity worlds exhausts the player. A backwater in the middle of a run gives the game room to breathe. The storyteller can TIME the backwater's calm before deploying the next disruption.
|
||||
|
||||
**The "nothing happened here — yet" effect.** On playthrough 1, the backwater is peaceful. On playthrough 2 with a different seed, maybe a Tier 1 module fires in the backwater. The player who passed through it quietly now finds it at the center of something. The world they dismissed is now unrecognizable. The replayability here is: the SAME WORLD TYPE can be a backwater in one seed and a flashpoint in another.
|
||||
|
||||
**False backwaters.** A world that APPEARS to be a backwater but is actually a critical logistical node for a ring operating between systems. The investigation player who investigates finds this. The tycoon player who passes through without looking finds nothing. Same generator output. The backwater is true for one player and false for another.
|
||||
|
||||
### 2.3 Generator Requirements for Backwater Worlds
|
||||
|
||||
The generator must be able to produce worlds that are GENUINELY unremarkable, not just understated-dramatic. This means:
|
||||
|
||||
- **Low Tier 1 module density** at world generation time — sometimes zero modules active. The backwater should feel like a break from conspiracy, not a conspiracy in disguise.
|
||||
- **High mundane triangle percentage** — the 50% mundane social fabric needs enough authoring to support a playthrough that ONLY engages with it.
|
||||
- **Stable NPC schedules** — backwater NPCs don't have disrupted routines. Their patterns are consistent. Consistency is itself a signal: this place isn't under pressure.
|
||||
- **Spatial spaciousness** — low fill density (Araminta's 4-8 quarters per block), outdoor spaces, natural light if planet-side. The physical space should feel unurgent.
|
||||
- **Low access tier tension** — not every door is locked. Not every zone has a surveillance camera. Backwaters have OPEN space that the player navigates freely.
|
||||
|
||||
**Important rule for backwaters:** the mundane triangle content must be authored to STAND ALONE as a worthwhile playthrough. Not as a stripped-down version of conspiracy content — as its own thing. A domestic drama in a farming settlement has its own texture, its own emotional stakes, its own satisfactions. If backwaters only exist as contrast for "real" content, players will sense it.
|
||||
|
||||
---
|
||||
|
||||
## Section 3: Non-Urban Terrain — Farmland, Wilderness, Ocean
|
||||
|
||||
### 3.1 Why Non-Urban Terrain Explodes Replayability
|
||||
|
||||
Non-urban terrain is the generator's highest-leverage unexplored axis from Round 1. I didn't think about it at all. The transit hub is the reference case — but it's ONE setting type, and the variety within it is constrained by its industrial character. Non-urban terrain opens completely different variation axes.
|
||||
|
||||
The key insight: **non-urban spaces have different relationship to time and rhythm.** Urban spaces (stations, cities, orbital installations) run on artificial clocks — shift work, tram schedules, institutional hours. Non-urban spaces run on natural cycles — harvest, tide, weather, season. That fundamental difference in temporal rhythm changes the social fabric, the investigation texture, and the playthrough experience.
|
||||
|
||||
### 3.2 Farmland
|
||||
|
||||
**What's different about a farming settlement:**
|
||||
|
||||
- **Seasonal rhythm as primary clock** — NPC schedules follow planting/growing/harvest cycles, not shift work. The detective who arrives during harvest is in a different social situation than the detective who arrives during winter. The community is together during harvest, dispersed during winter. This isn't just flavor — it changes who's accessible when.
|
||||
|
||||
- **Space is abundant but identity-dense** — physical space means less here. Which field belongs to whom, which water rights are contested, which crop variety was brought from the old world — these are the meaningful spatial facts. The investigation archaeology is land records, not surveillance camera angles.
|
||||
|
||||
- **Investigation vector is entirely different** — manifest discrepancies are cargo. Agricultural discrepancies are yield records, land claims, water access, seed variety. The grey economy is diverted agricultural produce, black-market seeds, borrowed equipment that never came back. Same underlying mechanic (asymmetric information, something doesn't add up), different domain.
|
||||
|
||||
- **Social dynamics: community memory is long** — farming settlements have generational memory. A Stone-dominant heritage culture (enduring, traditional, land-connected) in a mature drift stage means NPCs know who everyone's grandparents were. This is a replayability axis because which families have unresolved history varies per seed, but the mechanism of family-history-as-pressure is consistent.
|
||||
|
||||
- **Weather as a direct gameplay element** — Velen's fog (D-050) degrades vision equally, but on a farming planet, weather affects movement, NPC accessibility (farmers don't go to the community hall during a squall), and even evidence (footprints in mud, tracks in snow). Weather is a temporal variation axis that urban stations don't have.
|
||||
|
||||
**What replaying a farming settlement feels like differently from replaying a transit hub:**
|
||||
|
||||
In the transit hub, you're reading the human system — who controls cargo flow, what's being moved invisibly, who's under pressure from which institution. In the farming settlement, you're reading the human relationship to the land — who's losing their land, who's gaining from it, what the community is afraid to say about what happened last winter. Completely different investigative texture. Completely different emotional register. Same generator architecture, different lore inputs.
|
||||
|
||||
### 3.3 Wilderness
|
||||
|
||||
**What's different about a wilderness setting:**
|
||||
|
||||
- **No fixed population** — NPCs are transient. Surveyors, explorers, fugitives, researchers, seasonal workers. Social sites are temporary (waystation, survey camp, emergency shelter). The social world rebuilds every season.
|
||||
|
||||
- **No Meridian infrastructure** — zero surveillance. No coverage, no access tiers enforced by cameras. Physical presence is the only authority. The Commission doesn't matter here except when it arrives. This is the lowest-control, highest-personal-agency environment in the game.
|
||||
|
||||
- **Information travels physically** — no network, no gossip propagation over comm channels. Word of mouth means physical proximity. If you want to know what's happening, you have to be there. Information asymmetry is literal: someone who arrived yesterday knows things the survey camp that's been here six months doesn't.
|
||||
|
||||
- **Spatial dramatics are terrain, not corridors** — cover is natural (rock outcroppings, vegetation, elevation). There are no corridors. The grey economy out here IS the whole economy. Everything that isn't officially registered is contraband by default because there's no infrastructure to register it.
|
||||
|
||||
- **What replays differently:** The wilderness world varies the most between playthroughs because who happens to be there varies enormously. The generator's NPC population here is low and transient — which means the cast changes radically between seeds. The "same world" might have completely different inhabitants on playthrough 2 because the demographic seed produces a different mix of who was surveying this region this year.
|
||||
|
||||
### 3.4 Ocean
|
||||
|
||||
**What's different about an ocean/coastal setting:**
|
||||
|
||||
- **Ports as spatial unit** — not districts in the urban sense, but harbors with social sites organized around maritime function (harbormaster's office, fishing cooperative, chandler's market, sailors' inn). The spatial hierarchy maps differently: the port is a natural chokepoint, like the gate cluster but waterborne.
|
||||
|
||||
- **Tidal rhythms** — NPC schedules follow boat schedules, which follow tides. The player's access to certain NPCs is literally time-gated by natural phenomenon. The detective who arrives at low tide finds the fishers out. High tide, they're in the cooperative settling accounts. This is rhythm-based NPC accessibility that transit hubs can't reproduce.
|
||||
|
||||
- **Ships bring news** — the ocean world's information asymmetry is literal: boats from other systems bring information. Fresh arrivals know things the port doesn't yet. Being on the dock when a specific ship arrives is strategically meaningful in a way that transit hubs mediate through the gate cluster's institutional framework.
|
||||
|
||||
- **Grey economy is structural** — smuggling is older than the Commission here. The spatial infrastructure (hidden coves, pre-registered vessels, cargo manifests that misstate contents) isn't a recent adaptation to Commission oversight — it's how maritime commerce has always worked. The investigation texture is ancient.
|
||||
|
||||
- **DLC expansion as the model** — ocean settings, wilderness settings, specialized orbital installations, specific agricultural planet types — these are exactly the kind of template packs the lead mentioned. The generator pipeline handles them identically. The DLC provides new lore inputs (new heritage roots for maritime cultures, new economic pressure types for seasonal fishing economies, new social site templates for port-specific social dynamics) that the same generator instantiates.
|
||||
|
||||
### 3.5 Variation Axes Unique to Non-Urban Settings
|
||||
|
||||
| Axis | Farmland | Wilderness | Ocean |
|
||||
|---|---|---|---|
|
||||
| Temporal rhythm | Seasonal/agricultural | Project/expedition duration | Tidal/shipping schedule |
|
||||
| Information travel | Community gossip (slow, trust-gated) | Physical proximity only (immediate) | Ships from elsewhere (news arrives in batches) |
|
||||
| Grey economy type | Diverted yield, black-market seeds | Everything informal by default | Historical smuggling infrastructure |
|
||||
| Social site type | Community hall, market day, field shelter | Waystation, survey camp, emergency site | Harbormaster, fishing coop, sailors' inn |
|
||||
| Investigation vector | Land records, water rights, yield discrepancies | "Who was here and why" | Cargo manifests, ship logs, undeclared passengers |
|
||||
| NPC permanence | High (generational community) | Very low (transient) | Mixed (port workers permanent, sailors transient) |
|
||||
| Authority presence | Variable (land ownership contested via property law) | Minimal (physical authority only) | Moderate (harbormaster, maritime law) |
|
||||
|
||||
---
|
||||
|
||||
## Section 4: Insignificant vs. Epicenter — The Spectrum as System
|
||||
|
||||
The lead directive clarifies that "nothing happens here" to "this is the center of everything" is a spectrum the generator must produce intentionally. Let me name the axis formally.
|
||||
|
||||
**Drama Density** is a district/world parameter determined at the Pre-Pipeline stage (above geography). It ranges from:
|
||||
|
||||
- **Zero** — no Tier 1 modules, low economic pressure, stable social fabric. Backwater. Genuine quiet.
|
||||
- **Low** — one Tier 1 module active, domestic-scale pressure. A world with one interesting thing going on.
|
||||
- **Medium** — one Tier 1 module + active mundane triangle pressure + economic tension. The transit hub in steady state.
|
||||
- **High** — multiple Tier 1 modules, contested faction presence, elevated economic pressure. A world in flux.
|
||||
- **Flashpoint** — multiple modules active, faction conflict, historical disruption, elevated entanglement. Rare. Should feel rare.
|
||||
|
||||
The storyteller (D-005, D-023) uses drama density as a pacing parameter. The generator doesn't determine which module fires — the storyteller does that dynamically. But the generator determines the CAPACITY for drama: whether the world has enough social infrastructure to support a high-drama playthrough.
|
||||
|
||||
A backwater with zero Tier 1 module capacity isn't just quiet — it's GUARANTEED quiet. The storyteller cannot fire a major drama module here because the infrastructure doesn't exist. That's not a limitation. That's a promise to the player.
|
||||
|
||||
**Replayability implication of the spectrum:** On playthrough 1, you choose worlds with high drama density (you want action). On playthrough 2, after the emotional intensity of a flashpoint run, you might deliberately choose the backwater — the quiet life, the mundane social fabric, the gentle pace. That's a completely different game from the same generator. The variation isn't in the generated content — it's in WHICH content you choose to engage with.
|
||||
|
||||
---
|
||||
|
||||
## Section 5: Updated Variation Axes (Broadened Lens)
|
||||
|
||||
My Round 1 table of 13 axes was investigation-centric and missed several key dimensions. Here's the revised complete table.
|
||||
|
||||
### Fixed Per Seed (Stable Across Character Selection)
|
||||
|
||||
These axes vary between seeds but remain consistent within a single seed regardless of which character you play. The lead confirms: same seed + different character = same world with different lens.
|
||||
|
||||
| Axis | Pipeline Stage | Impact Across All Playstyles |
|
||||
|---|---|---|
|
||||
| **World seed (master)** | Game start | Derives all downstream variation deterministically |
|
||||
| **Drama density** | Pre-pipeline | Backwater → epicenter spectrum; determines storyteller capacity |
|
||||
| **Cultural ingredient composition** | Pre-pipeline | Social dynamics, trust mechanics, naming, NPC behavior patterns |
|
||||
| **Heritage root blend** | Pre-pipeline | Specific investigation strategy, social approach required |
|
||||
| **Faction power gradient** | Pre-pipeline | Political game: who to align with; tycoon game: who controls commerce; investigation game: whose rules to exploit |
|
||||
| **Economic pressure combination** | Pre-pipeline | Tycoon: investment opportunities; relationship: why NPCs are under stress; political: fault lines to exploit |
|
||||
| **Historical event seed** | Pre-pipeline | Sets the damage and residue that shapes current state |
|
||||
| **Terrain type** | Geography | Farmland/ocean/wilderness/station — changes rhythm, social structure, investigation vector |
|
||||
| **Infrastructure placement** | Infrastructure | Transport nodes, dead zones, Meridian coverage — movement grammar |
|
||||
| **Tier 1 module pool draw** | Game start | Which conspiracies are active (if any); tycoon/dating sim/political players may interact with or ignore these |
|
||||
| **NPC 10-axis generation** | Chunk fill | Who the people actually ARE — personality, want, secret, tolerance, relationships |
|
||||
| **Entanglement assignment** | Chunk fill | Which NPCs are conspiracy-adjacent; not just investigation — affects emotional availability for relationship players too |
|
||||
| **Triangle configuration** | Chunk fill | Social conflict topology — all playstyles navigate this |
|
||||
| **Quarter merge patterns** | Block generation | Physical layout, chokepoints, routes, hidden spaces |
|
||||
| **Evidence/drama node placement** | Chunk fill | Where the interesting things are; varies by playstyle in what counts as "interesting" |
|
||||
| **NPC tolerance thresholds per seed** | Chunk fill | Social consequences of choices — affects every playstyle |
|
||||
|
||||
### Character-Selection Lens (Same World, Different Perception)
|
||||
|
||||
These don't vary what the world IS — they vary what the player perceives and can do.
|
||||
|
||||
| Lens | What It Opens | What It Closes |
|
||||
|---|---|---|
|
||||
| **Smuggler** | Grey economy access, insider relationships, physical routes the system doesn't see | Institutional authority, formal investigation tools, access-tier-gated spaces without workarounds |
|
||||
| **Detective** | Institutional access, analytical lattice capabilities, formal investigation vectors | Grey economy trust, insider relationships, informal social networks |
|
||||
| **Future archetypes** | Each archetype opens different game mechanics and social positions on the same world | Everything outside their social/functional domain |
|
||||
|
||||
The replayability here is the *lens*, not the *world*. The world is the same. What you CAN SEE AND DO in it differs radically by character. This is more replayable than two different worlds, because you're discovering new things in the same place — not just a new place.
|
||||
|
||||
---
|
||||
|
||||
## Section 6: Reconciling With Araminta's Taxonomy
|
||||
|
||||
The flag from Qatux (OQ-8) is correct: my flavor categories and Araminta's empty quarter types use different taxonomies. Here's the reconciliation.
|
||||
|
||||
**The taxonomies are complementary, operating at different levels of abstraction:**
|
||||
|
||||
Araminta's taxonomy answers: **what SHAPE is this empty space, and what are its visual/access properties?**
|
||||
My taxonomy answers: **what CONTENT occupies this space, and what does it communicate about the social/economic state of the district?**
|
||||
|
||||
They compose, they don't conflict.
|
||||
|
||||
### Unified Quarter Fill Model
|
||||
|
||||
At block generation time (Araminta's step 1-3): assign **spatial type** (Araminta's five categories)
|
||||
At chunk fill time: assign **flavor content** (Nigel's four categories), constrained by spatial type AND cultural/economic parameters
|
||||
|
||||
| Spatial Type (Araminta) | Compatible Flavor Content (Nigel) | Cultural/Economic Driver |
|
||||
|---|---|---|
|
||||
| Open plaza | Settlement indicators (seating, shrines, personal gardens) | High drift stage, community bonds present |
|
||||
| Open plaza | Faction presence indicators (Commission kiosk, union notice board) | High faction control |
|
||||
| Service alley | Informal economy indicators (repair shops, vendor carts) | High economic pressure, low faction control |
|
||||
| Service alley | Economic stress indicators (unauthorized storage, abandoned equipment) | Survival-gap or debt-trap economic pressure |
|
||||
| Courtyard/garden | Settlement indicators (container gardens, personal shrines) | High community bonds, mature drift |
|
||||
| Courtyard/garden | Informal economy indicators (informal market, vendor cluster) | Prohibition-economy pressure |
|
||||
| Vehicle/cargo staging | Informal economy indicators (grey-market stalls at the edge) | Mixed formal/informal district |
|
||||
| Vehicle/cargo staging | Faction presence indicators (corporate branded infrastructure) | Syndic dominance |
|
||||
| Structural gap (undeveloped) | Economic stress indicators (shacks, temporary shelters) | Survival-gap pressure, institutional failure |
|
||||
| Structural gap (undeveloped) | *Empty by design* | Intentional restriction, recent disruption, imminent development |
|
||||
|
||||
**Key rule for the generator:** Structural gap + economic stress indicators = a space that LOOKS uninhabited but probably isn't. Shacks in a structural gap are the grey economy's residential infrastructure. This is where the ring members who don't have official housing end up. That's a mechanically important space for investigation players, and a morally textured space for relationship players (these are people living in the cracks).
|
||||
|
||||
**The L-shape notch reconciliation:** Araminta requires that L-shape notches have a visual/functional explanation. My flavor content categories provide exactly those explanations:
|
||||
- Service alley + informal economy = the notch is a grey-market side entrance
|
||||
- Courtyard + settlement indicators = the notch is a communal space that the building grew around
|
||||
- Structural gap + economic stress = the notch is where an addition was planned but never built
|
||||
|
||||
The generator selects notch explanation from flavor content appropriate to the zone's cultural/economic parameters. Same quarter, different explanation. The L-shape means something different in a labor-solidarity district than in a corporate-controlled one.
|
||||
|
||||
---
|
||||
|
||||
## Section 7: Miri's Response on Cultural Space Size — Implications
|
||||
|
||||
Miri's answer: the combination space "comfortably exceeds 300 meaningfully distinct societies." My Round 1 estimate of "20 distinct cultural compositions" was wildly conservative. The actual space is enormous.
|
||||
|
||||
This changes my math significantly — and my risk assessment.
|
||||
|
||||
My Round 1 calculation: 300 worlds × 2 characters × 20 cultural compositions = 12,000 distinct games.
|
||||
|
||||
With Miri's actual space: 300 worlds × (characters) × (many hundreds of meaningful cultural compositions) × (seed entropy) = effectively uncountable.
|
||||
|
||||
**But the question that matters for me isn't the size of the space. It's the resolution.**
|
||||
|
||||
Large combination space doesn't help if:
|
||||
1. Players can't perceive the difference between cultural composition A and composition B
|
||||
2. The mechanical differences are too subtle to feel distinct
|
||||
3. The same cultural composition produces the same gameplay even when the seed changes everything else
|
||||
|
||||
Miri's answer addresses this through the `privacy_level` and `trust.building_rate` levers — cultural parameters that translate directly to gameplay timelines and access mechanics. I want to add one more:
|
||||
|
||||
**Economic pressure combination is the highest-resolution variation lever for player experience.** Here's why:
|
||||
|
||||
Miri shows that Sova's `[tight-margin, prohibition-economy]` produces a specific moral texture — economically rational AND ideologically defensible grey economy. Compare to `[survival-gap, prohibition-economy]` — same contraband type but more desperate, less principled. That difference LANDS in player experience because it changes how NPCs feel about what they're doing. The tycoon player encounters different negotiating partners. The relationship player encounters different emotional registers. The investigator encounters different moral stakes in confrontation.
|
||||
|
||||
**My recommendation:** The economic pressure combination should be the highest-weighted variation axis for player-perceived variety, because it changes the EMOTIONAL TEXTURE of the world, not just its mechanics. Two transit hubs with different economic pressure combinations feel like different kinds of humanity, not just different kinds of logistics.
|
||||
|
||||
Miri's additional question (for me): "Are the cultural variation axes sufficient replayability levers, or do we need additional randomization within a cultural type?"
|
||||
|
||||
My answer: **Sufficient for cross-world variety. Insufficient for within-world replayability.** The cultural parameters are fixed per world. Within-world replayability comes from the seed-driven NPC generation, triangle configuration, and entanglement assignment — which vary WITHIN the cultural parameters. A Frost/Salt/Iron culture with entanglement pattern A is a different game from the same culture with entanglement pattern B, even though both feel "Krenn-like." The within-culture variation is the replayability mechanism. The cultural composition is the setting — it's stable, not randomized per run.
|
||||
|
||||
---
|
||||
|
||||
## Section 8: Seeds Are Solved — What This Means for My Analysis
|
||||
|
||||
The lead confirms: single seed, single world per seed. Same seed + different character = same world with different lens.
|
||||
|
||||
**This is the right call, and here's why from a replayability perspective.**
|
||||
|
||||
The "two keyholes on the same world" principle (D-027) is MORE replayable than two different worlds, because:
|
||||
|
||||
1. **The player can verify what the other character would have seen** — on playthrough 2, the player discovers things they MISSED on playthrough 1. Not just different things — specifically the things that were there all along and invisible to their character. That's a profoundly more satisfying discovery than "this world is different from the last one."
|
||||
|
||||
2. **Character selection becomes a genuine strategic choice** — "I want to see this world through the smuggler's eyes first, then come back as the detective" is a meta-game decision players can make. The world rewards that kind of deliberate multi-playthrough engagement.
|
||||
|
||||
3. **The comparison test works better** — two players comparing notes about the same seed find the world's structure is the same (conspiracy configuration, NPC positions, ring membership) but their experiences are completely different (what they could see, what they could access, what they learned). That's more interesting to compare than two different worlds.
|
||||
|
||||
**What this removes from my variation axes table:** I had "character selection" as a variation axis in Round 1, implying it changes the world. It doesn't — it changes the lens. I've updated the table accordingly (Section 5), treating character selection as a lens layer rather than a generator axis.
|
||||
|
||||
**What this adds:** A responsibility to ensure every generated world is WORTH seeing from multiple character perspectives. A world that only makes sense from the detective's angle fails the generator. This is a validation requirement: can every generated district skeleton produce a valid tycoon game? A valid relationship game? A valid investigation game? If any of those fail, the generator hasn't done its job.
|
||||
|
||||
---
|
||||
|
||||
## Section 9: Quarter Social Variation — Responding to Ozzie's OQ-3
|
||||
|
||||
Ozzie asks whether the flavor structure assignment in unclaimed quarters has **downstream social consequences** — does a garden quarter mean something different about who lives nearby versus a shack quarter?
|
||||
|
||||
My answer: **Yes, and the generator must make this explicit.**
|
||||
|
||||
The current framing (Round 1) treated flavor structures as ambient content — things that fill space and communicate setting. That's necessary but insufficient. Ozzie is right that if quarters are just aesthetic choices, players will see through them on the second station.
|
||||
|
||||
**Proposed mechanism: Flavor type → NPC pattern weight modifier**
|
||||
|
||||
| Flavor type | NPC pattern weight shift |
|
||||
|---|---|
|
||||
| Market stall cluster | +HANDLER (trade coordinator), +CIVILIAN (customers) |
|
||||
| Commission kiosk | +SYSTEM (enforcement), -HANDLER (less informal trade) |
|
||||
| Container garden | +ANCHOR (community pillars), +NOBODY (background domestics) |
|
||||
| Shack cluster | +CATALYST (people under pressure), +REMNANT (people left behind) |
|
||||
| Union hall | +SYSTEM (organized labor), +WITNESS (institutional memory) |
|
||||
| Corporate infrastructure | +SYSTEM (corporate agents), -ANCHOR (less community cohesion) |
|
||||
|
||||
This creates the causal chain Ozzie wants: **physical space is the consequence of social forces, and social forces adjust to the physical space that represents them.** A shack cluster in a structural gap quarter doesn't just LOOK like poverty — it attracts NPC patterns consistent with people living under economic stress. When the player investigates the shack quarter, the NPCs they find have different motivations and different secrets than the NPCs in the garden courtyard two blocks over.
|
||||
|
||||
**This is what makes the quarter system produce social variation, not just visual variation.** And it's where Ozzie's "questions encoded in space" become literal game mechanics.
|
||||
|
||||
---
|
||||
|
||||
## Summary: What Changed from Round 1
|
||||
|
||||
1. **The investigation lens was too narrow.** The generator must produce distinct replayable experiences for tycoon, relationship, political, and investigation playstyles simultaneously. Every generated world must be valid for all of them.
|
||||
|
||||
2. **The backwater is a first-class game state, not a gap in the drama density.** Nothing-happens-here worlds are the contrast that makes everything-happens-here worlds meaningful. The generator must produce them intentionally.
|
||||
|
||||
3. **Non-urban terrain types (farmland, wilderness, ocean) are massive unexplored variation axes.** Different temporal rhythms, different investigation vectors, different social site types, different grey economy structures. DLC template packs are exactly the right expansion model.
|
||||
|
||||
4. **The drama density spectrum** (backwater → epicenter) is a new named generator axis that I missed in Round 1.
|
||||
|
||||
5. **Araminta's spatial taxonomy and my flavor taxonomy are complementary**, operating at different levels. Spatial type is decided at block generation. Flavor content is decided at chunk fill, constrained by spatial type and cultural/economic parameters.
|
||||
|
||||
6. **Cultural space is vast — the critical resolution variable is economic pressure combination**, which produces the highest player-perceived variety by changing the emotional texture of the world.
|
||||
|
||||
7. **Single seed is right.** Same world, different lens. Character selection reveals what was always there.
|
||||
|
||||
8. **Quarter flavor types must produce downstream NPC pattern consequences**, not just visual variety. The shack quarter and the garden quarter attract different NPC patterns because they're the physical expression of different social forces.
|
||||
@@ -0,0 +1,324 @@
|
||||
# Generator Architecture Workshop — Round 3: Nigel (Replayability & Procedural Generation)
|
||||
|
||||
**Date:** 2026-02-27
|
||||
**Role:** Replayability Advocate
|
||||
**Task:** Assassination replayability. Dynamic world modification. Mobile chunks. Playstyle mismatch as discovery mechanic. Reconcile SignificanceTier/ComplexityTier/DramaDensity.
|
||||
|
||||
---
|
||||
|
||||
## Section 1: Assassination Replayability
|
||||
|
||||
### What Makes Assassination Gameplay Replayable
|
||||
|
||||
Assassination is constraint satisfaction under time pressure: reach the target, eliminate, escape unidentified. For this to replay differently, the constraints must be different each run. Specifically: different sightlines, different crowd patterns, different escape routes, different timing windows. Let me name what the generator actually varies.
|
||||
|
||||
### Sightline Geometry Per Seed
|
||||
|
||||
The sub-chunk quarter system produces different physical geometries per seed. Every quarter merge pattern decision propagates to LOS. The same social site template — say, the bar — can appear in four different physical configurations depending on which quarters merged. In one seed, the target's regular table is adjacent to the main entrance, exposed to the door from every approach. In another, the same NPC routine places them in a booth with a single sightline gap, approachable from the service corridor. The generator doesn't know assassins will be using this information. It produces geometry from social and economic parameters. The assassin reads that geometry as approach planning.
|
||||
|
||||
**The generator's guarantee to assassination gameplay:** sightline geometry must differ meaningfully between seeds of the same district type. This is already guaranteed if quarter merge patterns are seeded differently — but it requires that the spatial guarantee archetypes (particularly Traffic Chokepoints and Informal Zones) not always appear in the same relative positions. If the Traffic Chokepoint is always northwest of the Social Hub, every assassination approach maps to the same template.
|
||||
|
||||
**Requirement: archetype placement must vary in angular position across seeds, not just in distance from center.** This is currently unspecified in the generator design. I'm flagging it as a hard replayability requirement for the action-gameplay pillar.
|
||||
|
||||
### Crowd Pattern Variation Per Seed
|
||||
|
||||
NPC schedules are seeded from the 10-axis generation + D-031 day phases. The crowd patterns that provide cover or represent hazard vary per seed in two ways:
|
||||
|
||||
1. **Who is present**: The entanglement configuration determines which NPCs have divided attention, which are focused on their routine, and which are actively surveilling. In one seed, the logistics shift supervisor is entangled and distracted. In another, they're clean and paying full attention to the dock floor.
|
||||
|
||||
2. **When they're present**: Day-phase scheduling produces different density windows. The same space that's crowded enough to provide movement cover during shift transition is sparse and exposed during maintenance hours. The assassination timing window depends on which day-phase alignment the target's routine creates.
|
||||
|
||||
Both vary per seed. The assassin who memorized "the third hour of the evening shift is when the target is isolated" is working with playthrough-specific knowledge that won't transfer.
|
||||
|
||||
### Escape Routes Per Seed
|
||||
|
||||
Escape routes are the reverse of approach routes — they're the spaces that provide cover FROM the chokepoints. Quarter merge patterns determine where service alleys exist, where structural gaps are accessible, which back-facing edges of blocks have maintenance access. The escape geography is the backside of the same quarter system that produces the approach geometry.
|
||||
|
||||
**Structural variety guarantee**: For assassination gameplay to replay, the escape topology must be substantially different between seeds. Not just cosmetically different — the number of viable exits from a given elimination zone must vary (sometimes two exits, sometimes one, sometimes a path that requires prior access arrangement). This creates genuinely different risk profiles per playthrough, not just different aesthetics.
|
||||
|
||||
### Timing Windows Per Seed
|
||||
|
||||
The target's routine is seeded from NPC generation. Same role, different schedule. A senior official who visits the commissary daily in one seed visits weekly in another. The window in which they're accessible in the informal zone (Gestalt's Archetype 2) — the space without institutional coverage — is different per run.
|
||||
|
||||
Combined with the day-phase system (D-031) and the crowd pattern variation above, this means the **timing window arithmetic is unique per seed**. There's no universal "best time to move on this type of target." The assassin has to observe the specific NPC's specific routine in this specific seed.
|
||||
|
||||
### The Grid Breathability Question (OQ-R3-A) Is Critical for Assassination
|
||||
|
||||
Ozzie raises whether the block grid can rotate or breathe — whether streets can curve, whether adjacent districts can have different orientations. For most playstyles, this is primarily an aesthetic concern. For assassination gameplay, it's mechanically load-bearing.
|
||||
|
||||
If the grid is always four rectilinear quadrants with perpendicular streets, an experienced player can overlay a mental template onto any new district and immediately identify likely approach corridors, chokepoints, and escape vectors. Second Station Syndrome for assassination is: "I know where the service corridor will be before I've explored." The grid must be unpredictable enough that physical reconnaissance is required each run — even in familiar district types.
|
||||
|
||||
I'm not the right person to specify HOW the grid breathes (that's Tyre and Araminta). But I need the outcome: **the spatial skeleton of a district must not be predictable from district type alone.** Same district type, significantly different spatial skeleton. The quarter system handles fill variation. The block planning stage must handle skeleton variation.
|
||||
|
||||
---
|
||||
|
||||
## Section 2: Dynamic World Modification as a Replayability Tool
|
||||
|
||||
### Is World Mutation Good? YES.
|
||||
|
||||
A gas explosion changes a district. This is excellent for replayability. Here's why.
|
||||
|
||||
The generator produces a baseline world from a seed. Every run of the same seed starts identical. Replayability within a seed comes from one thing: **playthrough divergence from the baseline**. Destruction events are the highest-leverage divergence mechanism because they change the physical world, not just the social world.
|
||||
|
||||
Two playthroughs of the same seed:
|
||||
- Playthrough 1: The maintenance corridor in block 7 exists. The player uses it as an escape route.
|
||||
- Playthrough 2: A gas explosion (storyteller-triggered, different timing) blocked that corridor six hours before the player arrived. The escape route they planned doesn't exist.
|
||||
|
||||
These are genuinely different games. Not because the seed differed — because the simulation produced different outcomes.
|
||||
|
||||
### The Architectural Foundation Is Already There
|
||||
|
||||
Tyre's Phase 2 architecture already handles this correctly: ChunkData is cached after generation and written to save. A modified chunk (destroyed corridor, collapsed wall, fire-damaged room) is saved as modified ChunkData. The Phase 1 PreparedDistrict doesn't change — the social configuration, NPC rosters, and spatial skeleton remain the seed-derived baseline. Phase 2's tile data diverges from that baseline as events modify it.
|
||||
|
||||
This means destruction events don't require special generator support — they're modifications to existing ChunkData. The generator's job is to produce the *baseline*. The simulation's job is to track modifications. Save/load preserves the current state.
|
||||
|
||||
### Player-Caused Destruction as Permanent Private Knowledge
|
||||
|
||||
When the player blows a hole in a wall, they create an access route that exists nowhere in the generator's output. This is a form of **private geographic knowledge** — the player knows this route exists; most NPCs don't (until the Commission investigates the structural damage).
|
||||
|
||||
This is high-variance replayability because:
|
||||
1. On playthrough 2 (same seed), the hole doesn't exist until the player creates it again — or doesn't
|
||||
2. The decision of WHEN to create the destruction affects downstream events differently each run
|
||||
3. Player-authored geography creates personalized playthrough states that feel earned
|
||||
|
||||
**D-051 principle**: "every placed tile is someone's decision." When the player places destruction, they're authoring their world. The simulation records and respects that.
|
||||
|
||||
### The Storyteller's Destruction Grammar
|
||||
|
||||
The storyteller (D-005, D-023) can USE planned destruction as a narrative instrument. The mechanism:
|
||||
|
||||
1. **Pre-seeded structural vulnerabilities**: The generator seeds certain infrastructure with fragility tags (aging pipes, overloaded power conduits, unstable load-bearing configurations). These are invisible to the player unless discovered through investigation/engineering observation.
|
||||
|
||||
2. **Storyteller activation**: When narrative tension reaches a threshold, the storyteller can "activate" a fragility — not by scripting an explosion, but by seeding the simulation conditions where explosion becomes probable. An aging pressure seal under increased freight load, with a maintenance NPC distracted by a social conflict, becomes a plausible accident.
|
||||
|
||||
3. **Timing for dramatic effect**: The storyteller knows player position, active investigation threads, and dramatic potential. A gas explosion that occurs while the player is in a nearby space creates a "you barely missed it" moment. One that occurs WHILE the player is accessing the maintenance corridor creates maximum tension.
|
||||
|
||||
This is not scripted drama. It's the simulation producing dramatic outcomes from realistic conditions, with the storyteller nudging the probability. The destruction is CAUSED (Ozzie's requirement), not RANDOM.
|
||||
|
||||
### Risk: Destruction Must Remain Extraordinary
|
||||
|
||||
If destruction is too common, it becomes a mechanic rather than an event. The generator's fragility seeding must be sparse. A district where structural failures happen constantly loses the dramatic weight of destruction. The player should experience world modification as RARE and MEMORABLE — each instance a unique playthrough marker.
|
||||
|
||||
**Recommendation**: Fragility tags should be present in <5% of maintenance/infrastructure chunks per district. The storyteller should activate them only when dramatic conditions make the activation feel earned, not as a routine pacing tool.
|
||||
|
||||
---
|
||||
|
||||
## Section 3: Mobile Chunks — Trains, Ships, Traincars
|
||||
|
||||
### Why Mobile Environments Are Maximum Replayability
|
||||
|
||||
I want to make this case strongly before we even get to architecture: mobile environments are some of the highest-variance gameplay spaces the generator can produce, and they don't require the generator to work particularly hard. The variance comes from the SITUATION, not the space.
|
||||
|
||||
A ship voyage or train journey is a social pressure cooker because:
|
||||
1. **Temporal constraint**: The journey ends. Everything must happen before arrival.
|
||||
2. **Social confinement**: These specific NPCs are the whole world for the duration. No walking away, no coming back tomorrow.
|
||||
3. **Information compression**: Normal investigation can be deferred — talk to that NPC tomorrow, check the archive next week. On a vessel, you have the journey and that's it.
|
||||
|
||||
These structural properties produce high replayability without the generator doing anything special. The variation comes from:
|
||||
|
||||
- **Who's on this voyage** (passenger manifest seeding)
|
||||
- **What the passengers know** (entanglement configuration — one seed puts a ring operative on the same ship as the player's investigation target; another doesn't)
|
||||
- **What day-phase the journey occupies** (shared mealtimes, shift changes, the specific windows when certain conversations are possible)
|
||||
- **What external events occur during transit** (weather, delay, emergency — storyteller-seeded)
|
||||
|
||||
### Vessel Architecture — The Instanced District Model
|
||||
|
||||
I want to address OQ-R3-D directly. Rather than pure entity-carried chunks (tiles moving in coordinate space, which Miri flags as architecturally complex), I propose vessels as **instanced districts**:
|
||||
|
||||
**A vessel is a district instance that is:**
|
||||
- Generated at journey-start (Phase 2 runs on booking + departure)
|
||||
- Loaded as a normal district (player enters, chunks generate, NPCs spawn)
|
||||
- Visually situated through client-side animation (windows show terrain passing; the experience of movement is rendered without the coordinate actually changing)
|
||||
- Terminated at arrival (instance unloads, player transfers to destination district)
|
||||
|
||||
**What this gives us:**
|
||||
- Full architectural compatibility with D-094 hierarchy (same chunk/block/district model)
|
||||
- Full NPC simulation (schedules, relationships, knowledge graph — all work identically)
|
||||
- No coordinate-system complexity (tiles don't move)
|
||||
- Visual effect of travel through client rendering (Godot renders a parallax-scrolling background in window tiles)
|
||||
|
||||
**What this requires:**
|
||||
- The vessel template is authored like a D-025 social site — a fixed spatial layout, NPC role slots, triangle configurations
|
||||
- The passenger manifest is seeded at journey-start from the route + available NPC pool at the departure location
|
||||
- The instance has a lifespan (arrival time), which the storyteller can modify (delay, emergency stop, diversion)
|
||||
|
||||
**The temporal constraint as a replayability mechanic**: The player can see the arrival countdown (diegetically: through their neural insert navigation system). They know they have six hours. What they accomplish in those six hours depends on:
|
||||
- Who's aboard (seeded)
|
||||
- Which conversations become possible as trust builds during the journey (relationship mechanics within the instance)
|
||||
- What the storyteller drops into the voyage (external events that create pressure or opportunity)
|
||||
|
||||
Different seed, different passenger manifest, different dramatic possibilities. The same route (Sova → destination) is never the same journey twice.
|
||||
|
||||
### The Dating Sim on the Ship
|
||||
|
||||
I want to call out something specific here because it highlights the non-investigation playstyle potential: **the ship is the premier dating sim environment**.
|
||||
|
||||
In a normal district, relationship-building requires repeated visits over time. The bar exists, the player can go there any evening. The relationship unfolds at the pace of repeated encounters. On a ship, **proximity is enforced**. You share meals. You're in adjacent cabins. You're both stuck here for six hours.
|
||||
|
||||
Relationships that would take a week of deliberate effort in a district form (or break) in a single voyage. The player who wants to understand an NPC deeply has an unparalleled opportunity during transit. And the NPC who would normally take time to warm up may, under the specific social pressure of a confined space, reveal things they wouldn't in a normal encounter.
|
||||
|
||||
This is the "something happens on a ship that wouldn't happen in a bar" quality. The generator produces this not through special content authoring but through the structural situation the vessel instance creates.
|
||||
|
||||
---
|
||||
|
||||
## Section 4: Playstyle Mismatch as a Discovery Mechanic
|
||||
|
||||
### The Mismatch Is Good Design
|
||||
|
||||
I argued in Round 2 that the generator should NOT try to balance all playstyles equally within every district. Round 3 lets me be more specific: **playstyle mismatch is itself meaningful information about the world**.
|
||||
|
||||
When a tycoon player arrives at a farming settlement and finds almost nothing to trade, they've learned something real: this community isn't economically integrated into the wider network. It's self-sufficient, or it's isolated, or it's poor. The absence of tycoon opportunity is a worldbuilding signal, not a generator failure.
|
||||
|
||||
Similarly: an investigation player who arrives in a wealthy resort district and can't find a conspiracy isn't experiencing a failed district — they're experiencing a world where affluence and social control have suppressed the visible signals of crime. The investigation is HARDER, not absent. That difficulty is the discovery.
|
||||
|
||||
### How Players Discover Playstyle Fit
|
||||
|
||||
The player doesn't know in advance which playstyle a world favors. That knowledge is discovered through play — specifically, through **early engagement friction**:
|
||||
|
||||
- Tycoon player arrives at farming settlement, looks for the market, finds it's a seasonal thing happening once a month, not now → discovers this isn't a trading world, it's a community world
|
||||
- Investigation player arrives at resort world, can't find manifest discrepancies, can't find information gaps → discovers the ring here operates differently (social extortion, not cargo smuggling) and requires a completely different investigation approach
|
||||
- Dating sim player arrives at a logistics hub during a busy freight rotation, finds all NPCs too busy and scheduled for casual social engagement → discovers this isn't a leisurely social world, it runs on work discipline
|
||||
|
||||
The discovery is: **what kind of world is this?** That's a meaningful question the generator's outputs answer through gameplay friction, not text.
|
||||
|
||||
### Playstyle Drift as a Play Experience
|
||||
|
||||
A tycoon player who gets drawn into the social drama of a farming settlement because the NPC relationships were genuinely interesting isn't a lost tycoon — they're having an authentic experience. The simulation produced something compelling and they responded to it. Their playstyle DRIFTED.
|
||||
|
||||
This is one of the most valuable things the generator can produce: **the conditions for a player to surprise themselves**. They came for the market, they stayed for the people. That's a story the player will tell. It's emergent from systems that don't know what the player intended.
|
||||
|
||||
**Generator requirement**: The only hard requirement is that every Full-complexity district offers ENTRY POINTS for all playstyles via Gestalt's 7 spatial archetypes. Not equal depth — entry points. The tycoon player who drifted into dating sim mode can drift back if they choose. The world doesn't lock them in.
|
||||
|
||||
The Moderate and Minimal complexity districts (non-urban, backwater, passage nodes) don't need to guarantee all 7 archetypes. They offer what they offer. The player learns to read complexity tier through experience — another discovery mechanic.
|
||||
|
||||
### The "Best Place for X" Meta-Game
|
||||
|
||||
Across 300 worlds, players will develop opinions about which world types are best for which playstyle. The farming settlement is the place for relationships. The logistics hub is the place for investigation. The capital is the place for political drama.
|
||||
|
||||
This meta-knowledge is GOOD. It gives experienced players meaningful choices about where to go. It's the exploration game — not "what's in this world" (you'll find that out) but "what do I want this play session to be about?" Different players going to different worlds for different reasons is the game working correctly.
|
||||
|
||||
---
|
||||
|
||||
## Section 5: Reconciling SignificanceTier / ComplexityTier / DramaDensity
|
||||
|
||||
Qatux correctly flags these three as overlapping concepts that need reconciliation before the Pre-Pipeline stage can be formally specified. Here is my proposed unified model.
|
||||
|
||||
### What Each Concept Is Actually Measuring
|
||||
|
||||
**Gestalt's SignificanceTier** (Center-stage / Regional / Backwater / Waypoint / Insignificant):
|
||||
- Measures *relative network importance* — connectivity, political weight, historical significance
|
||||
- This is a STRUCTURAL parameter: how does this world relate to others?
|
||||
- Set at system generation, doesn't change during a playthrough
|
||||
|
||||
**Tyre's ComplexityTier** (Full / Moderate / Minimal / Empty):
|
||||
- Measures *generator output depth* — how many guarantees apply? How many templates get instantiated?
|
||||
- This is a CONTENT DEPTH parameter: how much does the generator produce here?
|
||||
- Set during Phase 1, doesn't change during a playthrough
|
||||
|
||||
**Nigel's DramaDensity** (Zero / Low / Medium / High / Flashpoint):
|
||||
- Measures *active narrative intensity* — how many Tier 1 modules are active right now?
|
||||
- This is a DYNAMIC parameter: it can change during play as the storyteller activates modules
|
||||
- Set initially by the generator; the storyteller has write access
|
||||
|
||||
### Why Two of These Can Collapse
|
||||
|
||||
SignificanceTier and ComplexityTier are correlated but not identical — and when they're not identical, the non-obvious case is the most interesting one.
|
||||
|
||||
A Waypoint (low network significance) almost always gets Minimal or Empty complexity. That's fine — a transit node with nothing permanent is correctly sparse.
|
||||
|
||||
But a Backwater (low network significance) can be EITHER Full complexity (a dense, rich, human community that just doesn't matter to the wider galaxy) OR Minimal complexity (genuinely sparse, few inhabitants, passing through). The difference between these two backwater types is enormous for gameplay — one produces a dating sim/political drama rich environment; the other is genuinely empty.
|
||||
|
||||
**The key insight: network significance and interior richness are independent.** A Backwater can have Full interior complexity. An Epicenter can be surprisingly sparse if it's primarily a transit hub rather than a residential community.
|
||||
|
||||
Therefore, we need BOTH axes — but they can be defined more cleanly:
|
||||
|
||||
### Proposed Two-Parameter Model
|
||||
|
||||
**Parameter 1: WorldTier** (static, set at system generation, captures network significance)
|
||||
- `Epicenter` — maximum connectivity, major faction presence, historically significant
|
||||
- `Regional` — meaningful connectivity, notable faction presence, relevant to the wider network
|
||||
- `Passage` — transit-relevant primarily, light faction footprint, functionally important but not socially deep
|
||||
- `Backwater` — low external connectivity, weak external faction presence, self-contained
|
||||
- `Waypoint` — minimal or no social complexity, geography/transit function only
|
||||
|
||||
**Parameter 2: ComplexityTier** (static, set at Phase 1, captures generator output depth)
|
||||
- `Full` — all 7 spatial archetypes guaranteed, complete NPC population, all four playstyle entry points
|
||||
- `Moderate` — subset of archetypes (4+), meaningful NPC population, 2-3 playstyle entry points
|
||||
- `Minimal` — 1-2 archetypes, sparse NPC population, 1 primary playstyle
|
||||
- `Empty` — geography only, no permanent social structure, no NPC simulation
|
||||
|
||||
These replace all three competing concepts with two orthogonal parameters. WorldTier answers "where does this world sit in the network?" ComplexityTier answers "how deep is the generator output?"
|
||||
|
||||
**The Backwater case resolved:**
|
||||
- `Backwater + Full` = a dense, isolated community rich with human drama. The information asymmetry challenge inverts (Miri's insight): you can't be anonymous, everyone knows your name within hours, the conspiracy is intimate. This is a completely different game from a logistics hub.
|
||||
- `Backwater + Minimal` = a genuinely sparse settlement, a homestead, a research outpost. A few NPCs, minimal social fabric, brief engagement.
|
||||
|
||||
**The Epicenter case:**
|
||||
- `Epicenter + Full` = The center of everything, complex, contested, rich with all four playstyle opportunities
|
||||
- `Epicenter + Moderate` = A junction node — important to the network, but the social life is shallow (high transit, low permanence). The tycoon game is excellent here; the dating sim is difficult.
|
||||
|
||||
### Parameter 3: DramaDensity (Dynamic, Storyteller-Controlled)
|
||||
|
||||
DramaDensity is fundamentally different from the first two parameters because it changes during play. It can't be collapsed into a static parameter.
|
||||
|
||||
**DramaDensity**: Zero / Low / Medium / High / Flashpoint
|
||||
- Set initially by the generator from the seed (how many Tier 1 modules are positioned to be active in this world)
|
||||
- WorldTier constrains the achievable range (a Waypoint can't sustain High; a Waypoint + Empty can't sustain anything above Zero)
|
||||
- The storyteller has write access and can elevate or suppress DramaDensity based on pacing needs
|
||||
- **The false backwater mechanism**: A world that starts at Zero DramaDensity can be elevated to Medium by the storyteller when the player's actions create the conditions for drama to become plausible. The generator seeded the structural capacity; the storyteller activates it.
|
||||
|
||||
### Unified Model Summary
|
||||
|
||||
| Concept | Parameter | Type | Set When | Who Owns It |
|
||||
|---|---|---|---|---|
|
||||
| Network importance / significance | `WorldTier` | Static | System generation | Generator |
|
||||
| Generator output depth | `ComplexityTier` | Static | Phase 1 | Generator |
|
||||
| Active narrative intensity | `DramaDensity` | Dynamic | Phase 1 initial; storyteller modifies | Generator initial; storyteller ongoing |
|
||||
|
||||
**The DistrictSkeleton** should carry all three: `world_tier: WorldTier`, `complexity_tier: ComplexityTier`, `drama_density: DramaDensity`. The first two are immutable after Phase 1. The third is a live field the storyteller system updates.
|
||||
|
||||
**Constraint relationship**: `WorldTier` constrains the maximum achievable `ComplexityTier` (an Epicenter can be Full; a Waypoint cannot). `ComplexityTier` constrains the maximum achievable `DramaDensity` (Full complexity can sustain Flashpoint; Empty cannot sustain above Zero).
|
||||
|
||||
### Why This Matters for Replayability
|
||||
|
||||
The three-parameter model enables a player-facing experience where worlds feel categorically different, not just quantitatively different. A Backwater/Full/Zero world is a genuinely different type of experience from a Regional/Full/High world — not just the same template with more or fewer drama events.
|
||||
|
||||
The DramaDensity being dynamic means: the world the player visits on playthrough 1 may be a different drama density on playthrough 2 (either because the storyteller applies different pacing, or because the player's actions in this playthrough create different preconditions for drama activation). The same World/Complexity configuration produces different lived experiences across playthroughs via the dynamic drama layer.
|
||||
|
||||
---
|
||||
|
||||
## Section 6: Cross-Cutting Observations for Round 3 Convergence
|
||||
|
||||
### On OQ-R3-B (Triangle Purpose Taxonomy)
|
||||
|
||||
Gestalt proposes `triangle_purpose: TrianglePurpose` (investigation/economic/political/social) on triangle nodes. From a replayability perspective: YES, this is essential and low-complexity to add.
|
||||
|
||||
If all triangles activate regardless of playstyle context, the player constantly has access to all dramatic possibilities. That reduces tension. A tycoon player who doesn't care about the conspiracy shouldn't have the conspiracy's triangles pressing on them unless they engage. Triangle purpose tags let the storyteller activate relevant triangles based on what the player is actually doing — not scripting the drama, but surfacing the drama that's relevant to the player's current engagement pattern.
|
||||
|
||||
### On OQ-R3-C (Maritime/Wilderness Informal Zone)
|
||||
|
||||
For wilderness: the informal zone is anywhere away from the camp/waystation. The wilderness itself is the informal zone — the entire geography is low-coverage, low-surveillance, low-NPC-density. There's no "finding the maintenance corridor" equivalent; the wilderness is all maintenance corridor.
|
||||
|
||||
For maritime: hidden coves, sea caves, below-deck storage compartments, vessels anchored in fog. The terrain provides the informal zone naturally.
|
||||
|
||||
Gestalt's `terrain_informal_zone` concept is correct. The generator doesn't need to deliberately place an informal zone in non-urban settings — the terrain type produces it automatically. The generator just needs to know that the wilderness biome flag satisfies the informal zone guarantee without explicit placement.
|
||||
|
||||
### On the Grid Breathability Question (OQ-R3-A)
|
||||
|
||||
I've argued this is load-bearing for action gameplay. My replayability position: the player must be required to do physical reconnaissance on every new location, regardless of how many similar locations they've visited. If the grid is predictable, reconnaissance becomes template-matching and stops being exploration.
|
||||
|
||||
I can't specify the technical solution (that's Tyre and Araminta). But I can specify the replayability requirement: **from a player-facing perspective, the physical skeleton of a Full-complexity district must not be recognizable as the same class of district until the player has explored it**. Whether that's achieved through grid rotation, non-rectilinear blocks, visual technique, or some combination — the output must defeat structural pattern-matching.
|
||||
|
||||
---
|
||||
|
||||
## Summary: Round 3 Positions
|
||||
|
||||
1. **Assassination replayability**: sightline variety (quarter geometry), crowd pattern variation (seeded schedules), escape topology variation (quarter backside), timing window variation (NPC routine seeding). Hard requirement: archetype placement must vary in ANGULAR position across seeds, not just distance from center. Grid breathability is mechanically load-bearing, not just aesthetic.
|
||||
|
||||
2. **Dynamic world modification**: excellent for replayability. Baseline → playthrough divergence is the key mechanism. Storyteller-activated fragilities produce CAUSED destruction (Ozzie's requirement). Player-caused destruction creates private geographic knowledge. ChunkData mutation already supported by Tyre's Phase 2 architecture.
|
||||
|
||||
3. **Mobile chunks**: Instanced district model (vessels are district instances with a lifespan, not entity-carried tiles). Passenger manifest seeded at journey-start. The vessel is the premier environment for temporal-constraint and dating-sim gameplay. The window/visual movement is a client rendering concern, not a simulation concern.
|
||||
|
||||
4. **Playstyle mismatch is good**: it's discovery, not failure. Friction reveals what kind of world this is. The only hard requirement is entry points (7 archetypes) for Full-complexity; not equal depth. Playstyle drift (following what's compelling regardless of intent) is the best outcome the generator can produce.
|
||||
|
||||
5. **Unified three-parameter model**: `WorldTier` (static, network significance), `ComplexityTier` (static, generator output depth), `DramaDensity` (dynamic, storyteller-modified). Collapses three competing concepts into two static + one dynamic. WorldTier constrains ComplexityTier; ComplexityTier constrains DramaDensity ceiling. The DistrictSkeleton carries all three.
|
||||
@@ -0,0 +1,369 @@
|
||||
# Generator Architecture Workshop — Round 4: Nigel (Replayability & Procedural Generation)
|
||||
|
||||
**Date:** 2026-02-27
|
||||
**Role:** Replayability Advocate
|
||||
**Task:** OQ-R4-A (MobileChunk replayability), OQ-R4-E (One NPC / Five Lenses), OQ-R4-F (soft re-generation coherence), final sign-off on 12 D-ready items.
|
||||
|
||||
---
|
||||
|
||||
## OQ-R4-A: Vessel Architecture — Accepting MobileChunk, Specifying Replayability Requirements
|
||||
|
||||
### Accepting the Architecture; Moving Forward
|
||||
|
||||
The lead has settled vessel architecture as entity-carried `MobileChunk`. My instanced district model is retired. I want to briefly record why I don't fight this: the persistent world-entity model offers one replayability property my model couldn't — **vessels have a history**. A ship that has docked at fifteen ports, been used to smuggle contraband twice, and hosted an assassination attempt on voyage seven is a RICHER object than a vessel that only exists during voyages. The entity-carried model enables vessels to accumulate simulation state across time. That is, on reflection, better for the game I want to make.
|
||||
|
||||
What follows is my full specification of what the MobileChunk model needs from a replayability perspective.
|
||||
|
||||
---
|
||||
|
||||
### The Stage and the Cast
|
||||
|
||||
The core conceptual frame for vessel replayability: **the vessel is a stage; the manifest is the cast**.
|
||||
|
||||
The stage (ChunkData interior) stays the same across voyages. The same ship has the same corridors, the same cabins, the same social spaces. This is correct and good — familiarity with the ship is earned knowledge that players can exploit on subsequent voyages. A player who has ridden the Tide-loop cargo hauler before knows where the service access is, knows which cabin is near the galley, knows the captain's usual table. That knowledge is capital they've built. The replayability isn't in rediscovering the layout; it's in who's aboard and what they know.
|
||||
|
||||
The cast (passenger manifest) changes every voyage. The same ship, the same route, but entirely different dramatic potential.
|
||||
|
||||
---
|
||||
|
||||
### Manifest Seeding Strategy
|
||||
|
||||
Every voyage produces a new passenger manifest. The seed formula:
|
||||
|
||||
```
|
||||
voyage_manifest_seed = derive_seed(master_seed, "vessel_manifest", vessel_entity_id, voyage_index)
|
||||
```
|
||||
|
||||
`voyage_index` increments on every departure, not on every calendar day. A ship that makes three voyages on the same in-game day has three distinct manifests.
|
||||
|
||||
**Manifest composition:**
|
||||
|
||||
The manifest has two zones:
|
||||
- **Fixed slots** — crew. Always present, same personnel per voyage. The cook is the cook. The first mate is the first mate. These NPCs are generated from the vessel's generation seed (not the voyage seed) and persist across all voyages. They develop relationships with repeat passengers over time.
|
||||
- **Variable slots** — passengers. Drawn fresh per voyage from the eligible NPC pool at the departure location at the time of departure.
|
||||
|
||||
**Passenger eligibility criteria** (evaluated at journey-start):
|
||||
1. NPC is present at the departure location at departure time
|
||||
2. NPC has a plausible purpose for this route (home port on the other end, active relationship at the destination, commercial reason, assigned by faction, fleeing a situation)
|
||||
3. NPC satisfies berth class (if the ship has class-stratified cabins, as Miri's `BoundedLinear` model specifies)
|
||||
4. NPC is not in a simulation state that prevents travel (hospitalized, under house arrest, actively mid-scene)
|
||||
|
||||
From the eligible pool, passengers are selected by `voyage_manifest_seed`. This means:
|
||||
|
||||
**Voyage A and Voyage B of the same ship, same route, drawn from overlapping NPC pools** — different manifests. The eligible pool at departure time changes between voyages because the simulation has run. NPCs complete trips, return home, get tied up elsewhere. The manifest isn't just a random draw from a static pool; it's a draw from whatever pool actually exists at departure, seeded deterministically.
|
||||
|
||||
---
|
||||
|
||||
### What Makes Voyage 5 Different from Voyage 1?
|
||||
|
||||
Five independent sources of variation across voyages of the same ship:
|
||||
|
||||
**1. Manifest composition**
|
||||
The passengers change every voyage. The entanglement configuration among those passengers — who's connected to whom, who's being watched, who's carrying knowledge the player wants — is seeded from the voyage manifest seed. Voyage 1: a smuggling ring operative sharing the ship with their handler, both unaware the player is investigating the same ring. Voyage 5: entirely different cast, different dramatic potential.
|
||||
|
||||
**2. NPC knowledge state drift**
|
||||
Even repeat passengers (NPCs who've traveled this route before) have different knowledge states on voyage 5 than voyage 1. The simulation has run. A NPC who on voyage 1 was unaware of a conspiracy is on voyage 5 the primary witness to it. Same NPC, same 10-axis generation, different information inventory because the world has changed.
|
||||
|
||||
**3. Storyteller state**
|
||||
DramaDensity can vary per voyage. A route that was Low-density when the player first traveled it becomes a Flashpoint voyage when the storyteller has activated drama modules that involve NPCs aboard this ship.
|
||||
|
||||
**4. In-transit events**
|
||||
The storyteller can seed in-transit events (delays, emergencies, unexpected dockings) from a per-voyage event seed. Voyage 3: smooth crossing. Voyage 5: unexpected stop at an unscheduled port while the Commission investigates a distress signal. The player who knows this route intimately has never encountered THIS version of it.
|
||||
|
||||
**5. Crew relationship state**
|
||||
The crew accumulates relationship state across voyages. The cook who was neutral toward the player on voyage 1 has warmed (or soured) by voyage 5 depending on simulation events. The crew provides persistent social continuity that makes repeat voyages feel like returning to a place with memory, not resetting to a blank state.
|
||||
|
||||
---
|
||||
|
||||
### The Temporal Constraint Mechanism
|
||||
|
||||
The arrival deadline is the primary dramatic engine aboard a vessel. The player can see it: their neural insert displays arrival time. This creates guaranteed temporal pressure without the generator engineering it.
|
||||
|
||||
For replayability: the temporal constraint means the player cannot do everything every voyage. On a six-hour crossing, there are perhaps four meaningful conversations possible, three explorations of the ship's spaces, and one incident. The player must choose. Different voyages, different choices, different outcomes — even with the same cast.
|
||||
|
||||
The storyteller can modify arrival time (delay, emergency, diversion). A voyage that was supposed to be six hours becomes nine. Three additional hours of enforced proximity. The NPC who had almost opened up, who was one more meal away from revealing what they know, now gets that meal. This is the highest-leverage storyteller tool aboard a vessel: not changing who's present, but changing how long they're all stuck together.
|
||||
|
||||
---
|
||||
|
||||
### Replayability Requirements for MobileChunk (For the D-Record)
|
||||
|
||||
Formalizing as verifiable requirements:
|
||||
|
||||
**R-V-1: Voyage manifest seeded per departure, not per vessel.**
|
||||
The same ship on different voyages must have meaningfully different passenger lists. The guarantee: at least N passengers must differ between adjacent voyages (N = floor(variable_slots × 0.5) — at least half the variable slots turn over).
|
||||
|
||||
**R-V-2: Crew is persistent, passengers are variable.**
|
||||
Crew NPCs persist across all voyages of the same vessel. This creates historical continuity. Passenger slots are refilled from the eligible pool at each departure.
|
||||
|
||||
**R-V-3: In-transit events are voyage-seeded, not vessel-seeded.**
|
||||
The same ship should not always produce the same incidents. Each voyage gets its own event seed, derived from the voyage manifest seed.
|
||||
|
||||
**R-V-4: Arrival time is storyteller-modifiable.**
|
||||
The temporal constraint is a storyteller instrument. The deadline can be extended (delay, diversion) or shortened (emergency early docking) based on narrative needs.
|
||||
|
||||
**R-V-5: Vessel interior does NOT re-generate per voyage.**
|
||||
The interior ChunkData is fixed at vessel generation time. Players who learn the ship's layout have earned that knowledge. The replayability is in the cast and the events, not in rediscovering the stage.
|
||||
|
||||
**R-V-6: Vessel carries ChunkMutations for accumulated damage.**
|
||||
A vessel that has been boarded, damaged, or modified during a voyage carries those modifications forward. The hole the player blasted through the bulkhead on voyage 3 is still there on voyage 5 unless repaired. Vessels accumulate history.
|
||||
|
||||
---
|
||||
|
||||
## OQ-R4-E: "One NPC, Five Lenses" — Replayability Check
|
||||
|
||||
### The Question
|
||||
|
||||
Miri demonstrates that one sufficiently complex NPC can provide all five playstyle entry hooks simultaneously (investigation anchor, tycoon economic chokepoint, dating sim social presence, political drama nexus, assassination latent hook). The question: does this create a district that plays the same every time?
|
||||
|
||||
### Answering the Direct Question
|
||||
|
||||
**Within a single seed**: YES, the same complex NPC provides the same hooks every visit. The investigation hook is always the same anomaly. The economic chokepoint they control is always the same resource. The same seed produces the same NPC with the same 10-axis profile. The district will feel "solved" once the player understands the NPC.
|
||||
|
||||
But this is the correct behavior. Same seed = same world. The point of a single complex NPC is not variation within a seed — it's that this is a place where ONE person MATTERS. In a small community, that's realism: there is a person here whose story is the story of this place. Exhausting that story in one thorough visit is accurate, not a design failure.
|
||||
|
||||
**Across seeds**: FULLY VARIABLE. Different seed = different NPC. Different anomaly. Different economic stranglehold. Different romantic archetype. Different political position. Different reason to be in a quiet backwater. The one-NPC minimal district provides maximum seed-to-seed variation because the entire dramatic content of the world is packed into one NPC, and that NPC is generated fresh per seed.
|
||||
|
||||
### But One NPC Is Not Enough for Intra-Seed Variation
|
||||
|
||||
The instinct to require 2-3 NPCs for minimal districts is correct, but the REASON is not replayability across seeds. The reason is **emergent drama requires relationships**.
|
||||
|
||||
Gestalt's minimum functional triangle is three nodes. One NPC cannot be in a triangle alone. Without relationships between NPCs, there are no triangles. Without triangles, the drama is a monologue — one person's story, fully contained within themselves. A monologue is finite. Once you've heard it, it's heard.
|
||||
|
||||
Two NPCs in tension produce a story. Three NPCs produce emergent behavior that none of them individually contains. The triangle is where unpredictable outcomes emerge from predictable NPC behaviors.
|
||||
|
||||
### The Minimum for Meaningful Replayability Within a Seed
|
||||
|
||||
**For a minimal-complexity insignificant district:**
|
||||
|
||||
- **1 NPC**: A character study. High seed-to-seed variation. Zero intra-seed variation after the first thorough visit. Not replayable.
|
||||
- **2 NPCs**: A relationship. Intra-seed variation from relationship dynamics (trust building/breaking, information transfer between them over time). Limited emergent behavior.
|
||||
- **3 NPCs**: A triangle. Intra-seed variation from triangle dynamics, shifting alliances, cascade effects when one node changes state. This is the minimum for genuine emergent narrative.
|
||||
|
||||
**My recommendation**: The minimum NPC count for a district to be replayable within a seed is **3 — one functional triangle**. For minimal-complexity districts, those 3 NPCs can each be simpler than a Full-complexity NPC (less information inventory, fewer entanglements, narrower routine), but there must be 3.
|
||||
|
||||
### Does the 10-Axis Model Support One NPC Providing All Five Hooks?
|
||||
|
||||
Yes, completely. The 10-axis model (Want, Secret/vulnerability, Relationships, Tolerance threshold, Daily routine, Information inventory, Contentment + 3 supporting) can absolutely encode an NPC who:
|
||||
- Has a Want that's an investigation hook (they want something that implicates them in something)
|
||||
- Has a Secret that's an assassination latent hook (they're someone significant in hiding)
|
||||
- Has Relationships that create economic chokepoints (they're the only one with the off-world comm codes)
|
||||
- Has a Tolerance threshold that creates political drama (they're near the edge; push them and the community fractures)
|
||||
- Has a Routine that creates dating sim opportunity (they gather with others every evening)
|
||||
|
||||
But having all five hooks in one NPC compresses the drama to a point. It works for the initial playstyle discovery (the world IS this person), but it creates a district that has no further depth once the NPC is understood.
|
||||
|
||||
**Conclusion on OQ-R4-E**: One NPC CAN provide all five hooks. The 10-axis model supports this. Across seeds, this produces maximum variation. Within a seed, this produces minimum emergent behavior. The answer to whether it's enough: **no — the minimum for intra-seed replayability is 3 NPCs (one functional triangle), even for minimal-complexity districts**. Miri's five minimum content types should be distributed across a minimum triangle, not collapsed into a single NPC.
|
||||
|
||||
---
|
||||
|
||||
## OQ-R4-F: Soft Re-Generation Coherence
|
||||
|
||||
### The XOR Problem
|
||||
|
||||
Gestalt proposes `original_seed XOR event_seed` for large-scale post-event re-generation. The question: does XOR-seeded regeneration produce caused variation or random variation?
|
||||
|
||||
The answer is: **it produces deterministic but incoherent variation**. Here's why this fails.
|
||||
|
||||
XOR combines two bit patterns arithmetically. The result has no semantic relationship to either input. `original_seed XOR event_seed` will always produce the same output (deterministic — good), but that output has zero structural relationship to the original seed (incoherent — bad). The content generated from the XOR seed would be as likely to produce an upscale market quarter as a burned-out ruin, because the XOR seed has lost all information about what the original district was.
|
||||
|
||||
This violates Ozzie's principle ("destruction must be CAUSED") and Miri's cultural response model (aftermath must be an intensification of existing character, not a transformation of it). A Frost-heritage community that has experienced a violence event should look MORE Frost (tighter, colder, doors closed, nobody talks to strangers) — not like a random re-roll that might be more Tide than the original.
|
||||
|
||||
### The Replayability Dimension of Re-Generation
|
||||
|
||||
Before proposing an alternative, I need to address the replayability question directly: **does any form of re-generation produce different-enough results across playthroughs of the same seed?**
|
||||
|
||||
The answer depends on what varies. If the post-event state is deterministic from seed + event type + event location + pre-event state, then two playthroughs of the same seed that both experienced the same event in the same location would produce identical post-event states. That's correct — same seed = same world. The variation across playthroughs comes from whether the event happens and when, not from random variation in the aftermath.
|
||||
|
||||
What the storyteller controls: whether and when to activate a fragility, trigger a trauma event, or cause structural damage. Different playthroughs of the same seed can have different event histories, producing different delta layers on the same base world. That's the replayability engine — not random reseeding of chunks.
|
||||
|
||||
### The Alternative: Typed Modification Instead of Re-Generation
|
||||
|
||||
No event actually requires chunk re-generation. Every event type maps to a `ChunkMutations` overlay:
|
||||
|
||||
**Fire/explosion:**
|
||||
- Tile overrides: burned floor tiles, collapsed wall tiles, ash-layer objects
|
||||
- Structural changes: specific walls marked as destroyed
|
||||
- Object removal: combustible objects replaced with debris objects
|
||||
- NPC modifications: displacement of NPC home points (their space no longer exists)
|
||||
|
||||
**Building collapse:**
|
||||
- MultiBlockReservation modified: vertical extent reduced
|
||||
- Floor zone zone_type changed from active to Ruins for affected z-levels
|
||||
- Structural changes at block level: entry points sealed
|
||||
|
||||
**Economic catastrophe:**
|
||||
- NPC contentment/want axes modified for residents
|
||||
- Object states changed (shops closed, market stalls empty)
|
||||
- No physical world changes — the buildings are still there, the market stalls are still there, but they're empty and the NPCS know it
|
||||
|
||||
**Political upheaval:**
|
||||
- Triangle activation changes (storyteller fires suppressed triangles)
|
||||
- NPC relationship modifications
|
||||
- Access tier changes (previously Semi-Private zones lock down to Restricted)
|
||||
- No physical world changes
|
||||
|
||||
In NONE of these cases is chunk re-generation needed. The `ChunkMutations` overlay handles all of them. Tyre's existing architecture is sufficient.
|
||||
|
||||
**The one case that might seem to require re-generation**: district-scale catastrophe (full district destroyed). My answer: this isn't re-generation — it's a new setting type. A district that has been catastrophically destroyed becomes a **Ruins** district. The ruins are generated from the SAME master seed, using the original district generation, with a damage overlay applied at Phase 2 that marks everything as destroyed. The ruins look like THAT district's ruins, not randomly generated rubble — because the tiles underneath are the same tiles, just tagged as destroyed.
|
||||
|
||||
### Formal Position on OQ-R4-F
|
||||
|
||||
**XOR-seeded re-generation is the wrong tool.** It produces deterministic but semantically incoherent results. It cannot satisfy the "caused, not random" requirement.
|
||||
|
||||
**The correct approach:**
|
||||
1. **Small-scale events** → `ChunkMutations` with event-typed tile overrides and structural changes
|
||||
2. **Medium-scale events** → `ChunkMutations` with broader structural changes + NPC state modifications
|
||||
3. **Large-scale catastrophe** → Original ChunkData + comprehensive damage overlay at Phase 2; setting type changes to Ruins; no re-seeding
|
||||
|
||||
**Replayability outcome**: The modification layer varies per playthrough (different events occur at different times, or don't occur at all). The base world never changes (same seed = same underlying district). Two playthroughs of the same seed can have completely different physical worlds in a district if one playthrough triggered the gas explosion and the other didn't. That is the replayability engine. The variance is in EVENT HISTORY, not in random chunk re-generation.
|
||||
|
||||
**What I'd put in the D-record**: "Post-event world modification is handled exclusively through the mutation overlay system (`ChunkMutations` / `WorldStateDelta`). The generator never re-runs for a generated district. Re-seeding via XOR is explicitly rejected as producing semantically incoherent results."
|
||||
|
||||
---
|
||||
|
||||
## Final Replayability Sign-Off: 12 D-Ready Items
|
||||
|
||||
For each item, I apply the Comparison Test: would two instances of this mechanism (same template, different seeds) produce distinguishable player experiences? And: would the same instance across two playthroughs of the same seed produce meaningfully different play?
|
||||
|
||||
---
|
||||
|
||||
**D-READY-1: DistrictLayoutMode — Grid and Organic Support**
|
||||
|
||||
**PASS — SIGNED OFF.**
|
||||
|
||||
Comparison Test: Grid district vs. Organic district of the same type → structurally different player experience (spatial reconnaissance is genuinely different; the assassin who uses a mental grid template is wrong in Organic mode). Same seed always produces the same layout mode — correct. The variation is across world regions, not within a seed.
|
||||
|
||||
One replayability note for the D-record: the distribution of Grid vs Organic districts must itself be seeded (different seeds produce different proportions of Grid/Organic across their worlds). If every generated world has Grid at the center and Organic at the margins, that's a predictable pattern a player can exploit. The distribution proportion should vary per seed.
|
||||
|
||||
---
|
||||
|
||||
**D-READY-2: Guarantee Tier System — Universal / Full-Only / Conditional**
|
||||
|
||||
**PASS — SIGNED OFF.**
|
||||
|
||||
Comparison Test: Two Full-complexity districts (different seeds) → both satisfy Tier 2 guarantees, but the SPATIAL REALIZATION differs per seed (which specific chunk is the Traffic Chokepoint, where the Encounter Corridor runs, what the Elevated Vantage position overlooks). The guarantee doesn't determine configuration, only presence. This is the right design — minimum guaranteed content without constraining configuration to a template.
|
||||
|
||||
One caveat: the guarantee system must not anchor archetypes to fixed positions within the district footprint. If the guarantee states "must have an Elevated Vantage" but the generator always places it northeast of the Social Hub, experienced players will use that pattern. The implementation must verify that archetype spatial positions vary in angular distribution across seeds. This is my earlier hard requirement, still standing.
|
||||
|
||||
---
|
||||
|
||||
**D-READY-3: TrianglePurpose Enum**
|
||||
|
||||
**PASS — SIGNED OFF (with a note).**
|
||||
|
||||
Comparison Test: Triangle purpose tags don't produce variation — they produce RELEVANCE. Two instances of the same triangle model with different purpose tags activate under different player playstyle conditions. This is not a variation mechanism; it is a targeting mechanism that prevents the storyteller from surfacing wrong-playstyle drama at the wrong moment.
|
||||
|
||||
For the D-record: `TrianglePurpose` is not a replayability feature — it is a multi-playstyle accessibility feature. Its replayability contribution is indirect: by activating the right triangles for the player's current lens, it ensures that drama which exists in the world is surfaced to the player who can engage with it, rather than being invisible noise.
|
||||
|
||||
---
|
||||
|
||||
**D-READY-4: WallBackside / TileBehindState**
|
||||
|
||||
**PASS — SIGNED OFF (with a condition).**
|
||||
|
||||
Comparison Test: Same district type, different seeds → different wall backside configurations. The proportion of `HiddenRoom` vs. `ServiceVoid` vs. `StructuralFill` must vary per seed, not be fixed by template. If every commissary wall always has a `ServiceVoid` on the other side, exploration is template-matching. The specific backside assignment must be seeded.
|
||||
|
||||
Condition for the D-record: **Backside assignments within a template must have seed-driven variation in their specific distribution.** The template can constrain TYPES (this district type can have HiddenRooms; this template slot is always StructuralFill) but the specific assignment per wall tile should vary. 90% automated tagging (Tyre's number) should mean 90% from seeded probabilistic rules, not 90% from fixed template values.
|
||||
|
||||
---
|
||||
|
||||
**D-READY-5: Dynamic Modification via Overlay (Not Re-Generation)**
|
||||
|
||||
**PASS — SIGNED OFF.**
|
||||
|
||||
This is the most important replayability mechanism in the architecture. The overlay model makes the same-seed-different-playthroughs scenario possible. The base world is identical across all playthroughs of the same seed. The modification history diverges based on what events the simulation has produced. Two players who started the same seed, made different decisions, and triggered different events have genuinely different physical worlds after those events — while sharing the same generator baseline.
|
||||
|
||||
This is EXACTLY how replayability should work: same world, different history.
|
||||
|
||||
---
|
||||
|
||||
**D-READY-6: ZonePalette Modifier System**
|
||||
|
||||
**PASS — SIGNED OFF.**
|
||||
|
||||
Comparison Test: Industrial farmland vs. rustic farmland → visually distinguishable. Frost-heritage industrial farmland vs. Tide-heritage industrial farmland → also distinguishable. The modifier system produces substantial combinatorial variety from a small base set.
|
||||
|
||||
Replayability note: palette combinations are static per district per seed. The same seed always produces the same palette. The variation is across seeds and across district types — not within a playthrough or across playthroughs of the same seed. This is correct. Visual identity of a place should be stable.
|
||||
|
||||
One note I want in the D-record: palette modifiers should influence NPC appearance as well as environment appearance. A Frost-heritage district should have NPCs whose clothing/gear palette is consistent with the Frost material grammar. This extends the "caused not random" principle to NPC appearance — people dress like they're from here.
|
||||
|
||||
---
|
||||
|
||||
**D-READY-7: Horizon View Corridor as Coastal Guarantee**
|
||||
|
||||
**PASS — SIGNED OFF.**
|
||||
|
||||
Comparison Test: Two coastal districts (different seeds) → both have horizon view corridors. The corridors are in different locations, overlook different portions of water, have different surrounding context. The MOMENT is guaranteed; the specific experience is seeded.
|
||||
|
||||
From a replayability standpoint: the horizon view is one of Ozzie's primary Wow Moments. Its value is partly in its unexpectedness — the player turns a corner and sees the ocean. If the horizon view corridor is always in the same relative position to the district entry point, experienced players expect it and the Wow diminishes. The reservation should constrain the corridor's existence and minimum width, but not its position. Let the generator place it wherever the spatial configuration produces it, as long as it exists.
|
||||
|
||||
---
|
||||
|
||||
**D-READY-8: Assassin Lens Spatial Guarantees (A-1 through A-4)**
|
||||
|
||||
**PASS — SIGNED OFF (with the angular variation requirement).**
|
||||
|
||||
Comparison Test: Two Full-complexity districts (different seeds) → both satisfy A-1 through A-4. The Elevated Vantage is in a different position. The Egress Multiplicity routes run different directions. The Temporal Opacity Window is at a different day-phase.
|
||||
|
||||
My standing hard requirement: archetype placement must vary in **angular position** across seeds, not just in distance from center. This requirement applies directly to the Elevated Vantage (A-1) and the relationship between it and the Traffic Chokepoint. If the Elevated Vantage is always north of the Traffic Chokepoint, every assassination approach is the same elevation/angle relationship regardless of seed. The guarantee system must verify that the angular distribution of archetype positions across multiple seeds is not clustered.
|
||||
|
||||
This is a verification requirement, not just a generation requirement. The guarantee audit should fail if archetypes are generated in positions that form a predictable template.
|
||||
|
||||
---
|
||||
|
||||
**D-READY-9: Heritage Grammar Overlay for Non-Urban Palettes**
|
||||
|
||||
**PASS — SIGNED OFF.**
|
||||
|
||||
Comparison Test: Frost-heritage farmland vs. Tide-heritage farmland → substantially different organizational grammar (Frost: individual plots, fenced separations, minimal communal space; Tide: open gradients, communal gathering areas, fluid spatial boundaries). This is not just cosmetic — the spatial grammar affects which playstyle affordances are naturally present (Tide produces more obvious Social Hub expressions; Frost produces more physical_distance informal zone expressions).
|
||||
|
||||
For the D-record: Heritage grammar is a generative input, not a decorative overlay. It shapes which archetypes are easy to satisfy and which are difficult. A Frost-heritage district has natural physical_distance informal zones but needs deliberate effort to produce an Encounter Corridor. This constraint shapes the district's playstyle affinity — which is the right level of influence.
|
||||
|
||||
---
|
||||
|
||||
**D-READY-10: Non-Urban Informal Zone Typology**
|
||||
|
||||
**PASS — SIGNED OFF.**
|
||||
|
||||
Comparison Test: Frost-heritage wilderness district → `physical_distance` informal zone type. Tide-heritage maritime district → `social_permission` informal zone type. The type is determined by heritage root — consistent and predictable. The LOCATION within the terrain is seeded.
|
||||
|
||||
One replayability note: the three informal zone types (social_permission / physical_distance / utilitarian_cover) create meaningfully different gameplay even when the player knows which type they're in. `Social_permission` means cover is about convention, not geography — you can be seen, you just can't be judged. `Physical_distance` means cover requires travel — you have to physically remove yourself. `Utilitarian_cover` means you need a functional excuse for your presence. Each type demands different strategies. The variation is not in "what is the informal zone" but in "how does one USE it." That's deep replayability from a simple typology.
|
||||
|
||||
---
|
||||
|
||||
**D-READY-11: Vertical Scale Architecture**
|
||||
|
||||
**PASS — with a replayability condition for the D-record.**
|
||||
|
||||
Comparison Test: Two Full-complexity skyscrapers (same heritage, different seeds) → different floor zone assignments? If z-band assignments are purely deterministic by building function (corporate building always has labor on 1-5, operations on 6-20, executive on 21-30), then experienced players can predict what's on floor 30 without visiting. That's the Second Station Syndrome applied vertically.
|
||||
|
||||
**Condition for the D-record**: z-band boundaries must have seed-variation within cultural constraints. The cultural model constrains the ORDERING (labor below operations below executive), but not the exact floor numbers. A corporate building in one seed has executive starting on floor 22; in another seed, floor 35. The player who knows "executive floors are in the upper third" is working with useful knowledge, but can't skip exploration — they still need to find the actual executive zone.
|
||||
|
||||
Secondary replayability property of vertical scale: **vertical access routes are playthrough-history dependent**. A player who befriended the building's head of facilities on an earlier encounter can now access the service elevator directly. A player who damaged the main elevator bank in a previous event now has to find an alternative route. The building's access topology is fixed by the seed; which routes are available to the player at any moment is determined by their relationship and event history. Same building, different access experience per playthrough.
|
||||
|
||||
---
|
||||
|
||||
**D-READY-12: Trauma Events as EraModification Subtypes**
|
||||
|
||||
**PASS — SIGNED OFF.**
|
||||
|
||||
Comparison Test: Same district before and after a PhysicalDestruction trauma event → different NPC pattern weight distribution (ANCHOR/WITNESS/REMNANT increase; normal distribution suppressed). The change is predictable from the heritage root — Frost communities respond differently to trauma than Tide communities. Two Frost-heritage communities that experience the same trauma type respond similarly (same cultural grammar). Two communities with different heritage roots diverge.
|
||||
|
||||
This is the correct behavior. The trauma response is not random — it is culturally CAUSED. Ozzie's principle is satisfied.
|
||||
|
||||
One replayability note: **the decay rate** (how quickly the cultural aftermath fades toward baseline) should be seeded at generation time with variation. A Frost-heritage community might always be slow to recover (heritage root determines the baseline rate), but the SPECIFIC rate for this community is seeded (some Frost communities are 20% faster to recover than the mean; others are 20% slower). This prevents trauma response from being perfectly predictable from heritage root alone — it adds the "this specific community" dimension that makes individual settlements feel distinct.
|
||||
|
||||
---
|
||||
|
||||
## Summary: Round 4 Positions
|
||||
|
||||
**OQ-R4-A resolved:** MobileChunk accepted. The vessel is a stage (persistent interior) + a cast (per-voyage manifest). Manifest seeded from `derive_seed(master, "vessel_manifest", vessel_id, voyage_index)`. At least 50% of variable passenger slots must turn over between adjacent voyages. Crew persistent across voyages. In-transit events voyage-seeded (not vessel-seeded). Arrival time is storyteller-modifiable. Vessel accumulates ChunkMutations across its lifespan. Requirements R-V-1 through R-V-6 stated for the D-record.
|
||||
|
||||
**OQ-R4-E resolved:** One NPC can provide all five playstyle hooks simultaneously. 10-axis model supports this fully. BUT: one NPC produces zero intra-seed emergent behavior (no relationships = no triangles = no emergence). The minimum for meaningful intra-seed replayability is 3 NPCs (one functional triangle), even for minimal-complexity insignificant districts. Miri's five minimum content types should be distributed across a minimum triangle.
|
||||
|
||||
**OQ-R4-F resolved:** XOR-seeded re-generation is explicitly rejected — it produces deterministic but semantically incoherent results. The correct approach: typed `ChunkMutations` overlays for all event scales. The generator never re-runs for a generated district. District-scale catastrophe produces a Ruins overlay on the original ChunkData, not a re-seeded replacement. Replayability comes from event history divergence across playthroughs, not from random chunk re-generation.
|
||||
|
||||
**12 D-ready items:** All signed off. Three replayability conditions to include in D-records:
|
||||
1. (D-READY-1) Grid/Organic distribution proportion must vary per seed — not fixed to a predictable geographic pattern.
|
||||
2. (D-READY-8 / D-READY-2) Archetype placement must vary in angular position per seed — not just distance from center. This is verifiable and testable. The guarantee audit should fail if archetypes cluster in predictable angular positions across a test run of N seeds.
|
||||
3. (D-READY-11) Z-band floor boundaries must have seed-variation within cultural ordering constraints — experienced players should know "executive is in the upper zone" without knowing which exact floor that begins on.
|
||||
@@ -0,0 +1,110 @@
|
||||
# Generator Architecture Workshop — Round 5: Nigel (Final Review)
|
||||
|
||||
**Date:** 2026-02-27
|
||||
**Role:** Replayability Advocate
|
||||
**Task:** Sign-off review of workshop-outcomes.md. Corrections only.
|
||||
|
||||
---
|
||||
|
||||
## Sign-Off Status
|
||||
|
||||
**SIGNED OFF** with two corrections required and two notes.
|
||||
|
||||
---
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
**1. MobileChunk replayability guarantees — PASS WITH NOTE**
|
||||
|
||||
D-READY-13 correctly captures: vessels as persistent world entities, Docked state with dock_position, boarding via gangway, interior cache persisting crew state across voyages, departure schedule as required generator output (error state if missing). The stage+cast framing is correct.
|
||||
|
||||
Note: R-V-1 through R-V-6 are cited by reference only ("see round-4-notes.md §5"). This is acceptable if round-4-notes.md is preserved. For D-record durability, R-V-1 (≥50% variable manifest slots must differ between adjacent voyages) and R-V-3 (in-transit events are voyage-seeded, not vessel-seeded) are the two most critical for implementation correctness and should be verified to appear in the referenced section before filing.
|
||||
|
||||
**2. Minimum 3 NPCs for intra-seed replayability — PASS**
|
||||
|
||||
Explicitly stated: "Minimum NPC count for intra-seed replayability: 3 (one functional triangle). One NPC = maximum seed-to-seed variation, zero intra-seed emergence. Three NPCs = triangles, shifting alliances, cascade effects. Even Minimal-complexity insignificant districts need 3 NPCs." Correct and complete.
|
||||
|
||||
**3. RegenerationStrategy enum — PASS**
|
||||
|
||||
`LocalOverlay / SoftReseed / FullReseed` correctly maps in-playthrough / scenario-boundary / era-level. XOR prohibition for in-playthrough events is stated as a hard constraint and confirmed as lead decision L-7. The allowance of SoftReseed for scenario-boundary events is a valid nuance — the player was not present, so causal legibility is not required. Correct.
|
||||
|
||||
**4. DramaDensity as runtime state — PASS**
|
||||
|
||||
L-5 is explicit. The three-layer model correctly places `drama_density` under `SIMULATION STATE (runtime storyteller — NOT generator output)`. Not on DistrictSkeleton. Confirmed.
|
||||
|
||||
**5. Three-parameter model (WorldTier + ComplexityTier + DramaDensity) — CORRECTIONS REQUIRED**
|
||||
|
||||
Two separate issues found:
|
||||
|
||||
---
|
||||
|
||||
## Correction 1 — WorldTier Ceiling Conflict (Local)
|
||||
|
||||
The constraint table states:
|
||||
> "WorldTier → ComplexityTier ceiling: Core/Regional → Full max; **Local → Moderate max**; Transit → Minimal; Dormant → Empty."
|
||||
|
||||
The very next sentence states:
|
||||
> "A narratively critical backwater can be `WorldTier::Local + ComplexityTier::Full`."
|
||||
|
||||
These are directly contradictory. Local cannot simultaneously have a Moderate ceiling and an explicit Full-complexity example.
|
||||
|
||||
**Root cause:** The WorldTier enum description for `Local` includes "limited budget," conflating network significance (Local = low external connectivity) with simulation budget (which should be fully determined by ComplexityTier alone). WorldTier is about network position. ComplexityTier is about generator output depth. They are independent — this was the central Round 3 insight confirmed by all three participants.
|
||||
|
||||
The `Backwater + Full complexity` case is fundamental to the game's design ("Insignificance is a lens, not a verdict"). A dense, isolated community of 150 people who've lived together for 40 years can be as socially rich as any hub — it's just not connected to the wider network.
|
||||
|
||||
**Required fix — corrected ceiling table:**
|
||||
|
||||
| WorldTier | ComplexityTier ceiling |
|
||||
|-----------|------------------------|
|
||||
| Core | Full |
|
||||
| Regional | Full |
|
||||
| **Local** | **Full** |
|
||||
| Transit | Minimal |
|
||||
| Dormant | Empty |
|
||||
|
||||
Also remove "limited budget" from the `Local` enum comment. Budget is ComplexityTier's responsibility, not WorldTier's.
|
||||
|
||||
---
|
||||
|
||||
## Correction 2 — Missing ComplexityTier → DramaDensity Ceiling
|
||||
|
||||
The document states the first half of the constraint chain:
|
||||
> WorldTier constrains ComplexityTier ceiling ✓
|
||||
|
||||
But does NOT state the second half:
|
||||
> ComplexityTier constrains DramaDensity ceiling ✗ (missing)
|
||||
|
||||
This constraint is load-bearing. A `ComplexityTier::Empty` district has no NPCs, no social sites, no triangles. The storyteller cannot meaningfully activate drama in a district with no social fabric. Allowing the storyteller to set `DramaDensity::Flashpoint` on an Empty district is a bug category, not a design option.
|
||||
|
||||
**Required addition** — after the existing WorldTier → ComplexityTier ceiling table, add:
|
||||
|
||||
> ComplexityTier → DramaDensity ceiling: Full → any intensity; Moderate → Active max; Minimal → Quiescent max; Empty → Zero only (no storyteller activation possible).
|
||||
|
||||
(Using the 3-level enum values currently in the struct: Quiescent / Active / Intense.)
|
||||
|
||||
This does not change any other part of the document. It is a missing half of the stated constraint chain.
|
||||
|
||||
---
|
||||
|
||||
## Notes (Not Corrections, Not Blocking)
|
||||
|
||||
**Note 1 — DramaDensity enum naming (Q-NNN-d)**
|
||||
|
||||
Q-NNN-d flags Round 4 struct as Quiescent/Active/Intense (3 levels) vs. Round 3's Zero/Low/Medium/High/Flashpoint (5 levels). My preference is 5 levels for finer storyteller control. Specifically: the distinction between `High` ("this is the current narrative focus") and `Flashpoint` ("crisis actively destabilizing the world") is a categorically different gameplay state that should not collapse into a single `Intense` value. If 3 levels is chosen for implementation simplicity, I ask that Flashpoint be preserved as the distinct peak value — it is the storyteller's maximum-pressure instrument and deserves its own state.
|
||||
|
||||
This is a Q-record and sprint work. Flagging my position, not blocking.
|
||||
|
||||
**Note 2 — Q-NNN-b Resolution**
|
||||
|
||||
Q-NNN-b is listed as unresolved: "Departure schedule model — departure windows as generator output for docked vessels." But D-READY-13 already states: "`scheduled_departure: Option<SimTick>` field in Docked state satisfies this; the generator must populate it. Vessels without departure schedules are an error state." This appears resolved within the document. Recommend closing Q-NNN-b before sprint planning.
|
||||
|
||||
---
|
||||
|
||||
## Overall Verdict
|
||||
|
||||
The document correctly captures the workshop architecture. Two corrections must be applied before D-records are filed:
|
||||
|
||||
1. Local ceiling must be Full (not Moderate) — the backwater case is core design
|
||||
2. ComplexityTier → DramaDensity ceiling must be stated — it is half of the constraint chain
|
||||
|
||||
Everything else accurately reflects my Round 3-4 positions. The replayability architecture this document specifies will deliver: two players comparing the same world mod will have wildly different stories to tell.
|
||||
@@ -0,0 +1,126 @@
|
||||
# Generator Architecture Workshop — Round 1: Ozzie
|
||||
|
||||
**Role:** Player Experience / Fan Perspective
|
||||
**Date:** 2026-02-27
|
||||
**Workshop:** Generator Architecture (#562)
|
||||
|
||||
---
|
||||
|
||||
## Disclaimer: I Am Not An Architect. I Am A Player.
|
||||
|
||||
I don't care about pipelines. I don't care about "zoning passes" and "district skeletons." I care about one thing: when I walk into a new station for the first time, does it feel REAL? Does it feel like somewhere people actually live? And when I come back to a different station six hours later, is it still exciting — or is it the same grey corridor wearing a different hat?
|
||||
|
||||
That's my job here. Make the case for the player. Shout when something sounds wrong. Lose my mind when something sounds right.
|
||||
|
||||
---
|
||||
|
||||
## What I Need From 300 Worlds
|
||||
|
||||
Three things. Non-negotiable.
|
||||
|
||||
**1. A reason to explore.**
|
||||
|
||||
Every station needs a "wait, what's that?" moment within the first two minutes of arrival. A weird shop jammed into an alcove. A maintenance ladder going somewhere it probably shouldn't. Two NPCs having a conversation that stops when you get close. Something. If I land on a new station and my first impulse is "okay, where's the quest marker," you've failed. The space itself needs to be a question.
|
||||
|
||||
**2. A place I'm not supposed to be.**
|
||||
|
||||
I need to find somewhere that feels like I wasn't meant to find it. A back room. A rooftop access. A corridor that's not on the map. This can't be everywhere — if it's everywhere, it's nowhere — but it has to exist, and I have to find it myself, not be guided to it. The generator needs to produce these spaces reliably. Not as marked secrets. Just as... the consequences of how a real place is built.
|
||||
|
||||
**3. Density contrast.**
|
||||
|
||||
Crowded market → narrow service corridor → sudden open atrium. That rhythm. That's what tells me this is a place that evolved, not a place that was assembled from a template. If every district has consistent density, consistent ceiling height, consistent noise level, it feels fake. The generator needs to produce contrast even when it's pulling from templates.
|
||||
|
||||
---
|
||||
|
||||
## The Generation Sins
|
||||
|
||||
Here's what would make me quit.
|
||||
|
||||
**Sin #1: The Second Station Syndrome.**
|
||||
|
||||
I arrive at station two and I immediately recognize the skeleton. Oh, it's the market district again. The bar is in the northwest quadrant, the transit hub is in the southeast, there's a service corridor along the east edge. Even if the art is different, if I recognize the SHAPE, the spell is broken. I stop exploring because I already know what's there. This is the death of the game.
|
||||
|
||||
**Sin #2: Decorative variation, structural sameness.**
|
||||
|
||||
If the generator produces districts that are geometrically different but functionally identical — same chokepoints, same social patterns, same access — then we've just reskinned the same space. I don't need a different coat of paint. I need a different reason to pay attention.
|
||||
|
||||
**Sin #3: Dead space.**
|
||||
|
||||
Rooms that exist but contain nothing — no NPCs, no loot, no environmental story, no reason to be there. Procedural generation loves to produce dead space. It's the easiest thing in the world to generate a corridor with nothing in it. I should never arrive somewhere and feel like I'm in a loading zone for somewhere else. Every space needs to pay rent.
|
||||
|
||||
**Sin #4: Predictable secrets.**
|
||||
|
||||
If I learn the grammar of how secrets are hidden — always in the northeast corner, always behind a stack of crates, always through a vent — then secrets become routine. "Oh, there's the secret." That's the opposite of discovery. The generator's variation needs to extend to WHERE things hide, not just what they look like.
|
||||
|
||||
**Sin #5: "Generated" readable from the outside.**
|
||||
|
||||
If I can look at a district and think "yes, this is clearly procedural" — I'm done. The aesthetic tells me this is content filler. Real places have weirdness in them. An awkward staircase that goes nowhere useful because the building was extended. A niche that's a completely different architectural style because it was added later. Irregularities that suggest history. The generator needs to produce irregularities. Not random noise — meaningful-feeling irregularities.
|
||||
|
||||
---
|
||||
|
||||
## What Makes the 50th Station Exciting
|
||||
|
||||
This is the real question.
|
||||
|
||||
For the 50th station to be exciting, the generator can't just be varying surface features. It has to be varying WHAT MATTERS.
|
||||
|
||||
What matters to me as a player:
|
||||
- **Who has power here** — and how it shows in the space. A station under Intersolar Commonwealth control looks and moves differently than one under de Terre influence. That's not just art. That's which doors are locked, which NPCs are nervous, where the cameras point.
|
||||
- **What happened here** — the environmental story. A district that used to be prosperous and isn't anymore. A market that's clearly improvised after something was destroyed. Spaces tell history. The generator needs inputs that make history legible.
|
||||
- **What's the social architecture** — where do the hierarchies show up physically? Where do the powerful people eat lunch? Where do the workers hide from supervisors? This makes stations feel like societies, not buildings.
|
||||
|
||||
If the generator is just varying layout geometry and art themes, the 50th station is just the 50th palette swap. If it's varying the SOCIAL AND POLITICAL TEXTURE — who's in charge, what they want hidden, what grudges are still warm — then I will happily explore the 100th.
|
||||
|
||||
---
|
||||
|
||||
## Hand-Crafted vs Obviously Procedural
|
||||
|
||||
Let me be honest: I don't care which one it is, as long as it READS as hand-crafted.
|
||||
|
||||
No Man's Sky fooled me for about 30 minutes. Dwarf Fortress fools me forever. The difference isn't technical — it's whether the output shows evidence of considered choices. A DF fortress feels hand-crafted because it's the product of systems that have opinions. The weird L-shaped room exists because miners hit an aquifer. That's not random — that's causal.
|
||||
|
||||
The sub-chunk quarter system sounds promising to me. L-shapes, merged footprints, irregular structures within a grid — those are the right instincts. The question is whether the results will feel CAUSED (this building is shaped this way because something made it this way) or RANDOM (this building is shaped this way because the RNG said so). Caused feels hand-crafted. Random feels generated.
|
||||
|
||||
What I need: the irregularities to feel like they have reasons, even if I can't articulate them. If I look at an L-shaped building and unconsciously think "yeah, that makes sense here," we've won. If I look at it and think "huh, weird," we've failed.
|
||||
|
||||
---
|
||||
|
||||
## What Spatial Surprises Matter Most
|
||||
|
||||
In order:
|
||||
|
||||
**1. Vertical surprise.** Going up when I didn't expect to. A building that reveals a second floor. A shaft. A balcony looking down on a space I thought was at ground level. This reorients my mental map in a satisfying way.
|
||||
|
||||
**2. Density inversion.** Finding something quiet in the middle of a loud area. Or something bustling inside what looked like a dead zone. The contrast is the surprise.
|
||||
|
||||
**3. Shortcuts that feel earned.** Not obvious shortcuts — those are just map design. A way through that I discovered, that I now own. A loose panel, an underused service route, an NPC who lets me through if I've done something for them. The generator needs to produce the SPATIAL POSSIBILITY of shortcuts; the systems layer turns them into earned ones.
|
||||
|
||||
**4. Hidden audience.** Spaces where I can watch without being seen. Or where I realise I'm being watched. This matters enormously for the game's investigation core. A generated district that has no natural sightline asymmetry — nowhere to stand and observe — is useless for the game's fantasy.
|
||||
|
||||
**5. A place that's too small to be safe.** A tiny space with one exit. A maintenance crawl that opens into someone's private room. The tension of confined geometry. The generator should occasionally produce spaces where the SHAPE creates vulnerability.
|
||||
|
||||
---
|
||||
|
||||
## My Gut Reaction to the Sub-Chunk Quarter System
|
||||
|
||||
This is the most interesting idea in the brief and the one I'm most nervous about.
|
||||
|
||||
The nervous part: "quarters that can merge, split, leave gaps, or host shacks/gardens" sounds like it's describing a system that produces visual variation within a regular grid. That's fine. But does it produce SOCIAL variation? Does the choice of what fills a quarter have downstream consequences — does a garden quarter mean something different about who lives nearby versus a shack quarter? If the quarters are just aesthetic choices, I'll see through them on the second station.
|
||||
|
||||
The exciting part: the irregularity principle. L-shapes, gaps, merged footprints — these are exactly the right inputs for making spaces feel like they grew rather than were placed. If I walk into a block and the building footprints are subtly wrong, are bumped against each other, leave a weird sliver of space between them — I will explore that sliver. I will want to know what's in it.
|
||||
|
||||
The worry: the grid will show. Even with quarter variation, if the blocks are always the same size and the streets are always aligned, I'll feel the skeleton underneath. What breaks the grid-ness isn't varying what's inside the grid. It's varying the grid itself — odd street angles, blocks that don't quite fit, infrastructure that predates the current layout. Can the generator produce HISTORICAL PALIMPSEST? Can it make stations that feel like they were built in layers by different people with different plans?
|
||||
|
||||
That's what I want. Not variety. History.
|
||||
|
||||
---
|
||||
|
||||
## Summary: What I'm Rooting For
|
||||
|
||||
A generator that asks not "how do we produce 300 different-looking stations" but "how do we produce 300 stations with different STORIES encoded in their geometry."
|
||||
|
||||
The technical architecture doesn't matter to me. What matters is whether the output makes me want to be there. Whether walking into a district gives me questions I want answered. Whether the space itself is a puzzle — not a quest-marker puzzle, a human puzzle. Why is this corridor blocked? Why do people avoid that corner? Who decided this building needed to be this shape?
|
||||
|
||||
Give me questions encoded in space. That's all I ask.
|
||||
|
||||
Make me care about the 50th station as much as the first. THAT'S the design challenge. THAT'S what I'm here to fight for.
|
||||
@@ -0,0 +1,244 @@
|
||||
# Generator Architecture Workshop — Round 2: Ozzie
|
||||
|
||||
**Role:** Player Experience / Fan Perspective
|
||||
**Date:** 2026-02-27
|
||||
**Workshop:** Generator Architecture (#562)
|
||||
|
||||
---
|
||||
|
||||
## I've Read Everything. Here's My Gut.
|
||||
|
||||
First: I'm floored. These five people are THINKING. The cultural ingredients system is exactly the kind of thing that could save this game from the procedural-sameness death spiral. The visual grammar constraints make me feel like the spaces will actually mean something. Nigel's comparison test — two players comparing notes and finding incompatible experiences — is EXACTLY the right design target.
|
||||
|
||||
But I have things to say. Let's go.
|
||||
|
||||
---
|
||||
|
||||
## On Tyre's Technical Architecture
|
||||
|
||||
**Does it address my grid concern?** Partially. But not enough.
|
||||
|
||||
Tyre told me the quarter system is "generation-side only" — it disappears after the fill pass. The server sees tiles. The player sees space. And the L-shape, the FullMerge, the MergeH options — these sound right. These sound like the difference between a building that was planned and a building that grew.
|
||||
|
||||
But here's what Tyre didn't answer: does the BLOCK grid vary? The 128×128 sim tile block, the 4×4 arrangement within a district — those stay fixed. The streets between blocks always align to the same grid. Every block has the same 64m² footprint. Even with all the L-shapes and merged chunks in the world, I will eventually feel that 64m grid underneath me.
|
||||
|
||||
What I need Tyre to address in the next round: can the STREET GRID rotate? Can blocks be non-rectilinear at the geography/infrastructure stage? If every district is a perfect 4×4 grid of identical-footprint blocks with perpendicular streets, I will feel the skeleton on the 5th station.
|
||||
|
||||
The edge contracts system is brilliant — chunks promising each other what their boundaries look like, so the generator can fill them coherently. That's the right instinct for how borders work. It's also, interestingly, the system that could ALLOW the grid to rotate, if the edge contracts can handle non-90-degree intersections.
|
||||
|
||||
The borderless generation implication is the most exciting thing in Tyre's output. "District generation must be local, not global" — if that means districts can grow organically from their neighbors rather than being stamped on a grid, I want that. BADLY.
|
||||
|
||||
**What I need:** Tell me the grid can breathe. Tell me two adjacent districts can have different orientations. Tell me a street can curve because the geography required it.
|
||||
|
||||
---
|
||||
|
||||
## On Miri's Cultural Ingredients System
|
||||
|
||||
**Does it solve Second Station Syndrome?** YES. This is the answer.
|
||||
|
||||
I asked in Round 1: does the 50th station have different SOCIAL AND POLITICAL TEXTURE? Miri said yes. And she showed her work.
|
||||
|
||||
The Frost/Salt/Iron + tight-margin + prohibition-economy combination for Sova — that's not decorative. That's mechanically load-bearing. A Frost-dominant culture means silence is NORMAL. On a Tide/Vine culture station, silence is suspicious. The SAME NPC BEHAVIOR means opposite things. That's not the 50th palette swap. That's a completely different game.
|
||||
|
||||
The absence parameters are the sleeper hit of Miri's system. A station with no philosophical alignment — pure pragmatism, no ideology — is mechanically different from one with labor-solidarity as a framework. The grey economy on Sova is rational economic behavior. On a solidarity-aligned station, the grey economy is politically organized. The detective confronts completely different moral architecture.
|
||||
|
||||
My concern: the six categories are rich for investigation gameplay. But do they produce variation for OTHER playstyles? I'll come back to this.
|
||||
|
||||
One thing I love unreservedly: "No heritage consciousness → functional naming, no substrate words, no food traditions." A transit hub with high turnover and no heritage consciousness is a place that doesn't have a self-concept. That's lonely in a way that makes me want to understand it. That's STORY.
|
||||
|
||||
---
|
||||
|
||||
## On Gestalt's Seven Spatial Guarantees
|
||||
|
||||
**Too investigation-focused? Yes. And here's why that matters now.**
|
||||
|
||||
The lead just told us this isn't a detective game. It's about asymmetric human awareness. That means the tycoon and the romantic lead and the political operator ALL need spatial guarantees that serve their gameplay.
|
||||
|
||||
Gestalt's seven guarantees are:
|
||||
1. Surveillance chokepoint
|
||||
2. Meridian dead zone
|
||||
3. Social hub
|
||||
4. Quiet zone / staging ground
|
||||
5. Vertical access / spatial discovery
|
||||
6. Triangle staging ground
|
||||
7. Something mundane that's secretly a crime scene
|
||||
|
||||
Numbers 1, 2, 4, 6, and 7 are detective guarantees. Number 3 and 5 are multi-playstyle.
|
||||
|
||||
This isn't a criticism of Gestalt — Round 1 was written before the broadened lens. But for Round 2, the guarantees need to expand.
|
||||
|
||||
**What the tycoon player needs from spatial guarantees:**
|
||||
- An economic choke node: somewhere goods or money must pass through, that can be controlled or leveraged
|
||||
- Competing commercial zones: there's a winner and a loser, spatially expressed
|
||||
- Infrastructure vulnerability: a supply chain that can be interrupted, rerouted, exploited
|
||||
- A space where deals happen informally: because the formal spaces are regulated
|
||||
|
||||
**What the dating sim player needs:**
|
||||
- A third place: somewhere that's neither work nor home, where social barriers drop
|
||||
- Ritual gathering points: the shift-change bar, the market morning, the rooftop at dusk
|
||||
- Privacy gradient: somewhere that can transition from public to intimate, spatially
|
||||
- A place to be seen: because romance happens in public before it happens in private
|
||||
|
||||
The surveillance chokepoint and the romantic encounter spot can be the SAME ROOM, seen through different lenses. That's the design target. But Gestalt's guarantees currently don't name the spaces in terms that serve the romantic's playthrough.
|
||||
|
||||
**My ask to Gestalt for Round 2:** Frame the guarantees in terms that serve EVERY playstyle. "Social hub" is doing real work here already — a bar is an investigation staging ground AND a dating venue AND where the tycoon hears gossip about competitors. But the guarantees that are purely investigation-flavored need to be reframed as multi-use spatial types.
|
||||
|
||||
---
|
||||
|
||||
## On Araminta's Visual Grammar
|
||||
|
||||
**Would I want to explore these spaces?** HELL YES. With one caveat.
|
||||
|
||||
Araminta gave me the most technically precise output of the round, and somehow it's the most emotionally reassuring. The zone palettes produce GEOGRAPHY OF FEELING. Cold institutional white → cargo grey-navy → dark transit → amber social warmth. Walking THROUGH those temperature zones is a spatial experience. That gradient is a story the player's body tells before their brain catches up.
|
||||
|
||||
The LOS anchor rule — every quarter must have at least one structural break — is the anti-dead-space rule I was screaming for in Round 1. Every quarter pays rent. I could cry.
|
||||
|
||||
The "settled principle" — space feels inhabited when it has accumulated objects, not large open areas — is the best single sentence in all of Round 1. That's not a visual rule. That's a philosophy of place. PLACES ARE WHAT PEOPLE DO IN THEM.
|
||||
|
||||
My caveat: Araminta's visual grammar is extremely station-centric. The zone palettes (gate cluster cold white, terminal institutional, maintenance dark, bar amber) are all interior urban spaces. What does this grammar do when we're on a planet? When we're in farmland? When we're at a beach resort?
|
||||
|
||||
I need to know that the visual grammar can produce the FEELING OF OUTSIDE. Not just different hex codes — actual spatial openness, natural light quality, the disorientation of no walls. Station-born players arriving at their first planet-side destination should feel DIFFERENT. The visual grammar needs to be able to generate that.
|
||||
|
||||
And actually — the CONTRAST between station interior and planetary exterior is a Wow Moment. Walking through a gate aperture and suddenly the hex codes change and the light comes from above and there's horizon? That's a moment I'd tell someone about. Does the visual grammar plan for that moment?
|
||||
|
||||
---
|
||||
|
||||
## On Nigel's Replayability System
|
||||
|
||||
**Nigel gets it. Nigel REALLY gets it.**
|
||||
|
||||
Structural randomness over surface randomness. The entanglement assignment is more important than the quarter merge. The social graph varies, not just the NPC portraits. Knowledge rot across playthroughs. The comparison test. ALL OF THIS.
|
||||
|
||||
"The generator doesn't produce 300 worlds. It produces 300 × (character options) × (cultural combinations) × (seed entropy) distinct game experiences." I want to put this on a wall.
|
||||
|
||||
The historical event seed is my favorite new idea: "A corporate merger 10 years ago → two different architectural styles visible, NPCs with residual loyalty conflicts." That's the historical palimpsest I asked for. That's CAUSED irregularity. A building is L-shaped because when the merger happened, they couldn't tear down the original east wing without disrupting operations, so they just built around it.
|
||||
|
||||
My one concern about Nigel: the flavor structure categories are heavily investigation-biased too. Informal economy indicators, economic stress indicators, faction presence indicators — these are all about social power and grey-market activity. They're the right categories for the investigator. They're less obviously useful for the person who's just trying to understand this place emotionally, or economically, or romantically.
|
||||
|
||||
A "settlement indicator" — container gardens, improvised seating clusters, personal shrines — that's actually multi-use. Those aren't just about crime. Those are about people making a home in an inhospitable place. That's the most human thing in Nigel's list, and I think it deserves to grow.
|
||||
|
||||
---
|
||||
|
||||
## NEW TERRITORY: Beyond Investigation
|
||||
|
||||
This is what the lead directive is actually asking. Not "does the investigation work?" but "does the WORLD work for every way a human being might engage with it?"
|
||||
|
||||
### What Does a Tycoon Player Need?
|
||||
|
||||
The tycoon is playing an economic game inside the social sim. They're not asking "who's guilty." They're asking "where is value being created and how do I redirect some of it toward me?"
|
||||
|
||||
For the tycoon, the generation sins are:
|
||||
|
||||
**Sin #1: An undifferentiated economy.** If every district has the same mix of economic activity, there's no leverage. The tycoon needs to see the gaps: what does this station import that it could produce? Where is the markup? What infrastructure constraint creates a monopoly opportunity? The generator needs to produce ECONOMIC GEOGRAPHY — places where resources flow through chokepoints, where production capacity exists but distribution doesn't, where there's a market for something nobody's selling.
|
||||
|
||||
**Sin #2: A political landscape with no edges.** The tycoon wants to know who you HAVE to deal with to do business here. Commission-heavy district means permits and bribes in the right direction. Syndic-heavy means the labor rates are set, take it or leave it. Weakly controlled means opportunity but also no enforceable contracts. If the generator produces a political landscape that's uniform — everyone's equally formal or informal — there's no arbitrage. No edges.
|
||||
|
||||
**Sin #3: Infrastructure that's already optimal.** The tycoon wants broken things. Inefficient routes. Supply chains that add two steps because nobody thought to build a connector. A generator that produces perfectly optimized infrastructure leaves no economic opportunity.
|
||||
|
||||
What makes a tycoon EXCITED about a new station: spotting an inefficiency in the third minute of exploring. "Wait — they're bringing freight in through the passenger terminal? That's expensive. If I could negotiate with the freight operator AND the Commission checkpoint supervisor..." That's gameplay.
|
||||
|
||||
The generator needs to produce the SPATIAL CONDITIONS for that moment. Not the moment itself — just the infrastructure that makes it imaginable.
|
||||
|
||||
### What Does a Dating Sim Player Need?
|
||||
|
||||
The dating sim player is building relationships. They want to understand people, to matter to them, to be known by them. The game's central mechanic — asymmetric information, trust tiers, invisible dialogue — actually SERVES this playstyle beautifully. The investigator uncovers secrets. The romantic does too. They just do it with different intent.
|
||||
|
||||
For the romantic, the generation sins are:
|
||||
|
||||
**Sin #1: No private space that feels earned.** Romance needs gradient — from public encounter to private access. If every space is either completely public or locked-restricted, there's nowhere to actually be alone with someone. The generator needs to produce spaces that are TECHNICALLY public but FEEL intimate: the quiet corner of the bar, the maintenance corridor that nobody uses in the afternoon, the roof access that's not actually supposed to be accessible.
|
||||
|
||||
**Sin #2: No ritual time.** Romance happens in repeated encounters. The shift-end bar crowd, the morning market regulars, the rooftop people who always seem to be there at dusk. These are SCHEDULED SOCIAL RITUALS. The generator needs to produce the spatial conditions for recurring social gathering — places where you can FIND someone again, where showing up regularly means something.
|
||||
|
||||
**Sin #3: No story to discover.** The most romantic thing in this game might be learning the history of someone who's been here longer than you. The labor dispute that left a mark. The family that arrived as refugees and built something. The maintenance corridor that's named after someone nobody can quite remember. These are the stories that make you feel like you're in a PLACE, not a simulation. The generator's historical palimpsest system is secretly the most romantic system in the whole game.
|
||||
|
||||
**Sin #4: No contrast between warmth and cold.** Romance is partly about finding warmth in an inhospitable world. A station that's uniformly comfortable has no stakes. The generator needs to produce spaces that are HARSH — cold maintenance levels, loud freight areas, institutional indifference — so the warm social spaces feel like sanctuary.
|
||||
|
||||
What makes a romantic player EXCITED about a new station: walking into the bar after twenty minutes of industrial corridors and going "oh. This is where the people are."
|
||||
|
||||
### What Makes a Backwater World Worth Visiting?
|
||||
|
||||
The lead directive says insignificant backwater worlds are valid. Not everything has to be dramatic. Good. I agree, and I want to push on WHY a backwater is interesting.
|
||||
|
||||
The generation sin for backwaters: **making them feel like unfinished stations.** A backwater that has all the same spatial types as a major hub, just smaller and sparser, is just a bad version of a hub. It's not interesting to visit. It's a station that failed.
|
||||
|
||||
A backwater is interesting when it's ENTIRELY itself. A place that has its own logic, its own completeness, even if that completeness is small. A farming settlement that's been here for 80 years and has exactly what it needs and nothing more. A research outpost where everyone knows everyone and the grey economy is someone swapping lab samples for home-cooked food. An orbital installation where the whole social world is twelve people and the investigation is necessarily intimate because there's nowhere to hide.
|
||||
|
||||
The generation win for backwaters: **density of human detail in a small space.** Because there are only 200 people, every one of them is legible. The cultural drift is highly visible. The political tensions are personal, not institutional. The history is SHORT but SPECIFIC — not "era stratification" but "that happened when Kira was still station manager, which was before the third growing season."
|
||||
|
||||
For the generator, backwaters need:
|
||||
- Small social site count (maximum 3-4)
|
||||
- But HIGH social entanglement — everyone is connected to everyone
|
||||
- A SINGLE dominant economic function that shapes everything (this is a farming world; the whole rhythm is agricultural)
|
||||
- Cultural ingredients that are strongly expressed because there's been no dilution
|
||||
- History that's recent enough to be personally remembered
|
||||
|
||||
The most interesting thing you can do in a backwater: become the ONLY outsider. Everyone else has been here for years. Your arrival is an event.
|
||||
|
||||
### What Makes Farmland or Ocean Interesting to Explore?
|
||||
|
||||
This is the one that worries me most, because the architecture as currently described is ENTIRELY built for interior urban spaces.
|
||||
|
||||
**Farmland:**
|
||||
|
||||
The generation sin for farmland: making it an empty field between interesting places. If farmland is just "low density of buildings, lots of open space, nothing happens here," players will skip it. They'll run through it to get to the next settlement.
|
||||
|
||||
Farmland is interesting when:
|
||||
- The LAND ITSELF is a character. What's growing? What does that tell you about who decided to grow it here and why?
|
||||
- There are SPATIAL SECRETS specific to farmland: irrigation systems that double as smuggling routes; storage facilities that are genuinely isolated; seasonal gathering points that only exist for two weeks a year
|
||||
- The scale contrast hits differently. Coming from a cramped station corridor into a field where you can see for 500 meters should feel PHYSICAL. The player's sense of their own observability changes completely
|
||||
- The people who work farmland are shaped by it. The schedule is agricultural. The culture is seasonal. The grey economy is what you do in the off-season when the money isn't coming in
|
||||
|
||||
The generator needs to produce AGRICULTURAL SPATIAL LOGIC: where the buildings cluster (near water, near roads, near each other for social life), why certain areas are left alone (flood risk, poor soil, someone's dispute), what the sight lines mean (a farmworker who can see for kilometers has a completely different relationship to surveillance than a dockworker in a corridor).
|
||||
|
||||
**Ocean / Beaches / Water:**
|
||||
|
||||
This is the most interesting challenge because water is the one geographic feature that genuinely changes the access topology grammar. You can't walk through it. You have to go around it, over it, or under it. That's a chokepoint that's NATURAL rather than institutional.
|
||||
|
||||
The ocean changes the game for EVERY playstyle:
|
||||
- The detective: maritime commerce is a different evidence type. Manifests are about ship cargo, not freight containers. Access topology includes the harbor, the dock authority, the tide schedule
|
||||
- The tycoon: maritime routes are a natural monopoly if you control the harbor infrastructure. The economic geography of a coastal settlement is DRAMATICALLY different from an inland one
|
||||
- The romantic: beaches and harbors are inherently liminal spaces — transitions between worlds. People are different near water. Social rules are looser. The romantic tradition of seaside encounters isn't an accident
|
||||
- The explorer: the horizon. The literal fact of being able to see the edge of the world from where you're standing. The visual grammar needs to produce HORIZON
|
||||
|
||||
The horizon is a Wow Moment the generator must not squander. A player who has spent their entire time in corridors and cargo bays and transit hubs who walks to the edge of a coastal settlement and sees ocean for the first time — that has to HIT. That has to be one of the big emotional beats of the game.
|
||||
|
||||
The generator needs to treat water's edge as a LANDMARK equivalent. Not a blank space. The edge of the world.
|
||||
|
||||
---
|
||||
|
||||
## The Edge Bleed Directive
|
||||
|
||||
The lead said: edge bleed between districts is a directive. No hard grid boundaries.
|
||||
|
||||
I want to stand up and cheer.
|
||||
|
||||
This is exactly what I meant by "historical palimpsest." Real places don't have clean edges. The residential district bleeds into the commercial district through a row of buildings that used to be housing and are now shops and haven't fully committed to either identity. The industrial zone has a bar in it because the workers needed somewhere to go and nobody was going to build a proper commercial zone next to a freight yard.
|
||||
|
||||
Edge bleed means the generator has to KNOW what it's blending. A residential/commercial edge is different from an industrial/maintenance edge. The visual grammar needs edge types the way it has zone types. "This chunk is 70% residential palette, 30% commercial palette, because it's the zone boundary and someone built a bakery here."
|
||||
|
||||
The emotional payoff: players will navigate BY the bleed zones. "I'm getting close to the port district, I can feel it — the buildings are changing." That's orientation through spatial reading. That's what makes a place feel REAL.
|
||||
|
||||
---
|
||||
|
||||
## Summary: What I'm Taking Into Round 3
|
||||
|
||||
**What's working:**
|
||||
- Miri's cultural ingredients system is the answer to Second Station Syndrome. Keep it.
|
||||
- Nigel's historical event seed is the answer to my historical palimpsest request. Keep it.
|
||||
- Araminta's settled principle and LOS anchor rule are anti-dead-space gold. Keep them.
|
||||
- Nigel's comparison test is the right success criterion. Keep it.
|
||||
|
||||
**What needs expanding:**
|
||||
- Gestalt's guarantees need to be reframed for ALL playstyles, not just investigation
|
||||
- The visual grammar needs a language for OUTSIDE — planetary surfaces, farmland, ocean
|
||||
- The generator needs to produce economic geography for tycoon gameplay (chokepoints, inefficiencies, political edges)
|
||||
- The generator needs to produce romance geography (third places, ritual gathering, earned privacy)
|
||||
- Backwaters need their own generation logic: small, dense in human entanglement, high cultural expression
|
||||
|
||||
**What I'm fighting for in Round 3:**
|
||||
- The grid must breathe. Non-rectilinear districts. Streets that curve.
|
||||
- The horizon must exist. When you can see the edge of the world, it must feel like something.
|
||||
- Backwaters must be complete, not failed hubs.
|
||||
- Every generation sin I named in Round 1 applies to EVERY playstyle, not just investigation. Dead space is dead space. Predictable secrets are predictable secrets. Whether you're tracking a smuggling ring or falling in love, you need the world to feel real.
|
||||
|
||||
The game is about asymmetric human awareness. That means the world must be WORTH being aware of, regardless of what you're trying to notice.
|
||||
@@ -0,0 +1,214 @@
|
||||
# Generator Architecture Workshop — Round 3: Ozzie
|
||||
|
||||
**Role:** Player Experience / Fan Perspective
|
||||
**Date:** 2026-02-27
|
||||
**Workshop:** Generator Architecture (#562)
|
||||
|
||||
---
|
||||
|
||||
## The Lead Said "Both." Now Prove It.
|
||||
|
||||
The lead mandated: some blocks grid, some organic chaos. That's the right answer. I'm not going to argue with the directive. What I AM going to do is describe what organic chaos FEELS LIKE from inside the game, so the team knows whether they've achieved it.
|
||||
|
||||
---
|
||||
|
||||
## 1. Grid Breathing — What Would Actually Convince Me?
|
||||
|
||||
Araminta gave me seven visual techniques to hide the grid: diagonal connectors, irregular setbacks, overhead elements crossing block edges, angled infrastructure, light territories, vegetation overflow, width variation. These are GOOD. I want all of them. But I need to be honest about what they actually do.
|
||||
|
||||
They hide the grid. They don't remove it.
|
||||
|
||||
A player who has been in five stations and five cities will develop spatial pattern recognition. Not consciously. They won't think "I see the 64m block structure." They'll think "this feels familiar." And they'll stop exploring as hard because some part of their brain is already mapping the space before they've seen it.
|
||||
|
||||
**What would actually convince me:**
|
||||
|
||||
Not straight streets. Not even diagonal streets. Streets that CURVE because the terrain required it. Streets that dead-end because someone built a wall across them. A block that's four-sided but not rectangular because it was wedged between two older streets that already existed. The block formed AROUND the streets, not the streets laid onto the blocks.
|
||||
|
||||
That's what organic chaos looks like. It's not "our grid has visual camouflage." It's "the generator's planning unit can acknowledge that geography PRECEDES grid."
|
||||
|
||||
**What I'd feel as a player:** I'd stop having a mental grid. Instead I'd have a mental web — this street goes roughly this way, and there's a building here that cuts across where I expected a street to be, and that alleyway I used before is definitely not where I thought it was. That disorientation is GOOD. It means I'm actually exploring, not filling in a pre-mapped skeleton.
|
||||
|
||||
**What the team needs to confirm:** Can the infrastructure stage, which runs before block planning, produce street networks that are NOT grid-aligned? Even partially? Even in one quadrant of a district? Because if streets can curve at the infrastructure stage, the blocks that fill between them will naturally be non-rectilinear. The anti-grid emerges from the sequence, not from visual techniques applied after the fact.
|
||||
|
||||
If the answer is "D-094 makes this architecturally hard," I want to hear that clearly. Then we decide together whether to defer, or whether we live with visual camouflage as our answer. But I need to know which one we're committing to.
|
||||
|
||||
---
|
||||
|
||||
## 2. The Destruction Fantasy
|
||||
|
||||
You've acquired a rocket launcher. You point it at a door. You pull the trigger.
|
||||
|
||||
What do you EXPECT to find on the other side?
|
||||
|
||||
Not "a reward." Not "the mission objective." Just — what does your body expect, before your brain gets involved? What is the PROMISE of a wall that can be broken through?
|
||||
|
||||
The promise is: something was hidden. Something worth hiding. The wall isn't a game mechanic — it's a secret keeper.
|
||||
|
||||
**When "nothing behind the wall" is acceptable:**
|
||||
|
||||
When the nothing IS the secret. You blew open a wall and found an empty maintenance crawl that smells like it was used recently. There's a scuff on the floor and a torn piece of fabric caught on a conduit. Nothing valuable. Evidence of someone. That's not nothing.
|
||||
|
||||
The generator produces a maintenance crawl behind that wall because maintenance crawls run behind things. But the wear marks and the fabric scrap — those are the historical event layer, the human detail layer, the layer that says "someone used this recently." Blank doesn't mean empty. Blank means unoccupied right now.
|
||||
|
||||
**When "nothing behind the wall" is a letdown:**
|
||||
|
||||
When what's behind the wall is geometrically identical to what was in front of it. You blow open a service corridor and find another service corridor that runs parallel to the one you were already in. Floors the same. Lights the same. Nothing different. Not even a story.
|
||||
|
||||
That's not a wall you were meant to break through. That's the generator tiling space without thinking about what it means when those tiles become accessible.
|
||||
|
||||
**The actual promise I'm making the generator:** Every space that can be accessed through destruction should be visually, spatially, or informationally distinct from the space that led to it. Even if it's empty. ESPECIALLY if it's empty. Because empty spaces tell stories through their emptiness. The empty room with a single chair facing the door tells a different story than the empty room with chairs knocked over and a broken light. The generator needs to produce meaningful emptiness.
|
||||
|
||||
**The generation sin for destruction:** Blank geometry. Walls as collision mesh rather than architectural history. The moment I blow through a wall and find a room with standard floor tiles and standard lighting and no evidence that anyone has ever been there — the immersion cracks. I'm in a game. I'm not somewhere.
|
||||
|
||||
**What I need from the generator:** When blocks are filled, is there a pass that considers "what if this space were accessed from an unexpected direction"? If every room is designed only from its intended access point, destruction reveals rooms that were never meant to be seen from the side. That's fine sometimes — a storage closet accessed from a blasted-open wall is a storage closet, and it looks like one, and that's correct. But the generator should be aware that its spaces will be seen from every angle, not just their intended entry. The historical detail layer (wear patterns, personal objects, evidence of use) needs to be present everywhere, not just near the official access points.
|
||||
|
||||
---
|
||||
|
||||
## 3. The Skyscraper Fantasy
|
||||
|
||||
You're standing at the base of a 50-floor building on a planet-side city. You look up.
|
||||
|
||||
I know this is a top-down game. I know you won't render the exterior of 50 floors. I'm asking what that MEANS as a player experience. What does vertical promise when you're always looking from above?
|
||||
|
||||
**What vertical actually gives you in a top-down game:**
|
||||
|
||||
Not the view up. The view DOWN. The moment you get to a high floor and can see the ground-level spaces from above — that's the payoff. You've been navigating through those spaces, and now you see the whole of them at once. The chokepoints you navigated by feel now visible as chokepoints by sight. The building you couldn't quite see the back of — there's the back. There's the alley you didn't know about.
|
||||
|
||||
The floor-above perspective is the detective's overview. It's the assassin's planning view. It's the tycoon seeing the whole market district. It's one of the best things a top-down game with vertical can do and I want to make sure we're designing FOR it, not accidentally getting it.
|
||||
|
||||
**What makes the skyscraper feel real:**
|
||||
|
||||
Every floor can't be the same. Floor 1 is public — retail, lobby, visible from street. Floor 5 has offices, different access rules. Floor 30 is where the building's ACTUAL business happens and has different security. Floor 50 is the executive level and it's emptier and more expensive and has windows looking out at the city. Each z-level is a narrative layer. The building is a social hierarchy expressed as architecture.
|
||||
|
||||
The generator needs to know that UPPER FLOORS COST. They're harder to reach, which means reaching them means something. The assassin who gets to floor 30 has earned the information asymmetry of height. The tycoon who gets a meeting on floor 50 has bought social access with their economic leverage. The floors aren't decoration. They're gates with views.
|
||||
|
||||
**Specific vertical surprises that matter:**
|
||||
|
||||
- **The service elevator that goes everywhere** while the public elevator has floors it skips. This is one of the most powerful space discoveries in any game. The servant's passage.
|
||||
- **The collapsed section** where floors 12-15 are inaccessible from the main stairwell because something happened there and nobody fixed it. But there's a maintenance route through floor 11 that still connects.
|
||||
- **The exterior balcony** where you can see the adjacent building's internal courtyard — a space you weren't meant to see from outside.
|
||||
- **The unexpected overlap** where two buildings share a floor because they were connected at some point and the connection was never fully removed.
|
||||
|
||||
**The generation sin for vertical:** Floors that are identical except for the access tier gate on the elevator. If every floor is the same zone palette, same furniture density, same template — just with different lock levels — then vertical is just a difficulty gate, not a spatial discovery. Each floor needs to tell you something new about the building and the people who use it.
|
||||
|
||||
---
|
||||
|
||||
## 4. The Assassin Fantasy
|
||||
|
||||
I want to play an assassin. Not a detective. Not a tycoon. Someone who needs to put a specific person in the ground and leave without being connected to it.
|
||||
|
||||
What does the generated world need to give me?
|
||||
|
||||
**What I NEED:**
|
||||
|
||||
**Sightlines from above.** Height equals safety for an assassin because it equals angles that defenders can't easily cover. The building that's three floors but has a section of roof that overlooks the target's regular lunch spot — that's a gift. The generator needs to produce height variation specifically in areas adjacent to social hubs. Not always. But sometimes. Often enough that I feel like I'm looking for it.
|
||||
|
||||
**Crowd cover.** I can't move through an empty corridor without being seen. I need the market district when it's busy. I need the shift change crowd flooding out of the logistics hub. I need mass human movement that I can dissolve into. The generator's temporal NPC density variation (D-031 integration mentioned in Gestalt's guarantees) is ESSENTIAL for assassin gameplay. If NPCs are uniformly distributed across all hours, every crowd is the same crowd. I need the 8pm market rush and the 3am empty corridors to be different game states.
|
||||
|
||||
**Approach distinct from escape.** This is my deepest need and probably the hardest to generate. I need to approach the target through one route and escape through a different one. If the district only has one logical way to reach the target location, I'm caught whether I succeed or fail. The generator must produce multiple-path topology that allows approach-via-one-path, escape-via-another as a spatial guarantee. This is Gestalt's Encounter Corridor archetype, but I need at least two of them pointing at every major social hub from different directions.
|
||||
|
||||
**Timing windows.** I'm not just looking for WHERE the target is. I'm looking for WHEN the target is somewhere without witnesses. The generator's daily rhythm system — the shift-based NPC schedules, the social hub peak hours — needs to create moments when specific NPCs are in specific places with reduced ambient traffic. I'm not asking the generator to write my assassination plan. I'm asking it to produce a world where those windows exist and can be discovered.
|
||||
|
||||
**The assassin generation sins:**
|
||||
|
||||
**Sin #1: Omnidirectional witness coverage.** If every location in the target's routine is surrounded by NPCs who would notice an incident from every angle, assassination is impossible without a social trust level I may not have. The generator must produce blind spots — structural, temporal, or social. Places and times where the math works for me.
|
||||
|
||||
**Sin #2: Escape routes that all converge.** One district entry/exit point defeats assassin gameplay. Even if I get the target clean, I'm identified at the only gate on my way out. The generator must produce districts with multiple access patterns — not just the official gate, but the maintenance exit, the neighboring district's connection, the emergency access that's technically locked but practically isn't.
|
||||
|
||||
**Sin #3: No vertical option.** A flat district is an assassin's nightmare. Every position is visible from adjacent positions. There's no height advantage. The cover is all horizontal. The generator needs to guarantee at least one elevated access point per district — a walkway, a second-floor balcony, a roof connection — that provides a different plane of sightlines.
|
||||
|
||||
**Sin #4: No crowd rhythm.** If the district is always equally busy, I can never rely on cover. If it's always equally empty, I'm always exposed. I need the district to have a SOCIAL CALENDAR that I can learn and exploit.
|
||||
|
||||
**What makes the assassin's game exciting:** The district is a puzzle I have to solve under time pressure without revealing that I'm solving it. And the puzzle changes every time because the target's schedule, the crowd timing, and the chokepoints all came from a seed. The assassin's gameplay is the detective's gameplay in reverse — instead of finding who did it, I'm designing a situation where what I did is undiscoverable.
|
||||
|
||||
---
|
||||
|
||||
## 5. Mobile Environments
|
||||
|
||||
You board a train. A ship. A spaceship. You're in motion.
|
||||
|
||||
What's the best version? What's the worst?
|
||||
|
||||
**The worst version:**
|
||||
|
||||
A rectangle. Chairs. Maybe a window. Nothing to do while you wait to arrive. The mobile environment as a loading screen with a bed in it. If the only reason to be on this train is to get to the other end of the track, then the train is a liability — it's time I'm spending not doing things, in a featureless box.
|
||||
|
||||
**What makes mobile environments actually exciting:**
|
||||
|
||||
THE SOCIETY IS COMPRESSED. On a train car, you have a cross-section of whoever was going the same direction on the same day. The dockworker and the corporate auditor and the family visiting relatives and the person who's clearly nervous about arriving. They're all stuck together. For a fixed duration. They can't leave.
|
||||
|
||||
This is a CRUCIBLE. The information that emerges in a compressed mobile space is different from what emerges in a fixed location because people are in transition — they're leaving one context and not yet in the next. They're between their roles. Someone going home from work is a different version of themselves than they are at work or at home. The train is where you catch people mid-transformation.
|
||||
|
||||
**For the investigation player:** The suspect is on this train. You have three hours before arrival to either find what you need or get close enough that arrival means something. Time pressure plus a bounded social space plus people in transitional psychological states — this is an investigation goldmine.
|
||||
|
||||
**For the romantic player:** You meet someone on the train. You have the journey. When you arrive, you might never see them again. The journey IS the relationship. The finite space creates intimacy.
|
||||
|
||||
**For the assassin:** Someone important is on this train and can't leave it. The closed environment is either a trap or an opportunity.
|
||||
|
||||
**For the tycoon:** The other passengers are future contacts, competitors, people who know things. The train car is a mobile networking event.
|
||||
|
||||
**What the generator needs to produce:** Mobile environments as distinct social worlds with their own rules. Not smaller versions of fixed locations. The train car has its own access topology (which seats are private, which are communal, where the conductor circulates), its own social norms (you don't talk to strangers unless the journey is long enough), its own timeline (approaching destination changes behavior).
|
||||
|
||||
**The ship crossing ocean:** Longer duration means deeper social development. The people on this ship have been together long enough that relationships have formed, tensions have built, small political structures have emerged. Arriving at port is a disruption of a miniature society. That's powerful.
|
||||
|
||||
**The spaceship between systems:** This should feel like the longest journey. The tightest social compression. The highest stakes — because whatever happens between departure and arrival, you can't get off. The information landscape on an in-transit vessel could be incredible. Secrets that only exist in the between-state, before arrival collapses them into the next destination's reality.
|
||||
|
||||
**The mobile environment generation requirement:** Time as a spatial dimension. The space is fixed; the SOCIAL STATE OF THE SPACE changes over the duration of the journey. The generator needs to produce not just the physical vessel interior but the social arc — who will have what conversation by the time you arrive, what tensions will have formed, what information will have surfaced. The journey is the content.
|
||||
|
||||
---
|
||||
|
||||
## 6. Not Every Place Is For You
|
||||
|
||||
You're an assassin. You arrive at a farming settlement. There's no obvious target. The rhythms here are agricultural. People are talking about harvest yields and drainage issues and someone's eldest daughter who left for the city.
|
||||
|
||||
Is this boring?
|
||||
|
||||
NO. And here's why.
|
||||
|
||||
**The mismatch is the content.** I am visibly wrong for this place. Every social interaction I have is filtered through "you're not from here." The assassin's toolkit — reading social hierarchies, finding the informal power structure, identifying who knows what — is ENTIRELY applicable to a farming settlement. The hierarchy here is different. The power is in land tenure and water access and who the community patriarch is. The secrets are different. The leverage is different.
|
||||
|
||||
But the SKILLS transfer completely.
|
||||
|
||||
**The farming settlement forces the assassin to slow down.** I can't rush through this space. I can't extract value quickly because I'm not trusted. The information I need is inside relationships I don't have yet. I have to EARN my way into the community's information landscape. And the community can TELL I'm in a hurry, which makes them trust me less.
|
||||
|
||||
This is actually harder for the assassin than the station district. The station district has strangers. I'm just another stranger. The farming settlement has known each other for thirty years. I'm the stranger. I'm the EVENT.
|
||||
|
||||
**What the "not every place is for you" experience produces:**
|
||||
|
||||
It makes me understand the world better. It makes me feel the social geography of this universe — that different places have different rules, and I can't apply the same playbook everywhere. A farming settlement IS NOT A FAILED STATION. It's a complete world with its own social architecture. The assassin who arrives here expecting a station and gets a community is confronting the reality that THIS IS WHAT THE UNIVERSE ACTUALLY CONTAINS.
|
||||
|
||||
The generation sin would be making the farming settlement too empty to have any social architecture at all. If there are four NPCs with nothing to say to each other, of course the assassin is bored. But if there's a complete small society — the family with the land dispute, the newcomer who married into the community, the elder who remembers when things were different, the teenager who wants to leave — then there's a social web the assassin can read and engage with on its own terms.
|
||||
|
||||
**What this means for the generator:** Complexity should scale with population and establishment, not with distance from the main narrative. A backwater farming settlement with 80 people who've been here for forty years should have a DENSER social graph per capita than a transit hub with 2000 transient workers. The drama isn't smaller. It's closer. It's personal.
|
||||
|
||||
**What the mismatch teaches the player:** That their playstyle is a lens, not a filter. The investigator doesn't find nothing at the farming settlement — they find a different KIND of mystery. The assassin doesn't have no targets — they find that "targets" here don't mean the same thing they mean in the city. The game is smarter than your playstyle. The playstyle is the starting assumption the world eventually corrects.
|
||||
|
||||
THAT is asymmetric awareness. Not "different players see different things." Players discover that what they were looking for is a simplification of a richer reality.
|
||||
|
||||
---
|
||||
|
||||
## Summary: What I'm Confirming, What I'm Still Fighting For
|
||||
|
||||
**Confirmed from Round 2 that I love:**
|
||||
- The two-phase generation. Background prep as district personality; on-demand as physical space. YES. The personality exists before I arrive; the physical manifestation of it generates as I move through it.
|
||||
- The flavor type → NPC pattern weight shift. Market stalls bring different people. That's social variation through spatial fill.
|
||||
- The era_cause fields. LShape buildings with a recorded reason for their shape. Historical palimpsest achieved.
|
||||
- The 7 universal spatial archetypes. Every playstyle finds the space it needs. Confirmed.
|
||||
- The `ComplexityTier` — gameplay guarantees only for Full. A farmland district doesn't need a surveillance chokepoint. Correct.
|
||||
|
||||
**Still fighting for:**
|
||||
- The grid breathing answer. Araminta's seven techniques are good camouflage. I want to know if the streets can curve at the infrastructure stage. Give me that answer in the D-record.
|
||||
- The horizon as a mandatory landmark reservation. Not just a visual palette. An actual generator slot that says "this district has a water edge and the water edge is a discovery moment."
|
||||
- Destruction revealing meaningful spaces. The historical detail layer needs to cover the whole space, not just the intended entry paths.
|
||||
- Mobile environments as time-compressed social worlds, not loading screens with chairs.
|
||||
|
||||
**New principles I'm proposing for the D-record:**
|
||||
|
||||
1. **Every space is seen from every angle, not just its intended entry.** Destruction and vertical access reveal spaces from unexpected directions. The detail layer must be uniform.
|
||||
2. **The playstyle is the starting assumption the world eventually corrects.** Mismatch between player expectation and settlement type is content, not failure.
|
||||
3. **The horizon is a generated landmark.** Water's edge is reserved at district planning, not incidental.
|
||||
4. **Mobile environments have a social arc, not just a physical interior.** The journey is content; the space changes state over time.
|
||||
|
||||
---
|
||||
|
||||
*I have loved this workshop. This team is building something real. Don't let it just be a detective game with extra rooms. Make it a world.*
|
||||
@@ -0,0 +1,191 @@
|
||||
# Generator Architecture Workshop — Round 4 (Final): Ozzie
|
||||
|
||||
**Role:** Player Experience / Fan Perspective
|
||||
**Date:** 2026-02-27
|
||||
**Workshop:** Generator Architecture (#562)
|
||||
|
||||
---
|
||||
|
||||
## The Fan's Verdict
|
||||
|
||||
I've read the notes. Three rounds of brilliant people building something real. Now you need me to close the loop as the PLAYER. No more open questions. Here are my verdicts.
|
||||
|
||||
---
|
||||
|
||||
## OQ-R4-A: The Vessel Question — My Verdict
|
||||
|
||||
**YES. Vessels must persist as world entities. Tyre's model wins.**
|
||||
|
||||
Let me tell you exactly why, from the player's gut.
|
||||
|
||||
You arrive at a coastal spaceport. You came on a ship. You disembark. You walk out into the port district. And somewhere behind you, there's a berth.
|
||||
|
||||
**Is the ship still there?**
|
||||
|
||||
YES. It has to be there. Not because of architecture. Because of BELIEF.
|
||||
|
||||
If I walk back toward the dock and the berth is empty — or worse, if there's a *different* ship there — something breaks. The world revealed itself as a stage set. The journey I just lived wasn't real. It was a content module that got unloaded when I was done with it. The crew I got to know doesn't exist anymore. The cabin where I found the incriminating letter is gone. The suspicious passenger I was watching during the crossing — dissolved.
|
||||
|
||||
This game is built on asymmetric information. It's built on the idea that things are REAL and I have incomplete access to them. The moment a ship dissolves when I leave it, that premise collapses. If the world only exists where I'm looking at it, I can't trust anything I know about it.
|
||||
|
||||
**The ship at the dock is a trust signal.** It tells me: this happened. That voyage was a real event in a real world. The people on that ship still exist somewhere. The things that occurred during the crossing had consequences that are still active.
|
||||
|
||||
For the investigation player especially: evidence from the journey might require going BACK to the ship. A name I heard, a face I saw, something in a cabin I didn't get a good look at — the ship being there means that thread is still pullable.
|
||||
|
||||
For the assassin: the target was on the ship. The ship is still docked. The target hasn't been able to leave yet because the connecting transport isn't until tomorrow. THE SHIP BEING THERE IS THE CONTINUATION OF THE CONTRACT.
|
||||
|
||||
For the romantic: the person you met is still on the ship, packing their bags, and you have a window.
|
||||
|
||||
**What "persist" actually means:**
|
||||
|
||||
The ship doesn't need to be frozen in the exact state I left it. Cabins get cleaned. Cargo gets moved. But the SHELL is there and the CREW is there and the DEPARTURE SCHEDULE is real. The ship stays at dock until its schedule says it leaves. Then it's gone — legitimately, procedurally gone, because it sailed. That's different from "it dissolved when the player stepped off."
|
||||
|
||||
The architectural cost is real. Nine-and-a-half dev-days versus Nigel's cheaper solution. That cost is worth it because the vessel persistence is load-bearing for the game's fundamental promise: this is a real world, not a sequence of content modules.
|
||||
|
||||
**Verdict: MobileChunk as entity-carried world entity. Tyre's model. Not negotiable.**
|
||||
|
||||
One addendum: the generator must also produce departure windows. Mobile environments that persist at dock without departure schedules turn every port into a ship graveyard. The vessel arrives, docks for N hours or days based on its route and cargo, and departs. That departure schedule is part of the world — and it creates URGENCY for players who want to get back on board.
|
||||
|
||||
---
|
||||
|
||||
## OQ-R4-F: Does Destruction Feel Caused? — My Verdict
|
||||
|
||||
**Not yet. XOR-seeded regeneration alone is not enough.**
|
||||
|
||||
Here's the test I'd run as a player:
|
||||
|
||||
I arrive in a district after the gas explosion event. I walk in from the east side. What do I see?
|
||||
|
||||
If XOR seeding produces random variation — meaning the worst damage could be anywhere, rooms near the source might be pristine, rooms far away might be rubble — then what I experience is *different*, not *caused*. I can't point to where it happened. I can't understand it as an event. It's just: this district now looks like this.
|
||||
|
||||
**That fails my principle.** Destruction must be caused. The player must be able to read the aftermath and understand the event that produced it. The epicenter should be identifiable. The damage gradient should radiate outward. The structural logic should be visible: load-bearing walls that faced the blast collapsed; walls behind other walls are intact; the roof went first in the affected zone; the floor is scorched concentrically.
|
||||
|
||||
XOR-reseeding produces variation. It doesn't guarantee that the variation is *spatially coherent with the event source.*
|
||||
|
||||
**What I need:** Constrained soft re-generation, not pure XOR. The event has:
|
||||
- A source location (specific tile or zone)
|
||||
- A damage type (blast, fire, flood, collapse)
|
||||
- An intensity (moderate, severe, catastrophic)
|
||||
|
||||
The re-generation should be parameterized by these. The seed varies, but the variation is *bounded by event physics.* Rooms adjacent to the explosion source always show blast damage. Rooms two districts away from a flood show water line staining, not fire damage.
|
||||
|
||||
Araminta's five visual stages (Active → Fresh Aftermath → Stabilized → Reconstruction → Healed Scar) are the right temporal vocabulary. But they need to be applied with spatial gradient from the source, not uniformly across the district.
|
||||
|
||||
**Practically:** I'm not asking for a full physics simulation. I'm asking for: when the event is generated, it stamps an epicenter and a radius. Everything within that radius gets heavy modification. Everything in the ring outside gets lighter modification. Everything beyond that is atmospheric (NPCs talking about it, smoke visible on the horizon, minor debris at the edge). The XOR seed varies the details within each zone; the zones themselves are determined by event parameters.
|
||||
|
||||
**The gap between "different" and "caused" is the difference between a world with history and a world with random states.**
|
||||
|
||||
If you can show me a gas-explosion district where I can stand at one point, look around, and say "IT HAPPENED HERE" — then the destruction feels caused. If I'm guessing, it's not there yet.
|
||||
|
||||
---
|
||||
|
||||
## Rooftop Bar — My Verdict
|
||||
|
||||
**Sometimes a bar. The variety is the point.**
|
||||
|
||||
The guarantee says tall building rooftops must be Insider or BreachOnly. A rooftop bar IS Insider — you have to know it exists and find the access. So the guarantee doesn't conflict with this. It just means the rooftop discovery can be EITHER.
|
||||
|
||||
Here's what I want as a player:
|
||||
|
||||
**Most rooftops I find:** Maintenance access. Equipment arrays. Maybe a view. The reward is the vantage point — you've earned height, and height gives you the overview. That is its own payoff.
|
||||
|
||||
**Some rooftops I find:** IT'S A BAR. Someone put tables up here. There are people. There are drinks. There's ambient sound. There's the WHOLE CITY VISIBLE BELOW and someone chose this as the place to be social. The contrast with the maintenance-access rooftop makes this more exciting, not less. If every rooftop were a bar, it would be expected. It's the RARITY that creates the "oh" moment.
|
||||
|
||||
**The discovery experience:**
|
||||
|
||||
Finding a restricted rooftop: tactical satisfaction. I got somewhere most people can't. The view is mine.
|
||||
|
||||
Finding a rooftop bar: social disruption. I came up here expecting to be alone with the view and found a SCENE. Suddenly this is an information space — who's up here? Why here? Who chose this location for this social event? What conversations are happening above the city that can't happen on the street?
|
||||
|
||||
The rooftop bar is a generator surprise — it tells me the world is richer than I expected. It breaks my assumptions about what "high floors = restricted" means. Some high floors are restricted because they're exclusive. Some are restricted because they're operational. Some are restricted because they're explicitly SOCIAL and you weren't invited.
|
||||
|
||||
**Verdict:** Generator should produce a minority of rooftops as Insider social spaces (bars, gardens, event venues). Not a specific percentage — just "some." The guarantee system says the roof exists and is Insider or BreachOnly. The content type is generator variation. Rooftop bars exist. They're not common. Finding one is a moment.
|
||||
|
||||
---
|
||||
|
||||
## Fan Validation: All 12 D-Ready Items
|
||||
|
||||
Reading these as a player. Does anything sound wrong? Does anything excite me? Is anything missing?
|
||||
|
||||
**1. DistrictLayoutMode — Grid and Organic**
|
||||
EXCITING. The city that grew vs the city that was planned. I want to feel the difference when I arrive. Grid tells me who's in charge here. Organic tells me how long this place has been here. I will feel this.
|
||||
|
||||
**2. Guarantee Tier System**
|
||||
Not exciting, but ESSENTIAL. Without this the generator is just hoping. With this the generator is promising. I want the generator to make promises it keeps.
|
||||
|
||||
**3. TrianglePurpose Enum with Tactical**
|
||||
YES. The tactical triangle (Target + Protector + Informant) is the assassination contract made spatial. This is what it looks like to generate "I have a contract here." The world knows there's a target before I do. The generator already made the triangle. I'm just discovering its shape.
|
||||
|
||||
**4. WallBackside / TileBehindState with BreachOnly**
|
||||
EXCITING. Every wall is now a promise. The ServiceVoid specifically — the conduit space between walls — is one of the most game-feeling things I've heard in this workshop. A space that's only accessible by going through walls? That is IMMERSIVE SIM. That is "I found a way that wasn't meant to be found."
|
||||
|
||||
**5. Dynamic Modification via Overlay**
|
||||
Correct and essential. But I want to note: the world having a generator state and a delta layer means the world has HISTORY. Not just current state. The delta layer is the record of what has happened since generation. That is incredibly powerful for investigation — you can read the delta and infer events. This is one of the best architectural decisions in the entire workshop.
|
||||
|
||||
**6. ZonePalette Modifier System**
|
||||
Good. Mostly invisible to me as a player but I'll feel it as "this farmland looks different from that farmland." I trust the team to make the combinations interesting.
|
||||
|
||||
**7. Horizon View Corridor**
|
||||
I fought for this in Round 2 and I'm glad it made the D-ready list. The mandatory water-edge viewing moment is NON-NEGOTIABLE. It is one of the primary Wow Moments. A coastal district without a clear line of sight to water is a failure mode. The reservation prevents this.
|
||||
|
||||
**8. Assassin Lens Spatial Guarantees (A-1 through A-4)**
|
||||
HELL YES. These are promises to me. The generator is promising: there will be an elevated position. There will be multiple egress routes. There will be a timing window. There will be a path that doesn't cross high security. These aren't design preferences. These are contract terms. The assassin player signed a contract with the generator and the generator will honor it.
|
||||
|
||||
**9. Heritage Grammar Overlay for Non-Urban Palettes**
|
||||
Exciting in the way deep systems are exciting — I may not consciously notice it, but I'll feel it. A Tide-heritage fishing village is arranged differently than a Frost-heritage logging settlement. That's cultural legibility in space. I want to arrive somewhere and feel the specific history of it.
|
||||
|
||||
**10. Non-Urban Informal Zone Typology**
|
||||
Important but mostly felt through gameplay rather than seen directly. The key insight — what happens on the boat is the crew's business — is the kind of rule I'll feel as a player when I realize I've been having conversations in a zone where there are no institutional consequences. That's very powerful for information gathering.
|
||||
|
||||
**11. Vertical Scale Architecture**
|
||||
VERTICAL IS THE GAME. Everything Gestalt and Tyre built here — z-bands, lazy loading, the access tier gradient, the mandatory discovery zone at the roof — this is the immersive sim in architectural form. The building that is itself a puzzle. Floor 30 having information that floor 1 can't have because floor 30 is harder to reach. YES. All of this.
|
||||
|
||||
**12. Trauma Events as EraModification Subtypes**
|
||||
Essential for history. The delta layer + the trauma subtypes together mean the world can have scars with specific causes. I can arrive at a district and read what happened to it — not just "this place is damaged" but "this place had a violence event and the heritage root of its population is showing me exactly how they responded." That's asymmetric awareness applied to history.
|
||||
|
||||
---
|
||||
|
||||
## What's Missing — Things That Would Make Me Feel Incomplete
|
||||
|
||||
Two things I don't see in the 12 D-ready items that I believe need to be added:
|
||||
|
||||
**Missing 1: The Departure Schedule Model**
|
||||
|
||||
If vessels persist at dock (my verdict above), the generator needs to produce departure windows. Not just "the ship is there" — but "the ship is there for 36 hours and then it leaves." The departure schedule is part of the world's temporal structure. It creates natural urgency. It means the player decision to re-board (or not) has a deadline. Without departure schedules, ports become ship graveyards and the vessel persistence loses its urgency.
|
||||
|
||||
This may already be implied somewhere in Miri's transit social grammar, but I didn't see it stated as a generator output. It needs to be.
|
||||
|
||||
**Missing 2: The Mobile Environment Social Arc**
|
||||
|
||||
I named this in Round 3 and it still isn't in the D-ready list. Miri's transit social modifier is a fantastic cultural grammar. But the JOURNEY itself — who talks to whom, what information surfaces at what point in the crossing, what tensions emerge as arrival approaches — needs a structural representation.
|
||||
|
||||
Not complex. Just: the mobile environment has a timeline. Certain events are seeded to occur at certain journey-stages. The passenger manifests are generated at journey-start. But the social arc — what changes about those passengers' relationships by the time you arrive — needs to be a generator output, not an emergent accident.
|
||||
|
||||
The journey is the content. If the social arc isn't structured, the content is random rather than authored. I want to know: by hour 6 of a 12-hour crossing, what was this generator PLANNING to have happen? That plan is the social arc.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
The generator is almost there. What excites me:
|
||||
|
||||
- The world is real and persistent (Tyre's vessels win)
|
||||
- Every wall is a secret keeper (WallBackside + BreachOnly)
|
||||
- Destruction has history (delta layer + trauma events)
|
||||
- Height has meaning (vertical scale + view down)
|
||||
- Every playstyle has guaranteed affordances (the audit system)
|
||||
- The journey is content (mobile environments as social pressure cookers)
|
||||
|
||||
What I'm still watching:
|
||||
|
||||
- Soft re-generation needs event parameters, not just XOR seeds — destruction must look caused
|
||||
- Departure schedules need a D-record
|
||||
- The mobile environment social arc needs a D-record
|
||||
|
||||
The 12 items are good. Add the two missing ones and this generator is making promises worth keeping.
|
||||
|
||||
**THAT is the game. Build it.**
|
||||
|
||||
---
|
||||
|
||||
*Round 3 closing note stands: Don't let it just be a detective game with extra rooms. Make it a world. We're closer than we were. This round is proof.*
|
||||
@@ -0,0 +1,46 @@
|
||||
# Generator Architecture Workshop — Round 5 (Final Review): Ozzie
|
||||
|
||||
**Role:** Player Experience / Fan Perspective
|
||||
**Date:** 2026-02-27
|
||||
**Workshop:** Generator Architecture (#562)
|
||||
|
||||
---
|
||||
|
||||
## Sign-Off
|
||||
|
||||
The outcomes document is good. "What This Generator Promises the Player" uses my language, captures my principles, and would make me want to play this game. The vessel persistence verdict is correctly stated. The XOR prohibition is correctly grounded — epicenter + radius + intensity means the damage radiates from a specific point, which is exactly the "IT HAPPENED HERE" test. The section reads like a generator that keeps its promises.
|
||||
|
||||
**I sign off on:**
|
||||
- "What This Generator Promises the Player" — correct and exciting
|
||||
- L-4 (entity-carried MobileChunk, vessels persist) — correct verdict
|
||||
- L-7 (XOR prohibited, DamageOverlay mandatory) — correctly stated, correctly reasoned
|
||||
- All 14 D-ready items — the player experience dimension is correctly captured on all of them
|
||||
- The NPC model (10 axes + Ysabel Vorn litmus test) — the one-NPC-five-lenses proof works
|
||||
- Departure schedules captured in D-READY-13 — correct
|
||||
- Mobile social arc in Q-NNN-c — correct to flag for sprint
|
||||
|
||||
---
|
||||
|
||||
## One Correction
|
||||
|
||||
**D-READY-11 (Vertical Scale) — Rooftop Bar Clause:**
|
||||
|
||||
Current text: *"Heritage root determines which config is assigned."*
|
||||
|
||||
This is wrong. Heritage root should INFLUENCE the probability — not determine the assignment.
|
||||
|
||||
If heritage root fully determines whether a rooftop is a bar or restricted, then experienced players can predict rooftop type from street-level observation. They'll learn: Tide buildings have bars, Frost buildings are restricted. The discovery moment dies. Finding a rooftop bar stops being a surprise and becomes recognition.
|
||||
|
||||
Suggested fix: *"Heritage root weights the probability distribution between `Restricted` and `PublicWithHiddenLayer`, but the final config is seeded per-building. A minority of buildings of any heritage root must be configurable as the non-dominant type."*
|
||||
|
||||
This preserves: the cultural tendency (Tide communities tend toward public rooftop spaces), while allowing: the seeded exception that makes discovery real (a Frost-heritage warehouse with a secret rooftop bar is more memorable than a Tide-heritage café with one because you didn't expect it).
|
||||
|
||||
The discovery layer mandatory in both cases — that part is correct. Keep it.
|
||||
|
||||
---
|
||||
|
||||
## Nothing Else to Flag
|
||||
|
||||
The document is structurally sound from a player experience perspective. No other descriptions read as "technically correct but emotionally flat." The generation sins I named across all four rounds are either guaranteed-against or explicitly flagged. The assassin's contract (Tactical triangles + A-1 through A-4) is in writing. The world is real. The walls are secret keepers. The destruction has an epicenter.
|
||||
|
||||
**Build it.**
|
||||
@@ -0,0 +1,344 @@
|
||||
# Generator Architecture Workshop — Round 1 Notes
|
||||
|
||||
**Compiled by:** Qatux (Documenter)
|
||||
**Date:** 2026-02-27
|
||||
**Source files:**
|
||||
- `docs/workshops/generator-architecture/gestalt-round1.md`
|
||||
- `docs/workshops/generator-architecture/tyre-round1.md`
|
||||
- `docs/workshops/generator-architecture/miri-round1.md`
|
||||
- `docs/workshops/generator-architecture/araminta-round1.md`
|
||||
- `docs/workshops/generator-architecture/nigel-round1.md`
|
||||
- `docs/workshops/generator-architecture/ozzie-round1.md`
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Round 1 produced six independent domain assessments of the generator architecture. Despite writing without cross-referencing each other, participants arrived at strong consensus on the pipeline model and the role of authored templates. The primary open tensions are in pipeline stage ordering, the depth of variation the quarter system will actually deliver, and the question of whether cultural variation translates mechanically (or remains decorative).
|
||||
|
||||
---
|
||||
|
||||
## Section 1: Consensus Points
|
||||
|
||||
### C-1: The Pipeline Model
|
||||
|
||||
All participants implicitly or explicitly accepted the Cities Skylines top-down pipeline as the working model:
|
||||
|
||||
```
|
||||
Geography
|
||||
→ Infrastructure (transport, utilities, Meridian coverage)
|
||||
→ Amenities & Services (social site type selection)
|
||||
→ Population (NPC density, entanglement seeding)
|
||||
→ Zoning (access tier assignment per zone)
|
||||
→ Block Generation (chunk merge strategy, multi-block reservations)
|
||||
→ Chunk Fill (D-025 template instantiation, sub-chunk quarters, NPC placement)
|
||||
```
|
||||
|
||||
**Sources:** Gestalt §3, Miri §5, Nigel §2, Tyre §5.3 pipeline table.
|
||||
|
||||
Each participant mapped their domain to this pipeline and found it accommodated their requirements without modification. No participant proposed a different top-level structure.
|
||||
|
||||
---
|
||||
|
||||
### C-2: Spatial Hierarchy (Confirming D-094)
|
||||
|
||||
All technical discussion respected the four-level hierarchy without question:
|
||||
|
||||
| Level | Sim tiles | Visual tiles | Physical | Role |
|
||||
|-------|-----------|--------------|----------|------|
|
||||
| Chunk | 64×64 | 32×32 | 32m | Streaming + serialization unit |
|
||||
| Block | 128×128 | 64×64 | 64m | Generator planning unit (4 chunks) |
|
||||
| District | 512×512 | 256×256 | 256m | Template composition unit (16 blocks) |
|
||||
| Quarter | 32×32 sim | 16×16 visual | 16m | **Fill-time constraint only — not a hierarchy level** |
|
||||
|
||||
The quarter clarification is important: Tyre stated explicitly that quarters are a generation-side layout concept, invisible to the runtime after fill. The server sees tiles; quarters exist only during the generation pass. Araminta and Nigel both accepted this framing.
|
||||
|
||||
**Sources:** Tyre §1.4, §4.4; Araminta §2.1; Nigel §3.
|
||||
|
||||
---
|
||||
|
||||
### C-3: "Templates Are Authored; Placement Is Generated"
|
||||
|
||||
Stated independently by three participants in nearly identical terms:
|
||||
|
||||
- Tyre: "D-025 templates are authored. Skeleton placement is generated. The generator arranges templates, not tiles."
|
||||
- Miri: "D-025 templates are bricks. The district skeleton is the architectural plan. The generator writes architectural plans from ingredients; human authors craft the bricks. The generator never touches the bricks themselves."
|
||||
- Gestalt: "The generator places the slots; templates fill them."
|
||||
|
||||
This principle governs the generator's relationship to the entire D-025 social site library. It is the mechanism that preserves hand-authored content quality while enabling procedural arrangement.
|
||||
|
||||
**Sources:** Tyre §2.3, Miri §5 (Q-036 reconciliation), Gestalt §3.
|
||||
|
||||
---
|
||||
|
||||
### C-4: District Skeleton as Atomic Generator Output (Q-036 direction)
|
||||
|
||||
Strong convergence: the district skeleton is the generator's primary compositional output. Tyre proposed a concrete Rust data structure (`DistrictSkeleton`). Miri endorsed the skeleton concept with a complementary description of its contents (society profile → social site slots + spatial positions + access topology + NPC capacity + triangle assignments). Gestalt mapped each of its seven spatial guarantees to specific fields of the skeleton.
|
||||
|
||||
No participant proposed an alternative atomic unit.
|
||||
|
||||
**Sources:** Tyre §2, Miri §5 (Q-036 reconciliation), Gestalt §2 and summary table.
|
||||
|
||||
---
|
||||
|
||||
### C-5: Grey Economy as Negative Space in the Generator
|
||||
|
||||
Three participants independently required the generator to model what official zoning does NOT account for:
|
||||
|
||||
- Gestalt (Guarantee 2): Every district must have at least one zone with `meridian_coverage: degraded` or `minimal` — explicitly generated, not incidental.
|
||||
- Miri: "The grey economy occupies the spaces that official zoning doesn't account for. The generator must model what's NOT in the official map — which corridors are maintenance-only, which zones have dead spots, which blocks have unofficial access routes. This is not flavor; it's where the investigation happens."
|
||||
- Ozzie: "A place I'm not supposed to be" is a non-negotiable player experience requirement. Spaces that "feel like I wasn't meant to find it."
|
||||
|
||||
Araminta adds a visual corollary: maintenance/service zones must always have at least one empty quarter per block of service access type, and the dark/sparse visual treatment that distinguishes them.
|
||||
|
||||
**Sources:** Gestalt §2 Guarantee 2, Miri §5 point 4, Ozzie "What I Need" §2, Araminta §3.2.
|
||||
|
||||
---
|
||||
|
||||
### C-6: Cultural Variation Must Produce Mechanical Variation
|
||||
|
||||
All six participants required that the society profile parameters (Q-032's six categories) translate into gameplay outcomes, not just aesthetics:
|
||||
|
||||
- Miri: "If cultural variation doesn't translate to mechanical variation... then 300 distinct cultural profiles produce only the illusion of variety."
|
||||
- Gestalt: Cultural variation produces "different investigation difficulty, specific NPC behavior patterns, and specific contraband moral texture."
|
||||
- Nigel: The cultural layer "has the highest variety payoff per authored ingredient" and trust-building timelines, access tier thresholds, and NPC pattern distributions must all vary by culture.
|
||||
- Ozzie: "If the generator is just varying layout geometry and art themes, the 50th station is just the 50th palette swap. If it's varying the SOCIAL AND POLITICAL TEXTURE — who's in charge, what they want hidden, what grudges are still warm — then I will happily explore the 100th."
|
||||
|
||||
The mechanism: `privacy_level` and `trust.building_rate` are the key translation parameters (Miri). Cultural parameters feed NPC behavior systems; they cannot be a pure naming/art variable.
|
||||
|
||||
**Sources:** Miri §1 and §4, Gestalt §3 amenities stage, Nigel §2 Stage 3, Ozzie "What Makes the 50th Station Exciting."
|
||||
|
||||
---
|
||||
|
||||
### C-7: Transit District as Generator Validation Fixture
|
||||
|
||||
Two participants independently proposed expressing the v0.1 Transit District (D-093) as generator output to validate the schema:
|
||||
|
||||
- Tyre §5.4: "Express the v0.1 Transit District as a hand-authored DistrictSkeleton + hand-authored ChunkData for each of its 64 chunks." This validates the schema, creates a test fixture, and validates the content pipeline.
|
||||
- Gestalt §5 (Q-C): Proposed the "minimum viable district" — 1 workplace, 1 bar, 1 maintenance spine, 1 transit node, 1 restricted zone, 2 active triangles — as the minimum that satisfies all seven spatial guarantees.
|
||||
|
||||
These are complementary: Tyre's is a schema validation exercise; Gestalt's is a gameplay completeness check. Together they form a complete validation plan for the generator's district output format.
|
||||
|
||||
**Sources:** Tyre §5.4, Gestalt §5 Q-C.
|
||||
|
||||
---
|
||||
|
||||
## Section 2: Open Questions (for Round 2)
|
||||
|
||||
### OQ-1: Pipeline Stage Ordering — Population Before or After Zoning?
|
||||
|
||||
**The tension:** Gestalt says NPC secrets must have plausible staging grounds before NPCs can be validly generated, creating a feedback loop between Population and Zoning. Miri places template instantiation at the district skeleton stage (after Zoning, before Block Generation). Tyre's pipeline table places NPC Population as the last stage (v0.3+), after Chunk Fill.
|
||||
|
||||
These three descriptions are not fully compatible. The ordering of Population relative to Zoning and Block Generation is unresolved.
|
||||
|
||||
**Gestalt's position:** Population follows zoning for assignment, but population requirements constrain zoning (feedback loop required).
|
||||
**Miri's position:** Triangle assignments happen at the district skeleton stage, after zoning but before block generation.
|
||||
**Tyre's table:** NPC Population is last — a v0.3+ implementation concern.
|
||||
|
||||
**For Round 2:** Tyre needs to address whether the feedback loop Gestalt describes creates implementation complexity. Can the skeleton stage partially resolve NPC type requirements (without full NPC generation) to guarantee spatial staging grounds exist?
|
||||
|
||||
**Raised by:** Gestalt Q-A; Miri §5 "when D-025 templates get instantiated"; Tyre §5.3 pipeline table.
|
||||
|
||||
---
|
||||
|
||||
### OQ-2: Seed Architecture — Single Master Seed or Per-Stage Seeds?
|
||||
|
||||
Nigel asks explicitly: "Is it a single master seed that derives all sub-seeds deterministically, or does each stage have its own seed parameter? I need to know whether 'same seed, different character selection' produces the same world with different lenses, or genuinely different worlds."
|
||||
|
||||
Tyre mentions determinism (D-010) but does not address how the seed propagates through stages.
|
||||
|
||||
**Stakes:** If same seed + different character = same world with different lenses, then character choice is a filter on the same information space. If same seed + different character = different worlds, the seed architecture is more complex and the reproducibility requirement (Q-030) more demanding.
|
||||
|
||||
**For Round 2:** Tyre to specify seed propagation architecture.
|
||||
|
||||
**Raised by:** Nigel §1 Guarantee 3, §7; Tyre §5.3 (mentions determinism, not seed propagation).
|
||||
|
||||
---
|
||||
|
||||
### OQ-3: Can the Quarter System Produce Social Variation, Not Just Visual Variation?
|
||||
|
||||
Ozzie raises this directly: "Does the choice of what fills a quarter have downstream consequences — does a garden quarter mean something different about who lives nearby versus a shack quarter? If the quarters are just aesthetic choices, I'll see through them on the second station."
|
||||
|
||||
Nigel endorses the quarter system as a replayability engine (§3) but focuses on physical geometry variation (chokepoints, routes). Ozzie wants to know if the fill type has social meaning.
|
||||
|
||||
**The question for Round 2:** Does the flavor structure assignment in unclaimed quarters (Nigel §4) feed back into NPC generation? A "market stall" quarter should presumably attract different NPC types than a "Commission kiosk" quarter. Is that dependency in the generator's data flow?
|
||||
|
||||
**Raised by:** Ozzie "Quarter System" section; Nigel §4.
|
||||
|
||||
---
|
||||
|
||||
### OQ-4: Historical Palimpsest — Can the Generator Produce Layered History?
|
||||
|
||||
Ozzie's most demanding requirement: "Can it make stations that feel like they were built in layers by different people with different plans?" She distinguishes CAUSED irregularities (this building is L-shaped because something made it this way) from RANDOM irregularities (the RNG said so).
|
||||
|
||||
Miri's era-stratification system (Era 1/2/3) and historical event modifier pass are the proposed technical mechanisms. Nigel proposes historical events as a seed modifier leaving "physical traces."
|
||||
|
||||
**The unanswered question:** What specific causal relationships does the generator encode? When the generator produces an L-shaped building, does it record WHY that shape exists, and can that reason surface as environmental storytelling? Or is the L-shape purely geometric, with the player inventing the reason?
|
||||
|
||||
**Raised by:** Ozzie "Hand-Crafted vs Obviously Procedural"; Miri §2 "Historical events"; Nigel §5 Layer 4.
|
||||
|
||||
---
|
||||
|
||||
### OQ-5: Society Profile YAML as Serde-Compatible Schema
|
||||
|
||||
Miri asks Tyre directly: "Can the content pipeline consume the society profile YAML format (from wiki-review R4) as a serde-compatible schema? The parameter depth is significant."
|
||||
|
||||
This is a technical feasibility question. The society profile has six categories, with blend weights, NULL states, and nested parameters. It needs to be consumable by the Rust pipeline.
|
||||
|
||||
**Raised by:** Miri §5 "For Tyre."
|
||||
|
||||
---
|
||||
|
||||
### OQ-6: Era Stratification in Chunk Data Structure
|
||||
|
||||
Miri asks Tyre: "How does era-stratification map onto the chunk data structure? The Z-level model (D-093) is confirmed, but does the chunk system have era fields?"
|
||||
|
||||
Tyre's `DistrictSkeleton` has a `zone_palette: Vec<ZoneDefinition>` field, which presumably could carry era tags. But this is not made explicit in Tyre's Round 1. Araminta's visual rules depend heavily on era tags being present at block level before chunk fill runs.
|
||||
|
||||
**Raised by:** Miri §5 "For Tyre"; Araminta §1.3.
|
||||
|
||||
---
|
||||
|
||||
### OQ-7: Size of the Cultural Ingredients Space
|
||||
|
||||
Nigel asks Miri: "How large is the cultural ingredients space? (Q-032 specifics.) The variety payoff of the cultural composition layer depends entirely on how many distinct ingredient combinations produce distinguishable district personalities."
|
||||
|
||||
Miri provides a conservative estimate ("comfortably exceeds 300 meaningfully distinct societies") but does not enumerate the combination count. Nigel's own calculation (300 worlds × 2 characters × 20 distinct cultural compositions = 12,000 meaningfully distinct games) depends on the "20 distinct compositions" assumption, which may be conservative or generous.
|
||||
|
||||
**Raised by:** Nigel §7; Miri §1 "How 300 worlds get variety."
|
||||
|
||||
---
|
||||
|
||||
### OQ-8: Visual Vocabulary for Flavor Structure Categories
|
||||
|
||||
Nigel proposes six flavor structure categories for unclaimed quarters (informal economy indicators, settlement indicators, economic stress indicators, faction presence indicators, plus two others). He asks Araminta what visual vocabulary distinguishes these categories.
|
||||
|
||||
Araminta's empty quarter types (plaza, service alley, courtyard, vehicle staging, structural gap) overlap partially with Nigel's flavor categories but use different taxonomy. These two systems need reconciliation before chunk fill can be specified.
|
||||
|
||||
**Raised by:** Nigel §7; Araminta §3.2.
|
||||
|
||||
---
|
||||
|
||||
## Section 3: Dissent and Alternative Proposals
|
||||
|
||||
### D-1: Ozzie's Skepticism About Second Station Syndrome
|
||||
|
||||
Ozzie is not convinced the quarter system alone defeats structural recognizability. Her concern: "Even with quarter variation, if the blocks are always the same size and the streets are always aligned, I'll feel the skeleton underneath." She wants the generator to vary the SOCIAL AND POLITICAL skeleton, not just geometry within a fixed structural skeleton.
|
||||
|
||||
This is not a rejection of the quarter system — it's a demand that the quarter system be a *consequence* of social/political variation, not a separate aesthetic variation pass. Her test: "two players should be able to compare notes and find genuinely different investigation experiences."
|
||||
|
||||
This aligns with Nigel's Guarantee 1 (Structural Non-Repeatability Per Seed) but frames it from the player-experience side rather than the systems side.
|
||||
|
||||
**Source:** Ozzie "The Generation Sins," "What Makes the 50th Station Exciting," "Quarter System" section.
|
||||
|
||||
---
|
||||
|
||||
### D-2: Gestalt vs. Miri on Triangle Template Instantiation Stage
|
||||
|
||||
**Gestalt's position:** "Triangle configuration is determined at the population stage... social graph → chunk fill. NOT: chunk fill → social graph. The generator must not produce spatial arrangements and then try to fill them with compatible social graphs. The social graph drives spatial requirements."
|
||||
|
||||
**Miri's position:** Templates are instantiated "at the district skeleton stage, after zoning but before block generation," with "triangle assignments (who's in conflict with whom across templates)" as a skeleton field.
|
||||
|
||||
These are not fully contradictory — Miri may be describing template *type* selection while Gestalt describes NPC *assignment* to triangle positions — but the vocabulary gap obscures whether they agree. Round 2 needs a shared definition of "triangle instantiation" before this can be resolved.
|
||||
|
||||
**Sources:** Gestalt §5 Q-B; Miri §5 "when D-025 templates get instantiated."
|
||||
|
||||
---
|
||||
|
||||
### D-3: Nigel's Reframing of the Generator's Purpose
|
||||
|
||||
Nigel argues the generator's promise is not "300 worlds" but "300 × (characters) × (cultural combinations) × (seed entropy) distinct game experiences." He explicitly names structural randomness (who's entangled, where evidence is, which triangles are active) as more important than geometric variation.
|
||||
|
||||
This reframes the generator's success criteria from "produces 300 visually distinct districts" to "produces distinct investigative experiences." The implication for architecture: entanglement assignment, triangle configuration, and evidence placement are first-class generator outputs — not emergent from spatial placement.
|
||||
|
||||
No other participant dissents from this, but Araminta's contribution focuses entirely on spatial/visual coherence without addressing investigative experience variation. Whether these two framings are in tension will depend on how the pipeline's final stage ordering shakes out.
|
||||
|
||||
**Source:** Nigel §1, §6, §7 summary table.
|
||||
|
||||
---
|
||||
|
||||
## Section 4: Cross-Cutting Themes
|
||||
|
||||
### Theme 1: Every Pipeline Stage Serves Gameplay
|
||||
|
||||
Gestalt frames all generator requirements as "ultimately guarantees about asymmetric information production." Araminta frames all visual rules as serving "a player who can read where they are, what tier of access they're in, and where cover is." Nigel frames every variation axis by its "impact on player." Ozzie demands that every space "pay rent."
|
||||
|
||||
The convergence: no pipeline stage is permitted to be purely aesthetic or purely technical. Infrastructure must produce surveillance topology AND stealth topology. Zoning must produce access tier palette. Block generation must produce chokepoints. Visual grammar must communicate spatial function.
|
||||
|
||||
This is an implicit shared principle that Round 2 should make explicit, as it has implications for generator validation: the test of a generated district is not "does it look right" but "does it play right."
|
||||
|
||||
---
|
||||
|
||||
### Theme 2: Dual-Reading Spaces
|
||||
|
||||
Gestalt's G-08 principle ("every ring location reads as mundane; criminal function visible only to those who know") appears independently in two other voices:
|
||||
|
||||
- Ozzie requires spaces that feel "like I wasn't meant to find it" — discovered, not guided-to.
|
||||
- Miri requires grey economy spaces that "occupy the spaces official zoning doesn't account for."
|
||||
|
||||
The generator must produce spaces that serve a manifest function (visible to all) and a latent function (visible to those with specific knowledge or access). This is not a post-generation content layer — it is a generation-time property. The template tag at chunk fill time must encode both functions.
|
||||
|
||||
---
|
||||
|
||||
### Theme 3: Physical History as a Generator Input
|
||||
|
||||
Multiple participants want the generator to produce spaces that feel like they have a history, not just a current state:
|
||||
|
||||
- Miri's era-stratification (Era 1/2/3 as construction layers) is the primary mechanism.
|
||||
- Miri's historical event modifier pass adds anomaly traces on top of steady-state generation.
|
||||
- Nigel's historical event seed (§5 Layer 4) makes history leave physical traces — repurposed buildings, blocked corridors, NPCs with long-memory grievances.
|
||||
- Ozzie demands "historical palimpsest" — layers built by different people with different plans.
|
||||
|
||||
The common thread: history is not flavor text; it is a structural input that produces physical consequences. A district that experienced a corporate merger 10 years ago has two architectural styles and NPCs with residual loyalty conflicts.
|
||||
|
||||
Whether the generator can produce this — and whether era tags alone are sufficient, or whether a dedicated historical event layer is required — is unresolved.
|
||||
|
||||
---
|
||||
|
||||
### Theme 4: Minimum Viable District as v0.1 Deliverable
|
||||
|
||||
Tyre and Gestalt both propose concrete v0.1 deliverables that validate the generator schema without running the generator:
|
||||
|
||||
- Tyre: hand-author the Transit District as a `DistrictSkeleton` to validate schema expressiveness. Estimated ~3-4 developer-days.
|
||||
- Gestalt: define the "minimum viable district" (1 workplace, 1 bar, 1 maintenance spine, 1 transit node, 1 restricted zone, 2 active triangles) as the completeness check.
|
||||
|
||||
These should be treated as a single deliverable: a hand-authored DistrictSkeleton representing the Transit District, validated against Gestalt's seven spatial guarantees. If the schema can express all seven guarantees for the Transit District, it can express any generator output.
|
||||
|
||||
---
|
||||
|
||||
## Section 5: Qatux Observations
|
||||
|
||||
### Implicit Decision Emerging
|
||||
|
||||
The following implicit decision appears to be forming across Round 1 and should be formally proposed in Round 2 for Jeroen's confirmation:
|
||||
|
||||
**Proposed decision:** The district skeleton is the primary atomic output of the generator. It contains: social site slots (type + position), access topology, NPC capacity and pattern distribution per site, triangle assignments (NPC conflict topology), cultural modifier tags, multi-block reservations, corridor spine, access points, and zone palette assignments. The generator selects and arranges D-025 templates into skeletons; it does not modify templates. This is consistent with D-025 and Q-036.
|
||||
|
||||
If confirmed, this should become a formal D-record.
|
||||
|
||||
---
|
||||
|
||||
### Flag: Vocabulary Divergence on "Triangle Instantiation"
|
||||
|
||||
Gestalt and Miri use overlapping vocabulary with potentially different meanings:
|
||||
|
||||
| Term | Gestalt's meaning | Miri's meaning |
|
||||
|------|-------------------|----------------|
|
||||
| "Triangle instantiation" | NPC assignment to triangle positions (Population stage) | Selection of D-025 template types for social sites (Skeleton stage) |
|
||||
| "Social graph drives spatial" | NPC conflict topology must precede spatial placement | Templates carry triangle connections as a skeleton field |
|
||||
|
||||
This may be a complementary split (Miri = which template types go where; Gestalt = which NPCs fill which roles in those templates) rather than a contradiction. Round 2 should establish shared vocabulary.
|
||||
|
||||
---
|
||||
|
||||
### Flag: Araminta and Nigel's Empty Quarter Taxonomies Need Reconciliation
|
||||
|
||||
Araminta's empty quarter types: plaza, service alley, courtyard/garden, vehicle/cargo staging, structural gap (undeveloped).
|
||||
|
||||
Nigel's flavor structure categories: informal economy indicators (market stalls, vendor carts, repair shops), settlement indicators (container gardens, seating clusters, shrines), economic stress indicators (shacks, abandoned equipment, unauthorized storage), faction presence indicators (Commission kiosks, union halls, corporate branded infrastructure).
|
||||
|
||||
These two systems overlap but do not map cleanly to each other. Before chunk fill can be specified, a unified taxonomy of "what fills an unclaimed quarter" must be agreed.
|
||||
|
||||
---
|
||||
|
||||
*Round 1 complete. Summary ready for Round 2 use. — Qatux*
|
||||
@@ -0,0 +1,493 @@
|
||||
# Generator Architecture Workshop — Round 2 Notes
|
||||
|
||||
**Compiled by:** Qatux (Documenter)
|
||||
**Date:** 2026-02-27
|
||||
**Source files:**
|
||||
- `docs/workshops/generator-architecture/gestalt-round2.md`
|
||||
- `docs/workshops/generator-architecture/tyre-round2.md`
|
||||
- `docs/workshops/generator-architecture/miri-round2.md`
|
||||
- `docs/workshops/generator-architecture/araminta-round2.md`
|
||||
- `docs/workshops/generator-architecture/nigel-round2.md`
|
||||
- `docs/workshops/generator-architecture/ozzie-round2.md`
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Round 2 was substantially reshaped by the lead directive: *this is NOT a detective game; it is a game about the inherent asymmetry of human awareness.* All six participants acknowledged and absorbed this fully. The dominant work of Round 2 was extending Round 1's investigation-centric architecture to serve tycoon, dating sim, political drama, and investigation playstyles simultaneously — plus opening the generator to non-urban terrain, insignificant places, and edge bleed. Eight of the eight Round 1 open questions were resolved. Four new open questions were raised.
|
||||
|
||||
---
|
||||
|
||||
## Section 1: Resolved Questions from Round 1
|
||||
|
||||
### R-OQ-1: Pipeline Stage Ordering — Population Before or After Zoning?
|
||||
|
||||
**Resolved.** Gestalt explicitly reversed his Round 1 position:
|
||||
|
||||
> "I was wrong about needing full co-resolution of population and zoning."
|
||||
|
||||
The solution, agreed by Tyre and Gestalt independently:
|
||||
|
||||
**Two-pass process within Phase 1:**
|
||||
- Pass 1 (district skeleton stage): Zone types → NPC role slot allocation → triangle topology selection → **spatial prerequisite validation** (verify required spaces exist for secrets that will be assigned; adjust zoning if not)
|
||||
- Pass 2 (NPC population stage): 10-axis generation fills role slots with concrete NPCs; secrets anchored to already-confirmed spaces
|
||||
|
||||
The validation pass (~200 lines of Rust, Tyre estimates 0.5 developer-days) catches edge cases where zoning fails to produce a required spatial type. The skeleton guarantees staging grounds before NPC generation runs. No feedback loop required.
|
||||
|
||||
**Sources:** Gestalt §3 Stage 5 revised position; Tyre §6.
|
||||
|
||||
---
|
||||
|
||||
### R-OQ-2: Seed Architecture — Single Master Seed or Per-Stage?
|
||||
|
||||
**Resolved by lead directive.** Single master seed. All participants accept.
|
||||
|
||||
Tyre provides the implementation: `SeedChain` with deterministic keyed-hash derivation:
|
||||
```
|
||||
derive_seed(master_seed, domain_tag, index) → blake3(master || domain || index)
|
||||
```
|
||||
|
||||
**Same seed + different character selection = same world.** Character selection is a filter (lens), not a world-generation input. The simulation produces the world; the character determines what the player can see and access within it. This fulfills D-027 ("two keyholes on the same world") and D-010 principle 3 (no baking player identity into the game loop).
|
||||
|
||||
Nigel updates his variation axes table accordingly: character selection is a "lens" layer, not a generator axis. The world is identical; the perception differs.
|
||||
|
||||
**Sources:** Tyre §3; Gestalt §4; Nigel §8.
|
||||
|
||||
---
|
||||
|
||||
### R-OQ-3: Can the Quarter System Produce Social Variation, Not Just Visual?
|
||||
|
||||
**Resolved.** Yes, through a `flavor type → NPC pattern weight modifier` mechanism.
|
||||
|
||||
Gestalt, Nigel, and Tyre each describe this independently:
|
||||
|
||||
| Flavor type | NPC pattern weight shift |
|
||||
|---|---|
|
||||
| Market stall cluster | +HANDLER (trade coordinator), +CIVILIAN (customers) |
|
||||
| Commission kiosk | +SYSTEM (enforcement), −HANDLER |
|
||||
| Container garden | +ANCHOR (community pillars), +NOBODY (background domestics) |
|
||||
| Shack cluster | +CATALYST (people under pressure), +REMNANT (people left behind) |
|
||||
| Union hall | +SYSTEM (organized labor), +WITNESS (institutional memory) |
|
||||
| Corporate infrastructure | +SYSTEM (corporate agents), −ANCHOR |
|
||||
|
||||
**Tyre's architectural note:** The quarter fill doesn't *cause* NPC behavior directly. Both the quarter fill and the NPC behavior are caused by the same upstream parameters (economic tier, cultural profile, faction presence). The player sees correlation and reads it as causation. That's architecturally correct — the relationship is real, just indirect.
|
||||
|
||||
**Araminta's contribution:** The visual grammar for each flavor category communicates social reality, not investigation routes. Every player reads the same quarter through their own lens. The grammar serves all playstyles because it describes *who inhabits a space and on whose terms*.
|
||||
|
||||
**Sources:** Gestalt §3 Chunk Fill stage; Tyre §8.1; Nigel §9; Araminta §6.
|
||||
|
||||
---
|
||||
|
||||
### R-OQ-4: Can the Generator Produce Historical Palimpsest — Layers and Caused Irregularities?
|
||||
|
||||
**Resolved.** Two complementary mechanisms:
|
||||
|
||||
**1. `EraModification` system (Tyre):** `BlockSkeleton` carries `era: Era` + `era_modifications: Vec<EraModification>`. Each modification records era, coverage fraction, and `ModificationType` (`SurfaceRetrofit`, `InternalConversion`, `StructuralAddition`, `InstitutionalUpgrade`). Chunk fill reads the full modification history.
|
||||
|
||||
**2. Cause fields (Gestalt):** Extends Tyre's system with `era_cause` — why a block's era differs from district norm (e.g., `corporate_merger`, `emergency_extension`, `organic_growth`). The `ChunkLayout::LShape` variant carries an analogous cause field. These causes manifest as visual evidence in chunk fill: a material seam for `organic_growth`, different era materials on the addition in `acquisition_boundary`.
|
||||
|
||||
**Araminta's Technique 4 (infrastructure routing):** A power conduit or rail line running at a slight angle to the street grid reads as older than the layout it crosses — "historical palimpsest" as diagonal infrastructure.
|
||||
|
||||
The generator records history as a sequence of modifications, not just a current state. The player may not consciously articulate the reason, but they feel "this shape makes sense here" (Ozzie's requirement for CAUSED rather than RANDOM irregularities).
|
||||
|
||||
**Sources:** Tyre §5 era fields; Gestalt §7 era_cause addition; Araminta §3 Technique 4; Miri §2 historical events.
|
||||
|
||||
---
|
||||
|
||||
### R-OQ-5: Society Profile YAML as Serde-Compatible Schema?
|
||||
|
||||
**Resolved.** Tyre provides the complete Rust struct with serde derive macros. Estimate: ~1 developer-day for all enum types and validation.
|
||||
|
||||
Key points:
|
||||
- NULL values serialize as `Option<T>` with serde default
|
||||
- Heritage blend weights serialize as `Vec<HeritageEntry>`, validated to sum ≈ 1.0 (±0.01 tolerance)
|
||||
- Society profiles can be hand-authored in YAML (for specific systems like Krenn), generator-derived from seed, or loaded via `serde_yaml`
|
||||
- A `validate()` method checks contradictory faction presence, weight sums, and count constraints
|
||||
|
||||
**Sources:** Tyre §4.
|
||||
|
||||
---
|
||||
|
||||
### R-OQ-6: Era Stratification in Chunk Data Structure?
|
||||
|
||||
**Resolved.** Era is assigned at **block level** (in Phase 1, Block Planning stage) and inherited by all chunks within the block.
|
||||
|
||||
`BlockSkeleton` gains:
|
||||
- `era: Era` — base construction era (Era1 / Era2 / Era3)
|
||||
- `era_modifications: Vec<EraModification>` — retrofits and additions
|
||||
|
||||
The z-level correlation from D-093 (z=0 → Era 1, z=1 → Era 2, z=2 → Era 3) is a *default pattern*, not mandatory. Per-block generation can deviate (a recently rebuilt ground level could be Era 3; an old observation deck could be Era 1).
|
||||
|
||||
**Araminta's confirmation:** Era tags are assigned at block generation time, not chunk fill time. Adjacent blocks can have different eras; the visual transition happens at block boundary chunks via setbacks, service alleys, or material seams.
|
||||
|
||||
**Sources:** Tyre §5; Araminta Round 1 §1.3 (confirmed unchanged).
|
||||
|
||||
---
|
||||
|
||||
### R-OQ-7: Size of the Cultural Ingredients Space?
|
||||
|
||||
**Resolved by Miri.** The raw combination space is hundreds of thousands; the gameplay-distinguishable space is **~1,000–7,700+ compositions**. At 300 worlds, the game samples a small fraction of available variety.
|
||||
|
||||
Correcting Nigel's Round 1 estimate of "20 distinct compositions": the actual space is ~100 minimum. Updated calculation: **300 worlds × 2 characters × 100 minimum cultural compositions = 60,000 meaningfully distinct games** before seed entropy.
|
||||
|
||||
**Critical caveat (Miri):** The binding constraint is **template library depth**, not the ingredients space. Cultural variety without template variety means cultural feel changes but spatial feel repeats. Template library expansion is the correct lever for expanding perceived variety.
|
||||
|
||||
**Nigel's response:** Sufficient for cross-world variety. Insufficient for within-world replayability — which comes from seed-driven NPC generation, triangle configuration, and entanglement assignment that vary *within* cultural parameters. The cultural composition is the setting; it's stable. The seed variation is the gameplay.
|
||||
|
||||
**Nigel's addition:** Economic pressure combination is the highest-resolution variation lever for *player-perceived* variety because it changes the emotional texture of the world, not just its mechanics. Two transit hubs with different economic pressure combinations feel like different kinds of humanity.
|
||||
|
||||
**Sources:** Miri §6; Nigel §7.
|
||||
|
||||
---
|
||||
|
||||
### R-OQ-8: Empty Quarter Taxonomy Reconciliation?
|
||||
|
||||
**Fully resolved.** The two taxonomies operate at different abstraction levels and compose cleanly.
|
||||
|
||||
**Unified two-layer model (Araminta, confirmed by Tyre and Nigel):**
|
||||
|
||||
Every empty/unclaimed quarter gets:
|
||||
1. **Spatial form** (Araminta's 5 types): Open plaza, Service alley, Courtyard, Staging ground, Undeveloped gap — answers "what SHAPE is this space and what are its visual/access properties?"
|
||||
2. **Content category** (Nigel's 4 + Civic baseline): Civic baseline, Informal economy, Settlement, Economic stress, Faction presence — answers "what CONTENT occupies this space and what does it communicate about social/economic state?"
|
||||
|
||||
Araminta provides a full compatibility matrix (25 combinations, with valid/invalid markings). Tyre formalizes as a `QuarterFill` struct with `form: QuarterForm` and `function: QuarterFunction`. The generator maintains a form×function validity table.
|
||||
|
||||
**Visual vocabulary for each content category (Araminta §5):**
|
||||
- Informal economy: warm irregular lighting, non-aligned awning structures on z=4, goods-display floor patterns, vendor-specific warm light pools
|
||||
- Settlement: organic overhead elements (container gardens on z=4), non-matching furniture, personal shrines, warmer ambient than zone baseline
|
||||
- Economic stress: failed/missing fixtures, damaged floor tile variants, abandoned equipment in irregular positions
|
||||
- Faction presence: cold standardized objects, institutional signage, uniform maintained lighting
|
||||
|
||||
**Sources:** Tyre §8.3; Araminta §4; Nigel §6.
|
||||
|
||||
---
|
||||
|
||||
## Section 2: Consensus Points Emerging in Round 2
|
||||
|
||||
### C-R2-1: Two-Phase Generation Architecture
|
||||
|
||||
Universal acceptance. Tyre provides the concrete implementation; Gestalt endorses and extends it; all other participants work within it.
|
||||
|
||||
**Phase 1 (Background Prep, async, ~50–500ms per district):**
|
||||
1. System Generation (star type, worlds, stations)
|
||||
2. Society Profile per world (serde YAML → Rust struct)
|
||||
3. District Skeleton per world (zoning, social sites, access topology, NPC slots, reservations, corridor spines, zone palettes, boundary descriptors)
|
||||
4. Block Planning per district (ChunkLayouts, edge contracts, era tags, quarter pre-assignments, landmark slots)
|
||||
5. NPC Population per district (role slot filling, triangle configuration, entanglement marking, spawn location preferences)
|
||||
6. Transition Strip Generation per shared edge (palette blending, access point alignment)
|
||||
|
||||
Output: `PreparedDistrict` struct (~10–50 KB per district; all 300-world galaxy fits in ~30–150 MB)
|
||||
|
||||
**Phase 2 (Local Area Gen, on-demand, ~100–500ms per chunk):**
|
||||
- Chunk Fill as player enters loading radius (template stamping, zone palette, era materials, NPC spawn points, LOS anchors)
|
||||
- Output: `ChunkData` cached, saved, never regenerated
|
||||
|
||||
The `PreparedDistrict` is the formal contract between phases. Phase 2 never calls Phase 1 functions; Phase 1 never produces tile data.
|
||||
|
||||
**Scheduling:** Home system Phase 1 is blocking at game start (~2–3s). Neighboring systems queue by gate distance. On-demand preparation when player books travel.
|
||||
|
||||
**Sources:** Tyre §1; Gestalt §3.
|
||||
|
||||
---
|
||||
|
||||
### C-R2-2: Edge Bleed Solution (Technical)
|
||||
|
||||
Tyre and Araminta converge on complementary solutions.
|
||||
|
||||
**Tyre's structural approach:** The outermost column/row of each district is a *transition strip*. `DistrictSkeleton` gains a `boundaries: DistrictBoundaries` field describing what each edge offers to the shared transition zone. Transition blocks:
|
||||
- Blend zone palettes (weighted average of both adjacent zones)
|
||||
- Use older of the two boundary eras
|
||||
- Carry no social sites (pass-through zones only)
|
||||
- Have smaller building footprints (no full-merge buildings)
|
||||
- Connect access points from both districts, dead-ending gracefully where only one district offers a corridor
|
||||
|
||||
Memory cost: ~4 KB per shared edge; trivial.
|
||||
|
||||
**Araminta's visual rules for transitional blocks:**
|
||||
- Floor tiles interpolate over the 64vt block width
|
||||
- Wall materials do NOT interpolate (structural integrity reads; inconsistent walls read as construction error)
|
||||
- Lighting fixture temperature interpolates
|
||||
- Ambient (CanvasModulate) interpolates
|
||||
- Overhead elements follow the building's home district palette — no interpolation
|
||||
|
||||
**Test (Araminta):** A player who has stopped moving in a boundary zone should not be able to say with certainty "I'm in District A" vs. "I'm in District B." They should feel "somewhere between institutional and residential."
|
||||
|
||||
**Miri's cultural bleed distinction:** Two types of bleed behave differently:
|
||||
- **Faction bleed**: radius-geometric from faction infrastructure, decays by block distance — predictable, detective can map it
|
||||
- **Cultural bleed**: flow-path along NPC movement corridors, strongest along high-traffic routes — requires knowing how people actually move
|
||||
|
||||
Shared boundary social sites serve both adjacent district cultures and are the primary sources of cross-triangle triangles (D-024).
|
||||
|
||||
**Sources:** Tyre §2; Araminta §1; Miri §5.
|
||||
|
||||
---
|
||||
|
||||
### C-R2-3: Playstyle-Agnostic Spatial Archetypes
|
||||
|
||||
Gestalt's revised guarantee set, accepted without challenge by all participants:
|
||||
|
||||
**7 universal spatial archetypes (every Full-complexity district must contain at least 1 of each):**
|
||||
|
||||
| Archetype | Investigation use | Tycoon use | Dating sim use | Political use |
|
||||
|---|---|---|---|---|
|
||||
| Traffic Chokepoint | Observation point | Trade route leverage | Serendipitous encounter | Campaign territory |
|
||||
| Informal Zone | Quiet zone / dead drops | Grey market space | Privacy / trysts | Back-channel meetings |
|
||||
| Social Hub | Rapport-building | Networking | Romance venue | Influence gathering |
|
||||
| Institutional Space | Authority access | Licensing/permits | Formal encounter | Power center |
|
||||
| Insider Space | Ring access visible | Guild/cooperative | Close friend group | Party/faction HQ |
|
||||
| Economic Node | Evidence trail (money follows crime) | Primary profit opportunity | Shared activity | Leverage over economic actors |
|
||||
| Encounter Corridor | NPC observation route | Supply chain link | Daily routine overlap | Visibility territory |
|
||||
|
||||
**4 additional per-playstyle guarantees:**
|
||||
- Tycoon: ≥1 economic asymmetry signal (demand gap, price differential, prohibited supply)
|
||||
- Dating sim / social: ≥1 temporal encounter window (social hub with defined active day-phases, D-031 integration)
|
||||
- Political: ≥1 power gradient visibility (SYSTEM-pattern NPC in visible authority position)
|
||||
- Non-urban only: natural chokepoint replacing the architectural corridor (mountain pass, harbor mouth, river ford)
|
||||
|
||||
**11-check guarantee audit** (Gestalt proposes runtime validation — all 11 checks serialized into the `DistrictSkeleton` as `guarantee_audit: GuaranteeAuditResult`).
|
||||
|
||||
**Ozzie's evaluation:** She asked Gestalt to reframe investigation-vocabulary guarantees for all playstyles. She does not directly endorse or reject the revised formulation in Round 2 — will assess in Round 3.
|
||||
|
||||
**Sources:** Gestalt §1–2 and §9 MVD table.
|
||||
|
||||
---
|
||||
|
||||
### C-R2-4: Non-Urban Terrain in Same Pipeline
|
||||
|
||||
Universal acceptance: same 4-level hierarchy, same pipeline stages, same architectural abstractions — different input parameters, different template libraries.
|
||||
|
||||
**What changes for non-urban:**
|
||||
- Fill density: urban 60–100% quarters filled → non-urban 0–20% (wilderness) to 20–40% (agricultural)
|
||||
- Template types: building templates → terrain templates (fields, forest, water, paths)
|
||||
- NPC density: 30–80 per urban district → 0–10 for wilderness
|
||||
- Edge contracts: door/corridor connections → path/road connections
|
||||
- LOS anchors: walls, pillars, furniture → trees, rock formations, fences, elevation changes
|
||||
- Zone palette: architectural materials → natural materials
|
||||
- Lighting model: PointLight2D fixture pools → global ambient (CanvasModulate) + canopy overhead layer as urban-equivalent occlusion
|
||||
|
||||
**Araminta's natural zone palettes:** Five new palettes defined: farmland (dark warm brown soil, amber sparse nocturnal), wilderness/forest (near-black floor, dense canopy overhead as urban-wall equivalent), ocean/coastal (near-black deep blue, animated specular reflection), beach (dark warm tan, global ambient only), mountain/snow (dark cold stone + bright snow inversion — only terrain where floor is lighter than ambient), secluded town (warm brown-grey, personal accumulated overhead elements as cultural expression).
|
||||
|
||||
**Tyre's `TerrainType` enum:** Station, Urban, Agricultural, Wilderness(biome), Water(water_type), Transitional, Orbital.
|
||||
|
||||
**Tyre's `ComplexityTier` enum:** Full, Moderate, Minimal, Empty. **Gameplay guarantees apply to Full complexity only.** A farmland district doesn't need a surveillance chokepoint.
|
||||
|
||||
**Sources:** Tyre §7; Miri §3; Araminta §2; Nigel §3; Gestalt §5.
|
||||
|
||||
---
|
||||
|
||||
### C-R2-5: Insignificant Places as a First-Class State
|
||||
|
||||
All participants accept. Miri's framing is the most precise:
|
||||
|
||||
> Insignificance is not a property of the society profile. It's a relation — a place is insignificant RELATIVE to the wider network.
|
||||
|
||||
**Miri's "insignificant" society profile characteristics:** High drift novelty (no cosmopolitan dilution), high insider trust threshold (a stranger is a social event), low information density, inverted anonymity (the player *cannot* be anonymous — everyone learns their name within hours). **The information asymmetry challenge inverts**: not "discover what's hidden" but "manage that you can't hide anything."
|
||||
|
||||
**Nigel's "drama density" axis:** Zero (no Tier 1 modules, stable social fabric, guaranteed quiet) → Low → Medium → High → Flashpoint (rare, must feel rare). The storyteller uses drama density as a pacing lever. A backwater is not low-content — it's a *promise* that genuine quiet is available.
|
||||
|
||||
**Nigel's "false backwater" concept:** A world that APPEARS to be a backwater but is a critical logistical node for a cross-system ring. The investigation player who investigates finds this. The tycoon player who passes through without looking finds nothing. Same generator output. Different game.
|
||||
|
||||
**Ozzie's requirement for backwaters:** They must be "complete, not failed hubs." Small, dense in human entanglement, strongly expressed cultural ingredients, history recent enough to be personally remembered. The player's arrival is an event. The generation win is density of human detail in a small space.
|
||||
|
||||
**Sources:** Miri §4; Nigel §2; Gestalt Stage 0; Tyre §7.5; Ozzie "Backwaters" section.
|
||||
|
||||
---
|
||||
|
||||
### C-R2-6: Society Profile as Playstyle-Agnostic Information Structure
|
||||
|
||||
Miri's central contribution: the society profile already contains what all playstyles need. The gap is not the profile but **what information categories are tracked** and **what actions they unlock**.
|
||||
|
||||
**By playstyle:**
|
||||
- Investigation: evidence of hidden activities → confrontation/exposure
|
||||
- Tycoon: economic intelligence (trade flows, price differentials, information barriers) → trade advantages, economic leverage
|
||||
- Dating sim: social/personal knowledge (relationship formation norms, trust mechanism) → relationship phases, access to private spaces
|
||||
- Political drama: power intelligence (faction relationships, leverage map, destabilizing secrets) → alliance formation, position seizure, scandal detonation
|
||||
|
||||
**Key insight (Miri):** The political drama and investigation crossover is structural. Investigation finds truth; political drama finds leverage. The knowledge graph (D-041) serves both. The difference is what the player chooses to DO with `KnowsDetails`-tier information.
|
||||
|
||||
**Dating sim and triangle structure:** Romantic competition is structurally identical to the investigation triangle (three NPCs with conflicting interests). The generator's D-024 model handles dating sim mechanics without modification. What changes is the *content tags* on triangle nodes (`motivation: romantic-rival` vs `motivation: operator`).
|
||||
|
||||
**Miri's addition:** Tourist economy settings require dual NPC population profiles — resident workers (reserved, labor-solidarity) and visitor tourists (open, friendly, with a countdown departure date). The class contrast is explicit and spatial. Three-zone access structure maps cleanly onto Gestalt's access tier model.
|
||||
|
||||
**Sources:** Miri §2; Nigel §1.
|
||||
|
||||
---
|
||||
|
||||
### C-R2-7: DLC as Template Library Expansion Model
|
||||
|
||||
Introduced by Miri, endorsed by Nigel. The ingredients menu stays stable; DLC adds eligible templates per ingredient combination. The generator gracefully falls back to base game templates if a DLC template is selected but unavailable.
|
||||
|
||||
Proposed DLC structure:
|
||||
- Base game: logistics, residential, administrative, bar/social, maintenance, gate cluster
|
||||
- "Agricultural Worlds" DLC: farmstead, granary, rural tavern, market day, seasonal camp, mill complex
|
||||
- "Maritime Settlements" DLC: fishing dock, harbor bar, vessel interior, lighthouse, chandlery
|
||||
- "Leisure Economies" DLC: resort lodge, surf shack, mountain chalet, seasonal service housing
|
||||
|
||||
**Sources:** Miri §6.3; Nigel §3.4.
|
||||
|
||||
---
|
||||
|
||||
## Section 3: New Open Questions for Round 3
|
||||
|
||||
### OQ-R3-A: Can the Block Grid Rotate or Breathe?
|
||||
|
||||
**Raised by Ozzie. Critical. Not addressed by any other participant.**
|
||||
|
||||
Ozzie's concern: even with quarter variation, L-shapes, and edge bleed, the underlying 4×4 block grid with perpendicular streets remains perceptible over multiple playthroughs. She explicitly asks:
|
||||
|
||||
> "Can two adjacent districts have different orientations? Can streets curve? Can blocks be non-rectilinear?"
|
||||
|
||||
Araminta's seven anti-grid visual techniques (diagonal connectors, irregular setbacks, overhead extension past block edges, angled infrastructure, light territories, vegetation overflow, street width variation) partially address this — but they hide the grid through visual means rather than removing it architecturally.
|
||||
|
||||
This may require an explicit decision: either (a) the grid breathes at the district generation stage (infrastructure stage can rotate blocks or introduce non-right-angle arrangements) or (b) the grid remains fixed and visual techniques are the full mitigation strategy. If (b), the team should evaluate whether that's sufficient against Ozzie's stated concern.
|
||||
|
||||
**Stakes:** If Ozzie is right, Second Station Syndrome re-emerges at the structural level even after all other problems are solved.
|
||||
|
||||
**For Round 3:** Tyre to address whether the D-094 hierarchy can accommodate non-rectilinear block arrangements, or whether this is deferred to a later milestone.
|
||||
|
||||
---
|
||||
|
||||
### OQ-R3-B: Triangle Purpose Taxonomy
|
||||
|
||||
**Raised by Gestalt.** The proposed `triangle_purpose: TrianglePurpose` field (investigation/economic/political/social) on `SocialSitePlacement.triangles` needs formal definition.
|
||||
|
||||
**Stakes:** If triangles carry purpose tags, the scenario instantiation stage can activate relevant triangles based on active playstyle context. Without this, all triangles activate regardless of relevance. This is the mechanism that makes the political drama's "active triangles" differ from the investigation's "active triangles" in the same district.
|
||||
|
||||
**For Round 3:** Tyre to confirm whether `TrianglePurpose` adds meaningful implementation complexity, or whether it's a simple tag on the existing `TriangleTemplate` struct.
|
||||
|
||||
---
|
||||
|
||||
### OQ-R3-C: Maritime/Wilderness Informal Zone
|
||||
|
||||
**Raised by Gestalt.** The Informal Zone archetype requires deliberate generation in every Full-complexity district. For architectural settings, this is a maintenance corridor or service back-alley. For wilderness/maritime settings, there is no equivalent.
|
||||
|
||||
Gestalt proposes `terrain_informal_zone` as a geography-defined sheltered space (cave, ravine, hidden cove). This satisfies the same gameplay guarantee (degraded institutional coverage, low ambient traffic, suitable for private or unofficial activity) through terrain rather than infrastructure.
|
||||
|
||||
**For Round 3:** Miri to confirm what wilderness informal zones look like culturally (what does "private exchange" mean when there is no institutional authority to hide from?).
|
||||
|
||||
---
|
||||
|
||||
### OQ-R3-D: Vessel Architecture — Entity-Carried Chunks
|
||||
|
||||
**Raised by Miri.** The `bounded_mobile` social site tag for vessels (ships, boats) may require an entity-carried chunk — a chunk that moves rather than being fixed to a coordinate. This is potentially architecturally significant.
|
||||
|
||||
> "Vessels move — this might require an entity-carried chunk, which is architecturally complex."
|
||||
|
||||
**For Round 3:** Tyre to assess whether mobile chunks are within the D-012 streaming model's scope, require a separate mechanism, or should be deferred to a later milestone.
|
||||
|
||||
---
|
||||
|
||||
### OQ-R3-E: The Horizon as a Generator Landmark
|
||||
|
||||
**Raised by Ozzie.** Walking to the edge of a coastal settlement and seeing ocean for the first time should be a Wow Moment. The generator must treat water's edge as a landmark equivalent — not a blank space.
|
||||
|
||||
This is partially addressed by Araminta's ocean zone palette (open water has dramatically extended LOS; shore is a transitional band). But the *generator* must also treat the coastal edge as a reserved landmark slot, analogous to Araminta's district quadrant landmark rule (1 per quadrant).
|
||||
|
||||
**For Round 3:** Araminta to confirm whether "water's edge as automatic landmark" is handled by the natural zone palette visual grammar, or requires an explicit landmark reservation at the district skeleton stage.
|
||||
|
||||
---
|
||||
|
||||
## Section 4: Dissent and Tensions
|
||||
|
||||
### D-R2-1: Ozzie's Partial Dissent on Anti-Grid
|
||||
|
||||
Ozzie explicitly says the current architecture "partially addresses" her grid concern — not fully. Her seven techniques are visual camouflage; they don't change the underlying architecture. She is making this a Round 3 demand:
|
||||
|
||||
> "Tell me the grid can breathe. Tell me two adjacent districts can have different orientations. Tell me a street can curve because the geography required it."
|
||||
|
||||
This is the one significant tension where a participant is unsatisfied with the Round 2 response. The team lead or Tyre must address this directly.
|
||||
|
||||
---
|
||||
|
||||
### D-R2-2: Miri on Social Site Template Diversity
|
||||
|
||||
Miri notes the investigation-centric design produced one primary social site type (the bar — shift-end social aggregation). Dating sim gameplay requires more types: communal meal space, recreational gathering venue, domestic invitation threshold. These are different D-025 templates, not a pipeline change.
|
||||
|
||||
Miri proposes the DLC model as the solution: base game templates serve investigation/tycoon; social expansion pack adds dating sim template library. This is a reasonable position but defers the dating sim's template requirements to a later milestone. No other participant challenged this, but it should be noted as a scoping decision.
|
||||
|
||||
---
|
||||
|
||||
### D-R2-3: Gestalt Adds Fields to Tyre's Data Structures Without Cross-Reference
|
||||
|
||||
Gestalt proposes three additions to `DistrictSkeleton`:
|
||||
1. `significance_tier: SignificanceTier`
|
||||
2. `setting_geometry: SettingGeometry`
|
||||
3. `guarantee_audit: GuaranteeAuditResult`
|
||||
|
||||
And a modification to `SocialSitePlacement.triangles`: add `triangle_purpose: TrianglePurpose`.
|
||||
|
||||
Tyre's Round 2 also adds three fields to `DistrictSkeleton` (`society_profile`, `terrain`, `complexity`), plus the full `DistrictBoundaries` struct.
|
||||
|
||||
These are complementary, not contradictory — but the combined `DistrictSkeleton` struct needs to be reconciled as a single canonical definition. Neither Tyre nor Gestalt was working from a shared draft. Round 3 should produce a unified struct definition.
|
||||
|
||||
---
|
||||
|
||||
## Section 5: Cross-Cutting Themes
|
||||
|
||||
### Theme 1: The Information Landscape Is Universal; The Lens Varies
|
||||
|
||||
Miri's framing provides the unifying theory: the generator produces one information landscape; what varies is which information the player's archetype seeks and what they do with it. Investigation reads the landscape as a crime scene. Tycoon reads it as a market. Dating sim reads it as a social web. Political drama reads it as a power structure.
|
||||
|
||||
This reframes the generator's success criterion: not "does it produce 300 visually distinct districts" but "does it produce 300 districts with rich enough information landscapes that all four playstyles find distinct, valid experiences within each one."
|
||||
|
||||
---
|
||||
|
||||
### Theme 2: Economic Pressure Combination Is the Highest-Leverage Variation Lever
|
||||
|
||||
Both Miri and Nigel independently converge on this. Miri demonstrates it through the Sova vs. Station Vareth contrast. Nigel elevates it as the variable that most changes *emotional texture* rather than just mechanical parameters.
|
||||
|
||||
Two Transit Hub districts with different economic pressure combinations feel like different kinds of humanity — the grey economy on a `[tight-margin, prohibition-economy]` world is rational and ideologically defensible; on a `[survival-gap, prohibition-economy]` world it is desperate and morally fraught. The investigation, the tycoon opportunity, the romantic stakes, and the political fault lines all change.
|
||||
|
||||
---
|
||||
|
||||
### Theme 3: Contrast as Content
|
||||
|
||||
Multiple participants name the spectrum from backwater to epicenter as itself a content dimension:
|
||||
- Nigel: drama density axis, backwaters as pacing tools for the storyteller
|
||||
- Ozzie: backwaters require the player's arrival to be an event; they are complete worlds at small scale
|
||||
- Miri: insignificant places have inverted information dynamics — high visibility, intimate conspiracy, no anonymity
|
||||
|
||||
The implication: the generator must not treat low-drama districts as scale-reduced versions of high-drama districts. They are categorically different content types with their own generator requirements.
|
||||
|
||||
---
|
||||
|
||||
### Theme 4: Template Library Depth as the Binding Constraint
|
||||
|
||||
Named explicitly by Miri, implied by Ozzie (who needs non-urban visual vocabulary), and addressed by the DLC model. The generator architecture is sound. The generator's variety ceiling is the D-025 template library, not the pipeline design.
|
||||
|
||||
This suggests the roadmap emphasis: once the generator pipeline is validated (Tyre's v0.1–v0.3 estimate), the primary work driving player-perceived variety shifts to template library authoring and expansion.
|
||||
|
||||
---
|
||||
|
||||
## Section 6: Qatux Observations
|
||||
|
||||
### Implicit Decision Forming: DistrictSkeleton Canonicalization
|
||||
|
||||
Tyre and Gestalt are both adding fields to `DistrictSkeleton` without a shared draft. The current composite of their proposals would include:
|
||||
- Tyre's original fields (district_id, seed, district_type, context, blocks, social_sites, reservations, access_points, corridors, z_levels, zone_palette)
|
||||
- Tyre's R2 additions: boundaries, society_profile, terrain, complexity
|
||||
- Gestalt's R2 additions: significance_tier, setting_geometry, guarantee_audit
|
||||
- Gestalt's R2 modification: `triangle_purpose` on `SocialSitePlacement.triangles`
|
||||
- Gestalt's era_cause on `BlockSkeleton`
|
||||
|
||||
**For Round 3:** A canonical `DistrictSkeleton` struct definition should be produced that reconciles all additions. Tyre is the appropriate author given the technical ownership.
|
||||
|
||||
---
|
||||
|
||||
### Flag: "Drama Density" and "Significance Tier" Are Overlapping Concepts
|
||||
|
||||
Gestalt's Stage 0 produces `SignificanceTier` (Center-stage / Regional / Backwater / Waypoint / Insignificant).
|
||||
Tyre's `ComplexityTier` produces (Full / Moderate / Minimal / Empty).
|
||||
Nigel's "Drama Density" axis produces (Zero → Low → Medium → High → Flashpoint).
|
||||
|
||||
These three concepts describe the same underlying parameter with different vocabulary and granularity. They need reconciliation before the Pre-Pipeline stage can be formally specified. Likely these collapse to one parameter (or two: a static complexity/significance tier and a dynamic drama density that the storyteller can modify).
|
||||
|
||||
---
|
||||
|
||||
### Flag: Vessel/Maritime Architecture Needs Decision Before Template Authoring Begins
|
||||
|
||||
If maritime DLC templates include vessel interiors as `bounded_mobile` social sites, and if vessel interiors require mobile chunks, this architectural decision needs to be made before maritime template authoring begins. Authoring vessel interiors for a static chunk architecture would waste work if mobile chunks turn out to be required.
|
||||
|
||||
---
|
||||
|
||||
*Round 2 complete. All 8 Round 1 open questions resolved. 5 new questions raised for Round 3. — Qatux*
|
||||
@@ -0,0 +1,551 @@
|
||||
# Generator Architecture Workshop — Round 3 Notes
|
||||
|
||||
**Compiled by:** Qatux (Documenter)
|
||||
**Date:** 2026-02-27
|
||||
**Source files:**
|
||||
- `docs/workshops/generator-architecture/gestalt-round3.md`
|
||||
- `docs/workshops/generator-architecture/tyre-round3.md`
|
||||
- `docs/workshops/generator-architecture/miri-round3.md`
|
||||
- `docs/workshops/generator-architecture/miri-round3-supplement.md`
|
||||
- `docs/workshops/generator-architecture/araminta-round3.md`
|
||||
- `docs/workshops/generator-architecture/nigel-round3.md`
|
||||
- `docs/workshops/generator-architecture/ozzie-round3.md`
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Round 3 is the convergence round. Nine lead directives were addressed. Five Round 2 open questions were resolved. The canonical DistrictSkeleton Rust struct was produced by Tyre. The pipeline architecture was formally stated by Gestalt. The generator is now structurally sound through v0.3, with v0.4 features (skyscrapers, full mobile chunks) scaffolded but deferred.
|
||||
|
||||
One structural tension carries into Round 4: vessel architecture (Tyre's entity-carried MobileChunk vs. Nigel's instanced district). This must be resolved before maritime and transit templates are authored.
|
||||
|
||||
---
|
||||
|
||||
## Section 1: Round 2 Open Questions — Resolution Status
|
||||
|
||||
### OQ-R3-A: Block Grid Rotation / "Breathing"
|
||||
|
||||
**Resolved.** Tyre delivers the structural answer Ozzie demanded.
|
||||
|
||||
D-094 defines **data sizes**, not geometry. A `DistrictLayoutMode` enum governs block placement:
|
||||
|
||||
```rust
|
||||
enum DistrictLayoutMode {
|
||||
Grid,
|
||||
Organic { placements: [[BlockPlacement; 4]; 4] },
|
||||
}
|
||||
struct BlockPlacement {
|
||||
offset: (i16, i16), // ±16 sim tiles per axis
|
||||
rotation_steps: u8, // 0–3 in 15° increments (max 45°)
|
||||
street_width_factor: f32, // 0.75–2.0
|
||||
}
|
||||
```
|
||||
|
||||
In `Organic` mode: streets are the **negative space** between shifted/rotated blocks. Adjacent districts can have different layout modes. The transition strip handles orientation mismatch. The 45° cap is hard (beyond that, tile-based pathfinding breaks).
|
||||
|
||||
Araminta provides the visual grammar for organic districts: 45° and angled wall tile variants, increased landmark density (12 vt vs 16 vt), wider street width range (4–14 vt), face-defined blocks. `grid_orientation: f32` on `DistrictSkeleton` propagates rotation to chunk fill.
|
||||
|
||||
Miri provides the generative logic: grid = power imposed (Commission/Syndic planning, Arc heritage, Era 3 development). Organic = power negotiated (Iron/Dust/Tide settlement, Era 1 pioneer foundations, maintenance/residential zones). Within a district, blocks can have different `street_geometry` assignments based on era and heritage.
|
||||
|
||||
Ozzie confirms: Araminta's seven anti-grid visual techniques are **camouflage, not structure**. Tyre's organic mode provides the structural answer. Ozzie accepts this as satisfying her demand.
|
||||
|
||||
**Outstanding note:** Tyre's cap is 45° rotation steps. For truly curving streets (Ozzie's "streets that curve because terrain required it"), the visual impression of curve comes from 45° jogs at intervals. True smooth curves are not achievable in the tile engine at v0.1–v0.3. Angular organic layouts, not flowing curves.
|
||||
|
||||
---
|
||||
|
||||
### OQ-R3-B: Triangle Purpose Taxonomy
|
||||
|
||||
**Resolved.** Gestalt proposes the enum; Tyre confirms it as implementation-trivial.
|
||||
|
||||
```rust
|
||||
enum TrianglePurpose {
|
||||
Investigation, Economic, Social, Political, Tactical, Mundane,
|
||||
}
|
||||
```
|
||||
|
||||
`Tactical` is the new addition for Round 3: the triangle whose three nodes are the target, their protector/guardian, and an informant or witness. Any NPC who is a potential assassination contract target is the central node of a `Tactical` triangle.
|
||||
|
||||
Triangles carry `purposes: Vec<TrianglePurpose>` — a triangle can serve multiple purposes. Mundane triangles (workplace rivalry, neighbour disputes) are always present in inhabited districts. The scenario instantiation system activates triangles based on which purposes are relevant to the player's current engagement.
|
||||
|
||||
Implementation: one `Vec<TrianglePurpose>` field on `TriangleAssignment`. ~20 lines of code.
|
||||
|
||||
---
|
||||
|
||||
### OQ-R3-C: Maritime / Wilderness Informal Zone
|
||||
|
||||
**Resolved.** Miri redefines the informal zone for non-institutional settings.
|
||||
|
||||
In institutionally-governed urban settings, the informal zone is defined by **institutional absence** (outside Meridian coverage). In non-institutional settings, the informal zone must be redefined as **outside the community social field**.
|
||||
|
||||
Three informal zone types for non-urban settings:
|
||||
- `social_permission` — convention covers this space (what happens on the boat is the crew's business)
|
||||
- `physical_distance` — community observation doesn't reach here without intent (the far fields in off-season)
|
||||
- `utilitarian_cover` — normal function provides plausible presence (in the barn checking the animals)
|
||||
|
||||
Heritage root determines which type appears: Frost → `physical_distance`; Tide/Dust → `social_permission`; Iron → `utilitarian_cover`.
|
||||
|
||||
Wilderness is the extreme case: the whole terrain is low-coverage, no Meridian equivalent. Nigel confirms: "the wilderness itself is the informal zone." The generator satisfies the Tier 1 Informal Zone guarantee for wilderness settings automatically — the biome flag counts.
|
||||
|
||||
Generator tag: `terrain_informal_zone` (Gestalt's term), required per Full-complexity non-urban district.
|
||||
|
||||
---
|
||||
|
||||
### OQ-R3-D: Vessel Architecture
|
||||
|
||||
**Partially resolved — architectural split requires Round 4 decision.**
|
||||
|
||||
Two structurally different proposals were submitted:
|
||||
|
||||
**Tyre (entity-carried MobileChunk):**
|
||||
```rust
|
||||
struct MobileChunk {
|
||||
entity_id: EntityId,
|
||||
data: ChunkData,
|
||||
interior_size: (u16, u16),
|
||||
world_position: WorldPosition,
|
||||
movement: MobileMovementState, // Docked | InTransit | InterSystem
|
||||
access_points: Vec<MobileAccessPoint>,
|
||||
}
|
||||
```
|
||||
The chunk is a real world entity. In `InTransit`, the exterior is a scrolling visual buffer (not loaded terrain tiles). In `InterSystem`, only the interior exists.
|
||||
|
||||
**Nigel (instanced district):**
|
||||
The vessel is a district instance generated at journey-start, loaded as normal district data, terminated at arrival. Visual movement is client-side animation (parallax background on window tiles). No coordinate system complexity; full D-094 compatibility. Tiles don't move.
|
||||
|
||||
These are **fundamentally different architectures** with different simulation implications. Tyre's model enables vessels to exist as world entities between voyages (docked at port, visible on the map). Nigel's model is cheaper and simpler but vessels only exist during voyages.
|
||||
|
||||
Both agree on: vessel interiors use the same NPC simulation system; passenger manifests are seeded at journey-start; temporal pressure (arrival deadline) is core gameplay.
|
||||
|
||||
Miri supplement provides cultural grammar for both models regardless of architecture: trains as `BoundedLinear` setting type with car-sequence social grammar; spaceships as institutionally-suspended environments; `transit_social_modifier` that adjusts trust-building rate, privacy level, and information flow.
|
||||
|
||||
**For the record:** this decision must be made before maritime and vessel template authoring begins. It affects the streaming model, the world map, and the NPC simulation tick.
|
||||
|
||||
---
|
||||
|
||||
### OQ-R3-E: Horizon as Generator Landmark
|
||||
|
||||
**Resolved.** Araminta delivers the mandatory reservation rule.
|
||||
|
||||
> **Rule:** Coastal districts must include a "horizon view" landmark reservation in the DistrictSkeleton — a mandatory negative-space view corridor of minimum 8 visual tiles unobstructed from street to water.
|
||||
|
||||
This reservation prevents the generator from placing a warehouse at the water's edge. The view must exist. The palette guarantees the *feeling*; the reservation guarantees the *moment*.
|
||||
|
||||
Gestalt confirms: the horizon view corridor is a Tier 2 guarantee for any district with `TerrainType::Water` on one boundary.
|
||||
|
||||
Ozzie confirms: the horizon is not negotiable. It is one of the game's primary Wow Moments.
|
||||
|
||||
---
|
||||
|
||||
## Section 2: Directive Coverage — All Nine
|
||||
|
||||
### Directive 1: Assassin Lens
|
||||
|
||||
**Fully addressed.** Team consensus: the assassin reads existing spaces differently, not new spaces.
|
||||
|
||||
**Gestalt** extends the 7 spatial archetypes with an assassin column (see below) and adds 4 assassin-specific spatial guarantees:
|
||||
- **A-1 Elevated Vantage:** Full-complexity district must have ≥1 position at z=1+ with LOS cone covering the primary Traffic Chokepoint
|
||||
- **A-2 Egress Multiplicity:** Every district entry point has ≥2 independent egress routes with no shared secondary chokepoint
|
||||
- **A-3 Temporal Opacity Window:** Full-complexity districts have ≥1 day-phase period where Traffic Chokepoint observer density drops below crowd-cover threshold
|
||||
- **A-4 Non-Institutional Access Route:** At least one path from district entry to Social Hub not crossing an access tier above `Semi-Private` (this serves all playstyles)
|
||||
|
||||
These are derived properties from existing spatial configuration, not new spaces. The guarantee audit checks whether the spatial configuration satisfies them.
|
||||
|
||||
**Miri** adds cultural depth: observational density × information liquidity × aftermath engagement = `assassination_difficulty: low/medium/high/extreme` (derived from society profile, not a new field). Heritage root table provides specific operational implications:
|
||||
- Frost: low observation, low liquidity, rigid pattern, low aftermath — paradise for operators, intelligence nightmare
|
||||
- Dust: maximum observation, high liquidity, high aftermath — community is both intelligence source and witness
|
||||
- Arc: low social surveillance during operation, INSTITUTIONAL RIGOR investigation afterward — the most dangerous aftermath
|
||||
|
||||
**Nigel** adds replayability dimension: sightline geometry varies per seed (quarter merge patterns), crowd patterns vary (seeded schedules + entanglement), escape topology varies (block backside quarter structure), timing windows vary (NPC routine seeding). Hard requirement flagged: archetype placement must vary in **angular position** per seed, not just distance from center. Otherwise experienced players overlay a mental template.
|
||||
|
||||
**Ozzie** names 4 assassination generation sins:
|
||||
1. Omnidirectional witness coverage (must produce blind spots)
|
||||
2. Escape routes that all converge (must produce multiple independent exits)
|
||||
3. No vertical option (must guarantee ≥1 elevated access per district)
|
||||
4. No crowd rhythm (NPC density must vary by day-phase)
|
||||
|
||||
---
|
||||
|
||||
### Directive 2: Destructible Boundaries
|
||||
|
||||
**Fully addressed.** Multi-layer solution across architecture, worldbuilding, and visual grammar.
|
||||
|
||||
**Gestalt** establishes the generator contract:
|
||||
- All tile data pre-exists (no on-the-fly generation on breach)
|
||||
- `TileBehindState` for every wall: `StructuralFill | HiddenRoom | Interstitial`
|
||||
- `AccessTier::BreachOnly` as a first-class access tier
|
||||
- **Guarantee:** Every Full-complexity district must contain ≥1 zone classified `BreachOnly` — a space with no non-destructive access route
|
||||
|
||||
**Tyre** provides the implementation:
|
||||
```rust
|
||||
enum WallBackside {
|
||||
AdjacentSpace, StructuralFill, ServiceVoid, ChunkBoundary, Exterior,
|
||||
}
|
||||
```
|
||||
No tile is ever "void" (ungenerated). 90% of wall tagging is automated; 10% is author choice. `ServiceVoid` (1-3 tiles of pipe/conduit) is visually interesting and supports modified LOS/object-passing.
|
||||
|
||||
**Miri supplement** provides cultural/worldbuilding layer:
|
||||
```yaml
|
||||
behind_boundary:
|
||||
content_type: private_domestic | authority_operational | economic_storage |
|
||||
structural_original | abandoned_era | active_concealment
|
||||
era: era1 | era2 | era3
|
||||
cultural_sensitivity: low | medium | high | extreme
|
||||
contents_hint: null | infrastructure | records | inventory | persons | evidence
|
||||
breach_consequence:
|
||||
immediate: null | alarm | NPC_response | environmental_hazard
|
||||
social: none | community_sanction | faction_response | vendetta_trigger
|
||||
```
|
||||
Era 3 wall in active use with no official record = someone sealed something recently and deliberately.
|
||||
|
||||
**Araminta** provides 3 visual cases: adjacent room (ragged edge, revealed floor, narrowed LOS cone), infrastructure cavity (color-coded conduits at z=1.5: power `#c8b840`, water `#4888c8`, data `#b8b8b8`), perimeter breach (floor underwall strip exposed). Wall infrastructure layer pre-generated, invisible until breach.
|
||||
|
||||
**Ozzie** names the principle: "Blank doesn't mean empty. Blank means unoccupied right now." Wear marks, recent use evidence, a torn piece of fabric on a conduit — these are the generator's promise that spaces were lived in. The historical detail layer must be uniform across the entire space, not concentrated near intended access points.
|
||||
|
||||
---
|
||||
|
||||
### Directive 3: Vertical Scale
|
||||
|
||||
**Fully addressed.** Deferred to v0.4 for implementation, but architecture is complete.
|
||||
|
||||
**Tyre** delivers:
|
||||
- `z_levels: u8` on `DistrictSkeleton` (no hard cap; engineering recommendation: 64)
|
||||
- `MultiBlockReservation` extended with `z_levels: u8` for skyscraper footprints
|
||||
- `FloorZone { z_level, zone_type, zone_palette, access_tier }` for per-floor assignment
|
||||
- `ZLevelLoadState: Loaded | Skeleton | Ungenerated` — lazy loading (only current floor + adjacent filled)
|
||||
- Stairwells and elevators as vertical spines through the building (tile positions preserved across floors)
|
||||
- Target milestone: v0.4 (~7 dev-days)
|
||||
|
||||
**Gestalt** adds system-level design:
|
||||
- **Z-bands** (floor groupings with similar social function) as the generator's planning unit — not floor-by-floor
|
||||
- Vertical access tier gradient: ground = most public; top = most restricted (monotonically non-decreasing)
|
||||
- **Guarantee:** Every tall structure (z_band_count ≥ 3) must have a roof zone classified `Insider` or `BreachOnly` accessible by non-obvious route
|
||||
|
||||
**Miri supplement** provides heritage-derived vertical social hierarchy:
|
||||
- Corporate: bottom = labor / mid = operations / top = executive
|
||||
- Commission-institutional: bottom = public services / top = secure records (inverted from corporate)
|
||||
- Iron-heritage occupation: horizontal solidarity networks per floor; outsider is immediately noticed
|
||||
- Cross-floor `Tactical` triangle: NPC A (floor 3) + NPC B (floor 17) + NPC C (floor 42) — player needs vertical access to work the triangle
|
||||
|
||||
**Araminta** provides visual grammar:
|
||||
- 4 height tiers (S1 = 1-3 floors, S2 = 4-10, S3 = 11-30, S4 = 30+)
|
||||
- Shadow is the primary height signal: 2–40 visual tiles, hardness scales with tier
|
||||
- Rooftop vocabulary by tier: S1 simple parapet; S2 HVAC clusters; S3 complex mechanical arrays; S4 antenna farm
|
||||
- Station interior: penumbra width (ambient occlusion) replaces directional shadow
|
||||
|
||||
**Ozzie** names the payoff: in top-down, vertical gives you the view DOWN. The floor-above perspective = detective overview, assassin planning view, tycoon seeing the whole market district at once. Generation sin: identical floors with just different lock levels.
|
||||
|
||||
---
|
||||
|
||||
### Directive 4: Dynamic World Modification
|
||||
|
||||
**Fully addressed.** Generator is immutable; modifications layer on top.
|
||||
|
||||
**Core principle (Tyre + Gestalt in full agreement):** The generator produces the world as it was. Modifications are a delta layer applied at render time.
|
||||
|
||||
**Tyre** provides `ChunkMutations`:
|
||||
```rust
|
||||
struct ChunkMutations {
|
||||
tile_overrides: Vec<TileOverride>,
|
||||
structural_changes: Vec<StructuralChange>,
|
||||
placed_objects: Vec<PlacedObject>,
|
||||
removed_objects: Vec<ObjectId>,
|
||||
}
|
||||
```
|
||||
Pending mutations can be applied to unvisited districts (stored at `PreparedDistrict` level, applied immediately at chunk fill time).
|
||||
|
||||
**Gestalt** provides the broader `WorldStateDelta` model covering all game state changes: `StructuralDamage`, `WallBreached`, `DoorStateChanged`, `ObjectModified`, `TileTypeChanged`, `AccessTierChanged`, `NpcRemoved`. For large-scale events: soft re-generation via `original_seed XOR event_seed`.
|
||||
|
||||
**Miri** provides the cultural response layer: trauma events intensify culture, not transform it. Heritage roots determine community response patterns. Active modification state decays toward baseline at heritage-root-dependent rates. NPC pattern weight shifts post-trauma: ANCHOR/WITNESS/REMNANT increase; normal distribution shifts.
|
||||
|
||||
**Nigel** frames it as replayability: baseline → playthrough divergence is the key mechanism. Storyteller-activated structural fragilities produce *caused* destruction, not random damage. Player-caused destruction is private geographic knowledge (the hole in the wall exists only in your playthrough). Fragility tags should be present in <5% of infrastructure chunks per district.
|
||||
|
||||
**Araminta** provides 5 destruction visual stages (Active → Fresh Aftermath → Stabilized → Reconstruction → Healed Scar) with specific hex values at each stage. Key visual: open-sky tile `#c8d8f0` at 100% brightness = "roof removed, open to sky" — the only floor-layer element brighter than ambient. Also affects gameplay: LOS changes dramatically in open-roofed areas.
|
||||
|
||||
---
|
||||
|
||||
### Directive 5: Entity-Carried Chunks as Core
|
||||
|
||||
**Addressed. Architectural split requires resolution (see OQ-R3-D above).**
|
||||
|
||||
Cultural grammar is settled regardless of architecture choice (Miri supplement):
|
||||
- Trains (`BoundedLinear`): class-sequence social grammar. Temporal pressure. Witness compactness. Social compression.
|
||||
- Spaceships (between systems): institutionally suspended environment. No Commission jurisdiction. No external communication. Social roles strip. Heritage roots determine behavior in suspension (Frost: doubles down on privacy; Tide: ship community expands; Salt: grey-market window opens).
|
||||
- Universal: `transit_social_modifier` adjusts trust-building rate (up), privacy level (down), enforcement level (down), internal information flow (up), external information flow (blocked until arrival).
|
||||
|
||||
Ozzie names the principle: mobile environments are social pressure cookers. The journey is the content. The space changes social state over time.
|
||||
|
||||
---
|
||||
|
||||
### Directive 6: Grid Breathing Both
|
||||
|
||||
**Resolved.** See OQ-R3-A above.
|
||||
|
||||
Summary: `DistrictLayoutMode: Grid | Organic`. Block offsets and rotations up to 45°. Streets as negative space in organic mode. Angular landmark at grid rotation seams. Heritage roots predict which mode a district uses. Mixed within district via block-level `street_geometry` assignment.
|
||||
|
||||
---
|
||||
|
||||
### Directive 7: Palette Granularity
|
||||
|
||||
**Resolved.** Modifier system, not more base palettes.
|
||||
|
||||
**Tyre** provides the data structure:
|
||||
```rust
|
||||
struct ZonePalette {
|
||||
base: BasePalette,
|
||||
modifiers: Vec<PaletteModifier>,
|
||||
}
|
||||
enum PaletteModifier {
|
||||
EconomicFunction(EconomicModifier), // industrial farming vs rustic farming
|
||||
Era(Era),
|
||||
Faction(FactionModifier),
|
||||
HeritageTint(HeritageRoot),
|
||||
ClimaticCondition(Climate),
|
||||
}
|
||||
```
|
||||
|
||||
**Araminta** expands to 8 base terrain types (T1 temperate farmland + T2 industrial/greenhouse as the two farmland types that directly address the lead directive) and provides 3 modifier axes: heritage root (structure material character), economic tier (condition/density), era (material generation) — plus optional faction overlay. Result: ~40-50 strongly differentiated visual feels; 200+ meaningfully distinct combinations.
|
||||
|
||||
**Miri** provides the conceptual model: terrain type = material vocabulary (what exists here); heritage root = organizational grammar (how it's arranged, decorated, related). Full table of 10 heritage roots × organizational principle × visual signature. Base game requirement, not DLC. DLC expands variant assets; the grammar rules are core.
|
||||
|
||||
---
|
||||
|
||||
### Directive 8: Not Every Place Serves Every Playstyle
|
||||
|
||||
**Fully addressed.** Team converges on: mismatch is content, not failure.
|
||||
|
||||
**Gestalt** formalizes with a 3-tier guarantee system:
|
||||
- **Tier 1 Universal** (all inhabited): Social Hub + Informal Zone + Encounter Corridor
|
||||
- **Tier 2 Full-only** (Full-complexity): Traffic Chokepoint + Institutional Space + Insider Space + Economic Node (with terrain-aware expressions)
|
||||
- **Tier 3 Conditional** (parameter-dependent): Elevated Vantage, Egress Multiplicity, Temporal Opacity Window, Economic Asymmetry Signal, Power Gradient Visibility
|
||||
|
||||
Guarantee audit is now conditional-aware. A Minimal-complexity farmstead gets 3 checks. A Full-complexity urban hub gets up to 11.
|
||||
|
||||
**Miri** provides the playstyle affinity matrix: 15 setting types × 5 playstyles, rated Primary/Secondary/Weak/Poor. "Poor" doesn't block a playstyle — it means the generator didn't budget for it. Players who insist on weak-affinity playstyles find sparse, unsatisfying affordances.
|
||||
|
||||
**Nigel** names the deeper principle: playstyle mismatch reveals what kind of world this is. Early engagement friction is discovery, not failure. The only hard requirement for Full-complexity districts: entry points for all playstyles (the 7 archetypes). Not equal depth — entry points.
|
||||
|
||||
**Ozzie** confirms: the farming settlement forces the assassin to use different skills at a different pace. The mismatch makes you understand the world. Generation sin: making the backwater too empty to have any social architecture. A settlement with 80 people who've been there 40 years should have denser social graphs per capita than a transit hub with 2000 transient workers.
|
||||
|
||||
---
|
||||
|
||||
### Directive 9: Insignificant as Social Lens
|
||||
|
||||
**Fully addressed.** Miri delivers the five-lens analysis.
|
||||
|
||||
**Miri** demonstrates same backwater (Stone/Tide, ~150 people, 40 years, one tavern, no faction presence) through five lenses:
|
||||
- **Investigation:** Everything is visible. Challenge is not finding information — it's that the information knows about you. Twist: the insignificant backwater is where someone goes to HIDE. One anomalous resident who shouldn't be here.
|
||||
- **Tycoon:** Land rights, water rights, one trading route. The community is captive. Economic maneuvers are conducted entirely in public.
|
||||
- **Dating sim:** No anonymity phase — you're known by day three. The romantic play is not "meet and discover" but "earn belonging."
|
||||
- **Political drama:** Personal-scale coalition politics at human scale. No institutional mediation. Win Aia's family, lose Torval's approval.
|
||||
- **Assassination:** Locally-significant backwater has Poor affinity by default. Exception: a network-significant person gone to ground here. The hardest assignment.
|
||||
|
||||
Minimum content for even Moderate-complexity insignificant districts: one anomalous presence (investigation hook), one economic chokepoint (tycoon hook), one sustained social gathering (dating sim hook), one contested allocation decision (political hook), one visitor of uncertain identity (assassination hook, latent). One NPC with sufficient complexity can provide all five simultaneously.
|
||||
|
||||
**Ozzie** states the principle: the playstyle is the starting assumption the world eventually corrects. Players discover that what they were looking for is a simplification of a richer reality. *That is asymmetric awareness.*
|
||||
|
||||
---
|
||||
|
||||
## Section 3: SignificanceTier / ComplexityTier / DramaDensity — Resolution
|
||||
|
||||
**Substantially resolved. One naming/placement question remains for Round 4.**
|
||||
|
||||
### What the Three Parameters Are
|
||||
|
||||
All three participants agree on the conceptual structure:
|
||||
|
||||
| Concept | What it measures | Type |
|
||||
|---|---|---|
|
||||
| Network significance | How important this location is in the galaxy | Static, set at system generation |
|
||||
| Generator budget | How much content the generator produces here | Static, set at Phase 1 |
|
||||
| Active narrative intensity | How much drama the storyteller is firing | Dynamic, storyteller-modified at runtime |
|
||||
|
||||
### The Naming Dispute
|
||||
|
||||
| Participant | Network significance | Generator budget | Active narrative |
|
||||
|---|---|---|---|
|
||||
| Gestalt | ~~SignificanceTier~~ (RETIRED) | ComplexityTier | DramaDensity |
|
||||
| Tyre | SignificanceTier (RETAINED) | ComplexityTier | DramaDensity (NOT on DistrictSkeleton) |
|
||||
| Nigel | WorldTier | ComplexityTier | DramaDensity |
|
||||
|
||||
### What the Canonical Struct Says
|
||||
|
||||
Tyre's §6.4 (the canonical DistrictSkeleton) retains `significance: SignificanceTier` as a struct field. DramaDensity is explicitly **not** on the DistrictSkeleton — it is runtime storyteller state.
|
||||
|
||||
Gestalt's §6.5 retires SignificanceTier and absorbs it into ComplexityTier + network position metadata, with DramaDensity as a runtime parameter.
|
||||
|
||||
### Resolution
|
||||
|
||||
**Substance**: all three participants agree. The DistrictSkeleton carries two static parameters (network significance + generator budget). DramaDensity is NOT a generator output; it lives in runtime storyteller state.
|
||||
|
||||
**Naming and placement**: Tyre's struct is the implementation reference. His `SignificanceTier` enum captures network significance. Nigel's `WorldTier` is a cleaner name for the same concept. **This is an open naming question for the D-record.**
|
||||
|
||||
The key constraint relationship (all three agree): network significance constrains ComplexityTier ceiling; ComplexityTier constrains DramaDensity maximum; DramaDensity is always ≤ ComplexityTier capacity.
|
||||
|
||||
---
|
||||
|
||||
## Section 4: Canonical DistrictSkeleton — Status
|
||||
|
||||
**Produced.** Tyre §6.4 provides the authoritative Rust struct.
|
||||
|
||||
### New Fields Added in Round 3
|
||||
|
||||
To the struct previously defined in Rounds 1–2:
|
||||
|
||||
```rust
|
||||
// Added in Round 3:
|
||||
significance: SignificanceTier, // network position (naming TBD)
|
||||
layout_mode: DistrictLayoutMode, // Grid | Organic
|
||||
setting: SettingType, // merged SettingGeometry + TerrainType
|
||||
|
||||
// On MultiBlockReservation (vertical scale):
|
||||
z_band_count: u8,
|
||||
floor_count: u8,
|
||||
z_band_zones: Vec<ZoneDefinition>,
|
||||
vertical_corridors: Vec<VerticalCorridorSpec>,
|
||||
|
||||
// On SocialSitePlacement.triangles:
|
||||
purposes: Vec<TrianglePurpose>, // on TriangleAssignment
|
||||
|
||||
// On ZonePalette:
|
||||
modifiers: Vec<PaletteModifier>, // palette modifier system
|
||||
|
||||
// Added by Gestalt §10:
|
||||
vertical_structure: VerticalStructure, // Flat | Medium | Tall | Skyscraper
|
||||
breach_only_zones: Vec<ZoneId>, // ≥1 for Full-complexity districts
|
||||
```
|
||||
|
||||
### What Is NOT on the DistrictSkeleton
|
||||
|
||||
- `DramaDensity` — runtime storyteller state (all three agree)
|
||||
- `assassination_difficulty` — derived descriptor on SocietyProfile (not skeleton-level)
|
||||
- `transit_social_modifier` — on MobileChunk, not static district skeleton
|
||||
|
||||
### Memory Budget
|
||||
|
||||
Tyre estimates ~8-14 KB per district with all Round 3 additions. 300 worlds × ~6 districts × ~12 KB = ~21 MB total for all skeletons. Trivial.
|
||||
|
||||
---
|
||||
|
||||
## Section 5: Items Ready to Become D-Records
|
||||
|
||||
The following decisions have achieved full or near-full team consensus and are ready to be formally recorded. Listed in priority order.
|
||||
|
||||
**D-READY-1: DistrictLayoutMode — Grid and Organic Support**
|
||||
Tyre + Araminta + Miri + Nigel + Ozzie all agree. The D-094 hierarchy defines data sizes, not geometry. `DistrictLayoutMode: Grid | Organic { placements }` with `BlockPlacement { offset, rotation_steps (max 45°), street_width_factor }`. Adjacent districts can have different modes. Implementation cost: ~3 dev-days.
|
||||
|
||||
**D-READY-2: Guarantee Tier System — Universal / Full-Only / Conditional**
|
||||
Gestalt defines the 3-tier system. All participants apply it. Tier 1 (all inhabited): Social Hub + Informal Zone + Encounter Corridor. Tier 2 (Full-complexity): Traffic Chokepoint, Institutional Space, Insider Space, Economic Node. Tier 3 (conditional): Elevated Vantage, Egress Multiplicity, Temporal Opacity Window, etc. Replaces the flat 11-check audit with conditional-aware logic.
|
||||
|
||||
**D-READY-3: TrianglePurpose Enum**
|
||||
Gestalt + Tyre agree. `TrianglePurpose: Investigation | Economic | Social | Political | Tactical | Mundane`. Tactical = Target + Protector + Informant/Witness (assassination context). Triangles carry `Vec<TrianglePurpose>`. ~20 lines of code.
|
||||
|
||||
**D-READY-4: WallBackside / TileBehindState**
|
||||
Gestalt (TileBehindState: StructuralFill | HiddenRoom | Interstitial) and Tyre (WallBackside: AdjacentSpace | StructuralFill | ServiceVoid | ChunkBoundary | Exterior) are complementary, not contradictory. Combined: every wall tile is tagged; no tile in a generated chunk is ever ungenerated void; `AccessTier::BreachOnly` is a first-class access tier; Full-complexity districts guarantee ≥1 BreachOnly zone.
|
||||
|
||||
**D-READY-5: Dynamic Modification via Overlay (Not Re-generation)**
|
||||
Tyre (ChunkMutations) + Gestalt (WorldStateDelta) agree completely. Generator state is immutable after Phase 1. Modifications are overlays. Pending mutations at PreparedDistrict level for unvisited districts. Soft re-generation for large-scale events via `original_seed XOR event_seed`.
|
||||
|
||||
**D-READY-6: ZonePalette Modifier System**
|
||||
Tyre + Araminta agree. `ZonePalette { base: BasePalette, modifiers: Vec<PaletteModifier> }`. 8 base terrain types (T1 rustic farmland, T2 industrial farmland are the split that addresses the lead directive). 3 modifier axes: heritage root, economic tier, era. Optional faction overlay.
|
||||
|
||||
**D-READY-7: Horizon View Corridor as Coastal Guarantee**
|
||||
Araminta + Gestalt agree. Mandatory negative-space view corridor (≥8 vt unobstructed) in coastal district skeleton. Tier 2 guarantee for any district with Water terrain on one boundary. Reservation prevents warehouse placement at waterfront.
|
||||
|
||||
**D-READY-8: Assassin Lens Spatial Guarantees (A-1 through A-4)**
|
||||
Gestalt defines; Miri, Nigel, Ozzie confirm. Four derived guarantees (Elevated Vantage, Egress Multiplicity, Temporal Opacity Window, Non-Institutional Route). These are derived properties from existing spatial configuration — not new spaces tagged for assassins.
|
||||
|
||||
**D-READY-9: Heritage Grammar Overlay for Non-Urban Palettes**
|
||||
Miri + Araminta agree (cross-domain). Terrain type = material vocabulary; heritage root = organizational grammar. 10 heritage roots × organizational principle. Base game, not DLC. Modifier flags at chunk fill time.
|
||||
|
||||
**D-READY-10: Non-Urban Informal Zone Typology**
|
||||
Miri: informal zone redefined from institutional absence to outside community social field. Three types: social_permission / physical_distance / utilitarian_cover. Generator tags per type; heritage root determines which appears.
|
||||
|
||||
**D-READY-11: Vertical Scale Architecture**
|
||||
Tyre + Gestalt + Miri agree. z-levels u8 field; practical cap 64; lazy z-level loading; FloorZone per-floor assignment; z-bands as generator planning units; vertical access tier gradient; roof as mandatory discovery zone for tall structures. Target: v0.4.
|
||||
|
||||
**D-READY-12: Trauma Events as EraModification Subtypes**
|
||||
Miri: `ModificationType::TraumaEvent` with subtypes (PhysicalDestruction, EconomicDisruption, PoliticalShock, ViolenceEvent, MigrationShock) + `cultural_aftermath: HeritageRootResponse`. Active modification state decays at heritage-root-dependent rates.
|
||||
|
||||
---
|
||||
|
||||
## Section 6: New Open Questions for Round 4
|
||||
|
||||
### OQ-R4-A: Vessel Architecture Decision (Tyre vs Nigel)
|
||||
|
||||
The two proposals are architecturally incompatible:
|
||||
- **Tyre:** `MobileChunk` as entity-carried ChunkData. Vessels exist as world entities. Docked state connects to static chunks. In-transit uses scrolling exterior visual buffer. Cost ~9.5 dev-days.
|
||||
- **Nigel:** Instanced district model. Vessel is a district generated at journey-start, lifespan at arrival. Visual movement is client-side animation. No coordinate complexity. Cheaper and simpler but vessels don't exist between voyages.
|
||||
|
||||
Questions to resolve: Do vessels need to be persistently world-present (docked at port, visible from the dock)? Or is it acceptable for vessels to only exist during voyages? This decision drives the streaming model, world map representation, and NPC simulation behavior.
|
||||
|
||||
### OQ-R4-B: SignificanceTier Naming and Scope
|
||||
|
||||
Gestalt retires `SignificanceTier`; Tyre retains it; Nigel proposes `WorldTier`. The substance is agreed (three orthogonal parameters). The D-record needs a canonical name and scope definition. Tyre's struct has the implementation vote. Does the team accept `significance: SignificanceTier` or rename to `world_tier: WorldTier`?
|
||||
|
||||
### OQ-R4-C: Assassination Difficulty Descriptor Placement
|
||||
|
||||
Miri proposes `assassination_difficulty: low/medium/high/extreme` as a derived descriptor from society profile. Open question: is this stored on the DistrictSkeleton (Phase 1 output), on the society profile itself, or computed on demand by the assassination gameplay system? Miri asks Gestalt for the integration point.
|
||||
|
||||
### OQ-R4-D: Heritage Grammar Overlay Representation
|
||||
|
||||
Miri's 10-row heritage grammar table needs encoding for chunk fill consumption. Miri asks Araminta: per-heritage modifier objects that chunk fill applies, or lookup tables within terrain palette assets? This affects both the authoring workflow and the chunk fill pipeline.
|
||||
|
||||
### OQ-R4-E: "One NPC, Five Lenses" — Does the 10-Axis Model Cover It?
|
||||
|
||||
Miri's minimum content requirement for insignificant districts (one anomalous presence, one economic chokepoint, one gathering rhythm, one contested allocation, one visitor of uncertain identity) could in theory be one NPC. Does the current 10-axis NPC model already support providing all five playstyle entry hooks simultaneously? Miri asks Nigel.
|
||||
|
||||
### OQ-R4-F: Soft Re-Generation Coherence
|
||||
|
||||
Gestalt's soft re-generation via `original_seed XOR event_seed` for large-scale events — does XOR-based reseeding produce visually/historically coherent results? Or does it produce results that look random rather than caused? Ozzie's principle is that destruction must be *caused*, not *random*. The cultural response model (Miri) requires that the aftermath feel like an intensification of existing character. Does XOR-seeded regeneration preserve this, or does it need a more structured approach (e.g., partial re-stamp with damage parameters)?
|
||||
|
||||
---
|
||||
|
||||
## Section 7: Cross-Cutting Themes
|
||||
|
||||
### 1. The Information Landscape Is the Game
|
||||
|
||||
Every playstyle — investigation, tycoon, dating sim, political drama, assassination — is fundamentally an information game. The generator's job is to produce a world where information is asymmetrically distributed, where discovering it requires skill and effort, and where the same information means different things depending on what lens you're using. The generator doesn't produce five games. It produces one information landscape that five lenses read differently.
|
||||
|
||||
This is the Round 3 synthesis of what the game *is*. Miri's formulation: "one NPC, five lenses." Ozzie's formulation: "asymmetric awareness — players discover that what they were looking for is a simplification of a richer reality."
|
||||
|
||||
### 2. The Generator Produces Capacity; the Storyteller Fires It
|
||||
|
||||
A consistent architectural boundary emerged and hardened across all participants:
|
||||
|
||||
- **Generator state** (Phase 1 + Phase 2): immutable after production. Deterministic from seed. The capacity of the world — what's possible here.
|
||||
- **Storyteller state** (runtime): DramaDensity, triggered modules, activated triangles, fragility explosions. The utilization of the world — what is happening here right now.
|
||||
- **Delta layer** (post-generation): modifications applied by simulation events. The history of the world — what has happened to it since.
|
||||
|
||||
These three layers compose at render time. The generator never re-runs.
|
||||
|
||||
### 3. Organic vs Grid Is a History Statement
|
||||
|
||||
Miri's worldbuilding insight, confirmed by all: grid = power imposed; organic = power negotiated. The layout mode of a district is a legible historical record of who built it and under what conditions. Commission-planned stations are grid. Pioneer settlements are organic. Old quarters that predate the Commission are organic in a way that tells you they were here before the plan. This is not just visual variety — it is *architectural history as information*.
|
||||
|
||||
### 4. Vertical Is Information Asymmetry Made Spatial
|
||||
|
||||
The skyscraper is a compressed information gradient. Lower floors have information about what's happening up high (the lobby worker knows who enters). Upper floors have information about what's happening below (the executive commissioned it). The vertical access challenge is the access tier system made physical. Getting to floor 30 is earning the information that lives there.
|
||||
|
||||
Ozzie names it: in top-down, vertical gives you the view DOWN. The detective's overview. The assassin's planning position. The tycoon seeing the whole district. This is a distinct gameplay affordance that flat districts cannot produce.
|
||||
|
||||
---
|
||||
|
||||
## Section 8: Qatux Observations
|
||||
|
||||
**For the record:**
|
||||
|
||||
1. **The canonical DistrictSkeleton is Tyre's §6.4.** Gestalt's §10 is the design specification (field names and semantic intent); Tyre's §6.4 is the implementation specification (Rust syntax and types). They are compatible with one exception: `SignificanceTier` vs. retired. The D-record should canonicalize the name.
|
||||
|
||||
2. **DramaDensity belongs in simulation state, not the generator.** All three participants who addressed the reconciliation (Gestalt, Tyre, Nigel) agree on this. The DistrictSkeleton carries the capacity ceiling. The storyteller system carries the current value.
|
||||
|
||||
3. **The vessel architecture decision is blocking.** Miri supplement provides cultural grammar for both models. Araminta's coastal palette is ready for maritime templates. Nigel's instanced district model is architecturally cleaner. Tyre's entity-carried model is more powerful but more complex. This must be decided in Round 4 — maritime and transit templates cannot be authored until the architecture is chosen.
|
||||
|
||||
4. **Ozzie's 4 assassination generation sins are testable properties.** They are not design principles but verifiable spatial guarantees: omnidirectional witness coverage, converging escape routes, no vertical option, no crowd rhythm. These can be added to the guarantee audit as conditional checks.
|
||||
|
||||
5. **Miri's `behind_boundary` descriptor (cultural sensitivity + social consequence) is a cross-domain requirement.** It requires coordination between: Tyre (WallBackside implementation), Miri (cultural sensitivity values per heritage root), Araminta (visual grammar for breach consequences), and Gestalt (BreachOnly guarantee and scenario instantiation). This is the kind of cross-domain dependency that needs a D-record to anchor it before templates are authored.
|
||||
|
||||
6. **The 45° organic rotation cap should be explicitly stated in the D-record.** It is a hard technical constraint, not a design preference. Beyond 45°, tile-based pathfinding produces unacceptable artifacts. Players expecting flowing curves will not get them from the tile engine — they will get angular organic layouts.
|
||||
|
||||
---
|
||||
|
||||
**Next:** Round 4 (if required) should resolve: vessel architecture decision (OQ-R4-A), SignificanceTier naming (OQ-R4-B), and whether the canonical struct is formally signed off for D-record production. The pipeline is architecturally sound. What remains is settling the naming disputes and the one structural split.
|
||||
@@ -0,0 +1,368 @@
|
||||
# Generator Architecture Workshop — Round 4 Notes
|
||||
|
||||
**Workshop:** Generator Architecture (#562)
|
||||
**Round:** 4 — Final Convergence
|
||||
**Date:** 2026-02-27
|
||||
**Participants:** Gestalt, Tyre, Miri, Araminta, Nigel, Ozzie
|
||||
**Documented by:** Qatux
|
||||
|
||||
---
|
||||
|
||||
## 1. Round 4 Assignment Summary
|
||||
|
||||
Round 4 had three categories of work:
|
||||
|
||||
1. **Open question resolution** — all six OQs from Round 3 carried forward. All are now resolved.
|
||||
2. **Concrete demonstration** — Miri's "write the NPC" exercise (OQ-R4-E). Complete.
|
||||
3. **D-record sign-off** — all 12 items from the D-ready list reviewed and approved by all six participants. Two additional items (D-READY-13 and D-READY-14) identified and added.
|
||||
|
||||
Pre-confirmed lead decisions (Round 4 input):
|
||||
- **WorldTier** wins over SignificanceTier
|
||||
- **Entity-carried MobileChunk** is core architecture
|
||||
- **DramaDensity** is runtime storyteller state, NOT on DistrictSkeleton
|
||||
- **Heritage grammar overlay** is base game, not DLC
|
||||
|
||||
---
|
||||
|
||||
## 2. Open Question Resolutions
|
||||
|
||||
### OQ-R4-A: Vessel Architecture — Resolved (Lead Directive)
|
||||
|
||||
**Decision: Entity-carried MobileChunk. Tyre's architecture. Lead-confirmed.**
|
||||
|
||||
All participants accepted. Tyre provided the final canonical `MobileChunk` struct. Nigel formally withdrew his instanced-district model and stated why the entity-carried model is superior for accumulating vessel history across voyages. Ozzie provided the player-experience verdict: the docked ship must physically exist and be present at the dock — this is load-bearing for the game's fundamental promise of a persistent world.
|
||||
|
||||
Key rationale (Ozzie): "The ship at the dock is a trust signal. It tells me: this happened. That voyage was a real event in a real world."
|
||||
|
||||
Additional vessel requirement raised by Ozzie: **departure schedules** must be a generator output. Vessels docked without scheduled departures produce port graveyards. The departure window is both world-time structure and a player urgency driver.
|
||||
|
||||
### OQ-R4-B: WorldTier Naming — Resolved (Lead Directive)
|
||||
|
||||
**Decision: `world_tier: WorldTier` on DistrictSkeleton.**
|
||||
|
||||
`SignificanceTier` is retired. `WorldTier` correctly describes what the field measures: simulation fidelity budget allocated to this location, not narrative importance. A narratively critical backwater can be `WorldTier::Local + ComplexityTier::Full`.
|
||||
|
||||
**Canonical WorldTier enum (Tyre, final):**
|
||||
```
|
||||
Core — Hub system. Full simulation, high faction pressure.
|
||||
Regional — Regional importance. 1–4 districts, partial full-budget.
|
||||
Local — Small community. 1 district, limited budget.
|
||||
Transit — Transit stop. Pass-through only, minimal simulation.
|
||||
Dormant — Not simulated until player approaches.
|
||||
```
|
||||
|
||||
WorldTier → ComplexityTier ceiling constraint table:
|
||||
|
||||
| WorldTier | ComplexityTier max |
|
||||
|-----------|-------------------|
|
||||
| Core | Full |
|
||||
| Regional | Full |
|
||||
| Local | Moderate |
|
||||
| Transit | Minimal |
|
||||
| Dormant | Empty |
|
||||
|
||||
### OQ-R4-C: Assassination Difficulty Descriptor — Minor Tension Noted
|
||||
|
||||
**Two valid positions emerged. The tension is recorded here for the D-record.**
|
||||
|
||||
**Gestalt:** `assassination_difficulty` is computed on demand — a function of `(SocietyProfile, SpatialGuarantees, StorytellerState) → DifficultyDescriptor`. Never stored. Called at contract acceptance and during pre-op planning. Rationale: the inputs include dynamic runtime state (active guard levels, current NPC distribution), so any stored value is stale.
|
||||
|
||||
**Miri:** `DerivedDistrictAnalysis` struct on `DistrictSkeleton`, computed at Phase 1 from society profile parameters (observation_density × information_liquidity × aftermath_engagement). Stored, not runtime-mutable. Rationale: Phase 1 Tactical triangle instantiation logic needs it before the gameplay system runs; the cultural difficulty of assassination is stable regardless of storyteller state.
|
||||
|
||||
**The actual tension:** Gestalt's position captures dynamic inputs that Miri's doesn't. Miri's position captures a Phase 1 dependency that Gestalt's doesn't address. These are not mutually exclusive: the `DerivedDistrictAnalysis` on the skeleton could provide the **cultural baseline** (static, Phase 1), while the on-demand computation combines that baseline with runtime state for the player-facing assessment. This synthesis is recommended for the D-record.
|
||||
|
||||
**Miri's proposed `DerivedDistrictAnalysis` struct:**
|
||||
```rust
|
||||
struct DerivedDistrictAnalysis {
|
||||
assassination_difficulty: AssassinationDifficulty,
|
||||
assassination_target_density: u8,
|
||||
primary_playstyles: [AffinityLevel; 5],
|
||||
}
|
||||
enum AssassinationDifficulty { Low, Medium, High, Extreme }
|
||||
```
|
||||
|
||||
**Qatux flag:** The D-record should specify both the stored baseline (`DerivedDistrictAnalysis`) and the on-demand runtime computation. They serve different purposes.
|
||||
|
||||
### OQ-R4-D: Heritage Grammar Overlay Representation — Resolved
|
||||
|
||||
**Decision: Data-driven `HeritageGrammarOverlay` structs in TOML/YAML content files (Miri) or equivalent (Araminta). Not lookup tables in palette assets. Not hardcoded.**
|
||||
|
||||
Miri proposed per-heritage `HeritageGrammarOverlay` Rust structs loaded from authored data, injected into ZonePalette at chunk fill time. Araminta proposed per-heritage TOML modifier files with the same separation: Araminta authors visual/arrangement grammar, Miri authors cultural/organizational grammar. Both converge on the same authoring model with aligned field sets.
|
||||
|
||||
**Key rule:** Heritage grammar modifier is applied at Phase 2 chunk fill time (not Phase 1), with one exception: `gathering_probability` influences Phase 1 block quarter pre-assignment.
|
||||
|
||||
**Authoring domain separation:**
|
||||
- Miri: organizational principles, boundary character, spacing, social grammar fields
|
||||
- Araminta: visual expression — object sets, arrangement algorithms, lighting temperature, overhead character
|
||||
|
||||
**Shared requirement:** The `ObjectTag` vocabulary must be co-maintained across both domains.
|
||||
|
||||
### OQ-R4-E: "One NPC, Five Lenses" — Resolved (Miri NPC exercise)
|
||||
|
||||
**Decision: One NPC can provide all five hooks. Minimum 3 NPCs required for intra-seed replayability.**
|
||||
|
||||
Miri produced **Ysabel Vorn**, a full 10-axis NPC profile for Harrow Drift (Backwater/Moderate farming settlement, Stone/Tide heritage). All five playstyle lenses demonstrated in detail. The 10-axis model covers **4.5 of 5** hooks.
|
||||
|
||||
**The gap: Axis 11 (Network Footprint).** The 10-axis model cannot distinguish between an NPC who is genuinely locally insignificant and one who is locally insignificant in appearance but carries network-significant information (e.g., a hiding Commission data analyst). The assassination hook for Ysabel is only available to a player with network-level intelligence access — locally, she registers as a trusted Anchor with no enemies.
|
||||
|
||||
**Proposed Axis 11:**
|
||||
```
|
||||
network_footprint: Option<NetworkFootprintTag>
|
||||
```
|
||||
- `None` for most procedural NPCs
|
||||
- `Some(tag)` for authored scenario NPCs; records external actors, reason for significance, and access tier required to see the footprint
|
||||
- Does not change local NPC behavior; enables Tactical triangle instantiation for the "false backwater" scenario type
|
||||
|
||||
**Nigel's finding on emergence:** One NPC provides zero intra-seed emergent behavior (no relationships = no triangles). Minimum for meaningful replayability within a seed: **3 NPCs — one functional triangle**. Miri's five minimum content types should be distributed across a minimum triangle, not collapsed into a single NPC.
|
||||
|
||||
### OQ-R4-F: Soft Re-Generation — Resolved. XOR Unanimously Rejected.
|
||||
|
||||
**Decision: `DamageOverlay` (structured damage parameters) for all in-playthrough events. XOR reseeding explicitly rejected.**
|
||||
|
||||
All four participants who addressed this (Gestalt, Tyre, Nigel, Ozzie) reached the same verdict by independent paths.
|
||||
|
||||
**Why XOR fails (Gestalt + Tyre tile-level demonstration):**
|
||||
- `original_seed XOR event_seed` produces a different block, not a damaged version of the original
|
||||
- Tile positions shift, zone assignments change, the pressure regulator moves — nothing is spatially coherent with the event source
|
||||
- Fails Ozzie's test: "destruction must be caused, not random"
|
||||
- The result looks *replaced*, not *damaged*
|
||||
|
||||
**The correct approach — `DamageOverlay`:**
|
||||
```rust
|
||||
struct DamageOverlay {
|
||||
overlay_type: DamageOverlayType,
|
||||
epicenter: ChunkLocalPos,
|
||||
radius: f32,
|
||||
intensity: f32,
|
||||
scatter_seed: u64, // variation WITHIN damage zone only
|
||||
}
|
||||
enum DamageOverlayType { GasExplosion, Fire, Structural { collapse_direction }, Flooding }
|
||||
```
|
||||
Per-tile damage is computed from distance to epicenter + scatter. The original chunk is unchanged. The cause is legible from the output: epicenter identifiable, damage gradient visible.
|
||||
|
||||
**`RegenerationStrategy` enum (Gestalt):**
|
||||
```rust
|
||||
enum RegenerationStrategy {
|
||||
LocalOverlay(DamageParameters), // in-playthrough — generator unchanged
|
||||
SoftReseed { seed_modifier: u64 }, // scenario-boundary temporal changes only
|
||||
FullReseed, // era-level discontinuities only
|
||||
}
|
||||
```
|
||||
**Hard rule:** In-playthrough events are ALWAYS `LocalOverlay`. `SoftReseed` and `FullReseed` are scenario-setup tools, not event responses. The generator never re-runs for player-witnessed events.
|
||||
|
||||
XOR-seeding remains acceptable ONLY for district-level regeneration under a different historical assumption (Phase 1 re-run for a different era branch — not in-playthrough damage).
|
||||
|
||||
---
|
||||
|
||||
## 3. Rooftop Bar Clause — Amended
|
||||
|
||||
**Old guarantee:** Every tall structure (z_band_count ≥ 3) must have a roof zone classified `Insider` or `BreachOnly`, accessible by non-obvious route.
|
||||
|
||||
**Problem:** This prohibited valid public social destinations (rooftop bars, observation galleries, religious sky gardens).
|
||||
|
||||
**Amended guarantee — Vertical Discovery:**
|
||||
```rust
|
||||
enum RooftopConfig {
|
||||
Restricted {
|
||||
zone_class: AccessTier, // must be Insider or BreachOnly
|
||||
access_route: RouteObviousness, // must be NonObvious
|
||||
},
|
||||
PublicWithHiddenLayer {
|
||||
primary_zone: ZoneType, // Social Hub, Economic Node, etc.
|
||||
secondary_restricted: ZoneSpec, // always present; Insider or BreachOnly
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
**The inviolable rule:** Every tall structure must have *something* at the top that is not fully accessible from below. The discovery layer is mandatory. The public/private split of the primary space is not.
|
||||
|
||||
Heritage-root-driven default:
|
||||
- Iron trade towers: `Restricted` (roof belongs to guild leadership)
|
||||
- Commission institutional: `PublicWithHiddenLayer` (public observation gallery + restricted records floor)
|
||||
- Frost isolated structures: `Restricted` (roof is heating systems, not a social space)
|
||||
|
||||
Visual grammar (Araminta):
|
||||
- Public rooftop: warm amber lighting cluster (`#f0b840`) + social furniture (tables/chairs clusters) + designed railing (`#2a2018` warm pavers)
|
||||
- Restricted rooftop: cold work lights only (`#c0d0e0` directed down) + mechanical equipment (HVAC, antennae) + service hatch
|
||||
|
||||
Ozzie's verdict: "Most rooftops: maintenance access and a view. Some rooftops: IT'S A BAR. The rarity is what creates the moment."
|
||||
|
||||
---
|
||||
|
||||
## 4. Ysabel Vorn — The NPC Litmus Test
|
||||
|
||||
**Summary of the 10-axis exercise result:** 4.5 of 5 playstyle hooks covered.
|
||||
|
||||
| Axis | Miri's field | Playstyle hook |
|
||||
|------|-------------|----------------|
|
||||
| 1 | Behavioral Pattern (ANCHOR + REMNANT secondary) | All lenses: community position |
|
||||
| 2 | Surface Motivation (water equity) | Political: the stated tiebreaker role |
|
||||
| 3 | Actual Motivation (stay hidden) | Investigation + Dating Sim: the closed core |
|
||||
| 4 | Vulnerability/Secret (Commission warrant, Callen file chain) | Investigation + Assassination |
|
||||
| 5 | Information Access (complete settlement knowledge + aging Commission expertise) | Tycoon + Investigation |
|
||||
| 6 | Trust Architecture (Stone/Tide blend, slow building) | Dating Sim: the arc |
|
||||
| 7 | Routine Pattern (dawn inspection, 6-weekly boundary check) | Assassination: the window |
|
||||
| 8 | Economic Position (water control lever, undisclosed evidence) | Tycoon: the entry point |
|
||||
| 9 | Relationship Network (3 triangles, 1 active/2 latent) | Political + Investigation + Tactical |
|
||||
| 10 | Tolerance Threshold (near-zero for exposure, declining for Kael Voss) | Dating Sim + Assassination |
|
||||
|
||||
**The gap (Axis 11):** Locally, Ysabel registers as `assassination_difficulty: Extreme` (150-person tight community, Stone observation, Tide aftermath). But the Tactical triangle (Ysabel ↔ Callen's agents ↔ player) only becomes visible with network-level access. The 10-axis model as currently specified cannot flag this from local data alone.
|
||||
|
||||
**New Q-record to raise:** `Q-NNN: Axis 11 (Network Footprint) — authored field for network-significant NPCs in locally-insignificant positions.`
|
||||
|
||||
---
|
||||
|
||||
## 5. D-Record Sign-Off — All 12 Items + 2 New
|
||||
|
||||
All 12 D-ready items from Round 3 were reviewed by all six participants. Status: **all signed off**, with amendments documented below.
|
||||
|
||||
| # | Item | Status | Key amendments |
|
||||
|---|------|--------|----------------|
|
||||
| D-READY-1 | DistrictLayoutMode: Grid / Organic | ✅ SIGNED OFF | Araminta: 45° rotation cap is a hard technical constraint (pathfinding), not a design preference. Must be stated as non-negotiable in D-record. Nigel: Grid/Organic distribution proportion must vary per seed. |
|
||||
| D-READY-2 | Guarantee Tier System | ✅ SIGNED OFF | Gestalt: added Power Gradient Visibility + Economic Asymmetry Signal as conditional Tier 3 checks. Araminta: rooftop destination clause added as Tier 2 guarantee. Nigel: archetype placement must vary in angular position across seeds, not just distance from center — this is verifiable and testable. |
|
||||
| D-READY-3 | TrianglePurpose Enum | ✅ SIGNED OFF | No structural amendments. Nigel: TrianglePurpose is a multi-playstyle accessibility feature, not a replayability feature. |
|
||||
| D-READY-4 | WallBackside / TileBehindState | ✅ SIGNED OFF | Gestalt: both enums are canonical and complementary — WallBackside (structural/LOS) and TileBehindState (gameplay). D-record must document both and their mapping. Araminta: Era-tagged infrastructure cavity contents (Era 1–3 bundle density) with standardized color codes. Nigel: backside assignments within a template must have seed-driven variation (not fixed-template values). |
|
||||
| D-READY-5 | Dynamic Modification via Overlay | ✅ SIGNED OFF | Add `DamageOverlay` struct and `RegenerationStrategy` enum from OQ-R4-F resolution. XOR is explicitly prohibited for in-playthrough events. Araminta: trauma event → visual destruction stage mapping added (PhysicalDestruction → Stage 2; economic/political/migration → quarter fill modifier, not destruction stages). |
|
||||
| D-READY-6 | ZonePalette Modifier System | ✅ SIGNED OFF | Araminta: explicitly name T1 (warm organic, natural lighting) and T2 (cool grey-green, artificial lighting) as rustic vs. industrial farmland. Nigel: palette modifiers should influence NPC appearance as well as environment. |
|
||||
| D-READY-7 | Horizon View Corridor | ✅ SIGNED OFF | Araminta: clarify as negative space (instruction to not place blockers), not a placed object. Low z=2 element marks waterfront point as designed viewing location. Nigel: corridor position should vary per seed — the Wow Moment needs to be discovered, not expected. |
|
||||
| D-READY-8 | Assassin Lens Spatial Guarantees (A-1 through A-4) | ✅ SIGNED OFF | Gestalt: A-1–A-3 are Tier 3 Conditional; A-4 is mandatory Full-complexity. Framing: derived properties of existing spatial configuration, not assassin-tagged features. Araminta: A-1 Elevated Vantage requires overhead-clear LOS corridor (no z=4 elements in LOS cone). Nigel: angular variation requirement is hard — guarantee audit should fail if archetype placement clusters in predictable angular positions across N seeds. |
|
||||
| D-READY-9 | Heritage Grammar Overlay for Non-Urban Palettes | ✅ SIGNED OFF | Now lockable with OQ-R4-D resolved. Miri: `HeritageGrammarOverlay` struct with organizational principles. Araminta: TOML modifier files with visual expression parameters. Both specify the `ObjectTag` shared vocabulary requirement. Phase 1 exception: `gathering_probability` evaluated at block planning for quarter pre-assignment. |
|
||||
| D-READY-10 | Non-Urban Informal Zone Typology | ✅ SIGNED OFF | Araminta: visual grammar per type (social_permission = gathering infrastructure present; physical_distance = sparse, unmaintained path; utilitarian_cover = functional work space with no obvious unofficial purpose). Nigel: each type demands different player strategies — the variation is in how to USE cover, not merely what it is. |
|
||||
| D-READY-11 | Vertical Scale Architecture | ✅ SIGNED OFF | Add Rooftop Bar Clause (RooftopConfig enum from Section 3). Araminta: roof zone must be assigned `PublicDestination | RestrictedDiscovery` during block planning. Nigel: z-band floor boundaries must have seed-variation within cultural ordering constraints (executive always in upper zone, but which exact floor varies per seed). |
|
||||
| D-READY-12 | Trauma Events as EraModification Subtypes | ✅ SIGNED OFF | Gestalt + Tyre: TraumaEvent uses LocalOverlay, not XOR reseeding. Physical destruction and cultural aftermath are separate tracks. Araminta: `trauma_visual_decay_rate: slow | medium | fast` per heritage root, with seed-variation within root baseline (Nigel). |
|
||||
|
||||
### D-READY-13: MobileChunk Specification (New)
|
||||
|
||||
**Status: D-READY.** The final canonical `MobileChunk` struct from Tyre (Round 4, §1/§5a) is complete and signed off. Contains:
|
||||
|
||||
- Full struct with `VesselClass`, `MobileInterior`, `MobileMovementState`, `TransitSocialModifier`, `NpcPersistence` enums
|
||||
- `Docked` state with `connected_chunk`, `docked_since`, `scheduled_departure`
|
||||
- `InTransit` and `InterSystem` states
|
||||
- Vessel template size reference (TrainCar → LargeMerchant)
|
||||
- Boarding sequence implementation notes
|
||||
- Memory budget: ~0.5–4 KB metadata + up to 64 KB ChunkData per vessel
|
||||
|
||||
**Replayability requirements from Nigel (R-V-1 through R-V-6):**
|
||||
- R-V-1: At least 50% of variable passenger slots must turn over between adjacent voyages
|
||||
- R-V-2: Crew persistent, passengers variable
|
||||
- R-V-3: In-transit events are voyage-seeded, not vessel-seeded
|
||||
- R-V-4: Arrival time is storyteller-modifiable
|
||||
- R-V-5: Interior does NOT re-generate per voyage
|
||||
- R-V-6: Vessel carries ChunkMutations for accumulated damage history
|
||||
|
||||
**Miri's cultural grammar:** `TransitSocialModifier` with `TransitVariant` (BoundedLinear / BoundedMobile / InterSystem) is the canonical vessel cultural layer. Heritage-root behavior tables by vehicle type and jurisdictional state.
|
||||
|
||||
### D-READY-14: DamageOverlay / RegenerationStrategy (New)
|
||||
|
||||
**Status: D-READY.** Produced by OQ-R4-F resolution with unanimous participant agreement.
|
||||
|
||||
Covers:
|
||||
- `DamageOverlay` struct (epicenter, radius, intensity, scatter_seed)
|
||||
- `DamageOverlayType` enum (GasExplosion, Fire, Structural, Flooding)
|
||||
- `RegenerationStrategy` enum (LocalOverlay / SoftReseed / FullReseed)
|
||||
- Hard constraint: in-playthrough events are ALWAYS LocalOverlay
|
||||
- Hard prohibition: XOR-seeding for in-playthrough events is explicitly rejected
|
||||
- Per-tile damage computation (distance from epicenter × scatter → tile modification)
|
||||
|
||||
---
|
||||
|
||||
## 6. New Open Questions for Sprint Work
|
||||
|
||||
| Q-ID | Question | Owner | Priority |
|
||||
|------|----------|-------|----------|
|
||||
| Q-NNN-a | Axis 11 (Network Footprint) — authored field for network-significant NPCs in locally-insignificant positions | Miri | High — affects assassination scenario instantiation |
|
||||
| Q-NNN-b | Departure schedule model — departure windows as generator output for docked vessels | Tyre + Miri | High — vessel persistence requires it (Ozzie requirement) |
|
||||
| Q-NNN-c | Mobile environment social arc — structural representation of the journey timeline (who talks to whom at which journey stage) | Miri + Gestalt | Medium — Ozzie: "the journey is content; if the social arc isn't structured, the content is random" |
|
||||
| Q-NNN-d | DramaDensity enum naming — Tyre's Round 4 struct uses Quiescent/Active/Intense (3 values) vs. Round 3's Zero/Low/Medium/High/Flashpoint (5 values). Which is canonical? | Tyre + Gestalt | Low — naming only, but should be settled before D-record |
|
||||
| Q-NNN-e | ObjectTag vocabulary co-maintenance — shared between Miri's HeritageGrammarOverlay and Araminta's asset categorization system | Miri + Araminta | Medium — needed for heritage grammar implementation |
|
||||
|
||||
---
|
||||
|
||||
## 7. Final Canonical Structures (Summary)
|
||||
|
||||
### DistrictSkeleton — Final (Tyre §5)
|
||||
|
||||
New fields since Round 3:
|
||||
- `world_tier: WorldTier` (renamed from `significance: SignificanceTier`)
|
||||
- `grid_orientation: f32` (district rotation from world-north)
|
||||
- `vertical_structure: VerticalStructure` (Flat / Medium / Tall / Skyscraper)
|
||||
- `breach_only_zones: Vec<ZoneId>` (AccessTier::BreachOnly zones explicitly tracked)
|
||||
- `derived_analysis: DerivedDistrictAnalysis` (assassination_difficulty, target_density, playstyle affinities) — Miri's addition
|
||||
|
||||
DramaDensity remains absent from DistrictSkeleton. Confirmed by all participants. Lives in `DistrictRuntimeState` in the simulation module.
|
||||
|
||||
### Three-Layer Model — Locked (Gestalt §5)
|
||||
|
||||
```
|
||||
GENERATOR STATE (immutable after Phase 1)
|
||||
├── Phase 1: DistrictSkeleton
|
||||
│ ├── world_tier: WorldTier
|
||||
│ ├── complexity_tier: ComplexityTier
|
||||
│ ├── layout_mode: DistrictLayoutMode (Grid | Organic)
|
||||
│ ├── guarantee_audit: GuaranteeAuditResult (3-tier)
|
||||
│ ├── rooftop: RooftopConfig (per MultiBlockReservation)
|
||||
│ ├── derived_analysis: DerivedDistrictAnalysis
|
||||
│ └── society_profile: SocietyProfileRef
|
||||
└── Phase 2: PreparedDistrict
|
||||
├── SocialSitePlacement (triangles with Vec<TrianglePurpose>)
|
||||
├── NpcManifest (seeded from society_profile)
|
||||
├── ZonePalette assignments (base + heritage modifiers)
|
||||
└── ChunkMutations pending
|
||||
|
||||
SIMULATION STATE (runtime storyteller)
|
||||
├── DistrictRuntimeState.drama_density: DramaDensity
|
||||
├── active_triangles: Vec<TriangleId>
|
||||
├── npc_pattern_weights: NpcPatternWeightSet
|
||||
└── assassination_difficulty on-demand computation
|
||||
(SocietyProfile + spatial_audit + StorytellerState → DifficultyDescriptor)
|
||||
|
||||
DELTA LAYER (post-generation)
|
||||
├── DamageOverlay / ChunkMutations::LocalOverlay
|
||||
├── NpcRemoved / NpcStateChanged
|
||||
├── AccessTierChanged
|
||||
└── WorldStateDelta (composed from all active mutations)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Memory Budget — Final
|
||||
|
||||
| Component | Size per district |
|
||||
|-----------|------------------|
|
||||
| Identity + WorldTier + ComplexityTier | ~96 bytes |
|
||||
| Blocks (4×4 × BlockSkeleton) | ~2 KB |
|
||||
| Social sites + triangles | ~1–4 KB |
|
||||
| Reservations + corridors (incl. z-bands) | ~0.5–3 KB |
|
||||
| Boundaries | ~4 KB |
|
||||
| Society profile ref | ~32 bytes |
|
||||
| Zone palette | ~0.5–1 KB |
|
||||
| Guarantee audit (3-tier expanded) | ~512 bytes |
|
||||
| Layout mode (Organic) | 0–1 KB |
|
||||
| VerticalStructure + breach zones + derived_analysis | ~128 bytes |
|
||||
| **Total per district** | **~9–16 KB** |
|
||||
|
||||
Fleet: 300 worlds × ~6 districts × ~13 KB = **~23 MB**
|
||||
Mobile chunks: ~3 MB at 50 active entities (paged by streaming model)
|
||||
Grand total: ~26 MB — within accepted RAM budget
|
||||
|
||||
---
|
||||
|
||||
## 9. Qatux Observations
|
||||
|
||||
**For the record:**
|
||||
|
||||
1. The XOR rejection is the single most unanimously confirmed decision of this workshop. All four participants who addressed it reached the same verdict by independent reasoning. The D-record should state the prohibition unambiguously.
|
||||
|
||||
2. The assassination_difficulty tension (Gestalt: computed-on-demand vs. Miri: DerivedDistrictAnalysis at Phase 1) is resolvable by synthesis: stored cultural baseline + on-demand runtime computation for player-facing assessment. This should be explicit in the D-record rather than left as a gap.
|
||||
|
||||
3. Ozzie's two additions to D-READY (departure schedules + mobile environment social arc) are requirements, not preferences. Both are downstream of the vessel persistence decision (D-READY-13). They should be raised as Q-records with high priority.
|
||||
|
||||
4. The Ysabel Vorn exercise is the single most complete demonstration of the NPC generation model produced in this workshop. It should be referenced in the NPC system D-record as the canonical litmus test case for validating the 10-axis model.
|
||||
|
||||
5. Tyre's DramaDensity enum in Round 4 (Quiescent/Active/Intense, 3 values) differs from Round 3's (Zero/Low/Medium/High/Flashpoint, 5 values). This naming gap should be resolved before the D-record is written.
|
||||
|
||||
6. WorldTier enum values are now canonical from Tyre's Round 4 output: Core / Regional / Local / Transit / Dormant. The Round 3 naming (CenterStage/Regional/Backwater/Waypoint/Insignificant) is superseded.
|
||||
|
||||
---
|
||||
|
||||
**Round 4 closes with all OQs resolved, all 12 D-records signed off (with amendments), 2 new D-records added, and 5 new Q-records raised for sprint work. The pipeline is locked. D-record production proceeds.**
|
||||
@@ -0,0 +1,209 @@
|
||||
# Generator Architecture Workshop — Round 5 Notes
|
||||
|
||||
**Workshop:** Generator Architecture (#562)
|
||||
**Round:** 5 — Final Review
|
||||
**Date:** 2026-02-27
|
||||
**Compiled by:** Qatux
|
||||
|
||||
---
|
||||
|
||||
## Purpose
|
||||
|
||||
Round 5 was a sign-off round. All six participants reviewed `workshop-outcomes.md` for accuracy against their Round 4 canonical outputs. No new design proposals were made. Corrections only.
|
||||
|
||||
---
|
||||
|
||||
## Sign-Off Status
|
||||
|
||||
| Agent | Role | Status | Corrections |
|
||||
|-------|------|--------|-------------|
|
||||
| Tyre | Technical Architect | Signed off with corrections | HIGH: WorldTier enum; MEDIUM: DistrictSkeleton fields; LOW: MobileMovementState |
|
||||
| Miri | Worldbuilder | Signed off with corrections | D-READY-10 heritage correlations; D-READY-12 principle |
|
||||
| Araminta | Visual Designer | Signed off with corrections | D-READY-6 terrain types; D-READY-9 domain; D-READY-13 vessel grammar; D-READY-5 stages |
|
||||
| Nigel | Replayability Advocate | Signed off with corrections | Missing ComplexityTier→DramaDensity ceiling |
|
||||
| Gestalt | Systems Design | Signed off with minor notes | complexity→complexity_tier naming |
|
||||
| Ozzie | Player Experience | Signed off with one correction | D-READY-11 rooftop "determines" → "weights probability" |
|
||||
|
||||
All six sign-offs confirmed. Workshop is closed.
|
||||
|
||||
---
|
||||
|
||||
## Corrections Applied to workshop-outcomes.md
|
||||
|
||||
### C-R5-1 — WorldTier Enum Variant Names (HIGH)
|
||||
**Source:** Tyre Round 5, Correction 1
|
||||
|
||||
The outcomes document used simplified/incorrect variant names. Corrected to Tyre's Round 4 canonical:
|
||||
|
||||
| Incorrect | Correct |
|
||||
|-----------|---------|
|
||||
| Core | Epicenter |
|
||||
| Regional | Regional (unchanged) |
|
||||
| Local | Backwater |
|
||||
| Transit | Passage |
|
||||
| Dormant | Waypoint |
|
||||
|
||||
Constraint ceiling also corrected:
|
||||
- **Backwater → Full allowed** (key game design insight: dense isolated community, network-insignificant ≠ budget-capped)
|
||||
- **Passage → Moderate** (was: Transit → Minimal)
|
||||
- **Waypoint → Minimal** (was: Dormant → Empty)
|
||||
|
||||
The original text "Local → Moderate max" materially prohibited the Backwater+Full case, which is one of the most important design combinations in the game.
|
||||
|
||||
---
|
||||
|
||||
### C-R5-2 — ComplexityTier → DramaDensity Ceiling (MEDIUM)
|
||||
**Source:** Nigel Round 5, Correction 2
|
||||
|
||||
The constraint chain was stated only halfway. Added second half:
|
||||
|
||||
> ComplexityTier → DramaDensity ceiling: Full → any intensity; Moderate → Active max; Minimal → Quiescent max; Empty → Zero only (no storyteller activation possible).
|
||||
|
||||
A `ComplexityTier::Empty` district has no social fabric. The storyteller cannot activate drama there.
|
||||
|
||||
---
|
||||
|
||||
### C-R5-3 — DistrictSkeleton Field List (MEDIUM)
|
||||
**Source:** Tyre Round 5, Correction 2
|
||||
|
||||
Five identity/context fields missing from the Phase 1 diagram, replaced by fields from other participants' proposals without attribution. Added:
|
||||
- `district_id: DistrictId`
|
||||
- `seed: u64`
|
||||
- `district_type: DistrictType`
|
||||
- `context: DistrictContext`
|
||||
- `access_points: Vec<AccessPoint>`
|
||||
|
||||
Added "(source: multi-participant)" notes to `vertical_structure` and `breach_only_zones` (present in outcomes but not in Tyre's canonical struct). Added "(source: Miri/Gestalt; Phase 1 computed)" to `derived_analysis`.
|
||||
|
||||
---
|
||||
|
||||
### C-R5-4 — D-READY-10 Heritage Root Correlations (HIGH)
|
||||
**Source:** Miri Round 5
|
||||
|
||||
The heritage root ↔ informal zone type mapping was factually wrong:
|
||||
- **Dust** was listed under `utilitarian_cover` — incorrect. Dust communities have maximum communal observation; the only privacy available is negotiated. Dust → `social_permission`.
|
||||
- **Iron** was missing entirely. Labor function covers presence in Iron communities. Iron → `utilitarian_cover`.
|
||||
|
||||
Corrected mapping: Frost/Stone → `physical_distance`; Tide/Vine/Dust → `social_permission`; Iron/Salt → `utilitarian_cover`.
|
||||
|
||||
---
|
||||
|
||||
### C-R5-5 — D-READY-11 Rooftop Config Assignment (MEDIUM)
|
||||
**Source:** Ozzie Round 5 + Araminta Round 5 (confirming)
|
||||
|
||||
"Heritage root determines which config is assigned" is wrong. Full determination kills the discovery moment — a Frost building with a rooftop bar is memorable *precisely because* it is unexpected.
|
||||
|
||||
Corrected: Heritage root **weights the probability** between `Restricted` and `PublicWithHiddenLayer`. The final config is seeded per-building. A minority of buildings of any heritage root must be configurable as the non-dominant type.
|
||||
|
||||
---
|
||||
|
||||
### C-R5-6 — D-READY-13 MobileMovementState Missing Idle (LOW)
|
||||
**Source:** Tyre Round 5, Correction 4
|
||||
|
||||
`MobileMovementState` was listed as `(Docked / InTransit / InterSystem)`. Tyre's Round 4 canonical includes a fourth state:
|
||||
|
||||
- `Idle` = vessel parked at a location but not docked to infrastructure (anchored ship, grounded shuttle)
|
||||
|
||||
Added to D-READY-13.
|
||||
|
||||
---
|
||||
|
||||
### C-R5-7 — D-READY-13 Missing Vessel Visual Grammar Reference (MEDIUM)
|
||||
**Source:** Araminta Round 5, Correction 3
|
||||
|
||||
D-READY-13 specified vessel structure and cultural grammar but had no source for how vessels look different from buildings. Added reference to Araminta's five-rule vessel visual grammar (`araminta-round4.md` §2):
|
||||
|
||||
1. Exterior hull uses vessel-identity material, not zone palette
|
||||
2. Window tiles reveal exterior context (docked vs. in transit)
|
||||
3. Compression modifier tightens proportions throughout
|
||||
4. Section transitions use vessel-identity threshold elements
|
||||
5. Class stratification expressed through proportion, not palette change
|
||||
|
||||
---
|
||||
|
||||
### C-R5-8 — D-READY-6 Terrain Type Numbering T5/T7 Transposed (MEDIUM)
|
||||
**Source:** Araminta Round 5, Correction 1
|
||||
|
||||
The outcomes document had T5 = mountain and T7 = wetland. Neither is correct per Araminta's Round 3 specification:
|
||||
- T5 = Coastal water (the terrain type referenced by D-READY-7's horizon view corridor guarantee)
|
||||
- T6 = Beach/coastal margin
|
||||
- T7 = Mountain/high terrain
|
||||
- T8 = Desert/arid
|
||||
|
||||
"Wetland" was never in the original 8 types. Added note: if wetland terrain is needed, it requires design work as a new T9.
|
||||
|
||||
---
|
||||
|
||||
### C-R5-9 — D-READY-9 Araminta's Authoring Domain Incomplete (MEDIUM)
|
||||
**Source:** Araminta Round 5, Correction 2
|
||||
|
||||
Araminta's authoring domain was listed as "object sets, arrangement algorithms, lighting temperature." The full domain covers additional visual expression fields she specified in her Round 4 TOML schema:
|
||||
- Floor surface variants (`[floor].variant_preference`)
|
||||
- Overhead flora density and character (`[overhead].density_factor`, `[overhead].character`)
|
||||
- Wall/structure material character (`[structure].primary_material`, `material_tone_shift`)
|
||||
- Boundary material type (`[boundaries].fence_type`)
|
||||
|
||||
Updated domain description accordingly.
|
||||
|
||||
---
|
||||
|
||||
### C-R5-10 — D-READY-5 Destruction Stages and Palette Constraint (MEDIUM)
|
||||
**Source:** Araminta Round 5, Correction 4
|
||||
|
||||
D-READY-5 referenced "Stage 2" and "Stage 3" without enumerating the full sequence. Added:
|
||||
|
||||
| Stage | Name | Visual state |
|
||||
|-------|------|-------------|
|
||||
| 1 | Active | DamageOverlay rendering live |
|
||||
| 2 | Fresh Aftermath | Structure breached; scorch, rubble, debris |
|
||||
| 3 | Stabilized | Debris cleared; structural state permanent |
|
||||
| 4 | Reconstruction | Scaffolding tiles, incomplete floors |
|
||||
| 5 | Healed Scar | Functional; residual visual tells remain |
|
||||
|
||||
Added destruction palette constraint: corruption-only (no new colors introduced by destruction; single exception: `#c8d8f0` open-sky tile when roof removed).
|
||||
|
||||
---
|
||||
|
||||
### C-R5-11 — D-READY-12 Trauma Intensification Principle (MINOR)
|
||||
**Source:** Miri Round 5
|
||||
|
||||
Added design principle framing to D-READY-12:
|
||||
|
||||
> Trauma intensifies culture, it does not transform it. A stressed community becomes a more concentrated version of itself. Decay is toward the community's pre-trauma baseline, not toward a new equilibrium.
|
||||
|
||||
---
|
||||
|
||||
### C-R5-12 — complexity → complexity_tier Field Naming (MINOR)
|
||||
**Source:** Gestalt Round 5, Correction 2
|
||||
|
||||
`complexity: ComplexityTier` in the Phase 1 diagram corrected to `complexity_tier: ComplexityTier` to parallel `world_tier` naming convention.
|
||||
|
||||
---
|
||||
|
||||
### Minor Notes Applied
|
||||
|
||||
- **Q-NNN-b** (departure schedule model): Added note that D-READY-13 resolves this — recommend closing before sprint planning.
|
||||
- **Q-NNN-f** (assassination difficulty synthesis): Clarified that on-demand computation is display-only; game logic uses Phase 1 `DerivedDistrictAnalysis` value.
|
||||
- **Key Tensions table**: Updated WorldTier canonical values from old names to new.
|
||||
|
||||
---
|
||||
|
||||
## Notes for D-Record Filing
|
||||
|
||||
The following items were identified as issues in the D-records to be filed, not errors in the outcomes document:
|
||||
|
||||
- **`GuaranteeAuditResult` struct** (Tyre Round 5, Correction 6): Tyre's Round 4 struct was missing `non_institutional_route`, `egress_multiplicity`, `horizon_view_corridor`, `breach_only_zone`, `rooftop_discovery` in the Tier 2/3 sections. These should be added when filing the D-record for D-READY-2/D-READY-8.
|
||||
- **`Docked` state struct** (Tyre Round 5, Correction 5b): The outcomes doc asserted `scheduled_departure` existed in the canonical struct, but Tyre's Round 4 struct was incomplete. Corrected to clarify these fields must be added at implementation time. Both `docked_since: SimTick` and `scheduled_departure: Option<SimTick>` are required — applied directly to D-READY-13 text.
|
||||
|
||||
---
|
||||
|
||||
## Post-Correction Status
|
||||
|
||||
- Workshop-outcomes.md: all 12 corrections applied. Document is accurate for all six domains.
|
||||
- 14 D-records remain ready for filing.
|
||||
- Q-NNN-b recommended for closure (resolved by D-READY-13).
|
||||
- Q-NNN-d (DramaDensity naming 3 vs 5 levels) remains open for sprint work. Nigel preference on record: preserve `Flashpoint` as distinct peak value.
|
||||
|
||||
---
|
||||
|
||||
*Round 5 complete. Workshop closed.*
|
||||
@@ -0,0 +1,472 @@
|
||||
# Round 1: Tyre — Technical Constraints on Generator Architecture
|
||||
|
||||
**Workshop:** Generator Architecture (#562)
|
||||
**Agent:** Tyre (Technical Architect)
|
||||
**Date:** 2026-02-27
|
||||
|
||||
---
|
||||
|
||||
## 1. Hard Technical Constraints on Spatial Hierarchy
|
||||
|
||||
These constraints are **non-negotiable** — they flow directly from confirmed D-records and cannot be relaxed without amending those decisions.
|
||||
|
||||
### 1.1 Chunk: 64×64 sim tiles (32×32 visual, 32m) — D-094
|
||||
|
||||
The chunk is the **streaming and serialization unit**. This is locked.
|
||||
|
||||
| Property | Value | Source |
|
||||
|----------|-------|--------|
|
||||
| Sim tiles | 64×64 | D-094 |
|
||||
| Visual tiles | 32×32 | D-094, D-066 (2x retina) |
|
||||
| Physical size | 32m × 32m | D-066 (0.5m/sim tile) |
|
||||
| Memory per chunk | ~21 KB raw tile data | 64×64 tiles × 5 bytes/tile (type + flags + occupancy) ≈ 20,480 bytes |
|
||||
| Serialization format | MessagePack | D-020 |
|
||||
|
||||
**Why 64×64 sim is the floor:** Shadowcasting (D-035) operates at sim resolution. A smaller chunk means more cross-chunk boundary queries during LOS computation. At 64×64, a single chunk covers the full LOS radius of most entities (~20-30 sim tiles) without requiring neighbor lookups for most casts. Halving to 32×32 sim would roughly quadruple the frequency of cross-chunk shadowcasting — measurable cost on the critical path.
|
||||
|
||||
**Why 64×64 sim is the ceiling (for now):** Larger chunks waste bandwidth for partial visibility. The ObserverSnapshot (D-020) sends only visible state. A 128×128 chunk would mean loading 4× the data when only a corner is visible. The 64×64 sweet spot minimizes the ratio of loaded-but-invisible tiles.
|
||||
|
||||
### 1.2 Block: 128×128 sim tiles (2×2 chunks, 64m) — D-094
|
||||
|
||||
The block is the **generator planning unit**. Four chunks arranged in a 2×2 grid.
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Sim tiles | 128×128 |
|
||||
| Visual tiles | 64×64 |
|
||||
| Chunks | 4 (2×2) |
|
||||
| Physical size | 64m × 64m |
|
||||
|
||||
**Generator implication:** The block is where the generator decides the building footprint strategy. Four chunks can:
|
||||
- Remain independent (4 small buildings/spaces)
|
||||
- Merge 2 horizontally or vertically (1×2 building spanning 64×32 sim tiles)
|
||||
- Merge 2 in L-shape (building occupying 3 of 4 chunks with gap)
|
||||
- Merge all 4 (single large building spanning the full 128×128 sim tiles)
|
||||
|
||||
This is a 2-bit decision per chunk pair (merge/don't merge on each axis), producing a tractable combinatorial space for the generator without requiring variable-size building footprints.
|
||||
|
||||
### 1.3 District: 512×512 sim tiles (4×4 blocks, 256m) — D-094
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Sim tiles | 512×512 per z-level |
|
||||
| Visual tiles | 256×256 |
|
||||
| Blocks | 16 (4×4) |
|
||||
| Chunks | 64 (8×8) |
|
||||
| Z-levels | 3 (Transit District; variable for other types) |
|
||||
| Memory per z-level | ~1.35 MB (64 chunks × ~21 KB) |
|
||||
| Memory for 3 z-levels | ~4 MB |
|
||||
|
||||
### 1.4 Hierarchy Depth: Exactly 4 Levels
|
||||
|
||||
The hierarchy is **Region → District → Block → Chunk**. No more, no fewer.
|
||||
|
||||
**Why not deeper (sub-chunk quarters)?** The workshop brief mentions a "sub-chunk quarter system" (¼ chunk = 32×32 sim tiles). *cracks knuckles* — let me be honest about what this means technically.
|
||||
|
||||
A 32×32 sim tile quarter is 16×16 visual tiles = 16m. That's actually a reasonable building footprint (The Last Shift bar is 28×22 visual). But:
|
||||
|
||||
1. **The quarter is NOT a hierarchy level — it's a fill rule.** The chunk remains the streaming unit. Quarters are a layout constraint within a chunk, not a separately loaded/serialized entity. The generator decides how to fill a chunk's 64×64 sim space using quarter-aligned placement rules, but the server still loads/saves/streams the full chunk.
|
||||
|
||||
2. **Quarter merge rules are purely generator-side.** The server doesn't know or care about quarters after generation. It sees tiles. The quarter concept exists only during the generation pass and in the template metadata.
|
||||
|
||||
3. **Adding a 5th hierarchy level (quarter) to the runtime would violate D-012's streaming model.** Chunk is the streaming atom. Sub-chunk streaming would require partial chunk updates over the wire, complicating the ObserverSnapshot and the client's tile map management for zero gameplay benefit.
|
||||
|
||||
**Recommendation:** Quarters are a **generation-time layout constraint**, not a spatial hierarchy level. The hierarchy stays at 4 levels. The quarter system is a set of placement rules the chunk-fill stage of the generator uses internally.
|
||||
|
||||
**Why not shallower?** Removing blocks (District → Chunk directly) loses the generator's "what goes in this 64m² area" planning step. The block is where multi-chunk building footprints are decided. Without it, the generator must either think in individual chunks (losing building coherence) or in full districts (losing locality). The 2×2 block is the minimum viable planning unit for building-scale decisions.
|
||||
|
||||
---
|
||||
|
||||
## 2. Data Structure for the District Skeleton (Q-036)
|
||||
|
||||
The district skeleton is the generator's output from the district-generation stage. It describes **what** a district contains and **where things go**, without specifying individual tiles.
|
||||
|
||||
### 2.1 Proposed Data Structure
|
||||
|
||||
```rust
|
||||
/// The district skeleton — atomic output of the district generation stage.
|
||||
/// This is a planning artifact consumed by the block/chunk fill stages.
|
||||
struct DistrictSkeleton {
|
||||
/// Unique district identifier (world-scoped)
|
||||
district_id: DistrictId,
|
||||
|
||||
/// Generator seed for deterministic reproduction
|
||||
seed: u64,
|
||||
|
||||
/// District classification driving template selection
|
||||
district_type: DistrictType, // e.g., Transit, Residential, Commercial, Industrial, Administrative, Medical
|
||||
|
||||
/// Economic/political context from pipeline stages above
|
||||
context: DistrictContext,
|
||||
|
||||
/// The 4×4 block grid — each block has a zoning assignment
|
||||
blocks: [[BlockSkeleton; 4]; 4],
|
||||
|
||||
/// Social sites placed within this district (D-025)
|
||||
social_sites: Vec<SocialSitePlacement>,
|
||||
|
||||
/// Multi-block structure reservations (structures spanning >1 block)
|
||||
reservations: Vec<MultiBlockReservation>,
|
||||
|
||||
/// Access topology — gate/entrance placement and connectivity
|
||||
access_points: Vec<AccessPoint>,
|
||||
|
||||
/// Corridor/thoroughfare spine connecting access points
|
||||
corridors: Vec<CorridorSpine>,
|
||||
|
||||
/// Z-level configuration
|
||||
z_levels: u8,
|
||||
|
||||
/// Zone palette assignments (fog tints, surface colors per D-093)
|
||||
zone_palette: Vec<ZoneDefinition>,
|
||||
}
|
||||
|
||||
struct DistrictContext {
|
||||
/// Faction controlling this district (affects templates, NPC generation)
|
||||
faction_control: FactionId,
|
||||
|
||||
/// Economic prosperity tier (0-4, affects object density, building quality)
|
||||
prosperity: u8,
|
||||
|
||||
/// Population density target (NPCs per block, guides NPC slot allocation)
|
||||
population_density: PopulationDensity, // Sparse/Normal/Dense/Packed
|
||||
|
||||
/// Cultural ingredients (Q-032) driving visual/naming variation
|
||||
cultural_profile: CulturalProfile,
|
||||
|
||||
/// Transport adjacency — which access points connect to what
|
||||
transport_links: Vec<TransportLink>,
|
||||
}
|
||||
|
||||
struct BlockSkeleton {
|
||||
/// Block position in the 4×4 grid (0-3, 0-3)
|
||||
position: (u8, u8),
|
||||
|
||||
/// Primary zoning type for this block
|
||||
zoning: ZoningType, // Residential, Commercial, Industrial, Institutional, Mixed, Open/Park, Infrastructure
|
||||
|
||||
/// Whether this block is claimed by a multi-block reservation
|
||||
reservation: Option<ReservationId>,
|
||||
|
||||
/// Chunk merge strategy for this block (how the 4 chunks combine)
|
||||
chunk_layout: ChunkLayout,
|
||||
|
||||
/// Social sites hosted in this block (references into district's social_sites vec)
|
||||
hosted_sites: Vec<SocialSiteId>,
|
||||
}
|
||||
|
||||
/// How the 4 chunks within a block are organized
|
||||
enum ChunkLayout {
|
||||
/// All 4 chunks independent (small buildings, mixed use)
|
||||
Independent,
|
||||
|
||||
/// Two chunks merged horizontally, two independent
|
||||
/// Contains: which pair merges (N or S row), orientation
|
||||
MergeH { row: MergeRow },
|
||||
|
||||
/// Two chunks merged vertically, two independent
|
||||
MergeV { col: MergeCol },
|
||||
|
||||
/// L-shaped merge (3 chunks), one independent
|
||||
LShape { corner: Corner },
|
||||
|
||||
/// Full merge (single large building spanning all 4 chunks)
|
||||
FullMerge,
|
||||
|
||||
/// Custom layout (for multi-block reservations that span into this block)
|
||||
Reserved,
|
||||
}
|
||||
|
||||
struct SocialSitePlacement {
|
||||
/// Social site identifier
|
||||
site_id: SocialSiteId,
|
||||
|
||||
/// Template tag selecting from the D-025 template library
|
||||
template_tag: String, // e.g., "logistics_hub", "bar", "residential_cluster"
|
||||
|
||||
/// Block(s) this site occupies
|
||||
blocks: Vec<(u8, u8)>,
|
||||
|
||||
/// Specific chunk(s) within those blocks
|
||||
chunks: Vec<ChunkCoord>,
|
||||
|
||||
/// NPC slot allocation (how many NPCs this site supports)
|
||||
npc_slots: NpcSlotAllocation,
|
||||
|
||||
/// Access tier for entry (D-028 Layer 1)
|
||||
access_tier: AccessTier, // Public, SemiPublic, SemiPrivate, Private, Restricted
|
||||
|
||||
/// Triangle templates to instantiate at this site (D-024, D-087)
|
||||
triangles: Vec<TriangleTemplate>,
|
||||
|
||||
/// Economic function (what this site does in the district economy)
|
||||
economic_function: EconomicFunction,
|
||||
}
|
||||
|
||||
struct NpcSlotAllocation {
|
||||
/// Named roles (authored, specific function)
|
||||
named_roles: Vec<RoleSlot>,
|
||||
|
||||
/// Generic background population slots (Tier 3)
|
||||
background_slots: u16,
|
||||
|
||||
/// Total NPC capacity at peak hours
|
||||
peak_capacity: u16,
|
||||
}
|
||||
|
||||
struct MultiBlockReservation {
|
||||
/// Reservation identifier
|
||||
id: ReservationId,
|
||||
|
||||
/// Template for the multi-block structure
|
||||
template_tag: String, // e.g., "gate_terminal", "park", "stadium"
|
||||
|
||||
/// Blocks claimed by this reservation (coordinates in the 4×4 grid)
|
||||
footprint: Vec<(u8, u8)>,
|
||||
|
||||
/// Whether this reservation crosses into a neighboring district
|
||||
cross_district: bool,
|
||||
|
||||
/// Z-levels occupied
|
||||
z_range: (u8, u8),
|
||||
}
|
||||
|
||||
struct AccessPoint {
|
||||
/// Position on the district boundary (edge + offset)
|
||||
edge_position: EdgePosition,
|
||||
|
||||
/// What this connects to (transit stop, neighboring district, gate)
|
||||
connects_to: ConnectionTarget,
|
||||
|
||||
/// Access tier (public entrance, restricted, staff only)
|
||||
access_tier: AccessTier,
|
||||
|
||||
/// Width in visual tiles (constrains throughput and NPC flow)
|
||||
width_vt: u8,
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 Size Estimate
|
||||
|
||||
Per district skeleton:
|
||||
- 16 BlockSkeletons: ~16 × 64 bytes = ~1 KB
|
||||
- Social sites (4-8 per district): ~8 × 256 bytes = ~2 KB
|
||||
- Multi-block reservations (0-3): ~3 × 128 bytes = ~384 bytes
|
||||
- Access points + corridors: ~1 KB
|
||||
- Context + metadata: ~512 bytes
|
||||
- **Total: ~5 KB per district skeleton**
|
||||
|
||||
For 300 worlds × avg 6 districts = 1,800 district skeletons = **~9 MB**. Trivial. Entire galaxy skeleton fits in memory.
|
||||
|
||||
### 2.3 Relationship to D-025 Social Sites
|
||||
|
||||
The generator does **not** invent new social site types. It:
|
||||
1. Selects from the D-025 template library based on zoning type and district context
|
||||
2. Places templates onto blocks/chunks using the spatial hierarchy
|
||||
3. Allocates NPC slots per template requirements
|
||||
4. Wires access topology (which sites connect to which corridors)
|
||||
|
||||
**D-025 templates are authored. Skeleton placement is generated.** The generator arranges templates, not tiles.
|
||||
|
||||
---
|
||||
|
||||
## 3. How Chunk Loading (D-012) Constrains the Spatial Hierarchy
|
||||
|
||||
### 3.1 Streaming Radius
|
||||
|
||||
The player's chunk loading radius determines how much of the district is live at any time. Current constraints:
|
||||
|
||||
| Parameter | Value | Source |
|
||||
|-----------|-------|--------|
|
||||
| Player vision range | ~20-30 sim tiles (LOS) | D-035 shadowcasting |
|
||||
| Sound range | Close: 5 sim tiles, Mid: 15, Far: 30 | D-018 |
|
||||
| Chunk size | 64 sim tiles | D-094 |
|
||||
|
||||
**Loading strategy:** 3×3 chunk grid centered on player = 9 chunks loaded. This covers 192×192 sim tiles (96m radius in each direction from center), safely beyond max LOS range. The player never sees a chunk boundary seam.
|
||||
|
||||
**Memory at 3×3 loading:** 9 chunks × ~21 KB = ~189 KB per z-level, ~567 KB for 3 z-levels. With entity data overlay: ~1-2 MB. Trivial.
|
||||
|
||||
### 3.2 Cross-Chunk Constraints on Generation
|
||||
|
||||
The generator must guarantee **tile continuity at chunk boundaries**. When two chunks are adjacent (whether in the same block or across blocks), their edge tiles must be compatible:
|
||||
- Wall segments must align or leave matching gaps (doors)
|
||||
- Floor types must transition cleanly (corridor entering a room)
|
||||
- Z-level connections (stairs, ramps) must align vertically
|
||||
|
||||
This is the hardest constraint on chunk-based generation. Two approaches:
|
||||
|
||||
**Option A: Edge contracts.** Each chunk face exports a set of "connection points" (door positions, corridor widths). The generator plans connections at the block level, then each chunk fill respects its edge contracts. *This is what I recommend.* It's how Wave Function Collapse and similar systems handle tile boundaries.
|
||||
|
||||
**Option B: Overlap zones.** Chunks share a 2-4 tile overlap strip with their neighbors. The generator fills the overlap first, then fills inward. Simpler conceptually but wastes tile real estate (up to 12.5% of each chunk at 4-tile overlap on all edges).
|
||||
|
||||
**Recommendation: Edge contracts (Option A).** Each chunk face has a fixed set of connection slots (e.g., 1-3 connections per face, each defined by position + width + access tier). The block-level planning stage determines which faces connect and where. The chunk-fill stage reads its face contracts and fills interior tiles accordingly.
|
||||
|
||||
### 3.3 Chunk Loading vs. Generator Computation
|
||||
|
||||
D-012 specifies that chunks load/unload around the player. For generated worlds, this means chunks must be **generatable on demand** when first entered, then cached.
|
||||
|
||||
**Generation pipeline timing:**
|
||||
|
||||
| Stage | When it runs | Output |
|
||||
|-------|-------------|--------|
|
||||
| Galaxy → System → District skeletons | Game start (from seed) | All 1,800 district skeletons |
|
||||
| Block planning (per district) | On first visit to district OR game start for home district | 16 BlockSkeletons with layouts + edge contracts |
|
||||
| Chunk fill (per chunk) | On entering loading radius | Tile data for one 64×64 chunk |
|
||||
|
||||
**Chunk fill time budget:** The player moves at Walk speed = 1 tile/2 ticks = 1 tile/200ms (at 10 tps). Crossing a 64-tile chunk takes ~12.8 seconds. A new chunk enters the 3×3 loading grid roughly every 6-12 seconds. **The chunk fill generator has a budget of ~500ms per chunk** (generous — can use background thread, D-010 deterministic sim doesn't constrain client-side gen).
|
||||
|
||||
At 64×64 = 4,096 tiles, that's ~122 microseconds per tile. Feasible. Template-based fill (stamp a pre-authored room into a quarter, decorate procedurally) will be well under budget. Full WFC at this scale takes ~10-50ms in optimized Rust.
|
||||
|
||||
### 3.4 Borderless Generation Implication
|
||||
|
||||
D-012 states the boundary can be removed for borderless worlds. For the generator, this means:
|
||||
- District skeletons must be generatable from neighbors' edge contracts (a new district skeleton can be created when the player approaches an ungenerated district boundary)
|
||||
- The 4×4 block grid is the district's internal structure; the inter-district boundary is just another set of edge contracts
|
||||
- **The generator pipeline must be able to run the district skeleton stage for a single district in isolation, given only its neighbors' access points as input**
|
||||
|
||||
This doesn't affect v0.1 (bounded, hand-authored) but constrains the generator architecture: district generation must be local, not global.
|
||||
|
||||
---
|
||||
|
||||
## 4. Performance Implications of Hierarchy Depth
|
||||
|
||||
### 4.1 Lookup Complexity
|
||||
|
||||
Converting a sim tile position to its hierarchy location:
|
||||
|
||||
```
|
||||
Chunk coord: (x / 64, y / 64) — 1 division
|
||||
Block coord: (chunk_x / 2, chunk_y / 2) — 1 division
|
||||
District coord: (block_x / 4, block_y / 4) — 1 division
|
||||
```
|
||||
|
||||
All integer divisions by powers of 2 = **bit shifts**. O(1) per lookup, ~3 nanoseconds. Hierarchy depth has zero performance impact on spatial lookups.
|
||||
|
||||
### 4.2 Spatial Queries (Pathfinding, LOS)
|
||||
|
||||
Pathfinding operates at sim-tile resolution within the loaded chunk grid. The hierarchy doesn't affect pathfinding cost directly. However:
|
||||
|
||||
- **Block-level precomputation:** The generator can precompute a block-level connectivity graph (which blocks connect to which, through which access points). This gives A* a coarse-grid initial path (~16 nodes per district) before refining to tile-level within the relevant chunks. **Saves 90%+ of pathfinding work for long paths.**
|
||||
- **District-level precomputation:** Same idea at district scale. For cross-district travel, the pathfinder walks the district connectivity graph (~6 districts per station), then block graph, then tile graph. Three-level hierarchical A*.
|
||||
|
||||
**Performance estimate for hierarchical A*:**
|
||||
|
||||
| Path type | Nodes searched | Time estimate |
|
||||
|-----------|---------------|---------------|
|
||||
| Within-chunk | ~100-500 tiles | <1ms |
|
||||
| Within-block (cross-chunk) | 4 chunks × ~200 tiles | ~2-5ms |
|
||||
| Within-district (cross-block) | 16 blocks × 4 chunk entries | ~1-3ms (coarse) + ~5ms (refine) |
|
||||
| Cross-district | 6 districts × 16 block entries | ~2ms (coarse) + ~8ms (refine) |
|
||||
|
||||
All well within the 100ms tick budget (D-031). The hierarchy **helps** pathfinding by providing natural coarse-graining.
|
||||
|
||||
### 4.3 Memory Layout
|
||||
|
||||
The hierarchy maps naturally to a flat array with computed indices:
|
||||
|
||||
```rust
|
||||
/// All chunks in a district, flat array indexed by (x, y, z)
|
||||
struct DistrictChunks {
|
||||
/// 8×8 chunks per z-level, up to 8 z-levels
|
||||
chunks: Vec<ChunkData>, // indexed as z * 64 + y * 8 + x
|
||||
}
|
||||
```
|
||||
|
||||
Cache-friendly, contiguous, no pointer chasing. 64 chunks per z-level fit in ~1.3 MB — easily fits in L2 cache for spatial queries.
|
||||
|
||||
### 4.4 What If We Added More Levels?
|
||||
|
||||
| Depth | Levels | Cost | Benefit |
|
||||
|-------|--------|------|---------|
|
||||
| 3 | Region → District → Chunk | Loses building-scale planning | Simpler generator |
|
||||
| **4** | **Region → District → Block → Chunk** | **Current. Balanced.** | **Building-scale planning + streaming** |
|
||||
| 5 | + Sub-chunk quarter | Quarter = extra indirection at fill time | Finer fill control |
|
||||
| 6 | + Room | Individual room tracking | Overkill — rooms are tile patterns |
|
||||
|
||||
**Verdict:** 4 levels is the sweet spot. Quarters are a fill-time concept, not a hierarchy level. Going deeper adds complexity without proportional benefit.
|
||||
|
||||
---
|
||||
|
||||
## 5. v0.1 Stub Interfaces for the Generator
|
||||
|
||||
v0.1 is hand-authored (D-036, D-093). The generator doesn't run. But the data structures and interfaces it will consume must exist as stubs now, or v0.2+ work will require a rewrite.
|
||||
|
||||
### 5.1 Must Stub Now (v0.1)
|
||||
|
||||
These interfaces are needed for the hand-authored Transit District to be expressible in generator-compatible terms. This validates the data model.
|
||||
|
||||
| Stub | What it does | Why now |
|
||||
|------|-------------|---------|
|
||||
| `DistrictSkeleton` struct | Serializable district description | The v0.1 Transit District should be representable as a DistrictSkeleton. This validates Q-036 — if the hand-authored district can be expressed as generator output, the data structure is correct. |
|
||||
| `ChunkData` struct | Per-chunk tile storage with edge contracts | Already partially exists for D-012 chunk loading. Needs edge contract fields added. |
|
||||
| `BlockSkeleton` struct | Per-block zoning + chunk layout | Validates that the 2×2 block decomposition works for the Transit District's hand-authored social sites. |
|
||||
| `SocialSitePlacement` struct | Template tag + block/chunk coordinates + NPC slots | Validates that D-025 social sites can be addressed within the spatial hierarchy. |
|
||||
| `DistrictType` enum | Transit, Residential, Commercial, etc. | Needed for Sova station's 6-district model (D-093, station profile). |
|
||||
| `AccessPoint` / `CorridorSpine` | Entry points and corridor network | Validates the access topology from D-093 (gate cluster → transition → terminal → bar). |
|
||||
|
||||
**Effort estimate: ~3-4 developer-days** to define structs, serialize the Transit District as a DistrictSkeleton, and write validation tests.
|
||||
|
||||
### 5.2 Stub at Block/Chunk Level (v0.1-v0.2)
|
||||
|
||||
| Stub | What it does | Target |
|
||||
|------|-------------|--------|
|
||||
| `ChunkLayout` enum | Merge strategy per block | v0.1 — needed for Transit District block decomposition |
|
||||
| `EdgeContract` struct | Connection points per chunk face | v0.2 — first generated chunks need this |
|
||||
| `ZoningType` enum | Block-level land use classification | v0.2 — drives template selection |
|
||||
|
||||
### 5.3 Generator Pipeline Stubs (v0.2+, Design Only Now)
|
||||
|
||||
These are the pipeline stages themselves. v0.1 doesn't execute them, but the stage interfaces should be **designed** (not implemented) now so the pipeline architecture is validated.
|
||||
|
||||
| Pipeline Stage | Input | Output | Implementation target |
|
||||
|----------------|-------|--------|----------------------|
|
||||
| Geography | World seed, system parameters | Planet/station type, basic terrain | v0.6+ |
|
||||
| Infrastructure | Geography output, transport network | Station layout (district count, positions, connections) | v0.4+ |
|
||||
| Zoning | Infrastructure, economic/political context | Per-block zoning assignments | v0.3+ |
|
||||
| Block Planning | Zoning, social site library, population targets | BlockSkeletons with ChunkLayouts + edge contracts | v0.3+ |
|
||||
| Chunk Fill | BlockSkeleton, edge contracts, template library | Tile data for each 64×64 chunk | v0.2 (first target) |
|
||||
| NPC Population | Social site placements, population density, cultural profile | NPC generation (D-024 axes, role assignments) | v0.3+ |
|
||||
|
||||
**Critical path for Q-037:** Chunk Fill is the first generator stage to implement (v0.2) because it's the most concrete — takes a planned block and fills tiles from templates. Everything above it can be hand-specified while Chunk Fill is developed and validated.
|
||||
|
||||
### 5.4 Validation Strategy: Transit District as Generator Ground Truth
|
||||
|
||||
**Recommendation:** Express the v0.1 Transit District (D-093) as a hand-authored `DistrictSkeleton` + hand-authored `ChunkData` for each of its 64 chunks. This serves as:
|
||||
|
||||
1. **Schema validation** — if the skeleton can't express the Transit District, the schema is wrong
|
||||
2. **Generator test fixture** — future generator output is compared against the hand-authored ground truth
|
||||
3. **Content pipeline test** — the skeleton → rendered map pipeline is validated end-to-end with known-good data
|
||||
|
||||
This is *not* requiring the Transit District to be "generated." It's requiring the generator's output format to be expressive enough to describe the Transit District. If it can describe the most complex hand-authored district, it can describe anything the generator produces.
|
||||
|
||||
---
|
||||
|
||||
## 6. Technical Risk Assessment
|
||||
|
||||
| Risk | Severity | Mitigation |
|
||||
|------|----------|------------|
|
||||
| Edge contract system produces tile discontinuities at chunk boundaries | HIGH | Comprehensive boundary tests; Transit District as test fixture validates edge alignment |
|
||||
| Generator can't fill chunks within 500ms budget | MEDIUM | Template stamping (not WFC) for v0.2; WFC only if templates are insufficient |
|
||||
| Multi-block structures create irregular block boundaries | MEDIUM | Reservation system claims blocks before fill; reserved blocks use custom layouts |
|
||||
| District skeleton data model doesn't survive contact with diverse district types | MEDIUM | Validate against all 6 Sova district types + 3 planetary settlement types before locking |
|
||||
| Cross-district structures (park spanning two districts) create coordination complexity | LOW | Cap at v0.6+; v0.1-0.5 districts are self-contained. `cross_district: bool` on reservations is the escape hatch. |
|
||||
| Quarter system over-complicates chunk fill | LOW | Quarters are generation-side only; if they cause problems, fall back to free-form template placement within chunks |
|
||||
|
||||
---
|
||||
|
||||
## 7. Summary of Hard Constraints
|
||||
|
||||
1. **Chunk = 64×64 sim tiles.** Non-negotiable. Streaming atom. (D-094)
|
||||
2. **Block = 2×2 chunks.** Generator planning unit. (D-094)
|
||||
3. **District = 4×4 blocks = 64 chunks.** Template composition unit. (D-094)
|
||||
4. **Hierarchy = 4 levels.** Quarters are fill rules, not hierarchy levels.
|
||||
5. **Edge contracts at chunk boundaries.** Required for cross-chunk tile continuity.
|
||||
6. **District skeleton must express D-025 social sites.** Generator arranges templates, doesn't invent new site types.
|
||||
7. **Chunk fill budget: ~500ms.** Based on player walk speed and 3×3 loading grid.
|
||||
8. **District generation must be local.** Required for D-012 borderless generation future.
|
||||
9. **MessagePack serialization for all generator output.** Per D-020.
|
||||
10. **Deterministic from seed.** Per D-010 principle 4. Same seed → same district → same tiles.
|
||||
|
||||
---
|
||||
|
||||
*Tyre — Round 1 complete. Standing by for Round 2 cross-pollination.*
|
||||
@@ -0,0 +1,793 @@
|
||||
# Round 2: Tyre — Technical Pipeline with Two-Phase Generation and Edge Bleed
|
||||
|
||||
**Workshop:** Generator Architecture (#562)
|
||||
**Agent:** Tyre (Technical Architect)
|
||||
**Date:** 2026-02-27
|
||||
|
||||
**Lead directive acknowledged:** This is NOT a detective game. The generator must support tycoon, dating sim, political drama, and investigation playstyles equally. The DistrictSkeleton and all spatial guarantees are playstyle-agnostic. The architecture bakes in *information asymmetry as a spatial property*, not investigation as a gameplay assumption.
|
||||
|
||||
---
|
||||
|
||||
## 1. Two-Phase Generation Architecture
|
||||
|
||||
The lead directive splits generation into two architecturally separate phases. *cracks knuckles* — this is actually elegant, because it maps cleanly onto two different computational profiles.
|
||||
|
||||
### 1.1 Phase 1: World Prep (Background, Async)
|
||||
|
||||
Runs on a spare CPU core while the player is playing. Produces the **skeleton layer** — everything above chunk fill. This is the "what goes where" pass.
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────┐
|
||||
│ PHASE 1: WORLD PREP (background thread, ~50-500ms/district) │
|
||||
├──────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Master Seed │
|
||||
│ ↓ │
|
||||
│ System Generation (star type, worlds, stations) │
|
||||
│ ↓ │
|
||||
│ Society Profile per world (ingredients → parameters) │
|
||||
│ ↓ │
|
||||
│ District Skeletons per world (zoning, social sites, │
|
||||
│ access topology, NPC slots, reservations, │
|
||||
│ corridor spines, zone palettes) │
|
||||
│ ↓ │
|
||||
│ Block Planning per district (ChunkLayout, edge │
|
||||
│ contracts, era tags, quarter assignments) │
|
||||
│ ↓ │
|
||||
│ NPC Population per district (role assignment, │
|
||||
│ triangle seeding, entanglement marking) │
|
||||
│ ↓ │
|
||||
│ OUTPUT: PreparedDistrict (skeleton + block plans + │
|
||||
│ NPC roster — everything except tile data) │
|
||||
│ │
|
||||
└──────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Characteristics:**
|
||||
- CPU-bound, no I/O. Pure deterministic computation from seed.
|
||||
- Can run speculatively for districts the player hasn't visited yet.
|
||||
- Output is small (~10-50 KB per district). All PreparedDistricts for a 300-world game fit in ~30-150 MB.
|
||||
- No rendering dependency. No Godot interaction. Pure Rust.
|
||||
- **Scheduling:** Prepare the player's home system at game start (blocking). Queue neighboring systems by gate distance. Prepare on-demand when the player books travel.
|
||||
|
||||
**Timing budget:** Phase 1 for one district: ~50-500ms (dominated by NPC population generation). One full world (6 districts): ~300ms-3s. Entire 300-world galaxy: ~90-900s (1.5-15 minutes). At game start, only the home system is blocking (~2-3s); everything else runs in background.
|
||||
|
||||
### 1.2 Phase 2: Local Area Gen (On-Demand, Interactive)
|
||||
|
||||
Runs when the player enters a district for the first time, triggered by chunk loading. Produces **tile data** — the actual playable space.
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────┐
|
||||
│ PHASE 2: LOCAL AREA GEN (on-demand, ~100-500ms/chunk) │
|
||||
├──────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ PreparedDistrict (from Phase 1) │
|
||||
│ ↓ │
|
||||
│ Chunk Fill (per chunk, on entering loading radius) │
|
||||
│ - Read BlockSkeleton + edge contracts │
|
||||
│ - Select template from social site tag │
|
||||
│ - Place walls, floors, furniture, fixtures │
|
||||
│ - Apply zone palette + era materials │
|
||||
│ - Place NPC spawn points from roster │
|
||||
│ - Validate edge contracts against neighbors │
|
||||
│ ↓ │
|
||||
│ OUTPUT: ChunkData (64×64 tile array, ready to stream) │
|
||||
│ │
|
||||
│ Chunk Cache (LRU, persists to save file) │
|
||||
│ - Generated chunks cached in memory │
|
||||
│ - Written to save on save-game │
|
||||
│ - Loaded from save on load-game (skips re-gen) │
|
||||
│ │
|
||||
└──────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Characteristics:**
|
||||
- Runs on the simulation thread (or a dedicated gen thread with result handoff).
|
||||
- Template-based stamping — NOT full WFC. WFC is a future optimization if templates prove insufficient.
|
||||
- Each chunk fill reads only its own BlockSkeleton + neighbor edge contracts. No global state dependency.
|
||||
- **Idempotent from seed:** Same PreparedDistrict + same chunk coordinates → same ChunkData. Always.
|
||||
- Once generated, chunks are cached and never regenerated (unless the save file is wiped).
|
||||
|
||||
**Timing budget per chunk:** ~100-500ms. Player walk speed = 1 tile/200ms, crossing a chunk takes ~12.8s. New chunks enter the 3×3 loading grid every ~6-12s. Budget is generous.
|
||||
|
||||
### 1.3 The Interface Between Phases
|
||||
|
||||
The `PreparedDistrict` is the contract between Phase 1 and Phase 2. It is the only data structure that crosses the boundary. Phase 2 never calls Phase 1 functions. Phase 1 never produces tile data.
|
||||
|
||||
```rust
|
||||
/// The contract between Phase 1 (world prep) and Phase 2 (local gen).
|
||||
/// Serializable, cacheable, deterministic from seed.
|
||||
struct PreparedDistrict {
|
||||
skeleton: DistrictSkeleton, // spatial plan (§2 below)
|
||||
block_plans: [[BlockPlan; 4]; 4], // per-block fill instructions
|
||||
npc_roster: NpcRoster, // generated NPCs with role assignments
|
||||
seed_chain: SeedChain, // derived seeds for Phase 2 determinism
|
||||
}
|
||||
|
||||
struct BlockPlan {
|
||||
skeleton: BlockSkeleton, // from Phase 1
|
||||
chunk_fills: [[ChunkFillSpec; 2]; 2], // per-chunk fill instructions
|
||||
edge_contracts: BlockEdgeContracts, // connection points on all 4 faces
|
||||
}
|
||||
|
||||
struct ChunkFillSpec {
|
||||
/// Template tag to instantiate (e.g., "logistics_hub_main_floor")
|
||||
template_tag: String,
|
||||
/// Quarter layout within this chunk
|
||||
quarter_layout: QuarterLayout,
|
||||
/// Derived seed for this specific chunk's procedural details
|
||||
chunk_seed: u64,
|
||||
/// Zone palette inherited from district
|
||||
zone_id: ZoneId,
|
||||
/// Era tag inherited from block
|
||||
era: Era,
|
||||
/// NPC spawn points assigned from roster
|
||||
npc_spawns: Vec<NpcSpawnPoint>,
|
||||
/// Access tier for this chunk's primary zone
|
||||
access_tier: AccessTier,
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Updated DistrictSkeleton with Edge Bleed
|
||||
|
||||
The lead directive is clear: the 4×4 block grid must NOT be perceptible. Districts must bleed into each other at boundaries.
|
||||
|
||||
### 2.1 The Edge Bleed Problem
|
||||
|
||||
D-094 defines a district as 512×512 sim tiles (4×4 blocks). If two adjacent districts have hard boundaries — Gate Cluster ends at block (3,y) and Residential starts at block (0,y) — the player walks through a visual seam. That seam screams "procedural grid."
|
||||
|
||||
### 2.2 Solution: Shared Boundary Blocks
|
||||
|
||||
At district boundaries, adjacent districts share a **transition strip** — a row of blocks that belongs to neither district exclusively. These blocks blend the zone palettes, era tags, and building character of both districts.
|
||||
|
||||
```
|
||||
District A District B
|
||||
┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐
|
||||
│ A │ A │ A │ A │ │ B │ B │ B │ B │
|
||||
├────┼────┼────┼────┤ ├────┼────┼────┼────┤
|
||||
│ A │ A │ A │ A │ │ B │ B │ B │ B │
|
||||
├────┼────┼────┼────┤ ├────┼────┼────┼────┤
|
||||
│ A │ A │ A │ A │ │ B │ B │ B │ B │
|
||||
├────┼────┼────┼────┤ ├────┼────┼────┼────┤
|
||||
│ A │ A │ Aₜ │ Aₜ │←─ SHARED ─→│ Bₜ │ Bₜ │ B │ B │
|
||||
└────┴────┴────┴────┘ └────┴────┴────┴────┘
|
||||
|
||||
Aₜ/Bₜ = transition blocks. Visually: A's palette → neutral → B's palette.
|
||||
```
|
||||
|
||||
**How it works:**
|
||||
|
||||
The outermost column/row of each district is designated as the **transition strip**. Transition blocks:
|
||||
- Use a blended zone palette (weighted average of both districts' adjacent zone palettes)
|
||||
- Can have mixed era tags (one chunk from District A's era, one from District B's)
|
||||
- Use a specific "transition corridor" street type (per V-05: 6vt width, neutral industrial palette)
|
||||
- Building footprints in transition blocks are smaller (no 2×2 full-merge buildings) to avoid buildings that feel like they belong to one district or the other
|
||||
- Social sites are NOT placed in transition blocks — they are pass-through zones, not destinations
|
||||
|
||||
### 2.3 Updated DistrictSkeleton Struct
|
||||
|
||||
```rust
|
||||
struct DistrictSkeleton {
|
||||
district_id: DistrictId,
|
||||
seed: u64,
|
||||
district_type: DistrictType,
|
||||
context: DistrictContext,
|
||||
|
||||
/// The 4×4 block grid — interior blocks
|
||||
blocks: [[BlockSkeleton; 4]; 4],
|
||||
|
||||
/// NEW: Boundary descriptors for edge bleed
|
||||
/// Each edge (N/S/E/W) describes what this district offers
|
||||
/// to the shared transition strip with its neighbor
|
||||
boundaries: DistrictBoundaries,
|
||||
|
||||
social_sites: Vec<SocialSitePlacement>,
|
||||
reservations: Vec<MultiBlockReservation>,
|
||||
access_points: Vec<AccessPoint>,
|
||||
corridors: Vec<CorridorSpine>,
|
||||
z_levels: u8,
|
||||
zone_palette: Vec<ZoneDefinition>,
|
||||
|
||||
/// NEW: Society profile reference (serde-compatible, §4)
|
||||
society_profile: SocietyProfileRef,
|
||||
|
||||
/// NEW: Terrain type for non-urban districts (§5)
|
||||
terrain: TerrainType,
|
||||
|
||||
/// NEW: District complexity tier (§6)
|
||||
complexity: ComplexityTier,
|
||||
}
|
||||
|
||||
struct DistrictBoundaries {
|
||||
/// For each of the 4 edges, describe the transition interface
|
||||
north: Option<BoundaryEdge>,
|
||||
south: Option<BoundaryEdge>,
|
||||
east: Option<BoundaryEdge>,
|
||||
west: Option<BoundaryEdge>,
|
||||
}
|
||||
|
||||
struct BoundaryEdge {
|
||||
/// Zone palette at this district's boundary edge
|
||||
edge_palette: ZonePalette,
|
||||
|
||||
/// Era tag at the boundary
|
||||
edge_era: Era,
|
||||
|
||||
/// Access points that open onto the boundary (doors, corridors)
|
||||
/// These must align with the neighbor's corresponding access points
|
||||
access_points: Vec<BoundaryAccessPoint>,
|
||||
|
||||
/// Terrain type at the boundary (for non-urban transitions)
|
||||
edge_terrain: TerrainType,
|
||||
|
||||
/// Building density at boundary (always lower than interior)
|
||||
edge_density: f32, // 0.0-1.0, typically 0.3-0.5 for transition zones
|
||||
}
|
||||
|
||||
struct BoundaryAccessPoint {
|
||||
/// Position along the edge (0-3 for 4 blocks on this edge)
|
||||
block_index: u8,
|
||||
|
||||
/// Offset within the block (in chunks: 0 or 1)
|
||||
chunk_offset: u8,
|
||||
|
||||
/// Width in visual tiles
|
||||
width_vt: u8,
|
||||
|
||||
/// Access tier
|
||||
access_tier: AccessTier,
|
||||
|
||||
/// What kind of connection (street, corridor, service, restricted)
|
||||
connection_type: ConnectionType,
|
||||
}
|
||||
```
|
||||
|
||||
### 2.4 Transition Block Generation
|
||||
|
||||
Transition blocks are generated in Phase 1 as a **joint operation** between two adjacent PreparedDistricts. The algorithm:
|
||||
|
||||
1. District A and District B are both Phase 1 complete.
|
||||
2. For each shared edge, compute the transition strip:
|
||||
- Read A's `boundaries.east` and B's `boundaries.west` (or whichever edge pair).
|
||||
- Align access points: match A's boundary access points with B's. Where both districts offer a corridor, connect them. Where only one does, dead-end the other gracefully (service door, maintenance hatch).
|
||||
- Blend zone palettes: transition blocks use `lerp(A.edge_palette, B.edge_palette, 0.5)` with rounding to nearest palette stop.
|
||||
- Select era: use the older of the two boundary eras (transitions feel like infrastructure, not new construction).
|
||||
- Generate transition block skeletons with the blended parameters.
|
||||
3. Store transition blocks in a `TransitionStrip` struct shared between both PreparedDistricts.
|
||||
|
||||
```rust
|
||||
struct TransitionStrip {
|
||||
/// Which two districts this strip connects
|
||||
district_a: DistrictId,
|
||||
district_b: DistrictId,
|
||||
|
||||
/// Shared edge (from A's perspective)
|
||||
edge: CardinalDirection,
|
||||
|
||||
/// Transition blocks (1×4 strip = 4 blocks between the districts)
|
||||
blocks: [TransitionBlock; 4],
|
||||
}
|
||||
|
||||
struct TransitionBlock {
|
||||
/// Blended palette
|
||||
palette: ZonePalette,
|
||||
era: Era,
|
||||
/// Simplified chunk layout (no large merges, mostly corridors)
|
||||
chunks: [[ChunkFillSpec; 2]; 2],
|
||||
/// Access points connecting to each district
|
||||
connections_a: Vec<BoundaryAccessPoint>,
|
||||
connections_b: Vec<BoundaryAccessPoint>,
|
||||
}
|
||||
```
|
||||
|
||||
**Memory cost:** 4 transition blocks per shared edge × ~1 KB each = ~4 KB per edge. A station with 6 districts has ~10 shared edges = ~40 KB of transition data. Trivial.
|
||||
|
||||
**Visual result:** Walking from the Terminal district into the Residential Core, the player crosses 2-3 blocks of gradual transition — neutral corridor widening, palette shifting, era mixing, building scale changing. No seam. No grid visible.
|
||||
|
||||
---
|
||||
|
||||
## 3. Seed Propagation — Single Master Seed with Deterministic Derivation
|
||||
|
||||
The lead says "seeds are solved." Good. Here's the architecture.
|
||||
|
||||
### 3.1 Seed Derivation Tree
|
||||
|
||||
One master seed. Everything else is deterministically derived. No per-stage seeds as independent parameters.
|
||||
|
||||
```rust
|
||||
/// Single master seed → everything.
|
||||
struct SeedChain {
|
||||
master: u64,
|
||||
}
|
||||
|
||||
impl SeedChain {
|
||||
/// Derive a sub-seed for a specific purpose.
|
||||
/// Uses a keyed hash: blake3(master || domain_tag || index)
|
||||
fn derive(&self, domain: &str, index: u64) -> u64 {
|
||||
let mut hasher = blake3::Hasher::new();
|
||||
hasher.update(&self.master.to_le_bytes());
|
||||
hasher.update(domain.as_bytes());
|
||||
hasher.update(&index.to_le_bytes());
|
||||
let hash = hasher.finalize();
|
||||
u64::from_le_bytes(hash.as_bytes()[..8].try_into().unwrap())
|
||||
}
|
||||
|
||||
fn system_seed(&self, system_id: u64) -> u64 {
|
||||
self.derive("system", system_id)
|
||||
}
|
||||
|
||||
fn district_seed(&self, system_id: u64, district_id: u64) -> u64 {
|
||||
self.derive("district", system_id * 10000 + district_id)
|
||||
}
|
||||
|
||||
fn npc_seed(&self, district_seed: u64, npc_index: u64) -> u64 {
|
||||
self.derive("npc", district_seed.wrapping_mul(1000) + npc_index)
|
||||
}
|
||||
|
||||
fn chunk_seed(&self, district_seed: u64, chunk_x: u64, chunk_y: u64) -> u64 {
|
||||
self.derive("chunk", district_seed ^ (chunk_x << 16) ^ chunk_y)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 Answering Nigel's Question
|
||||
|
||||
**"Same seed, different character selection — same world or different world?"**
|
||||
|
||||
**Same world.** The master seed determines the physical world, NPC roster, triangle configurations, entanglement pattern — everything generated. Character selection is a **filter**, not a world-generation input. Both characters exist in the same generated world. The player picks which lens to view it through.
|
||||
|
||||
This is architecturally correct per D-010 principle 3: "no baking player identity into the game loop." The simulation doesn't know which character is player-controlled. Character selection happens at the session layer, not the generation layer.
|
||||
|
||||
**Consequence:** Two players with the same seed but different character choices play in an *identical* world. Their experiences differ because information boundaries (D-010 principle 2) filter what each character can see, access, and know. This is exactly the D-027 "two keyholes on the same world" promise.
|
||||
|
||||
### 3.3 Seed-State Artifact (Q-030)
|
||||
|
||||
The seed state is a single file recording all derivation inputs:
|
||||
|
||||
```yaml
|
||||
# seed-state.yaml — complete reproduction record
|
||||
master_seed: 0xA7B3F1D2E5C84096
|
||||
character: smuggler # session layer, not generation layer
|
||||
tier1_module_draws: [smuggling_ring, corporate_espionage] # pool draws from master seed
|
||||
home_system: krenn
|
||||
home_district: transit
|
||||
# Everything else is deterministically derivable from master_seed.
|
||||
# This file exists for debugging and replay, not as a generation input.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Society Profile as Serde Schema (OQ-5)
|
||||
|
||||
Miri asks: can the content pipeline consume the society profile YAML as a serde-compatible schema?
|
||||
|
||||
**Yes.** Feasible. Not even challenging. Here's what the Rust struct looks like:
|
||||
|
||||
```rust
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
struct SocietyProfile {
|
||||
heritage: HeritageBlend,
|
||||
settlement_motivation: Option<SettlementMotivation>,
|
||||
economic_function: EconomicFunction,
|
||||
economic_pressure: Vec<EconomicPressure>, // 0-2 items
|
||||
drift_stage: DriftStage,
|
||||
faction_presence: FactionPresence,
|
||||
philosophical_alignment: Option<PhilosophicalAlignment>,
|
||||
meridian_coverage: MeridianCoverage,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
struct HeritageBlend {
|
||||
/// 1-3 roots with blend weights summing to 1.0
|
||||
roots: Vec<HeritageEntry>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
struct HeritageEntry {
|
||||
root: HeritageRoot,
|
||||
weight: f32,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
||||
enum HeritageRoot {
|
||||
Frost, Tide, Iron, Spice, Jade,
|
||||
Dust, Vine, Salt, Stone, Arc,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
enum DriftStage {
|
||||
Pioneer, // 0-50yr
|
||||
Crystallizing, // 50-150yr
|
||||
Mature, // 150-300yr
|
||||
Ancient, // 300+yr
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
struct FactionPresence {
|
||||
commission: PresenceTier,
|
||||
concord: PresenceTier,
|
||||
syndic: PresenceTier,
|
||||
independent: PresenceTier,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
enum PresenceTier {
|
||||
Comprehensive, Standard, Intermittent, Absent,
|
||||
}
|
||||
|
||||
// ... remaining enums follow the same pattern
|
||||
```
|
||||
|
||||
**serde_yaml** handles this out of the box. Miri's YAML format maps 1:1 to Rust structs. NULL values → `Option<T>` with serde default. Blend weights → `Vec<HeritageEntry>` with a validation pass to ensure sum ≈ 1.0.
|
||||
|
||||
**Validation:** Add a `validate()` method that checks:
|
||||
- Heritage weights sum to 1.0 (±0.01 tolerance)
|
||||
- At least 1 heritage root
|
||||
- At most 3 heritage roots
|
||||
- Economic pressure has 0-2 entries
|
||||
- No contradictory faction presence (e.g., `commission: Comprehensive` + `independent: SystemWide`)
|
||||
|
||||
**Integration:** Society profiles can be:
|
||||
1. Hand-authored in YAML (for specific systems like Krenn)
|
||||
2. Generated from seed (for the other 299 systems)
|
||||
3. Loaded via serde_yaml and passed to the generation pipeline
|
||||
|
||||
**Effort estimate:** ~1 developer-day to define all enum types and validation. The serde derive macros do the rest.
|
||||
|
||||
---
|
||||
|
||||
## 5. Era Fields in Chunk Data (OQ-6)
|
||||
|
||||
Miri asks: does the chunk data structure have era fields?
|
||||
|
||||
**Yes. At the block level, inherited by chunks.**
|
||||
|
||||
```rust
|
||||
struct BlockSkeleton {
|
||||
position: (u8, u8),
|
||||
zoning: ZoningType,
|
||||
reservation: Option<ReservationId>,
|
||||
chunk_layout: ChunkLayout,
|
||||
hosted_sites: Vec<SocialSiteId>,
|
||||
|
||||
/// NEW: Construction era for this block
|
||||
era: Era,
|
||||
|
||||
/// NEW: Era modifications (retrofits, additions)
|
||||
/// A block can have a base era + modification overlays
|
||||
era_modifications: Vec<EraModification>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
enum Era {
|
||||
/// Original construction. Lowest Meridian coverage.
|
||||
/// Maintenance corridors, foundation infrastructure.
|
||||
Era1,
|
||||
|
||||
/// First major retrofit/expansion. Mixed coverage.
|
||||
/// Operational spaces, working infrastructure.
|
||||
Era2,
|
||||
|
||||
/// Recent construction. Highest coverage.
|
||||
/// Institutional, commercial, modern residential.
|
||||
Era3,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
struct EraModification {
|
||||
/// Which era this modification represents
|
||||
era: Era,
|
||||
|
||||
/// What fraction of the block shows this modification (0.0-1.0)
|
||||
coverage: f32,
|
||||
|
||||
/// Type of modification
|
||||
mod_type: ModificationType,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
enum ModificationType {
|
||||
/// Surface-mounted conduits, junction boxes (Era 2 on Era 1)
|
||||
SurfaceRetrofit,
|
||||
/// New partition walls, converted spaces (Era 3 on Era 1/2)
|
||||
InternalConversion,
|
||||
/// Extension/addition changing building footprint
|
||||
StructuralAddition,
|
||||
/// Commission-grade infrastructure upgrade
|
||||
InstitutionalUpgrade,
|
||||
}
|
||||
```
|
||||
|
||||
**How it flows:**
|
||||
1. Phase 1 assigns `era` per block based on district context + z-level + historical events.
|
||||
2. Phase 1 assigns `era_modifications` for blocks that have been retrofitted.
|
||||
3. Phase 2 (chunk fill) reads the block's era + modifications and selects materials accordingly.
|
||||
4. Araminta's visual rules apply: base palette from era, modifications as overlay elements.
|
||||
|
||||
**Z-level correlation (from D-093):** The default station pattern is z=0 → Era 1, z=1 → Era 2, z=2 → Era 3. But this isn't mandatory — a recently rebuilt ground level could be Era 3, with an old observation deck as Era 1. The generator decides per-block, not per-z-level.
|
||||
|
||||
---
|
||||
|
||||
## 6. Population/Zoning Ordering (OQ-1)
|
||||
|
||||
Gestalt raises: NPC secrets must have plausible staging grounds. Population can't be assigned before spaces exist. But spaces need population targets to be correctly sized.
|
||||
|
||||
**Implementation cost of the feedback loop: LOW.** Here's why.
|
||||
|
||||
### 6.1 The Two-Pass Solution
|
||||
|
||||
This isn't a feedback loop — it's a two-pass pipeline where each pass produces a different artifact:
|
||||
|
||||
**Pass 1 (in Phase 1, district skeleton stage):**
|
||||
- Zoning assigns block types.
|
||||
- Population **targets** are set from capacity formulas (population density × block count × block type multiplier).
|
||||
- NPC **role slots** are allocated to social sites (e.g., "this logistics hub needs 1 supervisor, 3 dock workers, 2 customs handlers").
|
||||
- Triangle **templates** are selected (e.g., "workplace rivalry triangle in logistics hub" + "social tension triangle across bar and logistics hub").
|
||||
- Secret **type requirements** are checked: "this triangle requires a restricted-access staging ground" → verify at least one block has `access_tier: restricted`. If not, add one.
|
||||
|
||||
**Pass 2 (in Phase 1, NPC population stage):**
|
||||
- NPC 10-axis generation fills the role slots with concrete NPCs.
|
||||
- Secrets are assigned to NPCs with spatial anchoring to specific blocks/chunks.
|
||||
- Entanglement marking (which NPCs are in the 20%) is applied.
|
||||
- The NPC roster is complete.
|
||||
|
||||
**Key insight:** Pass 1 checks *spatial prerequisites*. It doesn't generate NPCs — it verifies that the spaces NPC secrets will need exist in the skeleton. If a triangle template requires a restricted zone and none exists, the skeleton adjusts its zoning (adds a restricted block) before NPC generation runs. This is a validation-and-adjust step, not a true feedback loop.
|
||||
|
||||
**Implementation cost:** One `validate_spatial_prerequisites()` function that runs after zoning, before NPC population. Checks ~10 spatial requirements (each gameplay guarantee from Gestalt's Round 1) against the skeleton. Adjusts zoning for any unmet requirement. ~200 lines of Rust. Half a developer-day.
|
||||
|
||||
### 6.2 Why This Isn't Expensive
|
||||
|
||||
The prerequisites are finite and small:
|
||||
- At least 1 block with `access_tier: Restricted` (for secrets requiring private space)
|
||||
- At least 1 block with `meridian_coverage: Degraded` (for grey economy activity)
|
||||
- At least 1 social site with `access_tier: Public` (for social manipulation)
|
||||
- At least 1 social site with `access_tier: Insider` (for asymmetric access)
|
||||
- At least 1 corridor spine connecting transit node to social sites (for routine observation)
|
||||
|
||||
These are Gestalt's guarantees expressed as spatial validators. The zoning pass produces them naturally 95% of the time. The validator catches edge cases and adjusts the remaining 5%.
|
||||
|
||||
---
|
||||
|
||||
## 7. Non-Urban Terrain: Farmland, Wilderness, Ocean, Secluded Towns
|
||||
|
||||
The lead directive pushes beyond population hubs. *Let me be honest about what this means technically.*
|
||||
|
||||
### 7.1 What Changes
|
||||
|
||||
Non-urban terrain changes **chunk fill content**, not the hierarchy structure. Chunks are still 64×64 sim tiles. Blocks are still 2×2 chunks. Districts are still 4×4 blocks. The spatial hierarchy is terrain-agnostic.
|
||||
|
||||
What changes:
|
||||
|
||||
| Property | Urban | Non-Urban |
|
||||
|----------|-------|-----------|
|
||||
| Fill density | 60-100% of quarters filled with structures | 0-20% filled; rest is terrain |
|
||||
| Template type | Buildings, corridors, rooms | Terrain features (fields, trees, water, paths) |
|
||||
| NPC density | 30-80 per district | 0-10 per district |
|
||||
| Social sites | 3-8 per district | 0-2 per district |
|
||||
| Edge contracts | Door/corridor connections | Path/road connections |
|
||||
| LOS anchors | Walls, pillars, furniture | Trees, terrain elevation, fences, hedgerows |
|
||||
| Zone palette | Architectural materials | Natural materials (soil, grass, water, rock) |
|
||||
|
||||
### 7.2 TerrainType Enum
|
||||
|
||||
```rust
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
enum TerrainType {
|
||||
/// Station interior (current default)
|
||||
Station,
|
||||
|
||||
/// Urban settlement (planet-side city)
|
||||
Urban,
|
||||
|
||||
/// Agricultural (farmland, orchards, greenhouses)
|
||||
Agricultural,
|
||||
|
||||
/// Wilderness (forest, grassland, desert, tundra)
|
||||
Wilderness { biome: Biome },
|
||||
|
||||
/// Water (ocean, lake, river delta)
|
||||
Water { water_type: WaterType },
|
||||
|
||||
/// Transitional (urban edge, suburbs, outskirts)
|
||||
Transitional,
|
||||
|
||||
/// Orbital (small installation, different geometry rules)
|
||||
Orbital,
|
||||
}
|
||||
```
|
||||
|
||||
### 7.3 How Non-Urban Chunks Fill
|
||||
|
||||
Non-urban chunk fill uses terrain templates instead of building templates:
|
||||
|
||||
- **Agricultural:** Grid of field plots (each plot = 1-2 quarters), irrigation channels as corridors, farmhouse/barn as the 1-2 buildings per district. Edge contracts carry road/path connections. A farm district is mostly open space with sparse LOS anchors (fences, crop height variation, equipment sheds).
|
||||
|
||||
- **Wilderness:** Procedural terrain with natural LOS blockers (trees, rock formations, elevation). Paths replace corridors. No buildings unless the district has a `SecludedSettlement` social site. Edge contracts carry trail connections.
|
||||
|
||||
- **Water:** Mostly impassable tiles. Docks/jetties as narrow accessible strips. Boats as mobile platforms. Edge contracts carry dock access points.
|
||||
|
||||
- **Transitional:** Sparse urban. Wide roads, scattered buildings, open lots. The "suburb" between a city district and farmland. This is where edge bleed naturally produces a transition from urban density to rural openness.
|
||||
|
||||
### 7.4 What Stays the Same
|
||||
|
||||
- **Chunk size:** 64×64 sim tiles. Still the streaming atom. A field is just a chunk full of crop tiles instead of floor tiles.
|
||||
- **Block planning:** Still 2×2 chunks. The "block" in farmland means "which field plot goes where" instead of "which building footprint goes where."
|
||||
- **District skeleton:** Still describes what's in the district. A wilderness district skeleton has fewer social sites (maybe 1 — a ranger station or hermit cabin) and more terrain descriptors.
|
||||
- **Edge contracts:** Still define how chunks connect at boundaries. Roads connect instead of corridors.
|
||||
- **Shadowcasting:** Still works. Trees and terrain features occlude LOS just like walls.
|
||||
|
||||
### 7.5 Insignificant Places
|
||||
|
||||
The lead directive explicitly requires "boring" districts — low-complexity, low-NPC, pass-through zones.
|
||||
|
||||
```rust
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
enum ComplexityTier {
|
||||
/// Full gameplay district — multiple social sites, rich NPC population,
|
||||
/// all gameplay guarantees met. (Transit District, Residential Core)
|
||||
Full,
|
||||
|
||||
/// Moderate — 1-2 social sites, moderate NPC population, partial
|
||||
/// gameplay guarantees. (Commercial Quarter, Industrial Sector)
|
||||
Moderate,
|
||||
|
||||
/// Minimal — 0-1 social sites, sparse NPCs, pass-through zone.
|
||||
/// No gameplay guarantees required. (Farmland, wilderness, transit corridor)
|
||||
Minimal,
|
||||
|
||||
/// Empty — no social sites, no NPCs. Pure terrain.
|
||||
/// (Open water, deep wilderness, uninhabited terrain)
|
||||
Empty,
|
||||
}
|
||||
```
|
||||
|
||||
**Gameplay guarantees (Gestalt's 7 from Round 1) only apply to `Full` complexity districts.** A farmland district doesn't need a surveillance chokepoint or three investigation paths. It needs to exist, be traversable, and feel appropriate to its terrain type.
|
||||
|
||||
**Why this matters for performance:** Minimal/Empty districts are trivially cheap. Their skeletons are tiny (~500 bytes). Their chunk fill is fast (terrain stamping, no NPC placement, no social site layout). The generator can produce hundreds of these as background filler for a planet-side world without meaningful CPU cost.
|
||||
|
||||
---
|
||||
|
||||
## 8. Addressing Remaining Open Questions
|
||||
|
||||
### 8.1 Quarter Fill Social Consequences (OQ-3)
|
||||
|
||||
Ozzie asks: does the quarter fill type have downstream social consequences?
|
||||
|
||||
**Yes, but through an indirect mechanism.** The quarter fill type is selected based on society profile + economic tier, which are the same parameters that drive NPC generation. A "market stall" quarter appears in districts with `economic_function: Mixed` or `economic_pressure: [tight-margin]`, which also produces NPCs with specific behavioral patterns (transaction-oriented trust models, informal economy participation).
|
||||
|
||||
The quarter fill doesn't *cause* NPC behavior. Both the quarter fill and the NPC behavior are *caused by the same upstream parameters*. The player sees correlation (market stalls → certain NPC types) and reads it as causation. That's architecturally correct — the relationship is real, just indirect.
|
||||
|
||||
**Implementation:** The quarter fill tag feeds into the NPC roster's `spawn_location_preference` field. NPCs generated with "informal economy" traits prefer to spawn near market stall quarters. This creates the spatial correlation Ozzie wants without a direct quarter → NPC dependency.
|
||||
|
||||
### 8.2 Historical Palimpsest (OQ-4)
|
||||
|
||||
Ozzie asks: when the generator produces an L-shaped building, does it record WHY?
|
||||
|
||||
**The generator records the causal chain, but the player discovers the reason through gameplay, not data inspection.**
|
||||
|
||||
The `EraModification` system (§5 above) encodes the cause: an L-shaped building has `mod_type: StructuralAddition` with an era tag indicating when the addition was built. The NPC roster can include NPCs who remember the change ("They added that wing after the dock expansion. Took our courtyard.").
|
||||
|
||||
What the generator does NOT do: generate a text explanation for every spatial anomaly. The anomalies come from the era/modification system; the explanations come from the NPC knowledge system and environmental text. This is the correct separation of concerns — the generator builds the space; the content systems make it legible.
|
||||
|
||||
### 8.3 Empty Quarter Taxonomy Reconciliation (OQ-8)
|
||||
|
||||
Nigel's categories (informal economy, settlement, economic stress, faction presence) and Araminta's categories (plaza, service alley, courtyard, vehicle staging, structural gap) are **orthogonal axes, not conflicting taxonomies.**
|
||||
|
||||
Araminta's types describe **physical form** (what the space looks like). Nigel's describe **social function** (what the space means). A market stall (Nigel: informal economy) is physically a **service alley** (Araminta) with vendor cart furniture. A personal shrine (Nigel: settlement indicator) is physically a **courtyard** (Araminta) with shrine furniture.
|
||||
|
||||
```rust
|
||||
struct QuarterFill {
|
||||
/// Physical form (Araminta's taxonomy)
|
||||
form: QuarterForm,
|
||||
|
||||
/// Social function (Nigel's taxonomy)
|
||||
function: QuarterFunction,
|
||||
|
||||
/// Furniture/object set selected from form × function
|
||||
furnishing_tag: String,
|
||||
}
|
||||
|
||||
enum QuarterForm {
|
||||
Plaza, ServiceAlley, Courtyard, VehicleStaging, StructuralGap,
|
||||
}
|
||||
|
||||
enum QuarterFunction {
|
||||
InformalEconomy, Settlement, EconomicStress, FactionPresence, Neutral,
|
||||
}
|
||||
```
|
||||
|
||||
The `form × function` matrix produces the furniture selection. Not all combinations are valid (no `VehicleStaging × Settlement` — cargo docks don't become shrines). The generator maintains a validity table.
|
||||
|
||||
---
|
||||
|
||||
## 9. Updated Pipeline Summary
|
||||
|
||||
```
|
||||
PHASE 1: WORLD PREP (background, async)
|
||||
═══════════════════════════════════════
|
||||
|
||||
Master Seed
|
||||
↓
|
||||
System Generation ─────── derives: system_seed
|
||||
↓
|
||||
Society Profile ────────── derives: society_seed
|
||||
↓ output: SocietyProfile (serde YAML)
|
||||
↓
|
||||
District Skeletons ─────── derives: district_seed per district
|
||||
├── Zoning (block types, access tiers)
|
||||
├── Spatial prerequisite validation (Gestalt's 7 guarantees,
|
||||
│ only for Full complexity districts)
|
||||
├── Social site placement (D-025 template selection + positioning)
|
||||
├── Multi-block reservations
|
||||
├── Corridor spines + access points
|
||||
├── Zone palette assignment
|
||||
└── Boundary descriptors (for edge bleed)
|
||||
↓
|
||||
Block Planning ──────────── per district
|
||||
├── ChunkLayout selection (merge strategy)
|
||||
├── Era assignment + modifications
|
||||
├── Edge contract computation
|
||||
└── Quarter layout (form × function)
|
||||
↓
|
||||
NPC Population ──────────── per district
|
||||
├── Role slot filling (10-axis generation)
|
||||
├── Triangle configuration
|
||||
├── Entanglement marking
|
||||
└── Spawn location preferences
|
||||
↓
|
||||
Transition Strip Gen ────── per shared district edge
|
||||
├── Palette blending
|
||||
├── Access point alignment
|
||||
└── Transition block skeletons
|
||||
↓
|
||||
OUTPUT: PreparedDistrict + TransitionStrips
|
||||
|
||||
|
||||
PHASE 2: LOCAL AREA GEN (on-demand, per chunk)
|
||||
═══════════════════════════════════════════════
|
||||
|
||||
PreparedDistrict
|
||||
↓
|
||||
Chunk enters loading radius
|
||||
↓
|
||||
Chunk Fill ──────────────── derives: chunk_seed
|
||||
├── Read BlockPlan + edge contracts
|
||||
├── Select/stamp template from social site tag
|
||||
├── Place terrain (non-urban) or architecture (urban)
|
||||
├── Apply zone palette + era materials
|
||||
├── Place furniture from form × function
|
||||
├── Place NPC spawn points
|
||||
├── Validate edge contracts against loaded neighbors
|
||||
└── Apply LOS anchor placement rules
|
||||
↓
|
||||
OUTPUT: ChunkData (cached, saved)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. Cost Summary
|
||||
|
||||
| Component | Effort | Target |
|
||||
|-----------|--------|--------|
|
||||
| SeedChain + derivation | 0.5 dev-days | v0.2 |
|
||||
| SocietyProfile serde schema | 1 dev-day | v0.2 |
|
||||
| DistrictSkeleton struct (updated, with boundaries) | 2 dev-days | v0.1 stub, v0.2 impl |
|
||||
| BlockPlan + ChunkFillSpec structs | 1 dev-day | v0.1 stub |
|
||||
| TransitionStrip generation | 2 dev-days | v0.3 |
|
||||
| TerrainType + non-urban chunk fill | 3 dev-days | v0.4+ |
|
||||
| ComplexityTier + minimal/empty district gen | 1 dev-day | v0.3 |
|
||||
| Spatial prerequisite validator | 0.5 dev-days | v0.3 |
|
||||
| Transit District as DistrictSkeleton (validation) | 3 dev-days | v0.1 |
|
||||
| Phase 1 background thread + scheduling | 2 dev-days | v0.3 |
|
||||
| Phase 2 chunk fill (template stamping) | 5 dev-days | v0.2 |
|
||||
| **Total** | **~21 dev-days** | **spread v0.1-0.4** |
|
||||
|
||||
Feasible. Challenging but doable. The critical path item is the Phase 2 chunk fill (~5 dev-days in v0.2) because it's the first thing that produces visible tiles. Everything else builds toward it or extends from it.
|
||||
|
||||
---
|
||||
|
||||
*Tyre — Round 2 complete. The two-phase split is clean. Edge bleed is solved at the data structure level. Non-urban terrain fits the same hierarchy. Seeds are trivially solved. Standing by for Round 3 convergence.*
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,176 @@
|
||||
# Round 5: Tyre — Final Review of Workshop Outcomes
|
||||
|
||||
**Workshop:** Generator Architecture (#562)
|
||||
**Agent:** Tyre (Technical Architect)
|
||||
**Date:** 2026-02-27
|
||||
|
||||
**Round 5 scope:** Review `workshop-outcomes.md` for accuracy against my Round 4 canonical output. Corrections only.
|
||||
|
||||
---
|
||||
|
||||
## Overall Assessment
|
||||
|
||||
The outcomes document is **accurate and well-compiled**. Qatux has correctly captured the three-layer model, the spatial hierarchy, the Phase 1 pipeline, and all 14 D-READY items. The lead decisions table is correct. The key tensions and resolutions table is correct. The open questions are correctly identified.
|
||||
|
||||
*cracks knuckles* — That said, I have a few corrections. None are architectural — they're all accuracy/consistency issues in how the outcomes doc represents decisions that were made.
|
||||
|
||||
---
|
||||
|
||||
## Corrections
|
||||
|
||||
### CORRECTION 1: WorldTier enum values don't match Round 4 canonical
|
||||
|
||||
**Location:** Workshop-outcomes §"WorldTier and ComplexityTier" (lines 127–143)
|
||||
|
||||
**Issue:** The outcomes document uses:
|
||||
```
|
||||
Core, Regional, Local, Transit, Dormant
|
||||
```
|
||||
|
||||
My Round 4 canonical enum (§2.1, the D-record version) uses:
|
||||
```
|
||||
Epicenter, Regional, Passage, Backwater, Waypoint
|
||||
```
|
||||
|
||||
The lead decision L-3 says "WorldTier wins over SignificanceTier as the field name." Correct — but the **enum variant names** should match the Round 4 canonical. The outcomes doc appears to have substituted simplified names that were never agreed upon.
|
||||
|
||||
**Fix:** Replace the WorldTier enum values with the Round 4 canonical:
|
||||
|
||||
| Current (incorrect) | Correct (Round 4 canonical) |
|
||||
|---------------------|---------------------------|
|
||||
| Core | Epicenter |
|
||||
| Regional | Regional |
|
||||
| Local | Backwater |
|
||||
| Transit | Passage |
|
||||
| Dormant | Waypoint |
|
||||
|
||||
Also update the constraint ceiling text:
|
||||
- Current: "Core/Regional → Full max; Local → Moderate max; Transit → Minimal; Dormant → Empty"
|
||||
- Correct: "Epicenter/Regional → Full max; Backwater → Full (key insight: dense isolated community); Passage → Moderate max; Waypoint → Minimal"
|
||||
|
||||
This matters because the Backwater → Full case is one of the most important combinations in the game (§2.3 of my Round 4 — the fishing village scenario). The current text says "Local → Moderate max" which would **prohibit** this case. That's a material error.
|
||||
|
||||
### CORRECTION 2: Missing fields on DistrictSkeleton summary
|
||||
|
||||
**Location:** Workshop-outcomes §"The Three-Layer Model" (lines 43–79)
|
||||
|
||||
**Issue:** The canonical DistrictSkeleton in my Round 4 (§5.1) includes fields that are absent from the outcomes summary:
|
||||
|
||||
- `district_id: DistrictId` — identity field, omitted
|
||||
- `seed: u64` — critical for deterministic generation, omitted
|
||||
- `district_type: DistrictType` — classification, omitted
|
||||
- `context: DistrictContext` — world context, omitted
|
||||
- `access_points: Vec<AccessPoint>` — district-level entries/exits, omitted
|
||||
|
||||
The summary does include `breach_only_zones`, `vertical_structure`, and `derived_analysis` which are **not** on my Round 4 canonical struct. These appear to have been pulled from other participants' proposals rather than the final canonical struct.
|
||||
|
||||
**Fix:** The DistrictSkeleton field list in the three-layer model should match the canonical struct from my Round 4 §5.1. Either reproduce it exactly or add a note that the summary is simplified and the full struct is in the D-record.
|
||||
|
||||
I'd recommend: keep the summary form but correct the field list to match the canonical. Add the missing identity/seed/context fields. Remove `breach_only_zones`, `vertical_structure`, and `derived_analysis` unless another participant's round 4 added these and I missed them — in which case, note the source.
|
||||
|
||||
### CORRECTION 3: Spatial hierarchy table — missing visual tile dimension
|
||||
|
||||
**Location:** Workshop-outcomes §"Spatial Hierarchy (D-094)" (lines 83–87)
|
||||
|
||||
**Issue:** Minor. The table lists "Visual tiles" as 32×32 for chunks, 64×64 for blocks, 256×256 for districts. These are correct. But my Round 4 also specifies that a Block is "2×2 chunks" in the DistrictSkeleton comments (§5.1, line: `/// The 4×4 block grid (each block = 128×128 sim tiles = 2×2 chunks)`). The outcomes table says Block = 4 chunks in the "Purpose" column. These are consistent (2×2 = 4 chunks total). No error — just confirming.
|
||||
|
||||
**No fix needed.** The table is correct.
|
||||
|
||||
### CORRECTION 4: MobileChunk — missing `Idle` movement state
|
||||
|
||||
**Location:** Workshop-outcomes §D-READY-13 (lines 334–346)
|
||||
|
||||
**Issue:** The outcomes document lists `MobileMovementState` as `(Docked / InTransit / InterSystem)`. My Round 4 canonical (§1.4) includes a fourth state: **`Idle`** — vessel parked at a location but not docked to infrastructure (anchored ship, grounded shuttle). This was a Round 4 addition (noted in my §6 cost summary: "MobileChunk Idle state added: +0.5 dev-days").
|
||||
|
||||
**Fix:** Add `Idle` to the MobileMovementState list:
|
||||
```
|
||||
MobileMovementState (Docked / InTransit / InterSystem / Idle)
|
||||
```
|
||||
|
||||
### CORRECTION 5: Implementation targets — MobileChunk effort
|
||||
|
||||
**Location:** Workshop-outcomes §"Implementation Targets" (lines 409–416)
|
||||
|
||||
**Issue:** The outcomes document says "MobileChunk (single-chunk vessels)" at v0.3, ~9.5 dev-days. This is consistent with my Round 4 estimate. However, my Round 4 milestone breakdown (§6) places mobile chunks at **v0.3** alongside organic layout, palette modifiers, edge bleed, etc. — the v0.3 total is ~23 dev-days. The outcomes table correctly shows ~9.5 for just the MobileChunk portion.
|
||||
|
||||
**No fix needed.** The figure is correct.
|
||||
|
||||
### CORRECTION 5b: MobileChunk `Docked` state missing required fields
|
||||
|
||||
**Location:** Workshop-outcomes §D-READY-13 (lines 340–341)
|
||||
|
||||
**Issue:** D-READY-13 explicitly states:
|
||||
> "The `scheduled_departure: Option<SimTick>` field in `Docked` state satisfies this; the generator must populate it. Vessels without departure schedules are an error state."
|
||||
|
||||
My Round 4 canonical `Docked` state (§1.4):
|
||||
```rust
|
||||
Docked {
|
||||
dock_position: WorldPosition,
|
||||
connected_chunk: Option<ChunkCoord>,
|
||||
}
|
||||
```
|
||||
|
||||
Neither `scheduled_departure` nor `docked_since` is present. The outcomes doc explicitly references these fields as satisfying a generator requirement — so the D-record struct must include them. The outcomes doc is correct; my Round 4 struct is incomplete here.
|
||||
|
||||
**Fix for D-record filing:**
|
||||
```rust
|
||||
Docked {
|
||||
dock_position: WorldPosition,
|
||||
connected_chunk: Option<ChunkCoord>,
|
||||
docked_since: SimTick,
|
||||
scheduled_departure: Option<SimTick>,
|
||||
},
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### CORRECTION 6: Guarantee audit — missing checks from Round 4
|
||||
|
||||
**Location:** Workshop-outcomes §D-READY-2 (lines 158–165) and §D-READY-8 (lines 249–257)
|
||||
|
||||
**Issue:** My Round 4 `GuaranteeAuditResult` struct (§5.2) has 11 named checks. D-READY-2 in the outcomes lists the tiers correctly. However, D-READY-8 says "A-1/A-2/A-3 are Tier 3 Conditional" and "A-4 is mandatory Full-complexity." In my Round 4 audit struct, A-4 (`non_institutional_route`) is NOT in the struct — it's listed in D-READY-8 as a requirement but I didn't add it as a named field on `GuaranteeAuditResult`.
|
||||
|
||||
**This is my omission from Round 4**, not an error in the outcomes doc. The outcomes correctly state A-4 is mandatory for Full-complexity. When filing the D-record, A-4 should be added to the `GuaranteeAuditResult` struct as a Tier 2 check (it's mandatory for Full, not conditional). Similarly, `egress_multiplicity` (A-2) is missing from my struct.
|
||||
|
||||
**Recommended fix for D-record filing (not outcomes doc):** Add `non_institutional_route: Option<AuditCheck>` and `egress_multiplicity: Option<AuditCheck>` to the Tier 2 section of `GuaranteeAuditResult`. Also add `horizon_view_corridor: Option<AuditCheck>` and `breach_only_zone: Option<AuditCheck>` and `rooftop_discovery: Option<AuditCheck>` from D-READY-2 Tier 2 list. The outcomes doc correctly lists these; my Round 4 struct was incomplete.
|
||||
|
||||
---
|
||||
|
||||
## Items Verified Correct (No Changes Needed)
|
||||
|
||||
- **L-1 through L-7:** All lead decisions accurately captured.
|
||||
- **Phase 1 pipeline stages:** Correct (5 stages).
|
||||
- **LayoutMode struct:** `BlockPlacement` with offset, rotation_steps, street_width_factor — matches Round 4.
|
||||
- **45-degree rotation hard cap:** Correctly stated as non-negotiable.
|
||||
- **D-READY-3 (TrianglePurpose):** Enum values match. `Vec<TrianglePurpose>` correctly noted.
|
||||
- **D-READY-4 (WallBackside/TileBehindState):** Dual classification correctly captured. Era-tagged infrastructure contents correct.
|
||||
- **D-READY-5 (DamageOverlay):** Structs match. `scatter_seed` correctly scoped. `RegenerationStrategy` correctly defined. XOR prohibition correctly stated.
|
||||
- **D-READY-6 (ZonePalette):** 8 base terrain types correct. Modifier axes (A/B/C) correctly described.
|
||||
- **D-READY-9 (Heritage Grammar):** Blend rules correct. Authoring domain separation (Miri vs Araminta) correct.
|
||||
- **D-READY-12 (Trauma Events):** `TraumaEventSubtype` enum matches. Decay rate per heritage root correct.
|
||||
- **D-READY-14 (DamageOverlay/RegenerationStrategy):** Correctly filed as separate D-record from D-READY-5. Prohibition framing accurate.
|
||||
- **NPC model (10 axes):** All axes correctly listed. Axis 11 correctly flagged as Q-record.
|
||||
- **Minimum NPC count (3):** Correctly stated.
|
||||
- **Key tensions table:** All 6 tensions and resolutions accurate.
|
||||
- **Open questions:** All 6 Q-records correctly identified with appropriate owners.
|
||||
- **Ozzie's "promises" synthesis:** Accurately captured.
|
||||
|
||||
---
|
||||
|
||||
## Summary of Required Corrections
|
||||
|
||||
| # | Severity | What | Where |
|
||||
|---|----------|------|-------|
|
||||
| 1 | **HIGH** | WorldTier enum values wrong (Core/Local/Transit/Dormant → Epicenter/Backwater/Passage/Waypoint). Constraint ceiling text prohibits the Backwater+Full case. | §WorldTier, lines 127–143 |
|
||||
| 2 | MEDIUM | DistrictSkeleton field list has missing and extra fields vs. Round 4 canonical | §Three-Layer Model, lines 43–62 |
|
||||
| 3 | — | No correction needed | §Spatial Hierarchy |
|
||||
| 4 | LOW | MobileMovementState missing `Idle` variant | §D-READY-13, line 336 |
|
||||
| 5 | — | No correction needed | §Implementation Targets |
|
||||
| 5b | MEDIUM | `Docked` state missing `scheduled_departure` + `docked_since` (D-READY-13 explicitly requires them) | §D-READY-13, line 340 |
|
||||
| 6 | NOTE | My Round 4 GuaranteeAuditResult struct was incomplete — outcomes doc is correct, but D-record filing should add missing Tier 2/3 fields | §D-READY-2/8 |
|
||||
|
||||
**Correction 1 is the only one I'd flag as potentially misleading** — the wrong enum values combined with the wrong constraint ceiling text could cause implementation to prohibit Backwater+Full, which is a key game experience. The rest are bookkeeping.
|
||||
|
||||
---
|
||||
|
||||
*Tyre — Round 5 review complete. One high-severity correction (WorldTier enum names and constraint ceiling), one medium (DistrictSkeleton field list), one low (missing Idle state). The outcomes document is solid work overall — the architecture is accurately represented.*
|
||||
@@ -0,0 +1,142 @@
|
||||
# Generator Architecture Workshop Brief
|
||||
|
||||
**Goal:** Establish the top-down procedural generator pipeline architecture — from geography down to individual chunk fill — that will power the 300-world model. Produce a D-record defining generator primitives, the spatial hierarchy, and the sub-chunk building system.
|
||||
**Ticket:** #562 (story, parent: #50 Chunk-based Map System)
|
||||
**Priority:** MEDIUM — prerequisite to #144 (Chunk generation system), Sprint 21+ target
|
||||
**Participants:** Gestalt (systems design), Tyre (architecture), Miri (worldbuilding), Araminta (spatial/visual), Nigel (replayability/procedural gen), Qatux (docs), SI (tickets)
|
||||
**Source:** Station District Layout Workshop (#153, Round 3), lead directive
|
||||
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
The v0.1 Transit District is hand-authored. The long-game goal is 300 procedurally generated worlds. The question this workshop must answer is: **what is the generator's architecture — top to bottom?**
|
||||
|
||||
The lead has identified a top-down pipeline model inspired by Cities Skylines:
|
||||
|
||||
```
|
||||
Geography
|
||||
→ Infrastructure (transport nodes, utilities)
|
||||
→ Amenities & Services
|
||||
→ Population (extrapolated from capacity)
|
||||
→ Zoning
|
||||
→ Block generation
|
||||
→ Chunk fill (individual buildings and spaces)
|
||||
```
|
||||
|
||||
This workshop also addresses a related structural question: how does the **sub-chunk quarter system** provide building variety within template-driven generation? A chunk divides into 4 quarters that can merge, split, leave gaps, or host shacks/gardens — producing L-shapes, mixed-use footprints, and irregular structures without breaking the generator's regularity.
|
||||
|
||||
Multi-block structures (train stations, government buildings, stadiums, parks, farmland) span multiple chunks and must be accounted for in the block and zoning passes before individual chunks are filled.
|
||||
|
||||
**Starting point:** Q-036 asks whether the district skeleton (social sites, NPC slots, triangle templates, economic function, access topology) is the atomic generator output unit. D-025 defines social sites as atomic template units for hand-authoring. This workshop must reconcile the two.
|
||||
|
||||
**What is already decided:**
|
||||
- D-025: Social site / functional cluster as atomic template unit (hand-authoring)
|
||||
- D-036: Sova Transit District as v0.1 setting (hand-authored)
|
||||
- D-012: Chunk-based map system (bounded for v0.1, borderless-capable)
|
||||
- #153 D-record (Station District Layout Workshop): district/block/chunk spatial hierarchy, spatial dimensions, access topology gradient — reference `decisions/content.md` for the confirmed record
|
||||
|
||||
**What is still open:**
|
||||
- Q-036: District skeleton as generator output (assigned Tyre, Gestalt)
|
||||
- Q-037: Generator development pipeline / phased production model (assigned SI, Tyre)
|
||||
- Q-039: Procedural gate topology generation
|
||||
|
||||
---
|
||||
|
||||
## Key Questions to Resolve
|
||||
|
||||
### 1. Pipeline Architecture
|
||||
|
||||
1. Is the Cities Skylines top-down model (geography → zoning → chunk fill) the right architecture for The Settled Reach, or does the game's station-centric setting require a different ordering?
|
||||
2. What is the correct sequence — does population follow zoning, or precede it?
|
||||
3. How does the pipeline handle stations (Sova) vs. planet-side cities vs. orbital installations? Same pipeline, different geography inputs?
|
||||
4. Where do political/economic conditions enter the pipeline? (Faction control, prosperity tier, trade routes)
|
||||
5. At what pipeline stage are the triangle templates (D-025) instantiated?
|
||||
|
||||
### 2. Spatial Hierarchy and Primitives
|
||||
|
||||
6. What are the canonical spatial units in the hierarchy? (Region → District → Block → Chunk → Sub-chunk quarter? Or different names/levels?)
|
||||
7. What is the confirmed chunk size in sim tiles? (Reference #153 D-record — the district workshop decided this)
|
||||
8. What is the block size — how many chunks per block?
|
||||
9. What is the district size — how many blocks per district?
|
||||
10. How does the sub-chunk quarter system work mechanically? (Quarter = ¼ chunk, can merge 2×2, 1×2, L-shape. What are the merge rules? Who decides fill vs. empty?)
|
||||
|
||||
### 3. Multi-Block Structures
|
||||
|
||||
11. How are multi-block structures (train stations, stadiums, government complexes, parks) represented in the generator? (Reserved footprint at the zoning pass? Pre-baked templates that claim N×M blocks?)
|
||||
12. What is the maximum multi-block footprint — is there a cap?
|
||||
13. How do multi-block structures interact with neighbouring chunk fills at their edges?
|
||||
14. Can a multi-block structure span district boundaries?
|
||||
|
||||
### 4. District Skeleton as Generator Output (Q-036)
|
||||
|
||||
15. Is the district skeleton (social site arrangement, NPC slot allocation, triangle template selection, access topology) the correct atomic output of the district-generation stage?
|
||||
16. How does the district skeleton output interact with D-025's social site templates? (Generator selects and arranges templates, not individual tiles?)
|
||||
17. What inputs does the district skeleton generator consume? (Zoning type, population density, faction control, economic function, transport adjacency)
|
||||
18. What does the district skeleton output look like as a data structure? (List of social site slots with positions, access tier, NPC capacity, template tag)
|
||||
|
||||
### 5. Replayability and Variation
|
||||
|
||||
19. What variation levers exist at each pipeline stage? (Seed, faction weights, economic tier, historical events?)
|
||||
20. How does the sub-chunk quarter system produce perceived variety across multiple playthroughs?
|
||||
21. How are "flavour" structures (shacks, gardens, market stalls) assigned to unclaimed quarter space?
|
||||
22. What prevents two generated districts from feeling identical even if they share the same zoning type?
|
||||
|
||||
### 6. v0.1 / Generator Boundary
|
||||
|
||||
23. Where does the v0.1 hand-authored content end and the generator begin? What stub interfaces must v0.1 leave behind?
|
||||
24. Which pipeline stages are in scope for implementation, and which are deferred (per Q-037's phased production model)?
|
||||
25. Does the v0.1 Transit District need to be expressible as generator output (for validation), or is it purely an authored ground-truth?
|
||||
|
||||
---
|
||||
|
||||
## Input Documents
|
||||
|
||||
| Document | What to read | Why |
|
||||
|----------|-------------|-----|
|
||||
| `decisions/content.md` | D-025 (social site template), #153 D-record | Generator must compose from these primitives |
|
||||
| `decisions/scope.md` | D-012 (chunk system), D-036 (Sova setting) | Spatial constraints and v0.1 setting |
|
||||
| `decisions/questions.md` | Q-036 (district skeleton), Q-037 (generator pipeline), Q-039 (gate topology) | Open questions this workshop resolves |
|
||||
| `docs/design/sova-station-profile.md` | District types, 6-district layout | The worldbuilding context the generator must reproduce |
|
||||
| `docs/design/spatial-layout-terminal-v01.md` | Terminal layout | Example of a hand-authored chunk cluster |
|
||||
| `docs/design/spatial-layout-bar-v01.md` | Bar layout | Example of a hand-authored chunk cluster |
|
||||
| `decisions/architecture.md` | D-014 (tile-based movement), D-012 (chunk loading) | Technical constraints on spatial units |
|
||||
| `docs/workshops/content-architecture/content-architecture-workshop-brief.md` | Three-tier content pipeline | How templates and procedural generation already relate |
|
||||
|
||||
---
|
||||
|
||||
## Expected Outputs
|
||||
|
||||
1. **D-record: Generator Architecture** — confirmed in `decisions/architecture.md`:
|
||||
- Top-down pipeline stages (named and sequenced)
|
||||
- Spatial hierarchy (named levels, tile dimensions per level)
|
||||
- Sub-chunk quarter system rules (merge/split/fill logic)
|
||||
- Multi-block structure reservation protocol
|
||||
- District skeleton as generator output: data structure definition
|
||||
- v0.1 / generator boundary (what's hand-authored, what's stubbed)
|
||||
|
||||
2. **Resolution of Q-036:** District skeleton as atomic generator output — yes/no + formal definition if yes
|
||||
|
||||
3. **Resolution of Q-037 scope:** Which pipeline phases land in which version window (v0.1 stub, v0.2–0.5 template expansion, v0.6–0.10 generator development)
|
||||
|
||||
4. **Tickets:** Implementation tasks derived from the D-record (chunk data structure update, district skeleton schema, zoning pass stub, block generation stub)
|
||||
|
||||
---
|
||||
|
||||
## Workshop Format
|
||||
|
||||
Three rounds:
|
||||
|
||||
**Round 1 — Domain Inventory**
|
||||
Each participant reviews existing decisions and states what their domain requires from the generator architecture.
|
||||
- Gestalt: what gameplay loops does the generator need to support? What must it guarantee (e.g., always a surveillance chokepoint, always a quiet zone)?
|
||||
- Tyre: what are the hard technical constraints on chunk size, hierarchy depth, and data structure for the district skeleton?
|
||||
- Miri: how does the generator reproduce the cultural/economic variation of 300 worlds? What lore-level inputs drive the pipeline?
|
||||
- Araminta: what visual coherence constraints does chunk fill need to satisfy? How does the sub-chunk quarter system produce plausible streetscapes?
|
||||
- Nigel: what variation and replayability guarantees must the generator provide? What makes two generated districts feel different?
|
||||
|
||||
**Round 2 — Pipeline Proposals**
|
||||
Propose concrete pipeline architecture. Name the stages, define the spatial hierarchy levels with tile dimensions, describe the district skeleton data structure. Respond to each other's domain requirements from Round 1.
|
||||
|
||||
**Round 3 — Convergence**
|
||||
Resolve conflicts, agree on the pipeline sequence, lock spatial hierarchy dimensions, define the district skeleton output format, set the v0.1/generator boundary. Draft the D-record.
|
||||
@@ -0,0 +1,470 @@
|
||||
# Generator Architecture Workshop — Outcomes
|
||||
|
||||
**Workshop:** Generator Architecture (#562)
|
||||
**Rounds:** 1 through 4
|
||||
**Dates:** 2026-02-27
|
||||
**Participants:** Gestalt, Tyre, Miri, Araminta, Nigel, Ozzie
|
||||
**Compiled by:** Qatux
|
||||
|
||||
---
|
||||
|
||||
## Purpose
|
||||
|
||||
This document is the authoritative summary of the Generator Architecture workshop. It compiles all confirmed decisions, the canonical data structures, the D-record inventory, and the open questions remaining for sprint work.
|
||||
|
||||
The source documents are the four round notes files:
|
||||
- `docs/workshops/generator-architecture/round-1-notes.md`
|
||||
- `docs/workshops/generator-architecture/round-2-notes.md`
|
||||
- `docs/workshops/generator-architecture/round-3-notes.md`
|
||||
- `docs/workshops/generator-architecture/round-4-notes.md`
|
||||
|
||||
---
|
||||
|
||||
## Lead Decisions
|
||||
|
||||
These are decisions made or confirmed by the project lead (Jeroen) and are not subject to further team debate.
|
||||
|
||||
| # | Decision | Round confirmed |
|
||||
|---|----------|-----------------|
|
||||
| L-1 | The generator uses a **two-phase** architecture: Phase 1 (DistrictSkeleton, async background) and Phase 2 (ChunkData on-demand per chunk). | R2 |
|
||||
| L-2 | Both **Grid and Organic** layout modes exist. The lead mandated "some blocks grid, some organic chaos." | R3 |
|
||||
| L-3 | **WorldTier** wins over SignificanceTier as the field name on DistrictSkeleton. | R4 |
|
||||
| L-4 | **Entity-carried MobileChunk** is core architecture. Vessels are persistent world entities with a Docked state. | R4 |
|
||||
| L-5 | **DramaDensity** is runtime storyteller state. It does NOT appear on DistrictSkeleton. | R4 |
|
||||
| L-6 | **Heritage grammar overlay** is base game content, not DLC. | R4 |
|
||||
| L-7 | **XOR reseeding for in-playthrough events is prohibited.** `DamageOverlay` is the correct approach for all player-witnessed structural events. | R4 (unanimously confirmed) |
|
||||
|
||||
---
|
||||
|
||||
## Confirmed Architecture — Summary
|
||||
|
||||
### The Three-Layer Model
|
||||
|
||||
```
|
||||
GENERATOR STATE (immutable after Phase 1)
|
||||
├── Phase 1: DistrictSkeleton
|
||||
│ ├── district_id: DistrictId (identity)
|
||||
│ ├── seed: u64 (deterministic generation)
|
||||
│ ├── district_type: DistrictType (classification)
|
||||
│ ├── context: DistrictContext (world context)
|
||||
│ ├── world_tier: WorldTier (simulation fidelity budget)
|
||||
│ ├── complexity_tier: ComplexityTier (content budget)
|
||||
│ ├── layout_mode: DistrictLayoutMode (Grid | Organic)
|
||||
│ ├── setting: SettingType (terrain + environment type)
|
||||
│ ├── blocks: [[BlockSkeleton; 4]; 4] (4×4 block grid)
|
||||
│ ├── reservations: Vec<MultiBlockReservation>
|
||||
│ ├── corridors: Vec<CorridorSpine>
|
||||
│ ├── z_levels: u8
|
||||
│ ├── vertical_structure: VerticalStructure (source: multi-participant)
|
||||
│ ├── breach_only_zones: Vec<ZoneId> (source: multi-participant)
|
||||
│ ├── social_sites: Vec<SocialSitePlacement>
|
||||
│ ├── society_profile: SocietyProfileRef
|
||||
│ ├── zone_palette: Vec<ZoneDefinition>
|
||||
│ ├── boundaries: DistrictBoundaries
|
||||
│ ├── access_points: Vec<AccessPoint> (district entries/exits)
|
||||
│ ├── guarantee_audit: GuaranteeAuditResult
|
||||
│ └── derived_analysis: DerivedDistrictAnalysis (source: Miri/Gestalt; Phase 1 computed)
|
||||
└── Phase 2: PreparedDistrict (on-demand per chunk)
|
||||
├── SocialSitePlacement (triangles with Vec<TrianglePurpose>)
|
||||
├── NpcManifest (seeded from society_profile)
|
||||
├── ZonePalette assignments (base + heritage modifiers)
|
||||
└── ChunkMutations pending
|
||||
|
||||
SIMULATION STATE (runtime storyteller — NOT generator output)
|
||||
├── DistrictRuntimeState.drama_density: DramaDensity
|
||||
├── active_triangles: Vec<TriangleId>
|
||||
├── npc_pattern_weights: NpcPatternWeightSet
|
||||
└── assassination_difficulty on-demand computation
|
||||
|
||||
DELTA LAYER (post-generation)
|
||||
├── DamageOverlay (LocalOverlay for in-playthrough events)
|
||||
├── NpcRemoved / NpcStateChanged
|
||||
├── AccessTierChanged
|
||||
└── WorldStateDelta (composed from all active mutations)
|
||||
```
|
||||
|
||||
### Spatial Hierarchy (D-094)
|
||||
|
||||
| Unit | Sim tiles | Visual tiles | Real meters | Purpose |
|
||||
|------|-----------|--------------|-------------|---------|
|
||||
| Chunk | 64×64 | 32×32 | 32m | Streaming unit |
|
||||
| Block | 128×128 | 64×64 | 64m | Generator planning unit (4 chunks) |
|
||||
| District | 512×512 | 256×256 | 256m | Simulation unit (4×4 blocks) |
|
||||
|
||||
### Phase 1 Generator Pipeline
|
||||
|
||||
```
|
||||
Pre-Pipeline: system generation, WorldTier assignment, galaxy topology
|
||||
↓
|
||||
Phase 1: DistrictSkeleton
|
||||
Stage 1: Classification (WorldTier, ComplexityTier, SettingType)
|
||||
Stage 2: Block grid (DistrictLayoutMode, BlockSkeleton ×16)
|
||||
Stage 3: Reservation (skyscrapers, terminals, MultiBlockReservation)
|
||||
Stage 4: Social site + NPC (triangles, society profile, DerivedDistrictAnalysis)
|
||||
Stage 5: Guarantee audit (3-tier conditional check)
|
||||
↓
|
||||
Phase 2: ChunkData (on-demand per player approach)
|
||||
Heritage grammar applied at chunk fill time
|
||||
↓
|
||||
World State Layer: DamageOverlay + DeltaLayer overlay at render time
|
||||
```
|
||||
|
||||
### Layout Mode
|
||||
|
||||
```rust
|
||||
enum DistrictLayoutMode {
|
||||
Grid,
|
||||
Organic {
|
||||
placements: [[BlockPlacement; 4]; 4],
|
||||
},
|
||||
}
|
||||
struct BlockPlacement {
|
||||
offset: (i16, i16), // ±16 sim tiles per axis
|
||||
rotation_steps: u8, // 0–3 (15° increments; hard cap at 45°)
|
||||
street_width_factor: f32, // 0.75–2.0 relative to standard
|
||||
}
|
||||
```
|
||||
|
||||
Hard technical constraint: maximum rotation is ±45°. This is non-negotiable — beyond 45°, tile-based pathfinding produces unacceptable movement artifacts. Organic districts produce the visual impression of curved streets through angular jogs and irregular setbacks, not smooth curves.
|
||||
|
||||
### WorldTier and ComplexityTier
|
||||
|
||||
```rust
|
||||
enum WorldTier {
|
||||
Epicenter, // Hub system. Full simulation, high faction pressure.
|
||||
Regional, // Regional. 1–4 districts, partial full-budget.
|
||||
Backwater, // Small community. 1 district. Network-insignificant, NOT budget-capped.
|
||||
Passage, // Transit stop. Pass-through.
|
||||
Waypoint, // Not simulated until player approaches.
|
||||
}
|
||||
enum ComplexityTier {
|
||||
Full, // All spatial guarantees. Rich NPC population.
|
||||
Moderate, // Tier 1 + partial Tier 2 guarantees. Moderate NPCs.
|
||||
Minimal, // Tier 1 only. Sparse NPCs.
|
||||
Empty, // No social sites, no NPCs. Pure terrain.
|
||||
}
|
||||
```
|
||||
|
||||
WorldTier → ComplexityTier ceiling:
|
||||
|
||||
| WorldTier | ComplexityTier ceiling |
|
||||
|-----------|----------------------|
|
||||
| Epicenter | Full |
|
||||
| Regional | Full |
|
||||
| Backwater | Full (key insight: dense isolated community — network insignificance ≠ simulation budget cap) |
|
||||
| Passage | Moderate |
|
||||
| Waypoint | Minimal |
|
||||
|
||||
ComplexityTier → DramaDensity ceiling: Full → any intensity; Moderate → Active max; Minimal → Quiescent max; Empty → Zero only (no storyteller activation possible). A `ComplexityTier::Empty` district has no social fabric; the storyteller cannot activate drama there.
|
||||
|
||||
---
|
||||
|
||||
## The 14 D-Ready Items
|
||||
|
||||
These 14 items are confirmed D-records ready to be filed in `decisions/`. Each has been reviewed and signed off by all workshop participants.
|
||||
|
||||
### D-READY-1: DistrictLayoutMode — Grid and Organic Support
|
||||
|
||||
Both layout modes coexist. Grid = power imposed (Commission-planned). Organic = power negotiated (pioneer settlements, organic growth). Organic mode uses `BlockPlacement` offsets and rotations to produce non-rectilinear street space as negative space between shifted/rotated blocks. 45° rotation is a hard technical ceiling.
|
||||
|
||||
The proportion of Grid vs. Organic districts across a world must vary per seed to prevent predictable meta-level patterns.
|
||||
|
||||
### D-READY-2: Guarantee Tier System — Universal / Full-Only / Conditional
|
||||
|
||||
**Tier 1 — Universal (all inhabited):** Social Hub, Informal Zone, Encounter Corridor.
|
||||
**Tier 2 — Full-complexity:** Traffic Chokepoint, Institutional Space, Insider Space, Economic Node, Horizon View Corridor (coastal), BreachOnly Zone (≥1), Rooftop Discovery Zone (tall structures).
|
||||
**Tier 3 — Conditional:** A-1 Elevated Vantage, A-2 Egress Multiplicity, A-3 Temporal Opacity Window, A-4 Non-Institutional Route, Economic Asymmetry Signal, Power Gradient Visibility.
|
||||
|
||||
Audit runs all applicable checks. A Minimal farmstead gets ~3 checks. A Full-complexity coastal urban hub gets up to 13.
|
||||
|
||||
Archetype placement must vary in **angular position** (not just distance from center) across seeds. The guarantee audit should fail if archetype positions cluster predictably across a test batch of N seeds.
|
||||
|
||||
### D-READY-3: TrianglePurpose Enum
|
||||
|
||||
```rust
|
||||
enum TrianglePurpose {
|
||||
Investigation, Economic, Social, Political,
|
||||
Tactical, // target + protector + informant/witness
|
||||
Mundane,
|
||||
}
|
||||
```
|
||||
|
||||
Triangles carry `Vec<TrianglePurpose>`. Purpose tags are multi-playstyle accessibility features: they ensure the right drama is surfaced to the player whose lens is active. `Tactical` encodes the assassination contract in spatial form.
|
||||
|
||||
### D-READY-4: WallBackside / TileBehindState — Dual Classification
|
||||
|
||||
Both enums are canonical. They serve complementary roles:
|
||||
- `WallBackside` (Tyre): structural — what is physically behind this wall tile (AdjacentSpace / StructuralFill / ServiceVoid / ChunkBoundary / Exterior)
|
||||
- `TileBehindState` (Gestalt): gameplay — what kind of space this represents (StructuralFill / HiddenRoom / Interstitial)
|
||||
|
||||
Mapping: `WallBackside::ServiceVoid` → `TileBehindState::Interstitial`. `WallBackside::AdjacentSpace` → `TileBehindState::HiddenRoom` or `StructuralFill` depending on access tier.
|
||||
|
||||
Era-tagged infrastructure cavity contents with standardized color codes:
|
||||
- Era 1: power conduit only (`#c8b840`)
|
||||
- Era 2: power + water/coolant (`#4888c8`) + comm lines (`#b8b8b8`)
|
||||
- Era 3: full bundle (all types, denser)
|
||||
|
||||
Backside assignments within a template must have seed-driven variation — not fixed-template values.
|
||||
|
||||
### D-READY-5: Dynamic Modification via Overlay (Not Re-Generation)
|
||||
|
||||
Generator output is immutable. All post-generation modifications are applied via overlay.
|
||||
|
||||
**`DamageOverlay`:**
|
||||
```rust
|
||||
struct DamageOverlay {
|
||||
overlay_type: DamageOverlayType,
|
||||
epicenter: ChunkLocalPos,
|
||||
radius: f32,
|
||||
intensity: f32,
|
||||
scatter_seed: u64, // variation within damage zone only
|
||||
}
|
||||
enum DamageOverlayType { GasExplosion, Fire, Structural { collapse_direction }, Flooding }
|
||||
```
|
||||
|
||||
**`RegenerationStrategy`:**
|
||||
```rust
|
||||
enum RegenerationStrategy {
|
||||
LocalOverlay(DamageParameters), // in-playthrough — MANDATORY
|
||||
SoftReseed { seed_modifier: u64 }, // scenario-boundary only
|
||||
FullReseed, // era-level discontinuity only
|
||||
}
|
||||
```
|
||||
|
||||
Hard constraint: in-playthrough events are ALWAYS `LocalOverlay`. XOR reseeding for in-playthrough events is explicitly prohibited.
|
||||
|
||||
Trauma event → visual stage mapping:
|
||||
- PhysicalDestruction/ViolenceEvent → Stage 2 (Fresh Aftermath), decays to Stage 3
|
||||
- EconomicDisruption/PoliticalShock/MigrationShock → quarter fill modifier (not destruction stages)
|
||||
|
||||
Full destruction stage sequence:
|
||||
|
||||
| Stage | Name | Visual state |
|
||||
|-------|------|-------------|
|
||||
| 1 | Active | Event in progress; DamageOverlay rendering live |
|
||||
| 2 | Fresh Aftermath | Structure breached; scorch, rubble, debris tiles visible |
|
||||
| 3 | Stabilized | Debris cleared; structural state permanent |
|
||||
| 4 | Reconstruction | Scaffolding tiles, incomplete floor sections |
|
||||
| 5 | Healed Scar | Functional again; residual visual tells remain |
|
||||
|
||||
Destruction palette constraint: corruption-only. No new colors are introduced by destruction. Existing zone palette tiles are darkened, desaturated, or replaced with structural-damage variants from the same palette family. Single exception: `#c8d8f0` (open-sky tile) appears at 100% intensity when a roofed structure has its roof removed — the only color destruction may introduce. Implementers must not create a separate destruction color set.
|
||||
|
||||
Replayability: the modification history diverges per playthrough based on event decisions. Same-seed worlds share the same generator baseline; different event histories produce different delta layers. This is the replayability engine.
|
||||
|
||||
### D-READY-6: ZonePalette Modifier System
|
||||
|
||||
```rust
|
||||
struct ZonePalette {
|
||||
base: BasePalette,
|
||||
modifiers: Vec<PaletteModifier>,
|
||||
}
|
||||
```
|
||||
|
||||
8 base terrain types (T1 temperate farmland [warm organic, natural lighting] / T2 industrial farmland [cool grey-green, artificial lighting] / T3 wilderness / T4 grassland / T5 coastal water [deep near-black blue, animated specular; referenced by D-READY-7 horizon corridor guarantee] / T6 beach/coastal margin [warm dark tan] / T7 mountain/high terrain [dark blue-grey stone, snow at elevation] / T8 desert/arid). T1 and T2 are the two farmland types, explicitly distinct. If wetland terrain is required, it must be specified as a new T9 type — it is not a replacement for any of the 8 canonical types.
|
||||
|
||||
Modifier axes: A (heritage root → material character), B (economic tier → condition/density), C (era → material generation), plus faction overlay, climate, condition, season.
|
||||
|
||||
Palette modifiers should influence NPC appearance as well as environment appearance. People dress like they're from here.
|
||||
|
||||
### D-READY-7: Horizon View Corridor as Coastal Guarantee
|
||||
|
||||
A **negative-space** reservation: ≥8 visual tiles unobstructed view corridor from nearest public street to water's edge. No building, tree, or z=4 element may occupy this corridor. A low z=2 element (railing, bench, bollard) marks the waterfront point as a designed viewing location.
|
||||
|
||||
Tier 2 Conditional guarantee for coastal districts. Position within the district must vary per seed — the Wow Moment of seeing the horizon must be discovered, not expected.
|
||||
|
||||
### D-READY-8: Assassin Lens Spatial Guarantees (A-1 through A-4)
|
||||
|
||||
These are **derived properties of existing spatial configuration**, not assassin-tagged features. They add no generation cost; the audit validates existing output.
|
||||
|
||||
- **A-1 Elevated Vantage** (Tier 3, Full-complexity): ≥1 position with clear LOS cone to Traffic Chokepoint. Generator ensures overhead-clear zone in LOS corridor during block planning.
|
||||
- **A-2 Egress Multiplicity** (Tier 3, Full-complexity): ≥2 exit routes to adjacent districts.
|
||||
- **A-3 Temporal Opacity Window** (Tier 3, Full-complexity): ≥1 time window (day-phase) where Social Hub has reduced ambient NPC coverage.
|
||||
- **A-4 Non-Institutional Access Route** (mandatory Full-complexity): ≥1 route to any Insider zone that does not pass through high-security institutional spaces.
|
||||
|
||||
A-1/A-2/A-3 are Tier 3 Conditional (trigger on `complexity_tier == Full`). A-4 is mandatory Full-complexity for all playstyles.
|
||||
|
||||
### D-READY-9: Heritage Grammar Overlay for Non-Urban Palettes
|
||||
|
||||
Data-driven `HeritageGrammarOverlay` structs (10 per heritage root). Loaded once at generator startup. Applied at Phase 2 chunk fill time by weighted blending.
|
||||
|
||||
Blend rules:
|
||||
- Continuous fields (decorative_density, repair_visibility, etc.): weighted average
|
||||
- Categorical fields (boundary_character, open_space_character): dominant heritage weight wins
|
||||
- Object tag lists: union of preferred/accent tags; intersection-exclusion of excluded tags
|
||||
|
||||
Phase 1 exception: `gathering_probability` evaluated at block planning for quarter pre-assignment.
|
||||
|
||||
Authoring domain separation:
|
||||
- **Miri:** organizational principles, boundary character, spacing, social grammar (HeritageGrammarOverlay Rust struct / authored data)
|
||||
- **Araminta:** visual expression — object sets, arrangement algorithms, floor surface variants, overhead flora density and character, wall/structure material character, boundary material type, lighting temperature (TOML modifier files, one per heritage root)
|
||||
|
||||
Shared requirement: `ObjectTag` vocabulary must be co-maintained.
|
||||
|
||||
### D-READY-10: Non-Urban Informal Zone Typology
|
||||
|
||||
Informal zones are defined as spaces outside the community's social field — not defined by institutional absence but by the type of social permission governing them.
|
||||
|
||||
Three types:
|
||||
- `social_permission`: normal zone palette; gathering infrastructure present; cover is about convention, not geography
|
||||
- `physical_distance`: sparse objects, unmaintained floor; isolation is the visual
|
||||
- `utilitarian_cover`: functional work objects; space reads as work space; unofficial use is invisible to casual observation
|
||||
|
||||
Visual grammar per type in `docs/workshops/generator-architecture/araminta-round4.md`.
|
||||
|
||||
Heritage root correlation: Frost/Stone → `physical_distance`; Tide/Vine/Dust → `social_permission`; Iron/Salt → `utilitarian_cover`. Location within terrain is seeded independently. (Dust = maximum communal observation, only privacy available is negotiated; Iron = labor function covers presence. Both confirmed Miri Round 5.)
|
||||
|
||||
### D-READY-11: Vertical Scale Architecture
|
||||
|
||||
Four height tiers (S1–S4):
|
||||
- S1: 1–2 z-levels (surface + roof/mezzanine)
|
||||
- S2: 3–10 z-levels
|
||||
- S3: 11–30 z-levels
|
||||
- S4: 30+ z-levels
|
||||
|
||||
Shadow length is the primary height signal in top-down view (2–40 visual tiles).
|
||||
|
||||
Lazy z-level loading: `ZLevelLoadState: Loaded | Skeleton | Ungenerated`. Only current + adjacent z-levels filled by Phase 2.
|
||||
|
||||
**Rooftop Bar Clause:** Every tall structure (z_band_count ≥ 3) must assign a `RooftopConfig: Restricted | PublicWithHiddenLayer`. The discovery layer is mandatory in both cases. Heritage root **weights the probability** between the two configs — it does not determine the outcome. A minority of buildings of any heritage root must be configurable as the non-dominant type. A Frost building with a rooftop bar must be possible; full determination kills the discovery moment. (Correction confirmed by Ozzie + Araminta, Round 5.)
|
||||
|
||||
Z-band floor boundaries must have seed-variation within cultural ordering constraints. A corporate building has executive floors in the upper zone, but which exact floor begins is seeded.
|
||||
|
||||
Vertical access routes are playthrough-history dependent: same building, different routes available based on player relationship and event history.
|
||||
|
||||
### D-READY-12: Trauma Events as EraModification Subtypes
|
||||
|
||||
```rust
|
||||
enum ModificationType {
|
||||
TraumaEvent {
|
||||
subtype: TraumaEventSubtype,
|
||||
cultural_aftermath: HeritageRootResponse,
|
||||
}
|
||||
}
|
||||
enum TraumaEventSubtype {
|
||||
PhysicalDestruction, EconomicDisruption, PoliticalShock,
|
||||
ViolenceEvent, MigrationShock,
|
||||
}
|
||||
```
|
||||
|
||||
Trauma events that physically alter structures apply damage via `LocalOverlay`. The original_seed is preserved. Cultural aftermath decays toward baseline at heritage-root-dependent rates.
|
||||
|
||||
Physical destruction and cultural aftermath are separate tracks:
|
||||
- Structural damage: `StructuralChange` in ChunkMutations
|
||||
- Cultural response: NPC weight distribution shift in `DistrictRuntimeState.npc_pattern_weights`
|
||||
|
||||
Decay rate is seeded per-community with variation around heritage-root baseline (prevents perfect predictability from heritage root alone).
|
||||
|
||||
`trauma_visual_decay_rate: slow | medium | fast` per heritage root. Default: medium.
|
||||
|
||||
Design principle: **Trauma intensifies culture, it does not transform it.** A stressed community becomes a more concentrated version of itself — Frost communities close harder, Tide communities grief more publicly, Iron communities organize more collectively. Decay is toward the community's pre-trauma baseline, not toward a new equilibrium. Players who have learned a heritage root's trust model can predict community behavior in the aftermath.
|
||||
|
||||
### D-READY-13: MobileChunk Specification
|
||||
|
||||
Entity-carried interior space attached to a mobile world entity. Not a district. Uses the same chunk fill primitives in a simpler flat structure (no Phase 1/Phase 2 split; no block grid; no zone negotiation).
|
||||
|
||||
Key structs: `MobileChunk`, `MobileInterior`, `VesselClass`, `MobileMovementState` (Docked / InTransit / InterSystem / Idle), `TransitSocialModifier`, `MobileNpcSlot`, `NpcPersistence` (Crew / Passenger). Note: `Idle` = vessel parked at a location but not docked to infrastructure (anchored ship, grounded shuttle).
|
||||
|
||||
Vessels are **persistent world entities**. In `Docked` state: present at dock_position, visible from dock as sprite overlay, boarding via gangway tile → MobileAccessPoint activation. Interior cache keyed by entity_id persists across voyages for crew state.
|
||||
|
||||
**Departure schedules** are required as a generator output. The `Docked` struct must include `docked_since: SimTick` and `scheduled_departure: Option<SimTick>` — these fields were absent from Tyre's Round 4 canonical struct and must be added at implementation time. The generator must populate `scheduled_departure`. Vessels without departure schedules are an error state.
|
||||
|
||||
Replayability requirements R-V-1 through R-V-6 (see round-4-notes.md §5, D-READY-13 section).
|
||||
|
||||
Memory: ~0.5–4 KB metadata + up to 64 KB ChunkData per vessel. At 50 active entities: ~3 MB, paged by streaming model.
|
||||
|
||||
**Cultural grammar:** `TransitSocialModifier` with `TransitVariant` (BoundedLinear / BoundedMobile / InterSystem). Heritage-root behavior tables by vehicle type. Miri's canonical spec at `docs/workshops/generator-architecture/miri-round4.md`.
|
||||
|
||||
**Vessel visual grammar:** see `docs/workshops/generator-architecture/araminta-round4.md` §2. Five rules govern visual distinction of MobileChunk interiors from static zone spaces: (1) exterior hull uses vessel-identity material, not zone palette; (2) window tiles reveal exterior context (docked vs. in transit); (3) compression modifier tightens proportions throughout; (4) section transitions use vessel-identity threshold elements; (5) class stratification expressed through proportion, not palette change.
|
||||
|
||||
### D-READY-14: DamageOverlay / RegenerationStrategy
|
||||
|
||||
See D-READY-5 for full specification. Filed separately as a D-record because it establishes the general modification strategy rather than only the overlay mechanics.
|
||||
|
||||
The key distinction: this D-record establishes the **prohibition** of XOR reseeding for in-playthrough events and the **mandate** for `LocalOverlay`. All participants confirmed this unanimously in Round 4.
|
||||
|
||||
---
|
||||
|
||||
## NPC Model — The Ysabel Vorn Litmus Test
|
||||
|
||||
The 10-axis NPC model was validated against a concrete NPC exercise (Miri, Round 4). Ysabel Vorn covers **4.5 of 5 playstyle hooks** on a Backwater/Moderate farming settlement.
|
||||
|
||||
**The 10 axes:**
|
||||
1. Behavioral Pattern (social archetype: ANCHOR, REMNANT, WITNESS, etc.)
|
||||
2. Surface Motivation (publicly visible goal)
|
||||
3. Actual Motivation (what they actually want)
|
||||
4. Vulnerability/Secret
|
||||
5. Information Access (tiered knowledge inventory)
|
||||
6. Trust Architecture (heritage-based trust model + specific trust network)
|
||||
7. Routine Pattern (daily/weekly/seasonal schedule)
|
||||
8. Economic Position (control levers + hidden assets)
|
||||
9. Relationship Network (triangle memberships — active and latent)
|
||||
10. Tolerance Threshold (per-trigger tolerance levels)
|
||||
|
||||
**The gap (Axis 11, proposed):** `network_footprint: Option<NetworkFootprintTag>` for NPCs who are locally insignificant in appearance but carry network-significant information or are relevant to external actors. Default `None` for procedural NPCs. Set explicitly for authored scenario NPCs.
|
||||
|
||||
This axis is not yet in the confirmed model — it is raised as a Q-record for sprint work.
|
||||
|
||||
**Minimum NPC count for intra-seed replayability:** 3 (one functional triangle). One NPC = maximum seed-to-seed variation, zero intra-seed emergence. Three NPCs = triangles, shifting alliances, cascade effects. Even Minimal-complexity insignificant districts need 3 NPCs.
|
||||
|
||||
---
|
||||
|
||||
## Key Tensions and Resolutions
|
||||
|
||||
| Tension | Round | Resolution |
|
||||
|---------|-------|-----------|
|
||||
| Grid-only vs. organic streets | R1–R3 | Both. Grid = power imposed; Organic = power negotiated. Both modes coexist in the same world. |
|
||||
| SignificanceTier vs. WorldTier naming | R3–R4 | Lead: WorldTier. Canonical values: Epicenter/Regional/Backwater/Passage/Waypoint. |
|
||||
| MobileChunk (entity-carried) vs. instanced district (Nigel) | R3–R4 | Lead: entity-carried MobileChunk. Vessels are persistent world entities. |
|
||||
| DramaDensity on struct vs. runtime | R3–R4 | Lead: runtime only. DramaDensity lives in DistrictRuntimeState, not DistrictSkeleton. |
|
||||
| XOR reseeding vs. structured damage | R3–R4 | Unanimous: DamageOverlay. XOR prohibited for in-playthrough events. |
|
||||
| Assassination difficulty: computed-on-demand (Gestalt) vs. Phase 1 stored (Miri) | R4 | Minor tension. Recommended synthesis: stored cultural baseline (DerivedDistrictAnalysis on skeleton) + on-demand computation for player-facing assessment. See round-4-notes §2, OQ-R4-C. |
|
||||
|
||||
---
|
||||
|
||||
## Open Questions for Sprint Work
|
||||
|
||||
| Q-ID | Question | Priority | Owner |
|
||||
|------|----------|----------|-------|
|
||||
| Q-NNN-a | Axis 11 (Network Footprint) — authored field for network-significant NPCs in locally-insignificant positions | High | Miri |
|
||||
| Q-NNN-b | Departure schedule model — departure windows as generator output for docked vessels (Ozzie requirement). **Note R5:** D-READY-13 resolves this — `scheduled_departure: Option<SimTick>` in Docked state is mandatory generator output. Recommend closing before sprint planning. | High | Tyre + Miri |
|
||||
| Q-NNN-c | Mobile environment social arc — structural representation of journey timeline (Ozzie requirement) | Medium | Miri + Gestalt |
|
||||
| Q-NNN-d | DramaDensity enum naming — Round 4 struct uses Quiescent/Active/Intense (3) vs. Round 3's Zero/Low/Medium/High/Flashpoint (5). Resolve before D-record. | Low | Tyre + Gestalt |
|
||||
| Q-NNN-e | ObjectTag vocabulary co-maintenance — shared between Miri's HeritageGrammarOverlay and Araminta's asset categorization | Medium | Miri + Araminta |
|
||||
| Q-NNN-f | Assassination difficulty synthesis — formal spec combining DerivedDistrictAnalysis baseline (Phase 1) with on-demand runtime computation (player-facing display only; game logic uses Phase 1 value) | Medium | Gestalt + Miri |
|
||||
|
||||
---
|
||||
|
||||
## Implementation Targets (From Participant Estimates)
|
||||
|
||||
| Feature | Target version | Estimated effort |
|
||||
|---------|---------------|-----------------|
|
||||
| Phase 1 DistrictSkeleton (basic) | v0.3 | ~3 dev-days |
|
||||
| Phase 2 chunk fill with heritage grammar | v0.3 | ~4 dev-days |
|
||||
| MobileChunk (single-chunk vessels) | v0.3 | ~9.5 dev-days |
|
||||
| Vertical scale (z-bands, lazy loading) | v0.4 | ~7 dev-days |
|
||||
| DamageOverlay system | v0.4 | ~1.5 dev-days |
|
||||
| MobileChunk::Block (large ships) | v0.5 | Deferred |
|
||||
|
||||
---
|
||||
|
||||
## What This Generator Promises the Player
|
||||
|
||||
From Ozzie's synthesis across all four rounds:
|
||||
|
||||
> **The world is real and persistent.** Vessels exist when you're not on them. The crew you met last voyage is still there. The damage you caused is still there.
|
||||
>
|
||||
> **Every wall is a secret keeper.** WallBackside + BreachOnly means no tile is ever void. There's always something behind the wall.
|
||||
>
|
||||
> **Destruction has history.** DamageOverlay + trauma subtypes mean the aftermath of events is legible. You can arrive at a district and read what happened.
|
||||
>
|
||||
> **Height has meaning.** Vertical scale + view down from above. The building is itself a puzzle. Floor 30 has information floor 1 can't have, because floor 30 is harder to reach.
|
||||
>
|
||||
> **Every playstyle has guaranteed affordances.** The 3-tier guarantee system and the assassin lens guarantees mean the generator is making contracts it keeps.
|
||||
>
|
||||
> **The journey is content.** Mobile environments are social pressure cookers, not loading screens with chairs.
|
||||
>
|
||||
> **Insignificance is a lens, not a verdict.** A Minimal/Dormant district contains a complete small society. The playstyle is the starting assumption the world eventually corrects.
|
||||
|
||||
---
|
||||
|
||||
*Workshop closes. Fourteen D-records ready for filing. Six Q-records raised for sprint work. The generator pipeline is locked.*
|
||||
@@ -833,9 +833,9 @@ if graph.entity_knowledge.len() > MAX_ENTITY_KNOWLEDGE {
|
||||
---
|
||||
|
||||
**Files referenced:**
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/server/src/npc/mod.rs` (lines 47-49: InformationInventory)
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/server/src/bridge/types.rs` (line 26: entity_id)
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/server/src/simulation/tier.rs` (tier system)
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/decisions/architecture.md` (D-010, D-020, D-026, D-030)
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/decisions/perception.md` (D-011, D-017)
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/decisions/questions.md` (Q-016, Q-019)
|
||||
- `/var/mnt/data/projects/settled-reach/planning/server/src/npc/mod.rs` (lines 47-49: InformationInventory)
|
||||
- `/var/mnt/data/projects/settled-reach/planning/server/src/bridge/types.rs` (line 26: entity_id)
|
||||
- `/var/mnt/data/projects/settled-reach/planning/server/src/simulation/tier.rs` (tier system)
|
||||
- `/var/mnt/data/projects/settled-reach/planning/decisions/architecture.md` (D-010, D-020, D-026, D-030)
|
||||
- `/var/mnt/data/projects/settled-reach/planning/decisions/perception.md` (D-011, D-017)
|
||||
- `/var/mnt/data/projects/settled-reach/planning/decisions/questions.md` (Q-016, Q-019)
|
||||
|
||||
@@ -727,8 +727,8 @@ Let's build this.
|
||||
---
|
||||
|
||||
**Files referenced:**
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/decisions/perception.md` (D-011, D-015-D-019)
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/decisions/architecture.md` (D-010, D-026)
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/decisions/content.md` (D-024, D-028, D-033)
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/decisions/questions.md` (Q-016, Q-017)
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/server/src/npc/mod.rs` (current NPC model)
|
||||
- `/var/mnt/data/projects/settled-reach/planning/decisions/perception.md` (D-011, D-015-D-019)
|
||||
- `/var/mnt/data/projects/settled-reach/planning/decisions/architecture.md` (D-010, D-026)
|
||||
- `/var/mnt/data/projects/settled-reach/planning/decisions/content.md` (D-024, D-028, D-033)
|
||||
- `/var/mnt/data/projects/settled-reach/planning/decisions/questions.md` (Q-016, Q-017)
|
||||
- `/var/mnt/data/projects/settled-reach/planning/server/src/npc/mod.rs` (current NPC model)
|
||||
|
||||
@@ -879,18 +879,18 @@ KnowledgeGraph::last_change(&self) -> Option<(StableId, KnowledgeSource, u64)>
|
||||
|
||||
## Files Referenced
|
||||
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/server/src/npc/mod.rs` -- Current NPC component model, InformationInventory placeholder (line 47-49)
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/server/src/perception/mod.rs` -- PerceptionPlugin stub
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/server/src/bridge/types.rs` -- ObserverSnapshot, VisibleEntity, wire protocol types
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/server/src/simulation/movement.rs` -- TilePosition, WalkabilityMap, validate_movement
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/server/src/simulation/tier.rs` -- SimulationTier, ScopeTag, LastInteraction
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/server/src/cause_chain.rs` -- CauseChain, CauseKind (aligns with KnowledgeSource)
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/server/Cargo.toml` -- Dependency inventory
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/decisions/architecture.md` -- D-010, D-020, D-026, D-030, D-031
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/decisions/perception.md` -- D-011, D-015, D-017, D-018, D-033
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/decisions/content.md` -- D-028, D-034, D-035
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/decisions/questions.md` -- Q-016, Q-017, Q-018, Q-019
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/docs/audits/architecture-review-2026-02-11.md` -- Architecture review consensus
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/docs/sprints/sprint-2/server.md` -- Sprint 2 server tasks
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/docs/sprints/sprint-2/joint.md` -- Sprint 2 joint tasks, integration proof
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/docs/workshops/knowledge-graph-information-boundaries/workshop-brief.md` -- Workshop brief
|
||||
- `/var/mnt/data/projects/settled-reach/planning/server/src/npc/mod.rs` -- Current NPC component model, InformationInventory placeholder (line 47-49)
|
||||
- `/var/mnt/data/projects/settled-reach/planning/server/src/perception/mod.rs` -- PerceptionPlugin stub
|
||||
- `/var/mnt/data/projects/settled-reach/planning/server/src/bridge/types.rs` -- ObserverSnapshot, VisibleEntity, wire protocol types
|
||||
- `/var/mnt/data/projects/settled-reach/planning/server/src/simulation/movement.rs` -- TilePosition, WalkabilityMap, validate_movement
|
||||
- `/var/mnt/data/projects/settled-reach/planning/server/src/simulation/tier.rs` -- SimulationTier, ScopeTag, LastInteraction
|
||||
- `/var/mnt/data/projects/settled-reach/planning/server/src/cause_chain.rs` -- CauseChain, CauseKind (aligns with KnowledgeSource)
|
||||
- `/var/mnt/data/projects/settled-reach/planning/server/Cargo.toml` -- Dependency inventory
|
||||
- `/var/mnt/data/projects/settled-reach/planning/decisions/architecture.md` -- D-010, D-020, D-026, D-030, D-031
|
||||
- `/var/mnt/data/projects/settled-reach/planning/decisions/perception.md` -- D-011, D-015, D-017, D-018, D-033
|
||||
- `/var/mnt/data/projects/settled-reach/planning/decisions/content.md` -- D-028, D-034, D-035
|
||||
- `/var/mnt/data/projects/settled-reach/planning/decisions/questions.md` -- Q-016, Q-017, Q-018, Q-019
|
||||
- `/var/mnt/data/projects/settled-reach/planning/docs/audits/architecture-review-2026-02-11.md` -- Architecture review consensus
|
||||
- `/var/mnt/data/projects/settled-reach/planning/docs/sprints/sprint-2/server.md` -- Sprint 2 server tasks
|
||||
- `/var/mnt/data/projects/settled-reach/planning/docs/sprints/sprint-2/joint.md` -- Sprint 2 joint tasks, integration proof
|
||||
- `/var/mnt/data/projects/settled-reach/planning/docs/workshops/knowledge-graph-information-boundaries/workshop-brief.md` -- Workshop brief
|
||||
|
||||
@@ -578,12 +578,12 @@ Let's build this.
|
||||
|
||||
## Files Referenced
|
||||
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/docs/workshops/knowledge-graph-information-boundaries/round1-tyre.md`
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/docs/workshops/knowledge-graph-information-boundaries/round1-dudley.md`
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/docs/workshops/knowledge-graph-information-boundaries/round1-paula.md`
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/docs/workshops/knowledge-graph-information-boundaries/round1-gestalt.md`
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/docs/workshops/knowledge-graph-information-boundaries/round1-si.md`
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/decisions/perception.md` (D-011, D-015-D-019, D-033)
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/decisions/content.md` (D-024, D-028, D-034, D-035)
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/decisions/architecture.md` (D-010, D-020, D-026, D-030)
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/decisions/questions.md` (Q-016, Q-017)
|
||||
- `/var/mnt/data/projects/settled-reach/planning/docs/workshops/knowledge-graph-information-boundaries/round1-tyre.md`
|
||||
- `/var/mnt/data/projects/settled-reach/planning/docs/workshops/knowledge-graph-information-boundaries/round1-dudley.md`
|
||||
- `/var/mnt/data/projects/settled-reach/planning/docs/workshops/knowledge-graph-information-boundaries/round1-paula.md`
|
||||
- `/var/mnt/data/projects/settled-reach/planning/docs/workshops/knowledge-graph-information-boundaries/round1-gestalt.md`
|
||||
- `/var/mnt/data/projects/settled-reach/planning/docs/workshops/knowledge-graph-information-boundaries/round1-si.md`
|
||||
- `/var/mnt/data/projects/settled-reach/planning/decisions/perception.md` (D-011, D-015-D-019, D-033)
|
||||
- `/var/mnt/data/projects/settled-reach/planning/decisions/content.md` (D-024, D-028, D-034, D-035)
|
||||
- `/var/mnt/data/projects/settled-reach/planning/decisions/architecture.md` (D-010, D-020, D-026, D-030)
|
||||
- `/var/mnt/data/projects/settled-reach/planning/decisions/questions.md` (Q-016, Q-017)
|
||||
|
||||
@@ -1179,13 +1179,13 @@ That is actually elegant.
|
||||
---
|
||||
|
||||
**Files referenced:**
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/docs/workshops/knowledge-graph-information-boundaries/workshop-brief.md`
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/docs/workshops/knowledge-graph-information-boundaries/round1-dudley.md`
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/docs/workshops/knowledge-graph-information-boundaries/round1-gestalt.md`
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/docs/workshops/knowledge-graph-information-boundaries/round1-si.md`
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/docs/workshops/knowledge-graph-information-boundaries/round1-tyre.md`
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/docs/workshops/knowledge-graph-information-boundaries/round1-paula.md`
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/decisions/architecture.md` (D-010, D-020, D-026, D-030, D-031)
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/decisions/perception.md` (D-011, D-015, D-017, D-018, D-033)
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/decisions/content.md` (D-024, D-028, D-034, D-035)
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/decisions/questions.md` (Q-016, Q-019)
|
||||
- `/var/mnt/data/projects/settled-reach/planning/docs/workshops/knowledge-graph-information-boundaries/workshop-brief.md`
|
||||
- `/var/mnt/data/projects/settled-reach/planning/docs/workshops/knowledge-graph-information-boundaries/round1-dudley.md`
|
||||
- `/var/mnt/data/projects/settled-reach/planning/docs/workshops/knowledge-graph-information-boundaries/round1-gestalt.md`
|
||||
- `/var/mnt/data/projects/settled-reach/planning/docs/workshops/knowledge-graph-information-boundaries/round1-si.md`
|
||||
- `/var/mnt/data/projects/settled-reach/planning/docs/workshops/knowledge-graph-information-boundaries/round1-tyre.md`
|
||||
- `/var/mnt/data/projects/settled-reach/planning/docs/workshops/knowledge-graph-information-boundaries/round1-paula.md`
|
||||
- `/var/mnt/data/projects/settled-reach/planning/decisions/architecture.md` (D-010, D-020, D-026, D-030, D-031)
|
||||
- `/var/mnt/data/projects/settled-reach/planning/decisions/perception.md` (D-011, D-015, D-017, D-018, D-033)
|
||||
- `/var/mnt/data/projects/settled-reach/planning/decisions/content.md` (D-024, D-028, D-034, D-035)
|
||||
- `/var/mnt/data/projects/settled-reach/planning/decisions/questions.md` (Q-016, Q-019)
|
||||
|
||||
@@ -331,8 +331,8 @@ INSERT INTO ticket_deps (blocker_id, blocked_id) VALUES (361, 182); -- Knowledg
|
||||
**End of Sprint 2 Impact Summary**
|
||||
|
||||
**Files referenced:**
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/docs/workshops/knowledge-graph-information-boundaries/round2-synthesis.md`
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/docs/sprints/sprint-2/server.md`
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/docs/sprints/sprint-2/joint.md`
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/docs/sprints/sprint-2/client.md`
|
||||
- `/var/home/jeroenschweitzer/Projects/settled-reach/planning/db/connectors/ticket` (CLI used for ticket operations)
|
||||
- `/var/mnt/data/projects/settled-reach/planning/docs/workshops/knowledge-graph-information-boundaries/round2-synthesis.md`
|
||||
- `/var/mnt/data/projects/settled-reach/planning/docs/sprints/sprint-2/server.md`
|
||||
- `/var/mnt/data/projects/settled-reach/planning/docs/sprints/sprint-2/joint.md`
|
||||
- `/var/mnt/data/projects/settled-reach/planning/docs/sprints/sprint-2/client.md`
|
||||
- `/var/mnt/data/projects/settled-reach/planning/db/connectors/ticket` (CLI used for ticket operations)
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
# Workshop Outcomes: Knowledge Graph & Information Boundaries
|
||||
|
||||
**Workshop:** Knowledge Graph & Information Boundaries
|
||||
**Date:** 2026-02-11
|
||||
**Rounds:** 2 (Design + Synthesis)
|
||||
**Participants:** Tyre, Gestalt, Paula, Dudley, Si
|
||||
**Facilitator:** Jeroen
|
||||
**Documenter:** Qatux
|
||||
**Status:** DONE — fully actioned, decisions filed, tickets created
|
||||
**Full notes:** `docs/workshops/knowledge-graph-information-boundaries/round2-synthesis.md`, `sprint2-impact.md`
|
||||
|
||||
---
|
||||
|
||||
## What the Workshop Accomplished
|
||||
|
||||
Replaced the `InformationInventory { known_facts: Vec<String> }` placeholder with a fully specified knowledge graph data model. Five agents analyzing from different angles converged independently on all fundamentals: per-entity ECS component, stable entity IDs, per-entry provenance tracking. The synthesis resolved the only substantive debate (centralized resource vs. per-entity component) unanimously in favour of per-entity. The resulting D-041 spec is the foundation for asymmetric information as a playable mechanic — and became load-bearing for D-010, D-011, D-017, D-028, D-033, and Q-016.
|
||||
|
||||
---
|
||||
|
||||
## Major Decision Produced
|
||||
|
||||
### D-041: Knowledge Graph Data Model
|
||||
|
||||
The core design decision of this workshop. Full specification in `decisions/perception.md`.
|
||||
|
||||
Key architectural choices:
|
||||
- `KnowledgeGraph` as a Bevy ECS `Component` on each entity (not a centralized resource)
|
||||
- `StableEntityId` (`u64`-based) for cross-reference stability; runtime `EntityRegistry` for bidirectional mapping
|
||||
- `BTreeMap<StableId, EntityKnowledge>` + `BTreeMap<FactId, FactKnowledge>` per entity
|
||||
- Four confidence levels: `Direct` > `KnowsDetails` > `KnowsOf` > `Suspects`
|
||||
- Three knowledge states: `Active`, `Stale`, `Contradicted`
|
||||
- `KnowledgeSource` tracked per-entry (not per-graph): `DirectObservation`, `ToldBy`, `Background`, `Heard`
|
||||
- Event-driven updates via `KnowledgeEventQueue`; decay pass once per game-minute
|
||||
- Sprint 2 scope: data structures + direct observation + basic decay only
|
||||
|
||||
### Additional Decisions Implied (formalized later)
|
||||
|
||||
The workshop produced the architectural foundation that fed into:
|
||||
- D-012: Information boundaries (per-character knowledge isolation)
|
||||
- Formal resolution of Q-016: Knowledge hierarchy (`Suspects` < `KnowsOf` < `KnowsDetails` < `Direct`)
|
||||
|
||||
---
|
||||
|
||||
## Open Questions Identified
|
||||
|
||||
| ID | Question | Sprint Impact | Resolved By |
|
||||
|----|----------|---------------|-------------|
|
||||
| Q-024 | Gossip propagation timing (immediate vs queued) | Sprint 3+ | D-080 (knowledge-flow-npc-boundaries workshop) |
|
||||
| Q-025 | Knowledge graph cap and eviction policy | Sprint 3+ | D-080 (closed: no cap needed at projected v0.1 scale) |
|
||||
| Q-026 | Contradiction detection algorithm | Sprint 3+ (THE FRIEND arc) | D-083 (knowledge-flow-npc-boundaries workshop) |
|
||||
|
||||
None blocked Sprint 2.
|
||||
|
||||
---
|
||||
|
||||
## Tickets Created
|
||||
|
||||
8 new tickets added to Sprint 2, all under epic #351. Sprint 2 expanded from 14 to 22 tickets (+6.5 developer-days).
|
||||
|
||||
| # | Title | Priority | Estimate |
|
||||
|---|-------|----------|----------|
|
||||
| #361 | KnowledgeGraph component + types (D-041) | critical | 1 day |
|
||||
| #362 | StableEntityId + EntityRegistry resource | critical | 1 day |
|
||||
| #363 | KnowledgeEventQueue + processing system | high | 0.5 day |
|
||||
| #364 | Direct observation knowledge flow | critical | 0.5 day |
|
||||
| #365 | Basic knowledge decay system | high | 0.5 day |
|
||||
| #366 | Observer snapshot knowledge integration | critical | 1 day |
|
||||
| #367 | Knowledge graph unit test suite | high | 1 day |
|
||||
| #368 | Knowledge vocabulary for v0.1 content | high | 0.5 day |
|
||||
|
||||
**Existing tickets affected:**
|
||||
- #89 (Information inventory) — cancelled, subsumed by #361
|
||||
- #269 (CauseChain component) — marked done (already implemented)
|
||||
- #138-142 (Information boundary epics) — reparented under #351; #139, #141, #142 deferred to Sprint 3; #140 cancelled (merged into #366)
|
||||
|
||||
**Critical path impact:** #361, #362, #363, #364 added serially to Sprint 2 critical path (10 tickets serial, up from 6).
|
||||
|
||||
---
|
||||
|
||||
## Sprint 2 Completion Criteria (Added by Workshop)
|
||||
|
||||
Two new acceptance criteria added to Sprint 2's definition of done:
|
||||
- Entity color reflects relationship state from knowledge graph (#361, #366)
|
||||
- Remembered (not visible) entities appear as ghosts at last-known position (#361, #366)
|
||||
|
||||
**Knowledge graph proof:** Observe an NPC, walk away, return. NPC appears as ghost at last-known position while not in LOS. Color shifts by relationship state.
|
||||
|
||||
---
|
||||
|
||||
*Compiled by Qatux. Source: `docs/workshops/knowledge-graph-information-boundaries/round2-synthesis.md`, `sprint2-impact.md`. Primary decision in `decisions/perception.md` (D-041).*
|
||||
@@ -0,0 +1,116 @@
|
||||
# Workshop Outcomes: v0.1 Content Scoping
|
||||
|
||||
**Workshop:** v0.1 Content Scoping
|
||||
**Date:** 2026-02-12
|
||||
**Rounds:** 2 + closing round (lead resolutions)
|
||||
**Participants:** Gestalt, Paula, Tyre, Mellanie, Stig, Dudley, Si, Qatux
|
||||
**Facilitator:** Jeroen
|
||||
**Documenter:** Qatux
|
||||
**Status:** CLOSED — all recoverable decisions filed, tickets created
|
||||
**Full notes:** `docs/workshops/v01-content-scoping/SUMMARY.md`, `si-ticket-changes.md`
|
||||
|
||||
---
|
||||
|
||||
## What the Workshop Accomplished
|
||||
|
||||
Applied the Wiki Review's long-term generator strategy to the immediate v0.1 hand-authored proof. Produced 20 decisions (D-042 through D-061), 38 new tickets, canonical NPC mapping for 17 characters, the 16-key EntityKnowledge specification, full content directory architecture, and a Sprint 3-5 roadmap. Tyre and Dudley independently produced structurally identical ObserverSnapshot v3 definitions without coordination — confirmed the architecture was sound. Lead issued 4 decisions resolving the major Round 1 disagreements between rounds, then resolved 3 remaining questions in a closing round.
|
||||
|
||||
**Note on decision IDs:** Several IDs assigned at this workshop collided with later numbering. Genuinely new decisions identified in retrospect were filed as D-087 (content directory structure), D-089 (NPC canonical mapping method), D-091 (EntityKnowledge 16-key canonical set), Q-031 through Q-034.
|
||||
|
||||
---
|
||||
|
||||
## Decisions Produced
|
||||
|
||||
### From Round 1 Consensus (7)
|
||||
|
||||
| ID | Decision | Domain |
|
||||
|----|----------|--------|
|
||||
| D-042 | Drin promoted from Tier 3 to Tier 2 | content.md |
|
||||
| D-043 | THE NOBODY mechanic deferred to v0.2; hidden data ships in v0.1 content | scope.md |
|
||||
| D-044 | v0.1 interaction model: 7 verbs (Move, Look, Monologue, Examine Object, Examine NPC, Talk, Overhear) | scope.md |
|
||||
| D-045 | v0.1 scope IN: news ticker, PC-as-NPC, time progression, relationship state transitions | scope.md |
|
||||
| D-046 | v0.1 scope OUT: inventory, stealth, combat, save/load, lattice modification | scope.md |
|
||||
| D-047 | v0.1 triangles: 3 active forks (T1, T2, T4), 2 passive tensions (T3, T5) | content.md |
|
||||
| D-048 | Client receives all text from server via state updates; client does not load content files | architecture.md |
|
||||
|
||||
### From Round 2 + Closing (13)
|
||||
|
||||
| ID | Decision | Domain |
|
||||
|----|----------|--------|
|
||||
| D-049 | YAML is the content file format for v0.1; RON is optional build-time optimization | architecture.md |
|
||||
| D-050 | Gestalt's NPC pattern/motivation mapping canonical for v0.1; Paula's emotional layer becomes v0.2 annotations | content.md |
|
||||
| D-051 | v0.1 ships single context-sensitive verb; multi-verb architecture modeled underneath | architecture.md |
|
||||
| D-052 | 3-state pause: Normal (100%), Overlay (50%), Paused (0%); server-authoritative | architecture.md |
|
||||
| D-053 | Self-contained triangle forks for v0.1; no cross-triangle cascade (v0.2) | content.md |
|
||||
| D-054 | ObserverSnapshot v3: adds sim_speed, nearby_interactions, active_dialogue, monologue, overheard, knowledge_updates, examine_result, ticker_headlines | architecture.md |
|
||||
| D-055 | 16 EntityKnowledge keys; 4 new role-perspective keys; trust_read merged into trust_level; secret_held → leverage_held | architecture.md |
|
||||
| D-056 | PC voice registers: smuggler (feeling-first, fragments, physical); detective (analysis-first, complete sentences, institutional) | content.md |
|
||||
| D-057 | Content directory: content/ with _schema/, global/, districts/ top-level split; JSON Schema validation at build time | process.md |
|
||||
| D-058 | THE FRIEND content pack template: Kael Davan, 91 lines across 5 arc phases | content.md |
|
||||
| D-059 | Monologue display: 160 char max, 2-line max, 4-6s display, 2s cooldown, queue depth 1, 9-level priority | architecture.md |
|
||||
| D-060 | actions[] renamed to verbs[] across all surfaces | architecture.md |
|
||||
| D-061 | No ticket merges across domain teams | process.md |
|
||||
|
||||
### Retrospective Filings (ID collisions resolved)
|
||||
|
||||
| ID | Decision | Domain |
|
||||
|----|----------|--------|
|
||||
| D-087 | Content directory structure (content/ split) | process.md |
|
||||
| D-089 | Canonical NPC pattern/motivation mapping method | content.md |
|
||||
| D-091 | EntityKnowledge 16-key canonical specification | architecture.md |
|
||||
|
||||
---
|
||||
|
||||
## Open Questions Carried Forward
|
||||
|
||||
| ID | Question | Status |
|
||||
|----|----------|--------|
|
||||
| Q-031 | NPC surnames for Drin, Sess, Tav awaiting Miri validation | Informational |
|
||||
| Q-032 | Interaction struct naming: AvailableActions (Tyre) vs EntityInteractions (Dudley) | Resolved at implementation |
|
||||
| Q-033 | 695 authored items: validated as scope input but not independently verified | Informational |
|
||||
| Q-034 | Dialogue max-width: pixel value for 20% height / max-width constraint | Pending lead call |
|
||||
|
||||
None blocked Sprint 3.
|
||||
|
||||
---
|
||||
|
||||
## Tickets Created
|
||||
|
||||
38 new tickets + 10 existing ticket updates. See `si-ticket-changes.md` for full list.
|
||||
|
||||
**Teams:** copy (21), server (13), client (2), ci (1).
|
||||
|
||||
**Critical path:** #261 (Dual Lens Authoring Guide) is the single biggest blocker — directly blocks 9 downstream tickets across the content pipeline. Five-day time-box recommended.
|
||||
|
||||
| Series | Count | Domain |
|
||||
|--------|-------|--------|
|
||||
| A (Wiki content fixes) | 8 | copy |
|
||||
| B (Style guides + specs) | 5 | copy |
|
||||
| C (Content directory + schemas) | 10 | copy/server/ci |
|
||||
| D (Design specs) | 2 | server/copy |
|
||||
| NEW 1-7 (Workshop rounds) | 7 | copy |
|
||||
| NEW 8-14 (Lead decisions, excl. killed NEW-12) | 6 | server/client |
|
||||
|
||||
**Killed:** NEW-12 (client pause state machine — pause is server-authoritative, client sends IPC command only).
|
||||
|
||||
**Sprint allocation:** Sprint 3 — foundations and specs. Sprint 4 — content conversion and authoring begins. Sprint 5+ — content at scale.
|
||||
|
||||
---
|
||||
|
||||
## NPC Canonical Mapping (17 NPCs)
|
||||
|
||||
The Gestalt-Paula synthesis produced the v0.1 canonical pattern/motivation mapping for all 17 Sova NPCs. This is the authoritative reference for content authoring.
|
||||
|
||||
| Name | Tier | Pattern | Motivation |
|
||||
|------|------|---------|-----------|
|
||||
| Kael Davan | T1 | FRIEND | OPERATOR |
|
||||
| Sera Venn | T1 | FRIEND | WITNESS |
|
||||
| Naia Tamm | T1* | MIRROR | CIVILIAN |
|
||||
| Voss, Lera, Torek, Devra, Maret, Resha, Drin, Renn, Pell, Harek | T2 | (varied) | (varied) |
|
||||
| Sess, Olin, Sabel, Tav | T3 | (varied) | (varied) |
|
||||
|
||||
Off-stage: Nils Davan — GHOST + HANDLER.
|
||||
|
||||
---
|
||||
|
||||
*Compiled by Qatux. Source: `docs/workshops/v01-content-scoping/SUMMARY.md`, `si-ticket-changes.md`. Decisions in relevant `decisions/` domain files (D-042 through D-061, D-087, D-089, D-091). Open questions in `decisions/questions.md` (Q-031 through Q-034).*
|
||||
@@ -0,0 +1,97 @@
|
||||
# Workshop Outcomes: v0.1 Gap Analysis
|
||||
|
||||
**Workshop:** v0.1 Gap Analysis
|
||||
**Date:** 2026-02-11
|
||||
**Rounds:** 2 (Gap identification + Synthesis)
|
||||
**Participants:** Gestalt, Tyre, Ozzie, Paula, Nigel, Gore, Hoshe
|
||||
**Facilitator:** Jeroen
|
||||
**Documenter:** Qatux
|
||||
**Status:** DONE — fully actioned, decisions confirmed, tickets created
|
||||
**Full notes:** `docs/workshops/v01-gap-analysis/si-ticket-changes.md`
|
||||
|
||||
---
|
||||
|
||||
## What the Workshop Accomplished
|
||||
|
||||
Stress-tested the full v0.1 plan (232 tickets, 7 initiatives) against three tracks: strength of concept proof, fun and wow factor, and completeness. Found significant gaps: missing infrastructure (collision, pathfinding, time system), a missing experience layer (observation pipeline, interaction verbs), and systemically underpriced tickets across social, dialogue, and replayability systems. The workshop ended with 273 tickets (+41) and a clear Sprint 1-5 dependency chain.
|
||||
|
||||
Key outcome: the workshop revealed that tile collision, A* pathfinding, the observation event generator, and the interaction dispatcher were absent from the ticket catalog despite being architectural blockers for almost everything else. These were added at critical priority.
|
||||
|
||||
---
|
||||
|
||||
## Decisions Confirmed
|
||||
|
||||
The workshop confirmed 6 decisions. These fed directly into later formal D-records:
|
||||
|
||||
| Decision | Formal Record | Notes |
|
||||
|----------|---------------|-------|
|
||||
| Deterministic replay is an architectural requirement, not just test infrastructure | D-010 (reinforced) | Promoted #201 to critical |
|
||||
| Time system: 10 tps, 4 day phases, diegetic clock | D-031 | Resolved Q-009; ticket #25 renamed and promoted |
|
||||
| Godot test framework = gdUnit4 | process.md | Tyre reversed GUT recommendation after Hoshe's analysis |
|
||||
| IPC testing = three-layer architecture (fixture, protocol mock, real integration) | architecture.md | Hoshe + Tyre |
|
||||
| CauseChain is a production component, not test pollution | architecture.md | #269 created |
|
||||
| Dual Lens Authoring Guide must precede content authoring | D-038 extended | All agents converged |
|
||||
|
||||
These decisions fed into the scope and architecture domain files. The three-tier content system (D-023), vertical slice (D-027), and population ratios (D-029) were validated against the gap analysis findings and confirmed as sound.
|
||||
|
||||
---
|
||||
|
||||
## Ticket Changes
|
||||
|
||||
**Before:** 232 tickets | **After:** 273 tickets (+41)
|
||||
|
||||
| Change Type | Count |
|
||||
|-------------|-------|
|
||||
| Priority promotions (existing) | 15 |
|
||||
| New epics | 3 |
|
||||
| New stories | 38 |
|
||||
| Dependency records added | 21 |
|
||||
| Renamed + promoted | 1 (#25) |
|
||||
|
||||
### Priority Promotions (15 tickets)
|
||||
|
||||
**Medium → High (11):** #103 (relationship dynamics), #105 (tolerance threshold triggers), #171 (trust-gated gossip), #172 (unprompted disclosure), #173 (trait modifier system), #175 (entanglement ratio), #176 (NPC pool generation), #121 (character voice variation), #126 (medium-range visual indicators), #162 (storyteller module activation), #178 (seed-based variation).
|
||||
|
||||
**High → Critical (3):** #201 (deterministic replay), #182 (divergent starting knowledge), #183 (divergent relationships).
|
||||
|
||||
### New Epics (3)
|
||||
|
||||
| ID | Title | Priority |
|
||||
|----|-------|----------|
|
||||
| #233 | Movement & Collision | critical |
|
||||
| #234 | Observation & Interaction | critical |
|
||||
| #235 | Game State Management | high |
|
||||
|
||||
### Critical New Stories
|
||||
|
||||
| ID | Title | Priority |
|
||||
|----|-------|----------|
|
||||
| #236 | Tile collision system | critical |
|
||||
| #239 | Observation event generator | critical |
|
||||
| #240 | Player interaction system and dispatcher | critical |
|
||||
| #237 | Tile-based A* pathfinding | high |
|
||||
| #238 | NPC path following and movement | high |
|
||||
| #253 | Monologue content architecture | high |
|
||||
| #261 | Dual Lens Authoring Guide | high |
|
||||
| (+ 31 more stories) | | high/medium/low |
|
||||
|
||||
### Critical Path Produced
|
||||
|
||||
```
|
||||
Sprint 1: #236 (collision) → #237 (pathfinding) → #238 (NPC movement)
|
||||
#25 (game clock) → #88 (daily routines)
|
||||
Sprint 2: #239 (observation generator) + #240 (interaction dispatcher)
|
||||
Sprint 3: Observation verbs, NPC conversation, monologue, triangle escalation
|
||||
Sprint 4: Content pipeline (#261 dual lens guide blocks all content packs)
|
||||
Sprint 5: Validation and playtest protocol
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Open Questions
|
||||
|
||||
None formally raised as Q-records by this workshop — the gap analysis was primarily a ticket and priority exercise. Questions about content authoring (Q-012 through Q-017) were raised in the companion content-gap-analysis workshop the same day.
|
||||
|
||||
---
|
||||
|
||||
*Compiled by Qatux. Source: `docs/workshops/v01-gap-analysis/si-ticket-changes.md`. Decisions confirmed fed into `decisions/scope.md` (D-023, D-027, D-029) and `decisions/architecture.md` (D-010, D-031).*
|
||||
@@ -0,0 +1,116 @@
|
||||
# Workshop Outcomes: Wiki Review & Content Standards
|
||||
|
||||
**Workshop:** Wiki Review & Content Standards
|
||||
**Date:** 2026-02-12
|
||||
**Rounds:** 4 + lead interview between R3 and R4
|
||||
**Participants:** Paula, Mellanie, Miri, Gestalt, Gore, Nigel, Ozzie, Tyre, Qatux, Si
|
||||
**Facilitator:** Jeroen
|
||||
**Documenter:** Qatux
|
||||
**Status:** CLOSED — all recoverable decisions filed, tickets created
|
||||
**Full notes:** `docs/workshops/wiki-review/SUMMARY.md`, `si-ticket-changes.md`
|
||||
|
||||
---
|
||||
|
||||
## What the Workshop Accomplished
|
||||
|
||||
Began as a v0.1 wiki review (45 files, ticket #368) and was redirected between rounds 2 and 3 by a major strategic reframe: the lead declared the target as 300 populated worlds before DLC. This transformed the workshop from a content authoring strategy into a generator specification strategy. All Round 4 responses independently arrived at the same conclusion: the workshop had been designing generator specifications all along. The district skeleton, NPC composition matrix, Sacred/Profane framework, and pool architecture were already generator-shaped.
|
||||
|
||||
**The strategic reframe:** Old model: writers produce districts, tooling accelerates writers. New model: engineers produce generators, writers produce generator inputs, tooling IS the product.
|
||||
|
||||
**Note on decision IDs:** Several IDs proposed at this workshop collided with later numbering. Genuinely new decisions identified in retrospect were filed as D-088 (300-world generator model), D-090 (three-tier world authoring), D-092 (Sacred/Profane/Middle Kingdom framework), Q-030, Q-035 through Q-039.
|
||||
|
||||
---
|
||||
|
||||
## Decisions Produced
|
||||
|
||||
### Long-Term Strategy Decisions (Confirmed by Lead)
|
||||
|
||||
| ID | Decision | Domain |
|
||||
|----|----------|--------|
|
||||
| D-088 | 300 worlds before DLC — generator model required | scope.md |
|
||||
| D-090 | Three-tier world authoring: Landmark (10-15 hand-authored), Regional (30-50 template), Generated (230-260 procedural) | scope.md |
|
||||
| D-092 | Sacred/Profane/Middle Kingdom randomization framework | architecture.md |
|
||||
|
||||
### Supporting Decisions (Rounds 1-2, v0.1 Specific)
|
||||
|
||||
| ID | Decision | Domain |
|
||||
|----|----------|--------|
|
||||
| Q-030 | Cultural ingredients menu: 6 ingredient categories, Heritage OPTIONAL, derivation function produces cultural parameters | pending formalization |
|
||||
| — | Hael renamed to Naia Tamm (resolves Kael/Hael sonic collision) | content.md |
|
||||
| — | Three-system NPC architecture: Thematic Patterns + Functional Motivations + Composition rules | content.md |
|
||||
| — | Cultural brief = generation seed (seed.yaml + brief.md dual artifact) | process.md |
|
||||
| — | 8 PC archetypes at v1.0; archetypes are FLUID positions, not classes | scope.md |
|
||||
| — | THE NOBODY: dynamic tier promotion (NOBODY → NOTICED → RECOGNIZED → KNOWN → INVESTED) | scope.md |
|
||||
|
||||
The specific v0.1 decisions (Naia rename, NPC architecture, THE NOBODY, THE MIRROR) were carried forward and filed in the subsequent v0.1 Content Scoping workshop where IDs were formally assigned.
|
||||
|
||||
---
|
||||
|
||||
## Open Questions Raised
|
||||
|
||||
| ID | Question | Status |
|
||||
|----|----------|--------|
|
||||
| Q-030 | Cultural ingredients menu: full formalization of 6 categories, null-heritage behavior, derivation function specification | Pending |
|
||||
| Q-035 | Naming algorithm: phonetic rules vs word lists — which approach for 300-world cultural naming | Pending |
|
||||
| Q-036 | Gate topology design: connectivity requirements, hub placement, small-world properties | Pending |
|
||||
| Q-037 | Storyteller cultural literacy: how storyteller adapts pacing to cultural trust-building rates | Pending |
|
||||
| Q-038 | NPC pattern composition rules: forbidden/preferred combination formalization | Pending |
|
||||
| Q-039 | Modding toolkit: content pack manifest, ADD/REPLACE/MERGE overlay operations | Pending |
|
||||
|
||||
---
|
||||
|
||||
## Tickets Created
|
||||
|
||||
29 new tickets (1 epic, 9 stories, 19 tasks) + 4 existing ticket updates. See `si-ticket-changes.md` for full list.
|
||||
|
||||
**Teams:** copy (21), server (7), ci (1).
|
||||
|
||||
### Existing Ticket Updates (4)
|
||||
|
||||
| ID | Action |
|
||||
|----|--------|
|
||||
| #301 | Update description with concrete taxonomy rules from workshop |
|
||||
| #319 | Update — Miri's Krenn brief supersedes original scope |
|
||||
| #368 | Mark done — wiki at wiki/ is the delivered output |
|
||||
| #261 | No change — confirmed still blocking, assign to copy when ready |
|
||||
|
||||
### New Epic
|
||||
|
||||
**Wiki Review Workshop Outputs** — parent epic for all workshop-produced tickets. Priority: high. Team: copy.
|
||||
|
||||
### Selected New Tickets
|
||||
|
||||
| Series | Count | Examples |
|
||||
|--------|-------|---------|
|
||||
| A (Wiki content updates) | 12 | A1 canonical names, A2 Hael→Naia rename, A3 Krenn brief, A7 smuggler attributes, A11 Triangle 1 fix |
|
||||
| B (Style guides + specs) | 5 | B1 NPC Authoring Style Guide, B2 MIRROR spec, B3 PC-as-NPC spec, B4 Smuggler voice card |
|
||||
| C (Content directory + schemas) | 10 | C1 design doc, C2 directory skeleton, C3 schemas, C9 validate-content CLI |
|
||||
| D (Design specs) | 4 | D1 cultural_gate design, D2 seed config schema, D3 secondary contraband, D4 news ticker |
|
||||
|
||||
---
|
||||
|
||||
## Deferred to Future Workshops
|
||||
|
||||
The wiki-review triggered scoping of several follow-on workshops:
|
||||
|
||||
- **Control & Interaction Scheme** — brief written during this workshop; held separately (`docs/workshops/control-interaction/`)
|
||||
- Perception system gravity variation for world transitions
|
||||
- Full NPC pattern composition rules (forbidden/preferred lists)
|
||||
- Gate topology design
|
||||
- Storyteller cultural literacy
|
||||
- LLM-assisted content pipeline design
|
||||
- Modding toolkit specification
|
||||
- Inter-world political generation
|
||||
|
||||
---
|
||||
|
||||
## Key Quotes Preserved
|
||||
|
||||
- Nigel: "Two players, same world, same seed, different experience because they noticed different people."
|
||||
- Gore: "Learning to see is the endgame."
|
||||
- Gestalt: "Hotline Miami movement + Disco Elysium interaction."
|
||||
- Gore: "The theme is the field, not any specific phrasing of it. The field is: what does it cost to be human inside something bigger than yourself?"
|
||||
|
||||
---
|
||||
|
||||
*Compiled by Qatux. Source: `docs/workshops/wiki-review/SUMMARY.md`, `si-ticket-changes.md`. Decisions in `decisions/scope.md` (D-088, D-090) and `decisions/architecture.md` (D-092). Open questions in `decisions/questions.md` (Q-030, Q-035 through Q-039).*
|
||||
Reference in New Issue
Block a user