Preflight worm-ride arrivals for bot candidates

This commit is contained in:
Quintine committed 2026-09-29 23:12:23 +10:00
1 parent 3d95db88cc
commit 583cd97a25
6 files changed
+108 -2

No files matched your search

+34
View File
@@ -224,3 +224,37 @@ export function botArrivalBlock(g: GameView, action: Action): string | null {
throw error;
}
}
/** The worm decision itself is replaced before entry reactions; only a new
* intrusion or another pending control conflicts with the destination.
* Homeworld riders retain their separate unsupported-combination policy.
*/
export function botWormRideArrivalBlock(g: GameView, to: string, sector: number): string | null {
const ride = g.decision;
if (g.status !== 'playing' || g.phase !== 1 || ride?.kind !== 'wormRide' ||
ride.player !== g.me || g.homeworlds || !validLocation(to, sector))
return null;
try {
quoteCompletedMovementArrival({
advanced: g.advanced,
overlapSupported: g.arrivalOverlapMode === true,
players: g.players,
order: { player: g.me, origin: ride.territory, to,
advisors: false, wantsFighters: false },
ambassadors: (g.ambassadors?.tokens ?? []).map(
({ zone, location, effect }) => ({ zone, location, effect })),
terror: (g.moritaniTerror?.tokens ?? []).map(
({ status, location }) => ({ status, location })),
controls: {
response: !!g.response, decision: false,
pendingTerror: !!g.terrorEntry, pendingAmbassador: !!g.ambassadorEntry,
paidBox: false,
},
flight: null,
});
return null;
} catch (error) {
if (error instanceof MovementArrivalError) return error.message;
throw error;
}
}
+3 -2
View File
@@ -100,7 +100,7 @@ import { sandmasterDefaultChoice } from './sandmaster-movement';
import { sandmasterWormCollection } from './sandmaster-worm';
import { richeseCardDefinition } from './richese-cards';
import { presenceAt } from './force-presence';
import { botArrivalBlock } from './bot-arrival';
import { botArrivalBlock, botWormRideArrivalBlock } from './bot-arrival';
import { validateCohortSelection, type OrnithopterMode } from './ornithopter';
import { fighterCount, isAdvisor } from './advisors';
import { casualtyOptions, maxCombatDial, maxCombatSupport, type CombatForces } from './combat';
@@ -2667,7 +2667,8 @@ function policyActions(g: GameView): Action[] {
...destinations(g)
.filter(
(to) =>
to.t !== d.territory && botEntryAllowed(g, me, to.t, to.s, 'move'),
to.t !== d.territory && botEntryAllowed(g, me, to.t, to.s, 'move') &&
!botWormRideArrivalBlock(g, to.t, to.s),
)
.slice(0, 16)
.map(