Announce eligible Basic leaderless battles before plans
Verify and publish checkpoint container / container (push) Successful in 10m34s
Verify and publish checkpoint container / container (push) Successful in 10m34s
This commit is contained in:
1 parent
2bac45b294
commit
685bd8bdfc
8 files changed
+417
-11
No files matched your search
+32
-1
@@ -985,6 +985,9 @@ export type Battle = {
|
||||
plans: Record<string, Plan>;
|
||||
/** Basic declarations recorded only when a new leaderless plan is sealed. */
|
||||
basicLeaderlessAnnouncements?: string[];
|
||||
/** Fresh clean Basic battles announce a bounded no-revival case before plans. */
|
||||
basicEarlyLeaderlessVersion?: 1;
|
||||
basicEarlyLeaderless?: string[];
|
||||
revealed: boolean;
|
||||
traitorCalls: Record<string, boolean>;
|
||||
traitorDecisionPromises?: TraitorDecisionPromise[];
|
||||
@@ -42679,6 +42682,25 @@ function applyActionWithInitiator(state: Game, id: string, action: Action, initi
|
||||
charityOrderIntegrity(g);
|
||||
return g;
|
||||
}
|
||||
/** The published inability is safe before a plan only when no leader can be
|
||||
* revived and this clean Basic roster cannot privately transfer a Cheap Hero.
|
||||
* Other cases retain the original seal-time announcement. */
|
||||
function announceEarlyBasicLeaderless(g: Game) {
|
||||
const b = g.battle;
|
||||
if (!b || b.basicEarlyLeaderlessVersion !== 1 || g.status !== 'playing' || g.advanced ||
|
||||
g.phase !== 6 || b.revealed || !b.prepared || b.preparation || b.preLeader && !b.preLeader.closed ||
|
||||
g.response || g.decision || g.truthtrance || g.phaseOpening || g.pendingKarama ||
|
||||
g.pendingKull || g.pendingTreacheryDiscard || g.pendingNullentropy) return;
|
||||
for (const id of [b.attacker, b.defender]) {
|
||||
if (b.plans[id] || b.basicEarlyLeaderless?.includes(id)) continue;
|
||||
const p = getPlayer(g, id), leaders = controlledLeaders(g, p);
|
||||
if (!leaders.length || leaders.some(l => l.dead || l.capturedBy || !l.usedAt || l.usedAt === b.territory) ||
|
||||
p.hand.some(c => c.kind === 'hero' && !(b.voice?.target === id && !b.voice.must &&
|
||||
playedVoiceMatch(c, 'leader', b.voice.kind)))) continue;
|
||||
(b.basicEarlyLeaderless ??= []).push(id);
|
||||
log(g, `${p.name} has no available leader or Cheap Hero for this battle.`);
|
||||
}
|
||||
}
|
||||
function finishActionContinuations(g: Game) {
|
||||
if (g.victoryContinuation) return;
|
||||
if (g.pendingNexusHarkonnenBetrayal) return;
|
||||
@@ -42751,6 +42773,7 @@ function finishActionContinuations(g: Game) {
|
||||
!g.decision && !g.response && !g.truthtrance && !g.phaseOpening &&
|
||||
!g.pendingKarama && !g.pendingTerrorEntry && !g.pendingAmbassador)
|
||||
finishMoritaniPlacement(g);
|
||||
announceEarlyBasicLeaderless(g);
|
||||
}
|
||||
function settleAutomaticContinuations(g: Game) {
|
||||
if (arrivalOrderWaiting(g)) return;
|
||||
@@ -46984,6 +47007,11 @@ function applyActionInner(
|
||||
...choice,
|
||||
chooserEvent: battleChooserEvent(g.turn, battleOrderAfterBattle(g), g.battleOrder?.uses.length ?? 0),
|
||||
event: battleEvent,
|
||||
...(!g.advanced && g.expansions.length === 0 && !g.ecazTreachery && !g.techTokens &&
|
||||
!g.strongholdCards && !g.leaderSkills && !g.homeworlds && !g.nexusCards && !g.discoveryEnabled &&
|
||||
!g.sandtrout && !g.coalitionState && g.players.every(seat =>
|
||||
['atreides', 'beneGesserit', 'emperor', 'fremen', 'guild', 'harkonnen'].includes(seat.faction))
|
||||
? { basicEarlyLeaderlessVersion: 1 as const } : {}),
|
||||
stoneAllocationVersion: 1,
|
||||
...(g.leaderSkills ? { smugglerCollectionVersion: 1 as const } : {}),
|
||||
...(g.leaderSkills && mentatQuestionModeSupported(g) ? { mentatQuestionVersion: 1 as const } : {}),
|
||||
@@ -47151,7 +47179,8 @@ function applyActionInner(
|
||||
b.plans[id] = validatePlan(g, p, action);
|
||||
if (b.plans[id].leader === null) {
|
||||
if (!g.advanced) (b.basicLeaderlessAnnouncements ??= []).push(id);
|
||||
log(g, `${p.name} announced a Battle Plan without a leader or Cheap Hero; no battle cards can be played.`);
|
||||
if (!b.basicEarlyLeaderless?.includes(id))
|
||||
log(g, `${p.name} announced a Battle Plan without a leader or Cheap Hero; no battle cards can be played.`);
|
||||
}
|
||||
if (b.fullPlan?.target === id) {
|
||||
recordFullPlanInspection(g, b.fullPlan.owner);
|
||||
@@ -49031,6 +49060,8 @@ export function viewGame(state: Game, id: string, now?: number) {
|
||||
})
|
||||
: [],
|
||||
submitted: Object.keys(b.plans),
|
||||
...(b.basicEarlyLeaderless?.some(playerId => !b.plans[playerId])
|
||||
? { earlyLeaderless: b.basicEarlyLeaderless.filter(playerId => !b.plans[playerId]) } : {}),
|
||||
leaderless: g.advanced
|
||||
? Object.keys(b.plans).filter(playerId => b.plans[playerId].leader === null)
|
||||
: (b.basicLeaderlessAnnouncements ?? []).filter(playerId => b.plans[playerId]?.leader === null),
|
||||
|
||||
Reference in new issue
Block a user