Connect Moritani Nexus losing-card retention

This commit is contained in:
Quintine committed 2026-09-28 11:13:39 +10:00
1 parent cb98ead411
commit 886a8f4478
16 files changed
+551 -51

No files matched your search

+1 -1
View File
@@ -2304,7 +2304,7 @@ export function GameTable({
: g.decision.kind === 'moritaniAssassinate'
? 'Moritani · Assassinate Leaders'
: g.decision.kind === 'moritaniRetention'
? 'Moritani · allied card retention'
? g.decision.source === 'nexus' ? 'Moritani Nexus · after-loss choice' : 'Moritani · allied card retention'
: g.decision.kind === 'moritaniTerror'
? 'Moritani · Terror entry reaction'
: g.decision.kind === 'moritaniSetup'
+41 -20
View File
@@ -2,7 +2,6 @@
import { useId, useState } from 'react';
import type { Action, GameView } from '@/game/engine';
import { territory } from '@/game/board';
import { battleCardLabel } from '@/game/battle-cards';
import { Button } from './ui/button';
import { CardInspector, CardRules } from './card-inspector';
@@ -21,6 +20,11 @@ export function MoritaniRetention({
const decision = game.decision;
if (decision?.kind !== 'moritaniRetention' || decision.player !== game.me)
return null;
const nexus = decision.source === 'nexus';
const canKeep = !nexus || !!game.nexusMoritaniRetention?.canKeep;
const choose = (keep: string | null): Action => nexus
? { type: 'decision', event: decision.event, keep }
: { type: 'decision', keep };
const me = game.players.find((player) => player.id === game.me);
if (!me) return null;
const cards = (me.hand ?? []).filter((card) =>
@@ -28,23 +32,42 @@ export function MoritaniRetention({
);
const selectedCard = cards.find((card) => card.id === selected);
const owner = game.players.find((player) => player.id === decision.owner);
const location = game.combatLocations.find(place => place.id === decision.territory)?.name
?? decision.territory;
const disabled = busy || !!game.response || !!game.truthtrance;
return (
<section
className="min-w-0 space-y-4"
aria-label="Moritani allied card retention"
aria-label={nexus ? 'Postbattle Moritani Nexus choice' : 'Moritani allied card retention'}
>
<p>
You lost the battle in {territory(decision.territory).name}. Your
Moritani ally{owner ? `, ${owner.name},` : ''} lets you choose one
eligible card played in that battle to keep. Using this ability is
optional.
</p>
<p className="fine">
Declare one card, then the table may respond with Karama before you
retain it. If the power is canceled, all these cards are discarded.
Declining also discards them.
</p>
{nexus ? (
<>
<p>
You lost the battle in {location}. Every
loser with an eligible played card gets this choice. If you hold the
Moritani Nexus card while unallied, spend it to retain one played
card a winner could keep; otherwise continue.
</p>
<p className="fine">
Used cards with mandatory discard cannot be retained. Spending the
Nexus card is public; your other hand cards remain private.
</p>
</>
) : (
<>
<p>
You lost the battle in {location}. Your
Moritani ally{owner ? `, ${owner.name},` : ''} lets you choose one
eligible card played in that battle to keep. Using this ability is
optional.
</p>
<p className="fine">
Declare one card, then the table may respond with Karama before you
retain it. If the power is canceled, all these cards are discarded.
Declining also discards them.
</p>
</>
)}
<fieldset
className="m-0 min-w-0 space-y-3 border-0 p-0"
disabled={disabled}
@@ -85,20 +108,18 @@ export function MoritaniRetention({
)}
<Button
className="min-h-11 w-full whitespace-normal"
disabled={disabled || !selectedCard}
onClick={() =>
selectedCard && act({ type: 'decision', keep: selectedCard.id })
}
disabled={disabled || !selectedCard || !canKeep}
onClick={() => selectedCard && canKeep && act(choose(selectedCard.id))}
>
Declare selected card
{nexus ? 'Spend Moritani Nexus · retain selected card' : 'Declare selected card'}
</Button>
<Button
variant="outline"
className="min-h-11 w-full whitespace-normal"
disabled={disabled}
onClick={() => act({ type: 'decision', keep: null })}
onClick={() => act(choose(null))}
>
Decline retention
{nexus ? 'Continue without retention' : 'Decline retention'}
</Button>
</section>
);