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>
34 KiB
Tyre — SW1-R1b: Endgame Feasibility — Galaxy-to-Ground Pipeline Architecture
Sub-workshop 1, Round 1b — Full Pipeline Technical Assessment No v0.2 scoping. Endgame vision, cost-annotated.
The Pipeline: 8 Layers, Top to Bottom
Layer 1: Galaxy Generation (300 Systems)
Status: LARGELY BUILT.
This is the most mature layer in the entire pipeline. What exists:
| Component | Location | Status |
|---|---|---|
systems.db |
server/data/systems-schema.sql |
7 tables: star_systems, system_gates, system_history, system_economy, system_factions, system_culture, historical_events |
| Wiki pages | wiki/star-systems/GJ-*/index.md |
300+ authored pages with supply dependency, faction notes, silence topics, narrative hooks, calibration notes |
| Star map generation algorithm | docs/design/star-map-plan.md |
6-phase algorithm: sector seeding → Prim's spanning tree → hub/loop/spur augmentation → topology classification → aperture assignment → validation |
| Generation script | tooling/generate-star-map.py |
Python script producing star-map.json + sector d2 diagrams |
| Gate topology data | system_gates table |
aperture_count, gate_connections, gate_topology (hub/junction/loop_member/dead_end/spur_end), hop_distance_from_gateway |
| Cultural data | system_culture, system_history tables |
founding culture, cultural corridor, heritage persistence, ambient anxiety, silence threshold |
What the runtime generator needs from this layer:
The game server reads systems.db at startup and builds an in-memory graph. Each system node carries its profile (tier, setting types, cultural corridors, economic base, faction presence). When the player travels to a system for the first time, the generator receives the system profile as input and begins cascading downward.
Cost annotation: Galaxy generation is a content authoring problem, not an engineering problem. The database schema exists. The wiki pipeline exists. The engineering work is loading systems.db into the Rust server at startup and building a queryable graph — cheap (days). The ongoing cost is authoring/reviewing the 300 wiki entries — that's Miri/Mellanie/Paula territory.
What's technically hard: Nothing. This layer is fundamentally a read-only dataset with graph queries.
What's technically cheap: Everything. BFS pathfinding, neighbor lookup, attribute filtering — all standard graph operations on 300 nodes. Fits comfortably in memory (~1-2MB structured data).
Layer 2: Location Profiles (Per-Planet/Station/Moon)
Status: NOT BUILT — the biggest structural gap.
The systems.db records that "GJ-699 has 2 habitable planets, 0 inhabited, no gas giant." But there are no individual planet/station/moon records. The jump from "system has 2 habitable planets" to "here is a specific planet with biome X, atmosphere Y, population Z" is entirely undefined.
What needs to exist:
SystemProfile (from systems.db)
└─ LocationProfile[] (new — per planet/station/moon/orbital)
├─ location_type: Planet | Station | Moon | Orbital | AsteroidBase
├─ physical: gravity, atmosphere, biome_zones[], terrain_type, hydrosphere_pct
├─ settlement: population, economic_role, founding_age, settlement_pattern
├─ cultural: heritage_blend (from system corridor + founding culture + local drift)
├─ infrastructure: spaceport_class, transit_connections, district_count
└─ districts[] → feeds into Layer 6
Cost annotation:
| Approach | Cost | Quality |
|---|---|---|
| Derived from system profile (algorithmic) | Medium (2-3 weeks) | Good — each system's attributes constrain what planets look like. A core-sector, wave-1, economic-tier-5 system doesn't have a frontier mining colony. |
| Hand-authored per inhabited planet | Very large (months of authoring for 300+ locations) | Excellent — every planet is unique. But doesn't scale. |
| Hybrid: authored for narrative-notable, generated for the rest | Medium-Large (3-4 weeks engineering + ongoing authoring) | Best of both — ~30-40 hand-crafted locations, ~260 generated with authored review passes. |
My assessment: The hybrid approach is the right answer and probably the only sane one. systems.db already tags narrative_notable systems. Those get hand-authored location profiles. The rest derive their profile from the system's attributes using a generation grammar:
economic_base: manufacturing+inhabited_planet_count: 2→ primary planet is industrial + orbital station, secondary planet is residential/agriculturalgate_topology: hub+economic_tier: 4+→ mandatory horizon station with large commercial districtcultural_corridor: tide+settlement_wave: wave_3→ heritage blend weights favor Tide-root architecture
What's technically hard: The generation grammar itself. Mapping ~30 system attributes to coherent planet profiles requires careful constraint satisfaction. The grammar must not produce contradictions (an "economic_tier: 1" system shouldn't generate a bustling metropolis). Authoring and validating the grammar rules is iterative.
What's technically cheap: The data structures. Adding a locations table to systems.db and a LocationProfile Rust struct is straightforward.
Layer 3: Planetary Topography
Status: NOT BUILT — but the solution space is well-understood.
Once we know a planet has biome zones, terrain type, and hydrosphere percentage, we need a surface. The question is: how detailed?
The key insight: we don't need a real planet. The player arrives at a specific location (gate → horizon station → transit → destination). They don't see the whole planet. They see a district, maybe neighboring districts. Planetary topography is a context that constrains district generation — "this district is on a coastal plain" or "this district is in a mountain valley" — not a renderable globe.
Three approaches with very different costs:
| Approach | Cost | What You Get |
|---|---|---|
| A. Abstract topography tags — each location gets tagged (coastal/mountain/desert/plains/tundra/oceanic/orbital). Tags constrain district generation SettingType + terrain palette. No actual terrain data. | Cheap (days) | Sufficient for district-level generation. "Coastal urban district" or "mountain wilderness district." The player never flies over the planet — they arrive at a point and explore outward. |
| B. Noise-based regional heightmap — per-location Perlin/simplex noise heightmap at ~1km resolution. River placement via hydraulic erosion simulation. Biome assignment from elevation + latitude + moisture. | Medium (3-5 weeks) | A terrain you can zoom into. District placement becomes geographically motivated (cities on rivers, ports on coasts). The player's minimap can show regional context. |
| C. Full planetary generation — plate tectonics, erosion simulation, climate modeling, ocean currents. Dwarf Fortress / Caves of Qud territory. | Very large (months) | A planet that makes geological sense. Beautiful, scientifically plausible, and almost entirely invisible to the player at ground level. |
My assessment: Approach A for the immediate pipeline, with B as the enrichment that makes the minimap/world-map feel real. Here's why:
The camera is at 30° (D-148), looking at a 512×512 district. The player sees maybe 50-100 visual tiles at a time. Planetary topography below district granularity is literally invisible at this camera angle. What the player does see is whether they're in a desert, by the ocean, or in mountains — and that's communicated by the district's SettingType and palette, not by a heightmap.
Approach B becomes valuable when you have a world map or minimap showing the region — "there's a mountain range to the west, a river delta to the south." That's a navigation/exploration feature, not a generation prerequisite.
RetroTerrain reference: Their approach (noise → heightmap → vertex colors → shader-based terrain painting) maps to Approach B. It's clean and well-understood. BUT: they crash at 1000×1000 because they don't chunk. We'd need to add chunking (which we already have infrastructure for). The terrain shader technique is directly applicable to our wilderness SettingType rendering.
What's technically hard in Approach B: Hydraulic erosion simulation (realistic river placement). Well-studied algorithm but computationally expensive — doing it at world-gen time (offline) is fine, doing it at runtime is not. Pre-generation with seed caching solves this.
What's technically cheap: Noise-based heightmaps. FastNoiseLite in Godot, the noise crate in Rust. Biome assignment from elevation thresholds is trivial.
Layer 4: Inbound Gateways — What's Around Arrival Points
Status: PARTIALLY DESIGNED (D-093, D-095), NOT BUILT.
When the player arrives in a new system, they come through a horizon gate. D-095 defines the lore (alien-built gate infrastructure, aperture counts, the entire transit model). D-093 defines the gate cluster spatial layout within a district.
What needs generation:
- The horizon station itself — a Station SettingType district. The gate cluster occupies one or more blocks. Institutional presence (Commission inspection, Institute monitoring) varies by system importance.
- The transit connection — how the player gets from the horizon station to their destination planet/station. This is either a skip-travel mechanic or a playable transit sequence (ship/shuttle interior as a MobileChunk per D-108).
- The first impression — what the player sees when they step off the gate platform. This is a spatial design problem, not just a generation problem.
Cost annotation:
| Component | Cost | Notes |
|---|---|---|
| Horizon station as a Station district | Included in Station SettingType — no separate cost | It's just a Station district with gate-specific blocks (gate cluster, customs, transit hub) |
| Transit skip-travel | Cheap (days) | Loading screen with diegetic framing — "transit in progress." The MobileChunk vessel interior is optional enrichment. |
| MobileChunk transit (playable voyage) | Medium (2-3 weeks per D-108) | Vessel interior as a social pressure cooker. High-value content but not a generation prerequisite. |
| "First impression" spatial design | Cheap as generation, hard as design | The generator places the gate cluster at a specific block. What's visible from that block's entrance is a function of the district layout. Guarantee system (D-097) can ensure an Encounter Corridor is visible from the gate entry point. |
What's technically hard: Making the first impression good. The generator can produce a syntactically correct horizon station, but the spatial experience of stepping through a gate into a new system is a design problem — it requires the guarantee system to enforce experiential constraints ("from the gate entry, the player must see at least one zone transition within 30 tiles").
What's technically cheap: The generation itself. A horizon station is a Station district. Gate blocks are template-stamped special rooms.
Layer 5: Content Spidering — LOD/Simulation-Tier Generation
Status: ARCHITECTURE DESIGNED (D-026), STREAMING BUILT, GENERATION HOOKS NOT BUILT.
This is where the simulation tier system (D-026) meets the generation pipeline. The four tiers:
| Tier | What Exists | What's Generated | When |
|---|---|---|---|
| Ungenerated | Nothing. System exists in systems.db graph. |
— | Player has never visited or approached. |
| State-saved | LocationProfile (Layer 2) + DistrictSkeleton (Phase 1). No tile data. ~1-2KB per district skeleton. | Phase 1 skeleton generated on first "approach" (player enters the system, or a connected system). | On system entry — background generation of neighbor systems' skeletons. |
| Background | Phase 1 skeleton + Phase 2 fill for districts near the player's destination. Tile data exists. NPC state machines run at 1/game-minute. | Phase 2 chunk fill triggered on district entry. | On transit approach — background generation during travel loading. |
| Active | Full sim. All chunks loaded within streaming radius. Full NPC simulation at 10 tps. | Already generated — just loaded from cache. | On arrival — chunk streaming activates from cache/generated data. |
The generation cascade:
Player enters system (gate transit)
├─ If system is Ungenerated:
│ ├─ Generate LocationProfiles for all bodies in system (Layer 2)
│ ├─ Generate Phase 1 skeletons for player's destination + immediate neighbors
│ └─ Background-generate Phase 1 for remaining districts (async)
├─ If system is State-saved:
│ ├─ Load existing skeletons from save
│ └─ Generate Phase 2 for destination district (if not already filled)
└─ Player arrives at district:
├─ Load/generate Phase 2 chunks within streaming radius
├─ Activate NPCs in loaded chunks (D-026 tier promotion)
└─ Chunk streaming takes over (existing system)
Cost annotation:
| Component | Cost | Notes |
|---|---|---|
| Generation trigger hooks in chunk_streaming.rs | Cheap (1-2 days) | The TODO is already in the code: "For v0.3+, the generator fills newly loaded chunks." Just need to call the Phase 2 generator from load_chunk. |
| Phase 1 background generation (async) | Medium (1-2 weeks) | Rust async task spawning for background generation. bevy_ecs tasks or tokio. Must not block the simulation tick. |
| Phase 2 on-demand generation | Medium (tied to Phase 2 algorithm cost) | The Phase 2 algorithm itself determines this cost. BSP + template stamping is fast enough for on-demand (~5-50ms per chunk). WFC might be too slow for on-demand. |
| Save/load of generated data | Medium (1-2 weeks) | DistrictSkeleton is already Serialize/Deserialize. Chunk tile data needs a compact format (MessagePack per D-020). Save file includes generated-but-not-original-seed data for districts the player has visited. |
| Cache management | Medium (1-2 weeks) | LRU cache for generated chunks. Memory budget per D-026. Eviction writes to save file. |
What's technically hard: The async generation pipeline. Generating a Phase 1 skeleton (constraint satisfaction with guarantee audit) cannot run on the simulation thread — it needs to run in background and deliver results when ready. Rust's async ecosystem handles this well (tokio::spawn or bevy_ecs async tasks), but integrating it with the ECS tick loop requires care.
What's technically cheap: The tier promotion/demotion. D-026's simulation tiers are about component presence on entities. bevy_ecs dynamic component add/remove is the designed mechanism. Promoting a State-saved NPC to Active means attaching simulation components — this is literally what bevy_ecs is built for.
Layer 6: Settlement Generation — Cities on Bones
Status: NOT BUILT — this is the missing bridge between topography and districts.
Given a LocationProfile (planet with population X, economic base Y, biome zones Z), where do settlements go? How many districts? How are they connected?
What needs generation:
- Settlement placement — where on the location surface do cities/towns/outposts appear? Constrained by topography (Approach A: tags, Approach B: heightmap).
- District count and type distribution — a population-500K industrial city has different district composition than a population-2K research outpost.
- Road/transit network — how districts connect to each other and to the horizon station.
- District boundaries — the
DistrictBoundariesstub in generator.rs. Adjacent districts must have compatible edges.
CityCrafter3D reference: Their pipeline is directly applicable at this level:
- Grid-based city layout (maps to our Grid DistrictLayoutMode)
- Noise-based district assignment (residential/commercial/industrial) — we'd substitute our richer
DistrictTypeenum - Block sizing with multi-block reservations (1x1, 2x1, 2x2) — maps directly to our 4×4 block grid with
MultiBlockReservation - Road network generation between blocks — their
generate_dynamic_roads_asyncwith road merging and intersection generation is a clean reference - Building density per district type — their density_settings pattern (min/max buildings, spacing, border margin) maps to our
density_pcton BlockSkeleton
Key difference from CityCrafter3D: They do everything client-side in GDScript. We do generation server-side in Rust. But the algorithm transfers: grid placement → district assignment → road network → building population.
Cost annotation:
| Component | Cost | Notes |
|---|---|---|
| Settlement placement from location profile | Cheap-Medium (1-2 weeks) | Rule-based: population → district count table. Economic base → district type distribution. Topography tag → valid SettingTypes. |
| District adjacency and road network | Medium (2-3 weeks) | Graph generation: districts as nodes, roads as edges. Must respect topography (no road through a mountain). Must ensure connectivity. |
| District boundary stitching | Hard (2-3 weeks) | Two adjacent districts must have matching access points at their shared edge. This is a constraint propagation problem — generate district A, then district B must respect A's boundary. |
| Transit network (inter-district) | Medium (1-2 weeks) | Higher-level than roads — shuttle routes, rail lines, vehicle paths. Can be abstract (graph edges with travel time) initially, rendered later. |
What's technically hard: District boundary stitching. When generating district A, you must leave "ports" on its edges where district B can connect. If district B is Organic layout (D-096) while district A is Grid, the boundary gets architecturally interesting. The previous Generator Architecture Workshop outputs don't fully solve this — the DistrictBoundaries type is still a String stub.
What's technically cheap: Settlement placement and district count. This is a lookup table with some noise. Population 500K → 8-12 districts. Economic base: manufacturing → 3 industrial, 2 commercial, 2 residential, 1 transit, 1 mixed.
Layer 7: District → Building (Phase 1 + Phase 2)
Status: DATA MODEL BUILT (generator.rs), ALGORITHM NOT BUILT.
This is the layer my Round 1 assessment covered. The data model is the most mature part: DistrictSkeleton with 4×4 block grid, BlockSkeleton, MultiBlockReservation, FloorZone, ZonePalette, ChunkMutations, WallBackside, SocialSitePlacement, TriangleAssignment.
Phase 1 (Skeleton) — the hard part:
- Assign 16 blocks with zoning, era, density
- Place multi-block reservations (skyscrapers, parks, terminals)
- Carve corridor spines
- Place social sites with triangle assignments
- Run guarantee audit (D-097: up to 13 checks)
Phase 2 (Chunk Fill) — the visible part:
- BSP room subdivision within blocks
- Template stamping for social site rooms
- Corridor carving between rooms
- Door placement
- Object/furniture placement
- WallBackside tagging (D-099)
- Tile palette application from ZonePalette
Cost annotations from Round 1 still apply. Adding context from the full pipeline:
- Phase 1 with full guarantee audit: 3-5 weeks (the guarantee system is a constraint solver)
- Phase 2 BSP + templates: 2-3 weeks
- Phase 2 with full WallBackside + object placement: 4-6 weeks
- Z-level generation (MultiBlockReservation floors): 2-3 weeks additional
- Organic layout mode (D-096 rotation/offset): 1-2 weeks additional
Layer 8: 2D → 3D Rendering
Status: ASSESSED IN ROUND 1 — recommendation stands.
Generate rendering-agnostic data (tile grids with type + z-level + position). The current 2D TileMapLayer renderer filters z > 0 and displays what it can. The 3D renderer replaces it when ready. Zero throwaway work.
The GridMapLayer reference (vendor) confirms the 2D-tile-data → 3D-GridMap bridge is a clean, well-understood pattern. Their approach: TileMapLayer data → bake to custom data layers → GridMap reads baked data. We'd skip the bake step and go directly from server tile data → GridMap placement.
Questions for the Product Owner
Q1: How does Layer 2 (Location Profiles) get populated?
This is the biggest structural gap. We have 300 systems in systems.db with rich attributes, but no individual planet/station records. Every layer below depends on this.
Technical tradeoff: Authoring 300+ location profiles by hand produces the best quality but doesn't scale. Pure generation from system attributes is fast but may produce bland or contradictory locations. The grammar that maps system attributes → location profiles is the critical intellectual work.
| Option | Cost | What You Get |
|---|---|---|
| A. Pure generation — system attributes → location profile via rules | Medium (2-3 weeks for grammar + generation code) | Every system gets locations automatically. Quality depends entirely on grammar quality. Bland results if grammar is shallow. |
| B. Hybrid — generated baseline + hand-authored overrides for narrative-notable systems | Medium-Large (3-4 weeks engineering + ongoing authoring) | Generated locations everywhere, hand-crafted for the ~30-40 systems that matter most. The generation grammar is validated against hand-authored examples. |
| C. Template library — 20-30 location templates, selected by system attribute matching | Medium (2-3 weeks) | Faster than per-system authoring, less variety than generation. A "manufacturing hub" template applied to 40 systems produces 40 similar-but-seeded locations. |
My assessment: B is the right answer. The systems.db already tags narrative_notable. Those get authored profiles (Miri territory). The rest use the generation grammar. The grammar rules are the critical design work — they encode "what kind of planet does a wave-3, economic-tier-2, manufacturing system in the deep frontier have?" The engineering to execute those rules is straightforward.
Cost: Medium for engineering, ongoing for authoring.
Q2: Planetary topography — how deep do we go?
The player arrives at a specific point and explores outward. They never see the whole planet. But they might see a world map. And the topography constrains what districts can exist.
Technical tradeoff: Abstract tags are cheap and sufficient for district generation. Real terrain makes the world map meaningful and enables terrain-aware features (rivers, elevation, weather). The ROI inflection point is "does the player ever look at a map bigger than one district?"
| Option | Cost | What You Get |
|---|---|---|
| A. Abstract tags only (coastal/mountain/plains/etc.) | Cheap (days of engineering, authored per location) | Districts know their terrain context. No world map beyond "you are here on planet X." Sufficient for ground-level gameplay. |
| B. Regional noise heightmap (~1km resolution) | Medium (3-5 weeks) | Terrain the player can see on a minimap. Rivers, coastlines, mountain ranges visible at region scale. Districts placed on geographically motivated positions. |
| C. Full planetary generation (tectonics + erosion + climate) | Very Large (months) | Geologically plausible planets. Beautiful, scientifically interesting, and almost invisible at 30° camera / district scale. |
My assessment: A to start, B as enrichment. The 30° camera at ground level cannot distinguish "noise heightmap coastline" from "tagged as coastal." The value of B is the world map experience — showing the player that districts exist in a geographically coherent space. If the world map is important to the endgame experience (and I suspect it is — it's the NMS/Stellaris "I can see my whole territory" feeling), then B is worth doing. C is pure gold-plating at our scale.
The RetroTerrain technique (noise → heightmap → vertex colors → shader) is directly applicable for B. We'd chunk it (they don't) and run it server-side (they run client-side). The shader work for terrain painting is reusable across all wilderness/rural SettingTypes.
Q3: Does the generation pipeline run offline, on-demand, or hybrid?
There's a fundamental architecture choice: does the game pre-generate the entire galaxy when you start a new game, or does it generate on-demand as you explore?
Technical tradeoff: Pre-generation means loading screens but consistent quality. On-demand means seamless exploration but risk of generation hitches. Hybrid means different layers pre-generate at different times.
| Option | Cost | Player Experience |
|---|---|---|
| A. Full pre-generation at new-game | Engineering: cheap. Time: expensive. Generating 300 systems × N locations × M districts takes minutes to hours depending on depth. | Long "generating world" screen. But: everything is ready when you start. No hitches. Consistent. The Dwarf Fortress model. |
| B. Full on-demand | Engineering: medium-hard (async pipeline, cache management, save integration) | Seamless exploration. But: first visit to any location has a generation pause. Risk of visible pop-in if generation is slow. |
| C. Hybrid — Layer 1-2 pre-generated, Layer 3-7 on-demand | Engineering: medium | Short "generating world" screen (Layer 1-2 takes seconds — it's table lookups and grammar rules). Districts generate as you approach. The NMS model. |
| D. Progressive — Layer 1 pre-gen, Layer 2 on first system visit, Layer 3-7 on district approach | Engineering: medium (the tier cascade described in Layer 5) | Minimal upfront wait. Each system visit triggers location generation. Each district approach triggers tile generation. The "fog of generation" parallels the fog of war. |
My assessment: D (progressive) is the correct architecture and also the most elegant. It maps exactly onto D-026 simulation tiers:
- New game:
systems.dbloaded. All 300 systems exist as graph nodes. Cost: milliseconds. - Player's home system: LocationProfiles generated at game start. Starting district Phase 1 + Phase 2 completed. Cost: seconds.
- Transit to new system: LocationProfiles generated during transit loading (the MobileChunk voyage or skip-travel screen). Phase 1 skeletons for destination and neighbors generated async. Cost: hidden behind transit.
- Arrive at district: Phase 2 fill on demand. Chunk streaming activates. Cost: <100ms per chunk if BSP is the algorithm.
This means generation latency is always hidden behind a diegetic transition (gate transit, shuttle ride, walking to a new district). The player never sees a "generating..." screen after the initial game start.
What's technically hard: The async pipeline coordination. Multiple layers generating concurrently for different systems/districts, writing to a shared cache, with the simulation tick continuing. Rust's ownership model actually helps here — each generation task owns its input data and produces an output that gets atomically inserted.
What's technically cheap: The progressive trigger logic. It's an if-chain: "is this system generated? no → generate it. is this district filled? no → fill it."
Q4: How do 5 zone types share one pipeline?
The Round 1 flag was correct: "each SettingType is essentially a separate generator." But the reframe asks: what does a shared pipeline look like?
Technical tradeoff: The more the pipeline shares between zone types, the cheaper each new zone is to add — but the less distinctive each zone feels. The less they share, the more each zone feels unique — but the implementation cost multiplies per zone type.
What CAN be shared across all zone types:
| Shared Component | Applies To | Notes |
|---|---|---|
| Phase 1 skeleton structure (4×4 blocks, zoning, social sites) | All types | Block grid works for Station (modules), Urban (city blocks), Agricultural (plots), Wilderness (terrain sectors). The block meaning changes but the structure doesn't. |
| Guarantee audit system (D-097) | All inhabited types | Tier 1 guarantees (Social Hub, Informal Zone, Encounter Corridor) apply to ALL inhabited districts regardless of SettingType. |
| ZonePalette + modifier system | All types | Base palette per SettingType, modifiers apply identically. |
| ChunkMutations / DamageOverlay | All types | Post-generation modification is setting-agnostic. |
| Social site placement | All inhabited types | Social sites go in blocks. The block's SettingType constrains which site templates are valid, but the placement mechanism is shared. |
| Chunk streaming | All types | Already setting-agnostic. |
What MUST differ per zone type:
| Per-Zone Component | Why It Differs | Cost Per Zone |
|---|---|---|
| Phase 2 fill algorithm | Station = rooms + corridors. Urban = lots + buildings + streets. Wilderness = terrain + vegetation + paths. | 2-4 weeks per zone type |
| Tile palette data | Different tile types, materials, visual vocabulary. | 1-2 weeks per zone type (asset-dominated) |
| Block semantics | Station block = module cluster. Urban block = city block with lot subdivision. Agricultural block = field + farmstead. | 1 week per zone type (definition + templates) |
| Height/terrain treatment | Station = flat interior. Urban = flat with building heights. Wilderness = terrain heightmap. | 1-3 weeks per zone type |
My assessment: The pipeline IS shared at Phase 1 level. The divergence happens at Phase 2. This means:
- Phase 1 is one implementation that works for all 5 zone types (the skeleton structure is zone-agnostic)
- Phase 2 needs one fill algorithm per zone type (or per zone type family — Station and Urban can share a lot of room/corridor logic)
- The total cost for 5 zone types is: Phase 1 (once, 3-5 weeks) + Phase 2 per zone (2-4 weeks × 5, minus shared code between similar types)
Zone type families that share Phase 2 code:
| Family | Members | Shared Fill Logic |
|---|---|---|
| Interior | Station, Orbital, Specialized | BSP room subdivision, corridor carving, door placement. Station is the base; others add templates. |
| Urban | Urban, Industrial, Maritime (port) | Lot subdivision, building placement, street network. CityCrafter3D patterns apply. |
| Natural | Wilderness, Agricultural, Water | Terrain heightmap, vegetation/crop placement, path networks. RetroTerrain patterns apply. |
| Transitional | Transitional | Hybrid of adjacent zone families — boundary-stitching problem. |
With 3 families instead of 8 independent generators, the Phase 2 cost drops from 5 × 3 weeks to 3 families × 3 weeks + per-type customization.
Total endgame cost for all zone types: Phase 1 (4 weeks) + 3 Phase 2 families (9 weeks) + per-type customization (3-4 weeks) = ~16-17 weeks of generation engineering.
Q5: What does the "content spidering" look like at the galaxy boundary?
When the player is at Van Maanen's Star and looks at the star map, they see 300 system nodes. Some are nearby (2 hops), some are distant (20+ hops). What exists at each distance?
Technical tradeoff: Generating too far ahead wastes resources on content the player may never visit. Generating too little ahead means visible loading when the player decides to travel. The sweet spot depends on how fast the player can traverse the gate network.
| Distance from Player | What Should Exist | Generation Trigger |
|---|---|---|
| Current system | Full: LocationProfiles + Phase 1 skeletons + Phase 2 for current district + chunk streaming active | At game start / on arrival |
| Adjacent systems (1 hop) | LocationProfiles + Phase 1 skeletons for likely destinations | On system entry (background async) |
| 2-3 hops | LocationProfiles only (planet count, economic role, population) | On system entry (cheap, batch) |
| 4+ hops | systems.db graph data only (name, sector, topology, economic tier) |
Already loaded at game start |
My assessment: This is the NMS model: the star map shows metadata for distant systems (name, type, faction, economic tier — all from systems.db), generates profiles for nearby systems, and fully generates districts only for the current location and immediate neighbors.
Cost: Cheap. The generation cascade is the progressive model from Q3. The only engineering work is the async pipeline that pre-generates adjacent systems during idle time. The systems.db data is already loaded and query-ready.
What's technically hard: Cache invalidation when the player returns to a previously-visited system. The generated districts must be saved and reloaded identically (MessagePack serialization per D-020). This is the save/load integration problem — not conceptually hard, but must be correct.
What's technically cheap: The star map UI showing systems.db metadata for all 300 systems. It's a read-only overlay on the graph. The data already exists and is query-ready.
Feasibility Summary: The Full Pipeline
| Layer | Status | Cost to Complete | Difficulty |
|---|---|---|---|
| 1. Galaxy (300 systems) | Built | Days (Rust loader for systems.db) | Easy |
| 2. Location profiles | Gap | 3-4 weeks (grammar + generation + hybrid authoring) | Medium — the grammar is the hard design work |
| 3. Planetary topography | Not built | Days (tags) to 3-5 weeks (heightmaps) | Easy to Medium |
| 4. Inbound gateways | Partially designed | Included in Station SettingType + 1-2 days for gate-specific templates | Easy |
| 5. Content spidering | Architecture exists | 2-3 weeks (async pipeline + cache + save integration) | Medium — async coordination |
| 6. Settlement generation | Not built | 3-5 weeks (placement + roads + boundary stitching) | Medium-Hard — boundary stitching is the challenge |
| 7. District → building | Data model built | 6-10 weeks (Phase 1 + Phase 2 for 3 zone families) | Medium-Hard — guarantee audit is a constraint solver |
| 8. 2D → 3D rendering | Assessed | 2-4 weeks | Medium — ongoing client work |
Total engineering estimate for the full endgame pipeline: ~20-30 weeks of dedicated generation engineering, depending on topography depth (A vs B) and zone type count at full fidelity.
The critical path is Layer 2 → Layer 6 → Layer 7. Everything else is either built (Layer 1), cheap (Layer 3A, Layer 4), or parallelizable (Layer 5, Layer 8). The three critical layers are sequential: you can't generate settlements (6) without location profiles (2), and you can't generate districts (7) without settlement placement (6).
The good news: The data model for Layer 7 is already built (579 lines). The infrastructure for Layer 1 is already built (300 wiki pages, systems.db, star map generation). The streaming system for Layer 5 is already built. The pipeline has bookends — the top and bottom are solid. The middle needs to be filled.