/** * Adaptive Tactics - Game State Management * Handles run state and memory ledger with localStorage persistence */ import { save, load } from './persistence.js'; const RUN_STATE_KEY = 'at_run_state'; const MEMORY_KEY = 'at_memory_ledger'; /** * Creates a fresh run state */ function createFreshRunState() { return { cycle: 1, player_name: '', active_ephraim_form: 'defiant_king', major_package: null, minor_modifier: null, current_map_id: 'fortress_map_01', win_count: 0, loss: false, last_transition: null }; } /** * Creates a fresh memory ledger */ function createFreshMemory() { return { primary_lane_history: [], eilisia_kill_leads: 0, mirella_high_heal_cycles: 0, fast_clear_count: 0, fracture_line_cycles: 0, bait_pull_cycles: 0, throne_rush_count: 0, last_carry_unit: null, turns_to_clear_history: [] }; } export class GameState { constructor() { this.runState = createFreshRunState(); this.memory = createFreshMemory(); this.battleState = null; this.load(); } /** * Load state from localStorage */ load() { const savedRun = load(RUN_STATE_KEY); const savedMemory = load(MEMORY_KEY); if (savedRun) { this.runState = { ...createFreshRunState(), ...savedRun }; } if (savedMemory) { this.memory = { ...createFreshMemory(), ...savedMemory }; } } /** * Save state to localStorage */ save() { save(RUN_STATE_KEY, this.runState); save(MEMORY_KEY, this.memory); } /** * Reset to fresh state */ reset() { this.runState = createFreshRunState(); this.memory = createFreshMemory(); this.battleState = null; this.save(); } /** * Set the player's name */ setPlayerName(name) { this.runState.player_name = name; this.save(); } /** * Get the current Ephraim form based on cycle */ getEphraimForm() { const cycle = this.runState.cycle; if (cycle <= 2) return 'defiant_king'; if (cycle <= 4) return 'dark_king'; if (cycle <= 6) return 'fallen_king'; if (cycle === 7) return 'corrupted_king'; return 'promised_death'; } /** * Get the scaling band for enemy stats */ getScalingBand() { const cycle = this.runState.cycle; if (cycle <= 2) return 'cycles_1_2'; if (cycle <= 4) return 'cycles_3_4'; if (cycle <= 6) return 'cycles_5_6'; return 'cycles_7_plus'; } /** * Initialize a new battle cycle */ initCycle(content) { this.runState.active_ephraim_form = this.getEphraimForm(); this.battleState = { turn: 1, phase: 'player', playerUnits: [], enemyUnits: [], tiles: [], selectedUnit: null, actedUnits: new Set(), turnLog: [], cycleMetrics: { playerLaneMovement: { west: 0, center: 0, east: 0 }, eilisiaKills: 0, mirellaHealCount: 0, turnsElapsed: 0, ephraimDamagedThisTurn: false, enemyActivations: [] } }; this.save(); } /** * Record a cycle win and update memory ledger */ recordCycleWin() { const metrics = this.battleState?.cycleMetrics; if (!metrics) return; // Determine primary lane const lanes = metrics.playerLaneMovement; let primaryLane = 'center'; if (lanes.west > lanes.center && lanes.west > lanes.east) { primaryLane = 'west'; } else if (lanes.east > lanes.center && lanes.east > lanes.west) { primaryLane = 'east'; } this.memory.primary_lane_history.push(primaryLane); // Track Eilisia kills if (metrics.eilisiaKills > 0) { // Check if Eilisia led in kills (simplified check) this.memory.eilisia_kill_leads++; } // Track Mirella healing if (metrics.mirellaHealCount >= 3) { this.memory.mirella_high_heal_cycles++; } // Track turn count this.memory.turns_to_clear_history.push(metrics.turnsElapsed); if (metrics.turnsElapsed <= 8) { this.memory.fast_clear_count++; } // Increment cycle and win count this.runState.cycle++; this.runState.win_count++; this.runState.active_ephraim_form = this.getEphraimForm(); this.save(); } /** * Record a loss */ recordLoss() { this.runState.loss = true; this.save(); } /** * Add entry to turn log */ addLogEntry(entry) { if (this.battleState) { this.battleState.turnLog.push(entry); // Keep last 10 entries if (this.battleState.turnLog.length > 10) { this.battleState.turnLog.shift(); } } } /** * Mark a unit as having acted this turn */ markUnitActed(unitId) { if (this.battleState) { this.battleState.actedUnits.add(unitId); } } /** * Check if a unit has acted this turn */ hasUnitActed(unitId) { return this.battleState?.actedUnits.has(unitId) ?? false; } /** * Reset acted units for new turn */ resetActedUnits() { if (this.battleState) { this.battleState.actedUnits.clear(); } } /** * Advance to next turn */ advanceTurn() { if (this.battleState) { this.battleState.turn++; if (this.battleState.cycleMetrics) { this.battleState.cycleMetrics.turnsElapsed++; } this.resetActedUnits(); } } /** * Switch phase between player and enemy */ switchPhase() { if (this.battleState) { this.battleState.phase = this.battleState.phase === 'player' ? 'enemy' : 'player'; } } }