First commit, done on M6 from the PLAN.MD

This commit is contained in:
gauvainboiche
2026-10-25 17:34:44 +01:00
parent d5dc2a3901
commit 04193e2013
86 changed files with 8396 additions and 0 deletions
+63
View File
@@ -0,0 +1,63 @@
// Ways the term can end early. Checked once per day after the economy has moved.
//
// default debt above the limit: immediate
// impeachment civil rights and opinion both very low for N days in a row: certain
// coup army loyalty and stability both very low: a daily chance that grows each day in the zone
// revolution unrest very high and opinion very low: same growing daily chance
//
// Entering a danger zone queues an urgent telegram (state.alerts) and pauses the game
// until the player acknowledges it. state.risk counts the days spent in each zone.
import { nextFloat } from "./rng.js";
function alert(state, kind) {
state.alerts.push({ kind, day: state.day });
state.pending.alert = true;
}
// Returns the game-over type or null. Mutates state.risk, state.alerts and the RNG.
export function checkGameOver(state, bal) {
const g = bal.gameOver;
const ind = state.indicators;
const risk = state.risk;
const debtRatio = (state.economy.debt / state.economy.gdp) * 100;
// Zone bookkeeping: count consecutive days inside, fade (or reset) outside.
const track = (name, inZone, fade) => {
if (inZone) {
risk[name] += 1;
if (risk[name] === 1) alert(state, name);
} else {
risk[name] = fade === "reset" ? 0 : Math.max(0, risk[name] - fade);
}
};
const chance = (name, perDay) => risk[name] > 0 && nextFloat(state) < Math.min(1, perDay * risk[name]);
if (debtRatio >= g.default.warnAbove) {
if (!risk.defaultZone) {
risk.defaultZone = true;
alert(state, "default");
}
} else if (debtRatio < g.default.warnAbove - 10) {
risk.defaultZone = false;
}
const inImpeachment = ind.civilRights < g.impeachment.civilRightsBelow && ind.opinion < g.impeachment.opinionBelow;
const inCoup = ind.armyLoyalty < g.coup.armyBelow && ind.stability < g.coup.stabilityBelow;
const inRevolution = ind.unrest > g.revolution.unrestAbove && ind.opinion < g.revolution.opinionBelow;
track("impeachment", inImpeachment, "reset");
track("coup", inCoup, 1);
track("revolution", inRevolution, 1);
if (debtRatio > g.default.debtAbove) return "default";
if (risk.impeachment >= g.impeachment.days) return "impeachment";
if (inCoup && chance("coup", g.coup.chancePerDay)) return "coup";
if (inRevolution && chance("revolution", g.revolution.chancePerDay)) return "revolution";
return null;
}
// The player has read the telegram at the front of the queue.
export function dismissAlert(state) {
state.alerts.shift();
state.pending.alert = state.alerts.length > 0;
}