Files
Dune/tests/ecaz-revival-cohort.test.ts
T

99 lines
5.0 KiB
TypeScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { applyAction, createGame, newPlayer, viewGame } from '../game/engine';
import { createDukeVidal } from '../game/duke-vidal';
import { newRevivalRules } from '../game/revival';
import { baseDeck } from '../game/cards';
function boundary() {
const g = createGame('ECAZCOHORT', newPlayer('e', 'Ecaz', 'ecaz'), false, ['ecaz']);
g.players.push(newPlayer('m', 'Moritani', 'moritani'));
Object.assign(g, { status: 'playing', phase: 4, turn: 3, order: ['e', 'm'],
dukeVidal: createDukeVidal(), revivalRules: newRevivalRules() });
g.players[0].spice = 20;
return g;
}
function dealGhola(g: ReturnType<typeof boundary>) {
g.deck = baseDeck();
const index = g.deck.findIndex(card => card.effect === 'ghola');
assert.ok(index >= 0);
const [card] = g.deck.splice(index, 1);
g.players[0].hand.push(card);
return card;
}
void test('an Ecaz repeat death does not suppress other native first-cohort returns', () => {
const g = boundary();
const owner = g.players[0];
owner.spice = 20;
owner.revivalCycle = 1;
for (const leader of owner.leaders) { leader.dead = true; leader.deaths = 1; }
owner.leaders[0].deaths = 2;
const options = viewGame(g, owner.id).revival.leaders;
assert.deepEqual(options.map(l => l.id).sort(), owner.leaders.slice(1).map(l => l.id).sort());
const selected = owner.leaders[1];
const after = applyAction(g, owner.id, { type: 'reviveLeader', leader: selected.id });
assert.equal(after.players[0].leaders.find(l => l.id === selected.id)!.dead, false);
assert.equal(after.players[0].leaders[0].dead, true);
assert.equal(after.players[0].spice, owner.spice - selected.strength);
assert.equal(after.players[0].leaderRevived, true);
assert.equal(after.players[0].leaders.length, 5);
assert.equal(after.dukeVidal!.leader.dead, false);
});
void test('a late first death joins an open later cohort without matching its generation number', () => {
const g = boundary(), owner = g.players[0];
owner.revivalCycle = 3;
owner.ecazRevivalCohort = { cycle: 3, returned: owner.leaders.slice(0, 4).map(l => l.id) };
for (const leader of owner.leaders.slice(0, 4)) { leader.dead = true; leader.deaths = 4; }
const late = owner.leaders[4];
late.dead = true;
late.deaths = 1;
const options = viewGame(g, owner.id).revival.leaders;
assert.deepEqual(options.map(l => l.id), [late.id]);
const after = applyAction(g, owner.id, { type: 'reviveLeader', leader: late.id });
assert.equal(after.players[0].leaders.find(l => l.id === late.id)!.dead, false);
assert.equal(after.players[0].spice, owner.spice - late.strength);
assert.equal(after.players[0].leaders.filter(l => l.dead).length, 4);
});
void test('an actual native Ghola return spends no ordinary slot but cannot re-enter the same cohort after dying again', () => {
const g = boundary(), owner = g.players[0];
for (const leader of owner.leaders) { leader.dead = true; leader.deaths = 1; }
const card = dealGhola(g), first = owner.leaders[0];
const returned = applyAction(g, owner.id, { type: 'card', card: card.id, leader: first.id });
assert.equal(returned.players[0].spice, owner.spice);
assert.equal(returned.players[0].leaderRevived, false);
const repeated = returned.players[0].leaders[0];
repeated.dead = true;
repeated.deaths++;
const next = viewGame(returned, owner.id).revival.leaders;
assert.deepEqual(next.map(l => l.id).sort(), owner.leaders.slice(1).map(l => l.id).sort());
const second = owner.leaders[1];
const after = applyAction(returned, owner.id, { type: 'reviveLeader', leader: second.id });
assert.equal(after.players[0].leaders.find(l => l.id === second.id)!.dead, false);
assert.equal(after.players[0].leaders[0].dead, true);
assert.equal(after.players[0].spice, owner.spice - second.strength);
});
void test('an independent Duke Ghola preserves a real five-Tanks opening without aligning its repeated deaths', () => {
const g = boundary(), owner = g.players[0];
for (const leader of owner.leaders.slice(0, 4)) { leader.dead = true; leader.deaths = 1; }
g.dukeVidal!.leader.dead = true;
g.dukeVidal!.leader.deaths = 7;
const card = dealGhola(g);
const returned = applyAction(g, owner.id, { type: 'card', card: card.id, leader: g.dukeVidal!.leader.id });
assert.equal(returned.dukeVidal!.leader.dead, false);
assert.equal(returned.dukeVidal!.leader.deaths, 7);
assert.equal(returned.dukeVidal!.controller, null);
assert.equal(returned.players[0].leaderRevived, false);
assert.equal(returned.players[0].spice, owner.spice);
const options = viewGame(returned, owner.id).revival.leaders;
assert.deepEqual(options.map(l => l.id).sort(), owner.leaders.slice(0, 4).map(l => l.id).sort());
const native = owner.leaders[0];
const after = applyAction(returned, owner.id, { type: 'reviveLeader', leader: native.id });
assert.equal(after.players[0].leaders[0].dead, false);
assert.equal(after.players[0].spice, owner.spice - native.strength);
assert.equal(after.dukeVidal!.leader.deaths, 7);
});