Support group travel agreements
Verify and publish checkpoint container / container (push) Successful in 11m13s

This commit is contained in:
Quintine committed 2026-10-29 08:04:30 +11:00
1 parent 82d857b667
commit e1e02fc1a1
10 files changed
+432 -56

No files matched your search

+10 -7
View File
@@ -8,7 +8,7 @@ import { createFactionDraft, validateFactionDraft, currentFactionDrafter, choose
import { createFactionSwap, validateFactionSwap, answerFactionSwap, cancelFactionSwap,
FactionSwapError, type FactionSwap } from './faction-swap';
import { createPublicDeal, createMultipartyPublicDeal, validatePublicDeals, respondPublicDeal, withdrawPublicDeal,
releasePublicDeal, markPublicDealPaid, voidPublicDealPayment, setPublicDealTravel, PublicDealError, type PublicDeal, type PublicDealPayment } from './public-deals';
releasePublicDeal, markPublicDealPaid, voidPublicDealPayment, setPublicDealTravel, publicDealTravelActor, PublicDealError, type PublicDeal, type PublicDealPayment } from './public-deals';
import { outstandingPublicDealPayments, pendingPublicDealPayments, publicDealPaymentTotal, PublicDealObligationError, type PendingPublicDealPayment } from './public-deal-obligations';
import { CharityPromiseError, liveCharityPromises, charityPromiseAnswers, bindCharityPromise, guardCharityClaim, guardCharityReady, reconcileCharityPromises, type CharityPromise } from './charity-promises';
import { victoryFinalTurn, continueVictoryCalendar, VictoryCalendarError } from './victory-calendar';
@@ -5968,7 +5968,7 @@ function publicDealIntegrity(g: Game): void {
const deal = g.deals?.find(entry => entry.id === row.sourceDeal);
const term = deal?.travel;
requireRule(deal && term && ['active', 'released'].includes(deal.status) &&
row.player === deal.to && row.asker === deal.from && row.turn === deal.turn &&
row.player === publicDealTravelActor(deal) && row.asker === deal.from && row.turn === deal.turn &&
row.answer === term.answer && row.mixed.kind === 'action' &&
row.mixed.action.kind === term.kind && row.mixed.action.territory === term.territory &&
row.mixed.action.minimum === term.minimum && row.mixed.action.sector === undefined &&
@@ -23512,7 +23512,7 @@ function bindTravelTruth(g: Game, p: Player, claim: TravelClaim, answer: boolean
/** A deal is a separately consented public source for the same physical
* travel constraint, not a Truthtrance question or a fabricated card play. */
function bindPublicDealTravel(g: Game, deal: PublicDeal) {
const term = deal.travel, player = getPlayer(g, deal.to);
const term = deal.travel, player = getPlayer(g, publicDealTravelActor(deal));
requireRule(term && deal.turn === g.turn && !g.advanced && g.expansions.length === 0 &&
nativePromiseScopeSupported(g) && travelTargetAvailable(g, player.id) && !g.truthtrance &&
!hasBribePromises(g, player.id) &&
@@ -42396,7 +42396,8 @@ function applyActionWithInitiator(state: Game, id: string, action: Action, initi
const keys = Object.keys(action).sort().join(',');
const single = (keys === 'target,terms,type' || keys === 'payment,target,terms,type' ||
keys === 'target,terms,travel,type' || keys === 'payment,target,terms,travel,type') && typeof action.target === 'string';
const multiple = (keys === 'targets,terms,type' || keys === 'payment,targets,terms,type') && Array.isArray(action.targets) &&
const multiple = (keys === 'targets,terms,type' || keys === 'payment,targets,terms,type' ||
keys === 'targets,terms,travel,type') && Array.isArray(action.targets) &&
action.targets.every(target => typeof target === 'string');
const hasPayment = Object.hasOwn(action, 'payment');
requireRule((single || multiple) && typeof action.terms === 'string' &&
@@ -42413,8 +42414,8 @@ function applyActionWithInitiator(state: Game, id: string, action: Action, initi
? createMultipartyPublicDeal(seats, id, action.targets as string[], action.terms as string, g.turn, event, payment!)
: createMultipartyPublicDeal(seats, id, action.targets as string[], action.terms as string, g.turn, event));
if (Object.hasOwn(action, 'travel')) {
requireRule(single && !g.advanced && g.expansions.length === 0 &&
nativePromiseScopeSupported(g), 'Choose a two-player travel agreement in a supported Basic table.');
requireRule(!g.advanced && g.expansions.length === 0 && nativePromiseScopeSupported(g),
'Choose a travel agreement in a supported Basic table.');
offer = publicDealRule(() => setPublicDealTravel(offer, action.travel, seats));
}
requireRule(!deals.some(deal => deal.id === offer.id), 'This deal identifier is already in use.');
@@ -42439,8 +42440,10 @@ function applyActionWithInitiator(state: Game, id: string, action: Action, initi
requireRule(typeof action.agree === 'boolean', 'Choose whether to request cancellation.');
next = publicDealRule(() => releasePublicDeal(current, g.players, id, action.agree as boolean));
} else next = publicDealRule(() => withdrawPublicDeal(current, g.players, id));
if (current.status === 'offered' && next.status === 'active' && next.travel)
if (current.status === 'offered' && next.status === 'active' && next.travel) {
requireRule(id === publicDealTravelActor(next), 'The traveler must give the final consent.');
bindPublicDealTravel(g, next);
}
if (current.status === 'active' && next.status === 'released' && next.travel) {
const receipt = g.travelPromises?.find(row => row.sourceDeal === next.id);
requireRule(receipt, 'The public travel deal lost its accepted commitment.');