// --- Constants ---
export const MAX_HP = 20;
export const MAX_UNDO_STEPS = 1;
export const STORAGE_KEY = 'scoundrel_state_v1';
export const SUITS = {
HEARTS: { symbol: '♥', color: 'red', type: 'POTION' },
DIAMONDS: { symbol: '♦', color: 'red', type: 'WEAPON' },
CLUBS: { symbol: '♣', color: 'black', type: 'MONSTER' },
SPADES: { symbol: '♠', color: 'black', type: 'MONSTER' }
};
export const RANKS = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A'];
export const THEMES = {
'Text': { label: 'Classic (Text)' },
'SimpleSVG': { label: 'Simple SVG', ext: 'svg', path: 'assets/themes/SimpleSVG' }
};
export const INITIAL_STATE = {
hp: 20,
max_hp: 20,
deck: [],
room: [null, null, null, null], // Fixed indices
discard_pile: [],
defeated_monsters: [],
weapon: null,
last_enemy_value: Infinity,
cards_played_this_turn: 0,
potion_used_this_turn: false,
can_flee: true,
game_over: false,
won: false,
fled_last_turn: false,
msg: "Welcome to the dungeon.",
theme: 'Text',
history: []
};
// --- Helpers ---
export const getCardValue = (rank) => {
if (rank === 'A') return 14;
if (rank === 'K') return 13;
if (rank === 'Q') return 12;
if (rank === 'J') return 11;
return parseInt(rank, 10);
};
export const createDeck = () => {
let deck = [];
let id_counter = 0;
for (const [suit_key, suit_data] of Object.entries(SUITS)) {
for (const rank of RANKS) {
if ((suit_key === 'HEARTS' || suit_key === 'DIAMONDS') && ['J', 'Q', 'K', 'A'].includes(rank)) continue;
deck.push({
id: `card-${id_counter++}`,
suit: suit_data.symbol,
color: suit_data.color,
type: suit_data.type,
rank: rank,
value: getCardValue(rank),
suit_key: suit_key
});
}
}
return deck;
};
export const shuffleDeck = (deck) => {
const new_deck = [...deck];
for (let i = new_deck.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[new_deck[i], new_deck[j]] = [new_deck[j], new_deck[i]];
}
return new_deck;
};
export const saveHistory = (currentState) => {
// Deep copy state excluding history itself to avoid recursion/heavy memory usage
const { history, ...stateToSave } = currentState;
// Basic deep copy for this simple state structure (arrays/objects)
const snapshot = JSON.parse(JSON.stringify(stateToSave));
// Limit history to MAX_UNDO_STEPS
return [...history, snapshot].slice(-MAX_UNDO_STEPS);
};
export const saveState = (state) => {
try {
// Convert Infinity to a placeholder string for JSON serialization
const serialized = JSON.stringify(state, (key, value) => {
return value === Infinity ? '___Infinity___' : value;
});
localStorage.setItem(STORAGE_KEY, serialized);
} catch (e) {
console.error("Failed to save state:", e);
}
};
export const loadState = () => {
try {
const saved = localStorage.getItem(STORAGE_KEY);
if (!saved) return null;
return JSON.parse(saved, (key, value) => {
return value === '___Infinity___' ? Infinity : value;
});
} catch (e) {
console.error("Failed to load state:", e);
return null;
}
};