Connect bare Basic native Ecaz coalitions
Admit fresh public Basic Ecaz starts with selected native E1/E2 families while retaining roster, inventory, seat and optional-profile guards. Keep actual coalition battle assertions. Include allied marker-only and mixed Richese presence, zero and capped materialization after both seals, and owner-specific casualties. Extend the explicitly provisional additive mixed-marker interpretation to Basic without new arithmetic or FAQ ruling. Use the current physical force pool for battle-wheel half steps so Ecaz can commit Ixian Suboids; cancellation restores Ecaz-only whole steps. Preserve Basic free support, zero funding/income, native Ix substitution, lead-owned cards and original Collection. Verify related Basic/Advanced rules, types/lint/build, nine actual-control/rendered-table programmes after genuine public Basic setup, explicit controlled board/budget/card staging and four existing profiles with legal lead/plan/native-substitution proposals. Full modes, wider optional configurations, comprehensive assurance and deployed acceptance remain unfinished. No strategic calibration, saved-room operation, reset, restart or deployment.
This commit is contained in:
1 parent
152039be5b
commit
1f3e71fe03
12 files changed
+570
-28
No files matched your search
+9
-13
@@ -10758,14 +10758,10 @@ export function initializeFactionExpansionsGameForAudit(state: Game): Game {
|
||||
return initialized;
|
||||
}
|
||||
function ecazOccupyCompositionSupported(g: Game): boolean {
|
||||
// Native Tleilaxu's ordinary Basic armies and Face Dance already use the
|
||||
// same coalition outcome. Admit their bare selected decks without opening
|
||||
// unrelated native factions or optional-module compositions.
|
||||
const basicTleilaxu = g.advanced === false && Array.isArray(g.expansions) && g.expansions.length === 2 &&
|
||||
g.expansions.includes('ecaz') && g.expansions.includes('ix') &&
|
||||
!!byFaction(g, 'tleilaxu') &&
|
||||
g.players.every(p => p.faction === 'ecaz' || p.faction === 'moritani' ||
|
||||
p.faction === 'tleilaxu' || CLASSIC_FACTIONS[p.faction]) &&
|
||||
// Bare 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 && !g.strongholdCards;
|
||||
if ((independentNexusProfile(g) || independentDiscoveryProfile(g)) && byFaction(g, 'ecaz')) return true;
|
||||
if (g.leaderSkills && nativeEcazLeaderSkillsProfile(g)) return true;
|
||||
@@ -10792,7 +10788,7 @@ function ecazOccupyCompositionSupported(g: Game): boolean {
|
||||
g.expansions.includes('ecaz') &&
|
||||
g.expansions.every(id => ['ecaz', 'ix', 'choam'].includes(id)) &&
|
||||
new Set(g.expansions).size === g.expansions.length &&
|
||||
(g.advanced || basicTleilaxu || (g.expansions.length === 1 && g.expansions[0] === 'ecaz' &&
|
||||
(g.advanced || basicNatives || (g.expansions.length === 1 && g.expansions[0] === 'ecaz' &&
|
||||
g.players.every(p => p.faction === 'ecaz' ||
|
||||
p.faction === 'moritani' || CLASSIC_FACTIONS[p.faction]))) &&
|
||||
g.players.length >= 2 && g.players.length <= 6 &&
|
||||
@@ -10810,7 +10806,7 @@ function ecazOccupyCompositionSupported(g: Game): boolean {
|
||||
/** Fresh native Occupy profile; Basic odd counts use the main printed rule provisionally. */
|
||||
export function initializeEcazOccupyGameForAudit(state: Game): Game {
|
||||
requireRule(ecazOccupyCompositionSupported(state),
|
||||
'Occupy requires supported native factions and their selected decks; Basic additionally admits native Tleilaxu with the bare Ecaz and Ix decks.');
|
||||
'Occupy requires supported native factions and their selected decks; bare Basic native families exclude optional modules.');
|
||||
requireFreshBaseRuntime(state);
|
||||
requireFreshFactionInventory(state);
|
||||
const g = initializeSetupGameForAudit(state, false, false, false, false, false, false, true, state.ecazTreachery === true);
|
||||
@@ -34859,7 +34855,7 @@ function applyActionInner(
|
||||
const noFieldPlayers = g.players.filter(player =>
|
||||
player.noField?.deployed?.location.territory === choice.territory &&
|
||||
(player.id === choice.attacker || player.id === choice.defender ||
|
||||
(g.advanced && connected && ecaz && ally?.ally === ecaz.id && player.id === ally.id &&
|
||||
(combined && ecaz && player.id === ally?.id &&
|
||||
(choice.attacker === ecaz.id || choice.defender === ecaz.id)))).map(player => player.id);
|
||||
let mixedNoFieldPlayers: string[] | undefined;
|
||||
for (const playerId of noFieldPlayers) {
|
||||
@@ -34867,8 +34863,8 @@ function applyActionInner(
|
||||
([key, n]) => n > 0 && splitLocation(key).territory === choice.territory,
|
||||
);
|
||||
if (!mixed) continue;
|
||||
requireRule(!combined || g.advanced,
|
||||
'Combined mixed No-Field dialing requires the selected Advanced Occupy composition.');
|
||||
requireRule(!combined || ecazOccupyCompositionSupported(g),
|
||||
'Combined mixed No-Field dialing requires an admitted native Occupy composition.');
|
||||
(mixedNoFieldPlayers ??= []).push(playerId);
|
||||
}
|
||||
if (combined) {
|
||||
|
||||
Reference in new issue
Block a user