45 lines
2.0 KiB
TypeScript
45 lines
2.0 KiB
TypeScript
import type { Game } from './engine';
|
|
import { homeworldContext } from './homeworld-game';
|
|
import { homeworldPopulations } from './homeworld-population';
|
|
|
|
type IxHomeworldContext = Pick<Game, 'advanced' | 'players' | 'homeworlds'>;
|
|
export type IxSuboidBonusInput = {
|
|
enabled: boolean;
|
|
amount: number;
|
|
elite: number;
|
|
free: number;
|
|
freeElite: number;
|
|
normalTanks: number;
|
|
};
|
|
|
|
export class IxHomeworldRevivalError extends Error {
|
|
constructor(message: string) {
|
|
super(message);
|
|
this.name = 'IxHomeworldRevivalError';
|
|
}
|
|
}
|
|
|
|
/** Printed native High benefit in either rules band. Actual revival timing,
|
|
* cost and eligibility belong to the original revival quote. */
|
|
export function ixHomeworldRevivalEnabled(context: IxHomeworldContext, playerId: string): boolean {
|
|
if (!context.homeworlds?.custody ||
|
|
!context.players.some(player => player.id === playerId && player.faction === 'ixians')) return false;
|
|
return homeworldPopulations(homeworldContext(context), context.homeworlds.custody)
|
|
.some(home => home.native === playerId && home.card === 'ix' && home.side === 'high');
|
|
}
|
|
|
|
const count = (value: unknown): value is number => Number.isSafeInteger(value) && (value as number) >= 0;
|
|
|
|
/** Additional physical Suboids for paid Cyborgs, after reserving every ordinary
|
|
* Suboid in the declared group. A shortage reduces only this bonus. */
|
|
export function quoteIxSuboidBonus(input: IxSuboidBonusInput): number {
|
|
const { enabled, amount, elite, free, freeElite, normalTanks } = input;
|
|
if (typeof enabled !== 'boolean' ||
|
|
![amount, elite, free, freeElite, normalTanks].every(count) ||
|
|
amount < 1 || amount > 20 || elite > amount || free > amount ||
|
|
freeElite > elite || freeElite > free || free - freeElite > amount - elite ||
|
|
normalTanks < amount - elite)
|
|
throw new IxHomeworldRevivalError('Choose valid physical revival counts, free counter types and available Suboids.');
|
|
return enabled ? Math.min(2 * (elite - freeElite), normalTanks - (amount - elite)) : 0;
|
|
}
|