Make normal Banker income mandatory in fresh Skills setups
This commit is contained in:
1 parent
628f59b73a
commit
3ed9856578
43 files changed
+1244
-263
No files matched your search
@@ -65,8 +65,7 @@ export function classicDiscoveryLeaderSkillsProfile(game: LeaderSkillProfile): b
|
||||
game.moritaniAssassinatePreview || game.advancedPreview || game.kullPreview ||
|
||||
game.nexusKullPreview || game.guildBetrayalPreview || game.richeseBetrayalPreview ||
|
||||
game.nexusIxianReplacementPreview || game.nexusIxianBetrayalPreview ||
|
||||
game.nexusHarkonnenBetrayalPreview ||
|
||||
game.spiceBankerIncomePreview) return false;
|
||||
game.nexusHarkonnenBetrayalPreview) return false;
|
||||
for (let i = 0; i < players.length; i++) {
|
||||
for (let j = 0; j < i; j++) if (players[j].faction === players[i].faction) return false;
|
||||
let classic = false;
|
||||
|
||||
+11
-56
@@ -2119,7 +2119,7 @@ export type Game = {
|
||||
/** Absent on legacy rooms whose starting cards were already dealt. */
|
||||
setupStage?: 'prediction' | 'skillTreachery' | 'leaderSkills' | 'traitors' | 'forces';
|
||||
leaderSkills?: LeaderSkillsState;
|
||||
/** Fresh local classic profile; earned custody remains with its original faction. */
|
||||
/** Fresh Skills normal income; already-earned spice stays with its original faction. */
|
||||
spiceBankerIncomePreview?: true;
|
||||
spiceBankerIncome?: BankerIncomeState;
|
||||
bureaucratPayments?: {used:BureaucratPaymentUse[];pending?:{
|
||||
@@ -8857,22 +8857,6 @@ function bankerIncomeContext(g: Game): BankerIncomeContext {
|
||||
}))})),
|
||||
assignments: g.leaderSkills?.assignments ?? []};
|
||||
}
|
||||
function bankerIncomeProfile(g: Game): boolean {
|
||||
const classicNexus = classicNexusLeaderSkillsProfile(g);
|
||||
const homeworlds = !!g.homeworlds && !g.expansions.length && !g.nexusCards &&
|
||||
!g.techTokens && !g.strongholdCards && homeworldLeaderSkillsProfile(g);
|
||||
return g.players.length >= 2 && g.players.length <= 6 &&
|
||||
new Set(g.players.map(p => p.faction)).size === g.players.length &&
|
||||
((!g.expansions.length && g.players.every(p => FACTIONS.some(f => f.id === p.faction && f.expansion === 'base'))) ||
|
||||
nativeExpansionLeaderSkillsProfile(g)) &&
|
||||
(!g.nexusCards || classicNexus) && (!g.homeworlds || homeworlds) &&
|
||||
(!g.techTokens || classicTechLeaderSkillsProfile(g) || nativeTechLeaderSkillsProfile(g) || strongholdLeaderSkillsProfile(g) || classicNexus) &&
|
||||
(!g.strongholdCards || strongholdLeaderSkillsProfile(g) || classicNexus) && !g.discoveryEnabled && !g.discoveries && !g.discoveryStash &&
|
||||
!g.greatMaker && !g.ecazTreachery && !g.semutaPreview &&
|
||||
((!g.moritaniAssassinatePreview && !g.moritaniAssassinate) || advancedMoritaniLeaderSkillsProfile(g)) && !g.advancedPreview &&
|
||||
!g.kullPreview && !g.nexusKullPreview && !g.guildBetrayalPreview && !g.richeseBetrayalPreview &&
|
||||
!g.nexusIxianReplacementPreview && !g.nexusIxianBetrayalPreview && !g.nexusHarkonnenBetrayalPreview;
|
||||
}
|
||||
function bankerIncomePaymentSignature(payment: SpiceBankerIncomePayment): string {
|
||||
return JSON.stringify([payment.event, payment.turn, payment.phase, payment.kind, payment.legs]);
|
||||
}
|
||||
@@ -8882,8 +8866,8 @@ function spiceBankerIncomeIntegrity(g: Game): void {
|
||||
'Deferred Spice Banker income requires its fresh local profile.');
|
||||
return;
|
||||
}
|
||||
requireRule(g.spiceBankerIncomePreview === true && bankerIncomeProfile(g) && !!g.leaderSkills && !!g.spiceBankerIncome,
|
||||
'The saved Spice Banker income profile lost its supported physical setup.');
|
||||
requireRule(g.spiceBankerIncomePreview === true && ordinaryLeaderSkillModeSupported(g) && !!g.leaderSkills && !!g.spiceBankerIncome,
|
||||
'The saved Spice Banker income lost its supported Leader Skills setup.');
|
||||
bankerIncomeRule(() => validateBankerIncomeState(g.spiceBankerIncome!, bankerIncomeContext(g)));
|
||||
const continuation = g.pendingTreacheryDiscard?.continuation;
|
||||
const responses = [g, g.pendingExchange, g.pendingNullentropy?.resume, g.pendingRicheseGift?.resume,
|
||||
@@ -10676,27 +10660,6 @@ export function initializeLeaderSkillsGameForAudit(state: Game): Game {
|
||||
if ((mixedE3 || homeworlds || nativeDiscoveryLeaderSkillsProfile(initialized) || pairedE3) && byFaction(initialized, 'ecaz')) initialized.ecazOccupyPreview = true;
|
||||
return initialized;
|
||||
}
|
||||
/** Fresh all-fourteen-card classic or supported native skills; no public income toggle. */
|
||||
export function initializeSpiceBankerIncomeGameForAudit(state: Game): Game {
|
||||
requireRule(bankerIncomeProfile(state) && !state.leaderSkills &&
|
||||
!state.spiceBankerIncomePreview && state.spiceBankerIncome === undefined,
|
||||
'Spice Banker income requires a fresh classic or supported native skill lobby without unsupported optional modules.');
|
||||
requireFreshSetup(state, state.expansions.length > 0);
|
||||
if (state.homeworlds) {
|
||||
const initialized = initializeHomeworldOccupationGameForAudit(state, true);
|
||||
initialized.spiceBankerIncomePreview = true;
|
||||
initialized.spiceBankerIncome = bankerIncomeRule(() => createBankerIncomeState(bankerIncomeContext(initialized)));
|
||||
return initialized;
|
||||
}
|
||||
const g = structuredClone(state);
|
||||
g.leaderSkills = createLeaderSkills(random);
|
||||
g.spiceBankerIncomePreview = true;
|
||||
g.spiceBankerIncome = bankerIncomeRule(() => createBankerIncomeState(bankerIncomeContext(g)));
|
||||
const initialized = initializeSetupGameForAudit(g, false, classicNexusLeaderSkillsProfile(g), false, false, true,
|
||||
g.expansions.length === 1 && g.expansions[0] === 'choam', g.expansions.length > 0);
|
||||
if (advancedMoritaniLeaderSkillsProfile(initialized)) initializeMoritaniAssassinateState(initialized);
|
||||
return initialized;
|
||||
}
|
||||
/** Independent cards keep the actual selected base/E1/E2 physical families. */
|
||||
function independentCardRoster(g: Game): boolean {
|
||||
if (g.expansions.length > 2 ||
|
||||
@@ -10802,6 +10765,12 @@ function initializeSetupGameForAudit(state: Game, homeworlds: boolean, nexus = f
|
||||
? 'Discovery supports fresh classic, selected E1/E2 or standalone E3 factions with optional original Tech or Advanced Strongholds and no other overlays.'
|
||||
: 'The audit initializer supports base factions without expansions or optional modules.',
|
||||
);
|
||||
if (leaderSkills) {
|
||||
requireRule(g.leaderSkills && g.spiceBankerIncomePreview === undefined && g.spiceBankerIncome === undefined,
|
||||
'Normal Spice Banker income starts only with fresh Leader Skills setup.');
|
||||
g.spiceBankerIncomePreview = true;
|
||||
g.spiceBankerIncome = bankerIncomeRule(() => createBankerIncomeState(bankerIncomeContext(g)));
|
||||
}
|
||||
initializeSetup(g, strongholdFactions || !!g.strongholdCards);
|
||||
if (nativeTech && byFaction(g, 'ecaz')) g.ecazOccupyPreview = true;
|
||||
return normalizeAutomaticGame(g);
|
||||
@@ -17600,8 +17569,8 @@ function occupiedPercentageIntegrity(g: Game) {
|
||||
g.pendingHomeworldOccupiedBonus === undefined, 'Occupied source receipts require their original fresh profile.');
|
||||
return;
|
||||
}
|
||||
requireRule(!g.spiceBankerIncomePreview || bankerIncomeProfile(g),
|
||||
'Occupied percentage and deferred Banker routing require their supported classic Homeworld source profile.');
|
||||
requireRule(!g.spiceBankerIncomePreview || ordinaryLeaderSkillModeSupported(g),
|
||||
'Occupied percentage and deferred Banker routing require their supported Leader Skills source context.');
|
||||
if (!g.homeworldOccupiedPercentageLedger) {
|
||||
requireRule(!g.pendingHomeworldOccupiedPercentage && !g.pendingHomeworldOccupiedBonus,
|
||||
'The original occupied percentage ledger is missing.');
|
||||
@@ -29667,20 +29636,6 @@ export function applyAction(state: Game, id: string, action: Action): Game {
|
||||
state = migrateAtomicsTargets(state);
|
||||
state = migrateFremenNexusRevival(state);
|
||||
if (state.spiceBankerIncomePreview) {
|
||||
const keysBySource: Record<string, readonly string[]> = {
|
||||
bid: ['type','amount','allyPayment'], passBid: ['type'],
|
||||
ship: ['type','territory','sector','amount','elite','allyPayment','smuggler'],
|
||||
guildShip: ['type','from','forces','eliteForces','territory','sector','amount','elite','allyPayment'],
|
||||
revive: ['type','amount','elite'], reviveLeader: ['type','leader'], reviveKwisatz: ['type'],
|
||||
emperorRevival: ['type','amount','elite'], passResponse: ['type'],
|
||||
traitorCall: ['type','call','leader'],
|
||||
};
|
||||
const allowed = action.type === 'ship' && action.noField !== undefined && getPlayer(state, id).faction === 'richese'
|
||||
? ['type','territory','sector','amount','elite','allyPayment','smuggler','noField','event']
|
||||
: action.type === 'decision' && state.decision?.kind === 'auctionPayment'
|
||||
? ['type','karama','card'] : keysBySource[action.type];
|
||||
requireRule(!allowed || Object.keys(action).every(key => allowed.includes(key)),
|
||||
'Use only the original native payment fields; Spice Banker income is automatic.');
|
||||
requireRule(!Object.keys(action).some(key => ['actor','bankerIncome','paymentSource','spiceBankerIncome','bankLegs','trainer'].includes(key)),
|
||||
'Spice Banker payment authority comes only from the original native transaction.');
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ export function noOtherLeaderSkillModules(game: LeaderSkillProfile): boolean {
|
||||
!game.discoveryEnabled && !game.strongholdCards && !game.techTokens && !game.ecazTreachery;
|
||||
}
|
||||
|
||||
function nexusLeaderSkillModulesSupported(game: LeaderSkillProfile, assassination = false, discovery = false, betrayal = false, bankerIncome = false): boolean {
|
||||
function nexusLeaderSkillModulesSupported(game: LeaderSkillProfile, assassination = false, discovery = false, betrayal = false): boolean {
|
||||
return !!game.nexusCards && typeof game.advanced === 'boolean' &&
|
||||
!!game.players && game.players.length >= 2 && game.players.length <= 6 &&
|
||||
((discovery && game.discoveryEnabled === true) ||
|
||||
@@ -48,15 +48,12 @@ function nexusLeaderSkillModulesSupported(game: LeaderSkillProfile, assassinatio
|
||||
!game.advancedPreview && !game.kullPreview && !game.nexusKullPreview &&
|
||||
(!game.guildBetrayalPreview || betrayal) && !game.richeseBetrayalPreview &&
|
||||
!game.nexusIxianReplacementPreview && !game.nexusIxianBetrayalPreview &&
|
||||
!game.nexusHarkonnenBetrayalPreview &&
|
||||
(!game.spiceBankerIncomePreview || bankerIncome);
|
||||
!game.nexusHarkonnenBetrayalPreview;
|
||||
}
|
||||
|
||||
/** Fresh classic Nexus/Skills, optionally Homeworlds/Discovery/Tech/Advanced Strongholds. */
|
||||
export function classicNexusLeaderSkillsProfile(game: LeaderSkillProfile): boolean {
|
||||
if (game.expansions.length || !nexusLeaderSkillModulesSupported(game, false, true, false, true)) return false;
|
||||
if (game.spiceBankerIncomePreview && (game.homeworlds || game.discoveryEnabled ||
|
||||
game.discoveries || game.discoveryStash || game.greatMaker)) return false;
|
||||
if (game.expansions.length || !nexusLeaderSkillModulesSupported(game, false, true, false)) return false;
|
||||
const players = game.players!;
|
||||
for (let i = 0; i < players.length; i++) {
|
||||
for (let j = 0; j < i; j++) if (players[j].faction === players[i].faction) return false;
|
||||
@@ -208,13 +205,12 @@ function discoveryLeaderSkillModulesSupported(game: LeaderSkillProfile): boolean
|
||||
!game.advancedPreview && !game.kullPreview && !game.nexusKullPreview &&
|
||||
!game.guildBetrayalPreview && !game.richeseBetrayalPreview &&
|
||||
!game.nexusIxianReplacementPreview && !game.nexusIxianBetrayalPreview &&
|
||||
!game.nexusHarkonnenBetrayalPreview &&
|
||||
!game.spiceBankerIncomePreview;
|
||||
!game.nexusHarkonnenBetrayalPreview;
|
||||
}
|
||||
|
||||
/** Recognize only the explicit overlay; native predicates still own roster/module legality. */
|
||||
function semutaLeaderSkillContext(game: LeaderSkillProfile): boolean {
|
||||
return game.semutaPreview === true && !game.spiceBankerIncomePreview &&
|
||||
return game.semutaPreview === true &&
|
||||
game.expansions.includes('choam') && !!game.players?.some(p => p.faction === 'richese');
|
||||
}
|
||||
|
||||
@@ -491,10 +487,7 @@ function homeworldLeaderSkillModulesSupported(game: LeaderSkillProfile): boolean
|
||||
game.expansions[0] !== 'ecaz' || !players.some(player => player.faction === 'moritani'))) ||
|
||||
game.kullPreview || game.nexusKullPreview || game.guildBetrayalPreview ||
|
||||
game.richeseBetrayalPreview || game.nexusIxianReplacementPreview ||
|
||||
game.nexusIxianBetrayalPreview || game.nexusHarkonnenBetrayalPreview ||
|
||||
(game.spiceBankerIncomePreview && (game.expansions.length || game.nexusCards ||
|
||||
game.discoveryEnabled || game.discoveries || game.discoveryStash || game.greatMaker ||
|
||||
game.techTokens || game.strongholdCards))) return false;
|
||||
game.nexusIxianBetrayalPreview || game.nexusHarkonnenBetrayalPreview) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+8
-8
@@ -4892,12 +4892,12 @@ export const RULE_TOPICS: RuleTopic[] = [
|
||||
category: 'Advanced & expansions',
|
||||
coverage: 'Partial',
|
||||
developmentStage: 'Verified',
|
||||
summary: 'The fresh banker-income preview gains one deferred spice once per phase when another player makes one qualifying payment to the Spice Bank, then collects automatically at native Mentat.',
|
||||
summary: 'Fresh supported all-fourteen Leader Skills setups automatically gain one deferred spice once per phase when another player makes one qualifying payment to the Spice Bank, then collect at native Mentat.',
|
||||
searchText: 'Spice Banker normal income bank payment four spice phase deferred front shield original owner death capture Mentat',
|
||||
steps: [
|
||||
'This separate fresh profile admits classic Basic/Advanced, supported Basic native families, bounded Advanced Ixian/Tleilaxu/CHOAM/Richese plus classic seats with required decks, or separate non-Harkonnen Advanced Moritani. All fourteen skills and native setup remain. Richese cache self-payments and authorized Advanced donor legs count only when actually paid to bank; allowed Emperor or seller income does not. Basic receipts and unrelated module/public gates remain.',
|
||||
'The explicit banker-income Nexus composition admits fresh classic Basic/Advanced all14/all12 setup, optionally original Tech at three or more seats and Advanced Strongholds. Actual bank payment four gains one deferred spice; player-recipient four and a separate Tech payout do not. Original Mentat collects automatically. Homeworlds, Discovery, expansion-family Nexus and Betrayal overlays remain outside this income entry; no starting Nexus hand or played-game conversion is added.',
|
||||
'The separate fresh banker-income --homeworlds composition admits classic Basic/Advanced original occupation and all fourteen Skills, without Nexus, Discovery, Tech, Strongholds or expansion overlays. It uses actual final native/occupied receipt Bank amounts. Bureaucrat diversion combines only with the same payer’s other Bank portions of the same original invoice. Low native income rounds the whole eligible invoice once; extra Bank rounding units and the first eligible diversion contributor are attributed primary-payer-first internally, without funding disclosure. Original occupied shares remain protected and Mentat collects automatically.',
|
||||
'Normal income is mandatory in new ordinary supported all-fourteen Leader Skills setups, including their original supported Homeworld, Nexus, Discovery, Tech, Stronghold and native overlay envelopes. No separate income profile or toggle remains. This adds no new module combination, public start or played-game conversion.',
|
||||
'Original native setup, decks, offers, phase controls and payment recipients remain. Only actual final Bank portions count; authorized donor contributions remain separate payer legs, and allowed Emperor, Guild or seller income does not become a Bank payment.',
|
||||
'Original native/occupied receipts supply final Bank amounts. Bureaucrat diversion combines only with the same payer’s other Bank portions of one original invoice. Low native income rounds the eligible invoice once, with Bank rounding and the first eligible diversion contribution attributed primary-payer-first internally. Funding identities are not disclosed.',
|
||||
'The printed normal band is mandatory once per phase: when another player makes a payment of at least four spice to the Spice Bank, gain one spice and place it in front of the shield. It is an additional bank grant, not a reduction of the payer’s payment or another player’s income.',
|
||||
'Only an actual completed positive bank payment qualifies. A payment to a player, zero/free/waived cost, self-payment, invalid declaration or unfinished possible payment supplies no income. Several smaller payments do not combine to reach four.',
|
||||
'Use the original actual bank portion after recipient and counter settlement, not a quoted fee or guessed wallet change. Paid auctions, funded shipments, paid revival and eligible resolved battle support keep their native continuation once. Canceled Emperor, Guild or Tleilaxu revival income can leave a real bank payment. Tleilaxu self-revival pays the Bank; other-player revival normally pays Tleilaxu. Its separate free-revival bank award is not payer debit: three paid plus that one reward never becomes four paid to the Bank. A stopped shipment supplies no payment.',
|
||||
@@ -4908,15 +4908,15 @@ export const RULE_TOPICS: RuleTopic[] = [
|
||||
'At the real current Mentat opening, collect the uncollected grants automatically once before optional actions and victory. No extra response, counter, confirmation or collect action is added. Collection itself is not another player-to-bank payment.',
|
||||
'This fresh local prototype provisionally keeps already-earned spice with the original gaining faction when the trainer dies, is captured or the skill changes owner. That is a conservative earned-currency custody choice, not an answer to the previously asked universal death/capture question.',
|
||||
'Public projection shows only physical front-shield owner/count and current-phase use. Private payment receipts, exact hidden source amounts, plans, and future skill entitlement are not exposed. Current and collected history survive JSON/recovery without replaying either original payment or collection.',
|
||||
'Bounded development verification covers actual payment families, threshold/recipient/trainer eligibility, deferred budgets, lifecycle custody and authenticated payment/collection races. Native smoke preserves all 33 Treachery Cards and 14 skills; two original-backed-up six-seat Basic/Advanced rooms verify human phone payment, refresh and actual Mentat collection. Local HTTP remains 49/55 with six upstream 503 failures, not green. Existing lower battle spending stays separate; complete skill/module and deployment acceptance remain open.',
|
||||
'Current bounded proof exercises ordinary native World/Nexus/Discovery/Tech/Stronghold and Semuta/Skills setup, real Bank-four versus below-threshold or player-recipient payments, unavailable deferred budgets, native Hajr recovery and original Mentat collection. A played Skills save without income metadata retains its legacy behavior. Two 390px journeys complete 18 original actions, including eight native UI submissions, without app errors or root overflow. Four minimal policies legally continue both contexts. Earlier payment/custody evidence remains historical; comprehensive assurance, complete modes and deployment acceptance remain open.',
|
||||
],
|
||||
related: ['leader-skills', 'battle', 'bidding', 'revival', 'implementation-checklist'],
|
||||
checklist: [
|
||||
{ area: 'Implementation', status: 'Implemented', detail: 'Actual final Bank payer legs, one physical Banker phase grant and original-owner Mentat collection connect through fresh classic and supported native profiles, including the separate classic Homeworld occupation entry. Native/occupied receipts supply actual retained Bank amounts; user-ruled diversion and whole-invoice attribution preserve payer costs. Paid revival remains distinct from free awards; free Terror is not a payment.', evidence: ['game/engine.ts', 'game/spice-banker-income.ts', 'game/homeworld-payment-income.ts', 'tests/homeworld-banker-income.test.ts', 'tests/homeworld-banker-transport.test.ts', 'tests/homeworld-bank-payment.test.ts'] },
|
||||
{ area: 'Implementation', status: 'Implemented', detail: 'Fresh ordinary all-fourteen Skills initializes the existing deferred-income ledger automatically; original supported module and native overlay setup stays authoritative. Actual final Bank payer legs, one physical Banker phase grant and original-owner Mentat collection remain. Existing games are not retrofitted; the separate initializer/profile and opt-ins are removed.', evidence: ['game/engine.ts', 'game/spice-banker-income.ts', 'game/leader-skill-profile.ts', 'game/homeworld-payment-income.ts', 'tools/prototype-room.ts'] },
|
||||
{ area: 'Player controls', status: 'Implemented', detail: 'A full-width read-only public front-shield notice explains unavailable spice and automatic collection; genuine original payment and final Collection controls work at 390px through refresh. No new income action or confirmation.', evidence: ['components/spice-banker-income.tsx', 'components/game-table.tsx'] },
|
||||
{ area: 'AI', status: 'Partial', detail: 'All four minimal legal policies preserve identical available-budget actions with deferred income present or absent. Original wallets exclude front-shield currency; strategy/calibration remain deferred.', evidence: ['game/bots.ts', 'game/spice-banker.ts'] },
|
||||
{ area: 'Documentation', status: 'Partial', detail: 'Printed threshold/phase/collection, original payment separation, provisional earned custody and per-payer composition are explicit. The user-ruled same-payer diversion, primary-first private attribution and whole-invoice low rounding are documented without universal publisher claims.', evidence: ['docs/LEADER_SKILLS_RULES.md', 'docs/SPICE_BANKER_RUNTIME.md', 'docs/HOMEWORLD_PAYMENT_INCOME_RULES.md', 'docs/RULE_DECISIONS.md'] },
|
||||
{ area: 'Verification', status: 'Partial', detail: 'The fresh Homeworld income entry passes292/292 in the frozen related18-file union, types/lint and build. Actual original world-to-world and Junction return Bank tariffs, low Kaitain auction income, isolated HWBANKQA CLI, private390px diversion and native wallet13-to-Mentat14/front0 are exercised. Existing classic/native and Tleilaxu paid/free/self/canceled boundaries remain source-bound evidence. Comprehensive assurance and deployed/full-module acceptance stay open.', evidence: ['tests/fixture-homeworld-banker-income.ts', 'tests/homeworld-banker-income.test.ts', 'tests/homeworld-banker-transport.test.ts', 'tests/homeworld-bank-payment.test.ts', 'tests/spice-banker-income.test.ts', 'tests/spice-banker-income-runtime.test.ts', 'tests/native-banker-income.test.ts', 'tests/prototype-room.test.ts', 'docs/SPICE_BANKER_RUNTIME.md'] },
|
||||
{ area: 'Verification', status: 'Partial', detail: 'Ordinary native World and Semuta programmes cover actual payment, physical trainer, deferred spendability, threshold/recipient exclusions, overlay continuation and once-only Mentat collection. Legacy played saves are not retrofitted. Two actual phone journeys and four legal policies exercise these contexts; this is not exhaustive combination, recovery, strategy or deployed acceptance.', evidence: ['tests/fixture-banker-world-default.ts', 'tests/banker-world-default.test.ts', 'tests/fixture-banker-overlay-default.ts', 'tests/banker-overlay-default.test.ts', 'tests/homeworld-banker-income.test.ts', 'tests/homeworld-banker-transport.test.ts', 'tests/homeworld-bank-payment.test.ts', 'tests/spice-banker-income.test.ts', 'tests/native-banker-income.test.ts', 'tests/prototype-room.test.ts', 'docs/SPICE_BANKER_RUNTIME.md'] },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -4951,7 +4951,7 @@ export const RULE_TOPICS: RuleTopic[] = [
|
||||
'A surviving skilled Sandmaster winner adds three board spice to an existing pile in the battle territory, even with no surviving forces. No pile adds nothing; a single pile resolves automatically. With several remaining positive piles, the winner selects one sector after any Smuggler allocation. Owner selection is a visibly provisional placement policy, not a publisher ruling.',
|
||||
'Rihani normally inspects two random Traitor Deck cards privately, then reshuffles them. A surviving selected native Rihani also offers a separate optional draw of two. Decide before seeing them: once drawn, keep one new card and publicly reveal and return one unused old card. The other new card returns secretly. A captured Rihani grants only the optional exchange. Your private history records both samples; a card just called to win is already used.',
|
||||
'Smuggler can include one free accompanying force in an off-planet shipment into an empty territory. Select the entire physical total; three forces cost the ordinary price of two. The checkbox can decline this optional benefit. Guild rounding follows the free force. Richese may instead ship one separate free reserve force beside its owned No-Field into an empty territory; the marker retains its ordinary price and hidden value. Existing forces, including advisors, prevent the bonus; ordinary Fremen on-planet reinforcement has no bonus.',
|
||||
'Spice Banker can commit one through three own spice with its Battle Plan, separate from force support. Only the surviving selected skilled disc gains that strength. The amount stays private until authorized plan inspection or public reveal. It is paid on win or loss, including leader death, except a sole traitor-call winner spends nothing. Normal deferred income connects only in the separate fresh classic or supported native banker-income profiles, including the bounded Advanced Moritani roster; ordinary/default starts are unchanged.',
|
||||
'Spice Banker can commit one through three own spice with its Battle Plan, separate from force support. Only the surviving selected skilled disc gains that strength. The amount stays private until authorized plan inspection or public reveal. It is paid on win or loss, including leader death, except a sole traitor-call winner spends nothing. Mandatory normal deferred income is automatic in fresh supported ordinary all-fourteen Skills setups; existing games are not retrofitted. Earned-faction custody remains provisional.',
|
||||
'Diplomat may use one committed Worthless as the opponent’s canonical printed defensive role when you played no actual defense: Shield, Snooper, Shield Snooper, defensive Weirding Way/Chemistry, or sealed/actually late-played Portable Snooper. Named protection stays distinct; copying the used role imports no activation, numeric modifier or late-play right. Sealed sources offer after reveal; a new late source may offer before the unresolved outcome, preserving prior false traitor decisions. No fresh opportunity follows a successful traitor declaration. The selected Worthless discards even after a win. Older base/printed-only battles keep their original source windows. Current World/Stronghold contexts retain independent original effects; own earned Carthag may add Snooper to a copied Shield but cannot create protection without a used source. A native Diplomat can protect its selected disc; captives grant no normal band. Surviving trained losers retain the separate printed/copied-strength retreat policy. Mirror/numeric inheritance remains separate.',
|
||||
'Normal Mentat questions use the user-approved uniform private card-show step before posture and faction powers in supported Leader Skills games. The opponent shows the named held weapon or chooses another held card, even for an exact match or sole eligible card. Weirding Way is a nameable default weapon; Chemistry is not. Cards stay held and need not enter a Battle Plan. New battles activate the question without an extra opt-in; already-opened unversioned battles retain their original flow. Empty hands skip without an answer. Private history records an observation, not a later hand guarantee.',
|
||||
'Bureaucrat may redirect two spice when one other player pays at least five to a player other than the skill owner, once per phase. Payer costs stay unchanged; declining preserves later use. Bribes qualify at transfer and remain unavailable until Mentat Pause. Supported ordinary/Richese auctions, Guild shipments and paid Tleilaxu revival have connected paths; a separate free-revival award cannot make a smaller price qualify. Allied payer shares never pool to reach five. Trainer or recipient contributions cannot qualify but do not hide an eligible other payer. Public prompts show gross and recipient, not private shares or which payer qualified. Supported classic and native E1/E2/E3 profiles and Homeworld Skills retain original costs and callbacks. Native Guild/Emperor/revival Karama cancellation resolves before Bureaucrat; Richese retains direct seller credit with no invented cancellation window. Basic has no Black Market; free Karama purchases remain normal-only. By user ruling Bureaucrat takes two off gross before occupied Homeworld allocation. Fresh classic occupation plus Skills now connects this: eight becomes two to Bank, three native and three occupied, with full original payer contributions retained. Decline gives four plus four; native income cancellation preserves the separate occupied share and creates no Bureaucrat offer. The low/occupied Guild two-odd contributor rounding boundary is unchanged. By user ruling Guild Nexus Betrayal also carries Bureaucrat on its holder receipt in the bounded classic Nexus plus Skills composition; the holder receives the fee minus two. Emperor gifts remain excluded by user ruling, without threshold disclosure. Other profiles, overlays and full-mode acceptance remain unfinished.',
|
||||
|
||||
Reference in new issue
Block a user