The reveal remembers the hand a wizard fell holding

Elimination destroys the evidence: a killed wizard's cards pass to
the killer, a treasure-lost wizard's go to the discard — so the
post-game reveal showed "empty-handed" for exactly the player whose
hand everyone wants to see. Both elimination paths now snapshot the
hand at the moment of death (finalHand), the finished view serves it,
and the gallery marks those rows "as they fell" in script. Because
rooms replay from the command log, already-finished games show their
fallen hands too. Test kills a wizard holding a Fireball and a 6 and
finds them in the reveal.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Eric Wagoner
2026-08-16 11:20:10 -04:00
co-authored by Claude Fable 5
parent e7b17f7643
commit da4ab03135
4 changed files with 31 additions and 1 deletions
+23
View File
@@ -315,3 +315,26 @@ describe("speedstone", () => {
expect(state.turn.movementAllowance).toBe(4);
});
});
describe("the post-game reveal", () => {
it("shows an eliminated player's hand as they fell, not their emptied one", async () => {
const { viewFor } = await import("../src/view");
let { state } = newGame();
state = toRound2(state);
const attacker = activePlayer(state);
const defender = state.players.find((p) => p.id !== attacker.id)!;
defender.position = { ...attacker.position };
defender.life = 1;
defender.hand = [
{ instanceId: "fireball#J", cardId: "fireball" },
{ instanceId: "number-6#J", cardId: "number-6" },
];
state = must(state, attacker.id, { type: "punch", targetId: defender.id });
state = must(state, defender.id, { type: "pass" });
expect(state.phase).toBe("finished");
// The killer took the cards — but the reveal remembers the fallen hand.
const view = viewFor(state, attacker.id);
const fallen = view.revealedHands?.[defender.id] ?? [];
expect(fallen.map((c) => c.cardId).sort()).toEqual(["fireball", "number-6"]);
});
});