Files
synthesis/src/run/crisis.ts
Денис Шкабатур 5b7dbb4df3 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>
2026-02-12 15:10:05 +03:00

86 lines
2.9 KiB
TypeScript
Raw 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.
/**
* Crisis System — Chemical Plague
*
* When escalation reaches its threshold, a crisis activates.
* The Chemical Plague poisons the atmosphere — player must craft
* the correct neutralizing compound to stop it.
*/
import type { CrisisConfig } from './types';
// ─── Chemical Plague Configuration ───────────────────────────────
export const CHEMICAL_PLAGUE: CrisisConfig = {
type: 'chemical-plague',
name: 'Chemical Plague',
nameRu: 'Химическая Чума',
description: 'A chain reaction is poisoning the atmosphere. Neutralize it with the right compound!',
descriptionRu: 'Цепная реакция отравляет атмосферу. Нейтрализуй правильным соединением!',
triggerThreshold: 0.8,
neutralizer: 'CaO', // Calcium oxide (quicklime) — absorbs acid gases
neutralizeAmount: 3, // need 3 units to fully neutralize
};
// ─── Crisis State ────────────────────────────────────────────────
export interface CrisisState {
config: CrisisConfig;
active: boolean;
/** Progress 0.01.0 — at 1.0 the world is fully poisoned */
progress: number;
resolved: boolean;
/** How many neutralizer units have been applied */
neutralizeApplied: number;
}
/** Damage growth rate per second during active crisis */
const CRISIS_DAMAGE_RATE = 0.01; // reaches 1.0 in ~100 seconds
/** Create a new crisis state from config */
export function createCrisisState(config: CrisisConfig): CrisisState {
return {
config,
active: true,
progress: 0,
resolved: false,
neutralizeApplied: 0,
};
}
/** Advance crisis damage over time */
export function applyCrisisDamage(crisis: CrisisState, deltaMs: number): void {
if (!crisis.active || crisis.resolved) return;
const deltaSec = deltaMs / 1000;
crisis.progress = Math.min(1.0, crisis.progress + CRISIS_DAMAGE_RATE * deltaSec);
}
/** Attempt to neutralize the crisis with a compound. Returns true if correct compound. */
export function attemptNeutralize(
crisis: CrisisState,
compoundId: string,
amount: number,
): boolean {
if (compoundId !== crisis.config.neutralizer) return false;
if (crisis.resolved) return true;
crisis.neutralizeApplied += amount;
// Reduce progress proportionally
const reductionPerUnit = 1.0 / crisis.config.neutralizeAmount;
crisis.progress = Math.max(0, crisis.progress - amount * reductionPerUnit);
// Check if fully neutralized
if (crisis.neutralizeApplied >= crisis.config.neutralizeAmount) {
crisis.resolved = true;
crisis.active = false;
crisis.progress = 0;
}
return true;
}
/** Check if crisis has been resolved */
export function isCrisisResolved(crisis: CrisisState): boolean {
return crisis.resolved;
}