Support Sapho ordering for shared arrivals
Verify and publish checkpoint container / container (push) Canceled after 0s

This commit is contained in:
Quintine committed 2026-10-29 05:29:51 +11:00
1 parent b18a767470
commit e457478f7d
18 files changed
+808 -23

No files matched your search

+14 -2
View File
@@ -4,6 +4,7 @@ import { caladanOwnsTerrorEntry, validateCaladanChildArrival, caladanEntryParent
import { currentHomeworldRevivalArrival } from './homeworld-revival-return';
import { validateRevivalArrivalSource, revivalOwnsTerrorEntry, validRevivalEntryParent,
revivalEntryParentTuple, type RevivalEntryParent } from './revival-terror-entry';
import { validateSaphoArrivalOrder } from './sapho-arrival-order';
type Overlap = NonNullable<Game['pendingArrivalOverlap']> & { revivalArrival?: RevivalEntryParent };
type TerrorEntry = NonNullable<Game['pendingTerrorEntry']> & { revivalArrival?: RevivalEntryParent };
@@ -28,7 +29,8 @@ export function arrivalOverlapSignature(record: Overlap): string {
record.ambassadorToken, record.terrorTokens,
...(record.revivalArrival === undefined ? [] : [revivalEntryParentTuple(record.revivalArrival)]),
...(record.victoryEvent === undefined ? [] : [['caladanVictory', record.victoryEvent]]),
...(record.caladanArrival === undefined ? [] : [caladanEntryParentTuple(record.caladanArrival)])]);
...(record.caladanArrival === undefined ? [] : [caladanEntryParentTuple(record.caladanArrival)]),
...(record.saphoOrder === undefined ? [] : [['saphoArrivalOrder', record.saphoOrder]])]);
}
/** A fresh discard belongs to the active owner of an ordinary or bound revived entry.
@@ -52,9 +54,19 @@ function ordinaryDiscardOverlap(g: DiscardContext, owner: Overlap['first']): Ove
!['shipment', 'movement'].includes(overlap.cause)) return null;
const ecaz = g.order.indexOf(overlap.ecaz), moritani = g.order.indexOf(overlap.moritani);
if (ecaz < 0 || moritani < 0 || ecaz === moritani ||
overlap.first !== (ecaz < moritani ? 'ambassador' : 'terror') ||
!g.players.some(p => p.id === overlap.ecaz && p.faction === 'ecaz') ||
!g.players.some(p => p.id === overlap.moritani && p.faction === 'moritani')) return null;
if (overlap.saphoOrder === undefined) {
if (overlap.first !== (ecaz < moritani ? 'ambassador' : 'terror')) return null;
} else {
const original: [string, string] = ecaz < moritani
? [overlap.ecaz, overlap.moritani] : [overlap.moritani, overlap.ecaz];
const selectedFirst = overlap.first === 'ambassador' ? overlap.ecaz : overlap.moritani;
try {
validateSaphoArrivalOrder(overlap.saphoOrder, overlap.event, original, selectedFirst);
if (overlap.saphoOrder.frame.passed.length !== original.length) return null;
} catch { return null; }
}
const active = overlap.stage === 'first' ? overlap.first :
overlap.first === 'ambassador' ? 'terror' : 'ambassador';
return active === owner ? overlap : null;