Implement mixed Planetologist advisor gather continuation
This commit is contained in:
1 parent
bc37cd38fe
commit
c265f0638e
16 files changed
+512
-171
No files matched your search
@@ -1,8 +1,47 @@
|
||||
import { FACTIONS } from './catalog';
|
||||
import { nativeExpansionLeaderSkillsProfile } from './leader-skill-profile';
|
||||
import type { Game, GameView } from './engine';
|
||||
import type { Game, GameView, Player } from './engine';
|
||||
import { splitLocation } from './board';
|
||||
import { isAdvisor } from './advisors';
|
||||
import { presenceAt, type ForcePresence } from './force-presence';
|
||||
|
||||
type MovementPlayer = Pick<Player, 'id' | 'faction' | 'advisors'> & ForcePresence & {
|
||||
moved?: number;
|
||||
advisorFlipMovementBlocked?: boolean | { turn: number; move: number };
|
||||
};
|
||||
type MovementGame = Pick<Game, 'advanced' | 'turn'> & {
|
||||
players: readonly (Pick<Player, 'id'> & ForcePresence)[];
|
||||
};
|
||||
type AdvisorGatherEntry = Readonly<{ requiresFlip: boolean; blocked: string | null }>;
|
||||
const noAdvisorGather: AdvisorGatherEntry = { requiresFlip: false, blocked: null };
|
||||
const fighterAdvisorGather: AdvisorGatherEntry = { requiresFlip: true, blocked: null };
|
||||
const freshAdvisorGather: AdvisorGatherEntry = {
|
||||
requiresFlip: true, blocked: 'Fresh spiritual advisors cannot become fighters during this turn.',
|
||||
};
|
||||
const canceledAdvisorGather: AdvisorGatherEntry = {
|
||||
requiresFlip: true, blocked: 'Advisor flipping was canceled for this movement. Choose a legal replacement without flipping advisors.',
|
||||
};
|
||||
|
||||
/** The canceled native flip stays unavailable for this movement opportunity. */
|
||||
export function advisorFlipMovementBlocked(game: Pick<Game, 'turn'>, player: MovementPlayer): boolean {
|
||||
const blocked = player.advisorFlipMovementBlocked;
|
||||
return typeof blocked === 'boolean' ? blocked :
|
||||
blocked?.turn === game.turn && blocked.move === player.moved;
|
||||
}
|
||||
|
||||
/** Provisional simultaneous gather: declare one common fighter arrival before
|
||||
* either source moves; native cancellation keeps both original groups in place. */
|
||||
export function planetologistGatherAdvisorEntry(game: MovementGame, player: MovementPlayer,
|
||||
origins: readonly string[], destination: string): AdvisorGatherEntry {
|
||||
if (!game.advanced || player.faction !== 'beneGesserit' || origins.length !== 2 ||
|
||||
isAdvisor(player, origins[0]) === isAdvisor(player, origins[1]) ||
|
||||
presenceAt(player, destination) ||
|
||||
!game.players.some(other => other.id !== player.id && presenceAt(other, destination)))
|
||||
return noAdvisorGather;
|
||||
if (origins.some(origin => player.advisors?.[origin]?.lockedTurn === game.turn))
|
||||
return freshAdvisorGather;
|
||||
return advisorFlipMovementBlocked(game, player) ? canceledAdvisorGather : fighterAdvisorGather;
|
||||
}
|
||||
export type PlanetologistMoveMode = 'range' | 'gather';
|
||||
export type PlanetologistMovement = {
|
||||
leader: string;
|
||||
|
||||
Reference in new issue
Block a user