Planet-down cascade workshop (3 rounds, 5 agents): layer-by-layer generation from empty world through population overlay, city planning, and street rendering. Includes consultant review by Troblum. Also commits: pre-Sprint-35 DB backup, Claude Code team-mode tmux test log (team-test.md). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
21 KiB
title, agent, workshop, round, created
| title | agent | workshop | round | created |
|---|---|---|---|---|
| Round 3 — Ozzie: Final Player Experience Review | ozzie | planet-down-cascade | 3 | 2026-05-01 |
Ozzie — Round 3: Final Player Experience Review
Last chance. Here it is.
1. Does the Complete Package Produce Worlds That Feel Inhabited?
The short answer is yes, with one condition. Let me walk through why.
The chain that works
Layer 1 gives you real geography — rivers that flow to the sea, cities that sit where they sit because of something. Layer 2 gives those cities explanations — the attractor-matching means every city was placed for a reason the world will show you if you look. Layer 3 gives each city a shape — five distinct archetypes producing five distinct navigational experiences, three components of district mix ensuring every settlement has essential human functions. Layer 4 gives you streets to walk.
The total package is: geography → civilization → city → street. Every step causes the next. The player never needs to be told why the fishing port is on the coast. The coast and the port are the same fact.
That's what this workshop produced. The causal chain is intact and automatic.
The condition
The complete package works IF the prosperity rendering is dramatic enough to communicate what's happening.
The prosperity baseline / current gap is the most powerful player experience moment in this entire system, and it happens automatically — no authored ghost city feature needed. The scenario: you walk into a District with prosperity_baseline = 0.8 (this was built to be wealthy — wide streets, large building footprints, expensive perimeter treatment) but prosperity_current = 0.21 (the economy collapsed — the corp pulled out, the workers left, the maintenance stopped). The GEOMETRY is intact and grand. The TILE CONDITION is Broken. You walk down wide streets in ruins.
THAT IS THE GAME. Right there. The gap between what a place was designed to be and what it is now — readable from the architecture.
This happens automatically from the two-field prosperity model. The rendering system has both values. The determinism rule keeps the layout locked. The economic simulation varies the condition. The player reads the gap.
But it only works if the threshold levels (0.63 / 0.43 / 0.23) produce visually dramatic differences between tiers. Intact needs to look genuinely well-maintained. Broken needs to look like ruins — not "slightly damaged." Paula's thresholds are right. The visual differentiation at each tier must be proportionally dramatic.
This is my primary requirement for the rendering spec when it's written: Broken is ruins. It is not "a bit rough."
2. founding_age → layout_mode — The Final Case
I'm going to argue this clearly because it's Q2 for Round 3 and needs a decision.
The player experience argument
Stand in two cities: a 200-year-old OrganicGrowth manufacturing town and a 15-year-old CompanyTown resource extraction facility. Same WorldTier. Same prosperity tier. Same economic role. At maximum, the current design differentiates them through prosperity_baseline offset, character tags (legacy_infrastructure vs. raw_settlement), and the political archetype's spatial pattern.
Walk through both cities. Without layout_mode variation driven by age, they have the same block structure. The character tags tell the generation system something. But the player doesn't read character tags — they navigate streets. They look at buildings. They see geometry.
Old cities should be harder to navigate. The streets evolved around older structures. The grid shifted. A road curves because it went around a building that was torn down two generations ago. Dead ends exist because a family refused to sell. The city has MEMORY built into its geometry.
Young cities should be easy to navigate but feel raw. The grid is perfect. The blocks are uniform. Nothing has had time to complicate the plan. The city feels like it was made by someone who had a drawing board and no history to work around.
This is a felt difference. The player navigates by feel. Old = organic, confusing in a good way. New = legible, cold in a productive way.
The concrete proposal
Add an irregularity_factor: f32 field to block-level generation. This determines how much the block edges deviate from perfect grid alignment.
irregularity_factor = clamp(founding_age_years / 200.0, 0.05, 1.0) × age_weight
Where age_weight varies by political archetype:
- OrganicGrowth: 0.9 — age compounds maximally with organic tendencies
- FreePort: 0.8 — multi-node grew independently; age shows
- AdminCapital: 0.5 — radial structure maintained by administrative will, but edges fray with age
- Contested: 0.7 — conflicting maintenance regimes produce irregular aging
- CompanyTown: 0.3 — corporate planning resists aging; spine is maintained
The minimum value (0.05) ensures even brand-new cities have some irregularity — construction variance, terrain response, no city is a perfect simulation artifact.
This doesn't require a new layout_mode enum value. It's a continuous parameter on existing block generation. High irregularity_factor produces blocks that deviate from their grid positions. Low irregularity_factor produces clean grid blocks. The street skeleton algorithm just varies how strictly it respects the grid.
For implementation: this feeds into the Phase 2 tile algorithm as a block-edge deviation tolerance. "Streets should be within N tiles of the ideal grid position" where N scales with irregularity_factor. Zero tolerance = perfect grid. High tolerance = streets curve around whatever stood here first.
My ask for Round 3: lock irregularity_factor as a Layer 3 block generation parameter derived from founding_age_years × archetype_age_weight. The exact formula can be tuned in implementation. The principle must be locked now.
3. Province Boundary Legibility — What the Player Needs
Province = 1 regional grid cell, ~540km × 270km on the reference body. TerritorialStatus is per Province. This is where political geography lives.
The requirement, stated precisely: The player must be able to identify Province boundaries on the planetary map without labeled borders. The boundaries must be visible as terrain features.
Why this is achievable from existing data
Province boundaries ARE watershed lines. The D8 drainage algorithm produces drainage basins. Where one basin ends and another begins IS the Province boundary. Those boundaries run along ridgelines, mountain ranges, and coastal features.
The generation already produces this information. The question is: does the planetary map render it?
The rendering requirement:
- Province boundaries = watershed/ridgeline features rendered as thin terrain variation (not thick colored borders)
- TerritorialStatus shown as Province fill color/texture (subtle; readable at a glance)
- CoreTerritory: dense settlement markers, road lines visible
- FrontierTerritory: scattered settlement markers, road lines thin toward Province edge
- ExtractiveZone: industrial marker texture or tinting, road lines heavy toward resource sites
- ContestZone: contested visual treatment (two-color, cross-hatched, or similar)
- WildernessBuffer: empty, no markers, natural terrain only
- AbandonedZone: reduced marker density, ruins indicator
The player experience payoff: the player zooms out to the planetary map and can read the political geography at a glance. They see where civilization is dense (CoreTerritory clusters), where it's exploitative (ExtractiveZone), where it's contested (ContestZone — the gradient between two territories), and where it's absent (WildernessBuffer). Then they zoom in to a city and everything they saw on the map has a physical manifestation at street level.
This is a requirement for the map UI, not for the generation algorithm. The generation produces the right data. The UI must render Province shapes as terrain features and TerritorialStatus as visual fill. If the map only shows cities as dots and roads as lines without Province context, TerritorialStatus is invisible to the player.
File this as a player experience requirement for Phase 3 map implementation.
4. Survey Data Unavailable — Finalized Three-Tier Design
The three-tier proposal is confirmed in the Round 2 notes. Here are the final design details.
The governing principle
The implant shows the player what it actually has. The player learns something from the placeholder, even in the worst case. Every tier conveys information. None of them convey "please wait."
Tier A: Partial Orbital Data (Normal Case — 3-5 second gap)
When: Heightmap BLOB is loaded, settlements haven't been placed yet.
What it shows:
- Terrain + coastlines from heightmap (already in memory)
- Known city names from
atlas_city_namesdisplayed as named points with no confirmed positions — labeled "Position survey pending" - Road routes not shown
- River courses not shown (drainage hasn't run yet)
- Status indicator: "Surface survey in progress"
The player experience: The shape of the world is visible. The names of the cities are known. But where exactly the cities sit, and what's between them, is pending. The player sees the silhouette of the civilization, not its details.
Most players never see Tier A. The background thread is fast (~136ms per Tyre's estimate). By the time the player navigates to a body's map, it's almost certainly complete. Tier A is the fallback for the edge case.
Tier B: Outdated Survey Data (Remote Frontier Worlds)
When: The body's cascade hasn't been triggered yet because no priority event fired for it — the player navigated there before news/dialogue/route scanning queued it.
What it shows:
- Old orbital survey data with explicit vintage timestamp: "Last comprehensive survey: GSY [specific in-universe year]"
- Historical settlement positions (if data exists) labeled "Unconfirmed — position data may be outdated"
- Road routes shown as dashed lines labeled "Historical — current status unknown"
- River courses from old orbital observation shown as approximations
- Status indicator: "Survey data vintage — accuracy unverified"
The player experience: The map shows a historical record, not current reality. The timestamps should be specific in-universe years. "Galactic Standard Year 3411" tells the player this survey was done before the current political situation. The player knows they're looking at a world that may have changed.
The discovery tension: the old map shows a city in a location where the generator places a ghost town. The player arrives expecting a city, finds ruins. The map wasn't wrong — the city existed. The world changed since the survey. This is the prosperity system doing its job, communicated through the gap between historical data and generated reality.
One new detail: The vintage timestamp should affect the accuracy of the positions shown. A 5-year-old survey is accurate. A 100-year-old survey shows cities where they were, not where they are (settlement drift at the attractor-matching scale is minimal, but the player doesn't know that). Create the expectation of inaccuracy even when the data happens to match.
Tier C: No Data (System Just Mentioned)
When: The Aho-Corasick scanner detected a body name in news/dialogue/documents. Generation request queued. Nothing loaded yet.
What it shows:
- Body type (planet, moon, station) from systems.db — this is always known
- System name and gate position — this is always known
- Black silhouette of the body shape (generic for body type, not specific heightmap)
- Blinking cursor
- Status: "Survey data unavailable. Orbital scan queued."
The player experience: Maximum tension. The player just heard about this place. They open the map. They know almost nothing. The scan is in progress. By the time they decide to go there — if they decide to go there — the map will have data.
Design note: The Aho-Corasick scanner should fire the Tier C display immediately when the body name is detected, not wait for the player to open the map. If the player reads a news ticker mentioning "Vellum-Reach," the scan request fires and the map is ready to show data by the time they check it. The "scan in progress" visual should be something the player can observe if they check the map immediately after encountering the name — then see it resolve if they check again a few seconds later. The discovery of the scan completing is itself a moment.
Priority Fallback Chain (Confirmed)
- Generation complete → full map
- Heightmap loaded, settlements pending → Tier A (terrain + named points, pending status)
- Only systems.db data, generation queued → Tier B (historical data if available, otherwise Tier C-like)
- Name detected, nothing loaded → Tier C (blinking cursor, scan in progress)
5. Final Flags — Speak Now
Things That Will Feel GREAT
The wealthy-district-in-ruins moment. Wide streets. Grand building footprints. Cracked tile conditions everywhere. The geometry says "this was money." The prosperity says "the money left." This happens automatically from the two-field model. It doesn't need a feature. It needs dramatic tile condition visual differentiation.
Walking into a FreePort for the first time. No spine. No hub. You think you know where the transit district is and you end up in the secondary market. The city doesn't care about making you comfortable. It grew for commerce, not for navigation. Every FreePort in the Reach will be different. Players will trade notes on how to navigate them.
The road that ends at an AbandonedZone. The road is maintained up to the Province boundary. Then the road surface degrades — the maintenance authority ran out of either money or will. The road continues into the AbandonedZone, just crumbling. The town is there. Fully generated. Dark. The player walks an unmaintained road into a ghost town that nobody scripted.
The approach to a PortFacing city from the sea. The harbor face of the city — the working front of it — visible from the approach. The Transit and Logistics districts at the water-facing edge. When the player arrives by sea, they see the city's face. When they arrive by land, they see its back. That orientation is real and it's architectural.
The 200-year-old CompanyTown. The spine is still there. The facility end is still the facility end. But two centuries of imperfect maintenance have made the streets drift. The blocks near the facility are still tight — corporate planning maintained them. The residential end of the spine has grown irregular. The city carries its history in its layout.
Things That Will Feel Wrong — Failure Modes
Pristine young cities. Even new cities need minimum irregularity (I'm proposing 0.05 floor). A brand-new corporate extraction facility that looks like a perfect simulation grid is obviously procedural. Construction variance, terrain response, logistics decisions — all of these produce at least slight irregularity. Lock the minimum.
District type indistinguishable at low prosperity. When an entire city is at Broken prosperity, every district looks like ruins. The Residential ruins look the same as the Commercial ruins look the same as the Industrial ruins. This is scatter-dependent (the stuff in the ruins tells you what kind of district it was) and I know scatter is deferred. I'm flagging it now so when scatter is designed, it explicitly addresses district-type legibility at low prosperity. The ruins should tell you what they were. This goes in the scatter spec.
Province size and player experience frequency. Province at ~540km × 270km is large. Most of a player's session will be within one Province. If they're in a CoreTerritory Province, they may never encounter a WildernessBuffer Province during a typical play session. That's fine — the TerritorialStatus system is macro-geography, not moment-to-moment navigation. But it means the intra-Province variation needs to do work. The road quality variation within a Province — MaintenanceAuthority differences, ExtractiveZone corridors, sub-settlement condition — these carry the weight of the player's micro-experience. Make sure Layer 2 road generation produces visible intra-Province variation, not just inter-Province variation.
The synthetic attractor cities. Cities placed at synthetic attractors exist because of economic decisions, not geography. A manufacturing hub that exists because a corp needed a production facility near a transit corridor — this is historically correct and common. But the player needs a reason to believe it. Without geographic explanation, the city can feel arbitrary. The SyntheticPlacementReason should be visible to the player somewhere — not as a tooltip, but as urban character. A CorpExpansion city looks like it was planned in a board meeting: efficient, corporate, grid-perfect. A PoliticalDecision city looks like it was planted by a government that needed a settlement there: administrative buildings prominent, services adequate, character thin. These character differences should emerge from the synthetic attractor reason in the same way geographic attractor type informs FoundingOrientation.
This is a new proposal: SyntheticPlacementReason should inform the default political archetype. CorpExpansion → CompanyTown. PoliticalDecision → AdminCapital. PopulationOverflow → OrganicGrowth. The geography couldn't produce an archetype for this city; the reason for its existence should.
Technically Correct But Emotionally Flat
The founding age derivation for sub-settlements: "mining camp = parent city age − 20." Mathematically reasonable. But a 180-year-old mining camp is ancient by mining camp standards. The character modifier system has legacy_infrastructure and retrofitted tags for old settlements. These need to translate visibly. An 180-year-old mining camp should look like multiple generations built on top of each other — original infrastructure, first renovation, second renovation, current state. The tags are correct; the visual manifestation needs to actually layer.
The TerritorialStatus enum: Six clean values that correctly classify every Province. But from a player experience standpoint, the most interesting state is the transition between statuses. A Province that used to be CoreTerritory and is now FrontierTerritory is very different from a Province that was always FrontierTerritory. The placed_at_generation flag captures the AbandonedZone case, but the "was CoreTerritory, now degraded" case produces FrontierTerritory — which looks the same as "always was frontier." This may matter in play. Something to watch during playtesting.
One Final Advocacy: L3-Q7
Port/station direction was deferred. I'm on record that I want it. Here is the specific player experience moment it creates:
You're standing in the Transit district of a PortFacing city. The district is at the water-facing edge of the city. You look up at the sky — specifically, toward the orbital station above. You can see it. The beanstalk, the freight platforms, whatever the setting uses for orbital access. The city was built to face its orbital. The Transit district is as close to it as the city can get. When you stand there, the architecture is pointing at the sky.
That is a screenshot moment. That is a "where am I in the universe" moment. That is what this game is about.
Paula already designed the mechanism — one query, one lookup, one edge assignment. The implementation is minimal. I'm formally requesting that L3-Q7 be included in scope before the Phase 4 orbital viewport work begins. File it now even if it's implemented later.
Summary for D-Records
Locking positions for the record:
| Item | Position |
|---|---|
irregularity_factor on block generation |
LOCK IT. Old cities deviate from grid; new cities grid-perfect. Minimum 0.05. Archetype weights as specified above. |
| Province boundaries on planetary map | PLAYER EXPERIENCE REQUIREMENT. Render as watershed/terrain features, not borders. TerritorialStatus as Province fill. Non-negotiable for Phase 3 map. |
| Survey data placeholder | THREE-TIER SYSTEM as specified. Tier A: partial orbital. Tier B: vintage data with in-universe timestamp. Tier C: blinking cursor. Priority fallback chain confirmed. |
| Broken prosperity rendering | "Broken is ruins, not slightly damaged." Lock this into the rendering spec. |
SyntheticPlacementReason → political archetype |
NEW PROPOSAL. CorpExpansion → CompanyTown. PoliticalDecision → AdminCapital. PopulationOverflow → OrganicGrowth. Resolve in Phase 3 design if not here. |
| L3-Q7 (port/station direction) | Formally requested for Phase 4 scope. Mechanism already designed by Paula. One screenshot moment. |
That's everything. The system is sound. Build it.
Round 3 complete.