Prototype charity Truthtrance and coalition rule foundations
Verify and publish checkpoint container / container (push) Successful in 10m14s
Verify and publish checkpoint container / container (push) Successful in 10m14s
This commit is contained in:
1 parent
e896570f07
commit
cea310b030
17 files changed
+1024
-35
No files matched your search
@@ -11,6 +11,7 @@ import { TECH_TOKENS } from './tech-tokens';
|
||||
import { isDiscoveryLocationId, JACURUTU_SIETCH } from './discoveries';
|
||||
import type { TwoPlayerControllers } from './two-player-controllers';
|
||||
import { allianceVictoryTarget } from './alliance-victory-option';
|
||||
import { coalitionGroups } from './coalition-alliance';
|
||||
|
||||
export type StrongholdProgress = {
|
||||
player: string;
|
||||
@@ -37,6 +38,22 @@ function requireProgress(
|
||||
if (!condition) throw new VictoryProgressError(message);
|
||||
}
|
||||
|
||||
/** Ordered side membership for the bounded coalition victory quote. Three-member
|
||||
* Advanced and Ecaz combinations remain unavailable until their board rules
|
||||
* and faction interactions are integrated. No game mode is enabled here. */
|
||||
export function victoryMembers(g: BoardContext, player: string): string[] {
|
||||
const seat = g.players.find(candidate => candidate.id === player);
|
||||
requireProgress(seat, 'Victory needs a seated player.');
|
||||
if (g.coalitionState === undefined)
|
||||
return g.order.filter(member => member === player || member === seat.ally);
|
||||
const groups = coalitionGroups(g.players, g.coalitionState);
|
||||
requireProgress(!groups.some(group => group.members.length === 3 &&
|
||||
(g.advanced || g.players.some(candidate => candidate.faction === 'ecaz'))),
|
||||
'Three-member victory rules require Basic play without Ecaz.');
|
||||
const group = groups.find(candidate => candidate.members.includes(player));
|
||||
return g.order.filter(member => member === player || !!group?.members.includes(member));
|
||||
}
|
||||
|
||||
/** Discovery locations use stronghold shipping and occupancy rules, but only
|
||||
* Jacurutu Sietch counts toward the normal stronghold victory. */
|
||||
export function countsForStrongholdVictory(id: string) {
|
||||
@@ -65,6 +82,8 @@ export function strongholdProgress(
|
||||
const extra = g.victoryExtraStrongholds ?? 0;
|
||||
requireProgress(Number.isSafeInteger(extra) && extra >= 0 && extra <= 200,
|
||||
'The agreed extra stronghold target must be a safe nonnegative count.');
|
||||
requireProgress(g.shortAllianceVictory === undefined || typeof g.shortAllianceVictory === 'boolean',
|
||||
'Choose whether the shorter alliance victory option is enabled.');
|
||||
// This validates every ID, faction and reciprocal alliance, even where no
|
||||
// stronghold has a force. It does not merge ordinary allies for occupancy.
|
||||
ecazOccupancyIdentity(g.players, g.players[0].id, {
|
||||
@@ -102,9 +121,7 @@ export function strongholdProgress(
|
||||
);
|
||||
const progress = g.order.map((id) => {
|
||||
const p = players.find((p) => p.id === id)!;
|
||||
const members = g.order.filter(
|
||||
(member) => member === id || member === p.ally,
|
||||
);
|
||||
const members = victoryMembers(g, id);
|
||||
const partner = players.find((other) => other.id === p.ally);
|
||||
const ecazPair =
|
||||
!!partner && (p.faction === 'ecaz' || partner.faction === 'ecaz');
|
||||
@@ -136,7 +153,8 @@ export function strongholdProgress(
|
||||
TECH_TOKENS.every(({ id }) => tech[id].owner === member),
|
||||
);
|
||||
const target = allianceVictoryTarget(
|
||||
players.map((player) => player.id), g.twoPlayerControllers, !!partner, g.shortAllianceVictory,
|
||||
players.map((player) => player.id), g.twoPlayerControllers, members.length > 1,
|
||||
members.length === 3 ? false : g.shortAllianceVictory,
|
||||
) + extra;
|
||||
return {
|
||||
player: id,
|
||||
|
||||
Reference in new issue
Block a user