'use client'; import type { GameView } from '@/game/engine'; import type { MixedActionExpression } from '@/game/mixed-action-question'; import { MIXED_BATTLE_MAX_DEPTH, MIXED_BATTLE_MAX_LEAVES, MIXED_BATTLE_MAX_NODES, MIXED_BATTLE_MAX_TERMS, parseBattleActionClaim, type MixedBattleActionClaim, } from '@/game/mixed-battle-question'; import { TRUTH_CARD_NAMES } from '@/game/truthtrance-card-names'; import { CHEAP_HERO_TRAITOR } from '@/game/traitors'; import { MixedActionFields, mixedActionInputError, type MixedActionConfig } from './mixed-action-fields'; import { Input } from './ui/input'; const dial = (): MixedBattleActionClaim => ({ kind: 'dial', compare: 'eq', value: 0 }); /** The original plan-element vocabulary is public. Authoring a question never * inspects either player's cards, available leaders, forces or ability to pay. */ const config: MixedActionConfig = { prefix: 'mixed-battle', legend: 'Mixed current-fact / actual battle-plan claim', actionLabel: 'battle-plan condition', actionTiming: 'Actual battle plan · this battle', actionHelp: <>Battle conditions concern the respondent’s actual plan in this battle, including a plan already fixed, sealed or revealed. Current facts are snapshotted at the answer. An unknown current fact uses the conservative plan commitment that guarantees the whole answer; if no such answer is possible, the answer is I don’t know. No alternate route is forced. Native Voice, Prescience, card, leader, force and payment rules still apply., fallbackError: 'Choose a current fact and an actual battle-plan condition.', maxLeaves: MIXED_BATTLE_MAX_LEAVES, maxDepth: MIXED_BATTLE_MAX_DEPTH, maxNodes: MIXED_BATTLE_MAX_NODES, maxTerms: MIXED_BATTLE_MAX_TERMS, newAction: dial, parseAction: (value, game) => parseBattleActionClaim(value, game.allLeaders.map(leader => leader.id)), renderAction: ({ value, id, game, disabled, onChange }) => <> {(value.kind === 'dial' || value.kind === 'support') && <> 40 || !Number.isInteger(value.value * (value.kind === 'dial' ? 2 : 1))} onChange={event => onChange({ ...value, value: event.currentTarget.valueAsNumber })} /> } {(value.kind === 'weapon' || value.kind === 'defense') && <> } {value.kind === 'leader' && <> } {value.kind === 'kwisatz' && <> } , }; export function mixedBattleInputError(value: unknown, game: GameView, target: string): string | null { return mixedActionInputError(value, game, target, config); } export function MixedBattleFields(props: { value: MixedActionExpression; game: GameView; target: string; disabled: boolean; onChange: (expression: MixedActionExpression) => void; }) { return MixedActionFields({ ...props, config }); }