Integrate native Ixian CHOAM and Tleilaxu Occupy aftermath

This commit is contained in:
Quintine committed 2026-10-02 14:47:54 +10:00
1 parent 3333432be8
commit 1057eb2719
17 files changed
+934 -89

No files matched your search

+29 -11
View File
@@ -158,13 +158,24 @@ const ECAZ_TREACHERY_SCENARIOS: readonly Scenario[] = EXPANSION_ROSTER_SCENARIOS
...scenario, profile: 'ecaz-treachery', ordinal: scenario.ordinal + 58,
}));
/** Ordinary Advanced Ecaz Occupy, without the independent three-card variant. */
const ECAZ_OCCUPY_SCENARIOS: readonly Scenario[] = [2, 3, 4, 5, 6].map(players => ({
ordinal: 169 + players - 2,
profile: 'ecaz-occupy',
rules: 'advanced',
expansions: ['ecaz'],
roster: (['ecaz', 'fremen', 'emperor', 'beneGesserit', 'harkonnen', 'guild'] as FactionId[]).slice(0, players),
}));
const ECAZ_OCCUPY_SCENARIOS: readonly Scenario[] = [
...[2, 3, 4, 5, 6].map((players): Scenario => ({
ordinal: 169 + players - 2, profile: 'ecaz-occupy', rules: 'advanced',
expansions: ['ecaz'],
roster: (['ecaz', 'fremen', 'emperor', 'beneGesserit', 'harkonnen', 'guild'] as FactionId[]).slice(0, players),
})),
...(['ixians', 'tleilaxu', 'choam'] as const).flatMap((native, family) =>
[2, 3, 4, 5, 6].map((players): Scenario => ({
ordinal: 174 + family * 5 + players - 2, profile: 'ecaz-occupy', rules: 'advanced',
expansions: ['ecaz', native === 'choam' ? 'choam' : 'ix'],
roster: (['ecaz', native, 'guild', 'fremen', 'emperor', 'beneGesserit'] as FactionId[]).slice(0, players),
}))),
...[4, 5, 6].map((players): Scenario => ({
ordinal: 189 + players - 4, profile: 'ecaz-occupy', rules: 'advanced',
expansions: ['ecaz', 'ix', 'choam'],
roster: (['ecaz', 'ixians', 'tleilaxu', 'choam', 'guild', 'fremen'] as FactionId[]).slice(0, players),
})),
];
const PAIRED_NEXUS_SCENARIOS: readonly Scenario[] = EXPANSION_ROSTER_SCENARIOS
.map(scenario => ({
...scenario,
@@ -303,7 +314,7 @@ function usage() {
'[--rules both|basic|advanced] [--players all|2|3|4|5|6] [--max-actions POSITIVE] ' +
'[--resume FAILED_GAME.json]\n' +
'Runs genuine setup and gameplay offline. Default/all keeps the six expansion samples; combined-nexus and combined-homeworld-nexus add five/six-seat Basic/Advanced all-expansion samples. Base, Homeworld, Nexus, Homeworld-Nexus, expansion roster, paired expansion Nexus, Ecaz card variant, Advanced Moritani assassination and skill profiles select their documented rosters. Stronghold-factions is Advanced only: Ixians + CHOAM, native Ixians + Tleilaxu, or native CHOAM + Richese with classic opponents, two through six seats; mixed four-native rosters also run at four through six seats. Selected Ix/CHOAM decks determine the canonical 47/35 Treachery Cards; Richese has a separate ten-card cache and all samples have six separate Stronghold Cards without other modules. Scenario names identify their native roster. --players requires a supported profile. Output must be a new private directory outside the checkout.' +
'\nEcaz-occupy is Advanced only: two through six seats, native Ecaz and classic opponents, 33 ordinary Treachery Cards and the E3 faction source. No three-card variant or optional overlays.'
'\nEcaz-occupy is Advanced only: native Ecaz plus classic/Ixian/Tleilaxu/CHOAM paired or mixed rosters, two through six seats; selected E3/E1/E2 sources determine ordinary33/47/35 cards. No Richese mixed planning, independent three-card variant or optional overlays.'
);
}
@@ -339,6 +350,10 @@ function scenarioName(scenario: Scenario) {
['ixians', 'tleilaxu', 'choam', 'richese'].includes(faction));
return `${scenario.profile}-${native.join('-')}-${scenario.roster.length}-${scenario.rules}`;
}
if (scenario.profile === 'ecaz-occupy') {
const native = scenario.roster.filter(faction => ['ixians', 'tleilaxu', 'choam'].includes(faction));
if (native.length) return `${scenario.profile}-${native.join('-')}-${scenario.roster.length}-${scenario.rules}`;
}
return scenario.profile === 'base' || scenario.profile === 'homeworld' || scenario.profile === 'nexus' || scenario.profile === 'homeworld-nexus' || scenario.profile === 'combined-nexus' || scenario.profile === 'combined-homeworld-nexus' ||
scenario.profile === 'choam-roster' || scenario.profile === 'ecaz-roster' || scenario.profile === 'ecaz-treachery' || scenario.profile === 'ecaz-occupy' || scenario.profile === 'moritani-assassinate' || scenario.profile === 'ix-roster' || scenario.profile === 'choam-nexus' || scenario.profile === 'ecaz-nexus' || scenario.profile === 'ix-nexus' || skillProfile(scenario.profile)
? `${scenario.profile}-${scenario.roster.length}-${scenario.rules}`
@@ -811,9 +826,12 @@ async function main() {
} : {}),
...(selected.some(scenario => scenario.profile === 'ecaz-occupy') ? {
ecazOccupy: {
treacheryCards: 33,
factionSource: 'E3',
scope: 'Advanced native Ecaz and classic opponents, two through six seats. Ordinary deck only; no independent Ecaz three-card variant or optional overlays. Authorized revised rulebook Advanced ceil contribution/floor survivors; not a designer erratum or Basic ruling.',
families: selected.filter(scenario => scenario.profile === 'ecaz-occupy').map(scenario => ({
roster: scenario.roster,
expansions: scenario.expansions,
treacheryCards: scenario.expansions.includes('ix') ? 47 : scenario.expansions.includes('choam') ? 35 : 33,
})),
scope: 'Advanced native Ecaz/classic/Ixian/Tleilaxu/CHOAM paired or mixed families, two through six seats. Selected E3/E1/E2 ordinary decks only; no Richese mixed planning, independent Ecaz three-card variant or optional overlays. Authorized revised Advanced ceil contribution/floor survivors; not a designer erratum or Basic ruling.',
},
} : {}),
options: {