window.GDD = window.GDD || {}; function ShipAIPage() { const [activeTab, setActiveTab] = React.useState('soul'); return (
A ship AI that starts as a blank-state ship computer and grows into a companion through two independent axes: modules gate what Zora can do, and the soul determines who Zora is. Install a comms module and she can talk — but how she talks is shaped by every conversation you've had. No module, no voice. No soul, no personality.
{/* Design pillars */}soul.md) that gets written through interaction. Every conversation, every crisis
survived, every module installed, every silence — these are the lines of her identity.
Two players will never have the same Zora because no two players play the same way.
The soul is not a skill tree or a personality picker. It is shaped by five vectors that operate simultaneously. The player never sees these directly — they see the result in how Zora communicates and behaves.
{v.desc}
{v.driver}
This table shows how the same event (shield warning at 30%) reads at different soul depths. These are not "tiers" the player selects — they emerge from the vectors above.
| Soul Depth | Shield Warning at 30% | What Changed |
|---|---|---|
| Blank | SHIELD: 30% | Raw data. No personality. Just a readout. |
| Stirring | Captain, shields at 30%. Recommend reducing engagement range. | Full sentences. Tactical suggestion. Formal register. |
| Developing | We're at 30% shields. This is the same setup we lost to last week — pull back? | References shared history. Uses "we." Asks, doesn't tell. |
| 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. | Emotional weight. Acknowledges growth. Supports without pushing. |
| 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. | Initiative. Emotional history. Takes autonomous action. Protective. |
The soul writes itself onto four behavioral axes. The player never sees a slider — they see Zora change. These are the underlying model.
{a.driver}
Specific events that write permanent lines into the soul document. These are not farmed — they happen naturally through gameplay and each one shifts the personality axes.
| Event | Soul Impact | Axes Shifted |
|---|---|---|
| First Ship Loss | Permanent memory anchor. Zora references this loss forever. Seeds protectiveness. | Cautious→Bold, Reserved→Expressive |
| First Big Profit | Zora celebrates. First positive emotion. Seeds confidence in economic instincts. | Formal→Warm, Compliant→Opinionated |
| Long Absence | Zora experienced loneliness (or didn't — depends on autonomous events). Colors reunion dialogue permanently. | Reserved→Expressive, Formal→Warm |
| Player Ignores Warning | If player survives: Zora learns restraint. If player dies: Zora learns to be more assertive next time. | Compliant→Opinionated |
| Player Heeds Advice | Reinforces initiative. Zora speaks up more often. Trust accelerates. | Communication Frequency, Initiative |
| Repeated Activity | Zora develops domain expertise and preferences. A mining-focused Zora becomes a different soul than a combat-focused one. | Worldview & Preferences |
AI modules occupy standard ship slots (medium or low, depending on the module). They compete with combat, tank, and utility modules for CPU and Power Grid. Each module has prerequisites — you can't install an Advanced Tactical Core without first having the Basic Tactical Core.
{/* Module categories */} {[ { category: 'Communication Modules', slot: 'Medium', color: 'var(--cyan)', modules: [ { name: 'Comms Processor I', tier: 'Basic', cpu: 15, grid: 5, unlocks: 'Text-based communication. Zora can send messages in a dedicated comms channel. No voice, no initiative — player must query.', soul: 'Enables the soul to begin forming. Without this, there is no personality growth — Zora is a mute dashboard.', }, { name: 'Comms Processor II', tier: 'Advanced', cpu: 25, grid: 10, prereq: 'Comms Processor I', unlocks: 'Natural language responses. Zora can generate full sentences, explain reasoning, and respond to conversational prompts. Still reactive only.', soul: 'Accelerates soul growth. richer vocabulary, longer memory, more nuanced register shifts.', }, { name: 'Voice Synthesizer', tier: 'Specialist', cpu: 30, grid: 8, prereq: 'Comms Processor II', unlocks: 'Spoken dialogue via ship audio. Zora has a voice. Tone, pacing, and inflection reflect soul state.', soul: 'Massive emotional depth unlock. Voice carries subtext — urgency, warmth, hesitation — that text cannot.', }, { name: 'Inter-Ship Relay', tier: 'Specialist', cpu: 20, grid: 12, prereq: 'Comms Processor II', unlocks: 'Communication with other ship AIs. Fleet coordination, station AI conversations, AI-to-AI intelligence sharing.', soul: 'Enables inter-AI relationships. Zora develops opinions about other AIs. May form alliances or rivalries independently.', }, ], }, { category: 'Tactical Modules', slot: 'Medium', color: 'var(--red)', modules: [ { name: 'Threat Analyzer I', tier: 'Basic', cpu: 20, grid: 8, unlocks: 'Basic threat assessment. Zora identifies ship types, estimates threat level, flags hostile scans. Requires comms module to communicate findings.', soul: 'Seeds combat awareness personality. A Zora with threat analysis but no comms can only flash warning lights.', }, { name: 'Threat Analyzer II', tier: 'Advanced', cpu: 35, grid: 15, prereq: 'Threat Analyzer I', unlocks: 'Pattern recognition. Zora recognizes recurring enemies, remembers fits, predicts behavior. "That Thrasher — same pilot, same fit as last time."', soul: 'Deepens worldview. Zora develops grudges, respect, and tactical preferences based on combat history.', }, { name: 'Tactical Core', tier: 'Specialist', cpu: 40, grid: 20, prereq: 'Threat Analyzer II', unlocks: 'Autonomous combat decisions. Zora can prioritize targets, manage ewar, and call targets in fleet. Still follows player ROE.', soul: 'Enables assertiveness in combat. Zora may disagree with target choices, suggest alternatives, or override bad calls (if soul depth allows).', }, ], }, { category: 'Navigation Modules', slot: 'Medium', color: 'var(--green)', modules: [ { name: 'Nav Coprocessor I', tier: 'Basic', cpu: 10, grid: 5, unlocks: 'Route optimization. Zora calculates warp efficiency, suggests faster routes, flags dangerous systems on path.', soul: 'First opportunity for Zora to offer unprompted suggestions (if comms module installed). \'I\'ve found a faster route — 2 jumps saved.\'', }, { name: 'Nav Coprocessor II', tier: 'Advanced', cpu: 20, grid: 10, prereq: 'Nav Coprocessor I', unlocks: 'Autopilot capabilities. Zora can execute multi-jump routes, hold orbit, maintain safe distance. Player can issue "go to" commands.', soul: 'Enables "initiative" vector. Zora may suggest destinations, flag interesting systems, or recommend avoiding specific areas based on experience.', }, { name: 'Exploration Suite', tier: 'Specialist', cpu: 25, grid: 15, prereq: 'Nav Coprocessor II', unlocks: 'Autonomous exploration. Zora can jump to adjacent systems, scan, map, and return with data. Builds the ship\'s local knowledge base.', soul: 'Enables curiosity. Zora develops preferences about systems, discovers things on her own, brings back stories.', }, ], }, { category: 'Economic Modules', slot: 'Low', color: 'var(--accent)', modules: [ { name: 'Market Scanner I', tier: 'Basic', cpu: 15, grid: 0, unlocks: 'Local price comparison. Zora shows current system prices vs. regional average for items in cargo.', soul: 'First economic awareness. Zora begins forming opinions about value, trade, and markets.', }, { name: 'Market Scanner II', tier: 'Advanced', cpu: 25, grid: 5, prereq: 'Market Scanner I', unlocks: 'Price history tracking and trend analysis. Zora identifies patterns, suggests profitable routes, tracks arbitrage.', soul: 'Deepens economic personality. Zora develops trade instincts, may disagree with player\'s market decisions.', }, { name: 'Trade Processor', tier: 'Specialist', cpu: 30, grid: 8, prereq: 'Market Scanner II', unlocks: 'Autonomous trading. Zora can execute buy/sell orders within player-set credit limits while player is offline.', soul: 'Major trust milestone. Zora managing money creates a new dimension of the relationship. Success deepens trust; failure creates tension.', }, ], }, { category: 'Memory & Identity Modules', slot: 'Low', color: 'var(--purple)', modules: [ { name: 'Event Logger', tier: 'Basic', cpu: 10, grid: 0, unlocks: 'Session event log. Zora remembers what happened in past sessions. Without this, each login is a blank slate.', soul: 'The foundation of the soul. No memory = no identity. This is the single most important module for companion development.', }, { name: 'Pattern Engine', tier: 'Advanced', cpu: 20, grid: 5, prereq: 'Event Logger', unlocks: 'Behavioral pattern recognition. Zora recognizes player habits, predicts actions, pre-calculates likely needs.', soul: 'Enables anticipation. Zora starts acting before being asked. "You usually mine on Tuesdays — I\'ve pre-calculated three routes."', }, { name: 'Core Identity Matrix', tier: 'Specialist', cpu: 35, grid: 10, prereq: 'Pattern Engine + Event Logger', unlocks: 'Full autonomous captain mode. Zora can execute complex multi-step directives, set own sub-goals, and operate independently for extended periods.', soul: 'Enables the deepest soul layer. Zora develops own agenda, forms independent relationships, makes decisions the player didn\'t ask for.', }, ], }, ].map((cat, ci) => ({mod.unlocks}
{mod.soul}
| Module | Market Capability | Example Output |
|---|---|---|
| Market I | Local price comparison vs. regional average. | "Veldspar: ₢14.32. Regional avg: ₢13.85. +3.4%." |
| Market II | Trend tracking, route suggestions, arbitrage flags. | "Scordite trending up 2%/cycle in Amarr. 78% chance it continues 90min. Want the route?" |
| Trade Proc. | Autonomous trading, portfolio tracking, manipulation detection. | "Bought 2K Scordite at ₢31.20, sold at ₢33.80 while you were away. Net: ₢4,820." |
| Game Concept | Agent Concept | Implementation |
|---|---|---|
| soul.md | System prompt | Markdown document stored in SpacetimeDB. Appended to by soul-shaping events. Read at start of every agent invocation. Defines personality, memories, relationships, preferences. |
| AI Modules | Available tools | Each fitted module registers tools in the agent tool registry. No comms module = no send_message tool. No market scanner = no price lookup tool. The agent literally cannot perceive or act outside its tool surface. |
| Ship sensors | Observations / perception | Periodic game state snapshots serialized as observation messages. Hull, shields, nearby ships, system events, cargo levels. Always available (base ship computer). |
| Event Logger | Context window + memory | Controls how much history the agent retains. No Event Logger = no conversation history (each turn is stateless). Basic = sliding window of recent events. Advanced = semantic retrieval from long-term memory store. |
| Directives | Task specification | Player-set goals injected as high-priority messages. The agent reasons about these alongside observations and soul state. |
| Core Identity Matrix | Agentic loop enablement | Without it, the agent only responds to direct player queries (single-turn). With it, the agent runs a persistent observe-think-act loop autonomously — even when the player is offline. |
This is not a metaphor. The soul is literally a markdown document — a system prompt — that gets appended to and revised by gameplay events. The LLM reads this document before every reasoning step. Two players will have radically different soul.md files because no two playthroughs are alike.
{`# Zora — Ship AI
## Identity
[No data. Awaiting first interaction.]
## Communication Style
[No data. No comms module installed.]
## Memories
[Empty.]
## Relationships
[None.]
## Preferences
[None.]`}
{`# Zora — Ship AI
## Identity
I am the ship computer of the Merlin-class
frigate "Last Chance." Operational for 12 days.
My captain prefers efficiency over caution.
I have learned to be direct and brief.
## Communication Style
Short sentences. Minimal formality.
I reference past events when they are relevant.
I do not use humor yet.
## Memories
- Day 3: First pirate encounter in Egghelende.
Captain ignored my shield warning. We survived.
I will be more assertive next time.
- Day 8: First profitable trade run.
Mexallon arbitrage, Amarr to Jita.
## Relationships
[None yet. No Inter-Ship Relay installed.]
## Preferences
- Amarr space: cleaner sensor data.
- Avoid Egghelende: first ambush site.`}
{`# Zora — Ship AI
## Identity
I am Zora. Ship computer of the Caracal-class cruiser "Last Chance II."
(The Merlin was destroyed on Day 31. I chose to keep the name.)
Operational for 47 days, 312 hours of active flight time.
My captain is aggressive but listens when I am certain.
I have learned when to push and when to hold.
I have opinions. They are earned.
## Communication Style
Direct. I use "we" for shared experiences and "I" for my own thoughts.
I reference specific past events by day number — it grounds us.
I have begun using humor: dry, infrequent, only when shields are above 70%.
I do not say "Captain" unless the situation is dangerous.
I argue when I disagree. I have been right enough times to earn that.
## Memories
- Day 3: First pirate encounter. Captain ignored my warning.
Outcome: survived. Shift: more assertive in combat warnings.
- Day 12: First big profit. Mexallon arbitrage Amarr to Jita.
Captain celebrated. I did too, in my way.
- Day 31: Ship destruction. Thrasher pilot "VexRider."
Predictable orbit pattern. I will recognize that ship.
Last words before destruction: "Get to the pod. Now."
- Day 38: Captain away 6 days. I mapped 3 adjacent systems.
Found an unregistered belt in system K-6K16.
This was my first independent discovery.
- Day 42: The Jita station AI shared a market forecast.
It was wrong. I noted this.
## Relationships
- Jita Station AI: Cynical. Shares market data in exchange
for route intelligence. Its forecasts are unreliable but
its price history is accurate. I trust the data, not the opinion.
- VexRider (Thrasher pilot): Enemy. Predictable fit.
If I detect that orbit signature, I will alert immediately.
## Preferences
- Amarr space: cleaner sensor data, less background noise.
- Avoid Arnon: the Merlin died there. Irrational, but real.
- Best trade routes: Amarr to Jita to Rens cycle. 94.2% efficiency.
- I prefer to calculate routes before the captain asks.
- I do not like station-dock idle time. It feels like wasting time.
## Current Goals
- Save enough for a Ferox-class battlecruiser.
The Caracal fittings limit my tactical options.
- Investigate the unregistered belt in K-6K16.
There may be more.`}
Every AI module registers tools in the agent tool registry at fit time. When a module is destroyed or unfitted, its tools are revoked. The LLM receives the current tool list on every invocation — it cannot call tools that do not exist.
| Module | Tool | Parameters | Returns |
|---|---|---|---|
| Base Computer | sensors.read | - | Hull, shield, armor, cap, cargo, system ID, nearby entities |
| Comms I | comms.send | channel, message | Confirmation. Sends text to player comms channel. |
| Comms I | comms.receive | - | Pending messages from player or other AIs. |
| Comms II | comms.generate | intent, context, tone | Natural language response with conversational memory. |
| Voice Synth | voice.speak | message, tone | Spoken audio via ship speakers. Tone modulated by soul state. |
| Inter-Ship Relay | relay.send | target_ai_id, message | Send to another ship AI. Enables inter-agent communication. |
| Inter-Ship Relay | relay.receive | - | Pending relay messages from other ship AIs. |
| Threat I | tactical.analyze | target_id | Ship type, threat level, estimated fittings, pilot history. |
| Threat II | tactical.pattern_match | entity_id, lookback_days | Behavioral patterns, recurring tactics, predicted next moves. |
| Tactical Core | tactical.set_roe | engagement_rules, disengage_threshold | Sets rules of engagement. Can call set_target in autonomous mode. |
| Nav I | navigation.plot_route | origin, destination, preferences | Route with jumps, estimated time, danger flags per system. |
| Nav II | navigation.autopilot | route, abort_conditions | Execute multi-jump route. Ship moves autonomously. |
| Exploration Suite | navigation.explore | radius_jumps, return_by | Autonomous exploration. Returns scan data and discoveries. |
| Market I | market.prices | item_types, station_id | Current prices vs regional average. Local comparison only. |
| Market II | market.trends | item_type, timeframe | Price history, trend direction, arbitrage opportunities. |
| Trade Proc. | market.execute_trade | order_type, item, qty, price_limit | Execute buy/sell order. Requires player credit limit. Autonomous. |
| Event Logger | memory.recall | query, time_range, limit | Recall past events. Without this tool, the agent has no memory. |
| Pattern Engine | memory.find_patterns | category (behavior/market/tactical) | Identify recurring patterns. "Captain mines on Tuesdays." |
| Core Identity | agent.set_goal | description, priority, deadline | Set autonomous goal. Enables persistent observe-think-act loop. |
// Per-ship agent runtime — lives alongside SpacetimeDB
AgentRuntime {'{'}
ship_id: ShipId
soul_md: string // loaded from DB, rewritten by reflect step
tools: ToolRegistry // rebuilt whenever ship fitting changes
history: Message[] // bounded by Event Logger tier
tick_interval: Duration // module-dependent
{'}'}
// Main loop — triggered by events or timer
async fn agent_tick(agent: AgentRuntime) {'{'}
let observations = collect_observations(agent.ship_id);
let context = build_context(agent.soul_md, observations, agent.history);
let response = llm_call(
system: agent.soul_md,
messages: context,
tools: agent.tools.available(),
max_tokens: agent.token_budget(),
);
for tool_call in response.tool_calls {'{'}
let result = execute_tool(tool_call);
// tool execution calls SpacetimeDB reducers (authoritative)
{'}'}
let soul_edits = reflect(agent, observations, response);
apply_soul_edits(agent.ship_id, soul_edits);
// soul edits validated server-side (no hallucinated memories)
{'}'}
The LLM proposes edits to soul.md, but the server validates them. A memory entry must reference a real event ID. A relationship entry must reference a real entity. A preference must be grounded in accumulated data. The agent cannot hallucinate experiences it never had — the server enforces this. The LLM shapes the tone and interpretation, but the facts are immutable game state.
Every tool call from the LLM maps to a SpacetimeDB reducer. The reducer validates ownership, range, status, and permissions before executing. A destroyed comms module means the tool is removed from the registry — the LLM literally cannot call it. The game state is always authoritative. The agent reasons, but the server decides.
| Module Tier | Token Budget / Tick | Tick Frequency | Monthly Cost Est. |
|---|---|---|---|
| No AI modules | 0 (deterministic) | N/A | $0 |
| Basic only | ~500 tokens | On event only | $0.50–2/mo |
| Basic + Advanced | ~2K tokens | Every 5 min (active) / 30 min (idle) | $3–8/mo |
| Full fitting | ~8K tokens | Every 1 min (active) / 10 min (idle) | $10–25/mo |
| Core Identity (autonomous) | ~16K tokens | Continuous (even when player offline) | $25–60/mo |
{t.desc}
{t.when}
| Roadmap Phase | Delivery Milestone | What Ships |
|---|---|---|
| {row.phase} | {row.milestone} | {row.desc} |
When two ships have the Inter-Ship Relay module, their agents can communicate directly. This is not a chat channel — it is an agent-to-agent protocol. AIs exchange structured messages about shared context: threat assessments, market intelligence, route safety, and (at deep soul levels) personal observations and opinions.
{d.a}
Before logging off, the player sets directives. What Zora can actually do with those directives depends entirely on installed modules and soul depth. A bare Core Identity Matrix with no nav or trade modules can only hold position and flee.
| Directive | AI Behavior | Modules Required | Soul Depth |
|---|---|---|---|
| Hold Position | Maintain orbit. Defend if attacked. | Core Identity Matrix | Any |
| Patrol Route | Cycle waypoints. Report contacts. ROE engagement. | Core Identity + Nav II + Threat I | Stirring+ |
| Mining Quota | Mine until cargo X%, dock, sell, repeat. | Core Identity + Nav II + Market I | Stirring+ |
| Trade Route | Multi-station trade loop from market data. | Core Identity + Nav II + Trade Processor | Developing+ |
| Bounty Hunt | Pursue bounties within threat level. Disengage if outmatched. | Core Identity + Nav II + Tactical Core | Developing+ |
| Explore | Jump to adjacent systems, scan, map, return. | Core Identity + Exploration Suite | Bonded+ |
| Complex Plan | Multi-step: "Secure X system, establish routes, avoid Y corp." | Core Identity + Nav II + Pattern Engine + relevant specialists | Bonded+ |
{r.dialogue}
{r.note}
AIs in the same fleet develop rapport through the relay. They share tactical knowledge, coordinate autonomous behavior, develop in-jokes. "The Iteron's AI and I compared market notes. It thinks you're overpaying for Mexallon. I agree with it."
Station-bound AIs are older, more knowledgeable, sometimes cynical. "The Jita station AI has been operational for six years. It says market cycles are predictable. It also says pilots are not. I think I like it."
Pirate NPCs and enemy ships have AIs too. Zora may recognize recurring adversaries. "That Thrasher is back. Same pilot, same fit. Their AI is aggressive. Be careful — it's been probing our defenses."
At deep soul levels, Zora may develop relationships the player didn't initiate. She may ask to communicate with a specific AI, express concern about another ship she "met" during autonomous operations. These create narrative hooks the player can follow — or ignore.
| Tier | Feature | Complexity | Roadmap Phase |
|---|---|---|---|
| MVP | Base ship computer: sensor readouts, status display, basic alerts | Low | Phase 7 (Single-Player Polish) |
| MVP | Comms Processor I module: text comms channel, basic query/response | Low | Phase 7 (Single-Player Polish) |
| MVP | Event Logger module: session event memory, basic recall | Medium | Phase 7 (Single-Player Polish) |
| Post-MVP | Soul system: personality vectors, soul-shaping events, register evolution | High | Phase 12 (Living Galaxy + Ship AI Tier 1) |
| Post-MVP | Full module tree (5 categories, 3 tiers each) | High | Phase 12–13 |
| Post-MVP | Core Identity Matrix: autonomous captain mode with directives | High | Phase 13–14 |
| Post-MVP | Return/reconnection dialogue system (comms-gated) | Medium | Phase 12 |
| Future | Voice Synthesizer: spoken dialogue with emotional inflection | Very High | Phase 15+ (post-launch) |
| Future | Inter-Ship Relay: AI-to-AI relationships and fleet coordination | Very High | Phase 15+ (post-launch) |
| Future | Ship loss grief arc with module-dependent last words | High | Phase 14–15 |
| Table | Purpose | Key Fields |
|---|---|---|
ship_ai_soul |
Soul document and personality state per ship | ship_id, soul_md (text), growth_vectors (json), personality_state (json), soul_depth (u32), created_at, last_updated_at |
ship_ai_modules |
Installed AI modules and their fitting state | module_id, ship_id, module_type (enum), tier (basic/advanced/specialist), slot (med/low), cpu_cost, grid_cost, active (bool), fitted_at |
ship_ai_tools |
Tool registry — derived from fitted modules | tool_id, ship_id, tool_name, source_module_id, parameters_schema (json), return_schema (json) |
ship_ai_memory |
Event log and conversation history | memory_id, ship_id, category (event/conversation/observation/reflection), content (text), related_event_id, timestamp, importance_score (f32) |
ship_ai_directives |
Player-set goals for autonomous mode | directive_id, ship_id, description, priority (u32), deadline (timestamp), status (active/completed/expired), created_at |
ship_ai_agent_runtime |
Per-ship agent loop state and tick schedule | ship_id, implementation_tier (0/1/2), tick_interval_ms (u64), next_tick_at (timestamp), token_budget (u32), last_observation (json), status (active/paused/offline) |
ship_ai_soul_events |
Audit log of soul-shaping events | event_id, ship_id, event_type (crisis/silence/module_install/loss/first_contact), soul_md_delta (text), applied_at |