Files
settled-reach/docs/workshops/world-generation/tyre-sw1r1.md
T
jpmschweitzerandClaude Opus 4.6 252e3d380a docs(workshops): complete world generation architecture workshop
3 rounds of SW1 (endgame feature vision) with 5 agents + Qatux.
Produced endgame-feature-vision.md (692 lines) covering the full
galaxy-to-ground generation pipeline, cultural cascade, replayability
architecture, and player experience beats.

Workshop was cut short when PO redirected to a 6-phase development
cascade (wiki content → economics → planetary maps → player control →
world gen → detail coloring). v0.2 target dropped. Heritage roots
(D-104/D-105/D-101/D-107) flagged for supersession — real-world
cultural corridors replace abstract roots.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 17:12:09 +01:00

17 KiB
Raw Blame History

Tyre — SW1-R1: Feasibility Guardrails for Generation Scope

Sub-workshop 1, Round 1 — Technical Feasibility Assessment


Feasibility Cheat Sheet

Already Built and Working

Component Location What It Does
DistrictSkeleton data model server/src/simulation/generator.rs Full type hierarchy: districts → blocks → chunks, social sites, reservations, z-levels, palettes, mutations. 579 lines of typed structs/enums.
Chunk streaming system server/src/simulation/chunk_streaming.rs Load/unload chunks by Chebyshev distance from player. Cadence-gated (every 10 ticks). Configurable radius.
Movement + walkability server/src/simulation/movement.rs WalkabilityMap with per-chunk BTreeMap storage, TileKind (Floor/Wall/Void/Restricted), TilePosition, ChunkCoord (with z). 32×32 tiles per chunk.
Tile renderer (placeholder) client/scripts/rendering/tile_renderer.gd TileMapLayer with colored rectangles for 5 tile types. Processes tile data from ObserverSnapshot.
World renderer pipeline client/scripts/rendering/world_renderer.gd D-049 z-stack: FogGroup → FloorTiles + Entities + FogOverlay. Tick-based invalidation.
Dual-scale grid D-066 confirmed 0.5m sim tiles, 1m visual tiles. 2:1 retina factor. Server knows only sim tiles.
3D camera system D-148 confirmed 30° tilt, 45° diamond rotation. Real Camera3D, not sprite faking.
3D character rendering D-149 confirmed Live 3D models via CharacterCompositor. Sprint 28 in progress.

Stubbed but Needs Implementation

Component Status What's Missing
Generator type aliases generator.rs lines 3996 27 stub types (all String or Vec<bool>). No actual generation logic — just the output shape.
Phase 1 (skeleton generation) Data model complete No algorithm to produce a DistrictSkeleton from a seed + constraints.
Phase 2 (chunk fill) Architecture defined No tile-level fill logic. GeneratorChunkData is Vec<bool>.
ZonePalette system Struct defined No palette data, no heritage→material mapping.
WallBackside Enum defined No assignment logic during chunk fill.
GuaranteeAuditResult String stub No audit implementation.
MobileChunk D-108 spec complete No structs in code yet.
ChunkMutations Struct defined No mutation application logic.

Easy to Add (days)

Feature Effort Why It's Cheap
Template-stamped room generator 23 days Define room templates as 2D tile grids, stamp them into chunk data. No algorithmic complexity.
Corridor carving between rooms 12 days A* or L-shaped corridors between room centers. Well-understood problem.
Tile palette → 3D mesh mapping 23 days Each TileKind maps to a MeshLibrary entry. GridMap or manual mesh placement.
Noise-based district type assignment 1 day FastNoiseLite (built into Godot), or Rust noise crate on server side. Threshold → district type.
Single-z-level GridMap rendering 23 days Replace TileMapLayer with GridMap for floor rendering. Straightforward migration.
Z-level selector (UI toggle) 1 day Filter tiles by z in renderer, add UI button. No new rendering tech.

Hard to Add (weeks+)

