History: AI-driven alternate-history simulator
Pax Historia-style sim where the LLM is the world engine.
- React 19 + Vite 6 + Tailwind v4 + shadcn/ui frontend
- Express single-port backend (/api + /sse + built client + SPA fallback)
- SQLite (better-sqlite3) persistence, one row per game
- MapLibre choropleth map (OpenFreeMap dark + ISO_A3 regions)
- Defensive turn loop: strip fences, balanced-{} extract, parse, clamp 0-100,
retry-once nudge, generic 'unclear' fallback; never crashes on bad output
- 5 seed presets (wwii-1939, coldwar-1955, modern-2025, no-wwii-1940, aegis-2400)
- LLM client over native fetch w/ injectable transport (mesh-bot pattern);
LLM_STUB=1 deterministic transport for tests/e2e
- Unit (vitest, 19) + deterministic Playwright e2e
- Multi-stage node:22-slim Docker + Traefik (history.dev.kkhost.pl:4321)
Co-Authored-By: OpenCode <opencode@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"id": "aegis-2400",
|
||||
"title": "The Stellar Concord",
|
||||
"startDate": "2400-01-01",
|
||||
"summary": "Humanity spans the solar system in five warring polities. Rule a faction in the far-future cold war.",
|
||||
"worldBackground": "The year is 2400. Four centuries after the first orbital colonies, humanity is no longer a single species of Earth but a family of polities spread across the solar system. The Stellar Concord — a fragile truce brokered after the Collapse of 2361 — binds them together more by mutual interest than by love. Each polity guards its own domain, its own economy, and its own vision of what humanity should become.\n\nEarth's Union holds the ancestral world and its teeming population. The Orbital Ring dominates the cislunar economy and the fold-gate transit lanes. The Red Collective of Mars has turned the desert into a forge and dreams of independence. The Outer Reach commands the ice-moons and the helium-3 that powers everything. The Deep Void, the most remote and the strangest, watches from the outer dark and plays long games. You are the ruler of one of these powers — and the Concord is only as strong as its weakest treaty.",
|
||||
"simulationRules": [
|
||||
"Science-fiction tone, but grounded and strategic: treat it like a cold war among space-faring civilizations.",
|
||||
"Prefer gradual change: 1-4 events per turn; polities rise and fall over generations, not weeks.",
|
||||
"Respect each polity's domain (its claimed regions) unless a decisive war or trade shift changes ownership.",
|
||||
"No single polity may dominate the entire solar system; the Concord keeps the balance.",
|
||||
"Resources — helium-3, fold-gates, shipbuilding — are the true currency of power.",
|
||||
"Diplomacy, espionage, and economic leverage are the primary tools; full war is last and costly.",
|
||||
"Keep all stat values between 0 and 100."
|
||||
],
|
||||
"nations": [
|
||||
{
|
||||
"id": "terra",
|
||||
"name": "Earth Union",
|
||||
"type": "major",
|
||||
"stats": { "military": 80, "economy": 90, "stability": 85, "population": 100 },
|
||||
"territory": ["GBR", "FRA", "DEU", "ITA", "ESP", "RUS", "UKR", "CHN", "IND"],
|
||||
"relations": { "orbital": "ally", "mars": "rival", "outer": "hostile", "deep": "hostile" }
|
||||
},
|
||||
{
|
||||
"id": "orbital",
|
||||
"name": "The Orbital Ring",
|
||||
"type": "major",
|
||||
"stats": { "military": 70, "economy": 95, "stability": 80, "population": 60 },
|
||||
"territory": ["USA", "CAN", "MEX", "BRA"],
|
||||
"relations": { "terra": "ally", "mars": "ally", "outer": "rival", "deep": "hostile" }
|
||||
},
|
||||
{
|
||||
"id": "mars",
|
||||
"name": "Red Collective",
|
||||
"type": "faction",
|
||||
"stats": { "military": 75, "economy": 70, "stability": 75, "population": 40 },
|
||||
"territory": ["AUS", "NZL", "SAU"],
|
||||
"relations": { "terra": "rival", "orbital": "ally", "outer": "neutral", "deep": "rival" }
|
||||
},
|
||||
{
|
||||
"id": "outer",
|
||||
"name": "The Outer Reach",
|
||||
"type": "major",
|
||||
"stats": { "military": 60, "economy": 80, "stability": 70, "population": 30 },
|
||||
"territory": ["JPN", "KOR", "MNG", "EGY"],
|
||||
"relations": { "terra": "hostile", "orbital": "rival", "mars": "neutral", "deep": "ally" }
|
||||
},
|
||||
{
|
||||
"id": "deep",
|
||||
"name": "The Deep Void",
|
||||
"type": "faction",
|
||||
"stats": { "military": 50, "economy": 55, "stability": 65, "population": 20 },
|
||||
"territory": ["ZAF", "NGA", "KEN"],
|
||||
"relations": { "terra": "hostile", "orbital": "hostile", "mars": "rival", "outer": "ally" }
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
{
|
||||
"id": "coldwar-1955",
|
||||
"title": "The Cold War",
|
||||
"startDate": "1955-01-01",
|
||||
"summary": "Two superpowers, one world. Proxy wars, space races, and the ever-present shadow of the bomb.",
|
||||
"worldBackground": "It is 1955. The Second World War is over, and the world is split into two armed camps. The United States and its Western allies command industrial might and a growing nuclear arsenal; the Soviet Union and its bloc answer with vast manpower, a sprawling industrial base, and a rival nuclear program. Neither side can win a direct war without risking mutual annihilation, so the contest is fought everywhere else — in Berlin, in Korea, in the new space race, and in the non-aligned world.\n\nThe superpowers court the nations of the Global South, fund coups and revolutions, and trade in influence as much as in dollars and rubles. The nuclear arms race defines every decision: every treaty, every test, every missile site. You are the leader of one of these powers — or a key player on one side of the divide — and you must outlast your rival without starting the war that ends everything.",
|
||||
"simulationRules": [
|
||||
"Serious, historically-grounded tone appropriate to the early Cold War era.",
|
||||
"Prefer gradual change: 1-4 events per turn; the balance of the superpowers shifts slowly.",
|
||||
"Nuclear escalation is catastrophic and rare; avoid it unless the player explicitly risks it.",
|
||||
"Respect existing borders (the Iron Curtain) unless a major political or military shift occurs.",
|
||||
"No single nation may dominate the world; the two blocs remain in uneasy equilibrium.",
|
||||
"Proxy conflicts and espionage are the primary arenas of competition.",
|
||||
"Keep all stat values between 0 and 100."
|
||||
],
|
||||
"nations": [
|
||||
{
|
||||
"id": "us",
|
||||
"name": "United States",
|
||||
"type": "major",
|
||||
"stats": { "military": 95, "economy": 95, "stability": 75, "population": 85 },
|
||||
"territory": ["USA", "CAN", "MEX"],
|
||||
"relations": { "su": "hostile", "uk": "ally", "cn": "hostile", "wdg": "ally", "fr": "ally" }
|
||||
},
|
||||
{
|
||||
"id": "su",
|
||||
"name": "Soviet Union",
|
||||
"type": "major",
|
||||
"stats": { "military": 90, "economy": 70, "stability": 80, "population": 100 },
|
||||
"territory": ["RUS", "UKR", "BLR", "GEO", "KAZ"],
|
||||
"relations": { "us": "hostile", "uk": "neutral", "cn": "ally", "wdg": "hostile", "fr": "neutral" }
|
||||
},
|
||||
{
|
||||
"id": "uk",
|
||||
"name": "United Kingdom",
|
||||
"type": "major",
|
||||
"stats": { "military": 70, "economy": 70, "stability": 75, "population": 55 },
|
||||
"territory": ["GBR", "IRL"],
|
||||
"relations": { "us": "ally", "su": "neutral", "cn": "neutral", "wdg": "ally", "fr": "ally" }
|
||||
},
|
||||
{
|
||||
"id": "cn",
|
||||
"name": "People's Republic of China",
|
||||
"type": "major",
|
||||
"stats": { "military": 80, "economy": 40, "stability": 85, "population": 100 },
|
||||
"territory": ["CHN", "MNG"],
|
||||
"relations": { "us": "hostile", "su": "ally", "uk": "neutral", "wdg": "hostile", "fr": "neutral" }
|
||||
},
|
||||
{
|
||||
"id": "fr",
|
||||
"name": "France",
|
||||
"type": "major",
|
||||
"stats": { "military": 60, "economy": 65, "stability": 70, "population": 60 },
|
||||
"territory": ["FRA", "DZA"],
|
||||
"relations": { "us": "ally", "su": "neutral", "uk": "ally", "cn": "neutral", "wdg": "ally" }
|
||||
},
|
||||
{
|
||||
"id": "wdg",
|
||||
"name": "West Germany",
|
||||
"type": "major",
|
||||
"stats": { "military": 40, "economy": 60, "stability": 65, "population": 60 },
|
||||
"territory": ["DEU"],
|
||||
"relations": { "us": "ally", "su": "hostile", "uk": "ally", "cn": "hostile", "fr": "ally" }
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
[
|
||||
{
|
||||
"id": "wwii-1939",
|
||||
"title": "World War II",
|
||||
"startDate": "1939-09-01",
|
||||
"summary": "The guns of September. Lead a major power through the greatest conflict in history."
|
||||
},
|
||||
{
|
||||
"id": "coldwar-1955",
|
||||
"title": "The Cold War",
|
||||
"startDate": "1955-01-01",
|
||||
"summary": "Two superpowers, one world. Proxy wars, space races, and the ever-present shadow of the bomb."
|
||||
},
|
||||
{
|
||||
"id": "modern-2025",
|
||||
"title": "Modern Day",
|
||||
"startDate": "2025-01-01",
|
||||
"summary": "A multipolar world of blocs, sanctions, and tech supremacy. Manage statecraft in the 21st century."
|
||||
},
|
||||
{
|
||||
"id": "no-wwii-1940",
|
||||
"title": "The Great Power Balance",
|
||||
"startDate": "1940-01-01",
|
||||
"summary": "A 1939 Anglo-German pact averted total war. Will the tense peace hold, or fracture into something worse?"
|
||||
},
|
||||
{
|
||||
"id": "aegis-2400",
|
||||
"title": "The Stellar Concord",
|
||||
"startDate": "2400-01-01",
|
||||
"summary": "Humanity spans the solar system in five warring polities. Rule a faction in the far-future cold war."
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,66 @@
|
||||
{
|
||||
"id": "modern-2025",
|
||||
"title": "Modern Day",
|
||||
"startDate": "2025-01-01",
|
||||
"summary": "A multipolar world of blocs, sanctions, and tech supremacy. Manage statecraft in the 21st century.",
|
||||
"worldBackground": "It is 2025. The world is multipolar and hyper-connected. A small number of powers — the United States, China, Russia, the European Union, India, and Japan — set the direction of a global economy that is both deeply interdependent and increasingly fragmented by trade wars, sanctions, and technology races. Power now flows as much through chips and data as through armies, and through finance and shipping lanes as through borders.\n\nThe great challenges are shared and political: climate, the balance of economic power, the spread of autonomous weapons, and the struggle for influence across the oceans and the Arctic. You lead one of these powers. Your tools are sanctions, alliances, trade, cyber capability, and — always in the background — the military. How you manage the great-power competition over the coming years will reshape the world order.",
|
||||
"simulationRules": [
|
||||
"Serious, contemporary tone; write like a foreign-affairs desk at a major newsroom.",
|
||||
"Prefer gradual change: 1-4 events per turn; great-power rivalry shifts incrementally.",
|
||||
"Modern warfare favors economic, cyber, and proxy instruments over large conventional wars; keep full-scale wars exceptional.",
|
||||
"Respect existing borders; territorial change requires a major war or a decisive political event.",
|
||||
"No single nation may dominate the world; the system stays multipolar.",
|
||||
"Trade, sanctions, technology, and alliances are the primary levers of power.",
|
||||
"Keep all stat values between 0 and 100."
|
||||
],
|
||||
"nations": [
|
||||
{
|
||||
"id": "us",
|
||||
"name": "United States",
|
||||
"type": "major",
|
||||
"stats": { "military": 95, "economy": 95, "stability": 70, "population": 85 },
|
||||
"territory": ["USA", "CAN", "MEX", "BRA"],
|
||||
"relations": { "cn": "hostile", "ru": "hostile", "eu": "ally", "in": "neutral", "jp": "ally" }
|
||||
},
|
||||
{
|
||||
"id": "cn",
|
||||
"name": "China",
|
||||
"type": "major",
|
||||
"stats": { "military": 85, "economy": 90, "stability": 80, "population": 100 },
|
||||
"territory": ["CHN", "MNG"],
|
||||
"relations": { "us": "hostile", "ru": "ally", "eu": "rival", "in": "rival", "jp": "hostile" }
|
||||
},
|
||||
{
|
||||
"id": "ru",
|
||||
"name": "Russia",
|
||||
"type": "major",
|
||||
"stats": { "military": 85, "economy": 55, "stability": 70, "population": 80 },
|
||||
"territory": ["RUS", "KAZ", "BLR"],
|
||||
"relations": { "us": "hostile", "cn": "ally", "eu": "hostile", "in": "ally", "jp": "hostile" }
|
||||
},
|
||||
{
|
||||
"id": "eu",
|
||||
"name": "European Union",
|
||||
"type": "alliance",
|
||||
"stats": { "military": 60, "economy": 85, "stability": 75, "population": 90 },
|
||||
"territory": ["GBR", "DEU", "FRA", "ITA", "ESP", "PRT", "NLD", "BEL", "SWE", "NOR", "POL", "CZE"],
|
||||
"relations": { "us": "ally", "cn": "rival", "ru": "hostile", "in": "neutral", "jp": "ally" }
|
||||
},
|
||||
{
|
||||
"id": "in",
|
||||
"name": "India",
|
||||
"type": "major",
|
||||
"stats": { "military": 70, "economy": 70, "stability": 75, "population": 100 },
|
||||
"territory": ["IND"],
|
||||
"relations": { "cn": "rival", "us": "neutral", "ru": "ally", "eu": "neutral", "jp": "ally" }
|
||||
},
|
||||
{
|
||||
"id": "jp",
|
||||
"name": "Japan",
|
||||
"type": "major",
|
||||
"stats": { "military": 55, "economy": 80, "stability": 85, "population": 60 },
|
||||
"territory": ["JPN"],
|
||||
"relations": { "us": "ally", "cn": "hostile", "ru": "hostile", "eu": "ally", "in": "ally" }
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
{
|
||||
"id": "no-wwii-1940",
|
||||
"title": "The Great Power Balance",
|
||||
"startDate": "1940-01-01",
|
||||
"summary": "A 1939 Anglo-German pact averted total war. Will the tense peace hold, or fracture into something worse?",
|
||||
"worldBackground": "In 1939, a stunning Anglo-German non-aggression pact averted the war that history remembers. Europe in 1940 is not burning — it is holding its breath. Germany is industrializing into a continental colossus but has been checked at the diplomatic border; Britain, spared a war on two fronts, is consolidating its empire and its navy; France, the old continent's center of gravity, watches nervously. The Soviet Union has turned inward and is quietly building the largest army in human history. Across the Pacific, Japan and the United States circle each other over Asia and the seas.\n\nThis is a world of fragile, knife-edge balances. Every alliance can be a future front. Every trade deal a hidden tripwire. You are a great power in this alternate 1940, and you have been handed a peace — for now. Manage it, or break it.",
|
||||
"simulationRules": [
|
||||
"A counterfactual, but keep it historically grounded and internally consistent.",
|
||||
"Serious tone; write like a historian describing a world that almost was.",
|
||||
"Prefer gradual change: 1-4 events per turn; the peace is fragile but not yet broken.",
|
||||
"Respect the (altered) 1940 borders; a break in the peace is a major, hard-won event.",
|
||||
"No single nation may dominate the world; the balance of power is the defining feature.",
|
||||
"Treat the absence of a world war as the baseline, not the exception.",
|
||||
"Keep all stat values between 0 and 100."
|
||||
],
|
||||
"nations": [
|
||||
{
|
||||
"id": "uk",
|
||||
"name": "United Kingdom",
|
||||
"type": "major",
|
||||
"stats": { "military": 75, "economy": 80, "stability": 85, "population": 60 },
|
||||
"territory": ["GBR", "IRL", "IND", "AUS", "CAN"],
|
||||
"relations": { "de": "neutral", "fr": "ally", "us": "neutral", "su": "neutral", "jp": "rival" }
|
||||
},
|
||||
{
|
||||
"id": "de",
|
||||
"name": "German Reich",
|
||||
"type": "major",
|
||||
"stats": { "military": 80, "economy": 80, "stability": 80, "population": 85 },
|
||||
"territory": ["DEU", "AUT"],
|
||||
"relations": { "uk": "neutral", "fr": "neutral", "us": "neutral", "su": "hostile", "jp": "neutral" }
|
||||
},
|
||||
{
|
||||
"id": "fr",
|
||||
"name": "France",
|
||||
"type": "major",
|
||||
"stats": { "military": 70, "economy": 75, "stability": 80, "population": 70 },
|
||||
"territory": ["FRA", "BEL", "LUX"],
|
||||
"relations": { "uk": "ally", "de": "neutral", "us": "neutral", "su": "hostile", "jp": "neutral" }
|
||||
},
|
||||
{
|
||||
"id": "us",
|
||||
"name": "United States",
|
||||
"type": "major",
|
||||
"stats": { "military": 65, "economy": 90, "stability": 85, "population": 80 },
|
||||
"territory": ["USA", "MEX", "BRA"],
|
||||
"relations": { "uk": "neutral", "de": "neutral", "fr": "neutral", "su": "neutral", "jp": "rival" }
|
||||
},
|
||||
{
|
||||
"id": "su",
|
||||
"name": "Soviet Union",
|
||||
"type": "major",
|
||||
"stats": { "military": 75, "economy": 60, "stability": 90, "population": 95 },
|
||||
"territory": ["RUS", "UKR", "GEO"],
|
||||
"relations": { "uk": "neutral", "de": "hostile", "fr": "hostile", "us": "neutral", "jp": "hostile" }
|
||||
},
|
||||
{
|
||||
"id": "jp",
|
||||
"name": "Empire of Japan",
|
||||
"type": "major",
|
||||
"stats": { "military": 80, "economy": 60, "stability": 75, "population": 85 },
|
||||
"territory": ["JPN", "KOR"],
|
||||
"relations": { "us": "rival", "uk": "rival", "de": "neutral", "su": "hostile", "fr": "neutral" }
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"id": "wwii-1939",
|
||||
"title": "World War II",
|
||||
"startDate": "1939-09-01",
|
||||
"summary": "The guns of September. Lead a major power through the greatest conflict in history.",
|
||||
"worldBackground": "It is early September 1939. Germany has just invaded Poland, and Britain and France have declared war. Europe stands on the edge of the largest conflict the world has ever seen. The Axis powers — Germany, Italy, and Japan — are pressing their advantage across Europe and the Pacific, while the Allies — Britain, France, the Soviet Union, and a still-neutral but industrially immense United States — are marshalling their strength.\n\nThe balance of power is delicate. Germany's army is the most battle-hardened force on the continent, but its resources are finite and its flanks exposed. Britain commands the seas but is an island nation. The Soviet Union has a vast army and deep territory but a fragile industrial base. The United States has unmatched economic power but is geographically isolated and politically divided over entry into the war.\n\nYou are the head of one of these nations. Every decision you make — military, economic, or diplomatic — ripples across the world and reshapes the map, the alliances, and the fate of hundreds of millions.",
|
||||
"simulationRules": [
|
||||
"Serious, historically-plausible tone; write like a war correspondent and a policy analyst combined.",
|
||||
"Prefer gradual change: 1-4 meaningful events per turn, never a single decisive world-ending event.",
|
||||
"Respect existing borders unless a war is declared or a decisive military shift occurs.",
|
||||
"No single nation may instantly dominate the world; power shifts are incremental.",
|
||||
"Respect the player's chosen nation's resources, manpower, and geography.",
|
||||
"Diplomacy can shift relations over time but rarely reverses a declared war in one turn.",
|
||||
"Keep stat values (military, economy, stability, population) between 0 and 100."
|
||||
],
|
||||
"nations": [
|
||||
{
|
||||
"id": "de",
|
||||
"name": "German Reich",
|
||||
"type": "major",
|
||||
"stats": { "military": 95, "economy": 70, "stability": 75, "population": 90 },
|
||||
"territory": ["DEU"],
|
||||
"relations": { "uk": "hostile", "fr": "hostile", "us": "neutral", "it": "ally", "su": "neutral", "jp": "ally" }
|
||||
},
|
||||
{
|
||||
"id": "uk",
|
||||
"name": "United Kingdom",
|
||||
"type": "major",
|
||||
"stats": { "military": 80, "economy": 75, "stability": 60, "population": 48 },
|
||||
"territory": ["GBR", "IRL", "IND"],
|
||||
"relations": { "de": "hostile", "us": "neutral", "fr": "ally", "su": "neutral", "jp": "neutral", "it": "hostile" }
|
||||
},
|
||||
{
|
||||
"id": "fr",
|
||||
"name": "France",
|
||||
"type": "major",
|
||||
"stats": { "military": 70, "economy": 60, "stability": 45, "population": 70 },
|
||||
"territory": ["FRA", "DZA"],
|
||||
"relations": { "de": "hostile", "uk": "ally", "us": "neutral", "su": "neutral", "it": "hostile", "jp": "neutral" }
|
||||
},
|
||||
{
|
||||
"id": "su",
|
||||
"name": "Soviet Union",
|
||||
"type": "major",
|
||||
"stats": { "military": 75, "economy": 55, "stability": 70, "population": 100 },
|
||||
"territory": ["RUS", "UKR", "BLR", "GEO"],
|
||||
"relations": { "de": "neutral", "uk": "neutral", "fr": "neutral", "us": "neutral", "it": "hostile", "jp": "hostile" }
|
||||
},
|
||||
{
|
||||
"id": "us",
|
||||
"name": "United States",
|
||||
"type": "major",
|
||||
"stats": { "military": 60, "economy": 95, "stability": 80, "population": 85 },
|
||||
"territory": ["USA", "MEX", "BRA"],
|
||||
"relations": { "uk": "neutral", "de": "neutral", "fr": "neutral", "su": "neutral", "it": "neutral", "jp": "neutral" }
|
||||
},
|
||||
{
|
||||
"id": "jp",
|
||||
"name": "Empire of Japan",
|
||||
"type": "major",
|
||||
"stats": { "military": 85, "economy": 60, "stability": 70, "population": 80 },
|
||||
"territory": ["JPN", "KOR"],
|
||||
"relations": { "us": "neutral", "uk": "neutral", "de": "ally", "it": "ally", "su": "hostile", "fr": "neutral" }
|
||||
},
|
||||
{
|
||||
"id": "it",
|
||||
"name": "Kingdom of Italy",
|
||||
"type": "major",
|
||||
"stats": { "military": 55, "economy": 50, "stability": 60, "population": 60 },
|
||||
"territory": ["ITA", "ALB", "MAR", "TUN"],
|
||||
"relations": { "de": "ally", "uk": "hostile", "fr": "hostile", "us": "neutral", "su": "hostile", "jp": "ally" }
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user