Files
Dune/tests/stronghold-battle.test.ts
T
2026-09-08 07:37:52 +10:00

145 lines
3.9 KiB
TypeScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { baseDeck, ixBattleCards, type Card } from '../game/cards';
import { richeseCards } from '../game/richese-cards';
import {
strongholdSnooper,
strongholdBattleEffects,
} from '../game/stronghold-battle';
import { battleCardEffects, battleWeaponsExplode } from '../game/battle-cards';
const cards = [...baseDeck(), ...ixBattleCards(), ...richeseCards()];
const get = (kind: Card['kind']) => cards.find((c) => c.kind === kind)!;
const portable = cards.find((c) => c.effect === 'portableSnooper')!;
void test('Carthag uses the actual poison/projectile roles and requires a real non-poison defense', () => {
const eligible = [get('shield'), get('weirdingWay')];
const ineligible = [
undefined,
get('worthless'),
get('snooper'),
get('shieldSnooper'),
get('chemistry'),
portable,
];
for (const weapon of [
undefined,
get('projectile'),
get('weirdingWay'),
get('worthless'),
get('artillery'),
]) {
for (const defense of eligible)
assert.equal(strongholdSnooper('carthag', weapon, defense), true);
for (const defense of ineligible)
assert.equal(strongholdSnooper('carthag', weapon, defense), false);
}
for (const weapon of [
get('poison'),
get('chemistry'),
get('poisonBlade'),
get('poisonTooth'),
])
for (const defense of [...eligible, ...ineligible])
assert.equal(strongholdSnooper('carthag', weapon, defense), false);
for (const effect of [null, 'arrakeen', 'habbanya_ridge_sietch'] as const)
assert.equal(strongholdSnooper(effect, undefined, get('shield')), false);
});
void test('Carthag augments either combatant without replacing Shield, Tooth or Artillery behavior', () => {
for (const [kind, dead] of [
['poison', false],
['poisonBlade', false],
['projectile', false],
['poisonTooth', true],
['artillery', false],
['lasgun', true],
] as const) {
const weapon = get(kind),
shield = get('shield');
const left = strongholdBattleEffects(
undefined,
shield,
weapon,
undefined,
true,
true,
'carthag',
null,
);
const right = strongholdBattleEffects(
weapon,
undefined,
undefined,
shield,
true,
true,
null,
'carthag',
);
assert.equal(left.attackerDead, dead, kind);
assert.equal(right.defenderDead, dead, kind);
assert.equal(left.stunned, right.stunned);
}
assert.equal(
battleWeaponsExplode(undefined, get('shield'), get('lasgun'), undefined),
true,
);
const both = strongholdBattleEffects(
get('artillery'),
get('shield'),
get('poison'),
undefined,
true,
true,
'carthag',
null,
);
assert.equal(both.attackerDead, false);
assert.equal(both.defenderDead, true);
assert.equal(both.stunned, true);
const tooth = strongholdBattleEffects(
undefined,
get('shield'),
get('poisonTooth'),
undefined,
true,
false,
'carthag',
null,
);
assert.equal(tooth.attackerDead, false);
});
void test('disabled module composition preserves ordinary results and does not mutate physical card records', () => {
const before = structuredClone(cards);
for (const weapon of [
undefined,
get('poison'),
get('projectile'),
get('chemistry'),
get('poisonTooth'),
get('artillery'),
])
for (const defense of [
undefined,
get('shield'),
get('snooper'),
get('shieldSnooper'),
get('chemistry'),
portable,
]) {
assert.deepEqual(
strongholdBattleEffects(weapon, defense, undefined, get('shield')),
battleCardEffects(weapon, defense, undefined, get('shield')),
);
strongholdBattleEffects(
weapon,
defense,
get('poison'),
get('shield'),
true,
true,
'carthag',
null,
);
}
assert.deepEqual(cards, before);
});