From e896570f079744c5e62798d0b7ad2f365778e56e Mon Sep 17 00:00:00 2001 From: Quintine <15965533+Quintine@users.noreply.github.com> Date: Wed, 28 Oct 2026 21:40:24 +1100 Subject: [PATCH] Add optional short alliance victory --- components/admin-lobby-controls.tsx | 13 ++- components/game-table.tsx | 8 ++ db/admin-lobby-configuration.ts | 2 + docs/CURRENT_STATUS.md | 18 ++++ docs/OPTIONAL_ALLIANCE_VICTORY.md | 20 ++++ docs/RULE_DECISIONS.md | 7 ++ docs/TRUTHTRANCE_TURN_ACTIONS.md | 4 +- game/admin-lobby-configuration.ts | 4 + game/alliance-victory-option.ts | 22 +++++ game/engine.ts | 24 ++++- game/reference.ts | 11 ++- game/truthtrance.ts | 6 +- game/victory-progress.ts | 8 +- game/victory-quote.ts | 2 +- lib/admin-lobby-client.ts | 5 +- lib/admin-lobby-configuration.ts | 5 +- tests/admin-lobby-client.test.ts | 18 +++- tests/admin-lobby-configuration.test.ts | 37 ++++++- tests/alliance-victory-option.test.ts | 41 ++++++++ tests/fixture-short-alliance-victory.ts | 96 +++++++++++++++++++ tests/fixture-truth-future-battle-revival.ts | 91 ++++++++++++++++++ .../short-alliance-victory-controls.test.tsx | 64 +++++++++++++ tests/short-alliance-victory-runtime.test.ts | 76 +++++++++++++++ tests/truth-future-battle-revival.test.ts | 70 ++++++++++++++ tools/admin-lobby-verification.mjs | 7 +- 25 files changed, 632 insertions(+), 27 deletions(-) create mode 100644 docs/OPTIONAL_ALLIANCE_VICTORY.md create mode 100644 game/alliance-victory-option.ts create mode 100644 tests/alliance-victory-option.test.ts create mode 100644 tests/fixture-short-alliance-victory.ts create mode 100644 tests/fixture-truth-future-battle-revival.ts create mode 100644 tests/short-alliance-victory-controls.test.tsx create mode 100644 tests/short-alliance-victory-runtime.test.ts create mode 100644 tests/truth-future-battle-revival.test.ts diff --git a/components/admin-lobby-controls.tsx b/components/admin-lobby-controls.tsx index 5376e420..1b84f78c 100644 --- a/components/admin-lobby-controls.tsx +++ b/components/admin-lobby-controls.tsx @@ -77,19 +77,21 @@ export function AdminLobbyControls({ accountId, code, canManage, onClose, onUpda } function selectKind(next: AdminLobbyAction['type']) { setKind(next); setConfirmed(false); setTarget(''); - setEnabled(next === 'rules' ? lobby?.advanced ?? false : next === 'techTokens' ? lobby?.techTokens ?? false : lobby?.strongholdCards ?? false); + setEnabled(next === 'rules' ? lobby?.advanced ?? false : next === 'techTokens' ? lobby?.techTokens ?? false : + next === 'shortAllianceVictory' ? lobby?.shortAllianceVictory ?? false : lobby?.strongholdCards ?? false); if (next === 'addBot') setFaction(baseFactions.find(item => !lobby?.players.some(player => player.faction === item.id))?.id ?? 'atreides'); if (next === 'removeBot' || next === 'configureBot') selectTarget(lobby?.players.find(player => player.bot)?.id ?? ''); if (next === 'assignHost') setTarget(lobby?.players.find(player => player.hostEligible && player.id !== lobby.host)?.id ?? ''); } const action: AdminLobbyAction = kind === 'rules' ? { type: kind, advanced: enabled } : - kind === 'techTokens' || kind === 'strongholdCards' ? { type: kind, enabled } : + kind === 'techTokens' || kind === 'strongholdCards' || kind === 'shortAllianceVictory' ? { type: kind, enabled } : kind === 'addBot' ? { type: kind, faction, difficulty } : kind === 'configureBot' ? { type: kind, target, faction, difficulty, position } : { type: kind, target }; const selectedPlayer = lobby?.players.find(player => player.id === target); const availableFactions = baseFactions.filter(item => !lobby?.players.some(player => player.faction === item.id && (kind !== 'configureBot' || player.id !== target))); const actionable = lobby?.editable && (kind === 'rules' ? enabled !== lobby.advanced : kind === 'techTokens' ? enabled !== lobby.techTokens : kind === 'strongholdCards' ? enabled !== lobby.strongholdCards && (!enabled || lobby.advanced) : + kind === 'shortAllianceVictory' ? enabled !== lobby.shortAllianceVictory : kind === 'addBot' ? lobby.players.length < 6 && availableFactions.some(item => item.id === faction) : kind === 'assignHost' ? selectedPlayer?.hostEligible && target !== lobby.host : kind === 'removeBot' ? !!selectedPlayer?.bot : !!selectedPlayer?.bot && availableFactions.some(item => item.id === faction) && @@ -142,7 +144,7 @@ export function AdminLobbyControls({ accountId, code, canManage, onClose, onUpda
Current rules: {lobby.advanced ? 'Advanced preview' : 'Basic'} · Tech Tokens {lobby.techTokens ? 'on' : 'off'} · Stronghold Cards {lobby.strongholdCards ? 'on' : 'off'}.
+Current rules: {lobby.advanced ? 'Advanced preview' : 'Basic'} · Tech Tokens {lobby.techTokens ? 'on' : 'off'} · Stronghold Cards {lobby.strongholdCards ? 'on' : 'off'} · Three-stronghold alliance victory {lobby.shortAllianceVictory ? 'on' : 'off'}.
Advanced preview is unfinished. Players must review the warning and the host must explicitly start the preview.