Prototype Richese No-Fields on foreign Homeworlds

This commit is contained in:
Quintine committed 2026-10-28 20:04:03 +11:00
1 parent dd3c199e2e
commit 850227c26d
71 files changed
+1806 -187

No files matched your search

+11 -2
View File
@@ -3,6 +3,7 @@ import type { FactionId } from './catalog';
import { specialForceName } from './combat';
import { isAdvisor } from './advisors';
import { HOMEWORLD_CARDS } from './homeworld-cards';
import { isBoardNoFieldLocation, type NoFieldLocation } from './richese-no-field';
/** Public physical custody only. No private cards, commitments or token faces. */
export type PublicForcePlayer = {
@@ -14,7 +15,7 @@ export type PublicForcePlayer = {
forces: Readonly<Record<string, number>>;
elites?: { reserves: number; tanks: number; forces: Readonly<Record<string, number>> };
advisors?: Record<string, { lockedTurn?: number }>;
noField?: { deployed: { location: { territory: string; sector: number } } | null } | null;
noField?: { deployed: { location: NoFieldLocation } | null } | null;
};
export type PublicForceWorld = {
id: string;
@@ -43,6 +44,14 @@ function locationName(id: string, sector: number) {
return sector > 0 ? `${name} · sector ${sector}` : name;
}
function markerLocationName(marker: NoFieldLocation) {
if (isBoardNoFieldLocation(marker)) return locationName(marker.territory, marker.sector);
const card = HOMEWORLD_CARDS.find(candidate => marker.homeworld ===
`homeworld:${candidate.faction}${candidate.id === 'salusa_secundus' ? ':salusa' : ''}`);
if (!card) throw new Error('Unknown No-Field Homeworld.');
return card.name;
}
function pool(id: string, name: string, total: number, elite = 0, advisors = false): ForcePool {
if (![total, elite].every(n => Number.isSafeInteger(n) && n >= 0) || elite > total)
throw new Error('Invalid public force count.');
@@ -86,7 +95,7 @@ export function forceInventory(player: PublicForcePlayer, worlds: readonly Publi
elite: rows.reduce((n, r) => n + r.elite, 0),
advisors: rows.reduce((n, r) => n + (r.advisors ? r.total : 0), 0),
split: !!player.elites,
marker: marker ? { name: locationName(marker.territory, marker.sector) } : null,
marker: marker ? { name: markerLocationName(marker) } : null,
};
} catch {
return null;