Support concealed No-Field Planetologist gathering

This commit is contained in:
Quintine committed 2026-10-26 09:37:01 +11:00
1 parent f6e6671ac5
commit 90c50736f2
14 files changed
+817 -42

No files matched your search

+4 -6
View File
@@ -82,17 +82,15 @@ export function planetologistMoveDraft(
}
const marker = includeNoField ? planetologistNoFieldMarker(game) : null;
if (includeNoField) {
if (mode !== 'range')
return { action: null, blocked: 'A concealed No-Field can use extra range, but cannot join a Planetologist gather.' };
if (!marker)
return { action: null, blocked: 'Choose your current deployed No-Field.' };
if (game.homeworldMobility?.noFieldMovementBlocked)
return { action: null, blocked: game.homeworldMobility.noFieldMovementBlocked };
if (selected.some(([from]) => splitLocation(from).territory !== marker.location.territory))
if (mode === 'range' && selected.some(([from]) => splitLocation(from).territory !== marker.location.territory))
return { action: null, blocked: 'The selected No-Field and physical forces must share one origin territory.' };
}
const origins = new Set(selected.map(([from]) => splitLocation(from).territory));
if (marker) origins.add(marker.location.territory);
const origins = new Set(marker ? [marker.location.territory] : []);
for (const [from] of selected) origins.add(splitLocation(from).territory);
if ((mode === 'range' && origins.size !== 1) || (mode === 'gather' && origins.size !== 2))
return {
action: null,
@@ -136,7 +134,7 @@ export function planetologistMoveDraft(
export function planetologistMovementBlocked(game: GameView, draft: Draft, unavailableReason?: string | null): string | null {
const me = game.players.find(player => player.id === game.me);
return unavailableReason ??
return unavailableReason ||
(!me || game.status !== 'playing' || game.phase !== 5 || game.active !== me.id
? 'Planetologist movement is available only during your movement turn.'
: game.ornithopter?.active
+9 -7
View File
@@ -91,11 +91,7 @@ function PlanetologistMovementDraft({
id={`${id}-mode`}
value={mode}
disabled={busy}
onChange={(event) => {
const nextMode = event.target.value as PlanetologistMoveMode;
setMode(nextMode);
if (nextMode !== 'range') setIncludeNoField(false);
}}
onChange={(event) => setMode(event.target.value as PlanetologistMoveMode)}
>
<option value="range">One territory farther, maximum three</option>
<option value="gather">Gather from two territories</option>
@@ -111,7 +107,7 @@ function PlanetologistMovementDraft({
id={`${id}-no-field`}
type="checkbox"
checked={includeNoField}
disabled={busy || mode !== 'range' || !!game.homeworldMobility?.noFieldMovementBlocked}
disabled={busy || !!game.homeworldMobility?.noFieldMovementBlocked}
onChange={(event) => setIncludeNoField(event.target.checked)}
/>
Include your concealed No-Field from {territory(marker.location.territory).name}, sector {marker.location.sector}
@@ -122,6 +118,12 @@ function PlanetologistMovementDraft({
Move it alone or with physical forces from its own territory; its
value stays concealed. No direct joint FAQ settles this combination.
</p>
<p className="fine" aria-label="Provisional Planetologist No-Field gather">
Provisional gather composition: the concealed marker supplies one of
exactly two origin territories, alone or with physical forces there.
Select physical forces from one other territory. Every origin uses
its normal range; gather adds no extra range. Its value stays concealed.
</p>
{game.homeworldMobility?.noFieldMovementBlocked && (
<p className="notice">{game.homeworldMobility.noFieldMovementBlocked}</p>
)}
@@ -203,7 +205,7 @@ function PlanetologistMovementDraft({
busy={busy} unavailableReason={unavailableReason} reasonId={`${id}-reason`} act={act}
/>
<p className="fine">
Concealed No-Fields cannot join gather, either Ornithopter card movement
Concealed No-Fields cannot join either Ornithopter card movement
or Discovery flight.
Normal movement and arrival rules still apply.
</p>