Retain original Advanced Strongholds in fresh Semuta games

This commit is contained in:
Quintine committed 2026-10-12 07:24:52 +11:00
1 parent bab8f3403d
commit 03e3d9bdbf
10 files changed
+208 -16

No files matched your search

+19 -12
View File
@@ -5529,7 +5529,8 @@ function treacheryDiscardIntegrity(g: Game) {
requireRule(g.semutaPreview === undefined || g.semutaPreview === true &&
g.expansions.includes('choam') && !!byFaction(g, 'richese') &&
!g.homeworlds && !g.nexusCards && !g.leaderSkills && !g.discoveries &&
!g.discoveryEnabled && (!g.techTokens || nativeFactionTechProfile(g, true)) && !g.strongholdCards,
!g.discoveryEnabled && (!g.techTokens || nativeFactionTechProfile(g, true)) &&
(!g.strongholdCards || nativeStrongholdFactionRoster(g)),
'This Semuta preview no longer matches its original Richese profile.');
const pending = g.pendingTreacheryDiscard;
const sequence = g.treacheryDiscardSequence ?? 0;
@@ -9545,15 +9546,19 @@ export function initializeEcazOccupyGameForAudit(state: Game): Game {
g.ecazOccupyPreview = true;
return g;
}
/** Original E1/E2 Stronghold roster; shared by fresh setup and Semuta validation. */
function nativeStrongholdFactionRoster(g: Game): boolean {
return g.advanced === true && g.players.length >= 2 && g.players.length <= 6 &&
Array.isArray(g.expansions) && g.expansions.length >= 1 && g.expansions.length <= 2 &&
g.expansions.every(id => id === 'ix' || id === 'choam') &&
(g.expansions.length < 2 || g.expansions[0] !== g.expansions[1]) &&
g.players.some(p => faction(p.faction).expansion !== 'base') &&
g.players.every(p => faction(p.faction).expansion === 'base' ||
g.expansions.includes(faction(p.faction).expansion));
}
/** Fresh native Stronghold composition; other overlays and public starts stay gated. */
export function initializeStrongholdFactionsGameForAudit(state: Game): Game {
requireRule(e3StrongholdFactionProfile(state) ||
(state.advanced === true && Array.isArray(state.expansions) &&
state.expansions.length >= 1 && state.expansions.length <= 2 &&
state.expansions.every(id => id === 'ix' || id === 'choam') &&
new Set(state.expansions).size === state.expansions.length &&
state.players.some(p => faction(p.faction).expansion !== 'base') &&
state.players.every(p => faction(p.faction).expansion === 'base' || state.expansions.includes(faction(p.faction).expansion))),
requireRule(e3StrongholdFactionProfile(state) || nativeStrongholdFactionRoster(state),
'Stronghold factions require supported Advanced native factions, classic opponents and their selected distinct decks.');
requireRule(!state.homeworlds && !state.nexusCards && !state.leaderSkills &&
!state.discoveryEnabled && !state.discoveries && !state.discoveryStash && !state.greatMaker &&
@@ -9597,8 +9602,8 @@ export function initializeMoritaniAssassinateGameForAudit(state: Game): Game {
initializeMoritaniAssassinateState(g);
return g;
}
/** Development-only Semuta in fresh Richese games: optional Ix deck and original
* native Tech profile, or bounded Basic native Moritani/E3. Public starts stay gated. */
/** Development-only Semuta in fresh Richese games: original native Tech and
* Advanced Stronghold compositions, or bounded Basic Moritani/E3. Public starts stay gated. */
export function initializeSemutaGameForAudit(state: Game): Game {
const nativeTerror = !state.advanced && state.expansions.length === 2 &&
state.expansions.includes('choam') && state.expansions.includes('ecaz') &&
@@ -9609,8 +9614,10 @@ export function initializeSemutaGameForAudit(state: Game): Game {
state.expansions.includes('choam') &&
(state.expansions.every(id => id === 'choam' || id === 'ix') || nativeTerror) &&
state.players.some(p => p.faction === 'richese'),
'Semuta needs a fresh Richese faction game: CHOAM with optional Ix and original native Tech prerequisites, or Basic native Moritani with CHOAM and Ecaz decks and classic opponents; other optional modules remain excluded.');
const g = initializeFactionExpansionsGameForAudit(state);
'Semuta needs a fresh Richese faction game: CHOAM with optional Ix, original native Tech prerequisites and Advanced Stronghold Cards, or Basic native Moritani with CHOAM and Ecaz decks and classic opponents; other optional modules remain excluded.');
const g = state.strongholdCards
? initializeStrongholdFactionsGameForAudit(state)
: initializeFactionExpansionsGameForAudit(state);
g.semutaPreview = true;
return g;
}
+1 -1
View File
@@ -1176,7 +1176,7 @@ export const RULE_TOPICS: RuleTopic[] = [
'Mandatory and winner battle discards also pause before native Tleilaxu Face Dance. Claim or Continue preserves the original winner’s casualties and card cleanup, then restores the same private Face Dancer opportunity. Replacement, leader death and force sources remain native; the claimed Treachery card stays with its claimant, and no Face Dancer card becomes a Semuta target.',
'Mandatory and winner battle discards also pause before quoted Advanced CHOAM force-payment income. Claim or Continue leaves the original amount unpaid through casualties and card cleanup, then opens the same allow/Karama response. Allow pays once; cancellation sends that income to the bank without refunding the original force payments. The original post-battle market still completes afterward.',
'Mandatory and winner battle discards also pause before a native Auditor opportunity. Claim or Continue preserves the original survival limit and opponent-used card identities, then eligibility and the full cancellation price use the current opposing hand. A card acquired from the other combatant can be eligible if the audited player did not use it. Payment or private inspection resumes once; only CHOAM receives the historical snapshot.',
'Fresh three-through-six-seat Basic/Advanced Richese games with CHOAM and optional Ix may retain original unused Tech Tokens under the existing native roster prerequisites. Mandatory and winner discards now offer Semuta before the original winner takes one loser-owned token. Claim or Continue leaves every token and income ledger in place until original cleanup finishes; the winner’s selected award still precedes Face Dance. Skills, Strongholds, other overlays and the separate Basic Moritani entry remain excluded.',
'Fresh three-through-six-seat Basic/Advanced Richese games with CHOAM and optional Ix may retain original unused Tech Tokens under the existing native roster prerequisites. Mandatory and winner discards now offer Semuta before the original winner takes one loser-owned token. Claim or Continue leaves every token and income ledger in place until original cleanup finishes; the winner’s selected award still precedes Face Dance. Advanced may additionally retain original unused Stronghold Cards at two through six seats; combining Tech requires three through six. The six separate public module cards remain unowned until the actual final Mentat assignment, using the board after effects such as Gamont. Neither Semuta claim nor its original closing CHOAM continuation awards a Stronghold Card early. Skills, other overlays and the separate Basic Moritani entry remain excluded.',
'A mandatory loser-card discard may also offer Semuta while the original winner’s compulsory used card remains reserved. For native Ixians, claim or Continue settles the original casualties, then restores the one-for-one Suboid/Cyborg substitution and its Karama response. The winning used Poison Tooth is not discarded until substitution or decline finishes; only then is that physical Tooth a separate fresh target before optional winner cleanup.',
'In the Basic native Moritani entry, winner compulsory/optional card discards may pause before the losing ally’s original retention choice. After that ally chooses one eligible played card or declines, native Karama finishes first; the completed unkept-card batch then offers Semuta. A kept or unrelated hand card is never a target. Multiple fresh cards require commitment and one private selection; taking a winner’s card does not add it to the original retention pool. Advanced Moritani, Nexus retention and unresolved casualty parents remain separate.',
'A printed Karama canceling native Harkonnen capture, CHOAM Auditor or quoted battle income, Ixian casualty substitution, or Basic Moritani allied retention now offers that exact public cost before the original cancellation finishes. Claim or Continue restores the saved response and cancels once. Acquiring the cost card cannot restore a captive, inspect a hand, pay the canceled income, exchange casualties or keep the proposed allied card. Later native card cleanup and markets still finish; Worthless conversion, other cancellations and module combinations remain separate.',