79 lines
2.5 KiB
TypeScript
79 lines
2.5 KiB
TypeScript
import type { Game } from './engine';
|
|
import { location } from './board';
|
|
import { validAmbassadorResume } from './ambassador-resume';
|
|
import { currentHomeworldRevivalArrival, validateHomeworldRevivalReturn } from './homeworld-revival-return';
|
|
import { validateHomeworldVictoryReturn } from './homeworld-victory-return';
|
|
import {
|
|
validateHomeworldArrival,
|
|
type HomeworldArrivalFrame,
|
|
type HomeworldArrivalTag,
|
|
} from './homeworld-arrival';
|
|
|
|
export type AmbassadorPhaseContext = Pick<
|
|
Game,
|
|
| 'turn'
|
|
| 'phase'
|
|
| 'players'
|
|
| 'homeworlds'
|
|
| 'homeworldRevivalReturn'
|
|
| 'homeworldRevivalProgress'
|
|
| 'homeworldVictoryReinforcement'
|
|
| 'lastBattleContext'
|
|
| 'pendingAmbassador'
|
|
>;
|
|
|
|
/** Extra phases belong only to the recorded arrival and its actual BG arrivals. */
|
|
export function ambassadorPhaseAllowed(g: AmbassadorPhaseContext): boolean {
|
|
const entry = g.pendingAmbassador;
|
|
const candidates: {
|
|
tag: HomeworldArrivalTag;
|
|
frame: HomeworldArrivalFrame | undefined;
|
|
}[] = [
|
|
{ tag: 'revivalEvent', frame: currentHomeworldRevivalArrival(g.homeworldRevivalReturn) ?? undefined },
|
|
{ tag: 'victoryEvent', frame: g.homeworldVictoryReinforcement },
|
|
];
|
|
const matching = candidates.filter(
|
|
({ tag, frame }) =>
|
|
entry &&
|
|
(entry[tag] !== undefined ||
|
|
(Array.isArray(frame?.ambassadors) &&
|
|
frame.ambassadors.some((record) => record?.event === entry.event))),
|
|
);
|
|
if (!matching.length) return g.phase === 1 || g.phase === 5;
|
|
if (matching.length !== 1) return false;
|
|
const { tag, frame } = matching[0];
|
|
if (
|
|
!entry ||
|
|
!frame ||
|
|
entry[tag] !== frame.event ||
|
|
frame.stage !== 'arrival' ||
|
|
frame.turn !== g.turn ||
|
|
frame.phase !== g.phase ||
|
|
entry.turn !== g.turn ||
|
|
entry.phase !== g.phase ||
|
|
entry.resume !== 'none' ||
|
|
!validAmbassadorResume(g, entry)
|
|
)
|
|
return false;
|
|
try {
|
|
if (tag === 'revivalEvent')
|
|
validateHomeworldRevivalReturn(g, g.homeworldRevivalReturn);
|
|
else validateHomeworldVictoryReturn(g);
|
|
validateHomeworldArrival(g, frame, tag);
|
|
} catch {
|
|
return false;
|
|
}
|
|
const record = frame.ambassadors!.at(-1);
|
|
if (
|
|
!record ||
|
|
record.completed ||
|
|
record.event !== entry.event ||
|
|
record.entrant !== entry.entrant ||
|
|
record.destination !== location(entry.territory, entry.sector)
|
|
)
|
|
return false;
|
|
return record.parent === undefined
|
|
? entry.guildAdvisorOrigin === undefined
|
|
: entry.guildAdvisorOrigin?.event === record.parent;
|
|
}
|