phase 6: school data, run state, meta-progression, crisis system
- Add school data (Alchemist: H, O, C, Na, S, Fe starting kit) - Add run cycle types: phases, escalation, crisis, body composition - Implement run state management (create, advance phase, discoveries, spores) - Implement meta-progression (codex, spore accumulation, run history) - Implement crisis system (Chemical Plague with neutralization) - Add IndexedDB persistence for meta state - 42 new tests (335 total) Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
183
src/run/types.ts
Normal file
183
src/run/types.ts
Normal file
@@ -0,0 +1,183 @@
|
||||
/**
|
||||
* Run Cycle Types — schools, run phases, meta-progression
|
||||
*
|
||||
* Defines the structure of a single run (birth → death → rebirth)
|
||||
* and the persistent meta-progression between runs.
|
||||
*/
|
||||
|
||||
// ─── Schools ─────────────────────────────────────────────────────
|
||||
|
||||
export interface SchoolData {
|
||||
id: string;
|
||||
name: string;
|
||||
nameRu: string;
|
||||
description: string;
|
||||
descriptionRu: string;
|
||||
/** Starting element symbols (looked up in element registry) */
|
||||
startingElements: string[];
|
||||
/** Quantity of each starting element */
|
||||
startingQuantities: Record<string, number>;
|
||||
/** Scientific principle the school teaches */
|
||||
principle: string;
|
||||
principleRu: string;
|
||||
/** Play style description */
|
||||
playstyle: string;
|
||||
playstyleRu: string;
|
||||
/** Hex color for UI representation */
|
||||
color: string;
|
||||
}
|
||||
|
||||
// ─── Run Phases ──────────────────────────────────────────────────
|
||||
|
||||
/** Phases of a single run in order */
|
||||
export enum RunPhase {
|
||||
Awakening = 0,
|
||||
Exploration = 1,
|
||||
Escalation = 2,
|
||||
Crisis = 3,
|
||||
Resolution = 4,
|
||||
}
|
||||
|
||||
/** Human-readable names for RunPhase */
|
||||
export const RUN_PHASE_NAMES: Record<RunPhase, string> = {
|
||||
[RunPhase.Awakening]: 'Awakening',
|
||||
[RunPhase.Exploration]: 'Exploration',
|
||||
[RunPhase.Escalation]: 'Escalation',
|
||||
[RunPhase.Crisis]: 'Crisis',
|
||||
[RunPhase.Resolution]: 'Resolution',
|
||||
};
|
||||
|
||||
export const RUN_PHASE_NAMES_RU: Record<RunPhase, string> = {
|
||||
[RunPhase.Awakening]: 'Пробуждение',
|
||||
[RunPhase.Exploration]: 'Исследование',
|
||||
[RunPhase.Escalation]: 'Эскалация',
|
||||
[RunPhase.Crisis]: 'Кризис',
|
||||
[RunPhase.Resolution]: 'Развязка',
|
||||
};
|
||||
|
||||
// ─── Crisis Types ────────────────────────────────────────────────
|
||||
|
||||
export type CrisisType = 'chemical-plague';
|
||||
|
||||
export interface CrisisConfig {
|
||||
type: CrisisType;
|
||||
name: string;
|
||||
nameRu: string;
|
||||
description: string;
|
||||
descriptionRu: string;
|
||||
/** Escalation threshold (0-1) at which crisis triggers */
|
||||
triggerThreshold: number;
|
||||
/** Compound that neutralizes the crisis */
|
||||
neutralizer: string;
|
||||
/** Amount needed to neutralize */
|
||||
neutralizeAmount: number;
|
||||
}
|
||||
|
||||
// ─── Run State ───────────────────────────────────────────────────
|
||||
|
||||
/** State of the current run */
|
||||
export interface RunState {
|
||||
/** Unique run identifier */
|
||||
runId: number;
|
||||
/** Selected school id */
|
||||
schoolId: string;
|
||||
/** Current phase */
|
||||
phase: RunPhase;
|
||||
/** Time spent in current phase (ms) */
|
||||
phaseTimer: number;
|
||||
/** Total run elapsed time (ms) */
|
||||
elapsed: number;
|
||||
/** Escalation level 0.0 – 1.0 */
|
||||
escalation: number;
|
||||
/** Whether crisis has been triggered */
|
||||
crisisActive: boolean;
|
||||
/** Whether crisis has been resolved */
|
||||
crisisResolved: boolean;
|
||||
/** Discoveries made this run */
|
||||
discoveries: RunDiscoveries;
|
||||
/** Whether the player is alive */
|
||||
alive: boolean;
|
||||
}
|
||||
|
||||
export interface RunDiscoveries {
|
||||
elements: Set<string>;
|
||||
reactions: Set<string>;
|
||||
compounds: Set<string>;
|
||||
creatures: Set<string>;
|
||||
}
|
||||
|
||||
// ─── Meta-Progression (persists between runs) ────────────────────
|
||||
|
||||
export interface CodexEntry {
|
||||
id: string;
|
||||
type: 'element' | 'reaction' | 'compound' | 'creature';
|
||||
discoveredOnRun: number;
|
||||
}
|
||||
|
||||
export interface MetaState {
|
||||
/** Total spores earned across all runs */
|
||||
spores: number;
|
||||
/** All codex entries (permanent knowledge) */
|
||||
codex: CodexEntry[];
|
||||
/** Total runs completed */
|
||||
totalRuns: number;
|
||||
/** Total deaths */
|
||||
totalDeaths: number;
|
||||
/** Unlocked school ids */
|
||||
unlockedSchools: string[];
|
||||
/** Best run statistics */
|
||||
bestRunTime: number;
|
||||
bestRunDiscoveries: number;
|
||||
/** Run history summaries */
|
||||
runHistory: RunSummary[];
|
||||
}
|
||||
|
||||
export interface RunSummary {
|
||||
runId: number;
|
||||
schoolId: string;
|
||||
duration: number;
|
||||
phase: RunPhase;
|
||||
discoveries: number;
|
||||
sporesEarned: number;
|
||||
crisisResolved: boolean;
|
||||
}
|
||||
|
||||
// ─── Body Composition (for death animation) ──────────────────────
|
||||
|
||||
/** Real elemental composition of the human body (simplified) */
|
||||
export const BODY_COMPOSITION: { symbol: string; fraction: number }[] = [
|
||||
{ symbol: 'O', fraction: 0.65 },
|
||||
{ symbol: 'C', fraction: 0.18 },
|
||||
{ symbol: 'H', fraction: 0.10 },
|
||||
{ symbol: 'N', fraction: 0.03 },
|
||||
{ symbol: 'Ca', fraction: 0.015 },
|
||||
{ symbol: 'P', fraction: 0.01 },
|
||||
{ symbol: 'S', fraction: 0.003 },
|
||||
{ symbol: 'Na', fraction: 0.002 },
|
||||
{ symbol: 'K', fraction: 0.002 },
|
||||
{ symbol: 'Fe', fraction: 0.001 },
|
||||
];
|
||||
|
||||
// ─── Constants ───────────────────────────────────────────────────
|
||||
|
||||
/** Phase durations in ms (approximate, can be adjusted) */
|
||||
export const PHASE_DURATIONS: Record<RunPhase, number> = {
|
||||
[RunPhase.Awakening]: 0, // ends when player leaves Cradle
|
||||
[RunPhase.Exploration]: 180_000, // 3 minutes
|
||||
[RunPhase.Escalation]: 120_000, // 2 minutes
|
||||
[RunPhase.Crisis]: 0, // ends when resolved or player dies
|
||||
[RunPhase.Resolution]: 60_000, // 1 minute
|
||||
};
|
||||
|
||||
/** Escalation growth rate per second (0→1 over Escalation phase) */
|
||||
export const ESCALATION_RATE = 0.005;
|
||||
|
||||
/** Spores awarded per discovery type */
|
||||
export const SPORE_REWARDS = {
|
||||
element: 5,
|
||||
reaction: 10,
|
||||
compound: 8,
|
||||
creature: 15,
|
||||
crisisResolved: 50,
|
||||
runCompleted: 20,
|
||||
};
|
||||
Reference in New Issue
Block a user