Support selected Nexus decks with leader skills
Verify and publish checkpoint container / container (push) Successful in 11m54s

This commit is contained in:
Quintine committed 2026-10-29 20:26:46 +11:00
1 parent 91d45d1dec
commit 00e01a7cd2
13 files changed
+314 -23

No files matched your search

+2 -2
View File
@@ -1,4 +1,4 @@
import { homeworldLeaderSkillsProfile, independentTreacheryLeaderSkillsProfile, classicNexusLeaderSkillsProfile, classicTechLeaderSkillsProfile, guildBetrayalNexusLeaderSkillsProfile, mixedE1E2NexusLeaderSkillsProfile, mixedE3NexusLeaderSkillsProfile, nativeDiscoveryLeaderSkillsProfile, nativeExpansionLeaderSkillsProfile, nativeTechLeaderSkillsProfile, noOtherLeaderSkillModules, pairedE3NexusLeaderSkillsProfile, pairedNexusLeaderSkillsProfile, standaloneE3NexusLeaderSkillsProfile, strongholdLeaderSkillsProfile, type LeaderSkillProfile } from './leader-skill-profile';
import { homeworldLeaderSkillsProfile, independentTreacheryLeaderSkillsProfile, classicNexusLeaderSkillsProfile, classicTechLeaderSkillsProfile, guildBetrayalNexusLeaderSkillsProfile, mixedE1E2NexusLeaderSkillsProfile, mixedE3NexusLeaderSkillsProfile, nativeDiscoveryLeaderSkillsProfile, nativeExpansionLeaderSkillsProfile, nativeTechLeaderSkillsProfile, noOtherLeaderSkillModules, pairedE3NexusLeaderSkillsProfile, pairedNexusLeaderSkillsProfile, selectedNexusLeaderSkillsProfile, standaloneE3NexusLeaderSkillsProfile, strongholdLeaderSkillsProfile, type LeaderSkillProfile } from './leader-skill-profile';
import { classicDiscoveryLeaderSkillsProfile } from './discovery-module-profile';
export type BureaucratPaymentKind = 'auction' | 'shipment' | 'bribe' | 'revival';
export type BureaucratPaymentSource = {
@@ -46,7 +46,7 @@ export function bureaucratPaymentModeSupported(game: LeaderSkillProfile): boolea
return independentTreacheryLeaderSkillsProfile(game) || (!game.homeworlds && game.expansions.length === 1 &&
(game.expansions[0] === 'choam' || game.expansions[0] === 'ix') &&
pairedNexusLeaderSkillsProfile(game)) ||
mixedE3NexusLeaderSkillsProfile(game) || mixedE1E2NexusLeaderSkillsProfile(game) || pairedE3NexusLeaderSkillsProfile(game) ||
selectedNexusLeaderSkillsProfile(game) || mixedE3NexusLeaderSkillsProfile(game) || mixedE1E2NexusLeaderSkillsProfile(game) || pairedE3NexusLeaderSkillsProfile(game) ||
guildBetrayalNexusLeaderSkillsProfile(game) ||
(noOtherLeaderSkillModules(game) &&
(!game.expansions.length ||
+3 -3
View File
@@ -60,11 +60,11 @@ export function independentDiscoveryNexusProfile(game: NexusCoreConfiguration):
}
/** Original selected decks do not require their native factions or the
* independent three-card variant. Keep Skills and hidden E3/Harkonnen
* compositions on their existing separately scoped paths. */
* independent three-card variant. Hidden E3/Harkonnen compositions retain
* their existing separately scoped paths. */
export function selectedNexusWithoutCardsProfile(game: NexusCoreConfiguration): boolean {
const players = game.players;
if (game.ecazTreachery || game.leaderSkills || !game.nexusCards || !players ||
if (game.ecazTreachery || !game.nexusCards || !players ||
!game.expansions.length || !nexusCoreRosterProfile(game, true, game.discoveryEnabled === true)) return false;
if (game.advanced && players.some(player => player.faction === 'harkonnen') &&
players.some(player => player.faction === 'ecaz' || player.faction === 'moritani')) return false;
+15 -7
View File
@@ -1,5 +1,5 @@
import { FACTIONS } from './catalog';
import { independentDiscoveryProfile, independentNexusProfile, classicNexusCoreProfile, nexusCoreProfile, mixedE3NexusRosterProfile } from './faction-module-profile';
import { independentDiscoveryProfile, independentNexusProfile, classicNexusCoreProfile, nexusCoreProfile, mixedE3NexusRosterProfile, selectedNexusWithoutCardsProfile } from './faction-module-profile';
import { classicDiscoveryLeaderSkillsProfile } from './discovery-module-profile';
/** Public configuration only; never gate a skill on a hidden card or random deal. */
@@ -204,6 +204,13 @@ export function mixedE3NexusLeaderSkillsProfile(game: LeaderSkillProfile): boole
mixedE3NexusRosterProfile(game, true);
}
/** Original selected decks with Nexus and Skills do not require a seat from
* every selected family. Keep independent cards and other previews on their
* own paths, including the Advanced hidden E3/Harkonnen capture boundary. */
export function selectedNexusLeaderSkillsProfile(game: LeaderSkillProfile): boolean {
return selectedNexusWithoutCardsProfile(game);
}
/** 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 {
@@ -298,7 +305,7 @@ export function classicTechLeaderSkillsProfile(game: LeaderSkillProfile): boolea
export function strongholdLeaderSkillsProfile(game: LeaderSkillProfile): boolean {
if (!game.strongholdCards || game.advanced !== true) return false;
if (independentTreacheryLeaderSkillsProfile(game)) return true;
if (game.expansions.length) return selectedDeckLeaderSkillsProfile(game) ||
if (game.expansions.length) return selectedNexusLeaderSkillsProfile(game) || selectedDeckLeaderSkillsProfile(game) ||
advancedMoritaniLeaderSkillsProfile(game) || nativeEcazLeaderSkillsProfile(game);
const players = game.players;
if (!players || players.length < (game.techTokens ? 3 : 2) || players.length > 6 ||
@@ -321,7 +328,7 @@ export function strongholdLeaderSkillsProfile(game: LeaderSkillProfile): boolean
/** Bounded integration of the ordinary Moritani roster, not Advanced assassination. */
export function basicMoritaniLeaderSkillsProfile(game: LeaderSkillProfile): boolean {
if (game.advanced === false && game.players?.some(player => player.faction === 'moritani') &&
selectedDeckLeaderSkillsProfile(game)) return true;
(selectedNexusLeaderSkillsProfile(game) || selectedDeckLeaderSkillsProfile(game))) return true;
return game.advanced === false && game.expansions.length === 1 &&
game.expansions[0] === 'ecaz' && e3LeaderSkillModulesSupported(game) &&
!!game.players?.some(player => player.faction === 'moritani') &&
@@ -332,7 +339,7 @@ export function basicMoritaniLeaderSkillsProfile(game: LeaderSkillProfile): bool
/** Existing bounded Advanced assassination roster, composed with native skills. */
export function advancedMoritaniLeaderSkillsProfile(game: LeaderSkillProfile): boolean {
if (game.advanced === true && game.players?.some(player => player.faction === 'moritani') &&
selectedDeckLeaderSkillsProfile(game)) return true;
(selectedNexusLeaderSkillsProfile(game) || selectedDeckLeaderSkillsProfile(game))) return true;
const players = game.players;
if (game.advanced !== true || game.expansions.length !== 1 ||
game.expansions[0] !== 'ecaz' || !players || players.length < 2 || players.length > 6 ||
@@ -358,7 +365,8 @@ export function advancedMoritaniLeaderSkillsProfile(game: LeaderSkillProfile): b
/** Ecaz's five native discs; the separate temporarily controlled Duke is not an assignment disc. */
export function nativeEcazLeaderSkillsProfile(game: LeaderSkillProfile): boolean {
if (game.players?.some(player => player.faction === 'ecaz') && selectedDeckLeaderSkillsProfile(game)) return true;
if (game.players?.some(player => player.faction === 'ecaz') &&
(selectedNexusLeaderSkillsProfile(game) || selectedDeckLeaderSkillsProfile(game))) return true;
const players = game.players;
if (typeof game.advanced !== 'boolean' || game.expansions.length !== 1 ||
game.expansions[0] !== 'ecaz' || !players || players.length < 2 || players.length > 6 ||
@@ -434,7 +442,7 @@ export function selectedDeckLeaderSkillsProfile(game: LeaderSkillProfile): boole
export function nativeExpansionLeaderSkillsProfile(game: LeaderSkillProfile): boolean {
return (game.expansions.length > 0 && independentTreacheryLeaderSkillsProfile(game)) ||
mixedE3NexusLeaderSkillsProfile(game) || mixedE1E2NexusLeaderSkillsProfile(game) || pairedE3NexusLeaderSkillsProfile(game) ||
selectedNexusLeaderSkillsProfile(game) || mixedE3NexusLeaderSkillsProfile(game) || mixedE1E2NexusLeaderSkillsProfile(game) || pairedE3NexusLeaderSkillsProfile(game) ||
basicMoritaniLeaderSkillsProfile(game) || selectedDeckLeaderSkillsProfile(game) ||
advancedMoritaniLeaderSkillsProfile(game) || nativeEcazLeaderSkillsProfile(game);
}
@@ -529,7 +537,7 @@ export function ordinaryLeaderSkillModeSupported(game: LeaderSkillProfile): bool
(!game.expansions.length || nativeExpansionLeaderSkillsProfile(game) ||
(game.expansions.length === 1 && game.expansions[0] === 'choam'))) ||
classicTechLeaderSkillsProfile(game) || nativeTechLeaderSkillsProfile(game) ||
strongholdLeaderSkillsProfile(game) || classicNexusLeaderSkillsProfile(game) ||
strongholdLeaderSkillsProfile(game) || classicNexusLeaderSkillsProfile(game) || selectedNexusLeaderSkillsProfile(game) ||
guildBetrayalNexusLeaderSkillsProfile(game) ||
singleE1E2NexusLeaderSkillsProfile(game) ||
mixedE3NexusLeaderSkillsProfile(game) || mixedE1E2NexusLeaderSkillsProfile(game) || pairedE3NexusLeaderSkillsProfile(game) ||
+1 -1
View File
@@ -6294,7 +6294,7 @@ export const RULE_TOPICS: RuleTopic[] = [
'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 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 include classics/base33, selected E1/E2 natives/union47 and standalone, paired or mixed E3 native families. Printed/native setup, first-Storm Tech, actual end-Mentat claims and all12 closing draws remain. Original no-Skills E3 Nexus now admits Advanced Harkonnen; Skills retains its Harkonnen exclusion and shared Duke never trains. Public starts, played-save conversion and pending effects remain separate.',
'Fresh selected-deck Nexus previews also admit an unseated selected family without independent Ecaz cards, with optional Discovery. Leader Skills and Advanced Harkonnen with Ecaz or Moritani retain their separate restrictions; wider interactions and complete-mode acceptance remain open.',
'Fresh selected-deck Nexus previews also admit an unseated selected family without independent Ecaz cards, with optional Leader Skills and Discovery. Advanced Harkonnen with Ecaz or Moritani retains its separate restriction; wider interactions and complete-mode acceptance remain open.',
'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.',