'use client'; import type { GameView } from '@/game/engine'; import type { MixedActionExpression } from '@/game/mixed-action-question'; import { parseRevivalActionClaim, type RevivalActionClaim } from '@/game/mixed-revival-question'; import { REVIVAL_EXPRESSION_MAX_DEPTH, REVIVAL_EXPRESSION_MAX_LEAVES } from '@/game/revival-expression-promises'; import { MixedActionFields, mixedActionInputError, type MixedActionConfig } from './mixed-action-fields'; import { Input } from './ui/input'; /** Names depend only on the respondent's public faction. Current casualties, * custody and eligibility never determine which questions can be authored. */ const leaders = (game: GameView, target: string) => { const faction = game.players.find(player => player.id === target)?.faction; return [...game.allLeaders.filter(leader => !!faction && leader.faction === faction), ...(game.advanced && faction === 'atreides' ? [{ id: 'kwisatz', name: 'Kwisatz Haderach' }] : [])]; }; const newForces = (): RevivalActionClaim => ({ kind: 'forces', counter: 'total', minimum: 1 }); const config: MixedActionConfig = { prefix: 'mixed-revival', legend: 'Mixed current-fact / future ordinary Revival claim', actionLabel: 'ordinary Revival condition', actionTiming: 'Future ordinary Revival · this turn', actionHelp: <>Count cumulative future ordinary native force and named-leader returns after the answer this turn. Smaller force returns add together; each normal or elite physical counter counts once. Prior returns, requests alone, Ghola, foreign leaders and special card returns do not count. Original costs, revival cycles, limits and turn order still apply. The claim grants no extra Revival opportunity. An unknown current fact uses the conservative future commitment that guarantees the whole answer. If no such value is available, the answer is I don’t know., fallbackError: 'Choose a current fact and a future ordinary Revival condition.', maxLeaves: REVIVAL_EXPRESSION_MAX_LEAVES, maxDepth: REVIVAL_EXPRESSION_MAX_DEPTH, newAction: newForces, parseAction: (value, game, target) => { const action = parseRevivalActionClaim(value); if (action.kind === 'leader' && !leaders(game, target).some(leader => leader.id === action.leader)) throw new Error('Choose a public native leader for the respondent’s faction.'); return action; }, renderAction: ({ value, id, game, target, disabled, onChange }) => { const choices = leaders(game, target); return <> {value.kind === 'forces' ? <> 20} onChange={event => onChange({ ...value, minimum: event.currentTarget.valueAsNumber })} /> : <> } ; }, }; export function mixedRevivalInputError(value: unknown, game: GameView, target: string): string | null { return mixedActionInputError(value, game, target, config); } export function MixedRevivalFields(props: { value: MixedActionExpression; game: GameView; target: string; disabled: boolean; onChange: (expression: MixedActionExpression) => void; }) { return MixedActionFields({ ...props, config }); }