Support Emperor special Karama truth commitments
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
b448144c52
commit
add8e1d51a
14 files changed
+345
-20
No files matched your search
+29
-3
@@ -19000,7 +19000,8 @@ function karamaSpendingBlock(g: Game, p: Player, card: Card, purpose?: KullPurpo
|
||||
required.effect === 'karamaShipment' && purpose === 'shipment-price' ||
|
||||
required.effect === 'karamaBattleCancel' && !!g.response &&
|
||||
purpose === karamaUsePurpose(g, { kind: 'cancel', response: g.response }) ||
|
||||
required.effect === 'karamaHarkonnenSpecial' && purpose === 'special:harkonnen') &&
|
||||
required.effect === 'karamaHarkonnenSpecial' && purpose === 'special:harkonnen' ||
|
||||
required.effect === 'karamaEmperorSpecial' && purpose === 'special:emperor') &&
|
||||
windowCardOpportunity(g, required.effect)?.source === required.source))
|
||||
return 'Retain this opportunity without a forbidden printed Karama cost.';
|
||||
const kullBlock = kullKaramaBlock(g, p, purpose);
|
||||
@@ -20492,8 +20493,10 @@ function spendKarama(g: Game, p: Player, card: Card, use: KaramaUse, kullOffered
|
||||
// still-open Harkonnen special promise before a foreign response can park
|
||||
// the shared reconciler.
|
||||
if (card.kind === 'special' && card.effect === 'karama' && auctionRows.some(row => {
|
||||
const stage = row.windowCards?.karamaHarkonnenSpecial;
|
||||
return stage && !stage.closed && windowCardOpportunity(g, 'karamaHarkonnenSpecial', stage.source)?.source === stage.source;
|
||||
return (['karamaHarkonnenSpecial', 'karamaEmperorSpecial'] as const).some(effect => {
|
||||
const stage = row.windowCards?.[effect];
|
||||
return stage && !stage.closed && windowCardOpportunity(g, effect, stage.source)?.source === stage.source;
|
||||
});
|
||||
})) guardTurnActionPrintedCardCost(g, p, used);
|
||||
if (auctionWindow && auctionRows.some(row => row.windowCards?.karamaAuction?.source === auctionWindow))
|
||||
guardTurnActionAuctionClosure(g, p.id, auctionRows);
|
||||
@@ -22384,6 +22387,24 @@ function quotedAmalReady(g: Game, actor: string): boolean {
|
||||
function* nativeWindowCardActions(g: Game, actor: string, effect: WindowCardEffect): Generator<Action> {
|
||||
if (!windowCardOpportunity(g, effect)) return;
|
||||
const player = getPlayer(g, actor);
|
||||
if (effect === 'karamaEmperorSpecial') {
|
||||
if (player.faction !== 'emperor' || g.kullPreview || g.pendingKull || g.semutaPreview ||
|
||||
g.semutaRecruitsPreview || g.semutaAdvancedOrdinaryPreview || g.truthtrance ||
|
||||
g.response || g.decision || g.phaseOpening || g.pendingKarama ||
|
||||
g.pendingTreacheryDiscard || g.pendingNullentropy) return;
|
||||
for (const card of player.hand.filter(card => card.kind === 'special' && card.effect === 'karama')) {
|
||||
const actions: Action[] = player.leaders.filter(leader => leader.dead && !leader.capturedBy && !leader.gholaBy)
|
||||
.map(leader => ({ type: 'card', mode: 'special', card: card.id, leader: leader.id }));
|
||||
for (let amount = 1; amount <= Math.min(3, player.tanks); amount++)
|
||||
for (let elite = 0; elite <= Math.min(amount, player.elites?.tanks ?? 0); elite++)
|
||||
actions.push({ type: 'card', mode: 'special', card: card.id, amount, elite });
|
||||
for (const action of actions) try {
|
||||
const intent = prepareSpecialKaramaIntent(g, actor, action);
|
||||
if (intent.kind === 'emperorForces' || intent.kind === 'emperorLeader') yield action;
|
||||
} catch (error) { if (!(error instanceof RuleError)) throw error; }
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (effect === 'karamaHarkonnenSpecial') {
|
||||
const opportunity = windowCardOpportunity(g, effect);
|
||||
// The public source identifies the unique native owner; eligibility and
|
||||
@@ -42816,8 +42837,13 @@ function resolveSpecialKaramaEffect(g: Game, p: Player, card: Card, intent: Spec
|
||||
log(g, `${p.name} used special Karama to revive ${n} forces for free.`);
|
||||
}
|
||||
techIncome(g, 'axlotl', p);
|
||||
const opportunity = windowCardOpportunity(g, 'karamaEmperorSpecial');
|
||||
if (opportunity && card.kind === 'special' && card.effect === 'karama')
|
||||
recordNativeTurnActionWindowCard(g, p.id, 'karamaEmperorSpecial', opportunity.source);
|
||||
discard(g, p, card.id);
|
||||
p.specialKaramaUsed = true;
|
||||
if (liveTurnActionPromises(g.turnActionPromises ?? [], p.id, g.turn).length)
|
||||
guardTurnActionPrintedCardCost(g, p, card);
|
||||
stageSpecialKaramaCost(g, intent, card, true);
|
||||
} else if (intent.kind === 'harkonnen') {
|
||||
const target = getPlayer(g, intent.target),
|
||||
|
||||
Reference in new issue
Block a user