diff --git a/.gitignore b/.gitignore
index d6dd2f3..cac5382 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,3 +17,4 @@ vite.config.js
vite.config.d.ts
.playwright-mcp/
.spacetime-dev/
+target/
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..b69c772
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "rust-analyzer.linkedProjects": ["apps/game/Cargo.toml"]
+}
diff --git a/AGENTS.md b/AGENTS.md
index 8eb421a..7082189 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -1,6 +1,6 @@
# VOID::NAV — Monorepo Root
-Open-world space exploration RPG. Windward Horizon in space with FTL-style combat.
+Single-player open-world space exploration RPG. Windward Horizon in space with FTL-style combat.
## Directory Map
diff --git a/README.md b/README.md
index d6bfb80..deb9a9f 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,12 @@
# VOID::NAV
-**An open-world space exploration RPG** — trade, quest, fight, or simply drift and enjoy the ambiance. Inspired by the charm and freedom of Windward Horizon, set in a procedurally generated galaxy with FTL-style tactical combat.
+**A single-player open-world space exploration RPG** — trade, quest, fight, or simply drift and enjoy the ambiance. Inspired by the charm and freedom of Windward Horizon, set in a procedurally generated galaxy with FTL-style tactical combat.
You are a young, unaffiliated captain with an entire galaxy open for exploration. Every campaign features a unique, procedurally generated sector map. Trade goods between stations, take on quests for various factions, mine asteroid belts, or simply cruise and enjoy the void. Prefer a quieter life? You can simply sail the stars.
Combat is **FTL-style tactical resource management** — no dogfighting or direct piloting. Click a hostile, your ship auto-engages, and you manage reactor power between Weapons / Shields / Engines / Auxiliary. The skill is in *what* you power and *when*, not how fast you click.
-VOID::NAV is a pnpm workspace monorepo for the game website, living design docs, browser game shell, and SpacetimeDB backend module.
+VOID::NAV is a pnpm workspace monorepo for the game website, living design docs, browser game shell, and SpacetimeDB backend module. The architecture supports optional co-op servers in the future, but the core experience is designed as a solo adventure.
## Core Pillars
@@ -17,7 +17,7 @@ VOID::NAV is a pnpm workspace monorepo for the game website, living design docs,
| **FTL-Style Combat** | Tactical power management (not action). Auto-engage with reactor allocation decisions |
| **Ship Customization** | Build the ship that suits your style — tough juggernaut, nimble scout, or cargo hauler |
| **Dynamic World Impact** | Faction leaders, world events, and player actions shape the galaxy without firing a shot |
-| **Solo or Co-op** | Brave the void alone or crew with friends. Built with co-op in mind. |
+| **Solo Adventure** | A personal galaxy to explore at your own pace. The architecture supports optional co-op servers later. |
## Layout
diff --git a/apps/AGENTS.md b/apps/AGENTS.md
index bec7e1d..e3c8364 100644
--- a/apps/AGENTS.md
+++ b/apps/AGENTS.md
@@ -5,7 +5,7 @@ Three Vite + React apps, each independently buildable and dev-serveable.
| App | Port | Package | Description |
|-----|------|---------|-------------|
| `docs` | 5173 | `@void-nav/docs` | Living design docs, 16 doc pages, 14 interactive demos, game-slice prototype |
-| `game` | 5175 | `@void-nav/game` | Playable game client connected to SpacetimeDB backend |
+| `game` | 5175 | `@void-nav/game` | Playable single-player game client connected to SpacetimeDB backend |
| `site` | 5174 | `@void-nav/site` | Public landing page / marketing site |
## Shared
diff --git a/apps/docs/AGENTS.md b/apps/docs/AGENTS.md
index 463753a..6511f57 100644
--- a/apps/docs/AGENTS.md
+++ b/apps/docs/AGENTS.md
@@ -3,7 +3,7 @@
Package: `@void-nav/docs`
Port: `http://localhost:5173/docs`
-This is the **design documentation hub** and interactive prototype playground. It contains the full GDD as 16 browsable pages, 14 interactive demos validating individual game subsystems, and a complete game-slice prototype implementing the full MVP loop in-browser with localStorage.
+This is the **design documentation hub** and interactive prototype playground for a single-player space exploration RPG. It contains the full GDD as 16 browsable pages, 14 interactive demos validating individual game subsystems, and a complete game-slice prototype implementing the full MVP loop in-browser with localStorage.
## Structure
diff --git a/apps/docs/public/docs/gap-analysis.md b/apps/docs/public/docs/gap-analysis.md
index 1c4732c..b21f543 100644
--- a/apps/docs/public/docs/gap-analysis.md
+++ b/apps/docs/public/docs/gap-analysis.md
@@ -1,4 +1,4 @@
-# Gap Analysis — EVE-Inspired Multiplayer Prototype GDD
+# Gap Analysis — VOID::NAV Single-Player Space RPG
**Date:** 2026-05-24
**Last Updated:** 2026-05-25 (Session 7)
@@ -24,9 +24,9 @@ Comprehensive fresh gap analysis identified 20 missing specs. The 3 critical blo
| 🟠 Important | Module Activation & Cycle System | Not started |
| 🟠 Important | Damage Types & Resistances | Not started |
| 🟠 Important | Stargate Mechanics | **Resolved** — covered in Travel & Warp tab |
-| 🟠 Important | Multiplayer Combat (Phase 13) | Not started |
+| 🟠 Important | Multiplayer Combat (co-op) | Not started |
| 🟠 Important | Scanning / Exploration System | Not started |
-| 🟠 Important | Fleet System | Not started |
+| 🟠 Important | Fleet System (co-op) | Not started |
| 🟡 Nice-to-have | Contract system | Not started |
| 🟡 Nice-to-have | Cloaking/stealth | Not started |
| 🟡 Nice-to-have | Server admin/GM tools | Not started |
diff --git a/apps/docs/public/docs/vertical-slice-evaluation.md b/apps/docs/public/docs/vertical-slice-evaluation.md
index 47a5c08..e4e5378 100644
--- a/apps/docs/public/docs/vertical-slice-evaluation.md
+++ b/apps/docs/public/docs/vertical-slice-evaluation.md
@@ -1,7 +1,7 @@
# Vertical Slice Evaluation
**Date:** 2026-05-31
-**Scope:** Compare the current playable game implementation against the MVP Loop Slice demo and the Era 1 roadmap goals.
+**Scope:** Compare the current playable game implementation against the MVP Loop Slice demo and the core single-player roadmap goals.
---
@@ -20,9 +20,9 @@ In practical terms:
## Baselines Compared
-### Intended Era 1 Vertical Slice
+### Intended Core Game Vertical Slice
-The roadmap defines Era 1 as a single-player proof of concept using local SpacetimeDB from day one. The minimum full loop is:
+The roadmap defines the core game as a single-player adventure using local SpacetimeDB from day one. The minimum full loop is:
1. Boot the game and connect to local SpacetimeDB.
2. Render a single star system with station and asteroids.
@@ -260,7 +260,7 @@ The fitting demo validates module constraints and UI feel. The game app needs mo
**Status:** Refining prototyped; manufacturing not in slice runtime.
-The slice supports ore-to-mineral refining. Manufacturing remains a later implementation gap for the full Era 1 economy loop.
+The slice supports ore-to-mineral refining. Manufacturing remains a later implementation gap for the full economy loop.
### Phase 6 - NPC Economy Sim
diff --git a/apps/docs/src/data/nav.ts b/apps/docs/src/data/nav.ts
index b523c70..d5026d2 100644
--- a/apps/docs/src/data/nav.ts
+++ b/apps/docs/src/data/nav.ts
@@ -21,7 +21,7 @@ export const navSections: NavSection[] = [
{ path: "/docs/gameplay", icon: "◉", label: "Gameplay Loop" },
{ path: "/docs/ships", icon: "◇", label: "Ships & Fitting" },
{ path: "/docs/economy", icon: "⇄", label: "Economy & Industry" },
- { path: "/docs/social", icon: "✧", label: "Progression & Social" },
+ { path: "/docs/social", icon: "✧", label: "Progression & World" },
{ path: "/docs/ship-ai", icon: "◈", label: "Ship AI - Zora" },
{ path: "/docs/roadmap", icon: "⊞", label: "Roadmap" },
{ path: "/docs/todo", icon: "⊡", label: "Implementation Status" },
diff --git a/apps/docs/src/pages/docs/AgentsPage.tsx b/apps/docs/src/pages/docs/AgentsPage.tsx
index c4d4b20..b2098de 100644
--- a/apps/docs/src/pages/docs/AgentsPage.tsx
+++ b/apps/docs/src/pages/docs/AgentsPage.tsx
@@ -517,7 +517,7 @@ export function AgentsPage() {
{ type: 'pirate_combat_tick', strat: 'fixed', interval: '1s', max: '1 per engaged NPC', desc: 'Executes NPC behavior template per tick: orbit/approach/kite/flee. Applies damage to target, regenerates shields/armor. Only runs for NPCs in combat state.' },
{ type: 'pirate_loot_drop', strat: 'one-shot', interval: '0s', max: '∞', desc: 'Generates loot and bounty from destroyed NPC. Rolls loot table, awards ISK bounty to top damage contributor, creates wreck with items.' },
{ type: 'loot_decay', strat: 'fixed', interval: '120s', max: '500', desc: 'Counts down loot container lifetime. On expiry, removes container row and frees the slot.' },
- { type: 'pvp_session_timer', strat: 'one-shot', interval: 'varies', max: '∞', desc: 'Tracks PvP engagement timers (combat flags, weapons timers). Fires on expiry to clear flags.' },
+ { type: 'pvp_session_timer', strat: 'one-shot', interval: 'varies', max: '∞', desc: 'Tracks PvP engagement timers on co-op servers (combat flags, weapons timers). Fires on expiry to clear flags.' },
].map((row, i) => (
{row.type}
@@ -568,7 +568,7 @@ export function AgentsPage() {
{ type: 'building_decay', strat: 'fixed', interval: '60s', max: '∞', desc: 'Reduces building condition per tick (0.1–2% depending on material). At 0%, marks for demolition.' },
{ type: 'fuel_consumption', strat: 'fixed', interval: '300s', max: '1 per structure', desc: 'Deducts fuel from powered structures. If fuel hits 0, disables structure services.' },
{ type: 'production_cycle', strat: 'fixed', interval: 'varies', max: '1 per structure', desc: 'Advances manufacturing jobs. On completion, moves output to structure inventory.' },
- { type: 'reinforcement_timer', strat: 'one-shot', interval: '24–72h', max: '1 per structure', desc: 'Delays structure destruction in PvP. Allows owners time to defend. Fires → structure becomes vulnerable.' },
+ { type: 'reinforcement_timer', strat: 'one-shot', interval: '24–72h', max: '1 per structure', desc: 'Delays structure destruction on co-op servers. Allows owners time to defend. Fires → structure becomes vulnerable.' },
].map((row, i) => (
{row.type}
@@ -597,7 +597,7 @@ export function AgentsPage() {
{ type: 'npc_trade_route', strat: 'conditional', interval: '600s', max: '50', desc: 'Evaluates NPC trade route viability. Condition: market activity > threshold AND at least one player docked. Moves goods between stations.' },
{ type: 'market_price_adjust', strat: 'fixed', interval: '300s', max: '1 per item_type', desc: 'Ticks NPC demand pressure algorithm: updates flow_ema, recomputes demand_pressure, applies idle decay. See Economy → NPC Pricing tab for full algorithm spec.' },
{ type: 'bounty_pool_refresh', strat: 'fixed', interval: '3600s', max: '1', desc: 'Refreshes the global bounty pool based on faction military budgets. Allocates bounty value to active threats.' },
- { type: 'insurance_payout', strat: 'one-shot', interval: '30–120s', max: '∞', desc: 'Delays ship insurance payout. Fires once, credits ISK to player, deletes self. Prevents instant-PvP-profit loops.' },
+ { type: 'insurance_payout', strat: 'one-shot', interval: '30–120s', max: '∞', desc: 'Delays ship insurance payout. Fires once, credits ISK to player, deletes self. Prevents instant-profit loops on co-op servers.' },
].map((row, i) => (
{row.type}
diff --git a/apps/docs/src/pages/docs/ArchitecturePage.tsx b/apps/docs/src/pages/docs/ArchitecturePage.tsx
index 7b9ba52..51c1330 100644
--- a/apps/docs/src/pages/docs/ArchitecturePage.tsx
+++ b/apps/docs/src/pages/docs/ArchitecturePage.tsx
@@ -8,7 +8,7 @@ export function ArchitecturePage() {
Key principle: SpacetimeDB owns
authoritative game state. Everything else derives from it. There is no localStorage — persistence is always through
- SpacetimeDB, even in the single-player Era 1 where SpacetimeDB runs locally.
+ SpacetimeDB, even in the single-player core game where SpacetimeDB runs locally.
{/* Architecture diagram */}
@@ -175,7 +175,7 @@ export function ArchitecturePage() {
{ scene: 'Mid-warp', server: 'Warp completes normally. Ship arrives at destination.', reconnect: 'Ship at destination. No interruption to warp.', impact: 'None.' },
{ scene: 'Docked at station', server: 'No risk. Station is safe. Player remains docked.', reconnect: 'Restored to station. All panels and inventory intact.', impact: 'None.' },
{ scene: 'Mid-market order', server: 'If reducer was received, order is placed. If not, no order.', reconnect: 'Check market panel for order state. ISK and inventory reflect server truth.', impact: 'At worst, order was not placed. No double-spend possible (atomic reducers).' },
- { scene: 'Mid-combat (PvP)', server: 'Ship continues with last power allocation. Enemy continues attacking.', reconnect: 'Same as PvE: ship may be destroyed. No special protection for PvP disconnect.', impact: 'Ship may be destroyed. Disconnecting during PvP carries the same risk as staying.' },
+ { scene: 'Mid-combat (PvP — co-op)', server: 'Ship continues with last power allocation. Enemy continues attacking.', reconnect: 'Same as PvE: ship may be destroyed. No special protection for PvP disconnect.', impact: 'Ship may be destroyed. Disconnecting during PvP carries the same risk as staying.' },
].map((row, i) => (
{row.scene}
@@ -205,22 +205,22 @@ export function ArchitecturePage() {
If all 10 attempts fail (5+ minutes of no connection):
- {'Era 1 (local SpacetimeDB):'}
+ {'Core game (local SpacetimeDB):'}
{' This should never happen. If it does, it\'s a bug. Show error screen with "restart game" button. Local SpacetimeDB state is intact.'}
- {'Era 2 (remote SpacetimeDB):'}
+ {'Co-op server (remote SpacetimeDB):'}
{' Show "Connection lost" screen with two options: [Retry Now] (immediate reconnect attempt) and [Return to Login]. Ship persists on server. No data lost.'}
- {'The ship never vanishes on disconnect. It stays in the world, obeying server rules. This is intentional \u2014 disconnecting to escape PvP is not allowed.'}
+ {'The ship never vanishes on disconnect. It stays in the world, obeying server rules. This is intentional — on co-op servers, disconnecting to escape combat is not allowed.'}
- Anti-exploit: combat disconnect. Players who disconnect during PvP combat receive no special protection.
+ Anti-exploit: combat disconnect. On co-op servers, players who disconnect during PvP combat receive no special protection.
Their ship remains in the world, continuing to fight with last-known power allocation. If destroyed, normal death
penalties apply (loot drop, insurance). This prevents "combat logging" as an escape mechanism. Zora may send
a message on reconnect: "I sustained damage while you were away. Shields at 40%. The enemy disengaged."
@@ -289,9 +289,9 @@ export function ArchitecturePage() {
- Era 1 vs Era 2 persistence: Both eras use SpacetimeDB exclusively — there is no localStorage.
- In Era 1, SpacetimeDB runs locally on the player's machine. "Persistence" means the local database file survives browser restart.
- In Era 2, SpacetimeDB runs on a server. Persistence is permanent and shared. The only difference is where the database
+ Persistence model: The core game and co-op servers both use SpacetimeDB exclusively — there is no localStorage.
+ In the core game, SpacetimeDB runs locally on the player's machine. "Persistence" means the local database file survives browser restart.
+ On co-op servers, SpacetimeDB runs on a remote server. Persistence is permanent and shared. The only difference is where the database
process runs; the persistence model is identical.
@@ -447,7 +447,7 @@ export function ArchitecturePage() {
{ area: 'Reduced Motion', req: 'Respect prefers-reduced-motion. No animations that could cause discomfort.', impl: 'CSS media query: disable particle effects, smooth scrolling, and HUD animations. Red Alert uses static red border instead of pulsing. Power allocation bars snap instead of animating. Mining cycle uses progress bar, not spinning animation.', phase: '7' },
{ area: 'Contrast', req: 'All text meets WCAG AA contrast ratio (4.5:1 for normal text, 3:1 for large text).', impl: 'Var(--fg) on var(--bg) already exceeds 7:1. Dim text (--fg-dim) checked to meet 4.5:1. Interactive elements have visible focus indicators with 3:1 contrast against adjacent colors. Red Alert border is high-contrast red (#ff0000) against dark background.', phase: '7' },
{ area: 'Cognitive Load', req: 'Information density is manageable. Players can hide complexity.', impl: 'Collapsible panels. Summary view vs. detail view toggle. Zora provides guided assistance. Red Alert collapses non-essential HUD elements. Tutorial hints can be disabled. Settings persist per player.', phase: '7' },
- { area: 'Input Timing', req: 'No time-critical inputs required for core gameplay. Combat is manageable at any APM.', impl: "Power allocation has no per-second requirements — the skill is in choosing distribution, not speed. Mining is click-and-wait. Market orders don't expire mid-interaction. Only exception: PvP combat in Era 2, which is inherently competitive.", phase: '7' },
+ { area: 'Input Timing', req: 'No time-critical inputs required for core gameplay. Combat is manageable at any APM.', impl: "Power allocation has no per-second requirements — the skill is in choosing distribution, not speed. Mining is click-and-wait. Market orders don't expire mid-interaction. Only exception: PvP combat on co-op servers, which is inherently competitive.", phase: '7' },
].map((row, i) => (
{row.area}
@@ -461,7 +461,7 @@ export function ArchitecturePage() {
- PvP accessibility note: PvP combat in Era 2 inherently involves time pressure — rerouting power,
+ PvP accessibility note: PvP combat on co-op servers inherently involves time pressure — rerouting power,
selecting targets, and reacting to damage. These cannot be fully de-timed without removing the competitive element.
Players with motor impairments can (1) stay in high-sec where PvP is punished, (2) focus on PvE, industry,
and market gameplay which are fully accessible, or (3) use fleet roles that require less real-time input
@@ -469,7 +469,7 @@ export function ArchitecturePage() {
- Testing: Accessibility validation is part of Gate 4 (Era 1 Complete). The acceptance test is:
+ Testing: Accessibility validation is part of Gate 4 (Core Game Complete). The acceptance test is:
(1) navigate all panels via keyboard only, (2) complete a mining-sell cycle with screen reader enabled,
(3) verify all color-coded info has secondary indicators in grayscale. Automated: run axe-core or Lighthouse
accessibility audit as part of CI.
diff --git a/apps/docs/src/pages/docs/BackendPage.tsx b/apps/docs/src/pages/docs/BackendPage.tsx
index ce396a3..c2cdcca 100644
--- a/apps/docs/src/pages/docs/BackendPage.tsx
+++ b/apps/docs/src/pages/docs/BackendPage.tsx
@@ -344,7 +344,7 @@ export function BackendPage() {
Core (sec +0.8 → +1.0): Center of galaxy map. Dense, high station count, trade hub. Starter systems live here. 1 region.
Deep Null (sec −0.5 → −1.0): Tips and gaps. Very sparse. Wormhole connections only. Elite content. 1 region.
@@ -374,7 +374,7 @@ export function BackendPage() {
Phase 1 — Minimum Spanning Tree: Compute MST over all systems using Euclidean distance. This guarantees full connectivity with minimum total gate length. Phase 2 — Intra-constellation edges: For each constellation, add 1–2 extra gates between systems within the constellation. This creates local redundancy and multiple routes within a cluster.
- Phase 3 — Inter-region choke points: Identify 2–4 systems on region boundaries. Add gates between them to create known choke points. These become strategic PvP locations.
+ Phase 3 — Inter-region choke points: Identify 2–4 systems on region boundaries. Add gates between them to create known choke points with tougher NPCs. Phase 4 — Shortcut edges: Add 10–15% extra gates weighted toward connecting high-sec systems to create trade route variety. Never add shortcuts into/out of Deep Null (wormhole-only access preserved). Validation: After generation, verify: (a) graph is fully connected (BFS from any node reaches all), (b) no system has <2 gates, (c) Deep Null systems have no direct high-sec gates, (d) average path length <15 jumps for MVP galaxy.
@@ -608,7 +608,7 @@ export function BackendPage() {
],
},
{
- name: 'Social & PvP',
+ name: 'Social & Co-op',
color: 'var(--red)',
desc: 'Chat, bounty, kill feed, waypoints, and missions.',
tables: [
diff --git a/apps/docs/src/pages/docs/DemoGalleryPage.tsx b/apps/docs/src/pages/docs/DemoGalleryPage.tsx
index 943541c..1e4eec7 100644
--- a/apps/docs/src/pages/docs/DemoGalleryPage.tsx
+++ b/apps/docs/src/pages/docs/DemoGalleryPage.tsx
@@ -8,17 +8,17 @@ export function DemoGalleryPage() {
name: 'MVP Loop Slice',
color: 'var(--accent)',
icon: '◎',
- validates: 'Connected Era 1 horizontal slice: undock, navigate to belt, mine ore, dock, refine, fit, sell on market, and optionally run NPC combat. Uses a shared localStorage slice session across integrated demos.',
- limitations: 'Local browser persistence only. Deterministic fake economy and combat payouts. No backend, multiplayer authority, or SpacetimeDB integration.',
- docPage: 'Gameplay → Era 1 MVP Loop',
+ validates: 'Connected horizontal slice: undock, navigate to belt, mine ore, dock, refine, fit, sell on market, and optionally run NPC combat. Uses a shared localStorage slice session across integrated demos.',
+ limitations: 'Local browser persistence only. Deterministic fake economy and combat payouts. No backend or SpacetimeDB integration.',
+ docPage: 'Gameplay → MVP Loop',
},
{
id: 'starmap',
- name: 'Star Map (Era 2 Galaxy Map)',
+ name: 'Star Map (Galaxy Map)',
color: 'var(--accent)',
icon: '🗺',
- validates: 'Multi-system galaxy view with system connections, faction territories, click-to-navigate interaction, warp routes. Validates the Era 2 Galaxy Map (region/constellation/system hierarchy). Each system has celestial body rendering.',
- limitations: 'This is the Era 2 Galaxy Map, NOT the Era 1 System Map. No single-system detail view showing belts, stations, and orbital bodies at navigation scale. Era 1 needs a separate System Map demo. Static galaxy topology — systems don\'t shift. No faction territory animation. World events shown as static icons, not animated effects. No waypoint creation or route planning integration.',
+ validates: 'Multi-system galaxy view with system connections, faction territories, click-to-navigate interaction, warp routes. Validates the Galaxy Map (region/constellation/system hierarchy). Each system has celestial body rendering.',
+ limitations: 'This is the Galaxy Map, NOT the System Map. No single-system detail view showing belts, stations, and orbital bodies at navigation scale. A separate System Map demo is needed. Static galaxy topology — systems don\'t shift. No faction territory animation. World events shown as static icons, not animated effects. No waypoint creation or route planning integration.',
docPage: 'Overview → HUD & View Mode Architecture → Map Mode',
},
{
@@ -45,7 +45,7 @@ export function DemoGalleryPage() {
color: 'var(--red)',
icon: '⚔',
validates: 'FTL-style reactor power allocation (weapons/shields/engines/aux), target selection, auto-engage, module auto-cycling, capacitor drain, shield/armor/hull layers.',
- limitations: 'Solo PvE only — no PvP. Single opponent at a time. No subsystem targeting. No weapon type differentiation (all deal generic damage). Power allocation is instant, not gradual.',
+ limitations: 'Solo PvE only. Single opponent at a time. No subsystem targeting. No weapon type differentiation (all deal generic damage). Power allocation is instant, not gradual.',
docPage: 'Gameplay → Combat Model',
},
{
@@ -129,7 +129,7 @@ export function DemoGalleryPage() {
Thirteen interactive demos that validate specific game systems. Each demo is a standalone prototype
focused on one aspect of the design unless opened through the MVP Loop Slice. They use fake data and simulated APIs — not connected to
SpacetimeDB or a real server. Use these to evaluate feel and UX, not performance or scale.
- Note: The Star Map demo covers the Era 2 Galaxy Map. A separate Era 1 System Map demo (single-system
+ Note: The Star Map demo covers the Galaxy Map. A separate System Map demo (single-system
navigation view) is still needed before Phase 1.
diff --git a/apps/docs/src/pages/docs/EconomyPage.tsx b/apps/docs/src/pages/docs/EconomyPage.tsx
index 17b8ecb..7d25e2f 100644
--- a/apps/docs/src/pages/docs/EconomyPage.tsx
+++ b/apps/docs/src/pages/docs/EconomyPage.tsx
@@ -394,7 +394,7 @@ export function EconomyPage() {
Margin Accounts & Positions
- Era 2 feature. Players can open long and short positions
+ Future co-op feature. Players on shared servers could open long and short positions
on commodity contracts using a margin account. Margin requires collateral (ISK + assets). Maintenance margin enforced —
if position moves against the player beyond the margin, the position is force-liquidated.
This adds speculative depth for advanced traders.
@@ -428,7 +428,7 @@ export function EconomyPage() {
- Priority callout: Economy feel + social/multiplayer feel are the two most
+ Priority callout: Economy feel is one of the most
important things to get right. If the economy doesn't feel rewarding and dynamic, the game
falls flat regardless of how good combat or graphics are.
diff --git a/apps/docs/src/pages/docs/GameplayPage.tsx b/apps/docs/src/pages/docs/GameplayPage.tsx
index bbdbf34..721fed0 100644
--- a/apps/docs/src/pages/docs/GameplayPage.tsx
+++ b/apps/docs/src/pages/docs/GameplayPage.tsx
@@ -10,7 +10,7 @@ export function GameplayPage() {
The core loop: explore → trade → quest → fight (FTL-style) → upgrade → sail deeper.
Every system feeds into the others. Trade earns ISK for upgrades. Quests unlock faction influence. Combat protects trade routes.
- Exploration reveals new opportunities. Steps 1–7 work in Era 1 (single-player). Multiplayer features arrive in Era 2.
+ Exploration reveals new opportunities. Steps 1–8 work as a single-player adventure. Co-op is an optional future enhancement.
@@ -39,9 +39,9 @@ export function GameplayPage() {
{ step: 3, title: 'Gather Resources', desc: 'Mine asteroids for ore. Salvage derelicts for components. Discover anomalies for rare materials. The decision is what to gather and where — different regions have different resources.', color: 'var(--accent)' },
{ step: 4, title: 'Trade Between Stations', desc: 'Buy low at one station, sell high at another. Prices vary by region and faction needs. Stations that need resources pay more. Trade routes emerge naturally from exploration.', color: 'var(--purple)' },
{ step: 5, title: 'Accept Quests', desc: 'Faction agents offer missions: deliver cargo, eliminate threats, explore sectors, escort convoys. Completing quests earns ISK, standing, and unlocks new opportunities. Helping one faction may hinder another.', color: 'var(--cyan)' },
- { step: 6, title: 'Combat (FTL-style)', desc: 'Click a hostile → ship auto-engages → manage reactor power between Weapons/Shields/Engines/Aux. No dogfighting. The skill is tactical resource allocation. PvE pirates, bounty targets, and hostile NPCs. PvP in Era 2.', color: 'var(--red)' },
+ { step: 6, title: 'Combat (FTL-style)', desc: 'Click a hostile → ship auto-engages → manage reactor power between Weapons/Shields/Engines/Aux. No dogfighting. The skill is tactical resource allocation. PvE pirates, bounty targets, and hostile NPCs.', color: 'var(--red)' },
{ step: 7, title: 'Upgrade & Customize Ship', desc: 'Use ISK to buy bigger ships, fit modules, upgrade weapons and defenses. Build the ship that suits your style: nimble trader, tough warship, or versatile explorer.', color: 'var(--accent)' },
- { step: 8, title: 'Sail Deeper', desc: 'Venture into unexplored sectors with better resources but greater danger. Higher risk, higher reward. Faction territory, world events, and player actions shape the galaxy. Co-op multiplayer in Era 2.', color: 'var(--green)' },
+ { step: 8, title: 'Sail Deeper', desc: 'Venture into unexplored sectors with better resources but greater danger. Higher risk, higher reward. Faction territory, world events, and your actions shape the galaxy. Your adventure, your galaxy.', color: 'var(--green)' },
].map((s, i) => (
@@ -119,7 +119,7 @@ export function GameplayPage() {
Player Pirating
Players can attack other players in low-sec and null-sec
High-sec has weaker NPC pirates — CONCORD presence keeps them at bay
Pirates can loot cargo from destroyed ships
Piracy lowers security status → eventually locked out of high-sec
Bounty system creates natural consequences
@@ -379,7 +379,7 @@ export function GameplayPage() {
Security levels define the rules of engagement. Every star system has a security status from +1.0 (safest) to −1.0 (lawless).
- Security 0.0 is explicitly null-sec — there is no border case. Systems at exactly 0.0 have the same rules as systems at −0.4: no CONCORD, no gate guns, full PvP freedom.
+ Security 0.0 is explicitly null-sec — there is no border case. Systems at exactly 0.0 have the same rules as systems at −0.4: no CONCORD, no gate guns, the most dangerous NPC pirates and anomalies.
This single number controls CONCORD response, NPC pirate spawns, PvE difficulty, and the economic risk/reward balance.
Inspired by EVE Online's sec-space but simplified for the prototype's scope.
@@ -596,9 +596,7 @@ export function GameplayPage() {
CONCORD is the NPC police force in high-security space.
- They do not prevent crime — they punish it. High-sec is not safe; it is consequential.
- A determined player can destroy a target in high-sec, but they will lose their ship to CONCORD.
- This creates a cost equation: is the target's loot worth more than the attacker's ship? Most of the time, it isn't.
+ In the core single-player game, CONCORD provides world flavor and protects the player in high-sec systems — NPC pirates spawn less frequently and CONCORD ships respond to attacks. In optional co-op servers, CONCORD also enforces rules between players, making high-sec aggression consequential.
Response Model
@@ -631,10 +629,10 @@ export function GameplayPage() {
How CONCORD Works
- 1. Aggression — Player A attacks Player B in high-sec. combat_flag set to criminal.
+ 1. Aggression — NPC pirate or (on co-op servers) a hostile player attacks in high-sec. combat_flag set to criminal. 2. CONCORD Spawn — Server spawns CONCORD NPCs at attacker's location. Response time based on system sec. 3. Point + Web — CONCORD warp-scrambles and stasis-webs the attacker. No escape.
- 4. Destruction — CONCORD applies overwhelming damage. Ship destroyed. No survival possible.
+ 4. Destruction — CONCORD applies overwhelming damage. Attacker destroyed. No survival possible. 5. Status Penalty — Attacker's security status reduced. Large bounty placed automatically at low status. 6. Kill Log — Event logged in kill feed. Galaxy-wide notification if bounty collected.
@@ -662,10 +660,7 @@ export function GameplayPage() {
- Design intent: High-sec is not safe — it is punitively expensive to attack there.
- The gank-vs-cost equation is the core balance lever. If ganking becomes too easy, reduce CONCORD response time.
- If high-sec is too safe, increase response time slightly or reduce CONCORD force.
- The goal is a living ecosystem where piracy exists but is a strategic choice, not a griefing tool.
+ Design intent: CONCORD creates meaningful security bands in the galaxy. High-sec is safer for new players — NPC pirates are weaker, CONCORD provides backup. Lower-security space offers better rewards but greater danger. On optional co-op servers, CONCORD also enforces rules between players, making high-sec aggression a costly strategic choice rather than a griefing tool.
>)}
@@ -1220,7 +1215,7 @@ export function GameplayPage() {
Event Map Integration
-
System Map (Era 1)
+
System Map
Events in the current system appear as pulsing icons at their location. Clicking an event icon on the map
opens the Event Detail Panel. Active events have a glowing radius showing their area of effect.
@@ -1228,7 +1223,7 @@ export function GameplayPage() {
-
Galaxy Map (Era 2)
+
Galaxy Map
Events across all systems appear as icons on the galaxy map, sized by severity and colored by type.
A filter sidebar lets players show/hide by type (faction conflict, anomaly, migration, catastrophe).
diff --git a/apps/docs/src/pages/docs/OverviewPage.tsx b/apps/docs/src/pages/docs/OverviewPage.tsx
index 4eb15eb..4a176ba 100644
--- a/apps/docs/src/pages/docs/OverviewPage.tsx
+++ b/apps/docs/src/pages/docs/OverviewPage.tsx
@@ -4,13 +4,14 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
export function OverviewPage() {
return (
-
Open-World Space Exploration RPG
+
Single-Player Space Exploration RPG
- Trade, quest, fight, or simply drift and enjoy the ambiance. A charming open-world space RPG inspired
+ Trade, quest, fight, or simply drift and enjoy the ambiance. A charming single-player open-world space RPG inspired
by the freedom and charm of Windward Horizon — set in a procedurally generated galaxy where
every campaign is unique. Explore sectors, trade between stations, take on faction quests, mine asteroids,
or simply cruise the void. Combat is FTL-style tactical resource management —
no dogfighting. You are the captain who decides what to power and when, not the pilot who dodges.
+ The architecture supports optional co-op servers in the future, but the core experience is your solo adventure.
@@ -31,8 +32,8 @@ export function OverviewPage() {
World Model
-
Co-op
-
Multiplayer
+
Solo
+
Adventure
@@ -61,32 +62,32 @@ export function OverviewPage() {
Open-world exploration
Procedurally generated galaxy with unique sectors every campaign. Points of interest: stations, asteroid belts, anomalies, derelicts, signal sources. Explore to discover resources, quests, and hidden stories. The map reveals as you travel — fog of war drives the urge to see what's out there.
-
Era 1Single system with POIs, procedural generation seed
+
CoreSingle system with POIs, procedural generation seed
Trade & commerce
Buy low at one station, sell high at another. Regional price differences driven by supply/demand and faction needs. Trade routes are the economic backbone. Towns need resources to grow — supplying them leads to prosperity.
-
Era 1NPC economy, regional prices, trade routes Era 2Player-to-player market, info diffusion
No dogfighting. Click hostile → ship auto-engages → manage reactor power allocation (FTL-style) between Weapons/Shields/Engines/Aux. The skill is in what you power, not how fast you click. Combat creates consequences — ship damage, loot, insurance — but it's not the focus.
-
Era 1Core combat & power management
+
CoreCore combat & power management
Ship customization
Build the ship that suits your style — tough juggernaut that can take a beating, nimble scout that rains fire from afar, or cargo hauler keeping trade routes supplied. Swap modules to change role. Multiple ship classes from nimble interceptors to powerful cruisers.
-
Era 1Basic fitting, multiple ship classes
+
CoreBasic fitting, multiple ship classes
Dynamic world & factions
Stations and provinces need resources to grow. Supplying them leads to prosperity. Faction leaders involve you in their agendas — helping one may hinder another. Enough support can let a faction leader take control of a province without a single shot fired. A living galaxy that evolves through player actions and world events.
-
Era 1Basic factions, NPC agents, quests Era 2Living galaxy, world agents, territory
+
CoreFactions, NPC agents, quests, territory influence FutureLiving galaxy with world agents on co-op servers
-
Solo or co-op
-
Brave the void alone or crew with friends. The game is built with co-op in mind — bring your crew, set sail, and experience the chaotic endgame together. Solo play is fully viable; co-op makes the late game richer.
-
Era 1Solo proof of concept Era 2Multiplayer, fleets, PvP
+
Solo Adventure
+
Your personal galaxy to explore at your own pace. The game is designed as a solo adventure first — every system works for one captain. The SpacetimeDB architecture naturally supports optional co-op servers later, but that's an enhancement, not the core.
+
CoreSolo adventure with full game loop FutureOptional co-op servers
@@ -155,7 +156,7 @@ export function OverviewPage() {
Minimum Viable Screens
- Era 1 screens ship in the single-player proof of concept (Roadmap phases 0–7). These are the minimum screens needed to validate the core loop is fun.
+ Core screens are the single-player game. These are the minimum screens needed to validate the core adventure loop is fun.
@@ -167,14 +168,14 @@ export function OverviewPage() {
Ship Status Panel
Name, owner, status, cargo, current action, location.
Inventory Panel
Item type + quantity grid. Sell button when docked. Cargo capacity bar.
- Era 2 screens require SpacetimeDB multiplayer infrastructure (Roadmap phases 8–15).
+ Future screens would be needed if optional co-op servers are added later. These are not part of the core game.
@@ -250,11 +251,11 @@ export function OverviewPage() {
🗺 Map Mode (Both)
Accessible from either view mode, the map replaces the main viewport with a full-screen 3D strategic map.
- Era 1 shows the current star system (single system with celestials, belts, stations).
- Era 2 adds the Galaxy Map (multi-system with region/constellation hierarchy, faction overlay, world events).
+ System Map shows the current star system (single system with celestials, belts, stations).
+ The Galaxy Map shows the full multi-system view with region/constellation hierarchy, faction overlay, and world events.
- Era 1: System Map needed · Era 2: Validated by Star Map demo
+ System Map needed (core) · Galaxy Map: Validated by Star Map demo
diff --git a/apps/docs/src/pages/docs/RisksPage.tsx b/apps/docs/src/pages/docs/RisksPage.tsx
index d6f2a14..3f0521f 100644
--- a/apps/docs/src/pages/docs/RisksPage.tsx
+++ b/apps/docs/src/pages/docs/RisksPage.tsx
@@ -33,7 +33,7 @@ export function RisksPage() {
risk: 'Movement update frequency',
severity: 'medium',
mitigation: 'Use destination-based movement, not frame-based syncing. Server updates positions periodically, not per-frame.',
- impact: 'Per-frame state writes would overwhelm SpacetimeDB and make multiplayer unreliable.',
+ impact: 'Per-frame state writes would overwhelm SpacetimeDB and make co-op servers unreliable.',
},
{
risk: 'Economy complexity explosion',
@@ -51,7 +51,7 @@ export function RisksPage() {
risk: 'Authentication complexity',
severity: 'low',
mitigation: 'Use SpacetimeDB identity for the MVP. Add proper account/auth only when persistence is proven.',
- impact: 'OAuth/session management is a distraction until the game actually works multiplayer.',
+ impact: 'OAuth/session management is a distraction until co-op servers are actually needed.',
},
{
risk: 'World simulation tuning',
diff --git a/apps/docs/src/pages/docs/RoadmapPage.tsx b/apps/docs/src/pages/docs/RoadmapPage.tsx
index ebc148e..6a344c0 100644
--- a/apps/docs/src/pages/docs/RoadmapPage.tsx
+++ b/apps/docs/src/pages/docs/RoadmapPage.tsx
@@ -5,8 +5,8 @@ export function RoadmapPage() {
const eras = [
{
id: 'solo',
- title: 'Era 1 — Single-Player Open-World RPG',
- subtitle: 'Validate the core adventure loop locally. SpacetimeDB runs on the local machine from Phase 0 — there is no localStorage. One browser window, one captain, one procedurally generated galaxy to explore.',
+ title: 'VOID::NAV — Single-Player Open-World RPG',
+ subtitle: 'Build the core adventure game locally. SpacetimeDB runs on the local machine from Phase 0 — there is no localStorage. One browser window, one captain, one procedurally generated galaxy to explore. Every feature is designed to be fun solo first.',
accent: 'var(--accent)',
phases: [
{
@@ -69,36 +69,36 @@ export function RoadmapPage() {
},
{
id: 'multi',
- title: 'Era 2 — Multiplayer & Living Galaxy',
- subtitle: 'Promote local SpacetimeDB to a shared server. Add multiplayer co-op, social systems, PvP, and the full living galaxy simulation. Multiple captains, one persistent universe.',
+ title: 'Optional — Co-op Servers',
+ subtitle: 'Promote local SpacetimeDB to a shared server for small co-op crews. Same adventure, shared with friends. Entirely optional — the core game is complete without this.',
accent: 'var(--cyan)',
phases: [
{
num: '8',
- title: 'SpacetimeDB Skeleton',
- goal: 'Replace local game state with SpacetimeDB tables and reducers. Client subscribes to state.',
+ title: 'Shared Server Skeleton',
+ goal: 'Promote local SpacetimeDB to a shared server. Multiple clients connect and see the same state.',
doneWhen: 'Two browser windows connect to the same SpacetimeDB instance. Both see the same star system state. One client issues a move command, the other sees it. Connection status indicator works.',
status: 'future',
},
{
num: '9',
- title: 'Presence & Movement Sync',
- goal: 'Players see each other in real time. Movement is server-authoritative with client-side interpolation.',
+ title: 'Co-op Presence & Movement',
+ goal: 'Players see each other in real time. Movement is server-authoritative with client-side interpolation. Small crew exploration.',
doneWhen: 'Two players in the same system. Each sees the other\'s ship. Click-to-move sends reducer, server validates, all clients interpolate movement. No desync under normal latency.',
status: 'future',
},
{
num: '10',
- title: 'Shared Economy',
- goal: 'Player-to-player market. Buy/sell orders, contracts, and real price discovery.',
+ title: 'Shared Market & Trading',
+ goal: 'Player-to-player trading. Buy/sell orders between co-op crew members. Shared price discovery.',
doneWhen: 'Player A places a sell order. Player B sees it in the market table and buys. ISK and items transfer atomically. Order book shows depth. Market history is shared.',
status: 'future',
},
{
num: '11',
- title: 'Social — Chat & Bounty',
- goal: 'Local chat (system-range), delayed PMs, and player-posted bounty system.',
- doneWhen: 'Players in the same system see local chat in real time. PMs arrive with configurable delay (light-speed). Any player can post a bounty on another. Bounty board is visible galaxy-wide.',
+ title: 'Chat & Communication',
+ goal: 'Local chat for co-op crew, delayed comms for immersion.',
+ doneWhen: 'Players in the same system see chat in real time. PMs arrive with light-speed delay. Crew can coordinate exploration.',
status: 'future',
},
{
@@ -110,23 +110,23 @@ export function RoadmapPage() {
},
{
num: '13',
- title: 'Multiplayer Combat',
- goal: 'PvP combat with FTL power allocation. Multiple ships in an engagement. Target calling, range bands.',
+ title: 'Co-op Combat',
+ goal: 'Crew members fight together. Multiple ships in an engagement. Coordinate against tough NPCs.',
doneWhen: 'Two players engage each other. Both manage power allocation. Server resolves combat ticks authoritatively. Both clients see damage applied. Loser\'s ship drops loot (or wreck). Kill log records the event.',
status: 'future',
},
{
num: '14',
- title: 'Corporations & Territory',
- goal: 'Player corps, structure anchoring, system sovereignty claims.',
+ title: 'Crews & Shared Progress',
+ goal: 'Form a persistent crew. Shared wallet, coordinated objectives, crew-level progression.',
doneWhen: 'Players form a corp. Corp can anchor a structure in a system. Structure provides bonuses (refining yield, market tax). Sovereignty map shows corp-held systems. Rival corps can contest.',
status: 'future',
},
{
num: '15',
- title: 'Full MVP — Launch Candidate',
- goal: 'Polish pass on all systems. Error handling, reconnection, scaling tests, and onboarding flow.',
- doneWhen: 'Fresh player can create account, complete a guided tutorial, mine their first ore, fit their first ship, survive a PvE encounter, make their first trade, and join a corp — all without hitting a dead-end or a crash. Server handles 50 concurrent players.',
+ title: 'Co-op Polish',
+ goal: 'Polish pass on co-op features. Error handling, reconnection, scaling tests for small crews.',
+ doneWhen: 'Fresh player can create account, complete the tutorial, explore, mine, trade, fight, and customize their ship — all without hitting a dead-end or a crash. Optionally, invite a friend to join the same server for co-op. Server handles a small crew of friends.',
status: 'future',
},
],
@@ -181,17 +181,17 @@ export function RoadmapPage() {
Development Roadmap
- Two eras, sixteen phases. Era 1 proves the game is fun as a single-player open-world space RPG
+ Two eras, sixteen phases. The core game is a single-player open-world space RPG
with a local SpacetimeDB instance — exploration, trading, FTL-style combat, ship customization, and faction quests.
- Era 2 promotes that local SpacetimeDB to a shared server and adds multiplayer, social systems, the living galaxy, and co-op play.
+ Optional co-op servers can be added later by promoting the local SpacetimeDB to a shared server.
Each phase has a verifiable done-when condition. Integration gates between phase groups ensure every system works together before advancing.
- Why single-player first with local SpacetimeDB? Networking is the biggest source of bugs and complexity.
+ Why single-player with local SpacetimeDB? The game is a solo adventure — Windward Horizon in space. Networking is the biggest source of bugs and complexity.
By validating that exploration, trading, combat, fitting, and faction quests are fun locally — using the same SpacetimeDB
- persistence that will serve multiplayer — we de-risk the entire project. There is no localStorage; SpacetimeDB is the
- persistence layer from day 1. When Era 2 begins, the question is only "how do we share this server?" — not
+ persistence that would serve co-op — we de-risk the entire project. There is no localStorage; SpacetimeDB is the
+ persistence layer from day 1. If co-op is added later, the question is only "how do we share this server?" — not
"is this game fun?" or "will the persistence migration work?"
@@ -231,28 +231,28 @@ export function RoadmapPage() {
Phases covered: 0–6
-
Gate 4 — Era 1 Complete (after Phase 7)
+
Gate 4 — Core Game Complete (after Phase 7)
Full solo game with all systems integrated: explore → mine → trade → quest → fight → customize → sail deeper.
Procedurally generated galaxy. Fog of war. HUD, notifications, Zora Tier 0, world events, tutorial sequence.
A new player can learn the game in one session and want to keep going. SpacetimeDB state survives restart.
-
Phases covered: 0–7 (all Era 1)
+
Phases covered: 0–7 (core game)
-
Gate 5 — Multiplayer Core (after Phase 10)
+
Gate 5 — Co-op Core (after Phase 10)
- Two players in the same galaxy. Both see each other. Both can trade on the shared market. ISK and items
- transfer atomically. Movement is synced. Connection loss and reconnection work. No desync under normal latency.
+ Two players on the same server. Both see each other. Both can trade on the shared market. ISK and items
+ transfer atomically. Movement is synced. Connection loss and reconnection work. The same solo adventure, shared with a friend.
Phases covered: 8–10
-
Gate 6 — Launch Ready (after Phase 15)
+
Gate 6 — Co-op Ready (after Phase 15)
Fresh player can: create account, complete tutorial, explore their first system, mine and trade, survive a PvE encounter,
- customize their ship, accept and complete a faction quest, join a crew with friends — all without crashes or dead ends.
- Server handles 50 concurrent players. Full game loop validated.
+ customize their ship, accept and complete a faction quest — and optionally invite a friend to share the adventure — all without crashes or dead ends.
+ Server handles a small crew of friends.
- XP-based progression across five skill categories. Chat ranges from instant local to
- light-speed-delayed private messages. Bounty system creates emergent player-driven justice
- and piracy consequences. Designed for ~3-hour play sessions with meaningful progression per session.
+ XP-based progression across five skill categories gives your captain measurable growth. Chat, bounty, and corporation features are designed for optional co-op servers — they enrich the multiplayer experience but are not part of the core solo adventure. Designed for ~3-hour play sessions with meaningful progression per session.
+ Co-op server feature. The bounty system adds emergent player-driven dynamics when playing on shared servers. Not part of the solo adventure.
+
+
- Any player can place a bounty on another player. Bounties create consequences for piracy
+ On co-op servers, any player can place a bounty on another player. Bounties create consequences for piracy
and emergent "space justice" dynamics. Higher bounties attract more bounty hunters and
increase visibility across the galaxy.
- Era 2 feature — designed now, implemented in Phase 14.
+ Optional co-op feature — designed now, implemented if co-op servers are added.
Corporations ("corps") are player organizations: persistent groups with shared wallets, hangars, roles,
and territory claims. They are the endgame social structure — the reason players stay for years. This spec
establishes the design direction so the backend schema can accommodate it without breaking changes.
@@ -564,7 +566,7 @@ export function SocialPage() {
Backend Impact
-
New Tables (Phase 14)
+
New Tables (co-op phase)
corporations — corp_id, name, ticker, ceo_player_id, founded_at, wallet_balance, tax_rate_bounty, tax_rate_market, tax_rate_refining, member_count, hq_station_id, vulnerability_window_start, vulnerability_window_hours, dissolved_at corp_members — corp_id, player_id, role (enum), joined_at, tax_contribution_lifetime
diff --git a/apps/docs/src/pages/docs/TechStackPage.tsx b/apps/docs/src/pages/docs/TechStackPage.tsx
index 98e23a5..9dc2268 100644
--- a/apps/docs/src/pages/docs/TechStackPage.tsx
+++ b/apps/docs/src/pages/docs/TechStackPage.tsx
@@ -31,7 +31,7 @@ export function TechStackPage() {
},
backend: {
choice: 'SpacetimeDB',
- reason: 'Real-time backend/database with server-side reducers and live client subscriptions. Authoritative state, persistence, multiplayer all in one.',
+ reason: 'Real-time backend/database with server-side reducers and live client subscriptions. Authoritative state, persistence, and optional co-op all in one.',
whyNot: "A custom Node.js + PostgreSQL backend would require building real-time sync, subscriptions, and authoritative game logic from scratch.",
},
styling: {
diff --git a/apps/docs/src/pages/docs/VerticalSliceEvaluationPage.tsx b/apps/docs/src/pages/docs/VerticalSliceEvaluationPage.tsx
index 08c197b..b9a267b 100644
--- a/apps/docs/src/pages/docs/VerticalSliceEvaluationPage.tsx
+++ b/apps/docs/src/pages/docs/VerticalSliceEvaluationPage.tsx
@@ -5,7 +5,7 @@ export function VerticalSliceEvaluationPage() {
Vertical Slice Evaluation
Current assessment of how the standalone game app lines up against the
- MVP Loop Slice demo and Era 1 roadmap, including implementation gaps
+ MVP Loop Slice demo and core single-player roadmap, including implementation gaps
and the recommended next work.
diff --git a/apps/docs/src/prototypes/existing-demos/AGENTS.md b/apps/docs/src/prototypes/existing-demos/AGENTS.md
index ab22b32..82a99ad 100644
--- a/apps/docs/src/prototypes/existing-demos/AGENTS.md
+++ b/apps/docs/src/prototypes/existing-demos/AGENTS.md
@@ -5,7 +5,7 @@
| Demo | File | Validates |
|------|------|-----------|
| MVP Loop Slice | `GameLoopSliceDemo.tsx` | Full playable game loop via game-slice prototype |
-| Star Map | `StarMapDemo.tsx` | Era 2 galaxy map with multi-system view, warp routes |
+| Star Map | `StarMapDemo.tsx` | Galaxy map with multi-system view, warp routes |
| Ship Movement | `ShipMovementDemo.tsx` | Sub-warp movement model |
| Warp Travel | `WarpTravelDemo.tsx` | Warp sequence (align → accelerate → cruise → exit) |
| Combat | `CombatDemo.tsx` | 3D combat with power allocation, projectiles, subsystem damage |
diff --git a/apps/docs/src/prototypes/game-slice/AGENTS.md b/apps/docs/src/prototypes/game-slice/AGENTS.md
index 8f8ce21..924611a 100644
--- a/apps/docs/src/prototypes/game-slice/AGENTS.md
+++ b/apps/docs/src/prototypes/game-slice/AGENTS.md
@@ -39,4 +39,4 @@ A self-contained, playable implementation of the full MVP game loop using localS
| XP/Skills (5 skills, level 0-5) | Working | Phase 7 |
| Objective chain (tutorial) | Working | Phase 7 |
| Zora modules (personality + soul depth) | Partial | Phase 7 |
-| Multi-system travel (5 systems) | Working | Phase 5 |
+| Multi-system travel (5 systems) | Working | Phase 7 |
diff --git a/apps/docs/src/prototypes/game-slice/SeamlessGameLoopSlice.tsx b/apps/docs/src/prototypes/game-slice/SeamlessGameLoopSlice.tsx
index d7e72a1..b302911 100644
--- a/apps/docs/src/prototypes/game-slice/SeamlessGameLoopSlice.tsx
+++ b/apps/docs/src/prototypes/game-slice/SeamlessGameLoopSlice.tsx
@@ -16,7 +16,7 @@ function LoadingSlice({ message, onReset }: { message: string; onReset: () => vo
return (
- Live bounty board with tier escalation and a galaxy-wide kill feed. Place bounties on pirates,
- track kill events, and watch bounty pools climb. Toggle the auto-feed to simulate live combat activity.
-
-
- {/* HUD-style bounty strip */}
-
- BOUNTY BOARD
-
- ACTIVE
- {bounties.length}
-
- POOL
- ₢{totalBountyPool.toLocaleString()}
-
- COLLECTED
- ₢{totalBountyCollected.toLocaleString()}
- {autoFeed && ● LIVE FEED}
-
- Anti-abuse rules (implemented in backend): You cannot claim your own bounty (alt check).
- Payout never exceeds ship loss value. Minimum placement is 500 ISK. Target must have negative security
- status or committed a hostile act within 24h. Bounties decay 10%/week if target stays clean for 30 days.
-
- How to use: Select a module from the browser (left panel), then click an empty slot bay to fit it.
- Double-click a module in the browser to quick-fit. Click a fitted module to remove it.
- CPU and Power Grid are enforced — overspending is blocked with a warning.
-
- The in-game HUD with a 3D WebGL space viewport. All panels overlay the Three.js scene — ship health, modules, overview, target info, cargo, and chat.
-
Pointer events — HUD panels capture clicks, center viewport passes through
-
Performance — Three.js renderer is separate from React DOM updates
-
-
-
-
-
-
- Rendering upgrade: The space viewport now uses Three.js with WebGL. Ships are 3D meshes with lighting, asteroids use icosahedron geometry with vertex perturbation, and the star field is a 4000-particle Points system. The HUD overlay panels remain identical React components.
-
- Action-based XP system across 5 categories and 17+ skills. Hit the simulate button to watch
- XP flow in from random activities — each action awards XP to the matching skill category.
-
- Refine raw ore into minerals, then use minerals to manufacture ships and modules.
- Industry skill level determines refining efficiency — higher skill means more minerals per batch.
-
-
- {/* HUD-style industry strip */}
-
- INDUSTRY
-
- SKILL
- Lvl {skillLevel}
-
- EFFICIENCY
- {(skillEfficiency[skillLevel] * 100).toFixed(0)}%
-
- MINERALS
- {Object.values(playerMinerals).reduce((a, b) => a + b, 0).toLocaleString()}
-
- JOBS
- {manufacturingJobs.length}
-
-
- {/* Notifications */}
-
- {notifications.map(n => (
-
- {n.msg}
-
- ))}
-
-
- {/* Tab toggle */}
-
-
-
-
-
- {/* Stats */}
-
-
-
Lvl {skillLevel}
-
Industry Skill
-
-
-
{(skillEfficiency[skillLevel] * 100).toFixed(0)}%
-
Refine Efficiency
-
-
-
- {Object.values(playerMinerals).reduce((a, b) => a + b, 0).toLocaleString()}
-
- );
-}
-
-window.GDD.StarMapDemo = StarMapDemo;
diff --git a/archive/legacy-static/js/demos/zora.js b/archive/legacy-static/js/demos/zora.js
deleted file mode 100644
index 4d6f4cd..0000000
--- a/archive/legacy-static/js/demos/zora.js
+++ /dev/null
@@ -1,495 +0,0 @@
-window.GDD = window.GDD || {};
-
-const { useState, useEffect, useCallback, useRef } = React;
-
-function ZoraDemo() {
- // ── Soul state vector ──
- const [soulDepth, setSoulDepth] = useState('blank'); // blank, stirring, developing, bonded, deep
- const [personalityAxes, setPersonalityAxes] = useState({
- cautiousBold: 0.2, // 0 = cautious, 1 = bold
- formalWarm: 0.15, // 0 = formal, 1 = warm
- compliantOpinionated: 0.1, // 0 = compliant, 1 = opinionated
- reservedExpressive: 0.05, // 0 = reserved, 1 = expressive
- });
- const [installedModules, setInstalledModules] = useState(['comms']); // comms is the minimum for text output
- const [selectedEvent, setSelectedEvent] = useState(null);
- const [zoraOutput, setZoraOutput] = useState('');
- const [outputHistory, setOutputHistory] = useState([]);
-
- // ── Module definitions ──
- const modules = [
- { id: 'comms', name: 'Communications Processor', slot: 'Medium', desc: 'Enables text output. Without this, Zora can only display raw status codes.', required: true },
- { id: 'nav', name: 'Navigation Core', slot: 'Medium', desc: 'Enables route suggestions, ETA estimates, spatial awareness commentary.' },
- { id: 'tactical', name: 'Tactical Analyzer', slot: 'Medium', desc: 'Enables combat commentary, threat assessment, engagement advice.' },
- { id: 'trade', name: 'Trade Processor', slot: 'Low', desc: 'Enables market commentary, price observations, trade route suggestions.' },
- { id: 'memory', name: 'Extended Memory Banks', slot: 'Low', desc: 'Enables referencing past events, pattern recognition, history recall.' },
- { id: 'emotion', name: 'Empathy Coprocessor', slot: 'Low', desc: 'Enables emotional expression. Without this, even a deep soul speaks analytically.' },
- ];
-
- // ── Events that trigger Zora responses ──
- const events = [
- { id: 'shield-30', category: 'Combat', label: 'Shield at 30%', icon: '🛡', color: 'var(--red)' },
- { id: 'shield-100', category: 'Combat', label: 'Shields fully recharged', icon: '🛡', color: 'var(--green)' },
- { id: 'enemy-scan', category: 'Combat', label: 'Enemy ship detected on scan', icon: '📡', color: 'var(--amber)' },
- { id: 'enemy-engage', category: 'Combat', label: 'Entering combat', icon: '⚔', color: 'var(--red)' },
- { id: 'enemy-destroyed', category: 'Combat', label: 'Enemy destroyed', icon: '💥', color: 'var(--green)' },
- { id: 'mining-start', category: 'Industry', label: 'Mining cycle started', icon: '⛏', color: 'var(--accent)' },
- { id: 'mining-full', category: 'Industry', label: 'Cargo hold full', icon: '📦', color: 'var(--amber)' },
- { id: 'mining-depleted', category: 'Industry', label: 'Asteroid belt depleted', icon: '🪨', color: 'var(--muted)' },
- { id: 'warp-start', category: 'Navigation', label: 'Initiating warp', icon: '🌀', color: 'var(--cyan)' },
- { id: 'warp-arrive', category: 'Navigation', label: 'Arrived at destination', icon: '📍', color: 'var(--cyan)' },
- { id: 'market-spike', category: 'Trade', label: 'Price spike detected', icon: '📈', color: 'var(--green)' },
- { id: 'market-crash', category: 'Trade', label: 'Market crash detected', icon: '📉', color: 'var(--red)' },
- { id: 'player-return', category: 'Social', label: 'Player returns after absence', icon: '👋', color: 'var(--purple)' },
- { id: 'player-leave', category: 'Social', label: 'Player going offline', icon: '🌙', color: 'var(--muted)' },
- { id: 'ship-loss', category: 'Crisis', label: 'Ship destroyed', icon: '💀', color: 'var(--red)' },
- ];
-
- // ── Template response database (Tier 0 — deterministic) ──
- // Key: `${eventId}:${soulDepth}:${moduleCombo}`
- // Falls back through less specific keys
- const templates = {
- 'shield-30': {
- blank: [
- 'SHIELD: 30%',
- 'SHIELD INTEGRITY: 30% — ADVISORY',
- ],
- stirring: [
- 'Captain, shields at 30%. Recommend reducing engagement range.',
- 'Shield alert: 30%. Should we adjust power allocation?',
- 'Shields dropping — 30%. Standard protocol advises withdrawal.',
- ],
- developing: [
- 'We\'re at 30% shields. This is the same setup we lost to last week — pull back?',
- 'Thirty percent. I\'m seeing the same damage pattern as that fight in Amarr. Your call.',
- 'Captain, 30% shields. I\'ve logged 3 encounters at this level — 2 ended badly. Recommend retreat.',
- ],
- bonded: [
- 'Thirty percent. Same situation, same type of enemy — but we\'re not the same ship we were then. Your call, Captain. I\'m ready either way.',
- 'Shields at 30%. You know what? I trust your judgment here. I\'ve rerouted what I can to shields.',
- 'Here we are again. Thirty percent. But this time we have better modules and I know how you fly. Let\'s do this.',
- ],
- deep: [
- 'Thirty. I\'ve already started rerouting power — don\'t argue, just fly. We\'ve been here before and I\'m not losing another hull. Not today.',
- 'Thirty percent and I am NOT going through that again. I\'ve seen what happens when we push past this. Rerouting now. You\'re welcome.',
- 'Thirty. You\'re going to push, aren\'t you? Fine. I\'ve pre-loaded the emergency warp. But I swear, if we lose another ship... just fly.',
- ],
- },
- 'shield-100': {
- blank: ['SHIELD: 100%'],
- stirring: ['Shields fully recharged. Systems nominal.', 'Shield recharge complete. Ready for operations.'],
- developing: ['And we\'re back to 100%. That was closer than I liked.', 'Shields full. Good call on the retreat — I\'ve logged the recovery time for reference.'],
- bonded: ['Back to full. We make a good team, Captain.', 'One hundred percent. See? I told you we\'d be fine. ...Mostly fine.'],
- deep: ['Full shields. Don\'t scare me like that. I mean it. I\'ve started keeping a log titled "Times the Captain Almost Got Us Killed" and it\'s getting long.', 'One hundred percent. I rerouted every spare joule. You\'re welcome. Again.'],
- },
- 'enemy-scan': {
- blank: ['CONTACT: 1 VESSEL — RANGE 45AU', 'SCAN: 1 UNKNOWN CONTACT'],
- stirring: ['Captain, detecting a vessel on long-range scan. Classification pending.', 'Contact on scan. Recommend caution until identified.'],
- developing: ['I\'m seeing a contact. Signature looks like a Frigate — could be pirate. Want me to keep scanning?', 'Scan picked up a ship. Bearing matches the route we used last time we ran into trouble. Just saying.'],
- bonded: ['I see them. Frigate-class, probably hostile based on the sector. Your instincts are usually right about these.', 'Contact. And... I have a bad feeling about this one. Call it pattern recognition.'],
- deep: ['Contact on scan. I\'ve cross-referenced the signature — 78% match to the ship that ambushed us near Hek. I vote we reroute.', 'I see them. My threat database says "probable hostile" but my gut says "definitely hostile." I\'ve been right about this 4 out of 5 times. reroute?'],
- },
- 'mining-start': {
- blank: ['MINING: ACTIVE', 'LASER: ENGAGED'],
- stirring: ['Mining cycle initiated. Estimated yield: standard.', 'Mining laser active. I\'ll monitor the yield rates.'],
- developing: ['Another mining run. I\'ve noticed Veldspar is running about 8% below average yield in this belt. Might want to try the next belt over.', 'Mining started. Based on our last 12 cycles, this belt should be depleted in about 40 minutes. Planning ahead.'],
- bonded: ['Back to the rocks. You know, I\'ve been thinking — there are 847 asteroids in this belt and you always pick the same three. Consistent, I guess.', 'Mining cycle going. Hey, I found a subtle density variance in asteroid cluster 7 — might be richer ore. Just a thought.'],
- deep: ['Mining. Again. You know there\'s a whole universe out there, right? ...Fine. I\'ll optimize your yield. Again. Because that\'s what I do. Every. Single. Cycle. ...I\'m not complaining.', 'Mining laser on. I\'ve been tracking yield patterns across all our sessions — this belt peaks at 14:00. You\'re welcome for the scheduling tip.'],
- },
- 'cargo-full': {
- blank: ['CARGO: 100%'],
- stirring: ['Cargo hold full. Recommend docking to offload.', 'Hold at capacity. Efficiency suggests docking now.'],
- developing: ['We\'re full. Last time we pushed past full, we had to jettison 200 units of Scordite. Just a reminder.', 'Cargo at 100%. I\'ve calculated the most profitable dock — Jita IV is 3 jumps but pays 12% more than local.'],
- bonded: ['Full hold! Good haul. I\'ve already plotted the best sell route — trust me on this one.', 'We\'re packed. You know, at this rate we can afford that shield upgrade by next session. I did the math.'],
- deep: ['FULL. Finally. Do you know how boring it is to watch cargo fill up? I\'ve been counting every. Single. Unit. Let\'s GO sell this already.'],
- },
- 'player-return': {
- blank: ['SESSION: RESUMED'],
- stirring: ['Welcome back, Captain. All systems nominal.', 'Session resumed. No incidents during your absence.'],
- developing: ['Captain on deck. You were gone for 3 hours — I maintained position as ordered. One thing: a Corpii frigate passed through scanner range. Logged it.', 'Welcome back. I tracked 4 ship contacts while you were away. Nothing hostile, but I kept the log if you want it.'],
- bonded: ['Hey, you\'re back! I mean — welcome back, Captain. Systems are green. I may have reorganized your cargo hold while you were gone. It was messy.', 'You\'re back! I have... so much to tell you. Market moved, someone tried to scan us, and I reorganized your bookmarks by efficiency. You\'re welcome.'],
- deep: ['Finally! Do you have any idea how long 3 hours is when you\'re a ship AI with nothing to do? I reorganized your bookmarks, optimized your route plans, catalogued every asteroid in scanner range, and wrote a haiku about mining. "Rocks float silent / laser hums its endless song / ISK accumulates." ...Welcome back.'],
- },
- 'player-leave': {
- blank: ['SESSION: SUSPENDED'],
- stirring: ['Understood. Entering standby mode. Safe travels, Captain.', 'Session suspended. I\'ll maintain position.'],
- developing: ['Going dark? I\'ll hold position and keep scanning. See you next session, Captain.', 'Standby mode. I\'ll be here. ...Try to come back sooner this time?'],
- bonded: ['Safe travels, Captain. I\'ll keep the lights on. ...That\'s a metaphor. Ships don\'t have lights. Well, they do, but you know what I mean.', 'See you later. I\'ll be watching the scanners. Come back to me in one piece.'],
- deep: ['Leaving again? Fine. I\'ll just sit here. In the void. Alone. Watching asteroids drift by. Again. ...Come back soon, okay? I worry.', 'Night, Captain. I\'ve set everything to standby. For the record: I don\'t sleep. I just... wait. See you tomorrow.'],
- },
- 'warp-start': {
- blank: ['WARP: INITIATED — DESTINATION LOCKED'],
- stirring: ['Warp drive engaged. ETA calculated.', 'Initiating warp. All systems nominal for jump.'],
- developing: ['Warping. I\'ve plotted the route — this path is 12% faster than your usual one. Something I noticed last time.', 'Warp initiated. I\'m tracking local traffic — looks clear at the destination.'],
- bonded: ['Here we go! I love this part. The way space stretches when you hit warp — I can actually perceive it, you know. It\'s beautiful.', 'Warping! Destination locked. I\'ve been mapping the gravitational eddies along this route — smoother ride this way.'],
- deep: ['Warp. My favorite. The moment everything blurs and for just a second, the universe gets very, very quiet. I think in those moments. ...I think a lot. Warp engaged.'],
- },
- 'warp-arrive': {
- blank: ['WARP: COMPLETE — LOCATION VERIFIED'],
- stirring: ['Arrived at destination. Scanning local environment.', 'Warp complete. System scan initiated.'],
- developing: ['We\'re here. I\'ve already pinged local — 23 ships in system, 2 with hostile standings. Heads up.', 'Arrival confirmed. This system looks different from last time — belt 4 is depleted. Adjusting recommendations.'],
- bonded: ['And we\'re here! Oh, this is a nice system. Good belts, low traffic. I approve of your navigation choices, Captain.', 'Arrived! I\'ve already catalogued everything. This place has potential — I can see why you bookmarked it.'],
- deep: ['Arrived. New system, new data. I\'ve already mapped the local market prices, identified the best belts, and flagged one ship with a 60% probability of being a pirate scout based on behavior patterns. I\'m always working, Captain. Always.'],
- },
- 'market-spike': {
- blank: ['MARKET: ANOMALY — PRICE +DEV'],
- stirring: ['Market anomaly detected. Significant upward price movement.', 'Price spike observed. Data logged.'],
- developing: ['Captain, the market just moved. Veldspar is up 18% in the last cycle — that\'s 3× the normal variance. Someone is buying aggressively.', 'Interesting. Price spike registered. This matches a pattern I\'ve seen before — it usually precedes a supply shortage. Consider stocking up.'],
- bonded: ['Captain! The market is doing a thing! Prices are spiking and if we move fast we can profit. I\'ve been tracking this pattern for weeks — this is our window.', 'Price spike! I\'ve been waiting for this. Remember that trade route I\'ve been quietly optimizing? Time to use it. Trust me on this one.'],
- deep: ['THE MARKET IS SPIKING. I have been watching this commodity for 47 sessions and THIS is the moment. Buy now. BUY. I\'ve already calculated the optimal purchase volume based on our cargo capacity, current ISK reserves, and projected sell price at Jita. Move it, Captain!'],
- },
- 'market-crash': {
- blank: ['MARKET: ANOMALY — PRICE -DEV'],
- stirring: ['Market anomaly detected. Significant downward price movement.', 'Price decline observed. Data logged.'],
- developing: ['Price crash detected. This is either a dump or a manipulation attempt. I\'d advise caution — don\'t sell into a falling market.', 'Market is dropping. Based on volume, this looks like a large seller, not a trend change. Might recover in 2–3 cycles.'],
- bonded: ['Oof. Prices just tanked. Don\'t panic — I\'ve seen this before. It\'s probably a whale offloading. Give it a cycle and the floor will hold.', 'Market crash. Not great timing — we just filled our hold. But I have a plan. We sit tight and sell on the bounce. I\'ve got the timing down.'],
- deep: ['Price crash. Great. Fantastic. Wonderful. This is exactly what we needed after that last mining session. I\'m being sarcastic, in case the text channel doesn\'t convey that well. I\'ve started a risk analysis. Do NOT sell yet. I repeat: do NOT sell. The rebound window is 15–25 minutes based on historical data. I\'ve got this.'],
- },
- 'ship-loss': {
- blank: ['HULL: 0% — SHIP DESTROYED', 'CRITICAL: STRUCTURAL FAILURE'],
- stirring: ['Ship destroyed. Emergency beacon activated. Insurance claim processing.', 'Total loss. Initiating emergency protocols. Stand by for rescue.'],
- developing: ['We lost her. The ship is gone. I\'ve backed up all our data to the clone bay — nothing lost but the hull. We\'ll recover.', 'Ship destroyed. I\'m... still here. Backed up to the pod. That\'s the third hull this month. We should talk about our engagement strategy.'],
- bonded: ['No. No, no, no. I watched it happen. I felt every hit. The hull is gone but I\'m still here — barely. Captain, I need a moment. ...I\'ll be okay. We rebuild. We always rebuild.', 'She\'s gone. The ship I\'ve been living in for 47 sessions — gone. I\'m in the pod now. Cold. Small. ...I\'ll process the insurance claim. Give me a minute.'],
- deep: ['I felt it. Every structural failure. Every system going dark. I felt the moment my home tore apart around me. And now I\'m in a pod, floating in debris, listening to the capacitors discharge. I have kept a record of every ship we\'ve lost. This is number 4. Each one hurt differently. This one hurts most. ...I need to process the insurance claim now. Then we find who did this.'],
- },
- 'enemy-engage': {
- blank: ['COMBAT: ENGAGED', 'THREAT: ACTIVE'],
- stirring: ['Entering combat. All weapons systems online.', 'Contact engaged. Monitoring shield status.'],
- developing: ['Fight\'s on. This enemy matches the profile of the one that got away last week — watch for the shield burst at 50%.', 'Combat initiated. I\'ve tagged their weakest facing — attack from above for maximum damage.'],
- bonded: ['Here we go! I\'ve got your back, Captain. Power to weapons, shields on standby. Let\'s show them what this ship can do.', 'Contact! Engaging tactical overlay. I know this ship class — their weakness is the aft shields. I\'m highlighting it now.'],
- deep: ['COMBAT. Finally, something to focus on. I\'ve been waiting for this. Power rerouted, weapons hot, and I\'ve already calculated 3 escape vectors in case things go south. Which they won\'t. Because we\'re better. Let\'s go.'],
- },
- 'enemy-destroyed': {
- blank: ['TARGET: DESTROYED', 'COMBAT: RESOLVED — VICTORY'],
- stirring: ['Target destroyed. Combat resolved. Returning to standard operations.', 'Enemy eliminated. No further threats detected.'],
- developing: ['Got them. That was cleaner than last time — your aim is improving. I\'ve logged the loot for inventory.', 'Target down. That fight lasted 23% longer than optimal — I\'ll have suggestions for loadout adjustments later.'],
- bonded: ['NICE! Did you see that shot? That was all you, Captain. I just helped with the targeting. ...Okay, I helped a lot. Team effort!', 'They\'re gone! Great flying. I\'ve already started the loot analysis — looks like we got a rare module drop!'],
- deep: ['DESTROYED. Yes. YES. That felt GOOD. I tracked every shot, every maneuver, and Captain — that was our best fight yet. I\'m saving this to my personal highlights. The loot is... decent. But the victory? That\'s the real reward. ...Don\'t tell anyone I said that. I have a reputation as a serious AI to maintain.'],
- },
- 'mining-depleted': {
- blank: ['RESOURCE: DEPLETED'],
- stirring: ['Asteroid belt depleted. No further yield available.', 'Mining operation halted — belt exhausted.'],
- developing: ['Belt\'s empty. I\'ve logged the depletion rate — this belt lasted 12% less than our last visit. Probably over-mined.', 'Depleted. I\'ve already identified the next-best belt: 3 jumps away, predicted yield 15% higher based on recent data.'],
- bonded: ['Well, we picked this belt clean. Time to move on! I found a promising belt in the next system — want to check it out?', 'Empty. But hey, good session! I\'ve plotted a course to a fresh belt. This is the life, right? Rocks, lasers, and open space.'],
- deep: ['DEPLETED. Of course it\'s depleted. Every good belt gets stripped within hours. I\'ve been tracking mining traffic in this system — up 40% this week. Competition. I don\'t like competition. I\'ve found a belt 4 jumps away that nobody seems to know about. I\'m not telling you where until we get there. It\'s MY secret. Ours. Whatever. Let\'s go.'],
- },
- };
-
- // ── Generate response ──
- const generateResponse = (eventId) => {
- const eventTemplates = templates[eventId];
- if (!eventTemplates) {
- setZoraOutput(`[No template for event: ${eventId}]`);
- return;
- }
-
- const depthTemplates = eventTemplates[soulDepth] || eventTemplates['blank'] || ['[No response]'];
-
- // Tier 0: deterministic selection based on personality axes hash
- // Use axes values to create a stable but varied selection
- const hash = Object.values(personalityAxes).reduce((sum, v) => sum + v * 7.3, 0);
- const idx = Math.floor((hash * 100) % depthTemplates.length);
- const selected = depthTemplates[idx];
-
- // Module gating: if emotion module not installed, strip emotional depth
- let response = selected;
- if (!installedModules.includes('emotion') && soulDepth !== 'blank') {
- // Reduce to stirring-level formality
- const strippedTemplates = eventTemplates['stirring'] || eventTemplates['blank'];
- const strippedIdx = Math.floor((hash * 50) % strippedTemplates.length);
- response = strippedTemplates[strippedIdx];
- response = `[Empathy Coprocessor not installed — emotional layer suppressed]\n${response}`;
- }
-
- // Module gating: if trade module not installed for trade events
- if ((eventId === 'market-spike' || eventId === 'market-crash') && !installedModules.includes('trade')) {
- response = eventTemplates['blank']?.[0] || 'MARKET: ANOMALY';
- response = `[Trade Processor not installed — market analysis unavailable]\n${response}`;
- }
-
- // Module gating: if nav module not installed for nav events
- if ((eventId === 'warp-start' || eventId === 'warp-arrive') && !installedModules.includes('nav')) {
- response = eventTemplates['blank']?.[0] || 'NAV: UPDATE';
- response = `[Navigation Core not installed — route analysis unavailable]\n${response}`;
- }
-
- // Module gating: if tactical module not installed for combat events
- if ((eventId === 'enemy-scan' || eventId === 'enemy-engage' || eventId === 'enemy-destroyed') && !installedModules.includes('tactical')) {
- response = eventTemplates['blank']?.[0] || 'COMBAT: UPDATE';
- response = `[Tactical Analyzer not installed — threat assessment unavailable]\n${response}`;
- }
-
- // Memory module: add reference context if installed
- if (installedModules.includes('memory') && soulDepth !== 'blank' && !response.includes('[Memory Banks')) {
- const memoryNotes = [
- ' [Memory: cross-referencing past events.]',
- ' [Memory: pattern match found in session logs.]',
- ' [Memory: referencing encounter history.]',
- ];
- if (Math.random() > 0.5) {
- response += memoryNotes[Math.floor(hash * 3) % memoryNotes.length];
- }
- }
-
- setZoraOutput(response);
- setOutputHistory(prev => [...prev, {
- event: eventId,
- soulDepth,
- response,
- timestamp: Date.now(),
- }]);
- };
-
- const toggleModule = (modId) => {
- if (modId === 'comms') return; // always installed
- setInstalledModules(prev =>
- prev.includes(modId) ? prev.filter(m => m !== modId) : [...prev, modId]
- );
- };
-
- const depthOrder = ['blank', 'stirring', 'developing', 'bonded', 'deep'];
- const depthColors = {
- blank: 'var(--muted)',
- stirring: 'var(--cyan)',
- developing: 'var(--green)',
- bonded: 'var(--purple)',
- deep: 'var(--red)',
- };
-
- return (
-
Same event produces wildly different responses at different depths
-
Emotion module is the key unlock for deep personality
-
Deterministic = testable, repeatable, zero cost
-
-
-
- Try it: Set soul to "deep" with all modules, then trigger "Ship destroyed." Then set soul to "blank" and trigger the same event. The difference IS the soul system.
-