Adopt authorized Advanced Moritani normal-reveal forfeiture

This commit is contained in:
Quintine committed 2026-10-02 18:55:40 +10:00
1 parent b89e93a67f
commit 934b2ee4d7
9 files changed
+96 -19

No files matched your search

+2 -2
View File
@@ -7581,7 +7581,7 @@ function projectedMoritaniAssassinate(g: Game, viewer: string) {
const own = viewer === state.owner;
const choices = pending && own ? nexusRule(() => moritaniAssassinateChoices(moritaniAssassinateContext(g,pending))) : null;
return {owner:state.owner,blocked:own && state.normalTraitorCall
? 'Assassinate Leaders after a normal traitor call awaits clarification of the printed loss-of-advantage rule.' : null,
? 'Moritani forfeited Assassinate Leaders for the rest of this game after revealing its Traitor Card normally.' : null,
pending:pending ? {event:pending.event,opponent:pending.opponent,territory:pending.territory,
cards:choices?.cards ?? [],blocked:choices?.blocked ?? null} : null,
history:state.opportunities.filter(r => r.stage === 'revealed' || r.stage === 'replaced').map(r => ({
@@ -20400,7 +20400,7 @@ function resolveBattle(g: Game, retreat?: DiplomatRetreatSelection) {
?.name ?? identity);
log(g, `${holder.name} revealed ${name} as a traitor.`);
if (holder.id === g.moritaniAssassinate?.owner)
log(g, `${holder.name} called a traitor normally. Further Assassinate Leaders use awaits clarification of the printed loss-of-advantage rule.`, {faction:'moritani',name:'Assassinate Leaders boundary'});
log(g, `${holder.name} revealed a Traitor Card normally and forfeited Assassinate Leaders for the rest of this game.`, {faction:'moritani',name:'Assassinate Leaders forfeited'});
}
const dead = (l: Leader | undefined) => {
if (l) {
+2 -1
View File
@@ -18,6 +18,7 @@ export type MoritaniAssassinateReceipt = {
export type MoritaniAssassinateState = {
version: 1;
owner: string;
/** Authorized Advanced source: normal reveal forfeits this ability for the game. */
normalTraitorCall: boolean;
opportunities: MoritaniAssassinateReceipt[];
};
@@ -291,7 +292,7 @@ export function moritaniAssassinateChoices(
return stopped('This Assassinate opportunity has already ended.');
if (state.normalTraitorCall)
return stopped(
'Assassinate after an ordinary Moritani traitor call awaits its duration ruling.',
'Moritani forfeited Assassinate Leaders for the rest of this game after revealing its Traitor Card normally.',
);
if (
state.opportunities.some(
+2 -2
View File
@@ -2997,7 +2997,7 @@ export const RULE_TOPICS: RuleTopic[] = [
'After you lose a battle, this advanced advantage is available only if the opposing leader disc survived and no Traitor was called.',
'You may reveal a Traitor Card for that opposing faction, but it must name a different leader from the one you just fought. If that named leader is not in the Tanks, kill it and collect spice for its value.',
'An already-dead named leader remains a legal reveal, awarding no death or spice. During Mentat Pause, set the revealed card aside face up as a marker and draw a new Traitor Card. You can use this advantage only once against each faction in the game.',
'The printed rule says a normal traitor reveal loses this advantage, but its duration remains unresolved. The preview guards further assassination after a normal call. Karama has no effect against Assassinate Leaders.',
'The authorized revised Advanced PDF, physical page35, requires that you have not revealed your Traitor Card normally this game. A normal own-card reveal therefore forfeits Assassinate Leaders for the rest of this game, across turns and opponents. Existing state preserves that forfeiture; Karama has no effect against the ability. This is the authorized source, not a new GF9 erratum.',
'If Harkonnen has captured your own leader and you hold its Traitor Card, you may call that traitor normally; you may not use Assassinate Leaders on that basis.',
'Terror Assassination chooses a random leader when its token is triggered. It does not use this battle-loss condition, different-leader Traitor Card or once-per-faction allowance. Moritani starts remain unavailable in Basic and Advanced.',
],
@@ -3005,7 +3005,7 @@ export const RULE_TOPICS: RuleTopic[] = [
{area:'Implementation',status:'Partial',detail:'Explicit Advanced Moritani/base-opponent preview before any normal traitor call; native disc deaths, printed bounty, dead-target zero bounty and exact Mentat replacement.',evidence:['game/moritani-assassinate.ts','game/engine.ts']},
{area:'Player controls',status:'Partial',detail:'Uniform private choice/decline, named target and bounty, public face-up markers and readable inspection; normal activation awaits private-step UX decision.',evidence:['components/moritani-assassinate.tsx','components/game-table.tsx']},
{area:'AI',status:'Partial',detail:'All four profiles choose from the owner-only quote or decline; no hidden rival data or strength-calibration claim.',evidence:['game/bots.ts','tests/moritani-assassinate-engine.test.ts']},
{area:'Documentation',status:'Partial',detail:'Official authority, dead-target conditional, normal-call ambiguity, exceptional custody and optional-module boundaries remain explicit.',evidence:['docs/MORITANI_ASSASSINATE_LEADERS.md']},
{area:'Documentation',status:'Partial',detail:'Printed effect and authorized Advanced game-long normal-reveal forfeiture are explicit; exceptional leader custody, private-step UX and optional-module boundaries remain open.',evidence:['docs/MORITANI_ASSASSINATE_LEADERS.md','docs/RULE_DECISIONS.md']},
{area:'Verification',status:'Partial',detail:'Rules, controls, genuine-setup staged battles, private views, authenticated recovery, concurrent writes and physical replacement chains; full faction acceptance remains open.',evidence:['tests/moritani-assassinate-quote.test.ts','tests/moritani-assassinate-engine.test.ts','tests/moritani-assassinate-controls.test.tsx','tests/moritani-assassinate-recovery.test.ts']},
],
related: [