Allow Semuta recovery before native Ghola income

Reuse the exact ordinary-discard income qualification for admission and
parent validation. Preserve physical revival and native conditional income
through claim, decline, full-hand exchange and original allow/cancel.
This commit is contained in:
Quintine committed 2026-10-24 16:48:20 +11:00
1 parent 19e554666e
commit 047011e243
11 files changed
+524 -19

No files matched your search

+7 -12
View File
@@ -1,3 +1,4 @@
import { ordinaryDiscardIncomeMatches } from './ordinary-discard-income';
import { gholaForcePreparations } from './ghola-force-preparation';
import { earlyAuctionFunding } from './early-auction-funding';
import { recordMovementDiscardKnowledge, knownMovementDiscards, recordMovementBoxKnowledge, recordMovementClaimKnowledge, clearMovementDiscardKnowledge, type MovementDiscardKnowledge } from './movement-discard-knowledge';
@@ -6440,16 +6441,8 @@ function treacheryDiscardIntegrity(g: Game) {
!c.resume.decision && !c.resume.pendingKarama && !c.resume.phaseOpening,
'The ordinary card has an unexpected suspended decision.',
);
const income = c.resume.response,
tleilaxu = byFaction(g, 'tleilaxu');
requireRule(
c.effect === 'ghola' && tleilaxu
? income?.kind === 'revivalIncome' &&
income.owner === tleilaxu.id &&
income.recipient === c.player &&
income.amount === 1 &&
income.passed.length === 0
: !income,
ordinaryDiscardIncomeMatches(g, c),
'The consumed card no longer matches its pending revival income.',
);
requireRule(
@@ -7779,9 +7772,11 @@ function semutaOfferSupported(
continuation.kind === 'karamaEmperorShareDiscard' ||
continuation.kind === 'karamaIncomeDiscard' ||
continuation.kind === 'karamaShipmentDiscard' ||
((continuation.kind === 'ornithopterDiscard' && continuation.source === 'cunning'
? continuation.resume.response?.kind === 'nexusGuildCunning'
: !continuation.resume.response) && !continuation.resume.decision &&
((continuation.kind === 'ordinaryCardDiscard'
? ordinaryDiscardIncomeMatches(g, continuation)
: continuation.kind === 'ornithopterDiscard' && continuation.source === 'cunning'
? continuation.resume.response?.kind === 'nexusGuildCunning'
: !continuation.resume.response) && !continuation.resume.decision &&
!continuation.resume.pendingKarama &&
(continuation.kind === 'amalDiscard'
? continuation.resume.phaseOpening?.passed.length === 0
+21
View File
@@ -0,0 +1,21 @@
import type { Game } from './engine';
type OrdinaryDiscard = Extract<
NonNullable<Game['pendingTreacheryDiscard']>['continuation'],
{ kind: 'ordinaryCardDiscard' }
>;
/** Only Ghola creates this conditional income after its physical effect. The
* same source qualification governs the fresh offer and its saved parent. */
export function ordinaryDiscardIncomeMatches(
game: Pick<Game, 'players'>,
continuation: Pick<OrdinaryDiscard, 'effect' | 'player' | 'resume'>,
): boolean {
const income = continuation.resume.response;
const tleilaxu = game.players.find(player => player.faction === 'tleilaxu');
return continuation.effect === 'ghola' && tleilaxu
? income?.kind === 'revivalIncome' && income.owner === tleilaxu.id &&
income.recipient === continuation.player && income.amount === 1 &&
income.passed.length === 0
: !income;
}
+10 -4
View File
@@ -1300,6 +1300,7 @@ export const RULE_TOPICS: RuleTopic[] = [
'The native Advanced BG extra-charity cancellation cost also offers printed Karama after the genuine claim allowance is consumed but before denial; claim/pass withholds the same extra allowance and cannot renew that turn’s claim. Wealthy Basic BG retains its original ordinary-charity guard. Allied Emperor gift and extra-revival cancellation costs likewise offer after original native setup, actual casualty/alliance and declaration: recovering the card does not transfer the canceled gift, return a counter or award extra revival. Original ally, populations, wallets, Tanks and native closing controls remain committed.',
'Original native Homeworld battle-reward cancellation costs also offer printed Karama: Advanced Harkonnen capture, native CHOAM Auditor and quoted force-payment income. Recovery preserves the accepted battle, paid support, leader death and original casualty/cleanup order, then completes the same denial. It cannot sample or transfer a captive, pay/inspect an audit, refund support or credit canceled income. An audit cancellation leaves any earlier allowed force-payment income intact. Existing exact roster, private-custody and source guards remain.',
'An ordinary Ghola played during battle also offers its consumed card after revival. Claim or Continue preserves the revived leader or forces and the opposing sealed plan, then normal planning resumes. It cannot revive again by resuming the receipt.',
'A completed Ghola can also be claimed while its native Tleilaxu one-spice income is waiting. The piece has already returned. Claim or Continue restores that same allow-or-cancel response without another revival or advance payment; normal revival allowances stay unchanged. This includes Tleilaxu using its own Ghola. Other pending effects retain their existing timing.',
'A completed paid Nullentropy Box search during battle offers only the used Box. Claim or Continue preserves the two-spice payment, private recovered card, already-shuffled pile and sealed opposing plan. The recovered card may be used in normal legal planning; the search is not repeated.',
'A clean Distrans transfer during battle also offers only the used Distrans. The private card has already reached its recipient; claim or Continue cannot repeat the gift or change a sealed plan. A recipient holding Semuta may claim the used Distrans and keep the already-transferred card.',
'Reactive Baliset and La La La also offer their used card after the accepted cost. The original uncommitted move or free-revival request is already stopped: claim or Continue installs the original restriction without moving forces, consuming movement, reviving or charging the denied request. Another legal move or paid revival remains available. Movement-card, Ambassador, Nexus and other competing parents remain separate.',
@@ -1315,7 +1316,7 @@ 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. Fresh private Discovery composition now connects both physical Shrine-role costs without changing original effects or printed identity. Fresh bare public Basic starts now initialize Semuta with selected native families. Clean CHOAM/Ixian Ambassador private batches, including BG copies, retain the original entry, already-earned credit and one later replacement draw. Older games and optional/Advanced scopes remain separate; nested originating-card coverage remains unfinished.",
"Completed Ghola now offers Semuta before its exact conditional native one-spice income, including self-income. Claim/pass preserves returned pieces and normal quotas, then restores the original allow/cancel response once. Other parent guards remain. 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. Fresh bare public Basic starts now initialize Semuta with selected native families. Clean CHOAM/Ixian Ambassador private batches, including BG copies, retain the original entry, already-earned credit and one later replacement draw. Older games and optional/Advanced scopes remain separate; nested originating-card coverage remains unfinished.",
},
{
area: 'Player controls' as const,
@@ -1327,7 +1328,7 @@ export const RULE_TOPICS: RuleTopic[] = [
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. Thirty-two controlled legal-policy probes cover both physical Shrine-role events in both modes; no calibration. Four existing profiles also complete actual public Basic BG-copy CHOAM Ambassador reactions through twenty legal proposals; no new strategy or calibration.",
"Eight conditional Ghola-income continuations accept32 legal proposals across normal/full hands and all four existing profiles; all recover the card and allow the real income. No strategy tuning. 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. Four existing profiles also complete actual public Basic BG-copy CHOAM Ambassador reactions through twenty legal proposals; no new strategy or calibration.",
},
{
area: 'Documentation' as const,
@@ -1339,7 +1340,7 @@ export const RULE_TOPICS: RuleTopic[] = [
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. Earlier 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. Fresh Basic/Ambassador evidence passes twelve-file142/142, types/lint/build, ten original-action handler/table-rendering programmes and four existing profiles with twenty legal proposals. Public setup, actual one-spice Semuta auction, card purchase, placement/shipment and two actual ordinary movement entries retain35 main plus10 cache. Only unopened positions and original scalar/packet lotteries are selected. Full-hand/own-card edges separately stage conserved card transfers. Stale battle acknowledgements/module-rejection expectations and fixture types were repaired; representative old failures reproduced against the previous engine. Framework aliases/CSS stub; no browser, visual, saved-room or deployed acceptance. Wider nested/provenance scope and complete modes remain open.",
"Current conditional-Ghola proof passes10 files156/156, types/lint/build and eight actual-control/GameTable SSR journeys. Eight existing profiles accept32 proposals. Native160-action source plus explicitly conserved card staging covers claim/pass, full hands and allow/cancel; separate controlled self-income/leader cases retain physical identity and normal quotas. A private runner eligibility repair retains earlier passing checks by unchanged source identity. Full modes, wider parents, browser/deployed and comprehensive assurance remain open. The following counts are historical family evidence. 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. Earlier 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. Fresh Basic/Ambassador evidence passes twelve-file142/142, types/lint/build, ten original-action handler/table-rendering programmes and four existing profiles with twenty legal proposals. Public setup, actual one-spice Semuta auction, card purchase, placement/shipment and two actual ordinary movement entries retain35 main plus10 cache. Only unopened positions and original scalar/packet lotteries are selected. Full-hand/own-card edges separately stage conserved card transfers. Stale battle acknowledgements/module-rejection expectations and fixture types were repaired; representative old failures reproduced against the previous engine. Framework aliases/CSS stub; no browser, visual, saved-room or deployed acceptance. Wider nested/provenance scope and complete modes remain open.",
evidence: [
'tests/basic-semuta-ambassador.test.ts',
'tests/fixture-basic-semuta-ambassador.ts',
@@ -1347,6 +1348,10 @@ export const RULE_TOPICS: RuleTopic[] = [
'tests/semuta-recovery.test.ts',
'tests/bot-semuta.test.ts',
'tests/semuta-reaction-controls.test.tsx',
'game/ordinary-discard-income.ts',
'tests/fixture-semuta-ghola-income.ts',
'tests/semuta-ghola-income.test.ts',
'tests/semuta-ghola-income-controls.test.tsx',
'tests/semuta-drug.test.ts',
'tests/treachery-discard-continuations.test.ts',
'tests/multiplayer-discard-continuations.test.ts',
@@ -2644,6 +2649,7 @@ export const RULE_TOPICS: RuleTopic[] = [
'A Basic ground-movement promise can also require Ghola force preparation. The guide returns physical Tanks to reserves, then preserves an unused affordable shipment and one later matching ground move. Ghola itself does not fulfill movement or consume normal revival allowances. A known discarded Ghola may be recovered with the paid Box and played again.',
'Returned forces go to reserves. A leader revived with this card can fight again this turn, including in another territory. Atreides can also select a dead Kwisatz Haderach; revive it separately from its accompanying leader. Returning a controlled foreign ghola does not transfer it back to its original faction. Additional advanced and expansion interactions remain under audit.',
'An actual Ecaz native Ghola return uses that disc in its current ordinary cohort without consuming the ordinary phase slot. A repeat waits for the remaining native cohort and another opening. Independent Duke Ghola preserves a satisfied five-Tanks opening and returns him set aside; only Ecaz may revive him.',
'Semuta may recover the used Ghola before its native Tleilaxu one-spice income resolves. Keep the returned piece and normal revival allowance; claim or Continue then restores the original income response. Taking the card never repeats its revival.',
'A saved play preserves the revived pieces, any earned technology income and the discarded card. Recovery restores any pending Tleilaxu income response without reviving or paying twice. Private preparation guidance waits for recovery to finish.',
],
checklist: [
@@ -2652,7 +2658,7 @@ export const RULE_TOPICS: RuleTopic[] = [
status: 'Partial',
detail:
'Ordinary and typed forces, controlled leaders and Kwisatz retain original use and custody. Actual Ecaz native Ghola/foreign returns now record completed native cohort identity; independent Duke resurrection preserves its five-Tanks opening without aligning death counters. Ecaz-only living set-aside custody remains; broader combinations and assurance stay unfinished.',
evidence: ['game/ghola-force-preparation.ts', 'game/engine.ts', 'game/ecaz-duke-revival.ts', 'game/ecaz-revival-cohort.ts', 'game/revival.ts'],
evidence: ['game/ordinary-discard-income.ts', 'game/ghola-force-preparation.ts', 'game/engine.ts', 'game/ecaz-duke-revival.ts', 'game/ecaz-revival-cohort.ts', 'game/revival.ts'],
},
{
area: 'Player controls',