/** * Configuration & Settings Management * Handles default values, slider bounds, custom defaults, and localStorage persistence. */ export const FACTORY_DEFAULTS = { // Starting entity counts & limits initialSheep: 25, initialWolves: 3, initialPlants: 35, maxPlantCap: 90, // Hard cap to keep CPU lightweight and meadow balanced // Sheep behavioral attributes sheepHungerDepletionRate: 1.2, // per second (sheep graze frequently) sheepGrazingReach: 18, // radius in pixels to snap up plants sheepMatingCooldown: 22, // seconds between sheep births // Wolf behavioral attributes & combat exertion wolfLungeCost: 7, // Health expended per attack bite (fatigue/struggle) wolfHungerDepletionRate: 1.3, // per second wolfAttackDamage: 38, // damage per bite to sheep wolfMatingCooldown: 35, // seconds between wolf litters wolfMatingThreshold: 86, // minimum hunger required to seek mate // Plant & flora dynamics plantSeedRate: 8, // % chance for clustered mature plants to disperse seed plantDryRate: 2.2, // moisture loss per second in clear weather rainFrequency: 45, // 0 - 100% decaySpeed: 1.0, // 0.2x to 3.0x multiplier on carcass decomposition // Movement speeds (preset balance) sheepMaxSpeed: 1.8, sheepFleeSpeed: 2.8, sheepPerceptionRadius: 160, wolfMaxSpeed: 2.2, wolfChaseSpeed: 4.1, wolfPerceptionRadius: 280, wolfAttackCooldown: 0.65, // World constraints worldWidth: 1280, worldHeight: 760, boundaryMargin: 40, // Continuous Mode (Screen Saver / Endless Ecosystem) continuousMode: false, continuousSheepInterval: 14, continuousWolfInterval: 32, continuousMaxGroupSize: 3, }; const STORAGE_KEY = 'LifeSimulator_Config_v2'; const CUSTOM_DEFAULTS_KEY = 'LifeSimulator_Custom_Defaults_v2'; export class ConfigManager { constructor() { this.current = this.load(); } load() { try { const saved = localStorage.getItem(STORAGE_KEY); if (saved) { const parsed = JSON.parse(saved); return { ...FACTORY_DEFAULTS, ...parsed }; } } catch (e) { console.warn('Failed to load settings from localStorage:', e); } return { ...FACTORY_DEFAULTS }; } save(newConfig) { this.current = { ...this.current, ...newConfig }; try { localStorage.setItem(STORAGE_KEY, JSON.stringify(this.current)); } catch (e) { console.warn('Failed to save settings to localStorage:', e); } return this.current; } saveAsNewDefaults(config) { this.current = { ...this.current, ...config }; try { localStorage.setItem(CUSTOM_DEFAULTS_KEY, JSON.stringify(this.current)); localStorage.setItem(STORAGE_KEY, JSON.stringify(this.current)); } catch (e) { console.warn('Failed to save custom defaults:', e); } return this.current; } resetToDefaults() { // Check if user set custom defaults, otherwise use factory defaults let base = FACTORY_DEFAULTS; try { const custom = localStorage.getItem(CUSTOM_DEFAULTS_KEY); if (custom) { base = { ...FACTORY_DEFAULTS, ...JSON.parse(custom) }; } } catch (e) { console.warn('Failed to read custom defaults:', e); } this.current = { ...base }; try { localStorage.setItem(STORAGE_KEY, JSON.stringify(this.current)); } catch (e) { console.warn('Failed to reset settings:', e); } return this.current; } resetToFactory() { this.current = { ...FACTORY_DEFAULTS }; try { localStorage.removeItem(CUSTOM_DEFAULTS_KEY); localStorage.setItem(STORAGE_KEY, JSON.stringify(this.current)); } catch (e) { console.warn('Failed to reset to factory defaults:', e); } return this.current; } } export const configManager = new ConfigManager();