From 26d45ecf2549743b0ca543f4d109bddc21f505e5 Mon Sep 17 00:00:00 2001 From: Quintine <15965533+Quintine@users.noreply.github.com> Date: Thu, 29 Oct 2026 20:09:52 +1100 Subject: [PATCH] Allow fresh Advanced native No-Field placement --- components/homeworld-shipment.tsx | 14 ++-- docs/CURRENT_STATUS.md | 9 +++ docs/RICHESE_NO_FIELD_RULES.md | 22 +++++- docs/RULE_DECISIONS.md | 8 +++ game/homeworld-shipment-options.ts | 7 ++ game/reference.ts | 10 +-- game/richese-homeworld-marker-shipment.ts | 6 +- tests/fixture-richese-native-marker.ts | 31 ++++++++ tests/native-world-no-field-controls.test.tsx | 27 ++++++- tests/native-world-no-field-helpers.test.ts | 11 ++- ...richese-homeworld-marker-controls.test.tsx | 3 +- .../richese-homeworld-marker-shipment.test.ts | 4 +- tests/richese-native-marker-runtime.test.ts | 70 +++++++++++++++++++ 13 files changed, 201 insertions(+), 21 deletions(-) create mode 100644 tests/fixture-richese-native-marker.ts create mode 100644 tests/richese-native-marker-runtime.test.ts diff --git a/components/homeworld-shipment.tsx b/components/homeworld-shipment.tsx index e9e5d02f..9566e339 100644 --- a/components/homeworld-shipment.tsx +++ b/components/homeworld-shipment.tsx @@ -26,7 +26,7 @@ export function HomeworldNoFieldShipment({ game, act, busy }: { 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 || !!source && game.advanced) && + (world.native !== me.id || game.advanced) && world.native !== me.ally && world.id !== source); const destination = targets.find(world => world.id === selectedDestination) ?? targets.find(world => world.native !== me.id) ?? targets[0]; @@ -34,19 +34,20 @@ export function HomeworldNoFieldShipment({ game, act, busy }: { const token = tokens.find(candidate => candidate.id === selectedToken) ?? tokens[0]; const pool = source ? game.homeworlds?.worlds?.find(world => world.id === source)?.forces[me.id] : { normal: me.reserves - (me.elites?.reserves ?? 0), elite: me.elites?.reserves ?? 0 }; + const nativeFresh = !source && destination?.native === me.id; const quote = richeseHomeworldMarkerChoice(game, destination?.id ?? '', token?.id ?? '', allyPayment, source, - forces); + nativeFresh ? { normal: 0, elite: 0 } : forces); return
Ship a concealed No-Field

Provisional Homeworld rule: ship one concealed marker {source ? `from ${homeworldName(game, source)}` : 'from your supply'} to - another non-allied Homeworld. Its value stays private and its represented forces + an eligible non-allied Homeworld. Its value stays private and its represented forces remain in your reserves until the marker is revealed. On your own Homeworld, the represented forces are already in those reserves and are not added again. - This uses your normal shipment. Physical forces from the same source may accompany it.

+ This uses your normal shipment. Physical forces from the same source may accompany it when moving to another World.

- {pool &&
+ {nativeFresh &&

Your physical reserves are already on Richese and cannot accompany this placement.

} + {pool && !nativeFresh &&
Accompanying forces from {source ? homeworldName(game, source) : 'your reserves'} {(['normal', 'elite'] as const).filter(kind => kind === 'normal' || pool.elite > 0).map(kind =>