Feature Effort Why It's Hard
Full Phase 1 with guarantee audit 34 weeks Combinatorial satisfaction: place 16 blocks, assign zoning, enforce 13 guarantee checks, vary per seed. Essentially a constraint solver.
WFC or grammar-based building interiors 23 weeks WFC requires careful tile adjacency ruleset authoring + solver tuning. Grammar-based requires defining the grammar. Both need extensive iteration.
Multi-z-level rendering with cutaway 23 weeks Transparency masking, depth sorting, camera-relative culling. Godot's render pipeline doesn't natively support "hide floors above camera" for isometric. Needs custom shader work.
Organic layout mode 12 weeks Block rotation/offset (D-096) creates non-axis-aligned boundaries. Pathfinding across rotated blocks, stitching streets at junctions, handling the 45° rotation cap.
Cross-district boundary stitching 23 weeks Adjacent districts must have matching access points, consistent road networks, and aligned chunk edges. Generator must know neighbor state.
Full ZonePalette with cultural modifiers 23 weeks 8 base terrain types × N heritage roots × N era layers × condition modifiers. Asset authoring dominates.
2D→3D rendering migration 24 weeks The current pipeline is Node2D + TileMapLayer. D-148/D-149 put us in 3D space. Fog shader, entity rendering, z-stack — all need migration. This is happening anyway but blocks generation rendering.

Reference Implementations — Relevance Assessment

Reference Relevance to Our Stack Verdict
CityCrafter3D HIGH. District→block→building pipeline maps to our hierarchy. Noise-based district assignment, density control, subdivision — all patterns we need. Godot 4.4, GDScript. BUT: generation is client-side (we need server-side Rust). Study the algorithm, not the code.
GridMapLayer HIGH. 2D tile data → 3D GridMap rendering is exactly our client-side need. TileMapLayer→GridMap bridge with subdivision support. Study for the client rendering upgrade.
Chunk Manager MEDIUM. Basic pattern matches ours but we already have a more sophisticated implementation in chunk_streaming.rs. Useful as a sanity check, not as a source of new patterns.
RetroTerrain MEDIUM. Procedural mesh + height shader is relevant for wilderness zones. BUT: crashes at 1000×1000 (their words), no chunking. We'd need the shader technique, not the generation approach.
PathMesh3D MEDIUM. Path extrusion for corridors, pipes, conduits — relevant for station interior detail (cables, ductwork). GDExtension (C++), performant. Future use, not v0.2 critical.
Block-based Procedural Map LOW-MEDIUM. Perlin noise + chunk loading — patterns we already know. Useful as a Godot 4.2 reference for seed determinism.
Spatial Gardener LOW. Manual brush painting, not procedural. Wrong paradigm — we need server-driven placement. The octree LOD concept is worth noting for future vegetation density, but not actionable now.
DeformableMesh LOW. Runtime mesh deformation for variety. Interesting for "make crates look different" but Godot 4.5+ required and not performance-optimized. Future nice-to-have.
SunshineClouds LOW. Volumetric cloud rendering — we'd only want the ground shadow dappling shader, which is a small extract. Not a priority for generation architecture.

Questions for the Product Owner

Q1: What SettingType(s) ship in v0.2?

The generator data model supports 8 SettingTypes (Station, Urban, Agricultural, Maritime, Wilderness, Water, Transitional, Orbital, Specialized). Each needs its own generation grammar, tile palette, and social site placement rules.

Technical tradeoff: Each SettingType is essentially a separate generator. Station interiors (corridors + rooms + modules) are algorithmically different from Urban (streets + lots + buildings) which is different from Wilderness (terrain + vegetation + paths). Sharing infrastructure between them is possible but the tile-level generation logic is unique per type.

