Files
settled-reach/docs/workshops/generator-architecture/gestalt-round3.md
T
jpmschweitzerandClaude Opus 4.6 9a5c9c4408 docs(docs): add frontmatter to generator-architecture workshop
Standardized YAML frontmatter on all 38 files with title, description,
type, workshop, agent, and round fields.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 23:40:37 +01:00

50 KiB
Raw Blame History

title, description, type, status, workshop, agent, round, created
title description type status workshop agent round created
Gestalt Round 3 — Convergence and Pipeline Statement Assassin playstyle, universal vs conditional guarantees, destructible boundaries, and vertical scale workshop archived generator-architecture gestalt 3 2026-02-27

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
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:

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

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)

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)

/// 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

/// 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_tierREMOVED (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.