diff --git a/components/shipment-claim-fields.tsx b/components/shipment-claim-fields.tsx index e8bcbb9f..a72f9f63 100644 --- a/components/shipment-claim-fields.tsx +++ b/components/shipment-claim-fields.tsx @@ -2,9 +2,11 @@ import { TERRITORIES } from '@/game/board'; import { Input } from '@/components/ui/input'; -export type ShipmentClauseInput = { territory: string; minimum: number }; +export type ShipmentClauseInput = { territory: string; minimum: number; sector?: number }; export function invalidShipmentClause(claim: ShipmentClauseInput) { - return !Number.isSafeInteger(claim.minimum) || claim.minimum < 1 || claim.minimum > 20; + return !Number.isSafeInteger(claim.minimum) || claim.minimum < 1 || claim.minimum > 20 || + claim.sector !== undefined && (!Number.isSafeInteger(claim.sector) || + !TERRITORIES.find(destination => destination.id === claim.territory)?.sectors.includes(claim.sector)); } /** Destination and physical minimum shared by flat and nested question builders. */ @@ -13,12 +15,36 @@ export function ShipmentClauseFields({ id, value, onChange }: { value: ShipmentClauseInput; onChange: (claim: ShipmentClauseInput) => void; }) { + const printed = TERRITORIES.find(destination => destination.id === value.territory); + // Mixed-shipment leaves have their own `kind` and remain on their existing + // territory-only parser until that separate question family is integrated. + const allowSector = !('kind' in value); return <> + {allowSector && <> + + + } = { actionLabel: 'shipment or ground-movement condition', actionTiming: 'Future shipment or ground move · this turn', actionHelp: <>Shipment conditions concern your single future original reserve shipment after the answer. + Choose any sector or one exact printed sector in that territory; only that sector satisfies an exact condition. Ground-movement conditions concern one actual future ground move before your Movement turn ends this round. Count physical forces in one action; smaller moves never add together. Earlier actions do not count. OR keeps legal shipment and movement alternatives available. No makes the whole expression false. @@ -28,7 +29,8 @@ const config: MixedActionConfig = { destination.id === value.territory) ? value.territory : ''} disabled={disabled} aria-invalid={!TERRITORIES.some(destination => destination.id === value.territory)} - onChange={event => onChange({ ...value, territory: event.currentTarget.value })}> + onChange={event => { + const destination = event.currentTarget.value; + if (value.kind === 'ship') onChange({ kind: 'ship', territory: destination, minimum: value.minimum }); + else onChange({ ...value, territory: destination }); + }}> {TERRITORIES.map(destination => )} + {value.kind === 'ship' && (() => { + const printed = TERRITORIES.find(destination => destination.id === value.territory); + return <> + + + ; + })()} = { Amal conditions count an actual accepted future printed play in this original phase opening. Earlier plays, disposal, other roles and recovery alone do not count. The condition closes with this opening. Amal halves available cash before ordinary payments become legal; preserve enough remaining cash for any payment condition. - Shipment conditions concern the single future original reserve shipment after the answer. + Shipment conditions concern the single future original reserve shipment after the answer. Choose any sector or one exact printed sector; + a different sector in the same territory does not satisfy an exact-sector condition. Ground-movement conditions use the maximum physical forces in one actual future move to that destination; smaller moves never add together. Bid conditions close with their named ordinary lot; Revival conditions close with your native Revival opportunity. Shipment and movement close at your own Movement turn end, while payment conditions last until the actual turn ends. @@ -429,10 +430,34 @@ const config: MixedActionConfig = { + {value.kind === 'ship' && (() => { + const printed = TERRITORIES.find(destination => destination.id === value.territory); + return <> + + + ; + })()} } {'minimum' in value && <>