Compose original mixed and paired Nexus optional modules
This commit is contained in:
1 parent
0e1797d4e0
commit
05ab2c92b0
30 files changed
+2268
-203
No files matched your search
@@ -1,4 +1,4 @@
|
||||
import { homeworldLeaderSkillsProfile, classicNexusLeaderSkillsProfile, classicTechLeaderSkillsProfile, nativeDiscoveryLeaderSkillsProfile, nativeExpansionLeaderSkillsProfile, nativeTechLeaderSkillsProfile, noOtherLeaderSkillModules, standaloneE3NexusLeaderSkillsProfile, strongholdLeaderSkillsProfile, type LeaderSkillProfile } from './leader-skill-profile';
|
||||
import { homeworldLeaderSkillsProfile, classicNexusLeaderSkillsProfile, classicTechLeaderSkillsProfile, mixedE1E2NexusLeaderSkillsProfile, nativeDiscoveryLeaderSkillsProfile, nativeExpansionLeaderSkillsProfile, nativeTechLeaderSkillsProfile, noOtherLeaderSkillModules, pairedE3NexusLeaderSkillsProfile, standaloneE3NexusLeaderSkillsProfile, strongholdLeaderSkillsProfile, type LeaderSkillProfile } from './leader-skill-profile';
|
||||
import { classicDiscoveryLeaderSkillsProfile } from './discovery-module-profile';
|
||||
export type BureaucratPaymentKind = 'auction' | 'shipment' | 'bribe' | 'revival';
|
||||
export type BureaucratPaymentSource = {
|
||||
@@ -36,7 +36,8 @@ export function bureaucratPaymentSignature(value: object): string {
|
||||
return JSON.stringify({ ...value, signature: undefined });
|
||||
}
|
||||
export function bureaucratPaymentModeSupported(game: LeaderSkillProfile): boolean {
|
||||
return (noOtherLeaderSkillModules(game) &&
|
||||
return mixedE1E2NexusLeaderSkillsProfile(game) || pairedE3NexusLeaderSkillsProfile(game) ||
|
||||
(noOtherLeaderSkillModules(game) &&
|
||||
(!game.expansions.length ||
|
||||
(game.expansions.length === 1 && game.expansions[0] === 'choam') ||
|
||||
nativeExpansionLeaderSkillsProfile(game))) || homeworldLeaderSkillsProfile(game) || classicTechLeaderSkillsProfile(game) || nativeTechLeaderSkillsProfile(game) || strongholdLeaderSkillsProfile(game) || classicNexusLeaderSkillsProfile(game) || standaloneE3NexusLeaderSkillsProfile(game) || classicDiscoveryLeaderSkillsProfile(game) || nativeDiscoveryLeaderSkillsProfile(game);
|
||||
|
||||
@@ -16,7 +16,8 @@ export function homeworldDiscoveryProfile(game: FactionModuleProfile): boolean {
|
||||
|
||||
/** The same roster/module contract during play; live Discovery frames are expected. */
|
||||
export function discoveryModeSupported(game: FactionModuleProfile): boolean {
|
||||
if (game.nexusCards) return standaloneE3DiscoveryNexusProfile(game) || singleE1E2DiscoveryNexusProfile(game);
|
||||
if (game.nexusCards) return standaloneE3DiscoveryNexusProfile(game) || singleE1E2DiscoveryNexusProfile(game) ||
|
||||
mixedE1E2DiscoveryNexusProfile(game) || pairedE3DiscoveryNexusProfile(game);
|
||||
if (typeof game.advanced !== 'boolean' || game.discoveryEnabled !== true ||
|
||||
game.players.length < 2 || game.players.length > 6 ||
|
||||
(game.techTokens && game.players.length < 3) || game.expansions.length > 2 ||
|
||||
@@ -181,3 +182,57 @@ export function singleE1E2DiscoveryNexusProfile(game: FactionModuleProfile): boo
|
||||
}
|
||||
return native === 1;
|
||||
}
|
||||
|
||||
/** Original natives from both selected E1/E2 families with Nexus/Discovery and no Skills. */
|
||||
export function mixedE1E2DiscoveryNexusProfile(game: FactionModuleProfile): boolean {
|
||||
if (typeof game.advanced !== 'boolean' || game.discoveryEnabled !== true ||
|
||||
!game.nexusCards || game.expansions.length !== 2 ||
|
||||
!game.expansions.includes('ix') || !game.expansions.includes('choam') ||
|
||||
game.players.length < 2 || game.players.length > 6 ||
|
||||
(game.techTokens && game.players.length < 3) ||
|
||||
(game.strongholdCards && !game.advanced) || game.leaderSkills ||
|
||||
game.ecazTreachery || game.semutaPreview || game.advancedPreview || game.kullPreview ||
|
||||
game.nexusKullPreview || game.guildBetrayalPreview || game.richeseBetrayalPreview ||
|
||||
game.nexusIxianReplacementPreview || game.nexusIxianBetrayalPreview ||
|
||||
game.nexusHarkonnenBetrayalPreview) return false;
|
||||
let ix = false, choam = false;
|
||||
for (let i = 0; i < game.players.length; i++) {
|
||||
const player = game.players[i];
|
||||
for (let j = 0; j < i; j++) if (player.faction === game.players[j].faction) return false;
|
||||
let family: string | undefined;
|
||||
for (const faction of FACTIONS)
|
||||
if (faction.id === player.faction) { family = faction.expansion; break; }
|
||||
if (family !== 'base' && family !== 'ix' && family !== 'choam') return false;
|
||||
if (family === 'ix') ix = true;
|
||||
if (family === 'choam') choam = true;
|
||||
}
|
||||
return ix && choam;
|
||||
}
|
||||
|
||||
/** Both original E3 natives with Nexus/Discovery and no Skills; Advanced capture exclusion remains. */
|
||||
export function pairedE3DiscoveryNexusProfile(game: FactionModuleProfile): boolean {
|
||||
if (typeof game.advanced !== 'boolean' || game.discoveryEnabled !== true ||
|
||||
!game.nexusCards || game.expansions.length !== 1 || game.expansions[0] !== 'ecaz' ||
|
||||
game.players.length < 2 || game.players.length > 6 ||
|
||||
(game.techTokens && game.players.length < 3) ||
|
||||
(game.strongholdCards && !game.advanced) || game.leaderSkills ||
|
||||
game.ecazTreachery || game.semutaPreview || game.advancedPreview || game.kullPreview ||
|
||||
game.nexusKullPreview || game.guildBetrayalPreview || game.richeseBetrayalPreview ||
|
||||
game.nexusIxianReplacementPreview || game.nexusIxianBetrayalPreview ||
|
||||
game.nexusHarkonnenBetrayalPreview) return false;
|
||||
let ecaz = false, moritani = false;
|
||||
for (let i = 0; i < game.players.length; i++) {
|
||||
const player = game.players[i];
|
||||
for (let j = 0; j < i; j++) if (player.faction === game.players[j].faction) return false;
|
||||
if (player.faction === 'ecaz') ecaz = true;
|
||||
else if (player.faction === 'moritani') moritani = true;
|
||||
else {
|
||||
if (game.advanced && player.faction === 'harkonnen') return false;
|
||||
let classic = false;
|
||||
for (const faction of FACTIONS)
|
||||
if (faction.id === player.faction) { classic = faction.expansion === 'base'; break; }
|
||||
if (!classic) return false;
|
||||
}
|
||||
}
|
||||
return ecaz && moritani;
|
||||
}
|
||||
+42
-28
@@ -1,7 +1,7 @@
|
||||
import { classicNexusModulesProfile, pairedNexusModulesProfile, singleE1E2NexusProfile, standaloneE3NexusProfile } from './nexus-module-profile';
|
||||
import { classicNexusModulesProfile, mixedE1E2NexusProfile, pairedE3NexusProfile, pairedNexusModulesProfile, singleE1E2NexusProfile, standaloneE3NexusProfile } from './nexus-module-profile';
|
||||
import { nativeFactionTechProfile } from './faction-module-profile';
|
||||
import { classicDiscoveryLeaderSkillsProfile, classicDiscoveryNexusProfile, homeworldDiscoveryProfile, discoveryModeSupported, discoveryModuleProfile, pairedDiscoveryNexusProfile, singleE1E2DiscoveryNexusProfile, standaloneE3DiscoveryNexusProfile } from './discovery-module-profile';
|
||||
import { advancedMoritaniLeaderSkillsProfile, advancedNativeLeaderSkillsProfile, homeworldLeaderSkillsProfile, classicNexusLeaderSkillsProfile, classicTechLeaderSkillsProfile, nativeDiscoveryLeaderSkillsProfile, nativeExpansionLeaderSkillsProfile, nativeTechLeaderSkillsProfile, ordinaryLeaderSkillModeSupported, pairedNexusLeaderSkillsProfile, singleE1E2NexusLeaderSkillsProfile, standaloneE3NexusLeaderSkillsProfile, strongholdLeaderSkillsProfile } from './leader-skill-profile';
|
||||
import { classicDiscoveryLeaderSkillsProfile, classicDiscoveryNexusProfile, homeworldDiscoveryProfile, discoveryModeSupported, discoveryModuleProfile, mixedE1E2DiscoveryNexusProfile, pairedDiscoveryNexusProfile, pairedE3DiscoveryNexusProfile, singleE1E2DiscoveryNexusProfile, standaloneE3DiscoveryNexusProfile } from './discovery-module-profile';
|
||||
import { advancedMoritaniLeaderSkillsProfile, advancedNativeLeaderSkillsProfile, homeworldLeaderSkillsProfile, classicNexusLeaderSkillsProfile, classicTechLeaderSkillsProfile, mixedE1E2NexusLeaderSkillsProfile, nativeDiscoveryLeaderSkillsProfile, nativeExpansionLeaderSkillsProfile, nativeTechLeaderSkillsProfile, ordinaryLeaderSkillModeSupported, pairedE3NexusLeaderSkillsProfile, pairedNexusLeaderSkillsProfile, singleE1E2NexusLeaderSkillsProfile, standaloneE3NexusLeaderSkillsProfile, strongholdLeaderSkillsProfile } from './leader-skill-profile';
|
||||
import { bribeTimingBlock, maximumBribe, type BribeOptions } from './bribe-options';
|
||||
import { quoteSpicePlacement, stormExposesTerritory, stormSectorAfter, wormConsumesForces } from './disaster-rules';
|
||||
import { isStormCardDistance, type StormCardComponent } from './storm-cards';
|
||||
@@ -7612,7 +7612,7 @@ function e3StrongholdFactionProfile(g: Game): boolean {
|
||||
return native !== null && (native !== 'moritani' || !byFaction(g, 'harkonnen'));
|
||||
}
|
||||
function moritaniAssassinateModeSupported(g: Game) {
|
||||
if (standaloneE3NexusProfile(g))
|
||||
if (standaloneE3NexusProfile(g) || pairedE3NexusProfile(g) || pairedE3NexusLeaderSkillsProfile(g))
|
||||
return g.advanced && g.players.some(player => player.faction === 'moritani');
|
||||
if (g.discoveryEnabled || g.discoveries)
|
||||
return g.advanced && !!g.discoveries &&
|
||||
@@ -8568,24 +8568,24 @@ export function initializeHomeworldOccupationGameForAudit(state: Game): Game {
|
||||
if (byFaction(g, 'ecaz')) g.homeworldEcazVictoryPreview = true;
|
||||
return g;
|
||||
}
|
||||
/** Original classic or standalone E3 Nexus setup; public starts remain gated. */
|
||||
/** Original classic and supported native Nexus setup; public starts remain gated. */
|
||||
export function initializeNexusGameForAudit(state: Game): Game {
|
||||
requireRule(!!state.nexusCards && state.nexusCards.cards === null && state.nexusCards.phase === null,
|
||||
'Enable Nexus cards in a fresh audit lobby first.');
|
||||
const standalone = standaloneE3NexusProfile(state);
|
||||
const single = singleE1E2NexusProfile(state);
|
||||
const pairedE3 = pairedE3NexusProfile(state);
|
||||
const native = standalone || pairedE3 || singleE1E2NexusProfile(state) || mixedE1E2NexusProfile(state);
|
||||
const discovery = classicDiscoveryNexusProfile(state) || standaloneE3DiscoveryNexusProfile(state) ||
|
||||
singleE1E2DiscoveryNexusProfile(state) || mixedE1E2DiscoveryNexusProfile(state) || pairedE3DiscoveryNexusProfile(state);
|
||||
if (state.discoveryEnabled) {
|
||||
requireRule(classicDiscoveryNexusProfile(state) || standaloneE3DiscoveryNexusProfile(state) ||
|
||||
singleE1E2DiscoveryNexusProfile(state),
|
||||
'Discovery Nexus requires a fresh classic, single E1/E2 native or standalone E3 lobby with original optional modules.');
|
||||
requireRule(discovery,
|
||||
'Discovery Nexus requires a fresh supported original classic or native roster and module envelope.');
|
||||
requireFreshBaseRuntime(state);
|
||||
requireFreshFactionInventory(state);
|
||||
}
|
||||
const g = initializeSetupGameForAudit(state, !!state.homeworlds, true, false,
|
||||
classicDiscoveryNexusProfile(state) || standaloneE3DiscoveryNexusProfile(state) || singleE1E2DiscoveryNexusProfile(state),
|
||||
false, false, standalone || single);
|
||||
if (standalone && byFaction(g, 'ecaz')) g.ecazOccupyPreview = true;
|
||||
if (standalone && g.advanced && byFaction(g, 'moritani')) initializeMoritaniAssassinateState(g);
|
||||
const g = initializeSetupGameForAudit(state, !!state.homeworlds, true, false, discovery, false, false, native);
|
||||
if ((standalone || pairedE3) && byFaction(g, 'ecaz')) g.ecazOccupyPreview = true;
|
||||
if ((standalone || pairedE3) && g.advanced && byFaction(g, 'moritani')) initializeMoritaniAssassinateState(g);
|
||||
return g;
|
||||
}
|
||||
/** Fresh audit admission only; ordinary games and public starts never opt in. */
|
||||
@@ -9334,18 +9334,25 @@ export function initializePairedNexusGameForAudit(state: Game): Game {
|
||||
state.players.some(player => player.faction === 'ixians') &&
|
||||
state.players.some(player => player.faction === 'tleilaxu'))),
|
||||
'The paired Nexus sample requires both selected expansion factions and their deck.');
|
||||
const discovery = state.discoveryEnabled === true && pairedDiscoveryNexusProfile(state);
|
||||
const pairedE3 = expansion === 'ecaz' && pairedE3NexusProfile(state);
|
||||
requireRule(expansion !== 'ecaz' || pairedE3,
|
||||
'Paired E3 Nexus retains its original Advanced Harkonnen capture exclusion.');
|
||||
const discovery = state.discoveryEnabled === true &&
|
||||
(pairedDiscoveryNexusProfile(state) || pairedE3DiscoveryNexusProfile(state));
|
||||
requireRule(!!state.nexusCards && state.nexusCards.cards === null && state.nexusCards.phase === null &&
|
||||
(!state.homeworlds || expansion === 'ix' || expansion === 'choam') &&
|
||||
(!state.homeworlds || expansion === 'ix' || expansion === 'choam' || pairedE3) &&
|
||||
!state.leaderSkills && !state.ecazTreachery &&
|
||||
(!state.discoveryEnabled || discovery) &&
|
||||
((!state.techTokens && !state.strongholdCards) || discovery || pairedNexusModulesProfile(state)),
|
||||
'Enable Nexus Cards with supported original paired E1/E2 Homeworlds, Discovery, Tech or Advanced Stronghold components.');
|
||||
((!state.techTokens && !state.strongholdCards) || discovery || pairedNexusModulesProfile(state) || pairedE3),
|
||||
'Enable Nexus Cards with supported original paired Homeworlds, Discovery, Tech or Advanced Stronghold components.');
|
||||
if (state.discoveryEnabled) {
|
||||
requireFreshBaseRuntime(state);
|
||||
requireFreshFactionInventory(state);
|
||||
}
|
||||
return initializeSetupGameForAudit(state, !!state.homeworlds, true, false, discovery, false, false, true);
|
||||
const g = initializeSetupGameForAudit(state, !!state.homeworlds, true, false, discovery, false, false, true);
|
||||
if (pairedE3) g.ecazOccupyPreview = true;
|
||||
if (pairedE3 && g.advanced) initializeMoritaniAssassinateState(g);
|
||||
return g;
|
||||
}
|
||||
|
||||
/** Genuine opt-in auction source interruption; ordinary/public starts stay gated. */
|
||||
@@ -9402,9 +9409,9 @@ export function initializeFactionExpansionsGameForAudit(state: Game): Game {
|
||||
return initialized;
|
||||
}
|
||||
function ecazOccupyCompositionSupported(g: Game): boolean {
|
||||
if (g.ecazOccupyPreview === true && standaloneE3NexusProfile(g) &&
|
||||
if (g.ecazOccupyPreview === true && (standaloneE3NexusProfile(g) || pairedE3NexusProfile(g)) &&
|
||||
g.players.some(player => player.faction === 'ecaz')) return true;
|
||||
if (g.leaderSkills && standaloneE3NexusLeaderSkillsProfile(g) &&
|
||||
if (g.leaderSkills && (standaloneE3NexusLeaderSkillsProfile(g) || pairedE3NexusLeaderSkillsProfile(g)) &&
|
||||
g.players.some(p => p.faction === 'ecaz')) return true;
|
||||
if (g.ecazOccupyPreview === true && g.discoveries && discoveryModeSupported(g) &&
|
||||
g.players.some(p => p.faction === 'ecaz')) return true;
|
||||
@@ -9566,12 +9573,14 @@ export function initializeLeaderSkillsGameForAudit(state: Game): Game {
|
||||
const g = structuredClone(state);
|
||||
g.leaderSkills = createLeaderSkills(random);
|
||||
const classicNexus = classicNexusLeaderSkillsProfile(g);
|
||||
const pairedE3 = pairedE3NexusLeaderSkillsProfile(g);
|
||||
const initialized = initializeSetupGameForAudit(g, homeworlds, classicNexus || pairedNexusLeaderSkillsProfile(g) ||
|
||||
singleE1E2NexusLeaderSkillsProfile(g) || standaloneE3NexusLeaderSkillsProfile(g), false,
|
||||
singleE1E2NexusLeaderSkillsProfile(g) || mixedE1E2NexusLeaderSkillsProfile(g) ||
|
||||
standaloneE3NexusLeaderSkillsProfile(g) || pairedE3, false,
|
||||
classicDiscoveryLeaderSkillsProfile(g) || nativeDiscoveryLeaderSkillsProfile(g) || (g.discoveryEnabled === true && classicNexus), true,
|
||||
g.expansions.length === 1 && g.expansions[0] === 'choam', nativeExpansionLeaderSkillsProfile(g));
|
||||
if (advancedMoritaniLeaderSkillsProfile(initialized)) initializeMoritaniAssassinateState(initialized);
|
||||
if ((homeworlds || nativeDiscoveryLeaderSkillsProfile(initialized)) && byFaction(initialized, 'ecaz')) initialized.ecazOccupyPreview = true;
|
||||
if (advancedMoritaniLeaderSkillsProfile(initialized) || (pairedE3 && initialized.advanced)) initializeMoritaniAssassinateState(initialized);
|
||||
if ((homeworlds || nativeDiscoveryLeaderSkillsProfile(initialized) || pairedE3) && byFaction(initialized, 'ecaz')) initialized.ecazOccupyPreview = true;
|
||||
return initialized;
|
||||
}
|
||||
/** Fresh all-fourteen-card classic or supported native skills; no public income toggle. */
|
||||
@@ -9611,11 +9620,13 @@ function initializeSetupGameForAudit(state: Game, homeworlds: boolean, nexus = f
|
||||
const nativeTech = factions && !leaderSkills && nativeFactionTechProfile(g);
|
||||
const discoveryComposition = discovery && (discoveryModuleProfile(g) ||
|
||||
classicDiscoveryNexusProfile(g) || pairedDiscoveryNexusProfile(g) ||
|
||||
mixedE1E2DiscoveryNexusProfile(g) || pairedE3DiscoveryNexusProfile(g) ||
|
||||
(leaderSkills && (classicDiscoveryLeaderSkillsProfile(g) || nativeDiscoveryLeaderSkillsProfile(g) || classicNexusLeaderSkillsProfile(g))));
|
||||
const nexusModules = nexus && (classicNexusModulesProfile(g) || pairedNexusModulesProfile(g) ||
|
||||
singleE1E2NexusProfile(g) || standaloneE3NexusProfile(g) ||
|
||||
singleE1E2NexusProfile(g) || mixedE1E2NexusProfile(g) || pairedE3NexusProfile(g) || standaloneE3NexusProfile(g) ||
|
||||
(leaderSkills && (classicNexusLeaderSkillsProfile(g) || pairedNexusLeaderSkillsProfile(g) ||
|
||||
singleE1E2NexusLeaderSkillsProfile(g) || standaloneE3NexusLeaderSkillsProfile(g))));
|
||||
singleE1E2NexusLeaderSkillsProfile(g) || mixedE1E2NexusLeaderSkillsProfile(g) ||
|
||||
pairedE3NexusLeaderSkillsProfile(g) || standaloneE3NexusLeaderSkillsProfile(g))));
|
||||
requireRule(!g.techTokens || ((skillTech || nativeTech || nexusModules || discoveryComposition) &&
|
||||
JSON.stringify(g.techTokens) === JSON.stringify(createTechTokens())),
|
||||
'Tech Tokens require a fresh supported three-through-six-seat lobby with unused tokens.');
|
||||
@@ -14699,13 +14710,14 @@ function ambassadorEffectBlock(
|
||||
return null;
|
||||
}
|
||||
function arrivalOverlapModeSupported(g: Game): boolean {
|
||||
return !!byFaction(g, 'ecaz') && !!byFaction(g, 'moritani') &&
|
||||
return pairedE3NexusLeaderSkillsProfile(g) || pairedE3NexusProfile(g) ||
|
||||
(!!byFaction(g, 'ecaz') && !!byFaction(g, 'moritani') &&
|
||||
g.players.every(player => CLASSIC_FACTIONS[player.faction] === true ||
|
||||
player.faction === 'ecaz' || player.faction === 'moritani') &&
|
||||
g.expansions.every(expansion => expansion === 'ecaz') &&
|
||||
!g.homeworlds && !g.nexusCards && !g.leaderSkills &&
|
||||
!g.discoveryEnabled && !g.techTokens && !g.strongholdCards &&
|
||||
!g.ecazTreachery;
|
||||
!g.ecazTreachery);
|
||||
}
|
||||
function arrivalOverlapIntegrity(g: Game) {
|
||||
const record = g.pendingArrivalOverlap;
|
||||
@@ -25759,6 +25771,8 @@ const RICHESE_CUNNING_ROSTER: Partial<Record<FactionId, true>> = {
|
||||
beneGesserit: true, guild: true, richese: true, choam: true,
|
||||
};
|
||||
function richeseCunningModeSupported(g: Game) {
|
||||
const mixed = mixedE1E2NexusProfile(g) || (!!g.leaderSkills && mixedE1E2NexusLeaderSkillsProfile(g));
|
||||
if (mixed) return !g.sandtrout;
|
||||
const skills = !!g.leaderSkills && (pairedNexusLeaderSkillsProfile(g) || singleE1E2NexusLeaderSkillsProfile(g));
|
||||
return pairedDiscoveryNexusProfile(g) || singleE1E2DiscoveryNexusProfile(g) ||
|
||||
(!!g.homeworlds && (skills || pairedNexusModulesProfile(g) || singleE1E2NexusProfile(g))) ||
|
||||
|
||||
@@ -127,6 +127,46 @@ export function standaloneE3NexusLeaderSkillsProfile(game: LeaderSkillProfile):
|
||||
(native === 'moritani' || !game.moritaniAssassinatePreview);
|
||||
}
|
||||
|
||||
/** Original E1/E2 natives from both selected families with classics and Nexus. */
|
||||
export function mixedE1E2NexusLeaderSkillsProfile(game: LeaderSkillProfile): boolean {
|
||||
if (game.expansions.length !== 2 || !game.expansions.includes('ix') ||
|
||||
!game.expansions.includes('choam') || !nexusLeaderSkillModulesSupported(game, false, true)) return false;
|
||||
const players = game.players!;
|
||||
let ix = false, choam = false;
|
||||
for (let i = 0; i < players.length; i++) {
|
||||
for (let j = 0; j < i; j++) if (players[j].faction === players[i].faction) return false;
|
||||
let family: string | undefined;
|
||||
for (const faction of FACTIONS)
|
||||
if (faction.id === players[i].faction) { family = faction.expansion; break; }
|
||||
if (family !== 'base' && family !== 'ix' && family !== 'choam') return false;
|
||||
if (family === 'ix') ix = true;
|
||||
if (family === 'choam') choam = true;
|
||||
}
|
||||
return ix && choam;
|
||||
}
|
||||
|
||||
/** Both original E3 natives and classic opponents; the shared Duke is never a training disc. */
|
||||
export function pairedE3NexusLeaderSkillsProfile(game: LeaderSkillProfile): boolean {
|
||||
if (game.expansions.length !== 1 || game.expansions[0] !== 'ecaz' ||
|
||||
!nexusLeaderSkillModulesSupported(game, game.advanced === true, true)) return false;
|
||||
const players = game.players!;
|
||||
let ecaz = false, moritani = false;
|
||||
for (let i = 0; i < players.length; i++) {
|
||||
for (let j = 0; j < i; j++) if (players[j].faction === players[i].faction) return false;
|
||||
const player = players[i];
|
||||
if (player.faction === 'ecaz') ecaz = true;
|
||||
else if (player.faction === 'moritani') moritani = true;
|
||||
else {
|
||||
if (game.advanced && player.faction === 'harkonnen') return false;
|
||||
let classic = false;
|
||||
for (const faction of FACTIONS)
|
||||
if (faction.id === player.faction) { classic = faction.expansion === 'base'; break; }
|
||||
if (!classic) return false;
|
||||
}
|
||||
}
|
||||
return ecaz && moritani;
|
||||
}
|
||||
|
||||
/** Discovery keeps original native roster predicates; only this module envelope
|
||||
* differs. Live token/entry/Great Maker frames are original consumers. */
|
||||
function discoveryLeaderSkillModulesSupported(game: LeaderSkillProfile): boolean {
|
||||
@@ -150,7 +190,7 @@ function discoveryLeaderSkillModulesSupported(game: LeaderSkillProfile): boolean
|
||||
function nativeLeaderSkillModulesSupported(game: LeaderSkillProfile): boolean {
|
||||
if (game.homeworlds) return homeworldLeaderSkillModulesSupported(game);
|
||||
if (noOtherLeaderSkillModules(game) || pairedNexusLeaderSkillsProfile(game) ||
|
||||
singleE1E2NexusLeaderSkillsProfile(game)) return true;
|
||||
singleE1E2NexusLeaderSkillsProfile(game) || mixedE1E2NexusLeaderSkillsProfile(game)) return true;
|
||||
if (game.discoveryEnabled || game.discoveries) return discoveryLeaderSkillModulesSupported(game);
|
||||
const players = game.players;
|
||||
if ((!game.techTokens && !game.strongholdCards) || !players ||
|
||||
@@ -173,7 +213,8 @@ function nativeLeaderSkillModulesSupported(game: LeaderSkillProfile): boolean {
|
||||
/** Standalone E3 native predicates retain their own roster, Duke and assassination limits. */
|
||||
function e3LeaderSkillModulesSupported(game: LeaderSkillProfile): boolean {
|
||||
if (game.homeworlds) return homeworldLeaderSkillModulesSupported(game);
|
||||
if (noOtherLeaderSkillModules(game) || standaloneE3NexusLeaderSkillsProfile(game)) return true;
|
||||
if (noOtherLeaderSkillModules(game) || standaloneE3NexusLeaderSkillsProfile(game) ||
|
||||
pairedE3NexusLeaderSkillsProfile(game)) return true;
|
||||
if (game.discoveryEnabled || game.discoveries) return discoveryLeaderSkillModulesSupported(game);
|
||||
const players = game.players;
|
||||
if ((!game.techTokens && !game.strongholdCards) || !players ||
|
||||
@@ -384,7 +425,8 @@ export function advancedNativeLeaderSkillsProfile(game: LeaderSkillProfile): boo
|
||||
}
|
||||
|
||||
export function nativeExpansionLeaderSkillsProfile(game: LeaderSkillProfile): boolean {
|
||||
return basicExpansionLeaderSkillsProfile(game) || advancedNativeLeaderSkillsProfile(game) ||
|
||||
return mixedE1E2NexusLeaderSkillsProfile(game) || pairedE3NexusLeaderSkillsProfile(game) ||
|
||||
basicExpansionLeaderSkillsProfile(game) || advancedNativeLeaderSkillsProfile(game) ||
|
||||
advancedMoritaniLeaderSkillsProfile(game) || nativeEcazLeaderSkillsProfile(game);
|
||||
}
|
||||
|
||||
@@ -405,6 +447,7 @@ function homeworldLeaderSkillModulesSupported(game: LeaderSkillProfile): boolean
|
||||
!players || players.length < 2 || players.length > 6 ||
|
||||
(game.nexusCards && !classicNexusLeaderSkillsProfile(game) &&
|
||||
!pairedNexusLeaderSkillsProfile(game) && !singleE1E2NexusLeaderSkillsProfile(game) &&
|
||||
!mixedE1E2NexusLeaderSkillsProfile(game) && !pairedE3NexusLeaderSkillsProfile(game) &&
|
||||
!standaloneE3NexusLeaderSkillsProfile(game)) ||
|
||||
(game.discoveryEnabled !== true && (game.discoveryEnabled || game.discoveries || game.discoveryStash || game.greatMaker)) ||
|
||||
(game.techTokens && players.length < 3) || (game.strongholdCards && !game.advanced) ||
|
||||
@@ -442,6 +485,7 @@ export function ordinaryLeaderSkillModeSupported(game: LeaderSkillProfile): bool
|
||||
classicTechLeaderSkillsProfile(game) || nativeTechLeaderSkillsProfile(game) ||
|
||||
strongholdLeaderSkillsProfile(game) || classicNexusLeaderSkillsProfile(game) ||
|
||||
singleE1E2NexusLeaderSkillsProfile(game) ||
|
||||
mixedE1E2NexusLeaderSkillsProfile(game) || pairedE3NexusLeaderSkillsProfile(game) ||
|
||||
pairedNexusLeaderSkillsProfile(game) || standaloneE3NexusLeaderSkillsProfile(game) ||
|
||||
classicDiscoveryLeaderSkillsProfile(game) || nativeDiscoveryLeaderSkillsProfile(game) ||
|
||||
homeworldLeaderSkillsProfile(game);
|
||||
|
||||
@@ -64,6 +64,7 @@ const opponents: readonly FactionId[] = [
|
||||
'guild',
|
||||
'emperor',
|
||||
'fremen',
|
||||
'ecaz',
|
||||
];
|
||||
const identifier = (value: unknown): value is string =>
|
||||
typeof value === 'string' &&
|
||||
|
||||
@@ -3,8 +3,8 @@ import type { Game } from './engine';
|
||||
import { acquireDuke, DUKE_VIDAL_ID, type DukeSource } from './duke-vidal';
|
||||
import { nexusCardMode } from './nexus-cards';
|
||||
import { nexusCleanPlayBlocked } from './nexus-play-boundary';
|
||||
import { standaloneE3NexusLeaderSkillsProfile } from './leader-skill-profile';
|
||||
import { standaloneE3NexusProfile } from './nexus-module-profile';
|
||||
import { pairedE3NexusLeaderSkillsProfile, standaloneE3NexusLeaderSkillsProfile } from './leader-skill-profile';
|
||||
import { pairedE3NexusProfile, standaloneE3NexusProfile } from './nexus-module-profile';
|
||||
|
||||
const SUPPORTED_FACTIONS: Partial<Record<FactionId, true>> = {
|
||||
ecaz: true, moritani: true, atreides: true, harkonnen: true,
|
||||
@@ -66,7 +66,7 @@ export function quoteNexusEcazDuke(g: Game, owner: string, automaticPending = fa
|
||||
if (g.advanced && g.players.some(player => player.faction === 'harkonnen'))
|
||||
blocked = 'Duke Vidal battle use is unavailable with Advanced Harkonnen.';
|
||||
else if (!nexusEcazDukeModeSupported(g) || nexusCardMode('ecaz', holder.faction, roster) !== 'cunning')
|
||||
blocked = 'Ecaz Nexus Cunning requires the paired Nexus-only roster or a fresh supported standalone Ecaz Nexus profile.';
|
||||
blocked = 'Ecaz Nexus Cunning requires a supported original paired or standalone Ecaz Nexus profile.';
|
||||
else if (holder.ally) blocked = 'Use Ecaz Nexus Cunning while unallied.';
|
||||
else if (g.status !== 'playing' || g.phase !== 6)
|
||||
blocked = 'Use Ecaz Nexus Cunning at the Battle phase boundary.';
|
||||
@@ -88,10 +88,11 @@ export function quoteNexusEcazDuke(g: Game, owner: string, automaticPending = fa
|
||||
}
|
||||
|
||||
export function nexusEcazDukeModeSupported(g: Game): boolean {
|
||||
if (standaloneE3NexusProfile(g) && g.players.some(player => player.faction === 'ecaz') &&
|
||||
if ((standaloneE3NexusProfile(g) || pairedE3NexusProfile(g)) &&
|
||||
g.players.some(player => player.faction === 'ecaz') &&
|
||||
!g.sandtrout && !(g.advanced && g.players.some(player => player.faction === 'harkonnen')))
|
||||
return !!g.nexusCards?.cards && g.players.length >= 3;
|
||||
if (g.leaderSkills && standaloneE3NexusLeaderSkillsProfile(g) &&
|
||||
if (g.leaderSkills && (standaloneE3NexusLeaderSkillsProfile(g) || pairedE3NexusLeaderSkillsProfile(g)) &&
|
||||
g.players.some(player => player.faction === 'ecaz') && !g.sandtrout)
|
||||
return !!g.nexusCards?.cards && g.players.length >= 3;
|
||||
return !!g.nexusCards?.cards && g.players.length >= 3 && g.players.length <= 6 &&
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { FACTIONS } from './catalog';
|
||||
import type { FactionModuleProfile } from './faction-module-profile';
|
||||
import { classicDiscoveryNexusProfile, pairedDiscoveryNexusProfile, singleE1E2DiscoveryNexusProfile, standaloneE3DiscoveryNexusProfile } from './discovery-module-profile';
|
||||
import { classicDiscoveryNexusProfile, mixedE1E2DiscoveryNexusProfile, pairedDiscoveryNexusProfile, pairedE3DiscoveryNexusProfile, singleE1E2DiscoveryNexusProfile, standaloneE3DiscoveryNexusProfile } from './discovery-module-profile';
|
||||
|
||||
/** Original classic Nexus modules, optionally Homeworlds; initializer checks undealt components. */
|
||||
export function classicNexusModulesProfile(game: FactionModuleProfile): boolean {
|
||||
@@ -115,3 +115,60 @@ export function singleE1E2NexusProfile(game: FactionModuleProfile): boolean {
|
||||
}
|
||||
return native === 1;
|
||||
}
|
||||
|
||||
/** Both selected E1/E2 native families with original Nexus and optional modules, without Skills. */
|
||||
export function mixedE1E2NexusProfile(game: FactionModuleProfile): boolean {
|
||||
if (game.discoveryEnabled || game.discoveries) return mixedE1E2DiscoveryNexusProfile(game);
|
||||
if (typeof game.advanced !== 'boolean' || !game.nexusCards ||
|
||||
game.expansions.length !== 2 || !game.expansions.includes('ix') || !game.expansions.includes('choam') ||
|
||||
game.players.length < 2 || game.players.length > 6 ||
|
||||
(game.techTokens && game.players.length < 3) ||
|
||||
(game.strongholdCards && !game.advanced) || game.leaderSkills ||
|
||||
game.discoveryEnabled || game.discoveries || game.discoveryStash || game.greatMaker ||
|
||||
game.ecazTreachery || game.semutaPreview || game.advancedPreview ||
|
||||
game.kullPreview || game.nexusKullPreview || game.guildBetrayalPreview ||
|
||||
game.richeseBetrayalPreview || game.nexusIxianReplacementPreview ||
|
||||
game.nexusIxianBetrayalPreview || game.nexusHarkonnenBetrayalPreview) return false;
|
||||
let ix = false, choam = false;
|
||||
for (let i = 0; i < game.players.length; i++) {
|
||||
const player = game.players[i];
|
||||
for (let j = 0; j < i; j++) if (player.faction === game.players[j].faction) return false;
|
||||
let family: string | undefined;
|
||||
for (const faction of FACTIONS)
|
||||
if (faction.id === player.faction) { family = faction.expansion; break; }
|
||||
if (family !== 'base' && family !== 'ix' && family !== 'choam') return false;
|
||||
if (family === 'ix') ix = true;
|
||||
if (family === 'choam') choam = true;
|
||||
}
|
||||
return ix && choam;
|
||||
}
|
||||
|
||||
/** Both original E3 natives with classic opponents, original Nexus and optional modules, without Skills. */
|
||||
export function pairedE3NexusProfile(game: FactionModuleProfile): boolean {
|
||||
if (game.discoveryEnabled || game.discoveries) return pairedE3DiscoveryNexusProfile(game);
|
||||
if (typeof game.advanced !== 'boolean' || !game.nexusCards ||
|
||||
game.expansions.length !== 1 || game.expansions[0] !== 'ecaz' ||
|
||||
game.players.length < 2 || game.players.length > 6 ||
|
||||
(game.techTokens && game.players.length < 3) ||
|
||||
(game.strongholdCards && !game.advanced) || game.leaderSkills ||
|
||||
game.discoveryEnabled || game.discoveries || game.discoveryStash || game.greatMaker ||
|
||||
game.ecazTreachery || game.semutaPreview || game.advancedPreview ||
|
||||
game.kullPreview || game.nexusKullPreview || game.guildBetrayalPreview ||
|
||||
game.richeseBetrayalPreview || game.nexusIxianReplacementPreview ||
|
||||
game.nexusIxianBetrayalPreview || game.nexusHarkonnenBetrayalPreview) return false;
|
||||
let ecaz = false, moritani = false;
|
||||
for (let i = 0; i < game.players.length; i++) {
|
||||
const player = game.players[i];
|
||||
for (let j = 0; j < i; j++) if (player.faction === game.players[j].faction) return false;
|
||||
if (player.faction === 'ecaz') ecaz = true;
|
||||
else if (player.faction === 'moritani') moritani = true;
|
||||
else {
|
||||
if (game.advanced && player.faction === 'harkonnen') return false;
|
||||
let classic = false;
|
||||
for (const faction of FACTIONS)
|
||||
if (faction.id === player.faction) { classic = faction.expansion === 'base'; break; }
|
||||
if (!classic) return false;
|
||||
}
|
||||
}
|
||||
return ecaz && moritani;
|
||||
}
|
||||
+112
-118
@@ -3820,7 +3820,7 @@ export const RULE_TOPICS: RuleTopic[] = [
|
||||
).join(' '),
|
||||
steps: [
|
||||
'Homeworlds are an optional module from Ecaz & Moritani, available under the official rules with Basic or Advanced play. They are separate locations outside Arrakis; they do not receive ordinary storm movement or count as ordinary strongholds.',
|
||||
'Fresh private Homeworld prototypes compose all fourteen Leader Skills, Discovery seven cards/eight tokens or both, Basic/Advanced two through six classic or supported native E1/E2 seats, or standalone Ecaz OR Moritani with classic opponents. Optional original Tech requires three or more seats; Stronghold Cards require Advanced. Classic, single or paired Ixians/Tleilaxu or CHOAM/Richese with one family deck, or standalone Ecaz OR Moritani entries may retain all12 Nexus through the existing skill or Nexus entry, with or without Skills. Original family decks and each roster/effect restriction remain: Advanced Moritani excludes Harkonnen; an otherwise legal no-Skills Ecaz/Harkonnen roster does not lift the separate Duke Cunning exclusion. Original setup/native placement, phase-end industry, source-local held cards and cleanup before mandatory winner Tech remain. Typed native Suk saves stay at the same home; external Emperor returns explicitly allocate normal/elite counters to actual native homes, an implementation interpretation rather than ordinary revival placement. Normal revival separately deposits Sardaukar at Salusa. Nested battles receive no Homeworld bonus; later Cistern income is separate from support/rescue. Mixed-deck Nexus, unsupported E3 pairs/mixed families, unrelated overlays, public starts and pending interactions stay separate.',
|
||||
'Fresh private Homeworld prototypes retain all fourteen Skills, Discovery7/8 or both in classic or supported E1/E2 and standalone Ecaz OR Moritani tables. Original Nexus entries additionally support single or paired one-family E1/E2, natives from BOTH selected Ix+CHOAM families with union47, and standalone OR paired Ecaz/Moritani/ecaz33 with classics, with or without Skills. Basic/Advanced2–6, Tech3+ and Advanced Strongholds2+ retain original setup, native placement, phase-end industry and source-local held cards. Advanced Moritani/paired E3 excludes Harkonnen; otherwise legal standalone no-Skills Ecaz/Harkonnen does not lift its separate Duke Cunning exclusion. Winning typed native Suk saves stay at that home; external Emperor returns allocate physical normal/elite counters to original homes as the existing interpretation. Normal revival separately deposits Sardaukar at Salusa. Nested battles receive no Homeworld bonus. Mixed E3/three-family Nexus, pending effects, public starts and played-save conversion remain separate.',
|
||||
'Each faction uses its own card and matching world token. In Basic play the Emperor uses Kaitain alone. Advanced play adds Salusa Secundus for its Sardaukar; movement can transfer both force types between the two Emperor worlds.',
|
||||
'Native reserves determine high or low population. Salusa counts Sardaukar, while the other cards count the faction’s reserves there. Reaching the high face’s minimum restores high population. Occupation also applies the low penalty.',
|
||||
'Low population normally grants one additional free force revival and one additional bank spice when collecting CHOAM Charity. Salusa grants neither bonus; CHOAM’s Tupile reverses the usual pattern by granting an advantage while low and a penalty while high.',
|
||||
@@ -3984,104 +3984,100 @@ export const RULE_TOPICS: RuleTopic[] = [
|
||||
area: 'Verification',
|
||||
status: 'Partial',
|
||||
detail:
|
||||
'Single-native E1/E2 Nexus adds15 meaningful programmes; affected398/398 across35 files and types/lint pass. All32 original six-seat families finish190/192 games with208205 accepted/208213 attempted actions and5539 JSON across two frozen trees, including one repaired original Smuggler continuation. Exhausted-cache/low-Tupile captures retain source guards. Actual390px original trained Ixian offer/typed Cistern entry, Maker/both-pile draw, free Suboid support and equal nested Cyborg exchange preserve20 physical/seven Cyborgs; no-training Richese five-plus-three pair/reveal costs one spice and preserves20. Earlier classic/native/E3 evidence remains canonical. Full rules, combinations, assurance/calibration and deployed acceptance remain open.',
|
||||
evidence: [
|
||||
'tests/single-nexus-e1-runtime.test.ts',
|
||||
'tests/single-nexus-e2-runtime.test.ts',
|
||||
'tests/homeworld-classic-skills-runtime.test.ts',
|
||||
'tests/homeworld-classic-discovery-runtime.test.ts',
|
||||
'tests/homeworld-skills-discovery-runtime.test.ts',
|
||||
'tests/homeworld-optional-modules-runtime.test.ts',
|
||||
'tests/homeworld-native-e1e2-modules-runtime.test.ts',
|
||||
'tests/homeworld-native-e3-modules-runtime.test.ts',
|
||||
'tests/homeworld-classic-nexus-skills-runtime.test.ts',
|
||||
'tests/homeworld-classic-discovery-nexus-runtime.test.ts',
|
||||
'tests/homeworld-paired-nexus-runtime.test.ts',
|
||||
'tests/homeworld-standalone-nexus-runtime.test.ts',
|
||||
'tests/e3-nexus-ecaz-runtime.test.ts',
|
||||
'tests/e3-nexus-moritani-runtime.test.ts',
|
||||
'tests/homeworld-custody.test.ts',
|
||||
'tests/homeworld-cards.test.ts',
|
||||
'tests/homeworld-payment-income.test.ts',
|
||||
'tests/homeworld-payment-income-engine.test.ts',
|
||||
'tests/homeworld-payment-income-recovery.test.ts',
|
||||
'tests/homeworld-collection.test.ts',
|
||||
'tests/homeworld-collection-engine.test.ts',
|
||||
'tests/homeworld-collection-recovery.test.ts',
|
||||
'tests/homeworld-grumman-engine.test.ts',
|
||||
'tests/homeworld-grumman-recovery.test.ts',
|
||||
'tests/homeworld-setup-engine.test.ts',
|
||||
'tests/homeworld-actions-engine.test.ts',
|
||||
'tests/homeworld-basic-counters.test.ts',
|
||||
'tests/homeworld-salusa-engine.test.ts',
|
||||
'tests/homeworld-combat.test.ts',
|
||||
'tests/homeworld-battle-resolution.test.ts',
|
||||
'tests/homeworld-battle-engine.test.ts',
|
||||
'tests/homeworld-battle-recovery.test.ts',
|
||||
'tests/homeworld-shipment-engine.test.ts',
|
||||
'tests/homeworld-shipment-recovery.test.ts',
|
||||
'tests/homeworld-shipment-controls.test.ts',
|
||||
'tests/homeworld-shipment-review.test.ts',
|
||||
'tests/guild-homeworld-shipment-engine.test.ts',
|
||||
'tests/guild-homeworld-shipment-recovery.test.ts',
|
||||
'tests/guild-homeworld-shipment-controls.test.ts',
|
||||
'tests/junction-transport.test.ts',
|
||||
'tests/junction-transport-engine.test.ts',
|
||||
'tests/junction-transport-recovery.test.ts',
|
||||
'tests/junction-transport-controls.test.ts',
|
||||
'tests/junction-transport-review.test.ts',
|
||||
'tests/homeworld-card-economy.test.ts',
|
||||
'tests/homeworld-tupile-sales-engine.test.ts',
|
||||
'tests/homeworld-tupile-sales-recovery.test.ts',
|
||||
'tests/bidding-end-engine.test.ts',
|
||||
'tests/bidding-end-controls.test.ts',
|
||||
'tests/bidding-end-recovery.test.ts',
|
||||
'tests/ecaz-poison-income.test.ts',
|
||||
'tests/ecaz-poison-income-engine.test.ts',
|
||||
'tests/homeworld-mobility.test.ts',
|
||||
'tests/homeworld-mobility-engine.test.ts',
|
||||
'tests/homeworld-mobility-recovery.test.ts',
|
||||
'tests/homeworld-spiritual-advisors.test.ts',
|
||||
'tests/homeworld-spiritual-advisors-recovery.test.ts',
|
||||
'tests/homeworld-advisor-ambassador.test.ts',
|
||||
'tests/homeworld-replacement-engine.test.ts',
|
||||
'tests/homeworld-recovery.test.ts',
|
||||
'tests/homeworld-charity-engine.test.ts',
|
||||
'tests/homeworld-revival-benefits-engine.test.ts',
|
||||
'tests/homeworld-revival-deployment.test.ts',
|
||||
'tests/homeworld-revival-return.test.ts',
|
||||
'tests/homeworld-revival-destinations.test.ts',
|
||||
'tests/homeworld-revival-deployment-engine.test.ts',
|
||||
'tests/homeworld-revival-deployment-controls.test.ts',
|
||||
'tests/homeworld-revival-deployment-recovery.test.ts',
|
||||
'tests/homeworld-victory-reinforcement.test.ts',
|
||||
'tests/caladan-reinforcement-controls.test.ts',
|
||||
'tests/homeworld-victory-reinforcement-recovery.test.ts',
|
||||
'tests/tupile-intelligence.test.ts',
|
||||
'tests/tupile-intelligence-answer.test.ts',
|
||||
'tests/tupile-intelligence-state.test.ts',
|
||||
'tests/tupile-intelligence-controls.test.ts',
|
||||
'tests/tupile-intelligence-engine.test.ts',
|
||||
'tests/tupile-intelligence-recovery.test.ts',
|
||||
'tests/homeworld-occupation-history.test.ts',
|
||||
'tests/homeworld-occupied-income.test.ts',
|
||||
'tests/homeworld-occupied-percentage.test.ts',
|
||||
'tests/homeworld-occupied-bidding.test.ts',
|
||||
'tests/homeworld-occupied-defenses.test.ts',
|
||||
'tests/homeworld-occupation-runtime.test.ts',
|
||||
'tests/homeworld-occupied-producers-engine.test.ts',
|
||||
'tests/homeworld-occupied-private-lots.test.ts',
|
||||
'tests/homeworld-occupied-tupile.test.ts',
|
||||
'tests/homeworld-occupied-tupile-runtime.test.ts',
|
||||
'tests/ecaz-homeworld-victory.test.ts',
|
||||
'tests/ecaz-homeworld-victory-runtime.test.ts',
|
||||
'tests/grumman-collection.test.ts',
|
||||
'tests/grumman-collection-engine.test.ts',
|
||||
'tests/grumman-collection-controls.test.ts',
|
||||
'tests/grumman-collection-recovery.test.ts',
|
||||
'tests/grumman-selection-integrity.test.ts',
|
||||
'tests/homeworld-benefits-recovery.test.ts',
|
||||
],
|
||||
'Mixed E1/E2 and paired E3 Nexus adds31 original physical programmes plus2 Loyalty-stock regressions. Final489/489 affected checks across42 files pass with types/lint. All64 original families finish258/288 six-seat games with338931 accepted/339426 attempted actions and9013 JSON across three frozen trees and preserved-prefix continuations. All30 remaining source-guard traces are read. Actual390px original Ixian offer/training, typed native and foreign-world payment/free Suboid plan and paired Ecaz foreign entry/living shared Duke preserve20 physical counters. Human Ixian loses, so no winning Suk rescue is claimed. Earlier qualified evidence remains canonical; full rules, assurance, calibration and deployed acceptance remain open.',
|
||||
evidence: ['tests/mixed-nexus-modules-runtime.test.ts', 'tests/paired-e3-nexus-modules-runtime.test.ts', 'tests/sample-custody.test.ts', 'tests/ambassador-terror-overlap-engine.test.ts', 'tests/single-nexus-e1-runtime.test.ts', 'tests/single-nexus-e2-runtime.test.ts', 'tests/homeworld-classic-skills-runtime.test.ts',
|
||||
'tests/homeworld-classic-discovery-runtime.test.ts',
|
||||
'tests/homeworld-skills-discovery-runtime.test.ts',
|
||||
'tests/homeworld-optional-modules-runtime.test.ts',
|
||||
'tests/homeworld-native-e1e2-modules-runtime.test.ts',
|
||||
'tests/homeworld-native-e3-modules-runtime.test.ts',
|
||||
'tests/homeworld-classic-nexus-skills-runtime.test.ts',
|
||||
'tests/homeworld-classic-discovery-nexus-runtime.test.ts',
|
||||
'tests/homeworld-paired-nexus-runtime.test.ts',
|
||||
'tests/homeworld-standalone-nexus-runtime.test.ts',
|
||||
'tests/e3-nexus-ecaz-runtime.test.ts',
|
||||
'tests/e3-nexus-moritani-runtime.test.ts',
|
||||
'tests/homeworld-custody.test.ts',
|
||||
'tests/homeworld-cards.test.ts',
|
||||
'tests/homeworld-payment-income.test.ts',
|
||||
'tests/homeworld-payment-income-engine.test.ts',
|
||||
'tests/homeworld-payment-income-recovery.test.ts',
|
||||
'tests/homeworld-collection.test.ts',
|
||||
'tests/homeworld-collection-engine.test.ts',
|
||||
'tests/homeworld-collection-recovery.test.ts',
|
||||
'tests/homeworld-grumman-engine.test.ts',
|
||||
'tests/homeworld-grumman-recovery.test.ts',
|
||||
'tests/homeworld-setup-engine.test.ts',
|
||||
'tests/homeworld-actions-engine.test.ts',
|
||||
'tests/homeworld-basic-counters.test.ts',
|
||||
'tests/homeworld-salusa-engine.test.ts',
|
||||
'tests/homeworld-combat.test.ts',
|
||||
'tests/homeworld-battle-resolution.test.ts',
|
||||
'tests/homeworld-battle-engine.test.ts',
|
||||
'tests/homeworld-battle-recovery.test.ts',
|
||||
'tests/homeworld-shipment-engine.test.ts',
|
||||
'tests/homeworld-shipment-recovery.test.ts',
|
||||
'tests/homeworld-shipment-controls.test.ts',
|
||||
'tests/homeworld-shipment-review.test.ts',
|
||||
'tests/guild-homeworld-shipment-engine.test.ts',
|
||||
'tests/guild-homeworld-shipment-recovery.test.ts',
|
||||
'tests/guild-homeworld-shipment-controls.test.ts',
|
||||
'tests/junction-transport.test.ts',
|
||||
'tests/junction-transport-engine.test.ts',
|
||||
'tests/junction-transport-recovery.test.ts',
|
||||
'tests/junction-transport-controls.test.ts',
|
||||
'tests/junction-transport-review.test.ts',
|
||||
'tests/homeworld-card-economy.test.ts',
|
||||
'tests/homeworld-tupile-sales-engine.test.ts',
|
||||
'tests/homeworld-tupile-sales-recovery.test.ts',
|
||||
'tests/bidding-end-engine.test.ts',
|
||||
'tests/bidding-end-controls.test.ts',
|
||||
'tests/bidding-end-recovery.test.ts',
|
||||
'tests/ecaz-poison-income.test.ts',
|
||||
'tests/ecaz-poison-income-engine.test.ts',
|
||||
'tests/homeworld-mobility.test.ts',
|
||||
'tests/homeworld-mobility-engine.test.ts',
|
||||
'tests/homeworld-mobility-recovery.test.ts',
|
||||
'tests/homeworld-spiritual-advisors.test.ts',
|
||||
'tests/homeworld-spiritual-advisors-recovery.test.ts',
|
||||
'tests/homeworld-advisor-ambassador.test.ts',
|
||||
'tests/homeworld-replacement-engine.test.ts',
|
||||
'tests/homeworld-recovery.test.ts',
|
||||
'tests/homeworld-charity-engine.test.ts',
|
||||
'tests/homeworld-revival-benefits-engine.test.ts',
|
||||
'tests/homeworld-revival-deployment.test.ts',
|
||||
'tests/homeworld-revival-return.test.ts',
|
||||
'tests/homeworld-revival-destinations.test.ts',
|
||||
'tests/homeworld-revival-deployment-engine.test.ts',
|
||||
'tests/homeworld-revival-deployment-controls.test.ts',
|
||||
'tests/homeworld-revival-deployment-recovery.test.ts',
|
||||
'tests/homeworld-victory-reinforcement.test.ts',
|
||||
'tests/caladan-reinforcement-controls.test.ts',
|
||||
'tests/homeworld-victory-reinforcement-recovery.test.ts',
|
||||
'tests/tupile-intelligence.test.ts',
|
||||
'tests/tupile-intelligence-answer.test.ts',
|
||||
'tests/tupile-intelligence-state.test.ts',
|
||||
'tests/tupile-intelligence-controls.test.ts',
|
||||
'tests/tupile-intelligence-engine.test.ts',
|
||||
'tests/tupile-intelligence-recovery.test.ts',
|
||||
'tests/homeworld-occupation-history.test.ts',
|
||||
'tests/homeworld-occupied-income.test.ts',
|
||||
'tests/homeworld-occupied-percentage.test.ts',
|
||||
'tests/homeworld-occupied-bidding.test.ts',
|
||||
'tests/homeworld-occupied-defenses.test.ts',
|
||||
'tests/homeworld-occupation-runtime.test.ts',
|
||||
'tests/homeworld-occupied-producers-engine.test.ts',
|
||||
'tests/homeworld-occupied-private-lots.test.ts',
|
||||
'tests/homeworld-occupied-tupile.test.ts',
|
||||
'tests/homeworld-occupied-tupile-runtime.test.ts',
|
||||
'tests/ecaz-homeworld-victory.test.ts',
|
||||
'tests/ecaz-homeworld-victory-runtime.test.ts',
|
||||
'tests/grumman-collection.test.ts',
|
||||
'tests/grumman-collection-engine.test.ts',
|
||||
'tests/grumman-collection-controls.test.ts',
|
||||
'tests/grumman-collection-recovery.test.ts',
|
||||
'tests/grumman-selection-integrity.test.ts',
|
||||
'tests/homeworld-benefits-recovery.test.ts',],
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -4094,11 +4090,11 @@ export const RULE_TOPICS: RuleTopic[] = [
|
||||
summary: 'A development prototype connects Great Maker, six Discovery spice blows, private token inspection, stash rewards, revealed locations, next-turn entry, Cistern income, bounded Orgiz transfers, Ornithopter movement, Jacurutu income, Testing Station and Shrine. Remaining interpretations and normal public starts stay gated.',
|
||||
searchText: 'Hiereg Smuggler Jacurutu Sietch Cistern Ecological Testing Station Shrine Orgiz Processing Station Treachery Card Stash Spice Stash Ornithopter',
|
||||
steps: [
|
||||
'Fresh Discovery development setup supports classic, selected Ixian/Tleilaxu/CHOAM/Richese families, or standalone Ecaz or Moritani with classic opponents in Basic or Advanced, with seven extra Spice Cards and eight tokens. Original unused Tech Tokens may be selected with three through six seats; original Stronghold Cards require Advanced. Other modules, paired or mixed Ecaz/Moritani families and normal public starts stay gated.',
|
||||
'Fresh Discovery retains Homeworlds in Basic/Advanced two through six classic or supported native E1/E2 seats, or standalone Ecaz OR Moritani with classic opponents, original seven cards/eight tokens and native reserve placement. Original Tech requires three or more seats; Stronghold Cards require Advanced. The separate original leader-skills --discoveries entry composes all fourteen Skills. Classic, single or paired Ixians/Tleilaxu or CHOAM/Richese with one family deck, or standalone Ecaz OR Moritani entries retain all12 Nexus through the original Nexus entry without Skills, or their existing skill entry. Maker, later parent entry, nested shipment/rescue, phase-end industry and cleanup before mandatory winner Tech retain actual sources; held benefits never spill into a Homeworld or unrelated nested site. Mixed-deck Nexus, unsupported E3 pairs/mixed families and unrelated overlays remain separate in this bounded profile, not outside the full goal.',
|
||||
'The fresh Leader Skills entry may explicitly add Discoveries with original classic or supported native decks, all fourteen skills, original Tech at three or more seats and Advanced Stronghold Cards. Original Homeworlds may be retained; --nexus-cards requires classic factions, single or paired Ixians/Tleilaxu OR CHOAM/Richese with one family deck, or standalone Ecaz OR Moritani with classics. All12 Nexus retain the actual settled-alliance end-Spice closing deal after Great Maker and both Advanced piles. Existing native roster and Duke/assassination/Harkonnen restrictions remain. Actual hands/offers, physical entry, nested tariffs, stash capacity, typed rescue, native aftermath and printed invoices retain their sources. Mixed decks, unsupported E3 pairs/mixed families, independent variants and separate Banker/Mentat previews remain outside these bounded compositions.',
|
||||
'The same fresh entry also adds --nexus-cards --discoveries to single or paired Ixians/Tleilaxu, single or paired CHOAM/Richese or standalone Ecaz OR Moritani with classics, optionally retaining original Homeworlds: all14 offered training, all12 Nexus and Discovery7/8, Basic/Advanced two through six, optional Tech at three or more seats and Advanced Strongholds. Original setup, first hands, offers and native components stay authoritative. Real Maker losses/votes/typed rides, both Advanced piles and settled alliance precede the end-Spice closing draw. E1 Suboid Cunning settles typed Suk rescue before one equal Cyborg Tank substitution; original cleanup and mandatory winner Tech precede a matching Face Dance, whose foreign-Homeworld suppression remains. E2 keeps the signed two-marker frame and one invoice. Ecaz keeps quiet living/unclaimed Duke separate from training and a real owner-labelled Arrakis Occupy; Moritani keeps skill-first assassination and one private Mentat replacement. Mixed/E3 pairs, shared Duke, borrowed Smuggler/pair companions, native free returns, captured/foreign training, Basic odd-force Ecaz and Advanced Harkonnen stay separate.',
|
||||
'A separate fresh Nexus entry may explicitly add Discoveries to classic factions, single or paired native Ixians/Tleilaxu OR CHOAM/Richese with classics and one family deck, or standalone Ecaz OR Moritani with classics and one original ecaz deck, without Skills and optionally retaining original Homeworlds. Original Tech requires three or more seats; Stronghold Cards require Advanced. Native Ecaz Arrakis Occupy and Advanced Moritani assassination retain their original source/effect exclusions; no training component or starting Nexus deal is added. End-Mentat ownership and next-turn physical entry remain. Great Maker finishes its losses, votes and typed reserve ride before ordinary Nexus settlement; cards are offered only at the end of the entire Spice Blow after both Advanced piles and settled alliance, not immediately or at Mentat. Source-clear ledgers, Guild-priced nested shipment and signed native one-invoice marker pairs retain physical pieces and original capacities. E3pairs/mixed families, unrelated previews, unresolved native free returns and mixed-module Fremen Betrayal remain separate.',
|
||||
'The Discovery-only fresh entry supports classics, selected Ixian/Tleilaxu/CHOAM/Richese families or standalone Ecaz OR Moritani with classics, Basic/Advanced2–6, seven extra Spice Cards/eight tokens, optional unused Tech3+ and Advanced Strongholds. Its separate Nexus/Skills entries below admit their additional exact compositions; Discovery-only paired or mixed E3 and public starts remain gated.',
|
||||
'Fresh Discovery retains original Homeworlds and native reserves in classic, supported E1/E2 or standalone E3 tables, Basic/Advanced2–6, optional Tech3+/Advanced Strongholds. Original Nexus entries additionally admit natives from BOTH Ix+CHOAM families/union47 or BOTH Ecaz+Moritani/ecaz33 with classics, with or without all14 Skills. Maker, actual parent/nested entry, source-local payments/rescue, phase-end industry and original-winner cleanup/Tech remain. Held benefits do not migrate into nested locations. Original capture/roster and unresolved-effect guards remain.',
|
||||
'The original leader-skills --nexus-cards --discoveries entry composes all14 offered training/all12 Nexus/Discovery7/8 for classics/base33, single or paired one-family E1/E2, natives from BOTH selected Ix+CHOAM families/union47, or standalone OR paired Ecaz/Moritani/ecaz33 with classics. Original Homeworlds may be retained; Tech requires3+ and Strongholds Advanced. Hands/offers, native components and actual Maker/both-pile/alliance-change closing draws remain authoritative. Shared Duke never trains; Advanced paired E3/Moritani excludes Harkonnen. Mixed E3/three-family and pending effects/public starts/save conversion remain separate.',
|
||||
'Connected native outcomes use original sources: Suboid Cunning and winning trained Suk settle typed fixed casualties before one equal actual Cyborg Tank substitution; original cleanup and mandatory winner Tech precede matching Face Dance, retaining its foreign-Homeworld suppression. Signed Richese two-marker one-invoice physical shipment requires a currently revealed nested site. Ecaz-selected coalition armies and Moritani skill-first assassination remain distinct from shared-Duke training. These programmes do not certify every skill or card band.',
|
||||
'The original nexus --discoveries entry retains NO Skills with classics/base33, single or paired one-family E1/E2, both selected Ix+CHOAM native families/union47, or standalone OR paired Ecaz/Moritani/ecaz33 with classics. Original Homeworlds/Tech3+/Advanced Strongholds remain optional. Real native Traitors, Arrakis Occupy and Advanced assassination marks remain; no starting Nexus hand or training is added. Maker losses/votes/typed reserve rides, both Advanced piles and actual settled alliance change precede the closing card deal. Source guards and public/played-save boundaries remain.',
|
||||
'Original Stronghold Cards are claimed only at end-Mentat. A held benefit applies in its named territory or the mobile stronghold through its actual declared copy; revealed Discovery locations do not inherit another territory’s defense or bank support. Jacurutu counts toward stronghold victory but creates no seventh Stronghold Card. Physical free entry, nested tariffs, trained or native force casualties, card cleanup and optional Tech reward retain their original sources.',
|
||||
'Great Maker first resolves the ordinary worm consequences. All players then vote in storm order on creating a Nexus. A strict majority is required; a tie adds no Nexus and an existing Nexus in the phase stays recorded. Fremen may then ride with actual reserve forces to one legal destination for free, without using ordinary shipment or movement. Storm and occupancy restrictions still apply.',
|
||||
'Each of the six Discovery territory cards destroys prior spice and forces in the named blow territory, including Fremen forces, before placing six new spice subject to the storm. It also places a random available face-down token of the printed type at the card’s separate token destination.',
|
||||
@@ -4138,11 +4134,9 @@ export const RULE_TOPICS: RuleTopic[] = [
|
||||
},
|
||||
{
|
||||
area: 'Verification', status: 'Partial',
|
||||
detail: 'Single-native E1/E2 Nexus adds15 original programmes and398/398 affected checks across35 files, types/lint pass. Across32 families,190/192 genuine six-seat games finish208205/208213 actions with5539 JSON across two frozen trees after one real ordinary-skill consumer omission is repaired through the shared predicate. Exhausted-cache/low-Tupile captures remain guarded. Actual390px typed native Cistern entry, Maker/both-pile alliance closing, human Suboid Cunning/equal exchange and native one-invoice five-plus-three reveal preserve original20-counter budgets. Earlier source-qualified evidence remains canonical; full rules/combinations and deployed acceptance remain open.',
|
||||
evidence: ['tests/e3-nexus-ecaz-runtime.test.ts', 'tests/e3-nexus-moritani-runtime.test.ts',
|
||||
'tests/single-nexus-e1-runtime.test.ts', 'tests/single-nexus-e2-runtime.test.ts',
|
||||
'tests/homeworld-paired-nexus-runtime.test.ts', 'tests/homeworld-standalone-nexus-runtime.test.ts',
|
||||
'tests/homeworld-classic-nexus-skills-runtime.test.ts', 'tests/homeworld-classic-discovery-nexus-runtime.test.ts', 'tests/homeworld-native-e1e2-modules-runtime.test.ts', 'tests/homeworld-native-e3-modules-runtime.test.ts', 'tests/homeworld-classic-discovery-runtime.test.ts', 'tests/homeworld-skills-discovery-runtime.test.ts', 'tests/homeworld-optional-modules-runtime.test.ts', 'tests/discovery-native-e1-skills-runtime.test.ts', 'tests/discovery-native-e2-skills-runtime.test.ts', 'tests/discovery-native-e3-skills-runtime.test.ts', 'tests/discovery-skills-strongholds-runtime.test.ts', 'tests/discovery-native-strongholds-runtime.test.ts', 'tests/ecaz-stronghold-runtime.test.ts', 'tests/e3-native-tech-runtime.test.ts', 'tests/discovery-classic-nexus-lifecycle.test.ts', 'tests/discovery-classic-nexus-effects.test.ts', 'tests/discovery-orgiz-advanced-runtime.test.ts', 'tests/discovery-classic-skills-runtime.test.ts', 'tests/discovery-module-profile.test.ts', 'tests/discovery-native-typed-runtime.test.ts', 'tests/discovery-native-marker-runtime.test.ts', 'tests/discovery-native-e3-runtime.test.ts', 'tests/discoveries.test.ts', 'tests/discovery-runtime.test.ts', 'tests/great-maker.test.ts', 'tests/discovery-board.test.ts', 'tests/discovery-admission.test.ts', 'tests/discovery-controls.test.ts', 'tests/discovery-entry.test.ts', 'tests/discovery-entry-runtime.test.ts', 'tests/discovery-entry-controls.test.ts', 'tests/discovery-entry-review.test.ts', 'tests/discovery-collection.test.ts', 'tests/discovery-flight.test.ts', 'tests/discovery-flight-engine.test.ts', 'tests/discovery-flight-recovery.test.ts', 'tests/discovery-battle.test.ts', 'tests/discovery-battle-recovery.test.ts', 'tests/discovery-storm.test.ts', 'tests/discovery-storm-recovery.test.ts', 'tests/discovery-shrine-engine.test.ts', 'tests/discovery-shrine-recovery.test.ts', 'docs/HOMEWORLD_RUNTIME_IMPLEMENTATION.md'],
|
||||
detail: 'Mixed E1/E2 and paired E3 preserves Discovery7/8/all12 Nexus, optional all14/HW/Tech/Advanced Strongholds. New31 physical programmes plus2 stock regressions; final489/489 affected checks across42 files pass with types/lint. Across64 original families,258/288 games finish338931/339426 actions and9013 JSON across three frozen trees and preserved continuations. Native Ecaz assassination, actual separate Loyalty stock and existing selected overlap order are repaired without new printed rulings. Actual original Maker votes/both piles and native card draws retain physical sources; no human nested entry or winning Suk is invented. Source guards and full acceptance remain open.',
|
||||
evidence: ['tests/mixed-nexus-modules-runtime.test.ts', 'tests/paired-e3-nexus-modules-runtime.test.ts', 'tests/sample-custody.test.ts', 'tests/ambassador-terror-overlap-engine.test.ts', 'tests/e3-nexus-ecaz-runtime.test.ts', 'tests/e3-nexus-moritani-runtime.test.ts', 'tests/single-nexus-e1-runtime.test.ts', 'tests/single-nexus-e2-runtime.test.ts', 'tests/homeworld-paired-nexus-runtime.test.ts', 'tests/homeworld-standalone-nexus-runtime.test.ts',
|
||||
'tests/homeworld-classic-nexus-skills-runtime.test.ts', 'tests/homeworld-classic-discovery-nexus-runtime.test.ts', 'tests/homeworld-native-e1e2-modules-runtime.test.ts', 'tests/homeworld-native-e3-modules-runtime.test.ts', 'tests/homeworld-classic-discovery-runtime.test.ts', 'tests/homeworld-skills-discovery-runtime.test.ts', 'tests/homeworld-optional-modules-runtime.test.ts', 'tests/discovery-native-e1-skills-runtime.test.ts', 'tests/discovery-native-e2-skills-runtime.test.ts', 'tests/discovery-native-e3-skills-runtime.test.ts', 'tests/discovery-skills-strongholds-runtime.test.ts', 'tests/discovery-native-strongholds-runtime.test.ts', 'tests/ecaz-stronghold-runtime.test.ts', 'tests/e3-native-tech-runtime.test.ts', 'tests/discovery-classic-nexus-lifecycle.test.ts', 'tests/discovery-classic-nexus-effects.test.ts', 'tests/discovery-orgiz-advanced-runtime.test.ts', 'tests/discovery-classic-skills-runtime.test.ts', 'tests/discovery-module-profile.test.ts', 'tests/discovery-native-typed-runtime.test.ts', 'tests/discovery-native-marker-runtime.test.ts', 'tests/discovery-native-e3-runtime.test.ts', 'tests/discoveries.test.ts', 'tests/discovery-runtime.test.ts', 'tests/great-maker.test.ts', 'tests/discovery-board.test.ts', 'tests/discovery-admission.test.ts', 'tests/discovery-controls.test.ts', 'tests/discovery-entry.test.ts', 'tests/discovery-entry-runtime.test.ts', 'tests/discovery-entry-controls.test.ts', 'tests/discovery-entry-review.test.ts', 'tests/discovery-collection.test.ts', 'tests/discovery-flight.test.ts', 'tests/discovery-flight-engine.test.ts', 'tests/discovery-flight-recovery.test.ts', 'tests/discovery-battle.test.ts', 'tests/discovery-battle-recovery.test.ts', 'tests/discovery-storm.test.ts', 'tests/discovery-storm-recovery.test.ts', 'tests/discovery-shrine-engine.test.ts', 'tests/discovery-shrine-recovery.test.ts', 'docs/HOMEWORLD_RUNTIME_IMPLEMENTATION.md'],
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -4422,12 +4416,12 @@ export const RULE_TOPICS: RuleTopic[] = [
|
||||
'Before drawing, choose whether to keep your own faction card, redraw it once, or redraw whenever it appears. Its effect is available in the reference before making this choice. The server applies that preference immediately; the table never pauses in a way that identifies a card you chose to keep.',
|
||||
'Entering any alliance discards your held Nexus Card, including alliances made through an Ambassador or Terror token. An offer that has not been accepted does not discard it.',
|
||||
'Use Cunning for your own faction, Betrayal when another player controls the printed faction, and Secret Ally when that faction is absent. Used cards go to the separate Nexus discard pile. Each printed effect has its own timing.',
|
||||
'Fresh local classic Nexus tables retain original Homeworlds with optional Tech Tokens in Basic/Advanced three-through-six-seat lobbies and/or Stronghold Cards in Advanced two-through-six-seat lobbies; selecting both requires three or more. Original base33/all12 setup, closing Nexus deals, first-Storm Tech and actual end-Mentat Stronghold custody remain. Separate leader-skills --nexus-cards composes all14 original training with these modules, optionally Discovery. Original paired E1/E2 and standalone E3 entries retain their own documented native roster/deck/effect boundaries. Unrelated previews, public starts and saved-game conversion remain separate.',
|
||||
'Fresh nexus --discoveries preserves original Tech and Advanced Stronghold prerequisites with classic factions, single or paired native Ixians/Tleilaxu OR CHOAM/Richese with one family deck, or standalone Ecaz OR Moritani with classics and ecaz33, without Skills. These entries may retain original Homeworlds. The original seven Discovery Spice Cards/eight tokens, protected nested locations, next-turn physical entry and Great Maker losses/votes/typed native reserve ride remain. The closing draw follows both Advanced piles and settled alliances; a preceding Shai-Hulud’s completed losses do not repeat. Source-clear quotas, borrowed Guild tariffs and signed native two-marker one-invoice shipments into currently revealed sites use original controls. E3pairs/mixed families, unresolved native free-return and mixed-module Fremen Betrayal or other unfinished effects remain guarded; no public start or save conversion.',
|
||||
'The fresh local Nexus entry also composes Tech and/or Advanced Strongholds with single or paired Ixians/Tleilaxu OR CHOAM/Richese and classic opponents, one original family deck and no Skills, optionally original Homeworlds. Discovery may be selected through --discoveries, including without Tech or Strongholds. Tech needs three through six seats; Strongholds needs two through six Advanced seats. Real closing draws, native typed forces, physical Face Dancers/No-Fields, original payments/rewards and held effects remain. The paired initializer still requires both native factions; single-native games use the existing generic initializer and original faction setup. Mixed families, unrelated previews, public starts and unresolved rulings remain separate.',
|
||||
'Fresh original Nexus tables may retain Homeworlds, Discovery7/8, Tech3+ Basic/Advanced and Strongholds2+ Advanced, optionally all14 through leader-skills --nexus-cards. Original roster/deck envelopes are classics/base33, single or paired one-family E1/E2, both selected Ix+CHOAM native families/union47, or standalone OR paired Ecaz/Moritani/ecaz33 with classics. Printed/native setup, first-Storm Tech, actual end-Mentat claims and all12 closing draws remain. Advanced paired E3/Moritani excludes Harkonnen; shared Duke never trains. Public starts, played-save conversion, mixed E3/three-family and pending effects remain separate.',
|
||||
'Fresh nexus --discoveries uses the original no-Skills envelopes above with optional Homeworlds, Tech3+ and Advanced Strongholds. Seven Discovery Spice Cards/eight tokens, protected nested sites, next-turn physical entry and actual Maker losses/votes/reserve ride remain. The card draw follows both Advanced piles and actual settled alliance change; earlier Shai-Hulud losses never repeat. Source-clear quotas, borrowed Guild tariffs and signed native one-invoice pairs at revealed sites use original controls, not new transport adapters.',
|
||||
'Without Skills, the existing generic Nexus initializer handles single and mixed selected E1/E2 natives, while paired one-family and paired E3 entries use their original paired initializer and require BOTH original natives. Native HMS/Face Dancers/Auditor/Richese cache, Ecaz ordinary discs/Loyalty/shared Duke and Advanced Moritani assassination remain physical. New overlays do not create a first Nexus hand, free native return, arbitrary marker companion or played-game conversion.',
|
||||
'The separate fresh local leader-skills --nexus-cards entry combines classic base33/all14 Skills/all12 Nexus in Basic or Advanced, two through six seats, optionally adding original Discovery7/8 through --discoveries. Original Tech requires three or more seats; Stronghold Cards require Advanced. Starting hands/offers, actual end-Spice closing draws, first-Storm Tech and end-Mentat held custody remain. Extra/ordinary free-three returns earn original phase-end Axlotl without changing skill custody. Emperor Cunning composes skill posture, support and Suk rescue; Arrakeen reduces payer cost, not committed support or rescue eligibility. Winner cleanup precedes mandatory Tech reward. Unrelated overlays and public starts remain guarded.',
|
||||
'The same fresh skill/Nexus entry supports single or paired Ixians/Tleilaxu OR CHOAM/Richese with classics and one original family deck/all14/all12, Basic/Advanced two through six seats. Selected original Tech requires three or more; Strongholds requires Advanced. Full Suboid Cunning composes typed skill rescue before equal actual Cyborg Tank substitution. Original held subsidy changes debit, not rescue support. Card cleanup and mandatory original-winner Tech precede Face Dance; a matching trainer dies and returns its skill once without another bounty, while held cards and tokens remain with the original winner. Partial Tleilaxu refresh preserves Mentat rights. Original signed Richese pair and CHOAM fuel/industry stay distinct. Original all14 Auditor exclusion and native-only optional own-disc revival training remain. Mixed families, E3, companions/mixed plans, native free-return accounting and pending rulings stay guarded.',
|
||||
'A separate standalone Ecaz OR Moritani skill/Nexus entry uses exact ecaz33/all14/all12 with classics, Basic/Advanced two through six seats, optionally original Homeworlds and Discovery; original Tech requires3+, Strongholds requires Advanced. Actual closing draws, five ordinary training discs, quiet living/unclaimed Duke Cunning and original Advanced assassination/normal-Traitor forfeiture remain. Native support/rescue, held effects, original card cleanup and mandatory winner Tech use existing handlers. Advanced Harkonnen, E3 pairs/mixed families/previews, Duke training/exceptional custody, enhanced Terror relocation/HMS/Grumman and other pending rulings stay guarded.',
|
||||
'The original all14 skill/Nexus envelope admits single or paired one-family E1/E2, BOTH selected Ix+CHOAM native families/union47, and standalone OR paired E3/ecaz33 with classics, Basic/Advanced2–6, optional Homeworlds/Discovery7/8/Tech3+/Advanced Strongholds. Full Suboid support composes winning typed fixed-loss Suk before equal actual Cyborg Tank substitution. Held subsidy changes debit, not rescue entitlement. Original cleanup/winner Tech precedes Face Dance; the replaced trainer dies/returns its skill once without another bounty, while earlier held rewards stay with the original winner. Original Auditor exclusion, signed Richese invoices, CHOAM fuel, native cache and pending-effect guards remain.',
|
||||
'Standalone OR paired Ecaz/Moritani original skill/Nexus entries use ecaz33/all14/all12 and classics, Basic/Advanced2–6, optional Homeworlds/Discovery/Tech3+/Advanced Strongholds. Each original roster/capture guard remains, including Advanced Harkonnen exclusion and no shared-Duke training. Quiet living/unclaimed Duke Cunning and native Advanced assassination use original distinct discs and exact continuation. In paired tables, native Ecaz may be a different opposing-faction assassination target; normal foreign-world Traitor prohibition does not become an assassination ban. Exceptional Duke custody, mixed E3/three-family, enhanced Terror/HMS/Grumman and pending effects remain separate.',
|
||||
'The original nexus entry also admits standalone Ecaz OR Moritani with classics, ecaz33/all12 and NO Skills, Basic/Advanced2–6, optionally Homeworlds, Discovery7/8, Tech3+ and Advanced Strongholds2+. Original Traitors/native setup precede a qualifying closing draw, with no starting Nexus hand. Quiet Duke Cunning stays separate from shared-disc training; no-Skills Ecaz may face Advanced Harkonnen without lifting the Cunning exclusion. Advanced Moritani excludes Harkonnen, retains post-loss private assassination/normal-call forfeiture and Mentat replacement, and uses supply-only Terror Cunning. Original Ecaz-selected coalition losses/payments and source-local held benefits/Tech remain. A sole loser token transfers automatically after cleanup; a real multi-token choice remains mandatory. Other native/mixed families, borrowed free-return/companion and relocation rulings, public starts and save conversion remain separate.',
|
||||
'Atreides Cunning adds a second, different opposing plan element after the first native answer. Both remain binding. Use it in your own battle before sealing your plan; Karama may cancel the extra attempt while preserving the first disclosure.',
|
||||
'With Atreides absent, Secret Ally inspects one opposing element in your battle. A sealed plan supplies only that selected answer automatically. Otherwise the opponent chooses an answer that permits a legal plan. Other players receive no private answer.',
|
||||
@@ -4460,11 +4454,11 @@ export const RULE_TOPICS: RuleTopic[] = [
|
||||
'When Moritani is absent, a defeated combatant with an eligible publicly played card receives the same postbattle choice whether or not they hold Moritani Nexus. An unallied holder may spend it to retain one played card that a winner could keep; other played cards follow ordinary discard. Without a publicly eligible card there is no prompt. The choice is after the battle result and before later income/capture; the public prompt protects hidden custody and is an interface inference. This Secret Ally effect has no invented ordinary Karama response. Native Moritani allied retention remains a different, cancelable ability.',
|
||||
'With actual Advanced Stronghold Cards, Arrakeen bank support changes the real payer debit, not personal income. Emperor Cunning temporary Sardaukar remain physically ordinary counters and retain ordinary Tanks custody. Original losing Moritani retention precedes mandatory original-winner Tech, then CHOAM inspection excludes used opposing cards even if retained. Ordinary city Collection remains separate; none of these windows repeats the original support, card cost or casualties.',
|
||||
'Ecaz Betrayal is available to an unallied holder with Ecaz seated and reciprocally allied in a shared Arrakis territory. At the opening of Shipment and Movement, choose one such territory; the ally returns its entire normal and starred force group from every sector there to reserves, leaving Ecaz forces in place. The Nexus card is spent before a Karama response. Cancellation preserves the board but not the card. Only the base/Ecaz Nexus roster without combined modules is supported.',
|
||||
'Ecaz Cunning lets an unallied native holder spend the physical Nexus card at a quiet Battle boundary to take the existing living, unclaimed Duke Vidal for the turn, even from Moritani. The Duke can be selected through ordinary Battle plans and is set aside after use or at turn end. The original paired Ecaz/Moritani Nexus-only profile and supported standalone Ecaz Nexus profile with classic opponents admit this bounded effect, with or without Skills and optional original Homeworlds, Discovery, Tech and Advanced Strongholds. Duke remains separate from training. Advanced Harkonnen is independently excluded even when the no-Skills roster is otherwise admitted. Taking Duke from the Tanks, capture or Ghola custody remains unimplemented. The Battle-only timing is a product boundary, not printed text.',
|
||||
'Ecaz Cunning lets an unallied native holder spend its physical Nexus at a quiet Battle boundary to take the existing living, unclaimed Duke for this turn, even from Moritani. Original standalone OR paired Ecaz/Moritani/classic Nexus profiles admit this bounded effect with or without Skills and optional Homeworlds/Discovery/Tech/Advanced Strongholds. The one shared Duke remains separate from ordinary training and is set aside after use or at turn end. Advanced Harkonnen is independently excluded even where standalone no-Skills roster admission otherwise permits it. Captured, dead or foreign-Ghola Duke custody and unqualified reaction timing remain guarded; this Battle boundary is the existing product interpretation, not a printed phase restriction.',
|
||||
'Fremen Betrayal has two bounded advance-declaration alternatives for an unallied holder in a classic Nexus table. Before the first Spice Blow or worm appearance, spend the physical card to prevent Fremen ordinary and Cunning worm rides for the turn; worm survival, destruction and Nexus still resolve. This clean timing is a product boundary, not an official post-appearance priority ruling. Instead, before Fremen move during Shipment and Movement, spend it to suppress their native two-territory advantage for that turn while ordinary movement and independent ornithopters remain. Only one alternative can be used even if the card is recycled later that turn. Owner controls show the currently available choice; combined modules and reactive post-worm timing remain gated.',
|
||||
'When Ecaz is absent, an unallied holder may spend its Nexus card at a quiet play boundary to ask whether any one player, including themself, holds one of the holder’s native faction leaders as an ordinary Traitor Card. The owner receives a private yes/no answer saved at the moment of use; no name or count is disclosed. Dead or captured native leaders count, but foreign Gholas, Duke Vidal, Cheap Hero and Face Dancers do not. Native-leader scope and private-only audience are explicit product interpretations, not publisher rulings; exceptional controlled-leader and public-disclosure combinations remain open.',
|
||||
'When Richese is absent, its Secret Ally replaces your ordinary reserve shipment with up to five physical forces charged as one. Select the explicit shipment checkbox; forces, elite identity, destination restrictions, Homeworld reserve sources and normal movement remain unchanged. Fremen remain free within their normal reinforcement range; Guild and an active Karama rate retain their existing tariff and payment routing. This is not a concealed No-Field or an extra shipment.',
|
||||
'Native Richese Cunning has a bounded two-No-Field shipment in genuine Richese/CHOAM Nexus games, including supported fresh Discovery/Tech/Advanced Strongholds without Skills or with the paired all14 Skills composition. Choose distinct unused tokens: one reveals immediately into reserve-capped public forces, the other remains concealed; pay for one marker and spend the Nexus. The previous shipment token cannot be either selection; the concealed token becomes next last-used. Both compositions retain the original signed pair frame and native response/Guild continuation, not a single-marker proof or free companion. A nested destination must remain currently revealed. Karama or Guild prevention preserves physical tokens and unpaid spice, with the original stopped-shipment policy. When Tech is selected, an accepted off-planet pair accrues Heighliners once at phase end. Other module combinations, mixed dialing and full faceup-component display remain gated.',
|
||||
'Native Richese Cunning uses the original signed two-No-Field shipment in supported single/paired E2 or selected mixed Ix+CHOAM native Nexus tables with classics, optional Skills/Homeworlds/Discovery/Tech/Advanced Strongholds. Select two distinct unused physical tokens: one reveals immediately into reserve-capped forces, one remains concealed; pay one marker invoice and spend the Nexus. The previous shipment token cannot be either choice, and the concealed one becomes last-used. Native/Guild response and actual payer/counter sources remain; a nested destination must be revealed. Prevention keeps physical tokens and unpaid spice, after any printed card cost. Sandtrout, arbitrary companions, shared allocation and other pending combinations retain their guards.',
|
||||
'Richese Betrayal has a separate opt-in auction preview. Before payment, an unallied rival may spend its physical Richese Nexus card to discard a public self-cache win without any purchase debit, or redirect another buyer’s cache/Black Market payment to the bank while preserving delivery and earned bonus. Every publicly possible holder acknowledges the same opportunity; private Use eligibility cannot determine public timing. Normal hidden self-purchases and private special-Karama acquisitions are not connected. See the dedicated guide for its existing local runtime/browser evidence and remaining release gates; that evidence does not verify Nexus Kull.',
|
||||
'Guild Cunning is declared when finishing your ordinary Shipment and Movement turn. It spends the Nexus and opens one Karama response. Allowance grants a second native shipment at normal Guild prices, including supported cross-shipment, return and Homeworld routes. Cancellation leaves the completed first turn intact. Only an unused Hajr move can follow the second shipment; no ordinary movement or third move is granted. The physical Ornithopter card combination remains unavailable. The separate guild-betrayal profile admits only original native shipment producers and explicitly blocks this second-shipment offer before Nexus spending; Cunning outside that profile is unchanged.',
|
||||
'With Guild absent, its Secret Ally is an explicit optional source for one ordinary shipment at Guild prices. It supports physical reserve shipment, cross-shipment and return to abstract reserves, plus half-price independently legal world-to-world shipment. Fremen may retain free reinforcement or choose the paid card route beyond its normal range, outside the storm. Native faction, typed sources and normal movement stay unchanged. Homeworld reserve return awaits a ruling; arbitrary foreign-world transport and concealed No-Fields are not granted.',
|
||||
@@ -4479,7 +4473,7 @@ export const RULE_TOPICS: RuleTopic[] = [
|
||||
{ area: 'Player controls', status: 'Partial', detail: 'Private lifecycle, inspections, exchanges, Tleilaxu refresh, Ixian activation, advisor selection, temporary Sardaukar and CHOAM effects, Moritani Betrayal, Ecaz Betrayal and owner-only Secret Ally inquiry, native Duke Cunning, Richese shipment and bounded auction Betrayal, Emperor purchase and Fremen Cunning controls are connected. Remaining effect controls are unfinished.', evidence: ['components/nexus-cards.tsx', 'components/nexus-traitors.tsx', 'components/nexus-tleilaxu.tsx', 'components/nexus-suboids.tsx', 'components/nexus-advisors.tsx', 'components/nexus-sardaukar.tsx', 'components/choam-power-cost.tsx', 'components/moritani-terror.tsx', 'components/nexus-moritani-betrayal.tsx', 'components/nexus-ecaz-betrayal.tsx', 'components/nexus-ecaz-inquiry.tsx', 'components/nexus-ecaz-duke.tsx', 'components/nexus-richese-betrayal.tsx', 'components/game-table.tsx'] },
|
||||
{ area: 'AI', status: 'Partial', detail: 'All four profiles choose legal actions through private offers, including Moritani/Ecaz Betrayal, Ecaz Secret Ally inquiry and native Duke Cunning, Fremen Cunning, Emperor purchase and bounded Richese auction Betrayal. Complete module strategy and calibration remain unfinished.', evidence: ['game/nexus-card-options.ts', 'game/nexus-traitor-options.ts', 'game/nexus-tleilaxu-options.ts', 'game/nexus-suboid-options.ts', 'game/nexus-advisor-options.ts', 'game/nexus-sardaukar-options.ts', 'game/choam-power-options.ts', 'game/nexus-moritani-options.ts', 'game/nexus-moritani-betrayal-options.ts', 'game/nexus-ecaz-betrayal-options.ts', 'game/nexus-ecaz-inquiry-options.ts', 'game/nexus-ecaz-duke-options.ts', 'game/nexus-richese-options.ts', 'game/bot-nexus-richese-betrayal.ts', 'game/nexus-guild-cunning-options.ts', 'game/bots.ts'] },
|
||||
{ area: 'Documentation', status: 'Partial', detail: 'Common rules, twelve printed faces and bounded runtime contracts retain explicit unresolved Ecaz Duke capture/Tanks/Ghola and inquiry audience/scope, Fremen nested Cunning, Great Maker, combined modules, fresh advisors, storm and borrowed Voice. Richese auction Betrayal has a separate cost/prepayment/privacy contract and excluded-producer boundaries. Guild Betrayal separately records full funded payment, own pre-funding, donor escrow once, the printed full-Junction override, four native adapters and neutral privacy; ordinary occupation/rounding and general response-priority questions remain unresolved.', evidence: ['docs/NEXUS_CARD_RULES.md', 'docs/NEXUS_ATREIDES_RULES.md', 'docs/NEXUS_HARKONNEN_RULES.md', 'docs/NEXUS_TLEILAXU_RULES.md', 'docs/NEXUS_IXIAN_CUNNING_RULES.md', 'docs/NEXUS_CUNNING_RUNTIME.md', 'docs/NEXUS_BENE_GESSERIT_RULES.md', 'docs/NEXUS_ADVISOR_RUNTIME.md', 'docs/NEXUS_EMPEROR_RULES.md', 'docs/NEXUS_SARDAUKAR_RUNTIME.md', 'docs/NEXUS_FREMEN_RULES.md', 'docs/NEXUS_ECAZ_RULES.md', 'docs/NEXUS_CHOAM_RULES.md', 'docs/NEXUS_CHOAM_RUNTIME.md', 'docs/NEXUS_MORITANI_RULES.md', 'docs/NEXUS_MORITANI_RUNTIME.md', 'docs/NEXUS_RICHESE_RUNTIME.md', 'docs/NEXUS_RICHESE_RULES.md', 'docs/NEXUS_GUILD_CUNNING_RUNTIME.md', 'docs/NEXUS_GUILD_RULES.md'] },
|
||||
{ area: 'Verification', status: 'Partial', detail: 'Single-native E1/E2 adds15 semantic programmes/398 affected checks across35 files, types/lint pass. All32 original six-seat families finish190/192 games with208205/208213 actions and5539 JSON across two frozen trees, including one repaired original bare-Skills Smuggler continuation. Exhausted-cache/low-Tupile source guards remain. Actual390px original trained Ixian offer/typed entry, Maker/both-pile draw, free Suboid support/equal nested Cyborg exchange and no-training Richese one-invoice5+3/reveal preserve20 physical counters. Earlier source-qualified evidence remains canonical, not new assurance or complete-mode/deployed certification.', evidence: ['tests/single-nexus-e1-runtime.test.ts', 'tests/single-nexus-e2-runtime.test.ts', 'tests/e3-nexus-ecaz-runtime.test.ts', 'tests/e3-nexus-moritani-runtime.test.ts', 'tests/homeworld-classic-nexus-skills-runtime.test.ts', 'tests/homeworld-classic-discovery-nexus-runtime.test.ts', 'tests/nexus-cards.test.ts', 'tests/nexus-card-engine.test.ts', 'tests/nexus-fremen-cunning.test.ts', 'tests/nexus-fremen-cunning-recovery.test.ts', 'tests/nexus-fremen-cunning-summon.test.ts', 'tests/nexus-fremen-cunning-summon-recovery.test.ts', 'tests/nexus-ecaz-betrayal-quotes.test.ts', 'tests/nexus-ecaz-betrayal.test.ts', 'tests/nexus-ecaz-betrayal-recovery.test.ts', 'tests/nexus-ecaz-inquiry.test.ts', 'tests/nexus-ecaz-duke-quote.test.ts', 'tests/nexus-ecaz-duke-engine.test.ts', 'tests/nexus-ecaz-duke-controls.test.ts', 'tests/nexus-ecaz-duke-recovery.test.ts', 'tests/nexus-traitor-recovery.test.ts', 'tests/nexus-face-dancer-engine.test.ts', 'tests/nexus-suboids-engine.test.ts', 'tests/normal-free-support.test.ts', 'tests/nexus-suboid-controls.test.ts', 'tests/nexus-advisor-controls.test.ts', 'tests/nexus-advisor-bots.test.ts', 'tests/nexus-sardaukar-controls.test.ts', 'tests/nexus-sardaukar-bots.test.ts', 'tests/nexus-choam-controls.test.ts', 'tests/nexus-choam-bots.test.ts', 'tests/nexus-moritani-controls.test.ts', 'tests/nexus-moritani-bots.test.ts', 'tests/nexus-moritani-betrayal.test.ts', 'tests/nexus-richese-controls.test.ts', 'tests/nexus-richese-bots.test.ts', 'tests/nexus-richese-betrayal-engine.test.ts', 'tests/nexus-richese-betrayal-recovery.test.ts', 'tests/nexus-guild-cunning-controls.test.ts', 'tests/nexus-guild-cunning-bots.test.ts', 'tests/nexus-module-payments-runtime.test.ts', 'tests/nexus-module-battles-runtime.test.ts', 'tests/paired-ix-nexus-modules-runtime.test.ts', 'tests/paired-choam-nexus-modules-runtime.test.ts', 'tests/classic-nexus-skills-payments-runtime.test.ts', 'tests/classic-nexus-skills-battles-runtime.test.ts', 'tests/nexus-skills-modules-payments-runtime.test.ts', 'tests/nexus-skills-modules-battles-runtime.test.ts', 'tests/paired-ix-nexus-skills-modules-runtime.test.ts', 'tests/paired-choam-nexus-skills-modules-runtime.test.ts', 'tests/ecaz-nexus-skills-modules-runtime.test.ts', 'tests/moritani-nexus-skills-modules-runtime.test.ts', 'docs/NEXUS_CARD_RULES.md'] },
|
||||
{ area: 'Verification', status: 'Partial', detail: 'Mixed E1/E2 and paired E3 adds31 physical programmes plus2 Loyalty-stock regressions, final489/489 affected checks across42 files and types/lint. All64 original six-seat families finish258/288 games with338931/339426 actions and9013 JSON across three frozen trees and preserved-prefix continuations. Native Ecaz assassination, separate physical Loyalty stock and exact paired overlap admission are repaired; all30 remaining traces retain printed source guards. Actual390px original human Ixian offer/training, typed shipment/free Suboid plan and paired Ecaz foreign arrival/living shared Duke preserve20 counters. Earlier evidence remains canonical; not complete modes, new assurance or protected deployed acceptance.', evidence: ['tests/mixed-nexus-modules-runtime.test.ts', 'tests/paired-e3-nexus-modules-runtime.test.ts', 'tests/sample-custody.test.ts', 'tests/ambassador-terror-overlap-engine.test.ts', 'tests/single-nexus-e1-runtime.test.ts', 'tests/single-nexus-e2-runtime.test.ts', 'tests/e3-nexus-ecaz-runtime.test.ts', 'tests/e3-nexus-moritani-runtime.test.ts', 'tests/homeworld-classic-nexus-skills-runtime.test.ts', 'tests/homeworld-classic-discovery-nexus-runtime.test.ts', 'tests/nexus-cards.test.ts', 'tests/nexus-card-engine.test.ts', 'tests/nexus-fremen-cunning.test.ts', 'tests/nexus-fremen-cunning-recovery.test.ts', 'tests/nexus-fremen-cunning-summon.test.ts', 'tests/nexus-fremen-cunning-summon-recovery.test.ts', 'tests/nexus-ecaz-betrayal-quotes.test.ts', 'tests/nexus-ecaz-betrayal.test.ts', 'tests/nexus-ecaz-betrayal-recovery.test.ts', 'tests/nexus-ecaz-inquiry.test.ts', 'tests/nexus-ecaz-duke-quote.test.ts', 'tests/nexus-ecaz-duke-engine.test.ts', 'tests/nexus-ecaz-duke-controls.test.ts', 'tests/nexus-ecaz-duke-recovery.test.ts', 'tests/nexus-traitor-recovery.test.ts', 'tests/nexus-face-dancer-engine.test.ts', 'tests/nexus-suboids-engine.test.ts', 'tests/normal-free-support.test.ts', 'tests/nexus-suboid-controls.test.ts', 'tests/nexus-advisor-controls.test.ts', 'tests/nexus-advisor-bots.test.ts', 'tests/nexus-sardaukar-controls.test.ts', 'tests/nexus-sardaukar-bots.test.ts', 'tests/nexus-choam-controls.test.ts', 'tests/nexus-choam-bots.test.ts', 'tests/nexus-moritani-controls.test.ts', 'tests/nexus-moritani-bots.test.ts', 'tests/nexus-moritani-betrayal.test.ts', 'tests/nexus-richese-controls.test.ts', 'tests/nexus-richese-bots.test.ts', 'tests/nexus-richese-betrayal-engine.test.ts', 'tests/nexus-richese-betrayal-recovery.test.ts', 'tests/nexus-guild-cunning-controls.test.ts', 'tests/nexus-guild-cunning-bots.test.ts', 'tests/nexus-module-payments-runtime.test.ts', 'tests/nexus-module-battles-runtime.test.ts', 'tests/paired-ix-nexus-modules-runtime.test.ts', 'tests/paired-choam-nexus-modules-runtime.test.ts', 'tests/classic-nexus-skills-payments-runtime.test.ts', 'tests/classic-nexus-skills-battles-runtime.test.ts', 'tests/nexus-skills-modules-payments-runtime.test.ts', 'tests/nexus-skills-modules-battles-runtime.test.ts', 'tests/paired-ix-nexus-skills-modules-runtime.test.ts', 'tests/paired-choam-nexus-skills-modules-runtime.test.ts', 'tests/ecaz-nexus-skills-modules-runtime.test.ts', 'tests/moritani-nexus-skills-modules-runtime.test.ts', 'docs/NEXUS_CARD_RULES.md'] },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -4662,7 +4656,7 @@ export const RULE_TOPICS: RuleTopic[] = [
|
||||
developmentStage: 'Prototyped',
|
||||
summary: 'Fourteen physical skills, private assignment choices, five battle disciplines, Planetologist movement/battle effects and Suk Graduate rescues, Mentat/Bureaucrat scoring and Bureaucrat payment redirection, Sandmaster victory spice, Rihani exchanges, optional Smuggler shipping and unmodified battle collection, Sandmaster route and worm-ride collection, sealed Spice Banker battle spending and optional Diplomat base-defense copying in development tables. Other effects and combined-module acceptance remain unfinished.',
|
||||
steps: [
|
||||
'Fresh Leader Skills retains Homeworlds in Basic/Advanced two through six classic or supported native E1/E2 seats, or standalone Ecaz OR Moritani with classic opponents, and all fourteen original offers, optionally original Discovery7/8, Tech at three or more seats and Advanced Stronghold Cards. Only classic factions additionally compose all12 Nexus through --nexus-cards. Native placement follows training, including the original Ixian pre-training card choice. Normal/trained Suk uses actual native, visitor or nested physical pools; native saved counters remain at that home. External Emperor returns explicitly allocate ordinary/elite counters to actual native homes, an implementation interpretation rather than ordinary revival placement. Exact-three Fremen Nexus revival separately deposits ordinary Emperor counters at Kaitain and Sardaukar at Salusa through the printed native return rule. Actual residual Cyborg Tanks feed optional equal Suboid substitution after rescue. Support precedes rescue; later Cistern income, source-local held effects and mandatory winner Tech after original cleanup stay separate. Bureaucrat invoices and minimal legal bots are connected. Native Homeworld/Nexus, unsupported E3 pairs/mixed families, unrelated overlays and pending interactions stay separate.',
|
||||
'Fresh all14 Leader Skills preserves original classic, supported E1/E2 or standalone Ecaz OR Moritani setup with Homeworlds/Discovery/Tech3+/Advanced Strongholds under each envelope. Explicit --nexus-cards additionally admits single/paired one-family E1/E2, BOTH selected Ix+CHOAM native families/union47 and standalone OR paired Ecaz/Moritani/ecaz33 with classics. Basic/Advanced2–6, original Ix pre-training offer, ordinary native discs and actual hands remain; Auditor/shared Duke never train. Winning normal/trained Suk uses source-labelled native, visitor or nested fixed-loss pools; native saved counters stay at that home and external Emperor returns allocate original homes. Original phase-end industry, held benefits, cleanup/Tech before Face Dance and native assassination remain; unreconciled bands, mixed E3/three-family, public starts and played-save conversion stay separate.',
|
||||
'Basic Moritani retains base opponents including Harkonnen. Its separate bounded Advanced classic/non-Harkonnen roster now composes the original assassination preview and all fourteen skills: winner Suk rescue and Rihani choice finish first, then an eligible different trained disc may be assassinated with its exact card return and printed bounty. No casualties repeat; original set-aside and one private Mentat replacement remain. See Moritani with Leader Skills for the exact scope.',
|
||||
'Fresh Advanced profiles compose native Ixians, Tleilaxu, CHOAM and/or Richese with classic opponents and distinct required family decks. All fourteen skills and native starts remain. Auditor stays unskilled; cyborg casualties, original CHOAM support and Richese capped marker revelation remain physical. Foreign revival creates no new skill. Native Ixian Technology on Richese lots, own mixed No-Field, captured replacement, Advanced Atreides Suk/KH and unrelated overlays retain their guards.',
|
||||
'Fresh three-through-six-seat Basic/Advanced development tables may compose all fourteen Skills with original Tech Tokens: classic factions, supported E1/E2 native families, or standalone Ecaz/Moritani with the exact ecaz deck and original roster exclusions. Starting cards/cache, skill/Traitor choices and printed/first-Storm assignment stay genuine. Existing leader-skills/banker-income entry preserves unused selected tokens; mixed E3 families, other overlays, public activation and saved-game conversion remain separate.',
|
||||
|
||||
Reference in new issue
Block a user