75 lines
2.9 KiB
TypeScript
75 lines
2.9 KiB
TypeScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { applyAction, viewGame } from '../game/engine';
|
|
import { botActions } from '../game/bots';
|
|
import {
|
|
choamPowerAction,
|
|
choamPowerBotPlay,
|
|
choamPowerPlays,
|
|
} from '../game/choam-power-options';
|
|
import {
|
|
NEXUS_CHOAM_EFFECTS,
|
|
nexusChoamFixture,
|
|
nexusChoamInventory,
|
|
holdNexusChoamCard,
|
|
} from './fixture-nexus-choam';
|
|
|
|
void test('all four CHOAM profiles use projected Cunning fuel at existing effect timing and preserve the Easy revival policy', () => {
|
|
for (const effect of NEXUS_CHOAM_EFFECTS)
|
|
for (const profile of ['Easy', 'Medium', 'Hard', 'Brutal'] as const) {
|
|
const f = nexusChoamFixture(effect);
|
|
const view = viewGame(f.g, f.owner);
|
|
view.players.find((player) => player.id === f.owner)!.bot = profile;
|
|
const before = structuredClone(view);
|
|
const action = botActions(view)[0];
|
|
assert.ok(action, `${profile}/${effect}`);
|
|
if (effect === 'laLaLa' && profile === 'Easy')
|
|
assert.deepEqual(action, { type: 'decision', decline: true });
|
|
else {
|
|
assert.equal(
|
|
action.nexus,
|
|
choamPowerPlays(view, effect).find(
|
|
(play) => play.card.id === f.cost.id && play.source === 'nexus',
|
|
)!.event,
|
|
);
|
|
assert.equal(action.card, f.cost.id);
|
|
assert.equal(action.effect, effect);
|
|
}
|
|
const result = applyAction(f.g, f.owner, action);
|
|
nexusChoamInventory(result);
|
|
assert.deepEqual(view, before);
|
|
}
|
|
});
|
|
|
|
void test('CHOAM fuel ranking favors printed powers then low-value private costs and never consumes blocked cards', () => {
|
|
const f = nexusChoamFixture('kulon');
|
|
const fuel = holdNexusChoamCard(f.g, f.owner, 'Baliset');
|
|
const value = (card: { id: string }) => (card.id === fuel.id ? 0 : 10);
|
|
const view = viewGame(f.g, f.owner);
|
|
const selected = choamPowerBotPlay(view, 'kulon', value)!;
|
|
assert.equal(selected.source, 'nexus');
|
|
assert.equal(selected.card.id, fuel.id);
|
|
for (const p of view.players.filter((player) => player.id !== f.owner))
|
|
for (const key of ['hand', 'spice', 'traitors'])
|
|
Object.defineProperty(p, key, {
|
|
get() {
|
|
throw new Error('Private opponent field read');
|
|
},
|
|
});
|
|
assert.equal(choamPowerBotPlay(view, 'kulon', value)!.card.id, fuel.id);
|
|
for (const play of view.choamWorthless!.plays)
|
|
if (play.card.id === fuel.id) play.blocked = 'Reserved';
|
|
assert.equal(choamPowerBotPlay(view, 'kulon', value)!.card.id, f.cost.id);
|
|
assert.equal(choamPowerAction(view, selected), null);
|
|
const printed = holdNexusChoamCard(f.g, f.owner, 'Kulon');
|
|
const regular = choamPowerBotPlay(viewGame(f.g, f.owner), 'kulon', (card) =>
|
|
card.id === printed.id ? 100 : 0,
|
|
)!;
|
|
assert.equal(regular.source, 'printed');
|
|
assert.deepEqual(choamPowerAction(viewGame(f.g, f.owner), regular), {
|
|
type: 'card',
|
|
mode: 'choam',
|
|
card: printed.id,
|
|
});
|
|
});
|