Prototype Emperor Nexus bank-auction purchase

This commit is contained in:
Quintine committed 2026-09-28 13:38:49 +10:00
1 parent 23ce406872
commit 1bda2ec31e
18 files changed
+916 -49

No files matched your search

+1 -1
View File
@@ -120,7 +120,7 @@ export function NexusCards({ game, act, busy }: { game: GameView; act: (action:
<div>
<h3>Nexus cards</h3>
<p className="fine">{offer.deckCount} in deck · {offer.discardCount} discarded · {Object.values(offer.held).filter((held) => held === true).length} held</p>
<p>Playable effects include Atreides inspections, Harkonnen exchanges, and Tleilaxu, Ixian, Bene Gesserit, Emperor, CHOAM and Moritani Cunning, plus Emperor Secret Ally’s three extra free revivals, Fremen Secret Ally’s ordinary three free revivals, Richese Secret Ally reserve shipping and Guild Cunning’s second shipment or absent-Guild Secret Ally shipping. Use the controls shown at each effect’s timing. CHOAM’s Kull Wahad effect, Moritani Cunning relocation and Grumman combinations, and other unfinished effects remain unavailable.</p>
<p>Playable effects include Atreides inspections, Harkonnen exchanges, and Tleilaxu, Ixian, Bene Gesserit, Emperor, CHOAM and Moritani Cunning, plus Emperor Secret Ally’s bank-auction purchase and three extra free revivals, Fremen Secret Ally’s ordinary three free revivals, Richese Secret Ally reserve shipping and Guild Cunning’s second shipment or absent-Guild Secret Ally shipping. Use the controls shown at each effect’s timing. CHOAM’s Kull Wahad effect, Moritani Cunning relocation and Grumman combinations, and other unfinished effects remain unavailable.</p>
</div>
{game.nexusAtreides && offer.card === 'atreides' && (
<div aria-label="Atreides Nexus effect" className="space-y-2">
+42 -1
View File
@@ -2,7 +2,7 @@
import { useState } from 'react';
import type { Action, GameView } from '@/game/engine';
import { nexusEmperorRevivalAction } from '@/game/nexus-emperor-secret-ally-options';
import { nexusEmperorPurchaseAction, nexusEmperorRevivalAction } from '@/game/nexus-emperor-secret-ally-options';
import { Button } from '@/components/ui/button';
export function NexusEmperorSecretAlly({
@@ -18,6 +18,47 @@ export function NexusEmperorSecretAlly({
const offer = game.nexusEmperorSecretAlly;
const owner = game.players.find((player) => player.id === game.me);
const emperorSeated = game.players.some((player) => player.faction === 'emperor');
const purchase =
offer?.purchase &&
game.nexusCards?.card === 'emperor' &&
!!owner &&
!emperorSeated &&
game.status === 'playing' &&
game.phase === 3 &&
game.decision?.kind === 'auctionPayment' &&
game.decision.player === game.me
? offer.purchase
: null;
if (purchase) {
const action = nexusEmperorPurchaseAction(game);
const blocked = busy || !action;
const reason = purchase.blocked ??
(!action
? (owner?.spice ?? 0) < purchase.price
? `You need ${purchase.price} spice in your own supply for this bid.`
: 'Finish the current interaction before spending the Emperor Nexus card.'
: null);
return (
<section className="min-w-0 space-y-3" aria-label="Emperor Secret Ally purchase">
<h3 className="font-serif text-xl">Emperor Secret Ally</h3>
<p className="text-base leading-7">
Your final bid is {purchase.price} spice. You must have all {purchase.price} spice
in your own supply without ally aid. Spend the Emperor Nexus card to keep that
spice instead of paying the bank; you receive the auction card normally.
</p>
{reason && <p className="notice">{reason}</p>}
<Button
className="min-h-11 whitespace-normal"
disabled={blocked}
onClick={() => {
if (!blocked && action) act(action);
}}
>
Spend Emperor Nexus card · retain {purchase.price} spice
</Button>
</section>
);
}
const eligible =
offer?.revival &&
game.nexusCards?.card === 'emperor' &&