85 lines
3.3 KiB
TypeScript
85 lines
3.3 KiB
TypeScript
import { homeworldLeaderSkillsProfile, classicNexusLeaderSkillsProfile, classicTechLeaderSkillsProfile, mixedE1E2NexusLeaderSkillsProfile, mixedE3NexusLeaderSkillsProfile, nativeDiscoveryLeaderSkillsProfile, nativeExpansionLeaderSkillsProfile, nativeTechLeaderSkillsProfile, noOtherLeaderSkillModules, pairedE3NexusLeaderSkillsProfile, standaloneE3NexusLeaderSkillsProfile, strongholdLeaderSkillsProfile, type LeaderSkillProfile } from './leader-skill-profile';
|
|
import { classicDiscoveryLeaderSkillsProfile } from './discovery-module-profile';
|
|
export type BureaucratPaymentKind = 'auction' | 'shipment' | 'bribe' | 'revival';
|
|
export type BureaucratPaymentSource = {
|
|
event: string;
|
|
turn: number;
|
|
phase: number;
|
|
kind: BureaucratPaymentKind;
|
|
payer: string;
|
|
payee: string;
|
|
amount: number;
|
|
signature: string;
|
|
};
|
|
/** The one physical skill card's use survives death, redraw and controller changes. */
|
|
export type BureaucratPaymentUse = {
|
|
event: string;
|
|
owner: string;
|
|
turn: number;
|
|
phase: number;
|
|
signature: string;
|
|
};
|
|
export type BureaucratPaymentView = {
|
|
pending: null | {
|
|
event: string;
|
|
owner: string;
|
|
payer: string;
|
|
payee: string;
|
|
amount: number;
|
|
kind: BureaucratPaymentKind;
|
|
redirect: 2;
|
|
};
|
|
usedThisPhase: boolean;
|
|
};
|
|
export class BureaucratPaymentError extends Error {}
|
|
export function bureaucratPaymentSignature(value: object): string {
|
|
return JSON.stringify({ ...value, signature: undefined });
|
|
}
|
|
export function bureaucratPaymentModeSupported(game: LeaderSkillProfile): boolean {
|
|
return mixedE3NexusLeaderSkillsProfile(game) || mixedE1E2NexusLeaderSkillsProfile(game) || pairedE3NexusLeaderSkillsProfile(game) ||
|
|
(noOtherLeaderSkillModules(game) &&
|
|
(!game.expansions.length ||
|
|
(game.expansions.length === 1 && game.expansions[0] === 'choam') ||
|
|
nativeExpansionLeaderSkillsProfile(game))) || homeworldLeaderSkillsProfile(game) || classicTechLeaderSkillsProfile(game) || nativeTechLeaderSkillsProfile(game) || strongholdLeaderSkillsProfile(game) || classicNexusLeaderSkillsProfile(game) || standaloneE3NexusLeaderSkillsProfile(game) || classicDiscoveryLeaderSkillsProfile(game) || nativeDiscoveryLeaderSkillsProfile(game);
|
|
}
|
|
export function bureaucratUsed(
|
|
used: readonly BureaucratPaymentUse[],
|
|
turn: number,
|
|
phase: number,
|
|
): boolean {
|
|
return used.some((use) => use.turn === turn && use.phase === phase);
|
|
}
|
|
/** Caller supplies only a living face-up native trainer and actual player payees. */
|
|
export function quoteBureaucratPayment(input: {
|
|
owner: string | null;
|
|
payer: string;
|
|
payee: string;
|
|
amount: number;
|
|
turn: number;
|
|
phase: number;
|
|
used: readonly BureaucratPaymentUse[];
|
|
}): { redirect: 2; income: number } | null {
|
|
if (
|
|
!Number.isSafeInteger(input.amount) ||
|
|
input.amount < 0 ||
|
|
!Number.isSafeInteger(input.turn) ||
|
|
input.turn < 1 ||
|
|
!Number.isSafeInteger(input.phase) ||
|
|
input.phase < 0 ||
|
|
input.phase > 8 ||
|
|
!input.payer ||
|
|
!input.payee
|
|
)
|
|
throw new BureaucratPaymentError(
|
|
'Bureaucrat needs a valid actual player payment.',
|
|
);
|
|
return input.owner &&
|
|
input.owner !== input.payer &&
|
|
input.owner !== input.payee &&
|
|
input.payer !== input.payee &&
|
|
input.amount >= 5 &&
|
|
!bureaucratUsed(input.used, input.turn, input.phase)
|
|
? { redirect: 2, income: input.amount - 2 }
|
|
: null;
|
|
}
|