Continue Kull through paid auction bonuses
Verify and publish checkpoint container / container (push) Successful in 10m25s

This commit is contained in:
Quintine committed 2026-10-29 01:53:55 +11:00
1 parent 6e1b95d2fc
commit 3d2470b7f8
8 files changed
+363 -5

No files matched your search

+24 -2
View File
@@ -1620,6 +1620,8 @@ export type Game = {
allianceReceipt?: true;
/** New Basic Kull attempts retain whole-answer order and progress. */
turnActionReceipt?: true;
/** A Basic bonus cancellation retains its already-paid auction parent. */
auctionReceipt?: true;
stage: 'offer' | 'counter';
selection?: { source: 'printed' | 'nexus'; card: string; nexusEvent?: string };
intent: { kind: 'ordinary'; use: KaramaUse } | { kind: 'special'; use: SpecialKaramaIntent };
@@ -6938,6 +6940,7 @@ function kullSemutaParentSupported(g: Game, frame?: NonNullable<Game['pendingKul
!frame.resume.decision && !frame.resume.pendingKarama && !frame.resume.phaseOpening;
let revivalSupported = false;
let guildSupported = false;
let bonusSupported = false;
if (nativeResponse && frame && use?.kind === 'cancel') {
// Success has just installed this very Kull restriction. Validate the
// suspended source as it stood before that restriction, without changing
@@ -6949,6 +6952,12 @@ function kullSemutaParentSupported(g: Game, frame?: NonNullable<Game['pendingKul
revivalSupported = !!g.pendingRevival && semutaRevivalKaramaResponse(source, use.response, frame.owner);
guildSupported = (!!g.pendingShipment || !!g.pendingGuildTransport) &&
semutaGuildShipmentKaramaResponse(source, use.response);
bonusSupported = frame.auctionReceipt === true && use.response.kind === 'harkonnenBonus' &&
!!g.currentAuctionSale && (g.currentAuctionSale.origin === 'normal'
? !!g.auction && !g.richeseAuction
: g.currentAuctionSale.origin === 'cache' && !!g.richeseAuction &&
g.richeseAuction.source === 'cache' && !g.auction) &&
semutaBonusNoFieldTraitorResponse(source, use.response, frame.owner);
} catch (error) {
if (!(error instanceof RuleError)) throw error;
}
@@ -6967,8 +6976,8 @@ function kullSemutaParentSupported(g: Game, frame?: NonNullable<Game['pendingKul
!g.pendingHomeworldShipment && !g.pendingTerrorEntry &&
!g.pendingEcazPlacement && !g.pendingMoritaniPlacement &&
!g.pendingArrivalOverlap && !g.pendingArrivalReaction?.length && !g.pendingExchange &&
!g.pendingRichesePurchaseIncome && !g.pendingChoamMarketGhola && !g.currentAuctionSale &&
!g.choamMarket && !g.richeseAuction && !g.pendingFremenMove && !g.pendingIxMove &&
!g.pendingRichesePurchaseIncome && !g.pendingChoamMarketGhola && (!g.currentAuctionSale || bonusSupported) &&
!g.choamMarket && (!g.richeseAuction || bonusSupported) && !g.pendingFremenMove && !g.pendingIxMove &&
!g.pendingMobileMove && !g.pendingChoamMove && !g.ornithopter && !g.ecologicalStorm &&
!g.summonedWorm && !g.wormRides.length;
}
@@ -6977,6 +6986,8 @@ function kullSemutaDiscardSignature(g: Game, c: KullSemutaDiscardContinuation):
resume: c.resume, declaration: c.declaration, use: c.use, turn: g.turn, phase: g.phase,
parent: nullentropyParentSignature(g, c.resume, c.frame.event),
active: g.active, order: g.order, auction: g.auction, richeseAuction: g.richeseAuction,
...(c.frame.auctionReceipt ? {auctionReceipt:c.frame.auctionReceipt, sale:g.currentAuctionSale,
round:g.richeseBidding, cache:g.richeseCache?.map(card => card.id), funding:g.richeseFunding, aid:g.aid} : {}),
restrictions: g.kullRestrictions, discard: g.discard.map(card => card.id),
...(c.battleBinding ? {battle:g.battle} : {}),
players: g.players.map(player => ({id:player.id, hand:player.hand.map(card => card.id),
@@ -19354,6 +19365,9 @@ function kullSignature(g: Game, frame: KullFrame): string {
alliancePromiseSequence:source.alliancePromiseSequence} : {}),
...(frame.turnActionReceipt ? {turnActionReceipt:frame.turnActionReceipt,
turnActionPromises:source.turnActionPromises,travelPromiseOrder:source.travelPromiseOrder} : {}),
...(frame.auctionReceipt ? {auctionReceipt:frame.auctionReceipt, sale:source.currentAuctionSale,
richeseAuction:source.richeseAuction, round:source.richeseBidding,
cache:source.richeseCache?.map(card => card.id), funding:source.richeseFunding, aid:source.aid} : {}),
});
}
/** Only the verified pre-source printed profile may bind its old held cost. */
@@ -19412,6 +19426,11 @@ function kullIntegrity(g: Game): void {
requireRule(frame.turnActionReceipt === undefined || frame.turnActionReceipt === true &&
turnActionPromiseModeSupported(g) && !!g.turnActionPromises?.length,
'The Kull attempt has lost its original whole-answer ledger.');
requireRule(frame.auctionReceipt === undefined || frame.auctionReceipt === true &&
!g.advanced && g.semutaPreview === true && !!g.currentAuctionSale &&
frame.intent.kind === 'ordinary' && frame.intent.use.kind === 'cancel' &&
frame.intent.use.response.kind === 'harkonnenBonus',
'The Kull attempt has lost its original paid auction bonus.');
validateKullAttemptStamp(g, frame, physicalTreacheryCards(g));
requireRule(Number.isSafeInteger(g.kullSequence) && g.kullSequence! > 0 &&
frame.event === JSON.stringify(['kull', g.turn, g.phase, g.kullSequence, frame.player, frame.owner]),
@@ -19504,6 +19523,9 @@ function beginKullAttempt(g: Game, p: Player, card: Card, intent: KullFrame['int
? { allianceReceipt: true as const } : {}),
...(turnActionPromiseModeSupported(g) && g.turnActionPromises?.length
? { turnActionReceipt: true as const } : {}),
...(g.semutaPreview && !g.advanced && !!g.currentAuctionSale && intent.kind === 'ordinary' &&
intent.use.kind === 'cancel' && intent.use.response.kind === 'harkonnenBonus'
? { auctionReceipt: true as const } : {}),
worthless: structuredClone(g.pendingChoamWorthless ?? null), signature: '',
};
// Payment dispatch removed this control before entering its native branch.