Allow Advanced Sapho to pause a started movement turn

This commit is contained in:
Quintine committed 2026-10-27 23:08:17 +11:00
1 parent 533c651b07
commit 812657bb35
13 files changed
+321 -26

No files matched your search

+2 -2
View File
@@ -27130,8 +27130,8 @@ function saphoMovementOrderContext(g: Game): SaphoMovementOrderContext | null {
return {queue,started:queue.remaining.filter(id=>saphoMovementStarted(g,getPlayer(g,id))),
guild:guild ? {player:guild.id,granted:!!g.guildTimingGranted,locked:!!g.guildTimingLocked} : null,
// These shared preparations are not yet owned/resumed across another
// player's turn. Only a clean Basic physical shipment/move may suspend.
allowStartedLast: !g.advanced && !g.karamaShipping && !g.ornithopter && !g.hajr.includes(active.id) &&
// player's turn. Only a clean physical shipment/move may suspend.
allowStartedLast: !g.karamaShipping && !g.ornithopter && !g.hajr.includes(active.id) &&
!(active.faction === 'choam' && g.choamMovement?.turn === g.turn) &&
!g.pendingTreacheryDiscard && !g.pendingKull && !g.pendingHomeworldShipment && !g.pendingGuildTransport &&
!g.pendingArrivalOverlap && !g.pendingArrivalReaction?.length && !g.pendingAdvisorMatching &&
+3 -3
View File
@@ -499,7 +499,7 @@ export const RULE_TOPICS: RuleTopic[] = [
'In ordinary cyclic bidding or native Advanced normal Black Market, provisional first/last changes the current lot only, anchored at the live next bidder. Later circuits use that local cycle. Keep standing bids, allied funding and passes; a passed holder waits for a real raise, and the high bidder has no pending bid to reorder. Every purchase still requires a strict raise. Full effective-cycle no-ops cannot consume the card. The next lot uses its normal physical opener.',
'Discarding Sapho frees a hand slot. A full-hand holder can join a still-open lot through this order change. Once Around completed opportunities cannot repeat. A cyclic pass stays spent until a genuine raise reopens it; a finished lot cannot reopen.',
'The movement controls change complete shipment and movement turns at a boundary before the current player begins. First moves you ahead of the remaining unstarted turns, including after earlier players have fully finished. In Advanced, provisional first ordering retains an unspent Guild’s native next-boundary take/wait choice; Guild may still act ahead. An already granted current Guild turn cannot be displaced, and a Karama-locked privilege stays locked. Last stays after the Guild even if the Guild later chooses to wait.',
'At a clean boundary after another player has begun shipment and movement, an unstarted holder may provisionally reorder only later unstarted turns. First means first after that current actor finishes; last remains after Guild. In Basic, the holder may also provisionally pause its own started turn and resume last, retaining already spent shipment and movement. Pending card, arrival, payment and shared movement preparations must finish first. Advanced Guild retains its next-boundary timing choice.',
'At a clean boundary after another player has begun shipment and movement, an unstarted holder may provisionally reorder only later unstarted turns. First means first after that current actor finishes; last remains after Guild. In Basic or Advanced, the holder may also provisionally pause its own started turn and resume last, retaining already spent shipment and movement. Pending card, arrival, payment and shared movement preparations must finish first. Advanced Guild retains its next-boundary timing choice; Guild may voluntarily pause its own granted turn.',
'Between completed battles, choose first or last among remaining battle choosers. The priority lasts for the rest of the Battle phase. You still need a real unresolved battle. Others may choose battles against you before your own turn; last is not immunity. This scope changes the chooser, not each battle’s aggressor or tie advantage.',
'In a fresh Richese battle, use unreserved Sapho at a clean boundary before both combatants finish final battle actions, including after sealed plans and revealed declarations. Habbanya still precedes ordinary aggressor tie priority. Participants, plans, promises, weapon choices and votes do not swap or replay. Older battles retain their pre-plan opportunity.',
'When two or more players declared Truthtrance in a supported clean parent, each queued holder may continue or use their held Sapho to move their entire pending question group first or last. Physical storm order and each holder’s card order stay unchanged. Supported Basic Semuta claim/pass restores the same question queue. Clean ordinary auction lots also preserve their standing bid and remaining clock. Richese cache Once Around and Silent lots preserve their original bidding and funding; Black Market, other special auctions, battle and pending-parent combinations remain unfinished.',
@@ -509,7 +509,7 @@ export const RULE_TOPICS: RuleTopic[] = [
'Finish pending shipment, movement and card preparations and decisions before changing order. The exact Extortion payer window is a supported exception for its own order only. Your hand panel lists available choices. Reserved cards and positions you already hold cannot be selected.',
'Completed bids and turns stay completed. Storm order, committed funding and movement counters do not reset. Refreshing preserves the same remaining opportunities and any declared last position.',
'In the explicitly opted-in Semuta preview, clean Once Around, movement and ordered Charity/Revival discards pause after their queues reorder; a clean between-battles chooser discard pauses after changing battle priority but before the next chooser acts; an aggressor discard pauses after changing ordinary tie priority. Charity/Revival retain their current participant, claims or requests and allowances through Semuta claim/pass. Fresh late continuations also bind revealed choices and the public final revision; old continuation bytes remain unchanged. Every seat receives the same neutral offer. Claim or decline moves only the used card or leaves it discarded; each committed queue or unresolved battle continues once. Direct combined late claim/capture proof remains open.',
'Both combatants receive the same persistent final battle opportunity after original votes and native late defense, regardless of held cards or result. Finish explicitly; a Sapho priority change clears both finish marks with a fresh event. The second finish closes priority before Stone counts and outcome settlement. This shared online procedure, cyclic lot duration, queued movement and the Basic own-turn pause are provisional conventions. Other phase ordering and Advanced own-turn suspension remain unfinished. Silent bids retain simultaneous timing and storm tie order.',
'Both combatants receive the same persistent final battle opportunity after original votes and native late defense, regardless of held cards or result. Finish explicitly; a Sapho priority change clears both finish marks with a fresh event. The second finish closes priority before Stone counts and outcome settlement. This shared online procedure, cyclic lot duration, queued movement and the own-turn pause are provisional conventions. Other phase ordering remains unfinished. Silent bids retain simultaneous timing and storm tie order.',
],
example:
'Atreides bids 2. Before taking its bid, the Emperor uses Sapho to go last. Richese bids 3, then the Emperor must bid at least 4 to win. Atreides does not receive another bid.',
@@ -524,7 +524,7 @@ export const RULE_TOPICS: RuleTopic[] = [
area: 'Implementation',
status: 'Partial',
detail:
'Finite Once Around, current-lot cyclic bidding, clean/queued movement and ordered Advanced Charity/Revival, remaining battle-choice and late aggressor modes are connected. Queued timing retains the started actor; Charity/Revival keep native claims or requests/allowances and separate physical order through their Semuta disposal. Tail timing is visibly provisional. Other phases and split-own-turn mode remain unfinished.',
'Finite Once Around, current-lot cyclic bidding, clean/queued movement and ordered Advanced Charity/Revival, remaining battle-choice and late aggressor modes are connected. Queued timing retains another started actor; a clean own started movement turn may provisionally resume last in either ruleset. Charity/Revival keep native claims or requests/allowances and separate physical order through their Semuta disposal. Tail timing is visibly provisional. Other phases remain unfinished.',
},
{
area: 'Player controls',
+1 -2
View File
@@ -8,7 +8,7 @@ export type SaphoMovementOrderContext = {
started: readonly string[];
/** Present only for Advanced Guild timing. */
guild: { player: string; granted: boolean; locked: boolean } | null;
/** Explicit Basic clean-boundary prototype; the engine owns all action state. */
/** Explicit clean-boundary prototype; the engine owns all action state. */
allowStartedLast?: boolean;
};
export class SaphoMovementOrderError extends Error {
@@ -78,7 +78,6 @@ export function reorderSaphoMovementOrder(context: SaphoMovementOrderContext, re
'Only a pending participant may change its movement position.');
if (context.started.includes(request.player) && request.player === queue.current &&
context.allowStartedLast === true) {
requireMovement(context.guild === null, 'The started-turn Sapho preview supports Basic timing only.');
requireMovement(request.mode === 'last', 'An already-started turn can only be moved to last.');
requireMovement(queue.remaining.length > 1, 'This participant is already last.');
// Suspend this same opportunity; never synthesize a completed turn or a