Support cohort-eligible Ambassador leader and KH repeats
Replace lifetime first-death caps with the selected provisional composition: first returns remain immediate, while later native leaders and KH must satisfy their existing ordinary death/cohort conditions. Extract one phase/slot/price-independent cohort quote for ordinary Revival and the independent Ambassador. Preserve ordinary timing, payment, prevention, native early service and one-leader controls. Snapshot an opened cohort before a free return makes a leader alive, preserving remaining ordinary returns. Keep Ecaz identity tracking and the shared Duke permission separate. KH retains activation/loss history and five native discs; update its marker above the actual opened owner cycle and old marker. Independent grants retain ordinary allowance and income policies. Explain eligibility in persistent controls and source-labelled reference. Verify related rules/controls, types/lint/build, controlled native/copied free-return-to-next-ordinary-Revival programmes layered on original public Basic paid-entry sources, controlled Advanced KH actual entry/return, income allow/cancel and twelve minimal legal policy continuations. Assigned repeat/cohort facts are explicitly controlled, not claimed original battle histories. Full modes, wider custody/module combinations, comprehensive assurance and deployed acceptance remain unfinished. No strategic calibration, saved-room operation, reset, restart or deployment.
This commit is contained in:
1 parent
16f654071a
commit
152039be5b
12 files changed
+719
-51
No files matched your search
+44
-20
@@ -5,7 +5,7 @@ import { isAuditorLeader } from './choam-auditor';
|
||||
import { homeworldLowBonus } from './homeworld-benefits';
|
||||
import { recruitsRevivalAllowance } from './recruits';
|
||||
import { DUKE_VIDAL_ID } from './duke-vidal';
|
||||
import { ecazDukeRevivalBlock, quoteEcazDukeRevival } from './ecaz-duke-revival';
|
||||
import { ecazDukeRevivalBlock, quoteEcazDukeRevival, type EcazDukeRevivalContext } from './ecaz-duke-revival';
|
||||
import {
|
||||
quoteEcazRevivalCohort, completeEcazRevivalCohortUse,
|
||||
recordEcazRevivalOpening, recordEcazFirstExecution,
|
||||
@@ -164,8 +164,45 @@ export function normalRevivalCycle(
|
||||
return cycle;
|
||||
}
|
||||
|
||||
/** Ordinary Ecaz cohorts keep native identity separate from independent Duke deaths.
|
||||
* Only the absent-Tleilaxu card quote may waive the unopened first cohort. */
|
||||
export type LeaderRevivalCohortContext = EcazDukeRevivalContext;
|
||||
export type LeaderRevivalCohortPlayer = Pick<
|
||||
Player, 'id' | 'faction' | 'leaders' | 'revivalCycle' | 'ecazRevivalCohort'
|
||||
>;
|
||||
export type LeaderRevivalCohortQuote = {
|
||||
cycle: number;
|
||||
leaders: readonly string[];
|
||||
dukeAvailable: boolean;
|
||||
dukeBlocked: string | null;
|
||||
};
|
||||
|
||||
/** Ordinary death/cohort permission only, independent of phase, allowance,
|
||||
* payment and prevention. The native Tleilaxu early service is separate.
|
||||
* Ecaz keeps native identity separate from independent Duke deaths; only the
|
||||
* absent-Tleilaxu card quote may waive the unopened first cohort. */
|
||||
export function quoteLeaderRevivalCohort(
|
||||
g: LeaderRevivalCohortContext,
|
||||
p: LeaderRevivalCohortPlayer,
|
||||
waiveOpening = false,
|
||||
): LeaderRevivalCohortQuote {
|
||||
const shared = p.faction === 'ecaz' && g.dukeVidal;
|
||||
const dukeContext = shared && g.status === 'playing' ? g : null;
|
||||
const dukeBlocked = dukeContext ? ecazDukeRevivalBlock(dukeContext, p.id) : null;
|
||||
const dukeAvailable = !!dukeContext && !dukeBlocked;
|
||||
const cohort = shared ? quoteEcazRevivalCohort(p, dukeAvailable, waiveOpening) : null;
|
||||
let cycle = cohort?.cycle ?? normalRevivalCycle(p);
|
||||
if (waiveOpening && !cohort) cycle = Math.max(1, cycle);
|
||||
const leaders = p.leaders.flatMap((leader) => {
|
||||
if (!leader.dead || leader.capturedBy || leader.gholaBy) return [];
|
||||
// Supplied Advanced p29 E permits Auditor revival each turn regardless
|
||||
// of the ordinary five-disc cohort, including its repeated deaths.
|
||||
const auditorReturn = g.advanced && p.faction === 'choam' && isAuditorLeader(leader);
|
||||
return auditorReturn || (cycle > 0 && (cohort
|
||||
? !cohort.returned.includes(leader.id) : leader.deaths === cycle))
|
||||
? [leader.id] : [];
|
||||
});
|
||||
return { cycle, leaders, dukeAvailable, dukeBlocked };
|
||||
}
|
||||
|
||||
export function leaderRevivalOptions(
|
||||
g: Pick<
|
||||
Game,
|
||||
@@ -192,27 +229,14 @@ export function leaderRevivalOptions(
|
||||
waiveOpening = false,
|
||||
) {
|
||||
const shared = p.faction === 'ecaz' && g.dukeVidal;
|
||||
const dukeContext = shared && g.status === 'playing' ? g : null;
|
||||
const dukeBlocked = dukeContext ? ecazDukeRevivalBlock(dukeContext, p.id) : null;
|
||||
const dukeAvailable = !!dukeContext && !dukeBlocked;
|
||||
const cohort = shared ? quoteEcazRevivalCohort(p, dukeAvailable, waiveOpening) : null;
|
||||
let cycle = cohort?.cycle ?? normalRevivalCycle(p);
|
||||
if (waiveOpening && !cohort) cycle = Math.max(1, cycle);
|
||||
const { cycle, leaders: cohortLeaders, dukeAvailable, dukeBlocked } =
|
||||
quoteLeaderRevivalCohort(g, p, waiveOpening);
|
||||
const enabled = g.phase === 4 && !revivalPrevented(g, p.id);
|
||||
const discount = revivalDiscount(g, p);
|
||||
const leaders = p.leaders.flatMap((leader) => {
|
||||
if (!enabled || !leader.dead || leader.capturedBy || leader.gholaBy)
|
||||
return [];
|
||||
// Supplied Advanced p29 E permits Auditor revival each turn regardless
|
||||
// of the other leaders in Tanks; retain the ordinary one-leader allowance.
|
||||
const auditorReturn =
|
||||
g.advanced &&
|
||||
p.faction === 'choam' &&
|
||||
isAuditorLeader(leader);
|
||||
const normal =
|
||||
!p.leaderRevived &&
|
||||
(auditorReturn || (cycle > 0 && (cohort
|
||||
? !cohort.returned.includes(leader.id) : leader.deaths === cycle)));
|
||||
const normal = !p.leaderRevived && cohortLeaders.includes(leader.id);
|
||||
if (
|
||||
!normal &&
|
||||
(p.faction !== 'tleilaxu' ||
|
||||
@@ -232,7 +256,7 @@ export function leaderRevivalOptions(
|
||||
];
|
||||
});
|
||||
if (dukeAvailable && enabled && !p.leaderRevived) {
|
||||
const quote = quoteEcazDukeRevival(dukeContext!, p.id, !!discount);
|
||||
const quote = quoteEcazDukeRevival(g, p.id, !!discount);
|
||||
leaders.push({
|
||||
id: DUKE_VIDAL_ID,
|
||||
name: quote.duke.leader.name,
|
||||
|
||||
Reference in new issue
Block a user