AdaptiveTactics / js /state.js
EphAsad's picture
Upload 61 files
076c3cb verified
/**
* 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';
}
}
}