Resolve Sneak arrivals during Great Maker rides
Verify and publish checkpoint container / container (push) Canceled after 0s
Verify and publish checkpoint container / container (push) Canceled after 0s
This commit is contained in:
1 parent
57321c2c8d
commit
2ad7f127ec
9 files changed
+290
-13
No files matched your search
+17
-3
@@ -2345,6 +2345,8 @@ export type Game = {
|
||||
rider: string;
|
||||
parent: {kind: 'terror' | 'ambassador' | 'overlap'; event: string};
|
||||
stage: 'parent' | 'queued' | 'resolving';
|
||||
/** Bind the held ride to the exact Great Maker encounter when applicable. */
|
||||
greatMaker?: {event: string; signature: string};
|
||||
} | null;
|
||||
/** One committed entry with two independently optional expansion reactions. */
|
||||
pendingArrivalOverlap?: {
|
||||
@@ -14578,6 +14580,7 @@ function afterWorm(g: Game) {
|
||||
g.pendingAmbassador?.resume === 'wormRide' ||
|
||||
g.pendingTerrorEntry?.resume === 'wormRide' ||
|
||||
g.pendingArrivalOverlap?.resume === 'wormRide' ||
|
||||
!!g.pendingSneakWorm ||
|
||||
(g.pendingKarama?.use.kind === 'cancel' &&
|
||||
g.pendingKarama.use.response.kind === 'advisorFlip' &&
|
||||
g.pendingKarama.use.response.advisorResume === 'wormRide') ||
|
||||
@@ -14890,6 +14893,7 @@ function stampGreatMaker(g: Game) {
|
||||
g.greatMaker!.signature = greatMakerSignature(g.greatMaker!);
|
||||
}
|
||||
function greatMakerIntegrity(g: Game) {
|
||||
sneakWormIntegrity(g);
|
||||
const frame = g.greatMaker, continuation = g.pendingTreacheryDiscard?.continuation;
|
||||
const controls = [g, g.pendingExchange, g.pendingNullentropy?.resume, g.pendingRicheseGift?.resume,
|
||||
g.pendingRichesePurchaseIncome?.resume, continuation && 'resume' in continuation ? continuation.resume : null,
|
||||
@@ -14935,6 +14939,12 @@ function greatMakerIntegrity(g: Game) {
|
||||
controls.some(control => control?.decision?.kind === 'intrusion' && control.decision.wormRide && control.decision.player === byFaction(g,'beneGesserit')?.id && control.decision.territory === frame.arrival!.territory) ||
|
||||
responses.some(response => response?.kind === 'advisorFlip' && response.advisorResume === 'wormRide' && response.owner === byFaction(g,'beneGesserit')?.id && response.location === frame.arrival!.territory) ||
|
||||
(g.pendingAmbassador?.resume === 'wormRide' && g.pendingAmbassador.territory === frame.arrival!.territory && g.pendingAmbassador.sector === frame.arrival!.sector) ||
|
||||
(g.pendingArrivalOverlap?.resume === 'wormRide' && g.pendingArrivalOverlap.cause === 'wormRide' &&
|
||||
g.pendingArrivalOverlap.entrant === byFaction(g, 'fremen')?.id &&
|
||||
g.pendingArrivalOverlap.territory === frame.arrival!.territory && g.pendingArrivalOverlap.sector === frame.arrival!.sector) ||
|
||||
(g.pendingSneakWorm?.greatMaker?.event === frame.event && g.pendingSneakWorm.greatMaker.signature === frame.signature &&
|
||||
g.pendingSneakWorm.rider === byFaction(g, 'fremen')?.id &&
|
||||
g.pendingSneakWorm.turn === g.turn && g.pendingSneakWorm.phase === g.phase) ||
|
||||
(g.pendingTerrorEntry?.resume === 'wormRide' && g.pendingTerrorEntry.territory === frame.arrival!.territory && g.pendingTerrorEntry.sector === frame.arrival!.sector),
|
||||
'The Great Maker has lost its reserve arrival interaction.');
|
||||
}
|
||||
@@ -15131,6 +15141,9 @@ function sneakWormIntegrity(g: Game): void {
|
||||
g.players.some(player => player.id === frame.rider && player.faction === 'fremen') &&
|
||||
!!frame.parent && ['terror','ambassador','overlap'].includes(frame.parent.kind) &&
|
||||
typeof frame.parent.event === 'string' && frame.parent.event.length > 0 &&
|
||||
(frame.greatMaker === undefined || !!frame.greatMaker && g.greatMaker?.stage === 'arrival' &&
|
||||
frame.greatMaker.event === g.greatMaker.event && frame.greatMaker.signature === g.greatMaker.signature) &&
|
||||
(g.greatMaker?.stage !== 'arrival' || frame.greatMaker !== undefined) &&
|
||||
(frame.stage === 'parent' || frame.stage === 'queued' ? queued.length === 1 :
|
||||
frame.stage === 'resolving' && queued.length === 0),
|
||||
'The saved Sneak arrival lost its original worm continuation.');
|
||||
@@ -27920,8 +27933,6 @@ function sneakAttackOptions(
|
||||
let blocked: string | null = null;
|
||||
try {
|
||||
allowedEntry(g, owner, entry.territory, entry.sector);
|
||||
if (g.advanced && g.greatMaker?.stage === 'arrival')
|
||||
blocked = 'Sneak Attack during a Great Maker arrival needs its original continuation; send no forces or leave the token hidden.';
|
||||
} catch (error) {
|
||||
if (!(error instanceof RuleError)) throw error;
|
||||
blocked = error.message;
|
||||
@@ -28218,7 +28229,10 @@ function decideTerror(g: Game, p: Player, action: Action) {
|
||||
requireRule(rider && !g.pendingSneakWorm && g.phase === 1,
|
||||
'This Sneak arrival cannot retain its original worm rider.');
|
||||
const event = crypto.randomUUID();
|
||||
g.pendingSneakWorm = {event, turn:g.turn, phase:g.phase, rider:rider.id, parent:wormParent!, stage:'parent'};
|
||||
const greatMaker = g.greatMaker?.stage === 'arrival'
|
||||
? {event:g.greatMaker.event, signature:g.greatMaker.signature} : undefined;
|
||||
g.pendingSneakWorm = {event, turn:g.turn, phase:g.phase, rider:rider.id, parent:wormParent!, stage:'parent',
|
||||
...(greatMaker ? {greatMaker} : {})};
|
||||
(g.pendingArrivalReaction ??= []).push({entrant:p.id,territory:entry.territory,
|
||||
sector:entry.sector,amount,elite:0,cause:'shipment',resume:'none',turn:g.turn,
|
||||
phase:g.phase,nativeSneakAdvisor:true,sneakWormEvent:event});
|
||||
|
||||
Reference in new issue
Block a user