Files
History/shared/types.ts
2026-10-11 14:36:35 +00:00

127 lines
3.2 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Domain types — the single source of truth shared by the frontend (src/), the
// backend (server/), and the LLM prompt contract. No runtime dependencies here.
/** A nation's 0–100 status indices. Every value is clamped to 0–100 by the engine. */
export interface NationStats {
military: number;
economy: number;
stability: number;
population: number;
}
export const STAT_KEYS = ['military', 'economy', 'stability', 'population'] as const;
export type StatKey = (typeof STAT_KEYS)[number];
export type NationType = 'major' | 'minor' | 'power' | 'alliance' | 'faction';
/** Direction of a bilateral diplomatic relationship. */
export type RelationStatus = 'ally' | 'neutral' | 'rival' | 'hostile' | 'war';
export const RELATION_STATUSES: RelationStatus[] = [
'ally',
'neutral',
'rival',
'hostile',
'war',
];
/**
* A single nation in the world. `territory` holds ISO_A3 codes; the map colors
* each of those regions with this nation's stable color (see protocol.nationColor).
*/
export interface Nation {
id: string;
name: string;
type: NationType;
stats: NationStats;
territory: string[];
relations: Record<string, RelationStatus>;
}
/** Categories a narrative event can take. */
export type EventType =
| 'military'
| 'diplomatic'
| 'economic'
| 'political'
| 'social'
| 'disaster'
| 'scientific'
| 'cultural';
export const EVENT_TYPES: EventType[] = [
'military',
'diplomatic',
'economic',
'political',
'social',
'disaster',
'scientific',
'cultural',
];
export type EventOutcome = 'success' | 'failure' | 'partial' | 'neutral';
/** A narrative event the simulation emitted on some turn. */
export interface EventEntry {
id: string;
turn: number;
date: string;
nation: string; // nation id the event concerns
type: EventType;
title: string;
text: string;
outcome: EventOutcome;
}
/**
* A single item queued in the current round, waiting to be committed by a
* "Jump forward". `kind: 'action'` is a free-text player move; `kind:
* 'diplomacy'` is a message to a specific nation (`to`).
*/
export type RoundItem = {
kind: 'action' | 'diplomacy';
text: string;
to?: string;
};
/** The full, persisted state of one game. Saved to SQLite by id. */
export interface GameState {
id: string;
presetId: string;
presetTitle: string;
playerNationId: string;
turn: number;
date: string;
nations: Record<string, Nation>;
events: EventEntry[];
/**
* Actions + diplomatic messages queued this round but not yet committed.
* Adding an item never advances the turn; a "Jump forward" processes the whole
* batch in a single turn and clears this back to `[]`.
*/
pending: RoundItem[];
}
/**
* A scenario the player can start. One JSON file per preset (presets/<id>.json).
* `worldBackground` + `simulationRules` become the LLM system prompt.
*/
export interface Preset {
id: string;
title: string;
startDate: string;
summary: string;
worldBackground: string;
simulationRules: string[];
nations: Nation[];
}
/** The lightweight manifest entry used to render the preset picker cards. */
export interface PresetMeta {
id: string;
title: string;
startDate: string;
summary: string;
}