diff --git a/components/game-table.tsx b/components/game-table.tsx
index 469650b3..405d2568 100644
--- a/components/game-table.tsx
+++ b/components/game-table.tsx
@@ -2,6 +2,7 @@
import { TraitorDecisionPromises } from './traitor-decision-promises';
import { MovementPromises } from './movement-promises';
import { MovementExpressionPromises } from './movement-expression-promises';
+import { MixedMovementPromises } from './mixed-movement-promises';
import { HomeworldEcazDuke } from './homeworld-ecaz-duke';
import { integerInputValue } from '../lib/integer-input';
import { normalAuctionHandBlock } from '@/game/normal-auction';
@@ -1989,6 +1990,7 @@ export function GameTable({
{g.karamaBlocked}
} {g.karamaPurposeBlocks?.map(({purpose, message}) =>{message}
)} diff --git a/components/mixed-movement-fields.tsx b/components/mixed-movement-fields.tsx new file mode 100644 index 00000000..e39ad057 --- /dev/null +++ b/components/mixed-movement-fields.tsx @@ -0,0 +1,181 @@ +'use client'; + +import type { ReactElement } from 'react'; +import type { GameView } from '@/game/engine'; +import { TERRITORIES } from '@/game/board'; +import { parseMixedActionExpression, type MixedActionExpression } from '@/game/mixed-action-question'; +import { MOVEMENT_EXPRESSION_MAX_DEPTH, MOVEMENT_EXPRESSION_MAX_LEAVES } from '@/game/movement-expression-promises'; +import { parseMovementClaim, type MovementClaim } from '@/game/movement-promises'; +import type { TruthFact } from '@/game/truthtrance'; +import { truthFactExpressionError } from '@/game/truth-fact-expression'; +import { TruthFactFields, invalidTruthFact } from './mixed-shipment-fields'; +import { Button } from './ui/button'; +import { Input } from './ui/input'; + +type MixedMovementExpression = MixedActionExpressionCurrent facts are evaluated at the answer. They create no promise to keep cards, spice or forces afterward. + Only the aggregate answer is shared. Individual fact answers and any reduced future branch remain private. + 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.
+Future movement progress records the maximum physical forces in one actual move after the answer, never the sum of smaller moves. + Prior moves and shipments do not count. A shipment can prepare a move but does not fulfill a movement condition. + The original movement, shipment, preparation, payment and turn rules still apply; this claim grants no extra movement opportunity. + A paid Box search must finish before moving; its fee is paid only once. + {' '}Mixed movement rules.
+ {waiting &&Your Movement turn is still ahead. Keep any needed forces, spice and cards available; movement controls appear on your turn. + {game.phase < 5 && ' Complete any current preparation below before confirming readiness.'} + {game.decision?.kind === 'nullentropy' && game.decision.player === game.me && ' Your already-paid Box search can finish now.'} +
} + {live && !sharedGuideElsewhere &&This answers the whole current-fact and future-movement question. Facts are fixed at this answer; later card or spice changes do not rewrite it. Unknown facts require an answer you can guarantee through the remaining legal movement. Individual fact answers and compiled branches are not published.
+ {(g.truthMixedMovementAnswers ?? []).map(answer =>Yes requires the whole AND/OR question to become true through your future physical ground moves. No keeps the whole expression false and may permit some moves. Each condition needs one qualifying group; smaller moves never add together. Original movement allowances, cards and responses still apply.
@@ -435,6 +450,7 @@ export function Truthtrance({ + @@ -523,6 +539,14 @@ export function Truthtrance({ {!g.truthTraitorTargets.includes(target) &&Reveal both plans and choose a voter who has not submitted their Traitor decision.
} {g.battle?.revealed &&{truthQuestionText(question, leaderName, locationName, name)}
} > + ) : kind === 'mixedMovement' ? ( + <> +Current facts freeze when answered. Only future actual physical ground moves can fulfill movement conditions; smaller groups never add together. No negates the whole mixed question. Native entitlements, owned preparations and earlier obligations remain.
+ {!g.truthMixedMovementTargets.includes(target) &&Choose a supported unused movement opportunity and finish pending decisions. Optional modules remain unfinished.
} +{mixedMovementError ?? truthQuestionText(question, leaderName, locationName, name)}
+ > ) : kind === 'movementExpression' ? ( <>