feat: Great Cycle system — 7-run macro cycles with traces and narrative
Core engine for the Great Cycle mechanic (GDD Section IV): - GreatCycleState tracking: cycle number, run within cycle, theme - RunTrace recording: death position, school, biome, discoveries per run - Cycle advancement: auto-advance to next cycle after 7 runs - Great Renewal: resets traces, advances theme, strengthens Mycelium - 6 narrative themes (Awakening→Doubt→Realization→Attempt→Acceptance→Synthesis) - Cycle world modifiers: terrain/resources/creatures scale with cycle - Narrative data JSON with Russian/English lore fragments per theme - MetaState + persistence + RunState extended with cycle fields - 38 new tests (549 total), all passing Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
113
src/run/types.ts
113
src/run/types.ts
@@ -117,6 +117,8 @@ export interface RunState {
|
||||
runId: number;
|
||||
/** Selected school id */
|
||||
schoolId: string;
|
||||
/** Biome being explored this run */
|
||||
biomeId: string;
|
||||
/** Current phase */
|
||||
phase: RunPhase;
|
||||
/** Time spent in current phase (ms) */
|
||||
@@ -133,6 +135,10 @@ export interface RunState {
|
||||
discoveries: RunDiscoveries;
|
||||
/** Whether the player is alive */
|
||||
alive: boolean;
|
||||
/** World seed for this run */
|
||||
worldSeed: number;
|
||||
/** Player death position in tile coords (set on death) */
|
||||
deathPosition: { tileX: number; tileY: number } | null;
|
||||
}
|
||||
|
||||
export interface RunDiscoveries {
|
||||
@@ -168,6 +174,8 @@ export interface MetaState {
|
||||
runHistory: RunSummary[];
|
||||
/** Mycelium knowledge graph (persistent between runs) */
|
||||
mycelium: MyceliumGraphData;
|
||||
/** Great cycle state (7-run macro cycles) */
|
||||
greatCycle: GreatCycleState;
|
||||
}
|
||||
|
||||
/** Serializable Mycelium graph data (stored in MetaState) */
|
||||
@@ -214,6 +222,10 @@ export interface RunSummary {
|
||||
discoveries: number;
|
||||
sporesEarned: number;
|
||||
crisisResolved: boolean;
|
||||
/** Biome explored (added Phase 11) */
|
||||
biomeId?: string;
|
||||
/** Great cycle number when this run occurred */
|
||||
cycleNumber?: number;
|
||||
}
|
||||
|
||||
// ─── Body Composition (for death animation) ──────────────────────
|
||||
@@ -232,6 +244,107 @@ export const BODY_COMPOSITION: { symbol: string; fraction: number }[] = [
|
||||
{ symbol: 'Fe', fraction: 0.001 },
|
||||
];
|
||||
|
||||
// ─── Great Cycle (every 7 runs) ──────────────────────────────────
|
||||
|
||||
/** Narrative themes for each great cycle (GDD Section IV) */
|
||||
export type CycleTheme =
|
||||
| 'awakening' // Cycle 1 (runs 1-7): learning the world
|
||||
| 'doubt' // Cycle 2 (runs 8-14): finding traces of past adepts
|
||||
| 'realization' // Cycle 3 (runs 15-21): understanding the nature of cycles
|
||||
| 'attempt' // Cycle 4 (runs 22-28): first attempts to transcend
|
||||
| 'acceptance' // Cycle 5 (runs 29-35): cycle is not a prison
|
||||
| 'synthesis'; // Cycle 6+ (runs 36+): unifying all knowledge
|
||||
|
||||
/** Human-readable names for CycleTheme */
|
||||
export const CYCLE_THEME_NAMES: Record<CycleTheme, string> = {
|
||||
awakening: 'Awakening',
|
||||
doubt: 'Doubt',
|
||||
realization: 'Realization',
|
||||
attempt: 'Attempt',
|
||||
acceptance: 'Acceptance',
|
||||
synthesis: 'Synthesis',
|
||||
};
|
||||
|
||||
export const CYCLE_THEME_NAMES_RU: Record<CycleTheme, string> = {
|
||||
awakening: 'Пробуждение',
|
||||
doubt: 'Сомнение',
|
||||
realization: 'Осознание',
|
||||
attempt: 'Попытка',
|
||||
acceptance: 'Принятие',
|
||||
synthesis: 'Синтез',
|
||||
};
|
||||
|
||||
/** Ordered themes by cycle number (0-indexed, cycles beyond 6 repeat 'synthesis') */
|
||||
export const CYCLE_THEMES: CycleTheme[] = [
|
||||
'awakening',
|
||||
'doubt',
|
||||
'realization',
|
||||
'attempt',
|
||||
'acceptance',
|
||||
'synthesis',
|
||||
];
|
||||
|
||||
/** A trace left by a completed run within a great cycle */
|
||||
export interface RunTrace {
|
||||
/** Run ID this trace belongs to */
|
||||
runId: number;
|
||||
/** Position within the great cycle (1-7) */
|
||||
runInCycle: number;
|
||||
/** School used this run */
|
||||
schoolId: string;
|
||||
/** Biome explored */
|
||||
biomeId: string;
|
||||
/** Death location (tile coords), null if run completed via boss victory */
|
||||
deathPosition: { tileX: number; tileY: number } | null;
|
||||
/** Phase reached when run ended */
|
||||
phaseReached: RunPhase;
|
||||
/** Was the crisis resolved? */
|
||||
crisisResolved: boolean;
|
||||
/** Number of unique discoveries */
|
||||
discoveryCount: number;
|
||||
/** Key element discoveries (up to 5 symbols for trace markers) */
|
||||
keyElements: string[];
|
||||
/** Duration of the run in ms */
|
||||
duration: number;
|
||||
/** World seed used for this run */
|
||||
worldSeed: number;
|
||||
}
|
||||
|
||||
/** Persistent great cycle state (stored in MetaState) */
|
||||
export interface GreatCycleState {
|
||||
/** Current great cycle number (1-based) */
|
||||
cycleNumber: number;
|
||||
/** Current run within the cycle (1-7, resets on renewal) */
|
||||
runInCycle: number;
|
||||
/** Current cycle's theme */
|
||||
theme: CycleTheme;
|
||||
/** Traces from runs in the CURRENT cycle (cleared on renewal) */
|
||||
currentCycleTraces: RunTrace[];
|
||||
/** Traces from the PREVIOUS cycle (for cross-cycle references) */
|
||||
previousCycleTraces: RunTrace[];
|
||||
/** Total great renewals completed */
|
||||
renewalsCompleted: number;
|
||||
/** Mycelium maturation level (increases each renewal) */
|
||||
myceliumMaturation: number;
|
||||
}
|
||||
|
||||
/** Number of runs per great cycle */
|
||||
export const RUNS_PER_CYCLE = 7;
|
||||
|
||||
/** World generation modifiers based on cycle number */
|
||||
export interface CycleWorldModifiers {
|
||||
/** Elevation noise scale multiplier (world shape variation) */
|
||||
elevationScaleMultiplier: number;
|
||||
/** Detail noise scale multiplier */
|
||||
detailScaleMultiplier: number;
|
||||
/** Resource density multiplier */
|
||||
resourceDensityMultiplier: number;
|
||||
/** Creature spawn rate multiplier */
|
||||
creatureSpawnMultiplier: number;
|
||||
/** Escalation rate multiplier (difficulty) */
|
||||
escalationRateMultiplier: number;
|
||||
}
|
||||
|
||||
// ─── Constants ───────────────────────────────────────────────────
|
||||
|
||||
/** Phase durations in ms (approximate, can be adjusted) */
|
||||
|
||||
Reference in New Issue
Block a user