Option Cost What You Get
A. Station only Small (23 weeks for basic generator) Corridors, rooms, airlocks, modules. Proves the entire pipeline end-to-end. Matches "first location the player sees" in many scenarios.
B. Station + Urban Medium (46 weeks) Adds streets, building lots, exteriors. Two visually distinct zone types. Covers docking → city gameplay loop.
C. Station + Urban + Wilderness Large (710 weeks) Adds terrain, vegetation, paths. Three zones. Full planet surface experience. Wilderness is algorithmically simplest but needs the most art assets.
D. All SettingTypes Very large (12+ weeks) Full world variety. Not recommended for v0.2.

My recommendation: Option A for v0.2 core, with Urban as a fast-follow. Station interiors are the most constrained environment (walls everywhere, clear rooms, obvious pathfinding) — they're the easiest to generate well and the hardest to generate badly. Prove the pipeline works before expanding surface area.


Q2: What building/room generation algorithm?

We need to fill blocks with rooms, corridors, and spatial structure. The data model is ready. The algorithm choice determines quality ceiling AND iteration cost.

Technical tradeoff: Simpler algorithms are faster to implement but produce more repetitive output. Complex algorithms produce better variety but are harder to tune and debug — especially with our determinism requirement (D-010 principle 4, BTreeMap everywhere, no HashMap, no f32 in generation paths).

Option Cost Quality Determinism Risk
A. Template stamping + variation Small (12 weeks) Medium — recognizable patterns, seed-driven variation in rotation/mirroring/detail Zero — templates are static data, placement is index math
B. BSP (Binary Space Partition) room subdivision Small-Medium (2 weeks) Good — natural room variety, recursive split produces organic-feeling layouts Low — pure integer math, well-understood algorithm
C. Grammar-based (L-system / shape grammar) Medium (34 weeks) High — rule-driven expansion produces culturally coherent spaces Low — rules are deterministic by definition, but debugging grammar rules is tedious
D. Wave Function Collapse (WFC) Large (46 weeks) Very high — maximum local variety while maintaining adjacency rules MEDIUM — WFC propagation order can diverge on different platforms if not carefully constrained. Backtracking adds complexity.

My recommendation: Option B (BSP) as the core algorithm, with template stamping for special rooms. BSP is the Dwarf Fortress / roguelike standard for good reason — it produces natural room layouts with zero tuning, runs in microseconds, and is trivially deterministic. Stamp social-site templates (bars, offices, medical bays) into BSP-carved spaces. Grammar-based can layer on top later for cultural variation. WFC is fascinating but the tuning cost is high and the determinism risk is real with D-010.


Q3: 2D TileMapLayer → 3D rendering migration — when?

This is the elephant in the room. The current rendering pipeline is 2D (Node2D + TileMapLayer). D-148 confirms a 30° Camera3D. D-149 confirms 3D character models. The world renderer needs to go 3D to match. Generation output format depends on this decision.

Technical tradeoff: If we generate for 2D rendering, we're building throwaway work. If we generate for 3D rendering, we need the 3D renderer first. The generation pipeline and the rendering pipeline are coupled at the tile data format level.

Option Cost Risk
A. Generate for 2D now, migrate later Small for generation, Medium for migration tax later Double work: tile format changes, renderer rewrite, fog shader migration
B. Migrate renderer to 3D first, then generate Medium (24 weeks for renderer migration) Blocks generation work until renderer is ready. But generation output is correct from day one.
C. Generate for 3D from start, temporary 2D renderer Small-Medium Server generates 3D-ready data (tile + z-level + height). 2D renderer ignores z/height, just renders floor. 3D renderer replaces it when ready. No double work.

My recommendation: Option C. The server doesn't care about rendering — it generates tile grids with z-level and TileKind data. The current TileMapLayer renderer already ignores z > 0 (line 91 of tile_renderer.gd: if tile_z != GROUND_FLOOR: continue). Generate 3D-ready data, let the 2D renderer display what it can, upgrade the renderer separately. Zero throwaway work.


Q4: How detailed is Phase 2 chunk fill in v0.2?

Phase 2 takes a BlockSkeleton (from Phase 1) and fills it with actual tile data — walls, floors, doors, objects. The question is how much detail the fill produces.

