This commit is contained in:
2026-04-09 09:00:25 -04:00
parent 5b44762fbb
commit d61b8de6b7
3 changed files with 26 additions and 10 deletions

View File

@@ -63,6 +63,25 @@ let state: GameState = createInitialState(setup);
let isNewGameModalOpen = false; let isNewGameModalOpen = false;
let previousScoreSnapshot: ScoreSnapshot[] | null = null; let previousScoreSnapshot: ScoreSnapshot[] | null = null;
function rebuildSetup(overrides: Partial<SetupState> = {}) {
setup = createSetupState(
overrides.playerCount ?? setup.playerCount,
overrides.columns ?? setup.columns,
overrides.rows ?? setup.rows,
overrides.startingNodesPerPlayer ?? setup.startingNodesPerPlayer,
overrides.sunbeamChance ?? setup.sunbeamChance,
overrides.diseaseChance ?? setup.diseaseChance,
overrides.seedInputs ?? setup.seedInputs,
overrides.paletteOrder ?? setup.paletteOrder,
overrides.initiativeMode ?? setup.initiativeMode,
overrides.biddingOrderRule ?? setup.biddingOrderRule,
overrides.weatherDraftEnabled ?? setup.weatherDraftEnabled,
overrides.winCondition ?? setup.winCondition,
overrides.maxRounds ?? setup.maxRounds,
overrides.topLeafTarget ?? setup.topLeafTarget,
);
}
function getLiveExposureScores() { function getLiveExposureScores() {
return buildEnergySimulation(state).scores; return buildEnergySimulation(state).scores;
} }
@@ -1307,7 +1326,7 @@ function attachEvents() {
if (output) { if (output) {
output.textContent = input.value; output.textContent = input.value;
} }
setup = createSetupState(Number(input.value), setup.columns, setup.rows, setup.startingNodesPerPlayer, setup.sunbeamChance, setup.diseaseChance, setup.seedInputs, setup.paletteOrder, setup.shuffleTurnOrder, setup.initiativeMode, setup.biddingOrderRule, setup.weatherDraftEnabled, setup.winCondition, setup.maxRounds, setup.topLeafTarget); rebuildSetup({ playerCount: Number(input.value) });
render(); render();
}); });
document.querySelector<HTMLInputElement>("#column-count")?.addEventListener("change", (event) => { document.querySelector<HTMLInputElement>("#column-count")?.addEventListener("change", (event) => {
@@ -1316,7 +1335,7 @@ function attachEvents() {
return; return;
} }
setup = createSetupState(setup.playerCount, Math.max(6, Math.min(24, columns)), setup.rows, setup.startingNodesPerPlayer, setup.sunbeamChance, setup.diseaseChance, setup.seedInputs, setup.paletteOrder, setup.shuffleTurnOrder, setup.initiativeMode, setup.biddingOrderRule, setup.weatherDraftEnabled, setup.winCondition, setup.maxRounds, setup.topLeafTarget); rebuildSetup({ columns: Math.max(6, Math.min(24, columns)) });
render(); render();
}); });
document.querySelector<HTMLInputElement>("#row-count")?.addEventListener("change", (event) => { document.querySelector<HTMLInputElement>("#row-count")?.addEventListener("change", (event) => {
@@ -1325,7 +1344,7 @@ function attachEvents() {
return; return;
} }
setup = createSetupState(setup.playerCount, setup.columns, Math.max(6, Math.min(24, rows)), setup.startingNodesPerPlayer, setup.sunbeamChance, setup.diseaseChance, setup.seedInputs, setup.paletteOrder, setup.shuffleTurnOrder, setup.initiativeMode, setup.biddingOrderRule, setup.weatherDraftEnabled, setup.winCondition, setup.maxRounds, setup.topLeafTarget); rebuildSetup({ rows: Math.max(6, Math.min(24, rows)) });
render(); render();
}); });
document.querySelector<HTMLInputElement>("#starting-nodes")?.addEventListener("change", (event) => { document.querySelector<HTMLInputElement>("#starting-nodes")?.addEventListener("change", (event) => {
@@ -1334,7 +1353,7 @@ function attachEvents() {
return; return;
} }
setup = createSetupState(setup.playerCount, setup.columns, setup.rows, Math.max(1, nextValue), setup.sunbeamChance, setup.diseaseChance, setup.seedInputs, setup.paletteOrder, setup.shuffleTurnOrder, setup.initiativeMode, setup.biddingOrderRule, setup.weatherDraftEnabled, setup.winCondition, setup.maxRounds, setup.topLeafTarget); rebuildSetup({ startingNodesPerPlayer: Math.max(1, nextValue) });
render(); render();
}); });
document.querySelector<HTMLInputElement>("#sunbeam-chance")?.addEventListener("change", (event) => { document.querySelector<HTMLInputElement>("#sunbeam-chance")?.addEventListener("change", (event) => {

View File

@@ -1,6 +1,6 @@
import { PLAYER_PALETTE, STARTING_POINTS } from "./constants"; import { PLAYER_PALETTE, STARTING_POINTS } from "./constants";
import type { GameState, Player, SetupState } from "./types"; import type { GameState, Player, SetupState } from "./types";
import { keyFor, shuffleArray } from "./utils"; import { keyFor } from "./utils";
export function createDefaultPaletteOrder(playerCount: number) { export function createDefaultPaletteOrder(playerCount: number) {
return Array.from({ length: playerCount }, (_, index) => index % PLAYER_PALETTE.length); return Array.from({ length: playerCount }, (_, index) => index % PLAYER_PALETTE.length);
@@ -76,7 +76,6 @@ export function createSetupState(
diseaseChance = 0, diseaseChance = 0,
seedInputs: string[] | null = null, seedInputs: string[] | null = null,
paletteOrder: number[] | null = null, paletteOrder: number[] | null = null,
shuffleTurnOrder = true,
initiativeMode: SetupState["initiativeMode"] = "fixed", initiativeMode: SetupState["initiativeMode"] = "fixed",
biddingOrderRule: SetupState["biddingOrderRule"] = "rotating", biddingOrderRule: SetupState["biddingOrderRule"] = "rotating",
weatherDraftEnabled = true, weatherDraftEnabled = true,
@@ -97,7 +96,6 @@ export function createSetupState(
diseaseChance, diseaseChance,
seedInputs: Array.from({ length: playerCount }, (_, index) => seedInputs?.[index] ?? defaults[index]), seedInputs: Array.from({ length: playerCount }, (_, index) => seedInputs?.[index] ?? defaults[index]),
paletteOrder: Array.from({ length: playerCount }, (_, index) => paletteOrder?.[index] ?? paletteDefaults[index]), paletteOrder: Array.from({ length: playerCount }, (_, index) => paletteOrder?.[index] ?? paletteDefaults[index]),
shuffleTurnOrder,
initiativeMode, initiativeMode,
biddingOrderRule, biddingOrderRule,
weatherDraftEnabled, weatherDraftEnabled,
@@ -164,7 +162,7 @@ export function normalizeSeedInputs(setup: SetupState) {
} }
export function createInitialState(setup: SetupState): GameState { export function createInitialState(setup: SetupState): GameState {
const playerPaletteOrder = setup.shuffleTurnOrder ? shuffleArray(setup.paletteOrder) : [...setup.paletteOrder]; const playerPaletteOrder = [...setup.paletteOrder];
const players = createPlayers(setup.playerCount, playerPaletteOrder); const players = createPlayers(setup.playerCount, playerPaletteOrder);
const turnOrder = players.map((player) => player.id); const turnOrder = players.map((player) => player.id);
const nodes = new Map(); const nodes = new Map();
@@ -213,7 +211,7 @@ export function createInitialState(setup: SetupState): GameState {
gameOver: false, gameOver: false,
history: [ history: [
`Round 1 begins on a ${setup.columns}x${setup.rows} board with ${setup.startingNodesPerPlayer} starting node${setup.startingNodesPerPlayer === 1 ? "" : "s"} each.`, `Round 1 begins on a ${setup.columns}x${setup.rows} board with ${setup.startingNodesPerPlayer} starting node${setup.startingNodesPerPlayer === 1 ? "" : "s"} each.`,
`${setup.shuffleTurnOrder ? "Turn order was randomized for this game." : "Turn order uses the setup order."}`, "Turn order uses the setup order unless changed by initiative drafting.",
], ],
roundSummary: null, roundSummary: null,
}; };

View File

@@ -21,7 +21,6 @@ export type SetupState = {
diseaseChance: number; diseaseChance: number;
seedInputs: string[]; seedInputs: string[];
paletteOrder: number[]; paletteOrder: number[];
shuffleTurnOrder: boolean;
initiativeMode: "fixed" | "bid"; initiativeMode: "fixed" | "bid";
biddingOrderRule: "rotating" | "lowest_growth_income"; biddingOrderRule: "rotating" | "lowest_growth_income";
weatherDraftEnabled: boolean; weatherDraftEnabled: boolean;