C2C — Core to Cosmos
Space strategy game shipping with yakmesh — the first application built on the full protocol stack.
What is C2C?
Core to Cosmos (C2C) is a space strategy game with procedural planet generation, AI-driven factions, and NPU-accelerated gameplay. It ships alongside yakmesh as a showcase application demonstrating real-world use of the protocol stack.
Tech Stack
- React + Vite frontend
- Node.js / Express backend
- SQLite database
- 391 art assets
- 85/85 tests passing
NPU Models
- 8 AI models via DirectML
- Planet generation & super-resolution
- Faction AI decision-making
- Combat prediction
- Adaptive threat scaling
Yakmesh Integration
C2C uses several yakmesh subsystems for networking, encryption, time synchronization, and distributed compute:
| Yakmesh System | C2C Usage |
|---|---|
| ANNEX | ML-KEM-768 encrypted WebSocket connections between game server and clients |
| SEVA | 5 NPU model slots (planet-variation, planet-heightmap, planet-superres, faction-brain, combat-predict) shared across the mesh |
| TIVRA | Hardware detection and ONNX model loading for local NPU inference |
| MANI | Authoritative game clock — every tick, mutation, and NPU inference uses MANI time |
| KATHA | In-game chat integrated via KOMM WebSocket |
| Studio | Story mode for game chronicles and faction narratives |
SEVA Model Slots
C2C registers 5 model slots with the SEVA compute sharing protocol. When a player's machine lacks an NPU, SEVA transparently routes inference to a peer node that has one:
planet-variation
Generates planet variations from metadata. Input: 8-float parameter vector. Runs on NPU for real-time planet customization.
planet-heightmap
Procedural terrain heightmaps for planet surfaces. Creates unique geography per planet seed.
planet-superres
Super-resolution upscaling of planet textures. Low-res textures upscaled on NPU for visual quality.
faction-brain
AI faction decision-making. Scores actions, picks strategies, generates faction narratives, handles diplomacy.
combat-predict
Combat outcome prediction for battle resolution. Predicts winner probability given force composition.
Fallback Chain
C2C's client-side NPU integration uses a transparent fallback chain. The player never knows which path was used — the experience is identical:
- HTTP API — Direct ONNX inference on game server's NPU/GPU
- WebSocket seva:work — If HTTP fails, route via WebSocket to server's NPU pool
- Mesh offload — If local server has no NPU, SEVA finds a mesh peer with one
- CPU fallback — Software computation, always available, always correct
Building Your Own Realm
C2C uses the Adapter pattern for realms.
Each realm is a self-contained folder in c2c/server/realms/ with a manifest and
an optional narrative module. The server discovers and loads all realms at boot.
Realm Folder Structure
c2c/server/realms/
your-realm/
manifest.json # Required — realm definition
narrative.js # Optional — NPU narrative voice
Manifest Skeleton
The manifest.json defines everything the server needs to register your realm,
create NPC factions, and drive the story arc system. Here is the minimum required structure:
{
"id": "my-realm",
"name": "My Realm",
"slug": "my-realm",
"mode": "sandbox", // sandbox | coop-pve | pvp
"description": "A custom realm for...",
"max_players": 100,
"config": {
"aesthetic": {
"palette": ["#0A0A1A", "#2D1B69", "#FF6600"],
"theme": "nebula-dark",
"accent": "#FF6600"
},
"gameplay": {
// Your realm-specific game rules
}
},
"factions": [ /* ... */ ],
"npcs": [ /* ... */ ],
"arcs": [ /* ... */ ]
}
Game Modes
| Mode | Description |
|---|---|
sandbox |
Open-ended play, no NPC antagonist, player-driven economy |
coop-pve |
Players unite against NPU-driven NPC factions (e.g. Obsidian Scion) |
pvp |
Player-vs-player competitive with faction allegiances |
Defining Factions
Each faction has a personality that drives the NPU decision-making, custom units, buildings, and mutable state that evolves as arcs progress:
{
"name": "The Swarm",
"tag": "SWRM",
"faction_type": "npc", // npc | player
"alignment": "hostile", // hostile | friendly | neutral
"capabilities": {
"units": [
{ "id": "drone", "name": "Hive Drone",
"attack": 60, "hull": 150, "shield": 20, "speed": 12000,
"desc": "Fast expendable swarm unit." }
],
"buildings": [
{ "id": "hive_spire", "name": "Hive Spire",
"desc": "Spawns drones. More spires = faster spawn rate." }
]
},
"personality": {
"aggression": 0.9,
"expansion_priority": 0.8,
"diplomacy_willingness": 0.0,
"target_preference": "nearest_first",
"retreat_threshold": 0.05,
"npu_voice": "hive_queen" // Links to narrative.js voice
},
"state": {
"phase": "dormant",
"planets_controlled": 0,
"threat_level": 0
}
}
Story Arcs
Arcs are narrative phases that unlock progressively. Each arc has a trigger condition and rewards. The server evaluates triggers every realm tick (30 seconds):
{
"name": "First Contact",
"slug": "first_contact",
"phase_number": 2,
"trigger_type": "event", // player_count | event |
// faction_state | community_goal
"trigger_config": {
"event": "alien_base_discovered",
"count": 1
},
"rewards_config": {
"resources": { "metal": 15000, "crystal": 10000, "deuterium": 5000 },
"npc_unlock": "aktai"
},
"description": "An alien scout probe is detected..."
}
| Trigger Type | Fires When |
|---|---|
player_count |
Realm reaches min_players members |
event |
A game event fires N times (discovery, combat, etc.) |
faction_state |
NPC faction state matches a condition (e.g. planets_controlled >= 5) |
community_goal |
Players collectively reach a threshold (alliance size, research, etc.) |
NPCs
NPCs are quest givers, antagonists, or wild cards. They appear when their arc unlocks and speak through the narrative module:
{
"id": "hive_queen",
"name": "The Hive Queen",
"role": "antagonist", // quest_giver | antagonist |
// mini_boss | wild_card
"title": "Mother of Drones",
"bio": "A vast intelligence distributed across a million bodies...",
"appears_in_arc": "first_contact",
"dialogue_tags": ["alien", "collective", "hungry"]
}
Narrative Voice Module
The optional narrative.js gives your realm a unique writing voice.
It exports vocabulary, dialogue templates, and event narration that the server
uses for chat messages, notifications, and arc descriptions:
// c2c/server/realms/my-realm/narrative.js
import { createLogger } from '../../lib/logger.js';
const log = createLogger('narrative');
const _registry = {};
export function register(realmSlug) {
_registry.slug = realmSlug;
log.info({ realmSlug }, 'My realm voice registered');
}
// Vocabulary pools — used by the server for procedural narration
export const ADJECTIVES = [
'chitinous', 'swarming', 'relentless', 'buzzing', 'vast',
];
export const VERBS = [
'swarm over', 'consume', 'burrow into', 'engulf', 'devour',
];
// NPC dialogue templates ($LOCATION replaced at runtime)
export const NPC_DIALOGUE = {
hive_queen: {
greeting: [
'We are many. You are few. The arithmetic is clear.',
'Every world you lose feeds a thousand of our young.',
],
mission_brief: [
'The hive detects weakness at $LOCATION. We hunger.',
],
},
};
Tech Tree Extensions
Realms can define custom technologies that unlock through arc progression. Each tech has resource costs, research time, and a description:
"tech_tree_extensions": {
"hive_biotech": {
"unlock_condition": "arc:first_contact",
"techs": [
{
"id": "chitin_armour",
"name": "Chitin Plating",
"cost": { "metal": 30000, "crystal": 15000 },
"time": 5400,
"desc": "Armour harvested from drone carapaces. +10% hull."
}
]
}
}
How It Works
Drop your realm folder into c2c/server/realms/ and restart the server.
The realm loader auto-discovers it, registers the realm in the database,
inserts factions and arcs, and loads the narrative module. No code changes needed.
See the built-in obsidian-scion/ realm for a complete reference implementation
with 6 story arcs, 6 NPCs, 2 factions, custom tech trees, and a full narrative voice.
AI Profiles
AI Profiles give players control over NPC faction behaviour. Instead of being locked to the personality baked into a realm manifest, players can select preset profiles, build custom personalities via sliders, or describe one in plain text and let the NPU generate a personality vector.
Three Tiers
| Tier | Source | How |
|---|---|---|
| Preset | Realm manifest | Select from built-in profiles — Berserker, Turtle, Diplomat, Expansionist, Balanced |
| Custom | Slider UI | Set each personality axis (aggression, expansion, diplomacy, target pref, retreat threshold) manually |
| NPU-Generated | Text description | Describe the AI you want in plain language — the NPU faction-brain model maps it to a personality vector |
Personality Shape
Every profile stores the same personality object used by NPC factions. The SEVA faction-brain model reads these numbers to drive NPC decision-making via NPU inference.
{
"aggression": 0.85, // 0 = pacifist, 1 = berserk
"expansion_priority": 0.9, // 0 = hunker down, 1 = claim everything
"diplomacy_willingness": 0.0, // 0 = no talks, 1 = always negotiate
"target_preference": "weakest_first", // weakest_first | strongest_first | nearest | defensive
"retreat_threshold": 0.15 // 0 = never retreat, 1 = flee at first scratch
}
Adding Presets to a Manifest
Realm creators add an ai_profiles array to their manifest.json.
The realm loader seeds them into the database automatically at boot.
"ai_profiles": [
{
"name": "Berserker",
"description": "All-out aggression. Attacks relentlessly, never retreats.",
"personality": {
"aggression": 1.0,
"expansion_priority": 0.7,
"diplomacy_willingness": 0.0,
"target_preference": "strongest_first",
"retreat_threshold": 0.0
},
"dialogue_tags": ["fierce", "reckless", "relentless"]
}
]
API Endpoints
| Method | Endpoint | Description |
|---|---|---|
GET |
/realms/:id/ai-profiles |
List presets + your custom profiles |
POST |
/realms/:id/ai-profiles |
Create a custom profile |
PUT |
/realms/:id/ai-profiles/:profileId |
Update your custom profile |
DELETE |
/realms/:id/ai-profiles/:profileId |
Delete your custom profile |
POST |
/realms/:id/ai-profiles/:profileId/apply |
Apply a profile to a faction |
POST |
/realms/:id/ai-profiles/generate |
NPU-generate a profile from text |
NPU Generation Example
Describe what you want in natural language. The faction-brain SEVA slot converts it into a personality vector using keyword extraction (CPU fallback) or NPU inference (when SEVA is online).
// POST /realms/:realmId/ai-profiles/generate
const res = await fetch(`/api/game/realms/${realmId}/ai-profiles/generate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
description: 'A ruthless conqueror who crushes the weak and expands relentlessly across every star system'
})
});
const { profile } = await res.json();
// profile.personality → { aggression: 0.95, expansion_priority: 0.9, ... }
// profile.dialogue_tags → ["fierce"]
// profile.source → "npu_generated"
Applying a Profile
Once created or selected, apply a profile to any NPC faction in your realm. The personality vector merges
into the faction's existing config — faction-specific fields like npu_voice
and taunts are preserved, while the core personality axes get overwritten
with your chosen profile.
Up to 20 custom profiles per realm per player. Presets are unlimited and shared across all players.
Version History
| Version | Changes |
|---|---|
| v3.0.0 | C2C ships with yakmesh. Full SEVA integration, 8 AI models, MANI time protocol, ANNEX encryption, 391 art assets, 85/85 tests. |