Connect Sapho first and last to Extortion payer choices
Apply the printed ordered-action alternative provisionally to the unanswered native Extortion suffix. Preserve collected bank5, completed declines, payer membership, one payment3 and placement-first policy. Replay a public local-order receipt and retain it through ledger answers; expire the old payer event even when the same player remains next. Permit only the exact current Extortion decision as a clean Sapho window. Add persistent remaining-order/card controls and existing minimal policy participation. The typed Semuta suffix parks one updated payer decision and restores it without paying, advancing or recollecting. Validation:9-file115/115, types/lint/build and six original public Basic/Advanced host/setup/paid-cache1/placed-Terror/paid-entry1/reveal/Mentat-placement-before-bank5 programmes. An actual earlier decline stays finished; first/payment3 and last/payment3 or all-decline preserve native retirement/recovery. Four profiles make eight legal holder/payer proposals and complete. Public order and private payer affordability render in actual GameTable plus enabled/busy controls. Pure replay/no-op/recovered reuse cases are separate. Bounded source/continuation review found no concrete defect. Extortion/Sapho boundary is provisional. Direct combined Semuta claim/capture, broader combinations, complete modes, final assurance and browser/deployed acceptance remain open. No saved-room/database/reset/restart/deployment operation.
This commit is contained in:
1 parent
2d89ddb6e1
commit
6c83148ead
14 files changed
+855
-16
No files matched your search
@@ -10,8 +10,11 @@ import { CardInspector } from './card-inspector';
|
||||
function unavailableReason(game: GameView) {
|
||||
if (game.status !== 'playing')
|
||||
return 'Order changes are available during play.';
|
||||
if (game.truthtrance || game.response || game.decision || game.phaseOpening)
|
||||
if (game.truthtrance || game.response || game.phaseOpening ||
|
||||
(game.decision && !(game.phase === 8 && game.decision.kind === 'moritaniExtortion')))
|
||||
return 'Finish the current interaction before changing turn order.';
|
||||
if (game.phase === 8 && game.extortion?.pending)
|
||||
return 'Only an unanswered non-Moritani player can change their Extortion choice position. Earlier declines stay finished. Already-held first/last positions and committed cards are unavailable; you may still decline payment when your choice arrives.';
|
||||
if (game.phase === 3) {
|
||||
if (game.richeseAuction?.method === 'silent')
|
||||
return 'Silent bids are simultaneous. These controls do not change their tie order.';
|
||||
@@ -63,6 +66,7 @@ export function JuiceOfSapho({
|
||||
const cyclic = option.scope === 'cyclicAuction';
|
||||
const battle = option.scope === 'battleOrder';
|
||||
const aggressor = option.scope === 'battleAggressor';
|
||||
const extortion = option.scope === 'extortion';
|
||||
return (
|
||||
<div
|
||||
key={`${option.scope}-${option.event}-${option.mode}`}
|
||||
@@ -71,6 +75,8 @@ export function JuiceOfSapho({
|
||||
<p>
|
||||
{aggressor
|
||||
? 'Become this battle’s aggressor. You win ordinary ties; a Habbanya Stronghold advantage still takes precedence. The participants, committed plans and later battle choices stay unchanged.'
|
||||
: extortion
|
||||
? `Take your Extortion choice ${option.mode} among unanswered players. Earlier declines and Moritani’s five-spice bank collection remain. You may decline instead of paying; the first actual three-spice payment ends all offers.`
|
||||
: cyclic
|
||||
? `Bid ${option.mode} in the current cyclic lot. Provisional duration: this lot only. Existing bids, funding and passes stay committed. Later circuits use the changed cycle; the next lot returns to its normal opener.`
|
||||
: once
|
||||
@@ -87,7 +93,7 @@ export function JuiceOfSapho({
|
||||
}}
|
||||
>
|
||||
{aggressor ? 'Become aggressor and discard Juice of Sapho' :
|
||||
`${once || cyclic ? 'Bid' : battle ? 'Choose battles' : 'Take your movement turn'} ${option.mode} and discard Juice of Sapho`}
|
||||
`${once || cyclic ? 'Bid' : battle ? 'Choose battles' : extortion ? 'Take your Extortion choice' : 'Take your movement turn'} ${option.mode} and discard Juice of Sapho`}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -18,12 +18,16 @@ export function MoritaniExtortionNotice({ game }: { game: GameView }) {
|
||||
</p>
|
||||
)}
|
||||
{pending && (
|
||||
<>
|
||||
<p>
|
||||
Moritani has collected the bank award. {payer?.name ?? 'The current player'}
|
||||
{' '}may pay {pending.amount} spice to prevent Extortion’s return, or decline.
|
||||
The first payment ends the opportunity; if everyone declines, the token
|
||||
returns to Moritani’s hidden supply.
|
||||
</p>
|
||||
<p>Remaining choices: {pending.remaining.map(id => game.players.find(player => player.id === id)?.name ?? id).join(' → ')}.</p>
|
||||
{pending.saphoReordered && <p>Juice of Sapho changed the remaining order. Earlier declines stay finished.</p>}
|
||||
</>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user