Compose Semuta recovery with physical Shrine card roles
This commit is contained in:
1 parent
f587374923
commit
5902286db5
13 files changed
+360
-29
No files matched your search
@@ -29,6 +29,24 @@ optional skill bands, combinations and public expansion starts remain open.
|
||||
Rules implementation continues; comprehensive assurance and administration
|
||||
remain deferred until all rules are implemented.
|
||||
|
||||
**Semuta connects both physical Shrine roles — 16 October.**
|
||||
Fresh private `semuta --discoveries` setup retains original Richese/CHOAM,
|
||||
optional Ix, unused Tech3+/Advanced Strongholds and original Discovery7/8.
|
||||
Truthtrance spent as Karama is recoverable before the same original effect;
|
||||
Karama spent as Truthtrance is recoverable after its single definite answer.
|
||||
Neither changes its printed face. Emperor revival does not repeat; original
|
||||
price provenance and normal-auction physical identity remain.
|
||||
|
||||
Affected six-file57/57, eight controlled runtime paths and32 legal policy
|
||||
probes pass. Two controlled390px journeys recover both faces; actual Guild
|
||||
shipment then pays bank3 for three counters, while the reverse path retains
|
||||
one yes answer. Width/scroll390; no application/browser error after isolated
|
||||
host setup repair. No saved room, human server, D1, deployment or public gate
|
||||
changed. Skills/Homeworld/Nexus/E3 composition and final assurance remain
|
||||
separate. [Source and exact evidence](SEMUTA_SOURCE_UPDATE_20260907.md#shrine-physical-role-costs--16-october-2026).
|
||||
Final types/lint and private CLI help pass; current source links and55
|
||||
Semuta evidence paths resolve. No build or broad assurance run in this slice.
|
||||
|
||||
**Semuta preserves native BG conversion and the separate counter cost — 16 October.**
|
||||
Physical Worthless recovery now precedes the same native conversion counter,
|
||||
not its effect. The card stays Worthless in its new faction. A later printed
|
||||
|
||||
@@ -904,6 +904,13 @@ conversion was fabricated.
|
||||
authorizes Truthtrance as Karama or Karama as Truthtrance in the existing effect
|
||||
paths. Cards retain their physical identity and custody. A committed converted
|
||||
Truthtrance retains its use receipt through departure, answering and discard.
|
||||
Fresh private `semuta --discoveries` setup now connects both physical-role
|
||||
discards: recover used Truthtrance without replacing its original Karama
|
||||
effect, or recover used Karama after one committed definite Truthtrance
|
||||
answer. Original CHOAM/optional Ix setup, unused Tech3+/Advanced Strongholds
|
||||
remain; Skills/Homeworlds/Nexus/E3 and public starts stay outside this entry.
|
||||
[Scoped controlled proof](SEMUTA_SOURCE_UPDATE_20260907.md#shrine-physical-role-costs--16-october-2026)
|
||||
is not natural draw/entry or complete-module acceptance.
|
||||
This does not implement missing special powers or resolve their pending rules.
|
||||
|
||||
Great Maker vote/ride, Discovery token/discard, next-turn entry, station and carried
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
# Dune implementation status
|
||||
|
||||
## 16 October 2026 — Semuta connects physical Shrine-role costs
|
||||
|
||||
Fresh private `semuta --discoveries` composes original Richese/CHOAM and
|
||||
optional Ix Discovery setup, with original unused Tech3+/Advanced Strongholds.
|
||||
Live profile validation now retains this admitted composition. Existing
|
||||
Karama continuations accept entitled physical Truthtrance; original auction
|
||||
resumption retains that physical face rather than a printed-Karama flag.
|
||||
Existing clean Truthtrance disposal accepts committed Shrine-source Karama.
|
||||
Claim/pass preserves original effects, one recorded answer and post-revival
|
||||
Emperor timing, with no manufactured card or repeated effect.
|
||||
|
||||
Eight new cases; affected six-file57/57. Eight controlled runtime paths and32
|
||||
legal policy probes pass. Two controlled390px actual-table journeys recover
|
||||
both faces; original Guild delivery pays bank3 for three forces and the
|
||||
reverse path retains one yes answer. Native setup precedes explicitly
|
||||
controlled Shrine placement/occupation/acquisition; this is not natural
|
||||
Discovery draw/entry or full-game evidence. No human server, D1, saved room,
|
||||
deployment or public start gate changed. Existing Skills/Homeworld/Nexus/E3
|
||||
and final-assurance boundaries remain.
|
||||
[Canonical source and proof](SEMUTA_SOURCE_UPDATE_20260907.md#shrine-physical-role-costs--16-october-2026).
|
||||
Final types/lint and actual private CLI help pass. Current source links and55
|
||||
Semuta evidence paths resolve; no production build or broad assurance run.
|
||||
|
||||
## 16 October 2026 — Semuta retains native BG role, conversion and counter costs
|
||||
|
||||
Added `bgKaramaCostDiscard` for the actual Worthless disposal before native
|
||||
|
||||
@@ -677,6 +677,7 @@ dedicated retrieved worked FAQs. [Contract and remaining limits](HOMEWORLD_OCCUP
|
||||
| Semuta on shipment-price activation | Claim/decline of the exact printed activation cost creates the same original half-normal bank-paid grant once. Physical recovery does not change its beneficiary/creator. Under the selected nonduplication extension to provisional stop refunds, a claimed cost is not refundable even if the new holder rediscarded it; Guild may use that same card for its actual stop without returning it to the former owner. Unclaimed refunds remain. This is product composition, not a publisher worked example. | [Source, policy and scoped proof](SEMUTA_SOURCE_UPDATE_20260907.md#shipment-price-cost-and-claimed-card-refund--16-october-2026) |
|
||||
| Semuta on printed native special costs | Preserve each native disposal point and original intent. Most printed costs precede their effect; native Emperor's completed revival precedes its cost disposal and is not repeated. CHOAM's selected hand cards form a separate private simultaneous batch after one earned credit; one fresh other-player card may be selected after commitment, never the earlier activation. Existing once-use, joint costs, native permission/typed custody and E3 entry gates remain unchanged. This composes the printed Semuta rule with existing native order, not a new publisher timing FAQ. | [Source/stages and original versus controlled proof](SEMUTA_SOURCE_UPDATE_20260907.md#printed-native-special-costs-and-choam-cashout--16-october-2026) |
|
||||
| Semuta on native BG conversion/counter costs | The played Worthless is fresh before the original native conversion response; recovery keeps its physical role and cannot bypass that counter. A later printed cancellation is a separate fresh cost and still denies the same conversion. Original four-use opportunity/incoming reservations and older passed history remain. Allowed converted prices retain claimed-cost provenance after real rediscard under the existing nonduplication policy. Kull remains before conversion/discard; Shrine/E3 scope stays separate. | [Native role/source and scoped proof](SEMUTA_SOURCE_UPDATE_20260907.md#native-bg-worthless-and-conversion-counter-costs--16-october-2026) |
|
||||
| Semuta on Shrine physical-role costs | Fresh private Richese/CHOAM/optional Ix Discovery setup composes the existing Shrine role and Semuta rules. An entitled Truthtrance used as Karama retains its physical face through the original price, cancellation, auction or special-cost continuation. Karama committed as Truthtrance is fresh after its single definite answer; recovery never repeats that answer. Emperor revival retains its original post-effect disposal. This is component composition, not a new publisher timing FAQ; Skills/Homeworld/Nexus/E3 and public gates remain separate. | [Source, controlled evidence and limits](SEMUTA_SOURCE_UPDATE_20260907.md#shrine-physical-role-costs--16-october-2026) |
|
||||
| Purchased price with immune Junction | Keep the original offered half/full tariff and normal payees; no quarter price or bank-only overlay. Under the standing choose-recommendation instruction, accepting this source with a purchased grant requires explicit acknowledgment that it ends unused, with no card refund. Consume only upon actual delivery, not failed, stale, unfunded or deferred acceptance; the ordinary purchased route remains available. This is a conservative product composition, not a publisher worked example. | [Source immunity and selected choice](JUNCTION_TRANSPORT_RULES.md#purchased-price-and-immune-offer--15-october-2026), [original versus controlled proof](JUNCTION_TRANSPORT_RUNTIME.md#purchased-price-source-choice--15-october-2026) |
|
||||
| Deferred shipment arrival | Quote unsupported ordinary arrivals before saving Guild interception. A validated legacy ordinary declaration may return unspent on the typed arrival error; corrupted declarations and special parent/card receipts are not silently cleared. This repairs continuation without deciding simultaneous reaction priority. | [Reproduction and bounded recovery](DEFERRED_SHIPMENT_ARRIVAL.md) |
|
||||
| Native Ambassador own-arrival continuation | Under the standing choose-recommended-option instruction, reuse committed entry after its own Guild income, BG Intrusion and accompaniment controls. Existing callbacks put a legitimate accompanying BG fighter child before the deferred original entrant; each sees the then-live token, so declining the child preserves a later original offer and consuming it does not recreate a token. Advisors remain exempt. This child-first/live-token composition is provisional, not a located publisher priority ruling. Actual busy controls, unsupported paired/module guards and separate native rate-window admission remain distinct. | [Native original-action evidence and boundary](DEFERRED_SHIPMENT_ARRIVAL.md#native-own-arrival-continuations--15-october-2026) |
|
||||
|
||||
@@ -2,6 +2,28 @@
|
||||
|
||||
Read-only engine audit, 2026-09-07. Read the complete `docs/SEMUTA_DRUG_ENGINE_AUDIT.md`, then inspected every current `discard(...)` call, direct Treachery-discard mutation and `draw(g)` caller in `game/engine.ts`, plus the Truthtrance discard callback and pure Box/Distrans results. Names below are integration anchors; approximate current lines are navigation aids only. This report adopts no additional source ruling and changes no project file.
|
||||
|
||||
## Shrine physical-role stages — 16 October 2026
|
||||
|
||||
Fresh private `semuta --discoveries` setup retains the original Discovery
|
||||
roster/modules; unsupported Skills/Homeworld/Nexus/E3 overlays stay excluded.
|
||||
The existing Karama cost continuations accept an entitled physical
|
||||
Truthtrance without changing its face. Auction and price resumption carry
|
||||
that committed physical card; claim/pass preserves the original owner,
|
||||
recipient, lot, payment and once-use. Emperor's post-revival disposal never
|
||||
repeats its completed revival.
|
||||
|
||||
`truthtranceDiscard` also accepts the already-validated `source: shrine`
|
||||
receipt for physical Karama after one definite answer. No fresh occupancy
|
||||
check is imposed on that committed Truthtrance role; existing history,
|
||||
promise, parent signatures and clean-continuation restrictions remain.
|
||||
Semuta recovery changes custody, not the recorded answer or printed face.
|
||||
|
||||
[Scoped evidence](SEMUTA_SOURCE_UPDATE_20260907.md#shrine-physical-role-costs--16-october-2026):
|
||||
57 affected cases, eight controlled runtime paths,32 legal policy probes and
|
||||
two controlled390px journeys. This is not original Discovery acquisition,
|
||||
full-combination or saved/deployed assurance.
|
||||
|
||||
|
||||
## Native BG cost and counter stages — 16 October 2026
|
||||
|
||||
The actual physical Worthless creates `bgKaramaCostDiscard` before the
|
||||
|
||||
@@ -2,6 +2,54 @@
|
||||
|
||||
7 September 2026. Read `docs/SEMUTA_DRUG_ENGINE_AUDIT.md` in full, inspected the physical card again, checked current capacity/recovery code, and freshly searched publisher sources. No project runtime edits.
|
||||
|
||||
## Shrine physical-role costs — 16 October 2026
|
||||
|
||||
The private `semuta --discoveries` entry now composes original fresh Richese/
|
||||
CHOAM and optional Ix setup with Discovery's seven Spice Cards/eight tokens,
|
||||
Basic/Advanced2–6, optional unused Tech3+ and Advanced Strongholds. Skills,
|
||||
Homeworlds, Nexus and E3 overlays, played-save conversion and public starts
|
||||
remain excluded. Live admission uses the same Discovery roster contract.
|
||||
|
||||
Existing [Shrine roles](DISCOVERY_PROTOTYPE.md#connected-behavior) and printed
|
||||
Semuta recovery compose without changing physical card identity. A current
|
||||
revealed-Shrine fighter may spend Truthtrance through the existing Karama
|
||||
price, cancellation, normal-auction purchase/payment and special-cost paths.
|
||||
The fresh cost retains that physical Truthtrance. Claim/pass resumes the
|
||||
original effect, not a BG conversion or a new source owned by the claimant.
|
||||
Native Emperor revival remains before its cost disposal and is never repeated.
|
||||
Auction continuation receives the committed physical card rather than
|
||||
manufacturing a printed-Karama flag.
|
||||
|
||||
Conversely, Karama committed as Truthtrance retains its `source: shrine`
|
||||
receipt. Its completed definite answer now offers that physical Karama to
|
||||
Semuta under the existing clean Truthtrance continuation restrictions.
|
||||
Recovery does not ask again, append another answer or reclassify the card.
|
||||
This connects existing component rules; it claims no new publisher timing FAQ.
|
||||
|
||||
Eight new behavior cases and the six-file affected union pass **57/57**.
|
||||
Eight runtime claim/pass paths and32 legal policy probes cover both roles,
|
||||
both modes and all four profiles. Fixtures use genuine ready/setup/first
|
||||
Movement, then **controlled Shrine placement, occupation and conserved hand
|
||||
acquisition**; auction/Revival tests explicitly stage their later clocks.
|
||||
These are not natural Discovery draw/entry or complete-game evidence.
|
||||
|
||||
Two actual styled390×844 table journeys recover each physical face. The price
|
||||
journey then declares three Guild forces, uses its actual Allow shipment
|
||||
control and pays bank3: spice5→2, reserves15→12, Wind Pass14 gains3; the grant
|
||||
retires while Richese holds physical Truthtrance. The reverse journey keeps
|
||||
one yes answer while Richese holds physical Karama. Width/scroll390 and no
|
||||
browser/application errors after correcting isolated host setup. Only an
|
||||
owned memory-only loopback host ran; no human server, D1, saved room,
|
||||
deployment or public gate changed. Proof is outside Git:
|
||||
`/tmp/dune-shrine-runtime.json`, `/tmp/dune-shrine-ui-proof.json`.
|
||||
Full combinations, recovery/deployed assurance and all five Semuta facets
|
||||
remain Partial.
|
||||
Final `npm run check:quick` passes. The actual private CLI help runs and
|
||||
includes the new composition; five current source links and55 Semuta test
|
||||
evidence paths resolve. No production build, broad suite or HTTP assurance
|
||||
was run for this bounded rules slice.
|
||||
|
||||
|
||||
## Native BG Worthless and conversion-counter costs — 16 October 2026
|
||||
|
||||
`bgKaramaCostDiscard` offers the actual played **Worthless** before the native
|
||||
|
||||
@@ -23,10 +23,12 @@ export function discoveryModeSupported(game: FactionModuleProfile): boolean {
|
||||
(game.techTokens && game.players.length < 3) || game.expansions.length > 2 ||
|
||||
(game.strongholdCards && !game.advanced) || game.leaderSkills || game.nexusCards ||
|
||||
game.ecazTreachery ||
|
||||
game.semutaPreview || game.advancedPreview || game.kullPreview || game.nexusKullPreview ||
|
||||
game.advancedPreview || game.kullPreview || game.nexusKullPreview ||
|
||||
game.guildBetrayalPreview || game.richeseBetrayalPreview ||
|
||||
game.nexusIxianReplacementPreview || game.nexusIxianBetrayalPreview || game.nexusHarkonnenBetrayalPreview)
|
||||
return false;
|
||||
if (game.semutaPreview && (game.homeworlds || !game.expansions.includes('choam') ||
|
||||
!game.players.some(player => player.faction === 'richese'))) return false;
|
||||
const e3 = game.expansions.length === 1 && game.expansions[0] === 'ecaz';
|
||||
for (let i = 0; i < game.expansions.length; i++) {
|
||||
const expansion = game.expansions[i];
|
||||
|
||||
+29
-17
@@ -5447,6 +5447,11 @@ function semutaEmperorShareKaramaResponse(g: Game, response: ResponseWindow): bo
|
||||
response.amount! > 0 && (response.elite === undefined || response.elite === 0 || response.elite === 1) &&
|
||||
!g.battle && !g.pendingShipment && !g.pendingGuildTransport;
|
||||
}
|
||||
/** Preserve physical identity: a Shrine authorizes the role, not a manufactured card. */
|
||||
function semutaKaramaRoleCost(g: Game, owner: string, card: Card): boolean {
|
||||
return card.effect === 'karama' || (card.effect === 'truthtrance' &&
|
||||
canUseAsKaramaRole(g, getPlayer(g, owner), card));
|
||||
}
|
||||
/** Original paid income sources; cancellation never reverses the completed transaction. */
|
||||
function semutaIncomeKaramaResponse(g: Game, response: ResponseWindow): boolean {
|
||||
if (g.battle || g.pendingShipment || g.pendingGuildTransport ||
|
||||
@@ -5643,7 +5648,7 @@ function specialKaramaDiscardSignature(g: Game, c: SpecialKaramaDiscardContinuat
|
||||
function stageSpecialKaramaCost(
|
||||
g: Game, intent: SpecialKaramaIntent, card: Card, complete: boolean,
|
||||
): boolean {
|
||||
if (!g.semutaPreview || card.effect !== 'karama') return false;
|
||||
if (!g.semutaPreview || !semutaKaramaRoleCost(g, intent.owner, card)) return false;
|
||||
return stageSpecialKaramaDiscard(g, intent,
|
||||
[{ card, discardedBy: intent.owner, publicFace: true }], complete ? 'complete' : 'effect');
|
||||
}
|
||||
@@ -6090,15 +6095,17 @@ function tupileDiscardSignature(g: Game, c: TupileDiscardContinuation) {
|
||||
});
|
||||
}
|
||||
function treacheryDiscardIntegrity(g: Game) {
|
||||
const discovery = g.discoveryEnabled === true && !!g.discoveries && discoveryModeSupported(g);
|
||||
requireRule(g.semutaPreview === undefined || g.semutaPreview === true &&
|
||||
g.expansions.includes('choam') && !!byFaction(g, 'richese') &&
|
||||
(!g.homeworlds || g.homeworldOccupationPreview === true && semutaHomeworldRoster(g)) &&
|
||||
(!g.nexusCards || semutaNexusProfile(g)) &&
|
||||
(!g.leaderSkills || ordinaryLeaderSkillModeSupported(g)) && !g.discoveries &&
|
||||
!g.discoveryEnabled && (!g.techTokens || (g.nexusCards
|
||||
(!g.leaderSkills || ordinaryLeaderSkillModeSupported(g)) &&
|
||||
((!g.discoveries && !g.discoveryEnabled) || discovery) &&
|
||||
(!g.techTokens || discovery || (g.nexusCards
|
||||
? semutaNexusProfile(g) : g.leaderSkills
|
||||
? nativeTechLeaderSkillsProfile(g) : nativeFactionTechProfile(g, true))) &&
|
||||
(!g.strongholdCards || nativeStrongholdFactionRoster(g)),
|
||||
(!g.strongholdCards || discovery || nativeStrongholdFactionRoster(g)),
|
||||
'This Semuta preview no longer matches its original Richese profile.');
|
||||
const pending = g.pendingTreacheryDiscard;
|
||||
const sequence = g.treacheryDiscardSequence ?? 0;
|
||||
@@ -6487,7 +6494,7 @@ function treacheryDiscardIntegrity(g: Game) {
|
||||
batch.cause === `karama:${c.use.response.kind}` &&
|
||||
batch.entries.length === 1 &&
|
||||
entry.publicFace && entry.discardedBy === c.player &&
|
||||
entry.card.id === c.card && entry.card.effect === 'karama' &&
|
||||
entry.card.id === c.card && semutaKaramaRoleCost(g, c.player, entry.card) &&
|
||||
g.players.some(p => p.id === c.player) &&
|
||||
c.stateSignature === karamaResponseDiscardSignature(g, c),
|
||||
'The spent Karama no longer matches its suspended native cancellation.',
|
||||
@@ -6529,7 +6536,7 @@ function treacheryDiscardIntegrity(g: Game) {
|
||||
batch.entries.every((entry, index) => !entry.publicFace && entry.discardedBy === c.player &&
|
||||
entry.card.id === cashout[index] && entry.card.id !== c.card)
|
||||
: batch.cause === `specialKarama:${c.intent.kind}` && batch.entries.length === 1 &&
|
||||
entry.card.id === c.card && entry.card.effect === 'karama' &&
|
||||
entry.card.id === c.card && semutaKaramaRoleCost(g, c.player, entry.card) &&
|
||||
entry.publicFace && entry.discardedBy === c.player) &&
|
||||
c.stateSignature === specialKaramaDiscardSignature(g, c),
|
||||
'The spent special Karama no longer matches its original native activation.',
|
||||
@@ -6543,7 +6550,7 @@ function treacheryDiscardIntegrity(g: Game) {
|
||||
c.use.kind === 'shipment' && c.use.card === c.card &&
|
||||
batch.cause === 'karama:shipment' && batch.entries.length === 1 &&
|
||||
entry.publicFace && entry.discardedBy === c.player &&
|
||||
entry.card.id === c.card && entry.card.effect === 'karama' &&
|
||||
entry.card.id === c.card && semutaKaramaRoleCost(g, c.player, entry.card) &&
|
||||
g.players.some(p => p.id === c.player) &&
|
||||
c.stateSignature === karamaShipmentPriceDiscardSignature(g, c),
|
||||
'The spent Karama no longer matches its original shipment-price purchase.',
|
||||
@@ -6559,7 +6566,7 @@ function treacheryDiscardIntegrity(g: Game) {
|
||||
batch.cause === (c.kind === 'karamaPaymentDiscard' ? 'karama:auctionPayment' : 'karama:purchase') &&
|
||||
batch.entries.length === 1 &&
|
||||
entry.publicFace && entry.discardedBy === c.player &&
|
||||
entry.card.id === c.card && entry.card.effect === 'karama' &&
|
||||
entry.card.id === c.card && semutaKaramaRoleCost(g, c.player, entry.card) &&
|
||||
g.players.some(p => p.id === c.player) &&
|
||||
c.stateSignature === karamaAuctionDiscardSignature(g, c),
|
||||
'The spent Karama no longer matches its reserved auction settlement.',
|
||||
@@ -7402,7 +7409,7 @@ function semutaOfferSupported(
|
||||
!g.players.some(p => p.faction === 'ecaz' || p.faction === 'moritani') &&
|
||||
!g.pendingArrivalOverlap))) &&
|
||||
!(continuation.kind === 'truthtranceDiscard' &&
|
||||
continuation.consumed.source === undefined &&
|
||||
(continuation.consumed.source === undefined || continuation.consumed.source === 'shrine') &&
|
||||
(continuation.promise === null ||
|
||||
continuation.promise.kind === 'shipment' ||
|
||||
continuation.promise.kind === 'battle'))) return false;
|
||||
@@ -7839,7 +7846,7 @@ function finishTreacheryDiscard(g: Game, claim?: { player: string; card: string
|
||||
g.pendingKarama = next.resume.pendingKarama;
|
||||
g.phaseOpening = next.resume.phaseOpening;
|
||||
const claimed = !g.discard.some(card => card.id === next.card);
|
||||
completeKarama(g, getPlayer(g, next.player), next.use);
|
||||
completeKarama(g, getPlayer(g, next.player), next.use, pending.batch.entries[0].card);
|
||||
if (claimed) g.karamaShipping!.costClaimed = true;
|
||||
} else if (next.kind === 'karamaCharityDiscard' ||
|
||||
next.kind === 'karamaInflationDiscard' ||
|
||||
@@ -7858,7 +7865,7 @@ function finishTreacheryDiscard(g: Game, claim?: { player: string; card: string
|
||||
g.phaseOpening = next.resume.phaseOpening;
|
||||
const use: KaramaUse = 'use' in next ? next.use :
|
||||
{ kind: next.kind === 'karamaPurchaseDiscard' ? 'purchase' : 'auctionPayment' };
|
||||
completeKarama(g, getPlayer(g, next.player), use);
|
||||
completeKarama(g, getPlayer(g, next.player), use, pending.batch.entries[0].card);
|
||||
} else if (next.kind === 'amalDiscard') {
|
||||
g.response = next.resume.response;
|
||||
g.decision = next.resume.decision;
|
||||
@@ -10501,12 +10508,16 @@ export function initializeSemutaGameForAudit(state: Game, skills = false): Game
|
||||
(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 supported original modules/skills; separate exact-CHOAM Homeworld occupation has no other modules, while Basic Moritani uses CHOAM/Ecaz and classics without modules. Other overlays remain excluded.');
|
||||
if (state.discoveryEnabled) requireRule(!nativeTerror && !skills && !state.homeworlds &&
|
||||
!state.nexusCards && discoveryModuleProfile(state),
|
||||
'Semuta Discovery keeps original Richese/CHOAM and optional Ix setup, without Skills, Homeworlds, Nexus or E3 overlays.');
|
||||
if (state.nexusCards) requireRule(!nativeTerror && !state.homeworlds &&
|
||||
!state.discoveryEnabled && !state.discoveries,
|
||||
'Semuta Nexus retains original E1/E2 rosters without Homeworlds, Discovery or E3.');
|
||||
if (state.homeworlds) requireRule(!skills && semutaHomeworldRoster(state),
|
||||
'Semuta Homeworlds require original Richese/CHOAM and classic factions, exact CHOAM, and no other modules.');
|
||||
const g = state.homeworlds ? initializeHomeworldOccupationGameForAudit(state)
|
||||
const g = state.discoveryEnabled ? initializeDiscoveryGameForAudit(state)
|
||||
: state.homeworlds ? initializeHomeworldOccupationGameForAudit(state)
|
||||
: skills ? initializeLeaderSkillsGameForAudit(state)
|
||||
: state.nexusCards ? state.expansions.length === 1 && !!byFaction(state, 'choam')
|
||||
? initializePairedNexusGameForAudit(state) : initializeNexusGameForAudit(state)
|
||||
@@ -14490,11 +14501,12 @@ function spendKarama(g: Game, p: Player, card: Card, use: KaramaUse, kullOffered
|
||||
if (!kullOffered && beginKullAttempt(g, p, card, { kind: 'ordinary', use }, promiseProven)) return;
|
||||
if (use.kind === 'shipment') use = { ...use, card: card.id };
|
||||
const used = discard(g, p, card.id);
|
||||
const guildShipmentDiscard = g.semutaPreview && card.effect === 'karama' &&
|
||||
const semutaRoleCost = g.semutaPreview && semutaKaramaRoleCost(g, p.id, card);
|
||||
const guildShipmentDiscard = semutaRoleCost &&
|
||||
use.kind === 'cancel' && semutaGuildShipmentKaramaResponse(g, use.response);
|
||||
const bgConversionCancelDiscard = g.semutaPreview && card.effect === 'karama' &&
|
||||
const bgConversionCancelDiscard = semutaRoleCost &&
|
||||
use.kind === 'cancel' && semutaBgConversionCancelResponse(g, use.response, g.pendingKarama);
|
||||
if (g.semutaPreview && card.effect === 'karama' &&
|
||||
if (semutaRoleCost &&
|
||||
use.kind === 'cancel' &&
|
||||
(use.response.kind === 'choamCharity' ||
|
||||
use.response.kind === 'choamInflation' ||
|
||||
@@ -14531,7 +14543,7 @@ function spendKarama(g: Game, p: Player, card: Card, use: KaramaUse, kullOffered
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (g.semutaPreview && card.effect === 'karama' &&
|
||||
if (semutaRoleCost &&
|
||||
(use.kind === 'purchase' || use.kind === 'auctionPayment')) {
|
||||
const continuation: KaramaAuctionDiscardContinuation = {
|
||||
kind: use.kind === 'purchase' ? 'karamaPurchaseDiscard' : 'karamaPaymentDiscard',
|
||||
@@ -14547,7 +14559,7 @@ function spendKarama(g: Game, p: Player, card: Card, use: KaramaUse, kullOffered
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (g.semutaPreview && card.effect === 'karama' && use.kind === 'shipment') {
|
||||
if (semutaRoleCost && use.kind === 'shipment') {
|
||||
const continuation: KaramaShipmentPriceDiscardContinuation = {
|
||||
kind: 'karamaShipmentPriceDiscard', player: p.id, card: used.id, use,
|
||||
resume: { response: g.response, decision: g.decision,
|
||||
|
||||
+8
-6
@@ -1203,8 +1203,9 @@ export const RULE_TOPICS: RuleTopic[] = [
|
||||
'A printed Karama canceling original paid Guild shipment income, non-Ambassador Emperor auction income or Richese special-purchase income also offers its exact public cost before the native denial. The price and physical transaction have already committed: claim or Continue cannot refund spice, re-ship forces, undo cache acquisition or replay a purchase. Original Movement, next-lot inspection or the Richese purchase’s suspended controls resume once. A winner may spend the very Karama it just bought; claiming that identity does not reverse its payment. Homeworld and Ambassador payment compositions remain separate.',
|
||||
'A printed Karama canceling native Guild transport permission or shipment rate now offers that exact public cost while the original reserve, cross/return or typed Homeworld declaration remains unpaid. Claim or Continue restores and applies that cancellation once. Recovering the cost never restores a denied route, retains the native discount, finances an unfunded group or repeats shipment. Ordinary movement and legal replacements remain; independent price grants stay distinct.',
|
||||
'A printed Karama buying another active player’s shipment price also offers its exact fresh cost before that same original grant activates. Claim or Continue preserves the original beneficiary, creator and half-normal bank-paid price. Physical recovery ends the provisional stop-refund eligibility for that cost, even if the claimant later discards it again. Guild can spend that very recovered card for an actual special stop without also refunding it to the former owner. Unclaimed original costs retain their older refund; this is selected source composition, not a publisher worked example.',
|
||||
'Printed native special-Karama costs now offer Semuta at their original disposal point. Recovery or Continue resumes the same committed native effect once even when its physical cost changed hands. Emperor revival already happened before its native disposal and is not repeated. CHOAM has a separate later private batch for its selected cashout cards after one earned credit: commit before inspection and recover one fresh card, never the old activation or one per discarded card. Original once-use, typed sources and refund remain; Advanced E3 entry and Shrine-source costs keep separate gates.',
|
||||
'Printed native special-Karama costs now offer Semuta at their original disposal point. Recovery or Continue resumes the same committed native effect once even when its physical cost changed hands. Emperor revival already happened before its native disposal and is not repeated. CHOAM has a separate later private batch for its selected cashout cards after one earned credit: commit before inspection and recover one fresh card, never the old activation or one per discarded card. Original once-use, typed sources and refund remain; Advanced E3 entry keeps its separate gate.',
|
||||
'A native Advanced BG Worthless-as-Karama cost also offers its actual physical card before the original conversion response. Claim or Continue cannot turn that card into a printed Karama, grant BG’s role to its new faction or bypass its native counter. A later printed counter cost is a different fresh event; taking it still denies the conversion. Original shipment/power/auction/winning-payment bindings and passed history remain. Allowed converted prices retain claimed-cost provenance even after later real CHOAM disposal, without a duplicate stop refund.',
|
||||
'The private semuta --discoveries entry composes original Richese/CHOAM and optional Ix Discovery setup, optionally unused Tech3+ and Advanced Strongholds, without Skills, Homeworlds, Nexus or E3. An entitled physical Truthtrance used as Karama offers its original fresh cost before the same price, cancellation, normal-auction or native special effect resumes. Emperor revival already happened and is not repeated. A physical Karama used as Truthtrance offers after its single definite answer. Recovery changes custody, never the printed face or original effect. Controlled Shrine setup evidence is not natural draw/entry or complete-mode acceptance.',
|
||||
'The separate fresh semuta --homeworlds entry retains original Richese/CHOAM and classic Homeworld occupation setup with exact CHOAM and no other modules. Paid Box search, clean Distrans transfer, definite Truthtrance answers, used ordinary specials, paid Kaitain disposal, Tupile cleanup and printed Karama canceling native Guild/Emperor/Richese-purchase income offer Semuta. Native printed Kulon, Baliset, La La La, Trip to Gamont and Jubba costs also pause before their original effect: claim/pass adds one movement bonus, denies free allowance without charging/moving forces, stops the uncommitted Baliset move, returns one original board counter before the same CHOAM close, or applies protection before the same recorded storm moves. Printed Karama canceling these powers pauses separately before denial; the retained Worthless fuel is not a candidate. A canceled reactive Baliset resumes its original declared move once; canceled Kulon/La La La/Gamont/Jubba do not apply their effects. A recovered card grants no other faction CHOAM power. Kaitain private groups require commitment before selection; each Tupile holder has a separate cost. Native income denial retains payment and the original occupied-share allocation. Basic unresolved epochs, Kull, other producers and public starts remain guarded.',
|
||||
'Legal completed CHOAM market sales also offer their used card in the Homeworld profile. Worthless cashout keeps its original two-spice credit; a non-Worthless duplicate keeps its three-spice credit and the original same-name witness stays held. The high-Tupile Worthless-sale prohibition still applies, including duplicate Worthless sales. Claim/pass cannot repeat payout, undo the actual reserve shipment or replace the original market close; no new bank-income interpretation is made.',
|
||||
'Final Ornithopter disposal also offers its used card in the Homeworld profile after the one-group range-three or original two-group movement completes, including an early end with no useful original group. Claim/pass cannot move those counters again or replay the paid native shipment; prior-move/Hajr, advisor and Homeworld-transfer boundaries remain. Clean Sapho Once Around and unstarted Movement first/last costs likewise offer after reordering the finite unacted queue. Earlier bids/funding and physical storm order stay committed, and the same next bidder or combined turn resumes once. Cyclic auctions, partly completed turns, first-versus-Guild and late battle timing are not opened.',
|
||||
@@ -1229,31 +1230,31 @@ export const RULE_TOPICS: RuleTopic[] = [
|
||||
area: 'Implementation' as const,
|
||||
status: 'Partial' as const,
|
||||
detail:
|
||||
'The Richese preview interrupts clean ordinary-card, paid Box, Ornithopter, Distrans, Truthtrance, four Sapho scopes, pre-leader Residual Poison, printed Karama canceling clean CHOAM Charity, Inflation or Bene Gesserit Charity or settling a normal auction purchase or winning bid, a completed CHOAM sale, clean Kulon, proactive or reactive La La La/Baliset and ordinary Trip to Gamont Worthless use, accepted printed Jubba before storm protection, Ix-deck Thumper/Amal and three battle discard stages, including before native Advanced Harkonnen capture. A private normal-auction or Black Market Ixian ally replacement pauses before its draw with a neutral, face-hidden offer; original payment and seller income settle once. Cache purchases retain their native allied-replacement prohibition. Ordinary definite Truthtrance answers pause whether or not another question remains reserved, and also when the answer bound a supported shipment or unsubmitted battle-plan promise. CHOAM sale income is committed before its neutral offer and the same market resumes once; Kulon adds one movement range, La La La blocks one target’s free revival, Baliset restricts the chosen player’s movement, ordinary Trip returns one selected force, and Jubba protects one CHOAM territory only after their offers. Karama’s physical cost is discarded before its neutral offer; the original response is canceled or the reserved lot settles once. Residual Poison commits one random leader death; Sapho commits its finite priority. Thumper waits before worm/spice draw; Amal restores an already-halved opening. Owner-only candidates and one physical Semuta transfer retain privacy. The user-approved full-hand exchange preserves final hand count and incoming reservations. Other Karama uses, other reactive Worthless uses, other private discards, nested responses and other pending rewards remain unfinished. Printed native Guild permission/rate costs now use a dedicated unpaid shipment continuation for reserve, cross/return and typed Homeworld sources; claim/pass applies the same denial/repricing once without delivery replay or invented funding. Printed shipment-price activation now has its own continuation: claim/decline creates the same original price once. Recovered physical cost retains the beneficiary/creator but loses provisional refund eligibility even after rediscard; the same recovered card can pay a real stop without being returned to its former owner. Printed native special costs now resume one committed native effect through effect/complete/cashout stages. Original Emperor post-revival disposal is preserved; CHOAM selected cards are a later private simultaneous batch after one credit. Existing native once-use, joint ordering and typed parent remain. Native BG physical Worthless cost now precedes the single original conversion emitter; the separately printed cancellation cost retains that pending use and still denies it. All four use bindings, incoming reservations and older passes remain. Allowed converted prices carry claimed-cost provenance through actual later rediscard/refund.',
|
||||
"The Richese preview interrupts clean ordinary-card, paid Box, Ornithopter, Distrans, Truthtrance, four Sapho scopes, pre-leader Residual Poison, printed Karama canceling clean CHOAM Charity, Inflation or Bene Gesserit Charity or settling a normal auction purchase or winning bid, a completed CHOAM sale, clean Kulon, proactive or reactive La La La/Baliset and ordinary Trip to Gamont Worthless use, accepted printed Jubba before storm protection, Ix-deck Thumper/Amal and three battle discard stages, including before native Advanced Harkonnen capture. A private normal-auction or Black Market Ixian ally replacement pauses before its draw with a neutral, face-hidden offer; original payment and seller income settle once. Cache purchases retain their native allied-replacement prohibition. Ordinary definite Truthtrance answers pause whether or not another question remains reserved, and also when the answer bound a supported shipment or unsubmitted battle-plan promise. CHOAM sale income is committed before its neutral offer and the same market resumes once; Kulon adds one movement range, La La La blocks one target’s free revival, Baliset restricts the chosen player’s movement, ordinary Trip returns one selected force, and Jubba protects one CHOAM territory only after their offers. Karama’s physical cost is discarded before its neutral offer; the original response is canceled or the reserved lot settles once. Residual Poison commits one random leader death; Sapho commits its finite priority. Thumper waits before worm/spice draw; Amal restores an already-halved opening. Owner-only candidates and one physical Semuta transfer retain privacy. The user-approved full-hand exchange preserves final hand count and incoming reservations. Other Karama uses, other reactive Worthless uses, other private discards, nested responses and other pending rewards remain unfinished. Printed native Guild permission/rate costs now use a dedicated unpaid shipment continuation for reserve, cross/return and typed Homeworld sources; claim/pass applies the same denial/repricing once without delivery replay or invented funding. Printed shipment-price activation now has its own continuation: claim/decline creates the same original price once. Recovered physical cost retains the beneficiary/creator but loses provisional refund eligibility even after rediscard; the same recovered card can pay a real stop without being returned to its former owner. Printed native special costs now resume one committed native effect through effect/complete/cashout stages. Original Emperor post-revival disposal is preserved; CHOAM selected cards are a later private simultaneous batch after one credit. Existing native once-use, joint ordering and typed parent remain. Native BG physical Worthless cost now precedes the single original conversion emitter; the separately printed cancellation cost retains that pending use and still denies it. All four use bindings, incoming reservations and older passes remain. Allowed converted prices carry claimed-cost provenance through actual later rediscard/refund. Fresh private Discovery composition now connects both physical Shrine-role costs without changing original effects or printed identity.",
|
||||
},
|
||||
{
|
||||
area: 'Player controls' as const,
|
||||
status: 'Partial' as const,
|
||||
detail:
|
||||
'All seats can Continue at the neutral fresh-discard boundary; only the actual holder sees Commit. In a mixed-owner battle batch, a committed holder can inspect and select only cards discarded by another player; nonholders receive no candidates. Normal Richese starts remain gated. Earlier four original-action390px native cost/continuation journeys exercise full4 reserve claim, denied cross plus ordinary1, typed full2 all-seat decline, and poor2/full4 release then one-force full2. No overflow/browser/application error; one tool-only stale-node race was resolved with fresh evidence, not replay. Earlier four original-action390px price journeys start at actual activation: bank3 allowance while Guild holds the cost, same-card reserve stop, typed bank2 after all-seat decline, and same-card typed stop followed by real ordinary movement. No overflow/browser/application errors; two tool-only stale-node races were resolved without replay. Earlier four390px special-cost journeys cover original reserve/typed Guild prevention claim/decline and controlled CHOAM private Kulon selection plus Emperor post-revival cost claim. Two original/two controlled; actual native movement/public force inspectors, no overflow/browser/application errors. Four new original-action390px journeys start from actual Baliset controls: bank3 after native allowance, printed counter recovery with denial intact, original full4 Guild repricing and unchanged free Chaumurky acquisition. Native advisors/next-lot inspection finish, with no overflow/browser/application errors.',
|
||||
"All seats can Continue at the neutral fresh-discard boundary; only the actual holder sees Commit. In a mixed-owner battle batch, a committed holder can inspect and select only cards discarded by another player; nonholders receive no candidates. Normal Richese starts remain gated. Earlier four original-action390px native cost/continuation journeys exercise full4 reserve claim, denied cross plus ordinary1, typed full2 all-seat decline, and poor2/full4 release then one-force full2. No overflow/browser/application error; one tool-only stale-node race was resolved with fresh evidence, not replay. Earlier four original-action390px price journeys start at actual activation: bank3 allowance while Guild holds the cost, same-card reserve stop, typed bank2 after all-seat decline, and same-card typed stop followed by real ordinary movement. No overflow/browser/application errors; two tool-only stale-node races were resolved without replay. Earlier four390px special-cost journeys cover original reserve/typed Guild prevention claim/decline and controlled CHOAM private Kulon selection plus Emperor post-revival cost claim. Two original/two controlled; actual native movement/public force inspectors, no overflow/browser/application errors. Four new original-action390px journeys start from actual Baliset controls: bank3 after native allowance, printed counter recovery with denial intact, original full4 Guild repricing and unchanged free Chaumurky acquisition. Native advisors/next-lot inspection finish, with no overflow/browser/application errors. Two controlled390px Shrine-role recovery journeys retain the bank3 three-force delivery and one definite answer.",
|
||||
},
|
||||
{
|
||||
area: 'AI' as const,
|
||||
status: 'Partial' as const,
|
||||
detail:
|
||||
'All four AI profiles use their own projected hand to commit or pass the exact current event, and can choose only privately projected committed candidates. This is minimal legal participation, not tuned strategy. For both new native permission and rate cost parents, all four actual original-state profiles recover the exact cost through legal actions and preserve the original denial/repricing. No tuning or calibration. All four original-state profiles claim the price cost; a subsequent real owner action executes the retained bank-paid shipment. This is legal source participation, not a new strategy preference or calibration. All four existing profiles recover the original Guild stop cost via legal private actions, and the native prevention then executes once. No new preference, tuning or calibration. For each native BG cost and printed counter-cost family, all four existing profiles recover only the current fresh card through their private legal action. Native response allowance/denial remains separate; subsequent owner actions exercise the real retained source. No tuning or calibration.',
|
||||
"All four AI profiles use their own projected hand to commit or pass the exact current event, and can choose only privately projected committed candidates. This is minimal legal participation, not tuned strategy. For both new native permission and rate cost parents, all four actual original-state profiles recover the exact cost through legal actions and preserve the original denial/repricing. No tuning or calibration. All four original-state profiles claim the price cost; a subsequent real owner action executes the retained bank-paid shipment. This is legal source participation, not a new strategy preference or calibration. All four existing profiles recover the original Guild stop cost via legal private actions, and the native prevention then executes once. No new preference, tuning or calibration. For each native BG cost and printed counter-cost family, all four existing profiles recover only the current fresh card through their private legal action. Native response allowance/denial remains separate; subsequent owner actions exercise the real retained source. No tuning or calibration. Thirty-two controlled legal-policy probes cover both physical Shrine-role events in both modes; no calibration.",
|
||||
},
|
||||
{
|
||||
area: 'Documentation' as const,
|
||||
status: 'Partial' as const,
|
||||
detail:
|
||||
'The guide distinguishes clean public ordinary-card, paid Box, Ornithopter, Distrans, definite ordinary Truthtrance answers (including queued questions, supported shipment promises and battle answers before or after plan submission/reveal), four Sapho scopes, pre-leader Residual Poison, printed Karama cancellation of CHOAM Charity, Inflation or Bene Gesserit Charity or clean normal-auction purchase or winning-bid payment, completed CHOAM card sales, clean Kulon/proactive La La La/Baliset/ordinary Trip to Gamont Worthless and accepted printed Jubba Cloak, Ix-deck Thumper/Amal and three battle batches from a private normal-auction or Black Market Ixian ally replacement, the cache replacement prohibition, privacy-neutral acknowledgements, the user-approved atomic full-hand exchange and remaining discard sources. The native Guild followup distinguishes unpaid transport from completed income and keeps existing denial/no-debt interpretations. Both original cards are actually auctioned; two extra active-price probes explicitly disclose controlled second-card acquisition. Printed price-cost activation is connected below; converted and special costs remain separate. The printed price-cost continuation and claimed-cost nonduplication extension are explicit. Unclaimed original refunds remain provisional and unchanged; recovery does not transfer or repeat the price benefit. Shrine costs and wider E3 entries remain separate; native BG and printed special costs are connected. Printed special costs and CHOAM cashout stages follow native disposal order without a new publisher timing ruling. Eight original and18 controlled paths plus2 original/2 controlled surfaces are explicit. Advanced E3 entry, Shrine costs and full assurance remain separate. The Worthless remains its actual printed role and does not grant BG conversion to a new faction. Native cost versus printed counter, four-use source/incoming bindings and claimed converted-price refund are explicit. Kull pre-discard priority is unchanged; stale native Kull fixture queues were corrected through real decisions. Shrine/E3 and final assurance stay separate.',
|
||||
"The guide distinguishes clean public ordinary-card, paid Box, Ornithopter, Distrans, definite ordinary Truthtrance answers (including queued questions, supported shipment promises and battle answers before or after plan submission/reveal), four Sapho scopes, pre-leader Residual Poison, printed Karama cancellation of CHOAM Charity, Inflation or Bene Gesserit Charity or clean normal-auction purchase or winning-bid payment, completed CHOAM card sales, clean Kulon/proactive La La La/Baliset/ordinary Trip to Gamont Worthless and accepted printed Jubba Cloak, Ix-deck Thumper/Amal and three battle batches from a private normal-auction or Black Market Ixian ally replacement, the cache replacement prohibition, privacy-neutral acknowledgements, the user-approved atomic full-hand exchange and remaining discard sources. The native Guild followup distinguishes unpaid transport from completed income and keeps existing denial/no-debt interpretations. Both original cards are actually auctioned; two extra active-price probes explicitly disclose controlled second-card acquisition. Printed price-cost activation is connected below; converted and special costs remain separate. The printed price-cost continuation and claimed-cost nonduplication extension are explicit. Unclaimed original refunds remain provisional and unchanged; recovery does not transfer or repeat the price benefit. Shrine costs and wider E3 entries remain separate; native BG and printed special costs are connected. Printed special costs and CHOAM cashout stages follow native disposal order without a new publisher timing ruling. Eight original and18 controlled paths plus2 original/2 controlled surfaces are explicit. Advanced E3 entry, Shrine costs and full assurance remain separate. The Worthless remains its actual printed role and does not grant BG conversion to a new faction. Native cost versus printed counter, four-use source/incoming bindings and claimed converted-price refund are explicit. Kull pre-discard priority is unchanged; stale native Kull fixture queues were corrected through real decisions. Shrine/E3 and final assurance stay separate. Shrine composition is documented separately from native BG conversion and from original Discovery acquisition evidence.",
|
||||
},
|
||||
{
|
||||
area: 'Verification' as const,
|
||||
status: 'Partial' as const,
|
||||
detail:
|
||||
'Genuine setup, custody, hidden-hand parity, saved JSON, authenticated SQLite continuation and legal AI participation cover clean ordinary-card, paid Box, Ornithopter, Distrans, Truthtrance, four Sapho scopes, pre-leader Residual Poison, printed Karama cancellation of CHOAM Charity, Inflation or Bene Gesserit Charity or clean normal-auction purchase or winning-bid payment, completed CHOAM card sales, clean Kulon/proactive La La La/Baliset/ordinary Trip to Gamont Worthless and accepted printed Jubba Cloak, Ix-deck Thumper/Amal, a private normal-auction Ixian ally replacement and three battle discard stages. Other private producers, Karama uses, other reactive Worthless uses, pending rewards, full games and live deployment remain unverified. Earlier thirteen-file158/158 passes, including12 new cases. Thirty-two original-action runtime/policy paths and four original-action390px journeys pass; two separately controlled cross/typed active-price probes retain the original independent grant. No worker/D1/real-room/deployed assurance or complete-mode claim. Earlier eighteen-file234/234 passes, including8 new cases. Fourteen original-action runtime/policy paths and four actual original-action390px journeys pass; two explicitly controlled extra-stop-card acquisitions prove unclaimed refunds. The original same-card stop uses no extra card or staged acquisition. No worker/D1/saved/deployed or complete-mode assurance. Earlier sixteen-file224/224 passes with13 new behavior cases. Twenty-six runtime/policy paths pass:8 original-action Guild paths including4 profiles,18 explicitly controlled native-effect paths. Four actual390px journeys pass (2 original/2 controlled). Existing income/refund consumers use actual neutral passes. No worker/D1/saved/deployed or complete-mode claim. Current nineteen-file238/238 passes with8 new cases. Twenty-six original-action runtime/policy paths and four actual original-action390px journeys pass. One controlled acquisition/phase probe uses a REAL subsequent CHOAM rediscard and Guild stop without force/wallet staging or duplicate refund. Separate2 controlled Kull parent probes and3 repaired focused cases pass. No worker/D1/saved/deployed certification.',
|
||||
"Genuine setup, custody, hidden-hand parity, saved JSON, authenticated SQLite continuation and legal AI participation cover clean ordinary-card, paid Box, Ornithopter, Distrans, Truthtrance, four Sapho scopes, pre-leader Residual Poison, printed Karama cancellation of CHOAM Charity, Inflation or Bene Gesserit Charity or clean normal-auction purchase or winning-bid payment, completed CHOAM card sales, clean Kulon/proactive La La La/Baliset/ordinary Trip to Gamont Worthless and accepted printed Jubba Cloak, Ix-deck Thumper/Amal, a private normal-auction Ixian ally replacement and three battle discard stages. Other private producers, Karama uses, other reactive Worthless uses, pending rewards, full games and live deployment remain unverified. Earlier thirteen-file158/158 passes, including12 new cases. Thirty-two original-action runtime/policy paths and four original-action390px journeys pass; two separately controlled cross/typed active-price probes retain the original independent grant. No worker/D1/real-room/deployed assurance or complete-mode claim. Earlier eighteen-file234/234 passes, including8 new cases. Fourteen original-action runtime/policy paths and four actual original-action390px journeys pass; two explicitly controlled extra-stop-card acquisitions prove unclaimed refunds. The original same-card stop uses no extra card or staged acquisition. No worker/D1/saved/deployed or complete-mode assurance. Earlier sixteen-file224/224 passes with13 new behavior cases. Twenty-six runtime/policy paths pass:8 original-action Guild paths including4 profiles,18 explicitly controlled native-effect paths. Four actual390px journeys pass (2 original/2 controlled). Existing income/refund consumers use actual neutral passes. No worker/D1/saved/deployed or complete-mode claim. Current nineteen-file238/238 passes with8 new cases. Twenty-six original-action runtime/policy paths and four actual original-action390px journeys pass. One controlled acquisition/phase probe uses a REAL subsequent CHOAM rediscard and Guild stop without force/wallet staging or duplicate refund. Separate2 controlled Kull parent probes and3 repaired focused cases pass. No worker/D1/saved/deployed certification. Eight new Shrine cases pass in the57-case affected union, with eight controlled runtime paths and two actual controlled390px journeys; no natural draw/entry, recovery or deployed acceptance.",
|
||||
evidence: [
|
||||
'tests/semuta-engine.test.ts',
|
||||
'tests/semuta-recovery.test.ts',
|
||||
@@ -1309,6 +1310,7 @@ export const RULE_TOPICS: RuleTopic[] = [
|
||||
'tests/semuta-shipment-price.test.ts',
|
||||
'tests/semuta-special-karama.test.ts',
|
||||
'tests/semuta-bg-karama.test.ts',
|
||||
'tests/semuta-shrine.test.ts',
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import {
|
||||
applyAction, createGame, initializeSemutaGameForAudit, joinGame, newPlayer,
|
||||
type Action, type Game,
|
||||
} from '../game/engine';
|
||||
import { SEMUTA_DRUG_ID } from '../game/semuta-drug';
|
||||
import { nextSemutaGuildIncomeNativeStep } from './fixture-semuta-guild-income';
|
||||
import { moveSemutaEmperorCard, semutaEmperorCardId } from './fixture-semuta-emperor-share';
|
||||
|
||||
export const shrinePlayer = (game: Game, id: string) => game.players.find(p => p.id === id)!;
|
||||
export function semutaShrineLobby(advanced = true) {
|
||||
let game = createGame('SEMUTASHRINE', newPlayer('r', 'Richese', 'richese'), advanced, ['choam']);
|
||||
joinGame(game, newPlayer('e', 'Emperor', 'emperor'));
|
||||
joinGame(game, newPlayer('g', 'Guild', 'guild'));
|
||||
game.discoveryEnabled = true;
|
||||
for (const player of game.players) game = applyAction(game, player.id, { type: 'ready' });
|
||||
return game;
|
||||
}
|
||||
|
||||
/** Original ready lobby/setup and first Movement; then CONTROLLED physical
|
||||
* Shrine placement/occupation and conserved hand acquisition. Not an original
|
||||
* Discovery draw/entry journey or full-game acceptance. */
|
||||
export function createControlledSemutaShrine(advanced = true) {
|
||||
let game = initializeSemutaGameForAudit(semutaShrineLobby(advanced));
|
||||
for (const position of [0, 1]) {
|
||||
const index = game.spiceDeck.findIndex((card, i) => i >= position && 'territory' in card && !card.discovery);
|
||||
assert.ok(index >= position);
|
||||
game.spiceDeck.splice(position, 0, game.spiceDeck.splice(index, 1)[0]);
|
||||
}
|
||||
for (let n = 0; n < 600; n++) {
|
||||
if (game.phase === 5 && game.active === 'g' && !game.phaseOpening && !game.response && !game.decision) break;
|
||||
const step = nextSemutaGuildIncomeNativeStep(game);
|
||||
game = applyAction(game, step.actor, step.action);
|
||||
}
|
||||
assert.equal(game.phase, 5);
|
||||
assert.ok(!game.response && !game.decision && !game.phaseOpening);
|
||||
for (const player of game.players) game.deck.push(...player.hand.splice(0));
|
||||
const shrine = game.discoveries!.tokens.find(token => token.face === 'shrine')!;
|
||||
Object.assign(shrine, { status: 'placed', territory: 'gara_kulon', sector: 8, revealedTurn: game.turn });
|
||||
shrinePlayer(game, 'e').reserves--;
|
||||
shrinePlayer(game, 'e').forces['shrine:0'] = 1;
|
||||
const truth = semutaEmperorCardId(game, card => card.effect === 'truthtrance');
|
||||
const karama = semutaEmperorCardId(game, card => card.effect === 'karama');
|
||||
moveSemutaEmperorCard(game, truth, 'e');
|
||||
moveSemutaEmperorCard(game, karama, 'e');
|
||||
moveSemutaEmperorCard(game, SEMUTA_DRUG_ID, 'r');
|
||||
return { game, truth, karama, holder: 'r', owner: 'e',
|
||||
provenance: 'CONTROLLED Shrine placement/occupation and conserved hand acquisition after genuine ready/setup/first Movement.' };
|
||||
}
|
||||
|
||||
export function startShrineTruth(game: Game, karama: string): Game {
|
||||
game = applyAction(game, 'e', { type: 'card', card: karama, shrineTruthtrance: [karama] });
|
||||
while (game.truthtrance?.stage === 'priority') {
|
||||
const actor = game.players.find(p => !game.truthtrance!.passed.includes(p.id))!;
|
||||
game = applyAction(game, actor.id, { type: 'truthPass' });
|
||||
}
|
||||
const ask: Action = { type: 'truthAsk', question: { kind: 'fact', target: 'r',
|
||||
fact: { kind: 'hand', name: 'Semuta Drug' } } };
|
||||
game = applyAction(game, 'e', ask);
|
||||
return applyAction(game, 'r', { type: 'truthAnswer', answer: 'yes' });
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { applyAction, initializeSemutaGameForAudit, viewGame, type Game } from '../game/engine';
|
||||
import { TERRITORIES } from '../game/board';
|
||||
import { presenceAt } from '../game/force-presence';
|
||||
import { createControlledSemutaShrine, semutaShrineLobby, shrinePlayer, startShrineTruth } from './fixture-semuta-shrine';
|
||||
import { reactSemutaSpecial } from './fixture-semuta-special-karama';
|
||||
import { settleSemutaBgNative } from './fixture-semuta-bg-karama';
|
||||
|
||||
for (const advanced of [false, true]) {
|
||||
void test(`Shrine ${advanced ? 'Advanced' : 'Basic'} recovered Truthtrance retains one original bank-paid shipment`, () => {
|
||||
for (const claim of [false, true]) {
|
||||
const f = createControlledSemutaShrine(advanced);
|
||||
const original = shrinePlayer(f.game, f.owner).hand.find(c => c.id === f.truth)!;
|
||||
let game = applyAction(f.game, f.owner, { type: 'card', card: f.truth, mode: 'shipment', target: 'g' });
|
||||
assert.equal(game.pendingTreacheryDiscard?.batch.cause, 'karama:shipment');
|
||||
assert.equal(game.karamaShipping, null);
|
||||
game = reactSemutaSpecial(game, f.holder, claim);
|
||||
assert.equal(game.karamaShipping?.owner, f.owner);
|
||||
assert.equal(!!game.karamaShipping?.costClaimed, claim);
|
||||
assert.deepEqual(claim ? shrinePlayer(game, f.holder).hand.find(c => c.id === f.truth) : game.discard.find(c => c.id === f.truth), original);
|
||||
assert.equal(game.pendingKarama ?? null, null, 'Shrine use is not the BG counterable conversion');
|
||||
const destination = TERRITORIES.find(t => t.type === 'sand' && t.sectors.some(s => s !== game.storm) &&
|
||||
game.players.every(p => presenceAt(p, t.id) === 0))!;
|
||||
const sector = destination.sectors.find(s => s !== game.storm)!;
|
||||
const before = structuredClone(shrinePlayer(game, 'g'));
|
||||
game = applyAction(game, 'g', { type: 'ship', territory: destination.id, sector, amount: 3, elite: 0, allyPayment: 0 });
|
||||
game = settleSemutaBgNative(game);
|
||||
assert.equal(shrinePlayer(game, 'g').spice, before.spice - 3);
|
||||
assert.equal(shrinePlayer(game, 'g').reserves, before.reserves - 3);
|
||||
assert.equal(shrinePlayer(game, 'g').forces[`${destination.id}:${sector}`], 3);
|
||||
assert.equal(game.karamaShipping, null);
|
||||
}
|
||||
});
|
||||
|
||||
void test(`Shrine ${advanced ? 'Advanced' : 'Basic'} physical Karama is fresh after its committed answer`, () => {
|
||||
for (const claim of [false, true]) {
|
||||
const f = createControlledSemutaShrine(advanced);
|
||||
let game = startShrineTruth(f.game, f.karama);
|
||||
assert.equal(game.truthHistory!.at(-1)?.answer, 'yes');
|
||||
assert.equal(game.pendingTreacheryDiscard?.batch.cause, 'truthtrance');
|
||||
const history = structuredClone(game.truthHistory);
|
||||
game = reactSemutaSpecial(game, f.holder, claim);
|
||||
assert.deepEqual(game.truthHistory, history);
|
||||
assert.equal(game.truthtrance, null);
|
||||
const physical = claim ? shrinePlayer(game, f.holder).hand.find(c => c.id === f.karama) : game.discard.find(c => c.id === f.karama);
|
||||
assert.equal(physical?.effect, 'karama');
|
||||
assert.equal(physical?.name, 'Karama');
|
||||
assert.equal(game.pendingTreacheryDiscard, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void test('Shrine special Emperor recovery never repeats already-completed revival', () => {
|
||||
for (const claim of [false, true]) {
|
||||
const f = createControlledSemutaShrine();
|
||||
f.game.phase = 4; // CONTROLLED Revival clock and two conserved Tank counters.
|
||||
const owner = shrinePlayer(f.game, f.owner);
|
||||
owner.reserves -= 2; owner.tanks += 2;
|
||||
const before = owner.reserves;
|
||||
let game = applyAction(f.game, f.owner, { type: 'card', card: f.truth, mode: 'special', amount: 2, elite: 0 });
|
||||
assert.equal(shrinePlayer(game, f.owner).reserves, before + 2);
|
||||
assert.equal(game.pendingTreacheryDiscard?.batch.cause, 'specialKarama:emperorForces');
|
||||
game = reactSemutaSpecial(game, f.holder, claim);
|
||||
assert.equal(shrinePlayer(game, f.owner).reserves, before + 2);
|
||||
assert.equal(shrinePlayer(game, f.owner).tanks, 0);
|
||||
assert.equal(shrinePlayer(game, f.owner).specialKaramaUsed, true);
|
||||
}
|
||||
});
|
||||
|
||||
void test('Shrine purchase recovery preserves the physical auction lot and spends no spice', () => {
|
||||
for (const mode of ['purchase', 'auctionPayment'] as const) for (const claim of [false, true]) {
|
||||
const f = createControlledSemutaShrine();
|
||||
// CONTROLLED auction phase/lot, conserving the original physical deck.
|
||||
const game = f.game; game.phase = 3;
|
||||
game.richeseBidding = null;
|
||||
const lot = game.deck.shift()!;
|
||||
game.auction = { cards: [lot], index: 0, bid: mode === 'purchase' ? 0 : 2,
|
||||
bidder: mode === 'purchase' ? null : f.owner, active: f.owner, passed: [], opener: 0 };
|
||||
if (mode === 'auctionPayment') game.decision = { kind: 'auctionPayment', player: f.owner };
|
||||
const spice = shrinePlayer(game, f.owner).spice;
|
||||
let done = applyAction(game, f.owner, mode === 'purchase'
|
||||
? { type: 'card', mode, card: f.truth }
|
||||
: { type: 'decision', karama: true, card: f.truth });
|
||||
assert.equal(done.pendingTreacheryDiscard?.batch.cause, `karama:${mode}`);
|
||||
assert.equal(shrinePlayer(done, f.owner).hand.some(c => c.id === lot.id), false);
|
||||
done = reactSemutaSpecial(done, f.holder, claim);
|
||||
assert.equal(shrinePlayer(done, f.owner).hand.filter(c => c.id === lot.id).length, 1);
|
||||
assert.equal(shrinePlayer(done, f.owner).spice, spice);
|
||||
assert.equal(shrinePlayer(done, f.holder).hand.some(c => c.id === f.truth), claim);
|
||||
}
|
||||
});
|
||||
|
||||
void test('Shrine cancellation recovery still denies the original unpaid Guild discount', () => {
|
||||
for (const claim of [false, true]) {
|
||||
const f = createControlledSemutaShrine();
|
||||
const destination = TERRITORIES.find(t => t.type === 'sand' && t.sectors.some(s => s !== f.game.storm) &&
|
||||
f.game.players.every(p => presenceAt(p, t.id) === 0))!;
|
||||
const sector = destination.sectors.find(s => s !== f.game.storm)!;
|
||||
const before = structuredClone(shrinePlayer(f.game, 'g'));
|
||||
let game = applyAction(f.game, 'g', { type: 'ship', territory: destination.id, sector, amount: 2, elite: 0, allyPayment: 0 });
|
||||
if (game.decision?.kind === 'guildShipment')
|
||||
game = applyAction(game, 'g', { type: 'decision', allow: true });
|
||||
assert.equal(game.response?.kind, 'guildRate');
|
||||
game = applyAction(game, f.owner, { type: 'card', card: f.truth, mode: 'cancel' });
|
||||
assert.equal(game.pendingTreacheryDiscard?.batch.cause, 'karama:guildRate');
|
||||
assert.equal(shrinePlayer(game, 'g').spice, before.spice);
|
||||
game = settleSemutaBgNative(reactSemutaSpecial(game, f.holder, claim));
|
||||
assert.equal(shrinePlayer(game, 'g').spice, before.spice - 4);
|
||||
assert.equal(shrinePlayer(game, 'g').reserves, before.reserves - 2);
|
||||
assert.equal(shrinePlayer(game, 'g').forces[`${destination.id}:${sector}`], 2);
|
||||
assert.equal(shrinePlayer(game, f.holder).hand.some(c => c.id === f.truth), claim);
|
||||
}
|
||||
});
|
||||
|
||||
void test('fresh Discovery setup retains original modules and rejects unsupported Semuta overlays', () => {
|
||||
for (const advanced of [false, true]) {
|
||||
let lobby = semutaShrineLobby(advanced);
|
||||
lobby = applyAction(lobby, lobby.host, { type: 'techTokens', enabled: true });
|
||||
if (advanced) lobby = applyAction(lobby, lobby.host, { type: 'strongholdCards', enabled: true });
|
||||
for (const player of lobby.players) if (!player.ready) lobby = applyAction(lobby, player.id, { type: 'ready' });
|
||||
const setup = initializeSemutaGameForAudit(lobby);
|
||||
assert.equal(setup.discoveries!.tokens.length, 8);
|
||||
assert.ok(setup.techTokens);
|
||||
assert.equal(!!setup.strongholdCards, advanced);
|
||||
assert.equal(viewGame(setup, 'r').status, 'setup');
|
||||
const alterations: ((g: Game) => void)[] = [g => { g.homeworlds = { custody: null }; },
|
||||
g => { g.nexusCards = { cards: null, phase: null }; }];
|
||||
for (const alter of alterations) {
|
||||
const invalid = structuredClone(lobby); alter(invalid);
|
||||
assert.throws(() => initializeSemutaGameForAudit(invalid), /Semuta Discovery/);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -54,7 +54,7 @@ export type PrototypeOptions = {
|
||||
ecazTreachery?: boolean;
|
||||
/** Independent original Nexus composition with Skills or Semuta, not public activation. */
|
||||
nexusCards?: boolean;
|
||||
/** Explicit classic Discovery/Skills composition, not a public activation. */
|
||||
/** Explicit original Discovery composition with Skills, Nexus or Semuta; no public activation. */
|
||||
discoveries?: boolean;
|
||||
/** Explicit original skills with Semuta, classic occupation or Guild Betrayal. */
|
||||
leaderSkills?: boolean;
|
||||
@@ -103,8 +103,8 @@ export function startPrototypeRoom(
|
||||
throw new Error('--ecaz-treachery requires the ecaz-occupy profile.');
|
||||
if (options.nexusCards && profile !== 'leader-skills' && profile !== 'semuta' && profile !== 'banker-income')
|
||||
throw new Error('--nexus-cards requires the leader-skills, banker-income or semuta profile.');
|
||||
if (options.discoveries && profile !== 'leader-skills' && profile !== 'nexus')
|
||||
throw new Error('--discoveries requires the leader-skills or nexus profile.');
|
||||
if (options.discoveries && profile !== 'leader-skills' && profile !== 'nexus' && profile !== 'semuta')
|
||||
throw new Error('--discoveries requires the leader-skills, nexus or semuta profile.');
|
||||
if (options.leaderSkills && profile !== 'semuta' && profile !== 'homeworld-occupation' && profile !== 'guild-betrayal')
|
||||
throw new Error('--leader-skills requires the semuta, homeworld-occupation or guild-betrayal profile.');
|
||||
if (options.homeworlds && profile !== 'semuta' && profile !== 'banker-income')
|
||||
|
||||
@@ -28,6 +28,7 @@ async function main() {
|
||||
'Usage: node --import tsx tools/start-prototype.ts --profile ix|discovery|homeworld-occupation|leader-skills|banker-income|factions|stronghold-factions|nexus|moritani-assassinate|ecaz-treachery|ecaz-occupy|semuta|kull|richese-betrayal|nexus-kull|guild-betrayal|ixian-replacement|ixian-betrayal|harkonnen-betrayal --db PATH --room CODE --version NUMBER --out /private/new-directory\nStarts only a fresh ready lobby for the selected development prototype. Stronghold-factions opts a fresh ready 2–6-seat Advanced roster with at least one selected native Ixians, Tleilaxu, CHOAM or Richese faction and otherwise classic opponents into Stronghold Cards, optionally preserving unused Tech Tokens at 3–6 seats. Select one or both distinct Ix/CHOAM decks; each native faction requires its family deck. The selected decks supply 47 Ix or combined, or 35 CHOAM canonical physical Treachery Cards, with a separate ten-card Richese cache when Richese plays. Native setup choices, HMS placement, Face Dancers, Richese cache and CHOAM Auditor remain genuine; custody starts unowned and is claimed by actual END Mentat. It does not redeal, reset or retrofit a saved game. Banker-income opts a fresh 2–6-seat classic Basic/Advanced base-deck roster, supported Basic Ixian/Tleilaxu/CHOAM/Moritani skill roster with its single required deck, or Advanced native Ixians, Tleilaxu and/or CHOAM plus classic roster with distinct required family decks, into automatic deferred normal income and native Mentat collection with all fourteen Leader Skills. Original bank payer costs exclude the separate Tleilaxu free-revival award; already-earned spice stays with its original faction under the existing provisional policy. Nexus enables the existing private Nexus setup. Moritani-assassinate explicitly opts into the bounded Advanced assassination preview. Semuta opts a fresh Richese roster into bounded clean-discard reactions; an included Ix deck supplies physical Thumper without opening public starts. Kull opts a fresh eligible CHOAM roster into the user-selected Karama interception preview. Richese-betrayal opts a fresh paired CHOAM/Richese Nexus roster into cache-purchase veto and sale-bank diversion. Nexus-kull opts a fresh CHOAM-plus-classic roster with CHOAM/Ix decks and Nexus into source-aware printed or any-Treachery-fueled Cunning Kull. Guild-betrayal opts a fresh classic roster with native Guild into full funded shipment-payment replacement; it preserves an explicitly enabled Homeworld module for Junction routes. Ixian-replacement opts a fresh classic Basic/Advanced base-deck roster, or Basic Tleilaxu plus classic opponents with the original Ix47 deck and no optional Sandtrout, into the exact normal-auction purchased-card replacement with Nexus alone. Native Ixians, Harkonnen buyers and special purchase sources remain unsupported. Ixian-betrayal opts a fresh 2–6-seat Basic/Advanced native Ixian plus classic/Tleilaxu roster with Ix 47-card Treachery and Nexus only into prevention of one actual native Bidding draw or Advanced Technology exchange, after native Karama counters. Harkonnen-betrayal opts a fresh 2–6-seat classic Basic/Advanced roster with native Harkonnen, base 33-card Treachery and Nexus alone into cancellation of an actual declared personal or allied Harkonnen Traitor Card after native counters, physical retirement and shuffle, and one private actual Mentat replacement. Modules, overlays, public starts and old-game retrofits remain excluded except for each profile’s documented composition. Nexus is not dealt initially: a qualifying alliance requires at least three seats; two unallied receivers require four. Backs up all rooms first, preserves sessions and existing games, and rejects stale versions. Normal game-start and publication gates remain closed.',
|
||||
'\nSemuta additionally admits a fresh Basic roster with native Richese and Moritani, classic opponents, exactly CHOAM and Ecaz decks, and no optional modules. Native setup remains genuine. Private Sabotage and Robbery overflow discards may offer Semuta before a clean ordinary shipment/movement arrival resumes. The victim/draw and original payment/forces are already committed; candidate faces stay hidden until commitment. Advanced Moritani, native Ecaz, Ix/E3 mixtures, worm/Ambassador/overlap arrivals and public starts remain outside this entry.',
|
||||
'\nSemuta with CHOAM and optional Ix preserves original unused Tech Tokens in fresh 3–6-seat Basic/Advanced Richese lobbies under existing native prerequisites. Advanced additionally retains original unused Stronghold Cards at2–6; both modules require3–6. Native setup, first-Storm Tech and final-Mentat Stronghold assignment remain original. Mandatory/winner discards react before the original winner takes one loser-owned token, before Face Dance. Closing Gamont reacts before the original CHOAM finish and changed-board claim. Optional original skills require --leader-skills as described below; other modules, the separate CHOAM/Ecaz Moritani entry, retrofit and public starts remain excluded.',
|
||||
'\n--profile semuta --discoveries uses original fresh Richese/CHOAM and optional Ix Discovery7/8 setup, Basic/Advanced2–6, with original unused Tech3+/Advanced Strongholds. Shrine physical roles stay distinct: Truthtrance may be played as Karama while its printed identity remains; Semuta recovers the used physical cost without replaying its effect. No Skills, Homeworlds, Nexus, E3, played-save conversion or public-mode gate is opened.',
|
||||
'\n--profile semuta --leader-skills explicitly composes original all14 skills with fresh native Basic Richese/CHOAM and classics using exact CHOAM, or Advanced native E1/E2 with Richese and selected required CHOAM/optional Ix decks, at2–6 seats. Optional original Tech requires3+; Strongholds requires Advanced. Original private offers/training, Auditor exclusion, normal Mentat question, typed Suk rescue and Rihani inspection/exchange remain. Traitor/Face Dancer movement is not a Treachery discard. Basic Ix mixtures without their original Nexus envelope, E3/Moritani, Homeworld/Discovery/Banker overlays, public starts and played-game conversion are not opened.',
|
||||
'\n--profile semuta --nexus-cards retains original all12 Nexus in fresh native Richese CHOAM/optional Ix lobbies, optionally --leader-skills, original Tech3+ and Advanced Strongholds2+. Single/paired CHOAM or both selected E1/E2 native families retain original prerequisites. No starting Nexus hand is added: a qualifying actual end-Spice draw follows a Nexus and settled alliance. CHOAM Secret Ally spends a Worthless for two bank spice only with CHOAM absent; CHOAM Betrayal spends its Nexus to discard one server-sampled native CHOAM hand card without compensation. Semuta claim/pass retires the original receipt once, after the committed fresh discard. No Homeworld, Discovery, E3, retrofit or public gate opens.',
|
||||
'\n--profile semuta --homeworlds uses original fresh Basic/Advanced Richese with CHOAM and classic factions, exact CHOAM deck, at2–6 seats. Native occupation setup/history remain original. Paid Box, Distrans, definite Truthtrance, ordinary specials, Kaitain, Tupile cleanup and legal CHOAM market sales offer used cards before their original suffix. Final Ornithopter disposal keeps completed original groups; finite Once Around and clean unstarted movement Sapho disposal keeps the reordered queue/funding. Accepted losing-card, mandatory winning-card and selected winner disposal remain separate fresh events, preserving paid deployments, casualties and original rewards without replaying combat. Clean Residual Poison keeps one native random death without bounty; early Sapho aggressor and remaining Battle chooser costs keep original participants and finite priority. Native printed CHOAM costs pause before their effect; printed Karama canceling these powers or native Guild/Emperor/Richese income is separately offered before denial. Printed CHOAM opening-income/Inflation cancellation and normal-lot Karama purchase/free-payment costs also pause before their original denial, spent attempt or zero-spice acquisition. Retained fuel/witness and credited sale spice remain unchanged. No repeated move/return/storm/payout/refund is introduced. Kull, Hajr/prior-flight integration, unresolved cyclic/partial/Guild/late Sapho timing, readied/inspected Poison costs, Advanced Harkonnen captive disclosure, other producers/modules, retrofit and public starts remain guarded.',
|
||||
@@ -68,8 +69,8 @@ async function main() {
|
||||
throw new Error('--ecaz-treachery requires --profile ecaz-occupy.');
|
||||
if (values['nexus-cards'] && values.profile !== 'leader-skills' && values.profile !== 'semuta' && values.profile !== 'banker-income')
|
||||
throw new Error('--nexus-cards requires --profile leader-skills, banker-income or semuta.');
|
||||
if (values.discoveries && values.profile !== 'leader-skills' && values.profile !== 'nexus')
|
||||
throw new Error('--discoveries requires --profile leader-skills or nexus.');
|
||||
if (values.discoveries && values.profile !== 'leader-skills' && values.profile !== 'nexus' && values.profile !== 'semuta')
|
||||
throw new Error('--discoveries requires --profile leader-skills, nexus or semuta.');
|
||||
if (values['leader-skills'] && values.profile !== 'semuta' && values.profile !== 'homeworld-occupation' && values.profile !== 'guild-betrayal')
|
||||
throw new Error('--leader-skills requires --profile semuta, homeworld-occupation or guild-betrayal.');
|
||||
if (values.homeworlds && values.profile !== 'semuta' && values.profile !== 'banker-income')
|
||||
|
||||
Reference in new issue
Block a user