Allow group departures with bribe commitments
Verify and publish checkpoint container / container (push) Successful in 10m51s
Verify and publish checkpoint container / container (push) Successful in 10m51s
This commit is contained in:
1 parent
3e0fa2a8a2
commit
0faa7923b0
13 files changed
+437
-37
No files matched your search
+16
-7
@@ -16036,6 +16036,9 @@ function allianceQuestionWindow(g: Game): boolean {
|
||||
function unsettledPromises(records: readonly {fulfilled?: boolean; released?: boolean}[] | undefined): boolean {
|
||||
return !!records?.some(record => !record.fulfilled && !record.released);
|
||||
}
|
||||
function coalitionAdmissionBlocked(g: Game): boolean {
|
||||
return [g.bribePromises, g.bribeExpressionPromises].some(unsettledPromises);
|
||||
}
|
||||
/** Group negotiation is deliberately unexposed until its other alliance
|
||||
* mechanics are integrated. This narrow profile keeps existing pair games
|
||||
* and unrelated commitments on their original paths. */
|
||||
@@ -16049,7 +16052,7 @@ function coalitionNexusAvailable(g: Game): boolean {
|
||||
g.expansions.length === 0 && g.players.every(seat =>
|
||||
['atreides', 'beneGesserit', 'emperor', 'fremen', 'guild', 'harkonnen'].includes(seat.faction)) &&
|
||||
Object.values(g.aid).every(credit => credit.amount === 0) &&
|
||||
![g.bribePromises, g.bribeExpressionPromises, g.turnActionPromises].some(unsettledPromises);
|
||||
!unsettledPromises(g.turnActionPromises);
|
||||
}
|
||||
function coalitionRule<T>(work: () => T): T {
|
||||
try { return work(); }
|
||||
@@ -16106,12 +16109,14 @@ function coalitionFundingAvailable(g: Game, p: Player, committedBid = false): bo
|
||||
if (!g.coalitionEscrow || !g.coalitionState || g.status !== 'playing' || g.advanced || ![3, 5].includes(g.phase) ||
|
||||
g.expansions.length || g.homeworlds || g.nexusCards || g.leaderSkills || g.techTokens ||
|
||||
g.strongholdCards || g.ecazTreachery || g.discoveryEnabled ||
|
||||
g.spiceBankerIncomePreview || g.kullPreview || g.richeseAuction || g.ixAuction ||
|
||||
(!committedBid && [g.bidPromises, g.phaseBidPromises, g.turnActionPromises,
|
||||
g.revivalPromises, g.leaderRevivalPromises, g.revivalExpressionPromises,
|
||||
g.bribePromises, g.bribeExpressionPromises].some(unsettledPromises))) return false;
|
||||
g.spiceBankerIncomePreview || g.kullPreview || g.richeseAuction || g.ixAuction) return false;
|
||||
const group = coalitionRule(() => coalitionOf(g.players, g.coalitionState, p.id));
|
||||
return !!group && group.members.length >= 3;
|
||||
if (!group || group.members.length < 3) return false;
|
||||
const groupHasUnsettled = (records: readonly {player: string; fulfilled?: boolean; released?: boolean}[] | undefined) =>
|
||||
!!records?.some(record => group.members.includes(record.player) && !record.fulfilled && !record.released);
|
||||
return committedBid || ![g.bidPromises, g.phaseBidPromises, g.turnActionPromises,
|
||||
g.revivalPromises, g.leaderRevivalPromises, g.revivalExpressionPromises,
|
||||
g.bribePromises, g.bribeExpressionPromises].some(groupHasUnsettled);
|
||||
}
|
||||
function coalitionEmperorGroup(g: Game, p: Player) {
|
||||
if (!g.coalitionState || p.faction !== 'emperor' || g.status !== 'playing' || g.advanced ||
|
||||
@@ -16200,7 +16205,7 @@ function alliancePromisePlan(g: Game, p: Player, promises = g.alliancePromises ?
|
||||
if (group && group.members.length >= 3) {
|
||||
if (groupAllianceAnswersMatch(g, p, opportunity, promises, expressions))
|
||||
return {actions: [] as Action[], bribePreparation:false};
|
||||
if (g.coalitionState!.proposal || [g.bribePromises, g.bribeExpressionPromises, g.turnActionPromises].some(unsettledPromises))
|
||||
if (g.coalitionState!.proposal || unsettledPromises(g.turnActionPromises))
|
||||
return null;
|
||||
const trial = structuredClone(g);
|
||||
try {
|
||||
@@ -44560,6 +44565,9 @@ function applyActionInner(
|
||||
}
|
||||
if (t === 'coalitionPropose' || t === 'coalitionAnswer' || t === 'coalitionLeave') {
|
||||
requireRule(coalitionNexusAvailable(g), 'Group negotiations are unavailable in this Nexus.');
|
||||
if (t === 'coalitionPropose' || t === 'coalitionAnswer' && action.accept !== false)
|
||||
requireRule(!coalitionAdmissionBlocked(g),
|
||||
'Resolve current bribe commitments before inviting an ally.');
|
||||
const revision = integer(action.expectedRevision, 0, Number.MAX_SAFE_INTEGER, 'Coalition revision');
|
||||
if (t === 'coalitionPropose') {
|
||||
initializeCoalitionEscrow(g);
|
||||
@@ -46864,6 +46872,7 @@ export function viewGame(state: Game, id: string, now?: number) {
|
||||
groups: coalitionRule(() => coalitionGroups(g.players, g.coalitionState)),
|
||||
proposal: g.coalitionState!.proposal,
|
||||
revision: g.coalitionState!.revision,
|
||||
...(coalitionAdmissionBlocked(g) ? {admissionBlocked:true} : {}),
|
||||
...(g.coalitionState!.variant ? {variant: g.coalitionState!.variant} : {}),
|
||||
} : null,
|
||||
homeworldAllianceBlocks: Object.fromEntries(g.players.filter((p) => p.id !== id)
|
||||
|
||||
Reference in new issue
Block a user