// Indicators and economy variables move toward a target each day: // target = start value + sum of weighted deviations from the start state + active biases // Because every term is a deviation from the scenario start, the start is an equilibrium. import { IND_IDS, VAR_IDS, clamp } from "./state.js"; import { biasFor } from "./modifiers.js"; import { nextNoise } from "./rng.js"; function computeTarget(def, base, group, key, state, devs, bal) { let t = base; const gain = group === "ind" ? bal.gain ?? 1 : 1; for (const [id, w] of Object.entries(def.sectors ?? {})) { t += gain * w * (state.sectors[id].quality - state.ref.sectors[id]); } // Going big pays off: extra weight for quality above `from` (excess) or below it (short). for (const [id, [from, w]] of Object.entries(def.excess ?? {})) t += w * Math.max(0, state.sectors[id].quality - from); for (const [id, [from, w]] of Object.entries(def.short ?? {})) t -= w * Math.max(0, from - state.sectors[id].quality); for (const [k, w] of Object.entries(def.world ?? {})) t += w * state.world[k]; if (def.drift) t += ((def.drift * (bal.driftScale ?? 1)) * state.day) / 365; for (const [id, w] of Object.entries(def.alloc ?? {})) { const s = state.sectors[id]; t += w * (s.alloc / s.need - state.ref.ratio[id]); } for (const [k, w] of Object.entries(def.econ ?? {})) { t += w * (devs[k] - state.ref.dev[k]); } for (const [k, w] of Object.entries(def.ind ?? {})) { t += w * (state.indicators[k] - state.ref.ind[k]); } return t + biasFor(state, group, key); } export function stepVars(state, bal, devs) { const next = {}; for (const id of VAR_IDS) { const def = bal.vars[id]; const target = computeTarget(def, state.ref.vars[id], "var", id, state, devs, bal); const v = state.economy[id]; next[id] = clamp(v + (target - v) / def.tau + nextNoise(state, def.noise), def.min, def.max); } Object.assign(state.economy, next); } export function stepIndicators(state, bal, devs) { const next = {}; for (const id of IND_IDS) { const def = bal.indicators[id]; const target = computeTarget(def, state.ref.ind[id], "ind", id, state, devs, bal); const v = state.indicators[id]; next[id] = clamp(v + (target - v) / def.tau + nextNoise(state, def.noise ?? bal.noise.indicator), 0, 100); } Object.assign(state.indicators, next); }