Announce leaderless native Basic battles before plans
Verify and publish checkpoint container / container (push) Successful in 10m14s
Verify and publish checkpoint container / container (push) Successful in 10m14s
This commit is contained in:
1 parent
00e01a7cd2
commit
f73a6e0a9c
9 files changed
+481
-21
No files matched your search
@@ -0,0 +1,73 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import { applyAction, viewGame, type Game } from '../game/engine';
|
||||
import { advanceNativeLeaderless, basicNativeLeaderlessFixture, nativeLeaderlessClean,
|
||||
nativeLeaderlessPlayer as player } from './fixture-basic-native-early-leaderless';
|
||||
import { advanceBasicSemutaAmbassador, basicSemutaAmbassadorInventory } from './fixture-basic-semuta-ambassador';
|
||||
|
||||
const announce = (game: Game, id: string) => game.log.filter(entry =>
|
||||
entry.text === `${player(game, id).name} has no available leader or Cheap Hero for this battle.`);
|
||||
|
||||
/** Public setup, real movement and battle choice come from the native fixture.
|
||||
* The tests stage only prior leader use/death and conserved physical cards. */
|
||||
void test('Basic Richese keeps its shared preparation when a battle leader is dead', () => {
|
||||
const fixture = basicNativeLeaderlessFixture('richese', {dead: true, ghola: true});
|
||||
let game = advanceNativeLeaderless(fixture.game, state => !!state.battle && nativeLeaderlessClean(state) &&
|
||||
!state.battle.preparation && !!state.battle.preLeader && !state.battle.preLeader.closed);
|
||||
const battle = game.battle!;
|
||||
assert.equal(battle.basicEarlyLeaderlessVersion, 1);
|
||||
assert.equal(battle.basicDeadLeaderPreparation, true);
|
||||
assert.deepEqual(battle.preLeader!.ready, [], 'Richese Sapho preparation keeps both combatants involved');
|
||||
assert.equal(announce(game, 'richese').length, 0);
|
||||
const event = battle.preLeader!.event;
|
||||
game = applyAction(game, 'richese', {type:'battlePreparationReady', event});
|
||||
assert.equal(game.battle!.preLeader!.closed, false);
|
||||
assert.equal(announce(game, 'richese').length, 0);
|
||||
game = applyAction(game, 'guild', {type:'battlePreparationReady', event});
|
||||
assert.equal(game.battle!.preLeader!.closed, true);
|
||||
assert.equal(announce(game, 'richese').length, 1);
|
||||
const richese = player(game, 'richese'), ghola = richese.hand.find(card => card.effect === 'ghola');
|
||||
const leader = richese.leaders.find(item => item.dead); assert.ok(ghola && leader);
|
||||
game = applyAction(game, 'richese', {type:'card', card:ghola.id, leader:leader.id});
|
||||
game = advanceBasicSemutaAmbassador(game, state => !!state.battle && nativeLeaderlessClean(state));
|
||||
assert.equal(player(game, 'richese').leaders.find(item => item.id === leader.id)!.dead, false);
|
||||
assert.ok(!(viewGame(game, 'guild').battle!.earlyLeaderless ?? []).includes('richese'));
|
||||
});
|
||||
|
||||
void test('Basic Distrans receipt of a Cheap Hero corrects an unsealed early announcement', () => {
|
||||
const fixture = basicNativeLeaderlessFixture('richese');
|
||||
let game = structuredClone(fixture.beforeBattle);
|
||||
const recipient = player(game, 'guild'), donor = player(game, 'emperor');
|
||||
for (const leader of recipient.leaders) {
|
||||
assert.ok(!leader.dead && !leader.capturedBy);
|
||||
leader.usedAt = fixture.territory === 'carthag' ? 'arrakeen' : 'carthag';
|
||||
}
|
||||
// Keep the recipient below its hand limit with no existing Hero, then move
|
||||
// the original Distrans and Hero into the donor's hand without creating a card.
|
||||
for (let i = recipient.hand.length - 1; i >= 0; i--)
|
||||
if (recipient.hand[i].kind === 'hero' || recipient.hand.length >= 4)
|
||||
game.deck.push(...recipient.hand.splice(i, 1));
|
||||
while (donor.hand.length > 2) game.deck.push(donor.hand.pop()!);
|
||||
const distransIndex = game.richeseCache!.findIndex(card => card.effect === 'distrans');
|
||||
assert.ok(distransIndex >= 0);
|
||||
const distrans = game.richeseCache!.splice(distransIndex, 1)[0];
|
||||
const heroIndex = game.deck.findIndex(card => card.kind === 'hero'); assert.ok(heroIndex >= 0);
|
||||
const hero = game.deck.splice(heroIndex, 1)[0];
|
||||
donor.hand.push(distrans, hero);
|
||||
const inventory = basicSemutaAmbassadorInventory(game);
|
||||
game = applyAction(game, fixture.chooser, fixture.choose);
|
||||
game = advanceNativeLeaderless(game, state => !!state.battle && nativeLeaderlessClean(state) &&
|
||||
!state.battle.preparation && (!state.battle.preLeader || state.battle.preLeader.closed));
|
||||
assert.ok(viewGame(game, 'richese').battle!.earlyLeaderless?.includes('guild'));
|
||||
assert.equal(announce(game, 'guild').length, 1);
|
||||
assert.equal(viewGame(game, 'emperor').distrans?.blocked, null);
|
||||
game = applyAction(game, 'emperor', {type:'card', card:distrans.id, target:'guild', give:hero.id});
|
||||
game = advanceBasicSemutaAmbassador(game, state => !!state.battle && nativeLeaderlessClean(state));
|
||||
assert.ok(player(game, 'guild').hand.some(card => card.id === hero.id));
|
||||
assert.ok(!(viewGame(game, 'richese').battle!.earlyLeaderless ?? []).includes('guild'));
|
||||
assert.equal(game.log.filter(entry => entry.text ===
|
||||
`${player(game, 'guild').name} now has an available Cheap Hero for this battle.`).length, 1);
|
||||
assert.deepEqual(basicSemutaAmbassadorInventory(game), inventory);
|
||||
game = applyAction(game, 'guild', {type:'battlePlan', leader:hero.id, dial:0, support:0, weapon:null, defense:null});
|
||||
assert.equal(game.battle!.plans.guild.leader, hero.id);
|
||||
});
|
||||
Reference in new issue
Block a user