Allow native Ecaz Skills coalitions without unrelated modules

This commit is contained in:
Quintine committed 2026-10-17 18:38:33 +11:00
1 parent 7ef3377218
commit 7182502b16
8 files changed
+118 -25

No files matched your search

+12
View File
@@ -29,6 +29,18 @@ optional skill bands and combinations remain open.
Rules implementation continues; comprehensive assurance and administration
remain deferred until all rules are implemented.
**Standalone Ecaz Skills coalition — 17 October.** Native Ecaz/classic all14
Skills now reaches ordinary allied Arrakis battles without Nexus or Worlds.
Fresh Basic participation and the existing native profile feed the same lead,
skill and separate-army continuation. Both normal starts were reproduced
blocked before repair. Actual Basic/Advanced Skills-only programmes reach
Collection, with no Nexus hand or World state added; all four policies work in
both modes with/without Worlds and retain physical counters. The affected
seven-file73/73, types/lint and build pass. Actual390px Skills-only entry has
no browser errors/overflow. Advanced Harkonnen/shared-Duke and other profile
guards remain; no complete-mode or deployed claim.
[Contract](LEADER_SKILLS_RUNTIME.md#standalone-ecaz-coalition--17-october-2026).
**Native World Ecaz Arrakis Occupy — 17 October.** Fresh Ecaz/classic
Homeworld games no longer need Nexus Cards for their ordinary Arrakis
coalition, including the supported native Skills entry. Basic setup now marks
+11 -1
View File
@@ -2,6 +2,15 @@
Historical primary-source audit, 2026-09-07, corrected after independent verification. The publisher/designer odd-force conflict remains unresolved as a publisher correction. Under the 8 October Basic-first prototype instruction, Basic now provisionally uses the main p8 paragraph: ceiling contribution/loss and floor survivors, with a visible control warning. This is not a numerical ruling by the user or designer. Advanced retains its separately authorized source. The earlier false attribution to Jack Reda remains withdrawn.
## Standalone Ecaz Leader Skills — 17 October 2026
The original native Ecaz/classic Skills profile now reaches the same Arrakis
coalition without an artificial Nexus or Homeworld dependency. Fresh Basic
setup records Ecaz participation, while both rules bands reuse the selected
plan-owner/skill and fixed-versus-variable army rules. The source profile's
Advanced Harkonnen, Duke assignment and other roster restrictions remain.
[Current standalone scope and evidence](LEADER_SKILLS_RUNTIME.md#standalone-ecaz-coalition--17-october-2026).
## Native World reserves with Arrakis Occupy — 17 October 2026
Fresh Ecaz/classic Homeworld games now retain their ordinary Arrakis coalition
@@ -28,7 +37,8 @@ and build pass; four standalone original-action smokes reach Collection.
Real390px normal-lobby Ecaz + Homeworlds + Skills setup reaches its offered
skill controls with no app errors or horizontal overflow. That is entry/control
proof, not a browser-played coalition battle or complete combination acceptance.
Unopened Spice order is controlled in the fixture; armies, wallets, alliances,
The fixture reorders unopened Spice; regression shuffles use fixed, scoped
entropy restored after each case. Runtime smokes retain native entropy. Armies, wallets, alliances,
World custody and phases follow native actions. Other E3/mixed module envelopes,
World-location coalition rules and final assurance remain separate.
+21
View File
@@ -1,5 +1,26 @@
# Dune implementation status
## 17 October 2026 — Independent native Ecaz Skills coalition
Both Basic and Advanced normal Ecaz/classic Skills-only starts were rejected
because coalition admission required an unrelated Nexus/World composition.
The existing native Ecaz Skills profile now admits the original Arrakis
coalition; fresh setup marks Basic participation. No new skill arithmetic,
alliance, army, card source, Nexus hand or World custody is invented.
Advanced Harkonnen/shared-Duke and other profile guards remain.
The original World coalition programme supplies a no-World control using
genuine setup, worm alliance and paid shipments. Both Skills-only runtime
smokes reach Collection; four policies in each mode with/without Worlds retain
all normal and starred counters. The affected seven-file73/73, types/lint and
build pass. Final deterministic ten-case rerun and types/lint pass after
scoping/restoring regression entropy; the runtime smokes use native randomness.
Actual390px normal-lobby Skills-only Ecaz setup presents its real
offer with no browser errors or overflow. Coalition behaviour is engine proof,
not a browser-played battle. Final assurance/calibration/combination acceptance
remain open; no deployment or saved-game conversion occurs.
[Current native Skills scope](LEADER_SKILLS_RUNTIME.md#standalone-ecaz-coalition--17-october-2026).
## 17 October 2026 — Native World Ecaz Arrakis coalition
The existing native World occupation and World/Skills setups could deal Ecaz
+26 -1
View File
@@ -7,8 +7,33 @@ and fixture opt-ins are removed; existing games are not retrofitted.
Earlier dated references to a separate entry describe historical checkpoints.
See [current activation and limits](SPICE_BANKER_RUNTIME.md#mandatory-ordinary-skills-default--17-october-2026).
## Standalone Ecaz coalition — 17 October 2026
Native Ecaz/classic all-fourteen Skills no longer needs Nexus Cards or
Homeworlds to resolve its ordinary allied Arrakis battle. The original native
profile now feeds the existing coalition and fresh setup marks participation in
Basic as well as Advanced. The selected lead supplies its own plan/skill; fixed
Ecaz and variable allied armies keep separate physical losses, cancellation,
normal skill effects and mandatory card cleanup.
This removes an artificial setup dependency, not the native profile's source
boundaries: Advanced Harkonnen, shared-Duke assignment and unsupported
roster/module combinations remain guarded. No starting Nexus hand or World
custody is created for Skills-only games, and no played table is redealt.
Both actual Skills-only normal starts failed at coalition admission before the
change; Basic and Advanced now reach Collection through original setup, a real
worm alliance and paid shipments. Four policies are exercised in each mode
with and without Worlds, retaining all physical counters. The affected
seven-file73/73, types/lint and build pass. Regression entropy is scoped and
restored per case; the final deterministic ten-case file also passes. Standalone
runtime smokes retain native randomness. A390px normal-lobby Skills-only
Ecaz start shows its actual offered cards with Nexus/Worlds unchecked and no
app errors or overflow. Browser evidence is entry/controls, not a played
coalition battle or final acceptance.
13 September 2026. This is **Prototyped**, with **Partial** rules coverage.
Normal mode starts and publication remain gated. The [source contract](LEADER_SKILLS_RULES.md)
Normal lobby access now exposes supported previews; full rules-mode acceptance and publication remain gated. The [source contract](LEADER_SKILLS_RULES.md)
contains all fourteen physical cards; the [capture interpretation](LEADER_SKILLS_CAPTURE.md)
records the fresh publisher/designer search requested by the user.
+3 -2
View File
@@ -1,7 +1,7 @@
import { classicNexusModulesProfile, mixedE1E2NexusProfile, mixedE3NexusProfile, pairedE3NexusProfile, pairedNexusModulesProfile, singleE1E2NexusProfile, standaloneE3NexusProfile } from './nexus-module-profile';
import { nativeFactionTechProfile } from './faction-module-profile';
import { classicDiscoveryLeaderSkillsProfile, classicDiscoveryNexusProfile, homeworldDiscoveryProfile, discoveryModeSupported, discoveryModuleProfile, mixedE1E2DiscoveryNexusProfile, mixedE3DiscoveryNexusProfile, pairedDiscoveryNexusProfile, pairedE3DiscoveryNexusProfile, singleE1E2DiscoveryNexusProfile, standaloneE3DiscoveryNexusProfile } from './discovery-module-profile';
import { advancedMoritaniLeaderSkillsProfile, advancedNativeLeaderSkillsProfile, homeworldLeaderSkillsProfile, classicIndependentLeaderSkillsProfile, classicNexusLeaderSkillsProfile, classicTechLeaderSkillsProfile, guildBetrayalNexusLeaderSkillsProfile, mixedE1E2NexusLeaderSkillsProfile, mixedE3NexusLeaderSkillsProfile, nativeDiscoveryLeaderSkillsProfile, nativeExpansionLeaderSkillsProfile, nativeTechLeaderSkillsProfile, ordinaryLeaderSkillModeSupported, pairedE3NexusLeaderSkillsProfile, pairedNexusLeaderSkillsProfile, singleE1E2NexusLeaderSkillsProfile, standaloneE3NexusLeaderSkillsProfile, strongholdLeaderSkillsProfile } from './leader-skill-profile';
import { advancedMoritaniLeaderSkillsProfile, advancedNativeLeaderSkillsProfile, homeworldLeaderSkillsProfile, classicIndependentLeaderSkillsProfile, classicNexusLeaderSkillsProfile, classicTechLeaderSkillsProfile, guildBetrayalNexusLeaderSkillsProfile, mixedE1E2NexusLeaderSkillsProfile, mixedE3NexusLeaderSkillsProfile, nativeDiscoveryLeaderSkillsProfile, nativeEcazLeaderSkillsProfile, 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';
@@ -10518,6 +10518,7 @@ export function initializeFactionExpansionsGameForAudit(state: Game): Game {
return initialized;
}
function ecazOccupyCompositionSupported(g: Game): boolean {
if (g.leaderSkills && nativeEcazLeaderSkillsProfile(g)) return true;
if (g.ecazOccupyPreview === true && (mixedE3NexusProfile(g) || standaloneE3NexusProfile(g) || pairedE3NexusProfile(g)) &&
g.players.some(player => player.faction === 'ecaz')) return true;
if (g.leaderSkills && (mixedE3NexusLeaderSkillsProfile(g) || standaloneE3NexusLeaderSkillsProfile(g) || pairedE3NexusLeaderSkillsProfile(g)) &&
@@ -10729,7 +10730,7 @@ export function initializeLeaderSkillsGameForAudit(state: Game): Game {
g.expansions.length === 1 && g.expansions[0] === 'choam', nativeExpansionLeaderSkillsProfile(g), independent);
if (advancedMoritaniLeaderSkillsProfile(initialized) || ((mixedE3 || pairedE3) && initialized.advanced &&
byFaction(initialized, 'moritani'))) initializeMoritaniAssassinateState(initialized);
if ((mixedE3 || homeworlds || nativeDiscoveryLeaderSkillsProfile(initialized) || pairedE3) && byFaction(initialized, 'ecaz')) initialized.ecazOccupyPreview = true;
if ((nativeEcazLeaderSkillsProfile(initialized) || mixedE3 || homeworlds || nativeDiscoveryLeaderSkillsProfile(initialized) || pairedE3) && byFaction(initialized, 'ecaz')) initialized.ecazOccupyPreview = true;
return initialized;
}
/** Independent cards keep the actual selected base/E1/E2 physical families. */
+10 -10
View File
@@ -1408,7 +1408,7 @@ export const RULE_TOPICS: RuleTopic[] = [
'Stone Burner compares physical undialed counters, not total dial or paid strength: active Occupy contributes floor(Ecaz forces / 2) plus the ally’s native undialed tokens. Canceled Occupy compares only the selected lead’s own pool. Physical Mirror copies use the same comparison and retain their original cleanup. Hidden opposing No-Field preflight uses public possible pools, not its actual denomination; genuinely winner-changing typed allocations remain blocked.',
'With the independent variant, Harass returns only the actual card user’s undialed forces. An Ecaz user keeps the original mandatory ceil contribution committed at free full strength while its floor count returns; ally support is separate. An allied user subtracts fixed strength before choosing its native typed commitment. Canceled Occupy uses its selected lead’s own pool. Returned reserves are outside later casualties/explosion/Face Dance.',
'Reinforcements consumes three card-user reserves normal-first and adds +2 normal score, never support or physical arrivals. Under the provisional native order, an own No-Field materializes before that original reserve fee and successful Harass returns; three reserves must remain after reveal before this plan may seal. Original/copied Stone ignores +2 score but not the fee. Existing all-revealed-outcome cost/disposal remains provisional. Basic/unprofiled co-side cards stay guarded.',
'Advanced numbers come from the user-authorized revised PDF, physical pages 32 and 19, not a new publisher erratum. Basic follows the main printed paragraph provisionally. Original faction/deck prerequisites, separate ten-card Richese cache and independent three-card variant selection stay. Ordinary-plus-marker Advanced Occupy extends the provisional additive interpretation, not the unresolved FAQ cap. Basic mixed-co-side, whole-plan/optional overlays and public starts remain separate gates.',
'Advanced numbers come from the user-authorized revised PDF, physical pages 32 and 19, not a new publisher erratum. Basic follows the main printed paragraph provisionally. Original faction/deck prerequisites, separate ten-card Richese cache and independent three-card variant selection stay. Ordinary-plus-marker Advanced Occupy extends the provisional additive interpretation, not the unresolved FAQ cap. Native Ecaz/classic Skills and supported World previews now retain ordinary Arrakis Occupy; Basic mixed-co-side cards, unsupported optional overlays and full-mode acceptance remain separate.',
],
checklist: [
{ area: 'Implementation', status: 'Partial', detail: 'Combined-side enumeration, lead choice, native Occupy response and owner-labelled physical outcomes are connected. Basic odd counts now follow the main printed paragraph provisionally; Advanced retains its authorized arithmetic. Optional/exotic composition refinement remains.', evidence: ['game/ecaz-occupy-battle.ts', 'game/board-resolution-quote.ts', 'game/battle-resolution-quote.ts', 'game/engine.ts'] },
@@ -1429,7 +1429,7 @@ export const RULE_TOPICS: RuleTopic[] = [
'Before any initial Traitor Cards are drawn, randomly select one of the five ordinary Ecaz Traitor Cards and set it aside face up. Everyone may inspect it. It remains outside the deck for the rest of the game, including later Traitor and Face Dancer draws.',
'Loyalty is automatic and cannot be stopped with Karama. It creates no player choice, payment or acknowledgment. The card names a leader, but does not remove, kill, transfer or otherwise change that leader disc. Duke Vidal has no Traitor Card and is never a candidate.',
'In new Advanced development games with Ecaz, the table displays the selected card before the Traitor choices. Inspect traitor enlarges its identity; refreshing or resuming the saved game keeps the same card. Basic games and games without native Ecaz do not use this power.',
'Older saved games that have already dealt their Traitor Cards retain that inventory; they do not gain a retroactive Loyalty draw. Bounded native Ecaz Leader Skills retain this original draw after public assignment. Public expansion starts, combined Occupy skills and Moritani assassination combinations remain gated.',
'Older saved games that have already dealt their Traitor Cards retain that inventory; they do not gain a retroactive Loyalty draw. Bounded native Ecaz Leader Skills retain this original draw after public assignment and now support their original allied Arrakis Occupy without an unrelated module. Unsupported Moritani/shared-Duke and other roster compositions remain guarded.',
],
checklist: [
{ area: 'Implementation', status: 'Partial', detail: 'One persisted native Ecaz card is selected before genuine initial dealing, excluded from setup and Nexus deck construction, and validated against all known circulating or retired Traitor locations. Older saves stay unchanged. Broader combinations remain gated.', evidence: ['game/ecaz-loyalty.ts', 'game/engine.ts'] },
@@ -3416,7 +3416,7 @@ export const RULE_TOPICS: RuleTopic[] = [
'Arrakeen pays only for actual support and creates no personal cash. CHOAM force-payment income includes the bank contribution, subject to its normal traitor and donor exclusions. Carthag does not protect an empty or Worthless defense, stop Poison Tooth, or remove a Shield’s Lasgun explosion risk.',
'Sietch Tabr uses the opposing dial, excluding leaders and other bonuses. A single traitor victory qualifies; mutual destruction does not. Tuek pays after an ordinary loss or a single traitor outcome as well as a win; a double traitor gives neither faction spice. Habbanya also decides a tied Stone Burner comparison.',
'Fresh Advanced local development tables may combine all fourteen Leader Skills with Stronghold Cards in classic or supported Ixian, Tleilaxu, CHOAM and Richese skill rosters, two through six players; optional Tech Tokens needs three through six. Original deck/cache and end-Mentat claims remain. Arrakeen pays bank support, not personal income; only the remaining actual payer debit qualifies for normal Banker income, now mandatory in fresh supported Skills setups. Skill rescue preserves the original support charge, then card cleanup and Tech reward finish before Face Dance. Modified/copied Diplomat defenses and active skill/Stone interpretations stay guarded; public activation, E3/other overlays and save conversion remain separate.',
'The original standalone Ecaz or Moritani skill roster additionally supports these Advanced combinations with the exact ecaz deck, original five-disc training and native exclusions. Normal Warmaster one on a temporary Duke composes Carthag Shield without granting trained three; normal winner Suk precedes unused-disc Moritani assassination, printed bounty, retained winner Tech and one private Mentat replacement. E3 pairs, mixtures and allied Occupy skills stay separate.',
'The original standalone Ecaz or Moritani skill roster additionally supports these Advanced combinations with the exact ecaz deck, original five-disc training and native exclusions. Normal Warmaster one on a temporary Duke composes Carthag Shield without granting trained three; normal winner Suk precedes unused-disc Moritani assassination, printed bounty, retained winner Tech and one private Mentat replacement. Standalone Ecaz also retains its selected-lead Arrakis coalition; unsupported E3 pairs and mixtures stay separate.',
'Fresh independent Treachery previews compose classic or selected Ix/CHOAM native/base rosters, including original Homeworlds, with Advanced Strongholds2–6 and optional Tech3–6. Actual end-Mentat earns custody. Reinforcements adds no supported counters; Harass vacates control without transferring a retained card early. Exact native fee/return, original card effects and winner Tech order remain; other overlays stay guarded.',
'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.',
],
@@ -4823,20 +4823,20 @@ export const RULE_TOPICS: RuleTopic[] = [
developmentStage: 'Prototyped',
summary: 'Five native trained discs, original Ambassador choices and ordinary battle effects, with the separate temporary Duke retained.',
steps: [
'Fresh Basic or Advanced native Ecaz with classic opponents retains the ecaz deck and all fourteen skills. Starting cards precede public skill assignments, Loyalty/Traitors and original six-force placement. Five native discs are eligible; the separate Duke is not an assignment disc. Public starts remain gated.',
'Fresh Basic or Advanced native Ecaz with classic opponents retains the ecaz deck and all fourteen skills. Starting cards precede public skill assignments, Loyalty/Traitors and original six-force placement. Five native discs are eligible; the separate Duke is not an assignment disc. Supported normal-lobby previews now use this setup.',
'Ordinary native role scores, actual Suk casualties, trainer death and optional own normal-disc revival skills use their original rules. Normal rescue returns one physical casualty; surviving trained rescue keeps one and returns up to two more, without refunding support or creating extra forces.',
'Original paid Ambassador placement and entrant reactions keep the exact token, training and movement suffix. Emperor Ambassador grants five bank spice; it is income, not a qualifying bank payment from another player for Banker.',
'A temporarily acquired Duke has printed strength six. A different living face-up Warmaster may give him only the normal one-point bonus with a physical Worthless card, never the trained-disc three. Surviving release or actual Duke death leaves the native trainer and card intact; bounty remains printed six.',
'Ecaz-only paid five-spice Duke revival retains the same living set-aside disc under the earlier selected interpretation. These paths keep an existing native skill and do not authorize shared-Duke assignment. Advanced Harkonnen, combined Occupy skills and other module/ruling boundaries remain explicit.',
'Fresh standalone Ecaz skill tables may preserve original Tech Tokens in Basic/Advanced with three through six seats, and Stronghold Cards in Advanced with two through six, optionally both. Original five-disc training, Ambassador/Duke acquisition, local held-card protection or income, Suk rescue and mandatory winner Tech remain. A native face-up Warmaster gives temporary Duke only normal one; Carthag physical Shield can prevent poison. Original paid five-spice Duke revival remains living and set aside, not reassigned. Advanced Harkonnen, allied Occupy skills, pairs, mixtures and other guards stay unchanged.',
'Ecaz-only paid five-spice Duke revival retains the same living set-aside disc under the earlier selected interpretation. These paths keep an existing native skill and do not authorize shared-Duke assignment. Advanced Harkonnen and other module/ruling boundaries remain explicit.',
'Fresh standalone Ecaz skill tables may preserve original Tech Tokens in Basic/Advanced with three through six seats, and Stronghold Cards in Advanced with two through six, optionally both. Original five-disc training, Ambassador/Duke acquisition, local held-card protection or income, Suk rescue and mandatory winner Tech remain. Allied Arrakis Occupy now uses the selected lead’s skill and separate fixed/variable army losses without needing Nexus or Worlds. Advanced Harkonnen, pairs, mixtures and other unsupported profiles stay guarded.',
],
related: ['leader-skills', 'duke-vidal', 'ecaz-ambassadors', 'spice-banker-income', 'implementation-checklist'],
checklist: [
{area:'Implementation',status:'Partial',detail:'Native five-disc profile composes original setup, Ambassador, ordinary rescue/death/revival and separate temporary Duke handlers. Combined Occupy skills and shared-Duke assignment remain guarded.',evidence:['game/leader-skill-profile.ts','game/engine.ts']},
{area:'Implementation',status:'Partial',detail:'Native five-disc profile composes original setup, Ambassador, ordinary rescue/death/revival, separate temporary Duke handlers and allied Arrakis Occupy with or without supported Worlds. Shared-Duke assignment and wider profile combinations remain guarded.',evidence:['game/leader-skill-profile.ts','game/engine.ts']},
{area:'Player controls',status:'Partial',detail:'Original skill offers, posture, battle slots, rescue, Ambassador acquisition and revival controls are reused. Human390px LQWE8TZM v18 exercises paid token/arrival/acquisition, Duke Worthless battle and original cleanup/refresh.',evidence:['components/leader-skills.tsx','components/duke-vidal.tsx','components/game-table.tsx']},
{area:'AI',status:'Partial',detail:'Existing legal native choices and all four physical Suk rescues compose. No new strategy or calibration.',evidence:['game/bots.ts','tools/faction-games.ts']},
{area:'Documentation',status:'Partial',detail:'Ordinary native and temporary Duke scope are separated from unresolved assignment, capture and combined force rules.',evidence:['docs/LEADER_SKILLS_RUNTIME.md','docs/DUKE_VIDAL_RULES.md']},
{area:'Verification',status:'Partial',detail:'Affected67/67, types/lint/build and twenty controlled rule programs pass. Ten genuine two-through-six-seat Basic/Advanced games complete4,264 accepted actions without rejection,110 JSON continuations and59 battles. Original CLI24HGMJCD v4 retains setup; humanLQWE8TZM v18 retains Collection/wallet11/eight real counters/living set-aside Duke and native Warmaster. Full combinations/assurance/public/deployed acceptance remain open.',evidence:['tests/native-ecaz-skills.test.ts','tests/native-ecaz-duke-skills.test.ts']},
{area:'Verification',status:'Partial',detail:'Standalone coalition follow-up passes73/73 affected cases, types/lint/build, two Skills-only runtime programmes and390px lobby entry. Four policies in Basic/Advanced with/without Worlds complete real allied battles and preserve physical counters. Earlier67/67/native Duke, complete-game and CLI evidence remains historical; full combinations/assurance/deployed acceptance stay open.',evidence:['tests/homeworld-ecaz-occupy-runtime.test.ts','tests/fixture-homeworld-ecaz-occupy.ts','tests/native-ecaz-skills.test.ts','tests/native-ecaz-duke-skills.test.ts']},
],
},
{
@@ -4932,7 +4932,7 @@ export const RULE_TOPICS: RuleTopic[] = [
'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. Supplied Advanced p34 excludes Richese auctions from Ixian Technology; 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.',
'Fresh Advanced classic or supported native two-through-six-seat skill tables may retain six original Stronghold Cards, with Tech at three or more seats. Original end-Mentat/local held effects remain. Arrakeen changes actual payer cost, not rescue or Banker eligibility; native CHOAM income retains bank support. Physical defenses, normal disciplines, holder ties and original dial/Worthless earnings remain. Standalone Ecaz Duke and Moritani assassination compose original rules; mixed E3, allied Occupy skills, copied Diplomat defenses, active skill/Stone and other guards stay separate.',
'Fresh Advanced classic or supported native two-through-six-seat skill tables may retain six original Stronghold Cards, with Tech at three or more seats. Original end-Mentat/local held effects remain. Arrakeen changes actual payer cost, not rescue or Banker eligibility; native CHOAM income retains bank support. Physical defenses, normal disciplines, holder ties and original dial/Worthless earnings remain. Standalone Ecaz Duke/Arrakis coalition and Moritani assassination compose original rules; mixed E3, exceptional copied defenses, active skill/Stone and other guards stay separate.',
'Fresh classic Leader Skills may explicitly add Nexus through local leader-skills --nexus-cards, Basic/Advanced two through six players, retaining selected original Tech at three or more seats and/or Advanced Strongholds. --discoveries additionally composes original Discovery7/8 in this classic profile. Saved hands/offers remain authoritative; the actual end-Spice closing draw follows Maker votes/typed rides, both Advanced piles and settled alliance. Free-return ledgers, bank purchase and Traitor Deck declarations stay distinct from training. Original phase-end industry, held payer support/physical defenses, physical Suk rescue and subsequent mandatory winner Tech rewards retain their own timing. Homeworlds, Banker/Mentat previews, borrowed Smuggler arithmetic and unresolved interactions remain separate.',
'The same fresh entry also adds --nexus-cards --discoveries to paired Ixians+Tleilaxu, paired CHOAM+Richese or standalone Ecaz OR Moritani with classics, original all14/all12/Discovery7/8, Basic/Advanced two through six with optional Tech3+ and Advanced Strongholds. Original offers/hands/native components remain authoritative. E1 Suboid Cunning settles typed Suk rescue before one equal Cyborg Tank substitution, then original cleanup and mandatory winner Tech precede a matching Face Dance; E2 keeps its signed one-invoice pair; Ecaz keeps quiet living/unclaimed Duke then a real owner-labelled mandatory 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 Ecaz, Advanced Harkonnen and other pending rulings stay guarded.',
'Both original paired Ixian/Tleilaxu or CHOAM/Richese factions plus classics may add Nexus through that fresh local skill entry, with one family deck/all14/all12, Basic/Advanced two through six players. Selected original Tech requires3+; Strongholds requires Advanced. Full unsupported Suboids retain Cyborg support and skill posture; physical Suk rescue precedes equal actual Cyborg Tank substitution. Original winner cleanup and mandatory Tech precede Face Dance, which returns a matching killed trainer skill once without another bounty. Held custody stays with the original winner. Richese Cunning retains its signed two-marker/one-invoice operation and native phase-end industry; ordinary skill proofs and companion exclusions stay separate. CHOAM fuel precedes ordinary Planetologist movement without a second card effect or artificial combat Special.',
@@ -4963,7 +4963,7 @@ export const RULE_TOPICS: RuleTopic[] = [
related: ['spice-banker-income', 'choam-leader-skills', 'ixian-leader-skills', 'tleilaxu-leader-skills', 'richese-leader-skills', 'ecaz-leader-skills', 'moritani-leader-skills', 'setup','choam-modules','implementation-checklist'],
checklist: [
{ area:'Implementation',status:'Partial',detail:'Exact fourteen-card custody, source-ordered setup, public capture, concealment, death and own revival connect five role bonuses, Planetologist movement/Special substitution and Suk Graduate casualty rescue. Rihani inspection/exchange and lower Mentat/Bureaucrat/Sandmaster effects are connected. Smuggler shipping, No-Field accompaniment and provisional modifier-inclusive battle collection, plus Sandmaster ground, worm, physical Ambassador and native HMS allocation are connected. Normal Mentat private questions and historical observations use the user-approved uniform step in new supported battles without an extra opt-in. Spice Banker lower spending and native Diplomat printed-defense copying are connected; trained retreat transfers undialed forces before losing casualties. Normal Banker income is mandatory in fresh supported ordinary all14 setups; existing games are not retrofitted and other combined interactions stay open. Bureaucrat redirects supported third-party payments with saved once-per-phase use, while user-classified gifts stay outside payment handling.',evidence:['game/leader-skill-cards.ts','game/leader-skills.ts','game/leader-skill-combat.ts','game/suk-graduate.ts','game/rihani-decipherer.ts','game/mentat-question.ts','game/bureaucrat-payment.ts','game/leader-skill-battle-board.ts','game/smuggler-shipment.ts','game/smuggler-no-field.ts','game/smuggler-battle.ts','game/spice-banker.ts','game/spice-banker-income.ts','game/sandmaster-movement.ts','game/sandmaster-worm.ts','game/fremen-ambassador.ts','game/diplomat-defense.ts','game/diplomat-retreat.ts','game/engine.ts'] },
{ area:'Player controls',status:'Partial',detail:'Private card/leader selection, readable inspectors, public battle posture and revival draw/decline, Planetologist range/gather controls, Special weapon selection and Suk Graduate physical rescue choices are connected. Rihani has private history and separate keep-new/reveal-old controls; automatic battle effects need no confirmation. Smuggler has explicit ordinary shipping opt-out and No-Field companion opt-in with physical-versus-priced force counts, plus surviving-leader battle collection with reveal-time guidance and owned multi-pile allocations. Banker exposes separate sealed spending and authorized inspection. Sandmaster exposes explicit legal routes, per-territory collection choices, optional worm/physical Ambassador destination checkboxes and direct victory-pile placement when several piles remain. Diplomat offers a named committed Worthless choice or decline after public reveal, and a separate surviving-loser destination/normal/elite retreat or decline. Bureaucrat offers redirect or full payment with explicit recipient amounts and deferred bribe custody. Remaining effect controls are missing.',evidence:['components/leader-skills.tsx','components/planetologist-movement.tsx','components/suk-graduate.tsx','components/rihani-decipherer.tsx','components/mentat-question.tsx','components/bureaucrat-payment.tsx','components/leader-skill-battle-guide.tsx','components/smuggler-shipment.tsx','components/smuggler-battle-collection.tsx','components/spice-banker.tsx','components/sandmaster-movement.tsx','components/sandmaster-worm.tsx','components/sandmaster-victory-spice.tsx','components/ambassador-movement.tsx','components/diplomat-defense.tsx','components/diplomat-retreat.tsx','components/game-table.tsx'] },
{ area:'Player controls',status:'Partial',detail:'Private card/leader selection, readable inspectors, public battle posture and revival draw/decline, Planetologist range/gather controls, Special weapon selection and Suk Graduate physical rescue choices are connected. Rihani has private history and separate keep-new/reveal-old controls; automatic battle effects need no confirmation. Smuggler has explicit ordinary shipping opt-out and No-Field companion opt-in with physical-versus-priced force counts, plus surviving-leader battle collection with reveal-time guidance and owned multi-pile allocations. Banker exposes separate sealed spending and authorized inspection. Sandmaster exposes explicit legal routes, per-territory collection choices, optional worm/physical Ambassador destination checkboxes and direct victory-pile placement when several piles remain. Diplomat offers a named committed Worthless choice or decline after public reveal, and a separate surviving-loser destination/normal/elite retreat or decline. Bureaucrat offers redirect or full payment with explicit recipient amounts and deferred bribe custody. Remaining combined-module and exceptional-timing controls are incomplete.',evidence:['components/leader-skills.tsx','components/planetologist-movement.tsx','components/suk-graduate.tsx','components/rihani-decipherer.tsx','components/mentat-question.tsx','components/bureaucrat-payment.tsx','components/leader-skill-battle-guide.tsx','components/smuggler-shipment.tsx','components/smuggler-battle-collection.tsx','components/spice-banker.tsx','components/sandmaster-movement.tsx','components/sandmaster-worm.tsx','components/sandmaster-victory-spice.tsx','components/ambassador-movement.tsx','components/diplomat-defense.tsx','components/diplomat-retreat.tsx','components/game-table.tsx'] },
{ area:'AI',status:'Partial',detail:'All four profiles use private offers, legal visibility/revival actions and Planetologist movement/battle candidates and legal Suk Graduate rescues, Rihani exchanges, shared battle scoring, Smuggler reserve/owned No-Field shipments and modifier-inclusive collection plans, exact multi-pile Smuggler allocations, Sandmaster route, worm, physical Ambassador destination collection and victory-pile placement, funded Banker commitments and optional Diplomat copying from public revealed defenses or choosing legal losing-battle retreat. Bureaucrat uses the public payee alliance to redirect enemy income or preserve allied income. These are legal prototype paths; complete skill strategy and difficulty calibration remain unfinished.',evidence:['game/bots.ts'] },
{ area:'Documentation',status:'Partial',detail:'All fourteen faces and common rules are recorded. Skilled capture follows public physical-card custody. The 13 October 2026 ruling resolves the captured-card replacement question: the original assignment is retained and no replacement is drawn while it exists; other material timing interpretations remain explicit.',evidence:['docs/LEADER_SKILLS_RULES.md','docs/LEADER_SKILLS_CAPTURE.md','docs/LEADER_SKILLS_RUNTIME.md','docs/PLANETOLOGIST_RULES.md','docs/SUK_GRADUATE_RULES.md','docs/LEADER_BATTLE_EFFECTS.md','docs/MENTAT_QUESTION.md','docs/BUREAUCRAT_PAYMENTS.md','docs/SMUGGLER_SHIPMENT.md','docs/SPICE_BANKER_RUNTIME.md','docs/SANDMASTER_WORM.md','docs/DIPLOMAT_DEFENSE.md'] },
{ area: 'Verification', status: 'Partial', detail: 'Earlier native/Smuggler/optional-module and recovery evidence remains dated in linked contracts. Used-defense capability3 adds preserved false-vote late copying, native-only Homeworld continuation and independently earned Carthag protection, with true-traitor, own-defense and legacy boundaries. Four390px journeys/25 actions reach original Collection; twelve four-policy programmes/40 actions retain legal copy/decline behavior. Printed-role/context scheduling remains provisional, not complete-mode, full strategy or deployed acceptance.', evidence: ['tests/diplomat-used-defense.test.ts', 'tests/diplomat-late-journey.test.ts', 'tests/fixture-diplomat-late-journey.ts', 'tests/diplomat-context-journey.test.ts', 'tests/fixture-diplomat-context-journey.ts', 'docs/DIPLOMAT_DEFENSE.md', 'tests/smuggler-kwisatz-journey.test.ts', 'tests/fixture-smuggler-kwisatz-journey.ts', 'tests/smuggler-artillery-journey.test.ts', 'tests/fixture-smuggler-artillery-journey.ts', 'docs/SMUGGLER_BATTLE.md', '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-skills-runtime.test.ts','tests/homeworld-skills-discovery-runtime.test.ts','tests/homeworld-optional-modules-runtime.test.ts','tests/leader-skills-engine.test.ts','tests/leader-skills-capture.test.ts','tests/captured-skill-revival.test.ts','tests/fixture-captured-skill-revival.ts','tests/captured-skill-special-revival.test.ts','tests/fixture-captured-skill-special-revival.ts','tests/leader-battle-effects.test.ts','tests/suk-graduate.test.ts','tests/mentat-question.test.ts','tests/bureaucrat-payment.test.ts','tests/smuggler-battle.test.ts','tests/spice-banker.test.ts','tests/advanced-native-skills.test.ts','tests/fixture-advanced-native-skills.ts','tests/skills-tech-payments-runtime.test.ts','tests/skills-tech-battle-runtime.test.ts','tests/ix-choam-skills-tech-runtime.test.ts','tests/tleilaxu-skills-tech-runtime.test.ts','tests/richese-skills-tech-runtime.test.ts','tests/classic-skills-stronghold-runtime.test.ts','tests/native-skills-stronghold-runtime.test.ts','tests/ecaz-skills-modules-runtime.test.ts','tests/moritani-skills-modules-runtime.test.ts','docs/LEADER_SKILLS_RUNTIME.md','docs/HOMEWORLD_RUNTIME_IMPLEMENTATION.md'] },
+12 -6
View File
@@ -31,11 +31,16 @@ export function nextHomeworldEcazStep(game: Game): HomeworldEcazStep | null {
return null;
}
/** Fresh native World setup, a real worm alliance and paid Arrakis shipments.
* Only the unopened Spice order is staged; no armies, wallets, phases, alliances
* or World custody are assigned. The selected skill offers remain the real deal. */
export function createHomeworldEcazOccupyFixture(options: { advanced?: boolean; skills?: boolean } = {}): HomeworldEcazOccupyFixture {
/** Fresh native setup (Worlds enabled by default), a real worm alliance and paid
* Arrakis shipments. Only unopened Spice order is staged; armies, wallets,
* phases, alliances, World custody and offered skills follow the real actions. */
export function createHomeworldEcazOccupyFixture(options: {
advanced?: boolean; skills?: boolean;
/** No-World control uses the same genuine alliance/Arrakis route. */
homeworlds?: boolean;
} = {}): HomeworldEcazOccupyFixture {
const advanced = options.advanced ?? true;
const homeworlds = options.homeworlds ?? true;
let game = createGame('WORLDECAZOCCUPY', newPlayer('ecaz', 'Ecaz', 'ecaz'), advanced, ['ecaz']);
joinGame(game, newPlayer('emperor', 'Emperor', 'emperor'));
joinGame(game, newPlayer('guild', 'Guild', 'guild'));
@@ -44,7 +49,7 @@ export function createHomeworldEcazOccupyFixture(options: { advanced?: boolean;
actions.push({ actor, action: structuredClone(action) });
game = applyAction(game, actor, action);
};
act('ecaz', { type: 'homeworlds', enabled: true });
if (homeworlds) act('ecaz', { type: 'homeworlds', enabled: true });
if (options.skills) act('ecaz', { type: 'moduleOption', module: 'leaderSkills', enabled: true });
for (const player of game.players) act(player.id, { type: 'ready' });
act('ecaz', advanced ? { type: 'start', advancedPreview: true } : { type: 'start' });
@@ -91,7 +96,8 @@ export function createHomeworldEcazOccupyFixture(options: { advanced?: boolean;
const actor = game.active!;
if (!shipped.has(actor)) {
act(actor, { type: 'ship', territory: battleTerritory, sector,
amount: actor === 'guild' ? 2 : 4, elite: actor === 'emperor' ? 2 : 0, allyPayment: 0 });
amount: actor === 'guild' ? 2 : 4,
elite: actor === 'emperor' && (advanced || homeworlds) ? 2 : 0, allyPayment: 0 });
shipped.add(actor);
reach(homeworldEcazClean);
}
+23 -5
View File
@@ -10,6 +10,15 @@ import { createHomeworldEcazOccupyFixture, homeworldEcazClean, nextHomeworldEcaz
const player = (game: Game, id: string) => game.players.find(p => p.id === id)!;
const leader = (game: Game, id: string, strongest: boolean) => player(game, id).leaders
.filter(l => !l.dead && !l.usedAt).sort((a, b) => strongest ? b.strength - a.strength : a.strength - b.strength)[0].id;
/** Keep the real shuffles deterministic; node:test restores the crypto method
* after each case, including failures. Event UUIDs do not affect bot variation. */
function fixedEntropy(t: test.TestContext): void {
t.mock.method(crypto, 'getRandomValues', <T extends ArrayBufferView | null>(array: T): T => {
assert.ok(array instanceof Uint32Array);
array.fill(0);
return array;
});
}
function revealAndFinish(state: Game, mixedLoss = false): Game {
let game = state;
while (game.battle) {
@@ -35,7 +44,8 @@ function revealAndFinish(state: Game, mixedLoss = false): Game {
}
for (const advanced of [false, true]) for (const lead of ['ecaz', 'ally'] as const)
void test(`${advanced ? 'Advanced' : 'Basic'} native Worlds ${lead} lead keeps separate typed Arrakis Occupy losses and original World custody`, () => {
void test(`${advanced ? 'Advanced' : 'Basic'} native Worlds ${lead} lead keeps separate typed Arrakis Occupy losses and original World custody`, t => {
fixedEntropy(t);
const f = createHomeworldEcazOccupyFixture({ advanced });
const actor = lead === 'ecaz' ? f.ecaz : f.ally;
let game = openEcazOccupyPlans(chooseEcazOccupyLead(f, lead));
@@ -62,7 +72,8 @@ for (const advanced of [false, true]) for (const lead of ['ecaz', 'ally'] as con
});
for (const lead of ['ecaz', 'ally'] as const)
void test(`native World Karama prevention keeps ${lead} as lead and spares the excluded allied army`, () => {
void test(`native World Karama prevention keeps ${lead} as lead and spares the excluded allied army`, t => {
fixedEntropy(t);
const f = createHomeworldEcazOccupyFixture();
const actor = lead === 'ecaz' ? f.ecaz : f.ally;
const excluded = actor === f.ecaz ? f.ally : f.ecaz;
@@ -88,9 +99,11 @@ for (const lead of ['ecaz', 'ally'] as const)
assert.deepEqual(game.homeworlds!.custody, before.homeworlds!.custody);
});
void test('all four legal profiles complete the native World Skills coalition and retain physical source integrity', () => {
for (const advanced of [false, true]) for (const homeworlds of [false, true])
void test(`all four ${advanced ? 'Advanced' : 'Basic'} Ecaz Skills profiles complete a coalition ${homeworlds ? 'with' : 'without'} Worlds`, t => {
fixedEntropy(t);
for (const difficulty of DIFFICULTIES) {
const f = createHomeworldEcazOccupyFixture({ skills: true });
const f = createHomeworldEcazOccupyFixture({ advanced, skills: true, homeworlds });
let game = f.game;
for (let n = 0; n < 150 && game.phase === 6; n++) {
let next;
@@ -106,6 +119,11 @@ void test('all four legal profiles complete the native World Skills coalition an
assert.equal(game.phase, 7, difficulty);
assert.ok(game.lastBattleContext!.combatants.includes(f.opponent));
assert.equal(game.battle, null);
homeworldGameIntegrity(game);
for (const p of game.players) {
assert.equal(p.reserves + p.tanks + Object.values(p.forces).reduce((sum, n) => sum + n, 0), 20);
if (p.elites) assert.equal(p.elites.reserves + p.elites.tanks +
Object.values(p.elites.forces).reduce((sum, n) => sum + n, 0), 5);
}
if (homeworlds) homeworldGameIntegrity(game);
}
});