Offer Semuta after clean final Truthtrance answer

This commit is contained in:
Quintine committed 2026-09-30 08:03:18 +10:00
1 parent 162f01c160
commit 836af6fb3a
9 files changed
+178 -46

No files matched your search

+7 -4
View File
@@ -5685,8 +5685,8 @@ function treacheryDiscardIntegrity(g: Game) {
} else throw new RuleError('Unknown saved discard continuation.');
}
/** Bounded public single-card reaction after a completed ordinary effect, paid
* Box search, early-ended Ornithopter flight or clean Distrans transfer. A
* completed flight's arrival may open further entry windows and stays automatic. */
* Box search, early-ended Ornithopter flight, clean Distrans transfer or final
* definite Truthtrance answer without a new promise or parent transaction. */
function semutaOfferSupported(
g: Game,
continuation: NonNullable<Game['pendingTreacheryDiscard']>['continuation'],
@@ -5695,8 +5695,11 @@ function semutaOfferSupported(
if (continuation.kind !== 'ordinaryCardDiscard' &&
continuation.kind !== 'nullentropyDiscard' &&
continuation.kind !== 'distransDiscard' &&
!(continuation.kind === 'ornithopterDiscard' && continuation.source === 'end')) return false;
if (continuation.kind === 'distransDiscard' &&
!(continuation.kind === 'ornithopterDiscard' && continuation.source === 'end') &&
!(continuation.kind === 'truthtranceDiscard' &&
continuation.consumed.source === undefined &&
continuation.remaining === null && continuation.promise === null)) return false;
if ((continuation.kind === 'distransDiscard' || continuation.kind === 'truthtranceDiscard') &&
(g.pendingChoamMove || g.pendingIxMove || g.pendingFremenMove ||
g.ornithopter || g.summonedWorm || g.wormRides.length > 0)) return false;
return g.semutaPreview === true && g.status === 'playing' &&
+4 -4
View File
@@ -1155,7 +1155,7 @@ export const RULE_TOPICS: RuleTopic[] = [
: definition.card.effect === 'portableSnooper'
? 'Choose Portable Snooper as your ordinary poison defense, or use the late-defense panel after reveal before your own traitor decision. It uses ordinary winner retention and cannot stop Poison Tooth.'
: definition.card.effect === 'semutaDrug'
? 'In an explicitly opted-in Richese development game, every seat sees a neutral response after a clean public ordinary-card discard, a completed paid Box search, early ending an Ornithopter flight, or completing a clean private Distrans transfer. Continue or commit your held Semuta with a free hand slot; only the freshly discarded public card transfers, never the private card given to its recipient. Completed-flight arrival, competing transactions, other discard producers, full-hand sequencing and normal Richese starts remain unfinished.'
? 'In an explicitly opted-in Richese development game, every seat sees a neutral response after a clean public ordinary-card discard, completed paid Box search, early-ended Ornithopter flight, clean private Distrans transfer or final definite Truthtrance answer. Continue or commit held Semuta with a free hand slot; only the freshly discarded public card transfers. A Distrans gift remains private with its recipient, and the Truthtrance answer/history is already bound. Competing transactions, later queued questions, full-hand sequencing and normal Richese starts remain unfinished.'
: 'Reference component only: this Richese card’s game actions are not enabled.',
],
...(definition.card.effect === 'semutaDrug'
@@ -1165,7 +1165,7 @@ export const RULE_TOPICS: RuleTopic[] = [
area: 'Implementation' as const,
status: 'Partial' as const,
detail:
'An explicitly opted-in Richese profile interrupts clean public ordinary-card, completed paid Box, early-ended Ornithopter and completed private Distrans discards with a neutral all-seat offer. Committing held Semuta claims the sole eligible other-player discarded card and discards Semuta. The private Distrans gift remains with its recipient; the other saved effects and movement queue resume once. Completed-flight arrival, competing transactions, other typed producers and full-hand exchange remain unfinished.',
'An explicitly opted-in Richese profile interrupts clean public ordinary-card, paid Box, early-ended Ornithopter, private Distrans and final definite Truthtrance discards with a neutral all-seat offer. Committing held Semuta claims only the other-player discarded card and discards Semuta. The private gift stays with its recipient, the answered Truthtrance history remains public, and saved effects or movement resume once. Promise-bound or queued questions, competing transactions, other typed producers and full-hand exchange remain unfinished.',
},
{
area: 'Player controls' as const,
@@ -1183,13 +1183,13 @@ export const RULE_TOPICS: RuleTopic[] = [
area: 'Documentation' as const,
status: 'Partial' as const,
detail:
'The guide distinguishes bounded public ordinary-card, paid Box, early-ended Ornithopter and clean Distrans previews, privacy-neutral acknowledgements and conservative free-slot policy from unresolved full-hand sequencing and remaining discard sources.',
'The guide distinguishes bounded public ordinary-card, paid Box, early-ended Ornithopter, clean Distrans and final definite Truthtrance previews, privacy-neutral acknowledgements and conservative free-slot policy from unresolved full-hand sequencing and remaining discard sources.',
},
{
area: 'Verification' as const,
status: 'Partial' as const,
detail:
'Genuine setup, physical card custody, neutral hidden-hand parity, saved JSON, authenticated SQLite CAS and legal AI participation cover clean ordinary-card, paid Box, early-ended Ornithopter and private Distrans reactions. Other discard producers, full games and live deployment remain unverified.',
'Genuine setup, physical card custody, neutral hidden-hand parity, saved JSON, authenticated SQLite CAS and legal AI participation cover clean ordinary-card, paid Box, early-ended Ornithopter, private Distrans and final definite Truthtrance reactions. Other discard producers, full games and live deployment remain unverified.',
evidence: [
'tests/semuta-engine.test.ts',
'tests/semuta-recovery.test.ts',