36 lines
1.8 KiB
TypeScript
36 lines
1.8 KiB
TypeScript
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { isLegalAction, resolveTurn } from '../src/shared/rules.js';
|
|
|
|
const actions = ['charge', 'blast', 'guard', 'beam', 'dodge'] as const;
|
|
const winners = [
|
|
[null, 1, null, 1, null],
|
|
[0, null, null, 1, null],
|
|
[null, null, null, 1, null],
|
|
[0, 0, 0, null, null],
|
|
[null, null, null, null, null],
|
|
];
|
|
for (let a = 0; a < 5; a++) for (let b = 0; b < 5; b++) {
|
|
test(`${actions[a]} / ${actions[b]} follows the agreed outcome table`, () => {
|
|
const result = resolveTurn([3, 3], [actions[a], actions[b]]) as { winnerIndex: number | null };
|
|
assert.equal(result.winnerIndex, winners[a][b]);
|
|
});
|
|
}
|
|
test('first turn allows only charge and guard; unknown actions are rejected', () => {
|
|
assert.equal(isLegalAction('charge', 0), true);
|
|
assert.equal(isLegalAction('guard', 0), true);
|
|
for (const action of ['blast', 'beam', 'dodge', 'fake']) assert.equal(isLegalAction(action, 0), false);
|
|
});
|
|
test('energy is spent on evasion and clashing attacks, and a hit cancels charging', () => {
|
|
assert.deepEqual(resolveTurn([3, 1], ['beam', 'dodge']), { energy: [0, 0], winnerIndex: null, hitIndex: null });
|
|
assert.deepEqual(resolveTurn([1, 0], ['blast', 'charge']), { energy: [0, 0], winnerIndex: 0, hitIndex: 1 });
|
|
assert.deepEqual(resolveTurn([1, 1], ['blast', 'blast']), { energy: [0, 0], winnerIndex: null, hitIndex: null });
|
|
assert.deepEqual(resolveTurn([0, 0], ['charge', 'charge']), { energy: [1, 1], winnerIndex: null, hitIndex: null });
|
|
assert.deepEqual(resolveTurn([0, 1], ['guard', 'dodge']), { energy: [0, 0], winnerIndex: null, hitIndex: null });
|
|
});
|
|
test('illegal actions cannot spend energy or mutate the input', () => {
|
|
const energy: [number, number] = [0, 0];
|
|
assert.throws(() => resolveTurn(energy, ['blast', 'charge']));
|
|
assert.deepEqual(energy, [0, 0]);
|
|
});
|