Support Emperor special Karama truth commitments
Verify and publish checkpoint container / container (push) Canceled after 0s
Verify and publish checkpoint container / container (push) Canceled after 0s
This commit is contained in:
1 parent
b448144c52
commit
add8e1d51a
14 files changed
+345
-20
No files matched your search
@@ -1,11 +1,12 @@
|
||||
import { harvesterAvailable } from './cards';
|
||||
|
||||
export const WINDOW_CARD_EFFECTS = ['weather', 'atomics', 'harvester', 'karamaAuction', 'karamaShipment', 'karamaBattleCancel', 'karamaHarkonnenSpecial', 'thumper', 'amal'] as const;
|
||||
export const WINDOW_CARD_EFFECTS = ['weather', 'atomics', 'harvester', 'karamaAuction', 'karamaShipment', 'karamaBattleCancel', 'karamaHarkonnenSpecial', 'karamaEmperorSpecial', 'thumper', 'amal'] as const;
|
||||
export type WindowCardEffect = typeof WINDOW_CARD_EFFECTS[number];
|
||||
export function windowCardNativeEffect(effect: WindowCardEffect): 'weather' | 'atomics' | 'harvester' | 'karama' | 'thumper' | 'amal' {
|
||||
return effect === 'karamaAuction' || effect === 'karamaShipment' || effect === 'karamaBattleCancel' || effect === 'karamaHarkonnenSpecial' ? 'karama' : effect;
|
||||
return effect === 'karamaAuction' || effect === 'karamaShipment' || effect === 'karamaBattleCancel' || effect === 'karamaHarkonnenSpecial' || effect === 'karamaEmperorSpecial' ? 'karama' : effect;
|
||||
}
|
||||
export type KaramaHarkonnenSpecialSource = { turn: number; owner: string };
|
||||
export type KaramaEmperorSpecialSource = { turn: number; owner: string };
|
||||
export type KaramaBattleCancelSource = {
|
||||
turn: number;
|
||||
battle: string;
|
||||
@@ -77,6 +78,16 @@ export function parseKaramaHarkonnenSpecialSource(source: unknown): KaramaHarkon
|
||||
return { turn: tuple[1], owner: tuple[2] };
|
||||
}
|
||||
|
||||
/** Decode the public owner and turn even after the special power is spent. */
|
||||
export function parseKaramaEmperorSpecialSource(source: unknown): KaramaEmperorSpecialSource | null {
|
||||
if (!identifier(source)) return null;
|
||||
let tuple: unknown;
|
||||
try { tuple = JSON.parse(source); } catch { return null; }
|
||||
if (!Array.isArray(tuple) || tuple.length !== 3 || tuple[0] !== 'karamaEmperorSpecial' ||
|
||||
!whole(tuple[1]) || tuple[1] < 1 || !identifier(tuple[2]) || JSON.stringify(tuple) !== source) return null;
|
||||
return { turn: tuple[1], owner: tuple[2] };
|
||||
}
|
||||
|
||||
/** Source decoding remains available after the actual grant closes its window. */
|
||||
export function parseKaramaShipmentSource(source: unknown): KaramaShipmentSource | null {
|
||||
if (!identifier(source)) return null;
|
||||
@@ -180,6 +191,17 @@ function globalWindowCardOpportunity(game: WindowCardGame, effect: WindowCardEff
|
||||
if (owners.length !== 1 || owners[0].specialKaramaUsed === true) return null;
|
||||
return { effect, turn: game.turn, source: JSON.stringify([effect, game.turn, owners[0].id]) };
|
||||
}
|
||||
if (effect === 'karamaEmperorSpecial') {
|
||||
const players = game.players;
|
||||
if (game.advanced !== true || game.phase !== 4 || !Array.isArray(players) || !players.length ||
|
||||
!players.every(player => object(player) && identifier(player.id) &&
|
||||
typeof player.faction === 'string' && (player.specialKaramaUsed === undefined ||
|
||||
typeof player.specialKaramaUsed === 'boolean')) ||
|
||||
new Set(players.map(player => player.id)).size !== players.length) return null;
|
||||
const owners = players.filter(player => player.faction === 'emperor');
|
||||
if (owners.length !== 1 || owners[0].specialKaramaUsed === true) return null;
|
||||
return { effect, turn: game.turn, source: JSON.stringify([effect, game.turn, owners[0].id]) };
|
||||
}
|
||||
if (effect === 'karamaBattleCancel') {
|
||||
const battle = game.battle, response = game.response, players = game.players;
|
||||
if (game.advanced !== false || game.phase !== 6 || !battle || !identifier(battle.event) ||
|
||||
|
||||
Reference in new issue
Block a user