Accelerate rules-first feedback and integrate native Strongholds

Apply user priority: save/recovery/privacy/custody assurance after all rules. Add quick types/lint, concise failure-preserving reporter, verbose mode, actual empty-execution guard, signal handling and focused verify name selection; compact canonical context/handoffs without mass moves. Tooling15, six negative CLI, named/empty source-bound smokes,206 doc links; same15-case278B vs2455B,2.35s vs2.36s no compute speedclaim. Native Advanced Ix/CHOAM47-card Stronghold profile: actual firstMentat/HMS/sixeffects,18native/four legalpolicies,five genuine2..6games3129actions/no rejection, human390px LAUDR2WNv14 bank2/personal1 plan and real battle. Earlier162/6513 checks before assurance amendment; finalquick25/build/guide pass. No new preservation/privacy audit or public/deployed/full-mode claim.
This commit is contained in:
Quintine committed 2026-10-02 09:30:52 +10:00
1 parent af6d27095c
commit e9830b6ced
27 files changed
+2339 -194

No files matched your search

+29 -7
View File
@@ -8065,7 +8065,7 @@ function finishMandatorySkillVisibility(g: Game) {
}
}
function initializeSetup(g: Game) {
function initializeSetup(g: Game, strongholds = !!g.strongholdCards) {
const ecaz = byFaction(g, 'ecaz');
if (ecaz && g.advanced) g.ecazLoyalty = { player: ecaz.id, card: null };
if (g.discoveryEnabled) g.discoveries = createDiscoveryState(random);
@@ -8073,7 +8073,7 @@ function initializeSetup(g: Game) {
const choam = byFaction(g, 'choam');
if (choam && g.advanced && !choam.leaders.some(isAuditorLeader))
choam.leaders.push(createAuditorLeader());
if (g.strongholdCards) {
if (strongholds) {
requireRule(g.advanced, 'Stronghold Cards require Advanced rules.');
g.strongholdCards = createStrongholdCards();
}
@@ -9077,6 +9077,27 @@ export function initializeFactionExpansionsGameForAudit(state: Game): Game {
!state.discoveryEnabled && !state.discoveries && !state.discoveryStash && !state.greatMaker &&
!state.techTokens && !state.strongholdCards,
'The faction prototype excludes optional modules, including Leader Skills and Discoveries.');
requireFreshFactionInventory(state);
return initializeSetupGameForAudit(state, false, false, false, false, false, false, true);
}
/** Fresh Advanced Ixian/CHOAM composition; normal starts and other modules stay gated. */
export function initializeStrongholdFactionsGameForAudit(state: Game): Game {
requireRule(state.advanced === true && state.expansions.length === 2 &&
state.expansions.includes('ix') && state.expansions.includes('choam') &&
state.players.some(p => p.faction === 'ixians') &&
state.players.some(p => p.faction === 'choam') &&
state.players.every(p => p.faction === 'ixians' || p.faction === 'choam' || faction(p.faction).expansion === 'base'),
'Stronghold factions require Advanced native Ixians and CHOAM, classic opponents, and exactly the Ix and CHOAM decks.');
requireRule(!state.homeworlds && !state.nexusCards && !state.leaderSkills &&
!state.discoveryEnabled && !state.discoveries && !state.discoveryStash && !state.greatMaker &&
!state.techTokens && !state.ecazTreachery &&
(!state.strongholdCards || JSON.stringify(state.strongholdCards) === JSON.stringify(createStrongholdCards())),
'Stronghold factions admit only unused Stronghold Cards, without other optional modules.');
requireFreshFactionInventory(state);
requireFreshBaseRuntime(state);
return initializeSetupGameForAudit(state, false, false, false, false, false, false, true, false, true);
}
function requireFreshFactionInventory(state: Game) {
requireRule(state.richeseCache === undefined && state.richeseRemoved === undefined &&
state.ecazAmbassadors === undefined && state.moritaniTerror === undefined && state.dukeVidal === undefined &&
state.mobileStronghold === undefined && state.ixSetupCards === undefined &&
@@ -9091,7 +9112,6 @@ export function initializeFactionExpansionsGameForAudit(state: Game): Game {
Object.entries(expected).every(([key, value]) => actual[key as keyof Leader] === value);
});
}), 'The faction initializer cannot overwrite existing inventories, leader custody or revival history.');
return initializeSetupGameForAudit(state, false, false, false, false, false, false, true);
}
/** Genuine, explicitly opted-in preview; no player action enables this profile. */
export function initializeMoritaniAssassinateGameForAudit(state: Game): Game {
@@ -9182,7 +9202,7 @@ export function initializeEcazTreacheryGameForAudit(state: Game): Game {
g.ecazTreachery = true;
return initializeSetupGameForAudit(g, false, false, false, false, false, false, true, true);
}
function initializeSetupGameForAudit(state: Game, homeworlds: boolean, nexus = false, ix = false, discovery = false, leaderSkills = false, choam = false, factions = false, ecazTreachery = false): Game {
function initializeSetupGameForAudit(state: Game, homeworlds: boolean, nexus = false, ix = false, discovery = false, leaderSkills = false, choam = false, factions = false, ecazTreachery = false, strongholdFactions = false): Game {
nexusCardsIntegrity(state);
homeworldRule(() => homeworldGameIntegrity(state));
homeworldBattleLossIntegrity(state);
@@ -9200,14 +9220,16 @@ function initializeSetupGameForAudit(state: Game, homeworlds: boolean, nexus = f
(nexus || !g.nexusCards) &&
(ecazTreachery || !g.ecazTreachery) &&
!g.techTokens &&
!g.strongholdCards &&
(strongholdFactions || !g.strongholdCards) &&
(homeworlds || !g.homeworlds) &&
g.players.every((p) =>
FACTIONS.some(
(f) => f.id === p.faction && (homeworlds || nexus || f.expansion === 'base' || (ix && f.expansion === 'ix') || (choam && f.expansion === 'choam') || (factions && g.expansions.includes(f.expansion))),
),
),
factions && nexus
strongholdFactions
? 'The Stronghold faction audit needs a fresh Advanced Ixian/CHOAM lobby without other optional modules.'
: factions && nexus
? 'The paired expansion Nexus audit needs a fresh lobby without other optional modules.'
: factions
? 'The faction prototype supports base factions and the selected expansion factions without optional modules.'
@@ -9219,7 +9241,7 @@ function initializeSetupGameForAudit(state: Game, homeworlds: boolean, nexus = f
? 'The Homeworld setup audit supports implemented deck sets without Tech Tokens or Stronghold Cards.'
: 'The audit initializer supports base factions without expansions or optional modules.',
);
initializeSetup(g);
initializeSetup(g, strongholdFactions || !!g.strongholdCards);
return normalizeAutomaticGame(g);
}
function ecazStartingForcesComplete(p: Player): boolean {
+26
View File
@@ -3157,6 +3157,7 @@ export const RULE_TOPICS: RuleTopic[] = [
'mentat',
'choam-combat',
'mobile-stronghold',
'stronghold-factions',
'choam-modules',
],
checklist: [
@@ -3207,6 +3208,31 @@ export const RULE_TOPICS: RuleTopic[] = [
},
],
},
{
id: 'stronghold-factions',
title: 'Ixians and CHOAM with Stronghold Cards',
category: 'Advanced & expansions',
coverage: 'Partial',
developmentStage: 'Verified',
summary: 'A fresh Advanced development profile connects genuine Ixian and CHOAM setup to all six Stronghold Card effects and native continued games.',
steps: [
'This private local profile requires native Ixians and CHOAM, unique two-to-six-seat rosters with classic opponents, exactly the Ix and CHOAM Treachery Decks and Stronghold Cards alone. Basic, Tleilaxu, Richese, Ecaz, Moritani and other module overlays remain outside it.',
'The canonical combined deck contains 47 physical cards, not 49: CHOAM replaces the two shared Ix cards instead of duplicating them. Genuine setup retains native Ixian starting-card choices, all original leaders and forces, the Advanced CHOAM Auditor and six initially unowned Stronghold Cards.',
'Card ownership begins only at the real first end of Mentat and is retained through the following turn. It is not assigned by a battle fixture or reset on refresh. Hidden Mobile Stronghold interior forces and its outside pointing territory stay distinct.',
'The mobile card copies an advantage of another currently controlled stronghold, not merely a retained card. A sole choice is automatic; multiple choices use the existing public pre-plan selection. Accepted choices stay bound to the same original battle through private plans and saved continuation.',
'Arrakeen provides at most two spice toward actual support, not extra personal cash. Native CHOAM income uses the original bank and player payment shares, including its established traitor and own-donor exclusions. Original cyborg/suboid and starred casualties, bounty and other native income stay separate.',
'Carthag, Habbanya, Sietch Tabr and Tuek’s Sietch retain their existing physical defense, tie, opposing-dial and played-Worthless contracts. This roster has no Richese cache or Stone Burner; that existing cross-roster interaction is not manufactured here.',
'Bounded rule-path evidence covers native first end-Mentat ownership, eighteen original battle/copy cases, all four legal policies and five unstaged complete two-through-six-seat games. A390px human Ixian selected Arrakeen, sealed dial6/support3 with bank2/personal1 and completed the original opposed battle. Earlier comprehensive checks remain dated evidence; save/recovery/privacy/custody assurance now follows all rules. Full-card/faction/module/deployed acceptance and public expansion starts remain open.',
],
related: ['stronghold-cards', 'mobile-stronghold', 'choam-combat', 'setup', 'implementation-checklist'],
checklist: [
{ area: 'Implementation', status: 'Implemented', detail: 'Fresh native Ixian/CHOAM setup, six-card creation, actual end-Mentat ownership and original HMS/copy/CHOAM battle economy compose the existing effects without public-start or old-game changes.', evidence: ['game/engine.ts', 'game/stronghold-cards.ts', 'game/battle-resolution-quote.ts'] },
{ area: 'Player controls', status: 'Implemented', detail: 'Existing gallery, inspector, mobile copy and support controls work through an original local setup at390px: copied bank support costs one actual personal spice and preserves the native opposed battle.', evidence: ['components/stronghold-cards.tsx', 'components/game-table.tsx'] },
{ area: 'AI', status: 'Partial', detail: 'All four projected minimal policies produce legal current copy actions; five genuine Advanced2..6 native games complete. Strategy/calibration and other combinations remain deferred.', evidence: ['game/bots.ts', 'tools/faction-games.ts'] },
{ area: 'Documentation', status: 'Partial', detail: 'Advanced prerequisite, physical47-card identity, native module-only profile, existing effects and pending excluded combinations are explicit.', evidence: ['docs/STRONGHOLD_CARDS.md', 'docs/RULE_DECISIONS.md'] },
{ area: 'Verification', status: 'Partial', detail: 'Native18/four-policy smoke, five unstaged games with3129 accepted actions/no rejections/82JSON restores, human390px rule-control battle and scoped review cover this profile. Earlier162 affected and6513 full checks pass; new save/privacy/custody assurance waits until all rules, not a repeated prototype gate.', evidence: ['tests/fixture-stronghold-factions.ts', 'tests/stronghold-factions-runtime.test.ts', 'tests/stronghold-factions-recovery.test.ts', 'tests/prototype-room.test.ts'] },
],
},
{
id: 'tech-tokens',
title: 'Tech tokens: income, conquest and victory',