From 1f03ae673b832a68d8829b0723de1ae121a7c83e Mon Sep 17 00:00:00 2001 From: Quintine <15965533+Quintine@users.noreply.github.com> Date: Wed, 28 Oct 2026 20:13:31 +1100 Subject: [PATCH] Support concealed Homeworld transfers and Ecaz victory --- components/homeworld-shipment.tsx | 10 +- docs/CURRENT_STATUS.md | 12 ++ docs/RICHESE_NO_FIELD_RULES.md | 28 +++- docs/RULE_DECISIONS.md | 10 +- game/ecaz-homeworld-victory.ts | 35 ++-- game/engine.ts | 35 ++-- game/homeworld-shipment-options.ts | 22 ++- game/reference.ts | 2 +- game/richese-homeworld-marker-shipment.ts | 42 ++++- tests/ecaz-homeworld-marker-victory.test.ts | 91 ++++++++++ ...omeworld-marker-transfer-controls.test.tsx | 115 +++++++++++++ ...ese-homeworld-marker-transfer-http.test.ts | 143 ++++++++++++++++ ...se-homeworld-marker-transfer-quote.test.ts | 52 ++++++ ...-homeworld-marker-transfer-runtime.test.ts | 158 ++++++++++++++++++ 14 files changed, 712 insertions(+), 43 deletions(-) create mode 100644 tests/ecaz-homeworld-marker-victory.test.ts create mode 100644 tests/richese-homeworld-marker-transfer-controls.test.tsx create mode 100644 tests/richese-homeworld-marker-transfer-http.test.ts create mode 100644 tests/richese-homeworld-marker-transfer-quote.test.ts create mode 100644 tests/richese-homeworld-marker-transfer-runtime.test.ts diff --git a/components/homeworld-shipment.tsx b/components/homeworld-shipment.tsx index b84fc317..7238edc0 100644 --- a/components/homeworld-shipment.tsx +++ b/components/homeworld-shipment.tsx @@ -23,16 +23,18 @@ export function HomeworldNoFieldShipment({ game, act, busy }: { const [selectedToken, setSelectedToken] = useState(''); const [allyPayment, setAllyPayment] = useState(0); if (!me || me.faction !== 'richese' || info?.owner !== me.id || !info.private) return null; + const deployed = info.private.deployed; + const source = deployed && 'homeworld' in deployed.location ? deployed.location.homeworld : undefined; const targets = (game.homeworlds?.worlds ?? []).filter(world => - world.native !== me.id && world.native !== me.ally); + world.native !== me.id && world.native !== me.ally && world.id !== source); const destination = targets.find(world => world.id === selectedDestination) ?? targets[0]; - const tokens = info.private.tokens.filter(token => token.id !== info.private!.lastShipped); + const tokens = info.private.tokens.filter(token => source ? token.id === deployed?.tokenId : token.id !== info.private!.lastShipped); const token = tokens.find(candidate => candidate.id === selectedToken) ?? tokens[0]; - const quote = richeseHomeworldMarkerChoice(game, destination?.id ?? '', token?.id ?? '', allyPayment); + const quote = richeseHomeworldMarkerChoice(game, destination?.id ?? '', token?.id ?? '', allyPayment, source); return
Ship a concealed No-Field -

Provisional Homeworld rule: ship one concealed marker from your supply to +

Provisional Homeworld rule: ship one concealed marker {source ? `from ${homeworldName(game, source)}` : 'from your supply'} to another non-allied Homeworld for one spice. Its value stays private and its physical forces remain in your reserves until the marker is revealed. This uses your normal shipment.