startTurn resets energy/block for all players and draws 5 cards each, also resets playersReady. resolveEnemyTurn iterates all enemies, resets each enemy's block, and has each enemy act against player 0. checkCombatEnd checks all enemies (victory) and any player (defeat).
146 lines
4.9 KiB
JavaScript
146 lines
4.9 KiB
JavaScript
import { beforeAll, describe, expect, test } from "bun:test";
|
|
import { initCards } from "./cards.js";
|
|
import { checkCombatEnd, resolveEnemyTurn, startTurn } from "./combat.js";
|
|
import { initEnemies } from "./enemies.js";
|
|
import { createCombatState } from "./state.js";
|
|
|
|
beforeAll(async () => {
|
|
await Promise.all([initCards(), initEnemies()]);
|
|
});
|
|
|
|
describe("startTurn", () => {
|
|
test("resets energy and block, draws 5 cards", () => {
|
|
let state = createCombatState("ironclad", "jaw_worm");
|
|
state = {
|
|
...state,
|
|
player: { ...state.player, energy: 0, block: 5 },
|
|
};
|
|
const next = startTurn(state);
|
|
expect(next.player.energy).toBe(3);
|
|
expect(next.player.block).toBe(0);
|
|
expect(next.player.hand).toHaveLength(5);
|
|
expect(next.combat.dieResult).toBeGreaterThanOrEqual(1);
|
|
expect(next.combat.dieResult).toBeLessThanOrEqual(6);
|
|
});
|
|
});
|
|
|
|
describe("resolveEnemyTurn", () => {
|
|
test("enemy attacks reduce player hp or block", () => {
|
|
let state = createCombatState("ironclad", "jaw_worm");
|
|
state = { ...state, combat: { ...state.combat, dieResult: 1 } };
|
|
const next = resolveEnemyTurn(state);
|
|
expect(next.combat.phase).toBe("player_turn");
|
|
expect(next.combat.turn).toBe(state.combat.turn + 1);
|
|
});
|
|
|
|
test("enemy block resets before acting", () => {
|
|
let state = createCombatState("ironclad", "jaw_worm");
|
|
state = {
|
|
...state,
|
|
enemy: { ...state.enemy, block: 5 },
|
|
combat: { ...state.combat, dieResult: 1 },
|
|
};
|
|
const next = resolveEnemyTurn(state);
|
|
// die result 1 maps to a defend action (3 hit + 1 block), block resets then regains 1
|
|
expect(next.enemy.block).toBe(1);
|
|
});
|
|
});
|
|
|
|
describe("checkCombatEnd", () => {
|
|
test("returns 'victory' when enemy hp is 0", () => {
|
|
let state = createCombatState("ironclad", "jaw_worm");
|
|
const deadEnemy = { ...state.enemies[0], hp: 0 };
|
|
state = { ...state, enemy: deadEnemy, enemies: [deadEnemy] };
|
|
expect(checkCombatEnd(state)).toBe("victory");
|
|
});
|
|
|
|
test("returns 'defeat' when player hp is 0", () => {
|
|
let state = createCombatState("ironclad", "jaw_worm");
|
|
const deadPlayer = { ...state.players[0], hp: 0 };
|
|
state = { ...state, player: deadPlayer, players: [deadPlayer] };
|
|
expect(checkCombatEnd(state)).toBe("defeat");
|
|
});
|
|
|
|
test("returns null when combat continues", () => {
|
|
const state = createCombatState("ironclad", "jaw_worm");
|
|
expect(checkCombatEnd(state)).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe("startTurn - multiplayer", () => {
|
|
test("resets energy and block for all players, draws 5 each", () => {
|
|
let state = createCombatState(["ironclad", "ironclad"], ["jaw_worm"]);
|
|
state = {
|
|
...state,
|
|
players: state.players.map((p) => ({ ...p, energy: 0, block: 5 })),
|
|
};
|
|
const next = startTurn(state);
|
|
expect(next.players[0].energy).toBe(3);
|
|
expect(next.players[0].block).toBe(0);
|
|
expect(next.players[0].hand).toHaveLength(5);
|
|
expect(next.players[1].energy).toBe(3);
|
|
expect(next.players[1].block).toBe(0);
|
|
expect(next.players[1].hand).toHaveLength(5);
|
|
});
|
|
|
|
test("playersReady resets on startTurn", () => {
|
|
let state = createCombatState(["ironclad", "ironclad"], ["jaw_worm"]);
|
|
state = {
|
|
...state,
|
|
combat: { ...state.combat, playersReady: [0, 1] },
|
|
};
|
|
const next = startTurn(state);
|
|
expect(next.combat.playersReady).toEqual([]);
|
|
});
|
|
});
|
|
|
|
describe("resolveEnemyTurn - multiplayer", () => {
|
|
test("all enemies act, block resets for each", () => {
|
|
let state = createCombatState(["ironclad"], ["jaw_worm", "jaw_worm"]);
|
|
state = {
|
|
...state,
|
|
enemies: state.enemies.map((e) => ({ ...e, block: 3 })),
|
|
combat: { ...state.combat, dieResult: 1 },
|
|
};
|
|
const next = resolveEnemyTurn(state);
|
|
// die result 1 is defend (3 hit + 1 block), so block resets then gains 1
|
|
expect(next.enemies[0].block).toBe(1);
|
|
expect(next.enemies[1].block).toBe(1);
|
|
expect(next.combat.turn).toBe(state.combat.turn + 1);
|
|
});
|
|
});
|
|
|
|
describe("checkCombatEnd - multiplayer", () => {
|
|
test("victory when all enemies at 0 hp", () => {
|
|
let state = createCombatState(["ironclad"], ["jaw_worm", "jaw_worm"]);
|
|
state = {
|
|
...state,
|
|
enemies: state.enemies.map((e) => ({ ...e, hp: 0 })),
|
|
};
|
|
expect(checkCombatEnd(state)).toBe("victory");
|
|
});
|
|
|
|
test("no victory if only one enemy at 0 hp", () => {
|
|
let state = createCombatState(["ironclad"], ["jaw_worm", "jaw_worm"]);
|
|
state = {
|
|
...state,
|
|
enemies: [
|
|
{ ...state.enemies[0], hp: 0 },
|
|
{ ...state.enemies[1], hp: 5 },
|
|
],
|
|
};
|
|
expect(checkCombatEnd(state)).toBeNull();
|
|
});
|
|
|
|
test("defeat when any player at 0 hp", () => {
|
|
let state = createCombatState(["ironclad", "ironclad"], ["jaw_worm"]);
|
|
state = {
|
|
...state,
|
|
players: [
|
|
{ ...state.players[0], hp: 0 },
|
|
{ ...state.players[1], hp: 11 },
|
|
],
|
|
};
|
|
expect(checkCombatEnd(state)).toBe("defeat");
|
|
});
|
|
});
|