Add campfireSmith and getUpgradableCards with tests

This commit is contained in:
Jared Miller 2026-02-25 10:33:30 -05:00
parent 91d32a71ee
commit 51dce7eba1
Signed by: shmup
GPG key ID: 22B5C6D66A38B06C
2 changed files with 77 additions and 1 deletions

View file

@ -1,4 +1,4 @@
import { getAllCards, getStarterDeck } from "./cards.js";
import { getAllCards, getCard, getStarterDeck } from "./cards.js";
import { createMap } from "./map.js";
import { shuffle } from "./state.js";
@ -27,6 +27,29 @@ export function campfireRest(run) {
return { ...run, hp: Math.min(run.hp + 3, run.maxHp) };
}
export function campfireSmith(run, cardId) {
const card = getCard(cardId);
if (!card?.upgraded) return run;
const idx = run.deck.indexOf(cardId);
if (idx === -1) return run;
const deck = [...run.deck];
deck[idx] = card.upgraded;
return { ...run, deck };
}
export function getUpgradableCards(run) {
const seen = new Set();
const result = [];
for (const id of run.deck) {
if (seen.has(id)) continue;
seen.add(id);
if (id.endsWith("+")) continue;
const card = getCard(id);
if (card?.upgraded) result.push(id);
}
return result;
}
export function revealRewards(run) {
const count = Math.min(3, run.cardRewardsDeck.length);
const revealed = run.cardRewardsDeck.slice(0, count);

View file

@ -3,8 +3,10 @@ import { getAllCards, initCards } from "./cards.js";
import { initEnemies } from "./enemies.js";
import {
campfireRest,
campfireSmith,
createRunState,
endCombat,
getUpgradableCards,
pickReward,
revealRewards,
skipRewards,
@ -104,6 +106,57 @@ describe("campfireRest", () => {
});
});
describe("campfireSmith", () => {
test("replaces first occurrence of base card with upgraded version", () => {
const run = { deck: ["strike_r", "strike_r", "defend_r"] };
const result = campfireSmith(run, "strike_r");
expect(result.deck).toEqual(["strike_r+", "strike_r", "defend_r"]);
});
test("does nothing if card not in deck", () => {
const run = { deck: ["defend_r", "bash"] };
const result = campfireSmith(run, "strike_r");
expect(result.deck).toEqual(["defend_r", "bash"]);
});
test("does nothing if card has no upgrade", () => {
const run = { deck: ["bash+", "strike_r"] };
const result = campfireSmith(run, "bash+");
expect(result.deck).toEqual(["bash+", "strike_r"]);
});
test("smiths strike_r from full ironclad starter deck", () => {
const run = createRunState("ironclad");
const originalCount = run.deck.filter((id) => id === "strike_r").length;
const result = campfireSmith(run, "strike_r");
expect(result.deck).toContain("strike_r+");
expect(result.deck.filter((id) => id === "strike_r")).toHaveLength(
originalCount - 1,
);
expect(result.deck).toHaveLength(run.deck.length);
});
});
describe("getUpgradableCards", () => {
test("returns unique base cards that have upgrades", () => {
const run = { deck: ["strike_r", "strike_r", "bash", "defend_r"] };
const result = getUpgradableCards(run);
expect(result).toContain("strike_r");
expect(result).toContain("bash");
expect(result).toContain("defend_r");
// duplicates deduplicated
expect(result.filter((id) => id === "strike_r")).toHaveLength(1);
});
test("excludes already-upgraded cards", () => {
const run = { deck: ["strike_r+", "bash+", "defend_r"] };
const result = getUpgradableCards(run);
expect(result).not.toContain("strike_r+");
expect(result).not.toContain("bash+");
expect(result).toContain("defend_r");
});
});
describe("rewards", () => {
test("revealRewards removes 3 from rewards deck and returns them", () => {
const run = createRunState("ironclad");