'use client'; import type { Action, GameView } from '@/game/engine'; import { bribeAction } from '@/game/bribe-options'; import { Button } from './ui/button'; type Props = { game: GameView; busy: boolean; send: (action: Action) => void }; /** The server supplies an exact native claim or payment, never a simulated transfer. */ export function TruthCharityPromise({ game, busy, send }: Props) { const own = game.truthCharityPromises.filter(promise => promise.turn === game.turn && promise.player === game.me); if (!own.length) return null; // A later-phase forecast never becomes a current action before Charity opens. const guide = game.phase === 2 ? game.truthCharityGuide : null, actor = game.me, turn = game.turn, action = guide?.action; const signature = JSON.stringify(action), event = action?.charityPromiseEvent; const canAct = () => { const me = game.players.find(player => player.id === actor); const recipient = typeof action?.target === 'string' ? game.players.find(player => player.id === action.target) : undefined; const amount = action?.amount; const payment = action?.type === 'bribe' && !!me && !!recipient && recipient.id !== actor && recipient.id !== me.ally && typeof amount === 'number' && !!bribeAction(game.bribeOptions, recipient.id, amount); const claim = action?.type === 'charity' && !!me && !me.charityClaimed && !game.ready.includes(actor) && !game.charity.truthBlocked && !game.charity.incomePending && !game.charity.orderBlocked && game.charity.amount > 0; return !busy && !!guide && !!action && game.truthCharityGuide === guide && guide.action === action && JSON.stringify(action) === signature && typeof event === 'string' && action.charityPromiseTurn === turn && game.truthCharityPromises.some(promise => promise.player === actor && promise.turn === turn && promise.event === event && promise.answer && !promise.fulfilled && !promise.released) && game.status === 'playing' && game.phase === 2 && game.me === actor && game.turn === turn && (!game.charityOrder || game.charityOrder.turn === turn && game.charityOrder.remaining[0] === actor) && !!me && !me.autopilot && (payment || claim) && !game.truthtrance && !game.response && !game.decision && !game.phaseOpening && !game.automaticContinuationPending && !game.roomControl?.paused && !game.roomControl?.closed; }; const recipient = game.players.find(player => player.id === action?.target)?.name ?? 'the quoted recipient'; return

Your Charity promises

Yes requires an actual eligible claim after the answer; No forbids claiming during this Charity phase. Earlier claims do not count.

{game.phase < 2 &&

Charity has not opened yet. The current turn and its original decisions continue; any claim guide appears only when Charity is available.

} {game.phase === 2 && game.charityOrder?.remaining.includes(actor) && game.charityOrder.remaining[0] !== actor &&

Wait for your Charity turn. The guide appears when your turn begins.

} {guide && action?.type === 'bribe' &&

The quoted payment can make you eligible for Charity. You pay immediately; the other player receives the bribe at the start of Mentat Pause.

} {guide && action && }
; }