Add optional short alliance victory
Verify and publish checkpoint container / container (push) Successful in 11m2s
Verify and publish checkpoint container / container (push) Successful in 11m2s
This commit is contained in:
1 parent
8fb9f59106
commit
e896570f07
25 files changed
+632
-27
No files matched your search
+20
-4
@@ -1437,6 +1437,8 @@ export type Game = {
|
||||
factionDraft?: FactionDraft;
|
||||
/** Explicit two-human/four-faction setup; absent from ordinary and legacy games. */
|
||||
twoPlayerControllers?: TwoPlayerControllers;
|
||||
/** Optional printed two-member alliance victory target; absent in older games. */
|
||||
shortAllianceVictory?: boolean;
|
||||
/** Explicit final turn after an agreed extension; absent means turn ten. */
|
||||
victoryFinalTurn?: number;
|
||||
/** Agreed addition to the ordinary stronghold win targets. Older games omit it. */
|
||||
@@ -5749,6 +5751,8 @@ function twoPlayerRule<T>(operation: () => T): T {
|
||||
|
||||
/** Reject stale or ambiguous ownership before either projecting or mutating a game. */
|
||||
function twoPlayerControllersIntegrity(g: Game): void {
|
||||
requireRule(g.shortAllianceVictory === undefined || typeof g.shortAllianceVictory === 'boolean',
|
||||
'The optional alliance victory setting must be true or false.');
|
||||
if (g.twoPlayerControllers === undefined) return;
|
||||
const seats = g.players.map(player => player.id);
|
||||
twoPlayerRule(() => {
|
||||
@@ -10689,7 +10693,7 @@ function requireFreshBaseRuntime(g: Game) {
|
||||
const configuration = new Set<keyof Game>(['code', 'version', 'host', 'players', 'playerPositions',
|
||||
'advanced', 'expansions', 'log', 'botsPending', 'botNextActionAt', 'techTokens', 'strongholdCards',
|
||||
'homeworlds', 'nexusCards', 'discoveryEnabled', 'leaderSkills', 'ecazTreachery', 'lobbyOptions', 'kullDefaultPolicy',
|
||||
'twoPlayerControllers']);
|
||||
'twoPlayerControllers', 'shortAllianceVictory']);
|
||||
const keys = [...new Set([...Object.keys(g), ...Object.keys(fresh)])] as (keyof Game)[];
|
||||
requireRule(keys.every(key => configuration.has(key) ||
|
||||
JSON.stringify(g[key]) === JSON.stringify(fresh[key])),
|
||||
@@ -31695,7 +31699,7 @@ function futureBattleLeaderTruthAnswers(g: Game, p: Player, q: FutureBattleLeade
|
||||
...(g.bidPromises ?? []), ...(g.phaseBidPromises ?? []), ...(g.richeseBidPromises ?? []),
|
||||
...(g.earlyRicheseBidPromises ?? []), ...(g.alliancePromises ?? []), ...(g.allianceExpressionPromises ?? []),
|
||||
];
|
||||
if (q.turn !== g.turn || q.target !== p.id || g.phase !== 5 ||
|
||||
if (q.turn !== g.turn || q.target !== p.id || (g.phase !== 4 && g.phase !== 5) ||
|
||||
(g.futureBattleLeaderPromises ?? []).some(row => row.turn === g.turn && row.player === p.id &&
|
||||
(row.status === 'waiting' || row.status === 'bound')) ||
|
||||
otherPromises.some(row => row.player === p.id && row.turn === g.turn && !row.fulfilled && !row.released) ||
|
||||
@@ -43681,6 +43685,17 @@ function applyActionInner(
|
||||
log(g, `${p.name} ${action.enabled ? 'enabled' : 'disabled'} the provisional two-person, four-faction setup. Human readiness was cleared.`);
|
||||
return g;
|
||||
}
|
||||
if (t === 'shortAllianceVictory') {
|
||||
requireRule(id === g.host && typeof action.enabled === 'boolean' &&
|
||||
Object.keys(action).every(key => key === 'type' || key === 'enabled'),
|
||||
'Only the host may change the optional alliance victory target.');
|
||||
if (action.enabled === !!g.shortAllianceVictory) return g;
|
||||
if (action.enabled) g.shortAllianceVictory = true;
|
||||
else delete g.shortAllianceVictory;
|
||||
g.players.forEach(player => (player.ready = !!player.bot));
|
||||
log(g, `${p.name} ${action.enabled ? 'enabled' : 'disabled'} the optional three-stronghold alliance victory. Human readiness was cleared.`);
|
||||
return g;
|
||||
}
|
||||
if (t === 'rules') {
|
||||
requireRule(id === g.host, 'Only the host can change the rules mode.');
|
||||
requireRule(typeof action.advanced === 'boolean' &&
|
||||
@@ -45792,10 +45807,10 @@ export function viewGame(state: Game, id: string, now?: number) {
|
||||
truthFutureBattleLeaderAnswers: g.truthtrance?.stage === 'answer' &&
|
||||
g.truthtrance.question?.target === id && g.truthtrance.question.kind === 'futureBattleLeader'
|
||||
? futureBattleLeaderTruthAnswers(g, me, g.truthtrance.question) : null,
|
||||
truthFutureBattleLeaderTargets: g.status === 'playing' && !g.advanced && g.phase === 5 &&
|
||||
truthFutureBattleLeaderTargets: g.status === 'playing' && !g.advanced && (g.phase === 4 || g.phase === 5) &&
|
||||
!g.expansions.length && !g.techTokens && !g.strongholdCards && !g.nexusCards && !g.homeworlds &&
|
||||
!g.leaderSkills && !g.discoveryEnabled && !g.ecazTreachery && !g.battle && !g.response &&
|
||||
!g.decision && !g.phaseOpening && !g.pendingKarama && !g.pendingTreacheryDiscard
|
||||
!g.decision && !g.phaseOpening && !g.pendingRevival && !g.pendingKarama && !g.pendingTreacheryDiscard
|
||||
? g.players.filter(player => player.id !== id && !(g.futureBattleLeaderPromises ?? []).some(row =>
|
||||
row.turn === g.turn && row.player === player.id && (row.status === 'waiting' || row.status === 'bound')))
|
||||
.map(player => player.id) : [],
|
||||
@@ -45916,6 +45931,7 @@ export function viewGame(state: Game, id: string, now?: number) {
|
||||
factionDraft: g.factionDraft ?? null,
|
||||
factionSwap: g.factionSwap ?? null,
|
||||
twoPlayerControllers: g.twoPlayerControllers ?? null,
|
||||
shortAllianceVictory: g.shortAllianceVictory === true,
|
||||
controlledFactionSeats: g.twoPlayerControllers
|
||||
? g.players.filter(player => g.twoPlayerControllers!.controllers.some(controller =>
|
||||
controller.seats.includes(id) && controller.seats.includes(player.id)))
|
||||
|
||||
Reference in new issue
Block a user