Galaxy Generation¶
Status: 🚧 Partial — Generation is real but the live path is the bang Docker sidecar (BangImportService), NOT the in-process GalaxyGenerator this doc describes — clusters/sectors/warps/stations/planets/formations import c … · ⚠︎ contains code↔spec divergence (impl audit 2026-06-16)
Where it runs: this pipeline executes in the external
sw2102-bangsidecar; the gameserver'sBangImportServicevalidates and persists the snapshot it produces. Read the phases, formulas, andservices/gameserver/...citations below as the canonical generation design that sw2102-bang implements and the gameserver validates against — not as in-gameserver code. See../OPERATIONS/bang-integration.md.
Purpose¶
The galaxy-generation pipeline builds the universe from a few configuration parameters: a Galaxy metadata row, then per-Region content (zones, clusters, sectors, warps, stations, planets, resource seeding). It is run at game initialization (Central Nexus + Terran Space) and again every time a player subscribes to a region (player-owned region creation). The pipeline is deterministic given a seed, idempotent at the region level, and re-runnable without leaving partial state.
Inputs¶
The generator reads:
- A configuration dict (max_sectors, density values, zone profile, optional seed).
- The Region row to populate (created separately by the regional service or admin tool).
- For player-owned regions: the owner's User row, region size tier (purchased), aesthetic preferences.
- The sw2102-bang dataset (precomputed sector layouts, planet seeds, port templates) — fed in as JSON for reproducible previews.
The system fires on:
- POST /api/v1/admin/galaxy/generate — initial galaxy create (Central Nexus + Terran Space).
- POST /api/v1/admin/regions/{id}/generate-content — create or re-create a region's content.
- Subscription activation — the regional service triggers content generation for a new player region.
- The sw2102-bang CLI — generates static dataset files that the gameserver imports.
Process¶
Step 1 — Galaxy metadata¶
generate_galaxy(name, config) creates exactly one Galaxy row:
- max_sectors — total capacity across all regions (default 10,000).
- statistics — counters initialized to zero (updated as regions populate).
- density — default station/planet/warp percentages.
Step 2 — Regions¶
Three region types with distinct profiles:
| Region type | Sectors | Zones | Station density | Planet density | Warp tunnel × |
|---|---|---|---|---|---|
| Central Nexus | 5,000 | 1 (Expanse) | 5% | 10% | 0.3 |
| Terran Space | 300 | 3 (Fed/Border/Frontier) | 15% | 25% | 1.0 |
| Player-owned | 800–1,200 (Standard tier; ±20% from 1,000) | 3 (default) | 15% | 25% | 1.0 |
Step 3 — Zones¶
_generate_zones_for_region(region) partitions sector numbers into security zones:
- Central Nexus → single
EXPANSEzone (sectors 1–5000), policing 3, danger 6. - Other regions → three zones split by sector number:
FEDERATION— first 33% — policing 9, danger 1.BORDER— middle 34% — policing 5, danger 4.FRONTIER— last 33% — policing 2, danger 8.
Step 4 — Clusters¶
_create_clusters_for_region(region, n) partitions the region's sector budget:
- Central Nexus → 20 clusters (~250 sectors each).
- Terran Space → 6 clusters (~50 sectors each).
- Player regions →
max(2, total_sectors // 50).
Each cluster carries:
- A type drawn from a region-appropriate set (Standard, Resource Rich, Population Center, Trade Hub, Military Zone, Frontier Outpost, Contested, Special Interest).
- Variable size (±33% from average).
- Optional nebula property (~20% of clusters) — defines the nebula type and coverage applied to member sectors.
Step 5 — Sectors¶
_create_sectors_for_cluster(cluster, region, zones) creates Sector rows incrementally:
- Sector numbers are sequential within the region. They are not globally unique — the canonical identifier for a sector is the compound tuple
(Region.id, Cluster.id, sector_number). Region A's sector 47 and Region B's sector 47 are distinct. - 85% generated as
STANDARD; 15% chosen from cluster's allowed special types (NEBULA,ASTEROID_FIELD,BLACK_HOLE,RADIATION_ZONE,WARP_STORM). - 3D coordinates from
_generate_cluster_coordinates. - Both
zone_id(sector-number range within the region) andcluster_id(creation grouping) set. - Resource seeds, hazard level, radiation level derived per type.
Step 6 — Warp graph¶
_create_warps_between_sectors() builds adjacency:
- Every sector connects to 2–4 neighbors (proximity-based).
- Warp cost = 1 turn for standard sector pairs.
- Stability factor accounts for hazard levels.
_create_warp_tunnels_enhanced(num_sectors, density_multiplier) adds long-distance tunnels:
- Density multiplier: 0.3 for Central Nexus, 1.0 elsewhere.
- Mix of one-way and bidirectional. Ambient one-way rates per ADR-0034: 5% of sector_warps rows and 15% of WarpTunnel rows are one-way (is_bidirectional = false). Of those one-ways, ~80% are marked (UI shows directional glyph) and ~20% are latent (is_latent = true; reveals via Warp Jumper scan). Formation stamping overrides — a BACKDOOR always produces a one-way regardless of base rate.
- Starter-cluster invariant: the starter cluster — sectors 1..fedspaceSize (default 10) — carries no natural one-ways (is_bidirectional = true for every warp into or out of these sectors). This is the narrow 10-sector pocket immediately around the Capital, not the broader Federation Zone (which spans 33% of the region). Player-built warp gates to a starter-cluster destination are still permitted because gates are a separate mechanism and not subject to the natural-warp anti-cheese rule.
- 10–20% of clusters intentionally left unconnected via tunnels (reachable only by Warp Jumper quantum jump — see ../FEATURES/galaxy/sectors.md#quantum-jump-warp-jumper for the multi-phase bearing/scan/commit loop).
Tunnel-type assignment. The generator produces only two tunnel types (see ../DATA_MODELS/galaxy.md#type-enum-warp_tunnel_type):
NATURAL— the default for proximity-based and long-distance tunnels generated above.ARTIFICIAL— extra engineered connections placed among the firstfedspaceSizesectors of the region (default 10 — the starter cluster, distinct from the broader Federation Zone) to ensure the starter cluster stays densely interconnected regardless of random tunnel layout. These havecreated_by_player_id = NULL(player-built gates also useARTIFICIALbut with the column populated; the predicate distinguishes them).
Spatial layout for low sectors. _generate_cluster_coordinates anchors the starter cluster (sectors 1..fedspaceSize) at the region's coordinate origin, then cascades subsequent clusters outward in roughly sector-number order so distance-from-origin tracks sector-number magnitude. This makes the starter cluster both numerically and physically compact for new-player navigation.
Step 7 — Stations & planets¶
_populate_sectors_with_ports(probability, region_id):
- Iterates sectors; rolls against probability.
- On hit, creates a Station of a region/zone-appropriate class (0–11).
- Initializes commodities JSONB with capacity/quantity/base_price/production_rate per the class trading pattern.
- Creates initial MarketPrice rows (see market-pricing.md).
_populate_sectors_with_planets(probability, region_id):
- Similar; creates Planet rows.
- Habitability, resource richness, type weighted by region/zone.
Step 8 — Capital Sector¶
Every region has exactly one Capital Sector — the welcome hub of the region, where the population-hub planet sits and pioneer migration contracts are issued. The Capital Sector's sector_number is stored on Region.capital_sector_number.
Capital placement:
- Terran Space (operator-run vanilla starter): Capital fixed at sector 1. This is the only region in the universe with a guaranteed, canonical "everyone knows where this is" landmark — first-time arrivals to the universe land here.
- Player-owned regions: Capital randomly placed within the Federation Zone (i.e., random(1, floor(0.33 × total_sectors))). New arrivals to a player region cannot predict where the Capital is — they have to explore the Federation Zone to find it. This is the discovery mystique that justifies the per-region scoped numbering: knowing how to find your home region's Capital does not help you find a foreign region's Capital.
- Central Nexus: Capital anchored in the Gateway Plaza cluster (sector range 2551–2800). The "Central Nexus Starport Prime" station sits in this cluster; it's the canonical landing spot for players arriving at the Nexus from a player region.
_ensure_region_capital_sector(region) populates the Capital Sector with:
- A population hub planet (
is_population_hub = True). - A
StationClass.CLASS_0station — the welcome hub — housing the regional Pioneer Office (the only place pioneer migration contracts are issued). Inventory bundle includes pioneer-contract slots at 30–80 cr per pioneer; standard commodities are present in low quantities for orientation trades. - Public, well-policed, non-destructible.
The sector immediately following the Capital (capital_sector_number + 1, if available) gets a StationClass.CLASS_1 station with the canonical mining-pattern inventory (buys ore + organics, sells equipment) — the basic-trading counterpart to the welcome hub. Inside the starter cluster, one warp from the Capital. Gives new players (and explorers in foreign regions) their first commerce step after finding the Capital.
Both stations are guaranteed by the seeder; they don't depend on the generic _choose_port_class_for_sector roll.
Step 9 — SpaceDocks (two per region)¶
_create_spacedocks_for_region(region) places two SpaceDock stations per region. SpaceDocks are a separate station kind from the Class 0–11 trading enumeration — they share the Station table but carry a distinguishing is_spacedock=True flag (or equivalent kind discriminator) instead of consuming a class slot. Both per-region SpaceDocks have identical service portfolios — is_quest_hub=True, is_faction_headquarters=True, services include genesis_dealer, mine_dealer, drone_shop, refining_facility, luxury_amenities, with the canonical service price table. (Class 11 in the trading enumeration is reserved for the Premium Tech Specialist trading pattern per ../FEATURES/economy/trading.md#class-11-premium-tech-specialist — exotic_technology + luxury_goods at +25% both directions — and is unrelated to SpaceDock infrastructure.)
| SpaceDock | Placement | Zone | Role |
|---|---|---|---|
| #1 — starter-cluster anchor | capital_sector_number + 9 (or nearest available, inside the starter cluster) |
Federation | Late-game logistics close to the Capital; players don't need to leave the starter cluster for high-end services. |
| #2 — frontier anchor | total_sectors − 5 (or nearest available, in the Frontier zone) |
Frontier | Rewards traversal into dangerous territory; gives Border + Frontier zones an economic landmark; mirror of #1 at the far end of the region. |
Both SpaceDocks are public, non-destructible, and carry the full service portfolio. Differentiation by location (not by content) gives Sector traversal economic stakes without forcing players to backtrack for specific services.
The two SpaceDocks are also a counterpart to the TradeDock system — see ../FEATURES/economy/tradedock-shipyard.md — which lives outside the Class-0..11 enumeration and offers a different service mix.
Step 9.5 — TradeDock seeding (Phase 10.5)¶
TradeDocks are seeded here, after generic stations and planets exist (Step 7) and before the anchored Capital + SpaceDock guarantees (Steps 8–9 / Phase 11). They are the galaxy's sole seed population of rare strategic shipyards — only 4–8 across the entire galaxy — and they never spawn dynamically; the only post-launch addition path is region-funded construction (see ../FEATURES/economy/tradedock-shipyard.md#region-funded-construction). TradeDocks sit outside the Class-0..11 trading enumeration; placed rows carry is_tradedock = true with a tradedock_tier of tier_a or tier_b. Only Tier-A TradeDocks can build Warp Jumper and Carrier hulls (see ../FEATURES/economy/docking-slips.md).
Per-region quota — the seeder places TradeDocks per region by region kind:
| Region kind | TradeDock count | Tier allocation |
|---|---|---|
| Central Nexus | 3 | 1 Tier-A (in an EXPANSE-zone commerce cluster — e.g. Gateway Plaza) + 2 Tier-B |
| Terran Space | 1 | 1 Tier-A |
| Player-owned region, ≥ 500 sectors | 0 or 1 | If present, Tier-B by default (Tier-A only on operator override) |
| Player-owned region, < 500 sectors | 0 | n/a |
Placement rules within a region:
- Prefer sectors in
EXPANSE-class clusters (established high-traffic trade corridors); fall back to the most populousCLUSTER-class cluster. - Place only at sectors with at least 2 inbound warps, so the dock is never isolated.
- Never place in starter-cluster sectors (
1..fedspaceSize) — that pocket belongs to the Capital, Class-1 station, and SpaceDock #1; TradeDocks belong to the broader trade network. - Never place in
FRONTIER-zone sectors — there are no TradeDocks past the Federation/Border boundary; Frontier-only regions reach a TradeDock cross-region via the Nexus. - Avoid collisions with sectors already targeted for Step 8–9 anchors (the Capital welcome planet and the two SpaceDocks).
Galaxy-wide invariants (validated in Step 10 / Phase 13):
- 4–8 TradeDocks total across the galaxy at generation completion.
- ≥ 1 Tier-A TradeDock somewhere in the galaxy (the Warp-Jumper-capable shipyard guarantee — without it, the player-built warp-gate loop is unreachable).
- ≥ 2 TradeDocks reachable from any starter-cluster sector via the warp-gate network, so a new player has a viable route to TradeDock services within their first session.
Step 8 (Capital) and Step 9 (SpaceDocks) run after this step so their anchored placements stay aware of which sectors are already TradeDock-occupied; the placement order is generic stations + planets → TradeDocks → Capital + Class-1 + SpaceDocks → faction influence.
Step 10 — Statistics roll-up¶
_update_galaxy_statistics(galaxy) recomputes the galaxy-level counters (total_sectors, station_count, planet_count, warp_tunnel_count).
sw2102-bang integration¶
The sw2102-bang repo (TypeScript) generates a deterministic dataset for offline previews:
- bigbang.ts — orchestrator (mirrors the steps above).
- graph.ts — warp graph generation.
- nebulae.ts, planets.ts, ports.ts, special.ts — content seeding.
- serialize.ts / db-writer.ts — output as JSON or directly into the gameserver DB.
The gameserver can either generate live (above pipeline) or import from a bang dataset. When importing: 1. Read JSON manifest. 2. Bulk-insert sectors, warps, stations, planets within a single transaction per region. 3. Run the same starter-sector and SpaceDock guards so any imported data is normalized.
Outputs / state changes¶
Per generation run:
- Galaxy row inserted (or stats updated).
- Region rows touched (one populated, others untouched in incremental runs).
- Zone, Cluster, Sector rows inserted for the region.
- sector_warps adjacency rows.
- WarpTunnel rows.
- Station, Planet, Resource, Market, MarketPrice rows.
Events emitted:
- region_generation_started (admin feed).
- region_generation_progress (per-step ticks).
- region_generation_completed — final summary.
- galaxy_updated — global broadcast for player-facing stats.
Invariants¶
- Every region has exactly one Capital Sector (
Region.capital_sector_number) with a population hub planet and a Class-0 station. - Every region has exactly two SpaceDocks: one anchored near the Capital (
capital_sector_number + 9or fallback inside the starter cluster) and one at the frontier end (total_sectors − 5or fallback inside the Frontier Zone). - The galaxy holds 4–8 TradeDocks total, with ≥ 1 Tier-A and ≥ 2 reachable from any starter-cluster sector via the warp-gate network (Step 9.5 / Phase 10.5). No TradeDock sits in a starter-cluster or Frontier-zone sector.
- Sector numbers are unique within a region.
- Every sector has at least one warp neighbor (no orphaned sectors).
Galaxy.statistics.total_sectorsmatchesSUM(Region.total_sectors)after every run.- No partial region state on failure — generation transactions roll back cleanly.
- Re-running region content generation on an already-populated region either is a no-op (idempotency check) or fully replaces (admin "force" flag); never mixed.
- Player-owned regions cannot reach into Central Nexus or Terran Space at generation time — connectivity goes through the warp gateway model only.
Failure modes¶
| Mode | Target handling |
|---|---|
| Generation fails mid-region | Single transaction per region; rollback to pre-run state. Admin notified. |
Sector budget exhausted (would exceed Galaxy.max_sectors) |
Pre-flight check rejects before mutation. |
| Idempotent re-run | If Region.is_populated, skip unless force=true. |
| Bang dataset corrupt / version mismatch | Import refuses; admin sees a structured error with the bang version expected. |
| Random seed not provided | Use a server-generated UUID seed; record it on Region.generation_seed for reproducibility. |
| Starter sector already exists with conflicting state | _ensure_region_starter_sector upserts: existing planet/station preserved, missing pieces filled in. |
| Player-region size out of bounds for tier | Clamped to the subscription tier's range (Standard tier 800–1200; higher tiers 📐 Design-only). Admin override extends bounds with audit log. |
| Concurrent generation requests on same region | Region-level advisory lock; second request returns 409 Conflict. |
Source map¶
| Concern | Path (target) |
|---|---|
| Generator | services/gameserver/src/services/galaxy_service.py:GalaxyGenerator |
| Galaxy / Region / Zone / Cluster / Sector models | services/gameserver/src/models/galaxy.py, region.py, zone.py, cluster.py, sector.py |
| Warp tunnel model | services/gameserver/src/models/warp_tunnel.py |
| Station / planet seed | _populate_sectors_with_ports, _populate_sectors_with_planets |
| Starter sector + SpaceDock | _ensure_region_starter_sector, _create_spacedock_for_region |
| TradeDock seeding (Step 9.5 / Phase 10.5) | services/gameserver/src/services/galaxy_service.py:_seed_tradedocks |
| Market price backfill | services/gameserver/src/services/galaxy_service.py:backfill_market_prices |
| Nexus generation alternative | services/gameserver/src/services/nexus_generation_service.py |
| Admin generation API | services/gameserver/src/api/routes/admin.py, admin_comprehensive.py |
| Bang generator | sw2102-bang/src/bigbang.ts (CLI: bigbang) |
| Bang DB writer | sw2102-bang/src/db-writer.ts |
Related¶
- DATA_MODELS:
../DATA_MODELS/galaxy.md,../DATA_MODELS/economy.md. - FEATURES:
../FEATURES/galaxy/generation.md,../FEATURES/galaxy/sectors.md. - SYSTEMS: market-pricing.md, genesis-deploy.md, regional-governance.md.
- ARCHITECTURE:
../ARCHITECTURE/multi-regional.md.