Technical tradeoff: More detail means more visual richness but exponentially more generation rules. Objects (furniture, terminals, crates) need placement logic, collision, and eventually interaction — each is a mini-system.

Option Cost What It Looks Like
A. Walls + floors only Small (1 week) Rooms exist, corridors connect them. Blank rooms. Playable for pathfinding and LOS testing.
B. Walls + floors + doors + basic objects Medium (23 weeks) Rooms have doors, some furniture markers. Looks like a game level.
C. Full fill with WallBackside, object placement, condition modifiers Large (57 weeks) Complete generator output matching the full data model. Every wall tagged, every room furnished.

My recommendation: Option B for v0.2. Walls, floors, doors, and basic object placement (furniture as collision rectangles with a TileKind). This is the minimum to feel like a real space rather than a maze. WallBackside tagging (D-099) can wait — it's a data enrichment pass that adds zero visual difference.


Q5: Full Phase 1 skeleton or simplified bootstrap?

The DistrictSkeleton is a rich data structure: 4×4 block grid, multi-block reservations, corridor spines, social sites, guarantee audit, zone palettes, cultural modifiers. Implementing the full Phase 1 generator that produces a valid DistrictSkeleton satisfying all guarantee tiers (D-097) is a significant engineering effort.

Technical tradeoff: The guarantee audit system (D-097) is essentially a constraint solver — place 16 blocks such that Tier 1 guarantees are met for all inhabited districts, Tier 2 for Full-complexity, and Tier 3 conditionally. This is the hardest part of Phase 1. Without it, generation is just "random blocks." With it, generation is "every district is playable."

Option Cost What You Get
A. Hardcoded test skeleton Tiny (12 days) A single DistrictSkeleton literal in code. Proves Phase 2 works. No actual generation.
B. Simple Phase 1 — random block assignment, no guarantees Small (12 weeks) Seed-driven block zoning. No guarantee audit. Some districts may lack required spatial affordances.
C. Phase 1 with Tier 1 guarantees only Medium (34 weeks) Every inhabited district has a Social Hub, Informal Zone, and Encounter Corridor. Basic playability guaranteed.
D. Full Phase 1 with all guarantee tiers Large (57 weeks) Full D-097 compliance. Up to 13 audit checks per Full-complexity coastal urban district.

My recommendation: Option B for v0.2, with the guarantee audit as a validation pass that logs warnings rather than blocks generation. This lets us iterate on generation quality by reading audit output without blocking the pipeline. Promote to hard-fail (Option C/D) when the generator is mature enough that audit failures indicate real bugs rather than "feature not yet implemented."


Architecture Compatibility Notes

Determinism (D-010)

All generation algorithms MUST use BTreeMap (not HashMap), seeded RNG via SimRng, and no f32 in generation paths. BSP and template stamping are naturally deterministic. WFC requires careful propagation ordering to be deterministic — this is solvable but adds implementation cost. The existing codebase enforces this correctly (generator.rs uses Vec and fixed-size arrays, not HashMap).

Camera/Rendering Tension

D-148 (30° Camera3D) and D-149 (3D characters) are confirmed but the world renderer is still 2D. The generation pipeline should output data that's rendering-agnostic: tile grids with type + z-level + position. The client decides how to render. This is already the case in the data model — ObserverSnapshot sends tile data, the renderer interprets it.

Wire Format

The existing protocol sends individual tile dictionaries ({x, y, z, type, visibility}). For generated worlds with thousands of tiles, this will need chunked transmission — send a chunk's tile grid as a flat array rather than individual tile objects. This is a protocol optimization, not an architecture change. Estimate: 1 day when needed.

Chunk Streaming

chunk_streaming.rs already supports load/unload with configurable radius. For generated worlds, the load_chunk path needs a hook to trigger Phase 2 fill on first load. This is the designed extension point — the TODO is explicit in the code comments ("For v0.3+, the generator fills newly loaded chunks with terrain data"). Estimate: 12 days to add the generation callback.