'use client'; import type { Action, GameView } from '@/game/engine'; import { liveRevivalExpressionPromises, revivalExpressionPromiseModeSupported, revivalExpressionText } from '@/game/revival-expression-promises'; import { Button } from './ui/button'; type RevivalExpressionPromiseProps = { game: GameView; busy: boolean; send: (action: Action) => void }; const leaderName = (game: GameView, id: string) => id === 'kwisatz' ? 'Kwisatz Haderach' : game.allLeaders.find(leader => leader.id === id)?.name ?? 'the named leader'; /** Preserve the authoritative whole-expression preparation or return quote. * A guide suggests a legal next action without committing to a fixed branch. */ export function RevivalExpressionPromiseGuideButton(props: RevivalExpressionPromiseProps) { const game = props.game, guide = game.revivalExpressionPromiseGuide; if (!guide) return null; const actor = game.me, turn = game.turn, phase = guide.phase, order = game.revivalOrder; const action = guide.action, event = action.revivalExpressionPromiseEvent, signature = JSON.stringify(action); const canAct = () => { const current = props.game, me = current.players.find(player => player.id === current.me); const payment = phase === 3 && action.type === 'decision' && current.decision?.kind === 'auctionPayment' && current.decision.player === actor; const native = current.richeseAuction; const nativePass = phase === 3 && action.type === 'richeseBid' && native && native.event === action.event && !native.outcome && native.eligible.includes(actor) && (native.method === 'silent' ? !native.submitted.includes(actor) && action.amount === 0 : native.active === actor && action.amount === null) && action.allyPayment === 0; const request = current.revivalRequests[actor]; const acceptedQuote = action.type === 'acceptLeaderRevival' && !!request && !request.declined && typeof request.price === 'number' && request.price === action.leaderRevivalPrice; const opportunity = phase === 2 ? !current.ready.includes(actor) && (action.type === 'charity' || action.type === 'ready') : phase === 3 ? payment || nativePass || action.type === 'passBid' && !native && current.auction?.active === actor : phase === 4 && !current.ready.includes(actor) && (action.type === 'revive' || action.type === 'reviveLeader' || action.type === 'reviveKwisatz' || acceptedQuote || action.type === 'ready') && current.revivalOrder === order && (!current.revivalOrder || current.revivalOrder.turn === turn && current.revivalOrder.remaining[0] === actor && current.active === actor); return !props.busy && current === game && revivalExpressionPromiseModeSupported(current) && current.status === 'playing' && current.phase === phase && current.me === actor && current.turn === turn && opportunity && current.revivalExpressionPromiseGuide === guide && current.revivalExpressionPromiseGuide.phase === phase && current.revivalExpressionPromiseGuide.action === action && JSON.stringify(action) === signature && typeof event === 'string' && (liveRevivalExpressionPromises(current.revivalExpressionPromises, actor, turn).some(promise => promise.event === event) || (current.mixedRevivalPromises ?? []).some(promise => promise.event === event && promise.player === actor && promise.turn === turn && !promise.fulfilled && !promise.released)) && !!me && !me.autopilot && !current.truthtrance && !current.response && (!current.decision || payment) && !current.phaseOpening && !current.automaticContinuationPending && !current.roomControl?.paused && !current.roomControl?.closed; }; return ; } export function RevivalExpressionPromises(props: RevivalExpressionPromiseProps) { const own = props.game.revivalExpressionPromises.filter(promise => promise.player === props.game.me); if (!own.length) return null; const live = liveRevivalExpressionPromises(own, props.game.me, props.game.turn).length > 0; const other = props.game.revivalOrder?.remaining[0]; const waiting = live && (props.game.phase < 4 || props.game.phase === 4 && other && other !== props.game.me); return

Your Revival expression promises

AND requires every condition; OR requires at least one. No negates the whole expression, not each condition separately. Legal alternatives remain available; no fixed branch is selected for you. Only future actual ordinary native force and named-leader returns after the answer count. Prior returns, requests alone, Ghola, foreign leaders and special card returns do not count.

Physical force progress is cumulative across smaller returns; each normal or elite counter counts once. Original costs, revival cycles, limits and turn order still apply. A guide may accept an existing current Tleilaxu quote; it does not arrange new consent. {' '}Revival expression rules.

{waiting &&

Your Revival opportunity is still ahead; {props.game.phase < 4 ? 'continue the current phase and preserve the resources for your whole answer.' : 'this promise remains visible while the current actor finishes.'}

} {live && }
; }