Allow Ecaz Ambassador Duke acquisition for an existing ally

This commit is contained in:
Quintine committed 2026-10-26 08:31:55 +11:00
1 parent cab6b41c67
commit 34dccdfd99
21 files changed
+965 -86

No files matched your search

@@ -0,0 +1,78 @@
'use client';
import type { Action, GameView } from '@/game/engine';
import { Button } from './ui/button';
export function EcazDukeAcquisitionChoices({
game,
act,
busy,
}: {
game: GameView;
act: (action: Action) => void;
busy: boolean;
}) {
const entry = game.ambassadorEntry;
if (
!entry ||
entry.stage !== 'offer' ||
entry.effect !== 'ecaz' ||
entry.owner !== game.me ||
game.decision?.kind !== 'ecazAmbassador' ||
game.decision.player !== game.me
)
return null;
const recipients = entry.beneficiaries.length
? entry.beneficiaries
: [{
player: entry.owner,
blocked: entry.dukeAcquisition
? entry.dukeAcquisition.blocked
: 'Duke acquisition is unavailable for this opportunity.',
}];
return (
<div className="flex flex-col gap-3" aria-label="Ecaz Ambassador Duke acquisition">
<p className="m-0 text-sm leading-6">
Acquire Duke Vidal for a listed recipient. The Ambassador returns to
your supply.
</p>
<p className="m-0 text-sm leading-6" aria-label="Provisional shared Duke tenure">
Provisional ordinary acquisition: the chosen recipient keeps Duke Vidal
until battle use, including when unused beyond this turn, unless another
rule takes him away. The separate Duke loan after a new alliance lasts
for the current turn. Only Ecaz may revive him.
</p>
{recipients.map((recipient) => {
const blocked = recipient.blocked;
const disabled = busy || !!blocked;
const reasonId = `ecaz-duke-${entry.event}-${recipient.player}-blocked`;
const name = game.players.find((player) => player.id === recipient.player)?.name ?? recipient.player;
return (
<div key={recipient.player} className="flex flex-col gap-2">
<Button
className="min-h-11 whitespace-normal motion-reduce:transition-none"
data-testid={`ecaz-duke-acquisition-${recipient.player}`}
disabled={disabled}
aria-describedby={blocked ? reasonId : undefined}
onClick={() => {
if (!disabled)
act({
type: 'decision',
event: entry.event,
trigger: true,
beneficiary: recipient.player,
choice: 'duke',
});
}}
>
Acquire Duke Vidal for {name}
</Button>
{blocked && <p id={reasonId} className="m-0 text-sm leading-6">{blocked}</p>}
</div>
);
})}
</div>
);
}
+2 -30
View File
@@ -13,6 +13,7 @@ import { LeaderInspector } from './leader-inspector';
import { AmbassadorInspector, AMBASSADOR_COVERAGE } from './ecaz-ambassadors';
import { AmbassadorMovement } from './ambassador-movement';
import { AmbassadorShipment } from './ambassador-shipment';
import { EcazDukeAcquisitionChoices } from './ecaz-duke-acquisition-choices';
const buttonClass = 'min-h-11 whitespace-normal motion-reduce:transition-none';
@@ -51,11 +52,6 @@ export function EcazEntry({
(choice) => !choice.blocked && selected.includes(choice.card.id),
);
const legalSelection = entry.effect === 'choam' || chosen.length === 1;
const dukeBlock =
entry.dukeAcquisition?.blocked ??
(entry.dukeAcquisition
? null
: 'Duke acquisition is unavailable for this opportunity.');
const allianceBlock =
entry.allianceOffer?.blocked ??
(entry.allianceOffer ? null : 'This alliance opportunity is unavailable.');
@@ -84,11 +80,6 @@ export function EcazEntry({
<>
{entry.effect === 'ecaz' ? (
<>
<p className="m-0 text-sm leading-6">
Acquire Duke Vidal for Ecaz. The Ambassador returns to your
supply. Ecaz keeps Duke until battle use or until Moritani takes
him.
</p>
{duke && (
<LeaderInspector
identity={{
@@ -99,26 +90,7 @@ export function EcazEntry({
}}
/>
)}
<Button
className={buttonClass}
disabled={busy || !!dukeBlock}
aria-describedby={dukeBlock ? `${id}-duke-block` : undefined}
onClick={() => {
if (!dukeBlock)
send({
trigger: true,
beneficiary: entry.owner,
choice: 'duke',
});
}}
>
Acquire Duke Vidal for Ecaz
</Button>
{dukeBlock && (
<p id={`${id}-duke-block`} className="m-0 text-sm leading-6">
{dukeBlock}
</p>
)}
<EcazDukeAcquisitionChoices game={game} act={act} busy={busy} />
<Button
className={buttonClass}
disabled={busy || !!allianceBlock}