Compose independent Ecaz cards with selected phase modules
This commit is contained in:
1 parent
68a7870e2e
commit
0a98a92f4b
17 files changed
+733
-15
No files matched your search
+4
-3
@@ -16,7 +16,7 @@ import { movementShipmentPreparations } from './movement-shipment-preparation';
|
||||
import { MovementClaimError, liveMovementPromises, movementEventAllowed, movementPromiseModeSupported, movementPromiseTargetAvailable, settleMovementEvent, finishMovementPromises, validMovementClaim, type MovementClaim, type MovementPromise } from './movement-promises';
|
||||
import { findMovementCompletion, type MovementCompletion } from './movement-promise-search';
|
||||
import { classicNexusModulesProfile, mixedE1E2NexusProfile, mixedE3NexusProfile, pairedE3NexusProfile, pairedNexusModulesProfile, singleE1E2NexusProfile, standaloneE3NexusProfile } from './nexus-module-profile';
|
||||
import { independentDiscoveryProfile, independentNexusProfile, nexusCoreProfile, nativeFactionTechProfile, selectedFactionStrongholdProfile } from './faction-module-profile';
|
||||
import { independentDiscoveryProfile, independentNexusProfile, nexusCoreProfile, nativeFactionTechProfile, selectedFactionStrongholdProfile, selectedIndependentCardsProfile } from './faction-module-profile';
|
||||
import { classicDiscoveryLeaderSkillsProfile, classicDiscoveryNexusProfile, homeworldDiscoveryProfile, discoveryModeSupported, discoveryModuleProfile, mixedE1E2DiscoveryNexusProfile, mixedE3DiscoveryNexusProfile, pairedDiscoveryNexusProfile, pairedE3DiscoveryNexusProfile, singleE1E2DiscoveryNexusProfile, standaloneE3DiscoveryNexusProfile } from './discovery-module-profile';
|
||||
import { advancedMoritaniLeaderSkillsProfile, selectedDeckLeaderSkillsProfile, homeworldLeaderSkillsProfile, independentTreacheryLeaderSkillsProfile, classicNexusLeaderSkillsProfile, classicTechLeaderSkillsProfile, guildBetrayalNexusLeaderSkillsProfile, mixedE1E2NexusLeaderSkillsProfile, mixedE3NexusLeaderSkillsProfile, nativeDiscoveryLeaderSkillsProfile, nativeEcazLeaderSkillsProfile, nativeExpansionLeaderSkillsProfile, nativeTechLeaderSkillsProfile, ordinaryLeaderSkillModeSupported, pairedE3LeaderSkillsProfile, pairedE3NexusLeaderSkillsProfile, pairedNexusLeaderSkillsProfile, singleE1E2NexusLeaderSkillsProfile, standaloneE3NexusLeaderSkillsProfile, strongholdLeaderSkillsProfile } from './leader-skill-profile';
|
||||
import { bribeTimingBlock, maximumBribe, type BribeOptions } from './bribe-options';
|
||||
@@ -11852,8 +11852,8 @@ function ecazOccupyCompositionSupported(g: Game): boolean {
|
||||
// Native Basic uses the same physical coalition and selected decks.
|
||||
// Family/roster checks below remain authoritative; optional configurations
|
||||
// retain their separate registered profiles rather than inheriting admission.
|
||||
const basicNatives = g.advanced === false &&
|
||||
!g.ecazTreachery && (!g.techTokens || nativeFactionTechProfile(g)) && !g.strongholdCards;
|
||||
const basicNatives = g.advanced === false && !g.strongholdCards &&
|
||||
((!g.ecazTreachery && (!g.techTokens || nativeFactionTechProfile(g))) || selectedIndependentCardsProfile(g));
|
||||
if ((independentNexusProfile(g) || independentDiscoveryProfile(g)) && byFaction(g, 'ecaz')) return true;
|
||||
if (g.leaderSkills && nativeEcazLeaderSkillsProfile(g)) return true;
|
||||
if (g.ecazOccupyPreview === true && (mixedE3NexusProfile(g) || standaloneE3NexusProfile(g) || pairedE3NexusProfile(g)) &&
|
||||
@@ -12128,6 +12128,7 @@ function ecazHomeworldProfile(g: Game): boolean {
|
||||
}
|
||||
/** Independent cards compose original phase modules, not unrelated previews. */
|
||||
function independentCardModulesProfile(g: Game): boolean {
|
||||
if ((g.techTokens || g.strongholdCards) && selectedIndependentCardsProfile(g)) return true;
|
||||
if ((g.techTokens || g.strongholdCards) && (independentNexusProfile(g) || independentDiscoveryProfile(g))) return true;
|
||||
if ((g.techTokens || g.strongholdCards) && g.leaderSkills && !g.sandtrout &&
|
||||
independentTreacheryLeaderSkillsProfile(g)) return true;
|
||||
|
||||
@@ -15,6 +15,8 @@ export type FactionModuleProfile = {
|
||||
discoveryStash?: unknown;
|
||||
greatMaker?: unknown;
|
||||
ecazTreachery?: unknown;
|
||||
sandtrout?: unknown;
|
||||
spiceBankerIncomePreview?: unknown;
|
||||
semutaPreview?: unknown;
|
||||
advancedPreview?: unknown;
|
||||
kullPreview?: unknown;
|
||||
@@ -132,11 +134,11 @@ export function selectedPhaseModuleRoster(
|
||||
/** Keep unrelated overlays outside this phase-only permission. Semuta's caller
|
||||
* additionally retains its old roster envelope below, rather than inheriting
|
||||
* new selected-family admission through its explicit context flag. */
|
||||
function phaseModuleContext(game: FactionModuleProfile, semuta = false): boolean {
|
||||
function phaseModuleContext(game: FactionModuleProfile, semuta = false, independent = false): boolean {
|
||||
return typeof game.advanced === 'boolean' &&
|
||||
!(game.strongholdCards && !game.advanced) && !game.leaderSkills &&
|
||||
!game.homeworlds && !game.nexusCards && !game.discoveryEnabled && !game.discoveries &&
|
||||
!game.discoveryStash && !game.greatMaker && !game.ecazTreachery &&
|
||||
!game.discoveryStash && !game.greatMaker && (independent ? game.ecazTreachery === true : !game.ecazTreachery) &&
|
||||
(!game.semutaPreview || (semuta && game.semutaPreview === true)) &&
|
||||
!game.advancedPreview && !game.kullPreview && !game.nexusKullPreview &&
|
||||
!game.guildBetrayalPreview && !game.richeseBetrayalPreview &&
|
||||
@@ -193,6 +195,19 @@ export function selectedFactionStrongholdProfile(game: FactionModuleProfile): bo
|
||||
selectedPhaseModuleRoster(game) && (!game.techTokens || game.players.length >= 3);
|
||||
}
|
||||
|
||||
/** Independent physical cards with optional original phase modules. This is a
|
||||
* selected-deck permission; base-only, World and trained compositions retain
|
||||
* their separate original profiles and physical freshness stays external. */
|
||||
export function selectedIndependentCardsProfile(game: FactionModuleProfile): boolean {
|
||||
if (!game || game.ecazTreachery !== true ||
|
||||
!selectedPhaseModuleRoster(game) || !phaseModuleContext(game, false, true) ||
|
||||
(game.techTokens && game.players.length < 3) || game.sandtrout || game.spiceBankerIncomePreview) return false;
|
||||
return (!game.ecazOccupyPreview || game.ecazOccupyPreview === true &&
|
||||
game.players.some(player => player.faction === 'ecaz')) &&
|
||||
(!game.moritaniAssassinatePreview || game.moritaniAssassinatePreview === true && game.advanced &&
|
||||
game.players.some(player => player.faction === 'moritani'));
|
||||
}
|
||||
|
||||
export type MixedE3NativeRoster = {
|
||||
advanced?: boolean;
|
||||
expansions: readonly string[];
|
||||
|
||||
+4
-4
@@ -3901,7 +3901,7 @@ export const RULE_TOPICS: RuleTopic[] = [
|
||||
'Classic Advanced Nexus core also retains original Strongholds2–6 and optional Tech3–6 with base33 or selected independent36, optionally all14. Earn cards only at actual end-Mentat. Earned Arrakeen composes temporary-Sardaukar support and real Reinforcements reserve fees without making bank money personal; earned Carthag still requires a physical effective defense after an original Harkonnen call is canceled. Original cleanup, token reward, held custody and private Mentat replacement remain.',
|
||||
'Fresh Advanced all14 Skills uses registered actual seats and selected ordinary decks with original Strongholds2–6 and optional Tech3–6, including its independent-card/World envelope. Native E3 needs no Nexus or exact single family merely to use Skills. Original Nexus/Discovery/Semuta card contexts and Advanced role guards remain separate. Actual end-Mentat claims stay. Arrakeen funds only local holder-plan support, never native World support, personal cash or reserve fees; normal Banker uses the final payer debit. Rescue, cleanup, Tech and Face Dance retain their order.',
|
||||
'Ecaz/Moritani Skills may include other registered selected-family seats and unused selected ordinary decks, with original Worlds/phase modules and optional independent cards. Native five-disc training and original role exclusions remain. Normal Warmaster one on a temporary Duke never grants trained three. Winner Suk precedes unused-disc assassination, bounty, winner Tech and one Mentat replacement. Ecaz-held support belongs only to the selected Ecaz plan, not an allied plan; fixed and variable armies remain separate. Advanced E3/Harkonnen, shared Duke and effect-specific guards stay.',
|
||||
'Fresh independent Treachery previews retain classic/E1/E2 and original standalone/paired E3 bare rosters; all14 additionally admits registered mixed selected families. Original Worlds, Advanced Strongholds2–6 and optional Tech3–6 retain actual end-Mentat custody. Reinforcements adds no supported counters; Harass vacates control without transferring a held card early. Exact native fees/returns, card effects and winner Tech remain; bare mixed-E3 World/phase, original Nexus/Discovery card and role/effect guards stay separate.',
|
||||
'Fresh independent Treachery previews retain clean registered selected-deck paired/mixed/all-three native rosters and classic-only unused decks, with optional Tech3–6 and Advanced Strongholds2–6. Basic mixed Ecaz also admits bare cards. Original end-Mentat custody, physical reserve fees, owner-only Harass returns and selected-winner Tech remain. Bare mixed E3 Worlds and separate Skills/Nexus/Discovery/Semuta profiles retain their own admission.',
|
||||
'The six effects, public ownership and pre-plan choice are integrated in development games. Enable Stronghold Cards in an Advanced preview lobby. Complete Advanced compliance and every expansion interaction remain under verification.',
|
||||
],
|
||||
example:
|
||||
@@ -3982,7 +3982,7 @@ export const RULE_TOPICS: RuleTopic[] = [
|
||||
{ area: 'Player controls', status: 'Implemented', detail: 'Original local390px controls cover HMS copy/support, real cache Stone reveal mode and partial Face Dance replacement. Standalone E3 human controls select the Ecaz holder lead, show bank2/personal1 for actual support3, seal native plans and keep the physical Shield; Moritani reveals printed Master Bewt bounty through its original inspector and choice. Original Collection and Mentat continue after refresh.', evidence: ['components/stronghold-cards.tsx', 'components/game-table.tsx'] },
|
||||
{ area: 'AI', status: 'Partial', detail: 'Four minimal legal policies consume actual marker/Stone/FaceDance/copy choices; eighteen genuine paired/mixed Advanced2..6 games complete. Strategy/calibration and other combinations remain deferred.', evidence: ['game/bots.ts', 'tools/faction-games.ts'] },
|
||||
{ area: 'Documentation', status: 'Partial', detail: 'Advanced family/deck/cache admission, existing six effects, original winner versus replacement and explicit guarded combinations are recorded without completing every card or faction.', evidence: ['docs/STRONGHOLD_CARDS.md', 'docs/RULE_DECISIONS.md'] },
|
||||
{ area: 'Verification', status: 'Partial', detail: 'New selected-deck cases cover normal mixed/classic setup, actual six-native income and claims, native Harkonnen/Moritani assassination and labelled controlled Ecaz/Ixian coalition battles. Full modes remain unfinished. Prior E1/E2 evidence remains dated. Standalone E3 adds20 focused cases, affected native/CLI179, types/lint/build and actual controlled holder-only funding, tie/income, assassination/death/forfeiture and four legal policies. Four genuine two/three-seat E3 games complete642 accepted actions,15 JSON continuations and3 battles without rejection; no natural assassination claim. Human390px Ecaz reaches v18/Mentat with bank2/personal1, separate Collection2 and physical Ecaz2/Guild1 survivors; Moritani reaches v11/Mentat with wallet18 and one original private replacement. No new assurance/full-suite campaign or public/deployed certification.', evidence: ['tests/phase-module-profile.test.ts', 'tests/mixed-phase-modules-runtime.test.ts', 'tests/mixed-phase-modules-controls.test.tsx', 'tests/phase-module-ecaz-runtime.test.ts', 'tests/phase-module-moritani-runtime.test.ts', 'tests/ecaz-stronghold-runtime.test.ts', 'tests/moritani-stronghold-runtime.test.ts', 'tests/richese-strongholds-runtime.test.ts', 'tests/tleilaxu-strongholds-runtime.test.ts'] },
|
||||
{ area: 'Verification', status: 'Partial', detail: 'New selected-deck cases cover normal mixed/classic setup, actual six-native income and claims, native Harkonnen/Moritani assassination and labelled controlled Ecaz/Ixian coalition battles. Full modes remain unfinished. Prior E1/E2 evidence remains dated. Standalone E3 adds20 focused cases, affected native/CLI179, types/lint/build and actual controlled holder-only funding, tie/income, assassination/death/forfeiture and four legal policies. Four genuine two/three-seat E3 games complete642 accepted actions,15 JSON continuations and3 battles without rejection; no natural assassination claim. Human390px Ecaz reaches v18/Mentat with bank2/personal1, separate Collection2 and physical Ecaz2/Guild1 survivors; Moritani reaches v11/Mentat with wallet18 and one original private replacement. No new assurance/full-suite campaign or public/deployed certification.', evidence: ['tests/independent-phase-profile.test.ts', 'tests/independent-phase-modules-runtime.test.ts', 'tests/independent-phase-ecaz-battle.test.ts', 'tests/phase-module-profile.test.ts', 'tests/mixed-phase-modules-runtime.test.ts', 'tests/mixed-phase-modules-controls.test.tsx', 'tests/phase-module-ecaz-runtime.test.ts', 'tests/phase-module-moritani-runtime.test.ts', 'tests/ecaz-stronghold-runtime.test.ts', 'tests/moritani-stronghold-runtime.test.ts', 'tests/richese-strongholds-runtime.test.ts', 'tests/tleilaxu-strongholds-runtime.test.ts'] },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -4001,7 +4001,7 @@ export const RULE_TOPICS: RuleTopic[] = [
|
||||
'Owning all three tokens counts as one additional stronghold at victory checks. An alliance cannot combine separate token holdings to qualify: one member must own the complete set. Multiple sides reaching the victory target can share the win.',
|
||||
'Token ownership and pending income are public and persist. Fresh registered selected-family all14 keeps original Tech3–6 Basic/Advanced and optional Advanced Strongholds2–6, including supported Worlds and independent cards, without an incidental Nexus or single-family E3 requirement. Original Nexus/Discovery/Semuta and role/effect guards remain. Rescue/board-spice precedes winner Tech and Face Dance. Mandatory normal Banker waits for Mentat, separate from phase-end Tech; fees/H returns are not revival/shipment. Native CHOAM opening income is not Charity. Two-player Tech and full combined acceptance remain unfinished.',
|
||||
'Without other optional overlays, fresh normal selected-deck starts retain original Tech3–6 Basic/Advanced with registered paired/mixed/all-three native families or classic-only seats and unused decks. Advanced Strongholds2–6 optionally compose. Native payments, typed casualties, selected Ecaz lead rewards and existing captured-leader Moritani assassination remain separate; split allied holdings never form a complete set. Explicit Semuta keeps its earlier scope. Existing provisional Basic odd Occupy, Richese rulings and unrelated profiles are not newly decided; played games are not converted.',
|
||||
'Classic/E1/E2 and original standalone/paired E3 bare independent-card previews retain Worlds, Tech3–6 and optional Advanced Strongholds2–6. All14 extends this to registered mixed selected families. Recruits changes current native rates without repeating Axlotl or advancing payout. Harass deposits and reserve fees are not free Revival or off-planet shipment. Original phase income/native custody/winner rewards remain; bare mixed-E3 World/phase and unrelated module/role guards stay separate.',
|
||||
'Clean independent-card selected-deck rosters include paired/mixed/all-three natives and classic-only unused families with optional Tech3–6 and Advanced Strongholds2–6. Recruits changes current native rates without repeating Axlotl or advancing payout. Harass deposits and reserve fees are not free Revival or off-planet shipment. Original phase income, mandatory coalition/assassination and winner rewards remain. Bare mixed E3 Worlds and unrelated module/role profiles keep separate admission.',
|
||||
'Classic Nexus core composes original Tech3–6 Basic/Advanced and optional Advanced Strongholds2–6 with base33 or selected independent36, optionally all14. Real first-Storm owners and actual token counts set income. A paid fixed Tleilaxu force group does not become free because Recruits is active; subsequent genuine free returns accrue one Axlotl pile, not one pile per request. Pending spice cannot fund Revival before phase end. Harass returns and reserve fees are not token-triggering Revival or shipment; actual battle winners take one original opposing token.',
|
||||
],
|
||||
example:
|
||||
@@ -4019,7 +4019,7 @@ export const RULE_TOPICS: RuleTopic[] = [
|
||||
{ area: 'Player controls', status: 'Partial', detail: 'Normal mixed selected-deck module controls and Start reach original setup/Storm; separate existing five-module lobby reaches original training/Storm. Native fixed-five and ordinary-free controls show original prices, physical Tanks and pending pile separately; actual phase close pays it. Stronghold and card inspectors retain their own entitlements.', evidence: ['components/game-table.tsx', 'tests/fixture-nexus-core-tech.ts'] },
|
||||
{ area: 'AI', status: 'Partial', detail: 'Four existing own-view policies legally claim funded card shipment, complete real Revival into phase-end payout and finish earned Stronghold/Nexus battles. No strategic calibration or fixed-choice pin.', evidence: ['game/bots.ts', 'tests/fixture-nexus-core-tech.ts', 'tests/fixture-nexus-core-strongholds.ts'] },
|
||||
{ area: 'Documentation', status: 'Partial', detail: 'Printed trigger/exception, owner count, pending-versus-spendable spice, original payout, winner reward and complete-set victory remain distinct. Current classic core phase scope and inherited timing are explicit; full module/faction combinations and assurance remain open.', evidence: ['game/reference.ts', 'docs/NEXUS_CARD_RULES.md', 'docs/STRONGHOLD_CARDS.md', 'docs/RULE_DECISIONS.md'] },
|
||||
{ area: 'Verification', status: 'Partial', detail: 'Original-action consumers cover funded five-for-one delivery, paid fixed5 versus free2, a second genuine free request, pending-income affordability and Harass/winner transfer. Actual all14 Revival UI and four legal policies reach payout; older broader and saved evidence remains dated.', evidence: ['tests/nexus-core-tech-runtime.test.ts', 'tests/fixture-nexus-core-tech.ts', 'tests/tech-tokens.test.ts', 'tests/nexus-module-payments-runtime.test.ts', 'tests/nexus-skills-modules-payments-runtime.test.ts'] },
|
||||
{ area: 'Verification', status: 'Partial', detail: 'Original-action consumers cover funded five-for-one delivery, paid fixed5 versus free2, a second genuine free request, pending-income affordability and Harass/winner transfer. Actual all14 Revival UI and four legal policies reach payout; older broader and saved evidence remains dated.', evidence: ['tests/selected-phase-recruits-runtime.test.ts', 'tests/independent-phase-modules-runtime.test.ts', 'tests/nexus-core-tech-runtime.test.ts', 'tests/fixture-nexus-core-tech.ts', 'tests/tech-tokens.test.ts', 'tests/nexus-module-payments-runtime.test.ts', 'tests/nexus-skills-modules-payments-runtime.test.ts'] },
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user