diff --git a/packages/engine/src/game.ts b/packages/engine/src/game.ts index 945d2f9..ffa96d8 100644 --- a/packages/engine/src/game.ts +++ b/packages/engine/src/game.ts @@ -4523,8 +4523,9 @@ function doCast(prev: GameState, cmd: Extract): Comma if (!isWand) return null; let charges = st.wandCharges[inHand.instanceId]; if (charges === undefined) { - if (mods.numbers.length === 0) return "a wand's first use needs a number card to set its charges"; - charges = mods.magnitude.power; // AMPLIFY and ADD both work here + // "ANY CARD MAY BE PLAYED WITHOUT A NUMBER CARD, but its power is + // only 1" — a bare first use lights a single charge. + charges = mods.magnitude.power; // 1 without a number; AMPLIFY and ADD work here st.wandCharges[inHand.instanceId] = charges; if (!wielder.displayed.includes(inHand.instanceId)) wielder.displayed.push(inHand.instanceId); events.push({ type: "wandCharged", player: wielder.id, card: inHand, charges }); diff --git a/packages/engine/test/wands.test.ts b/packages/engine/test/wands.test.ts index 193bc0b..af1563f 100644 --- a/packages/engine/test/wands.test.ts +++ b/packages/engine/test/wands.test.ts @@ -12,11 +12,6 @@ describe("magic wands", () => { const wand = giveCard(state, attacker, "blaster-wand"); giveCard(state, attacker, "number-2", "N", 1); - // First use without a number card is refused. - expect(applyCommand(state, attacker, { - type: "cast", instanceId: wand.instanceId, target: { kind: "player", playerId: defender }, - }).ok).toBe(false); - // Charged with a 2: fires (3 damage), one charge left, wand displayed. state = must(state, attacker, { type: "cast", instanceId: wand.instanceId, numberInstanceIds: ["number-2#N"], @@ -210,3 +205,20 @@ describe("dropping objects", () => { expect(refused.ok).toBe(false); }); }); + +describe("a bare wand lights a single charge", () => { + it("'played without a number card, its power is only 1': one shot, then dust", () => { + let { state } = newGame(); + state = toRound2(state); + const { attacker, defender } = faceOff(state); + const bw = giveCard(state, attacker, "blaster-wand"); + state = must(state, attacker, { + type: "cast", instanceId: bw.instanceId, target: { kind: "player", playerId: defender }, + }); + state = must(state, defender, { type: "pass" }); + // The single charge fired (3 flat damage) and the wand crumbled. + expect(state.players.find((p) => p.id === defender)!.life).toBe(12); + expect(state.players.find((p) => p.id === attacker)!.hand.some((c) => c.cardId === "blaster-wand")).toBe(false); + expect(state.wandCharges[bw.instanceId]).toBeUndefined(); + }); +}); diff --git a/packages/web/src/App.svelte b/packages/web/src/App.svelte index 7884924..53b854a 100644 --- a/packages/web/src/App.svelte +++ b/packages/web/src/App.svelte @@ -1818,7 +1818,7 @@ — {EDGE_HINTS[selectedCard.cardId] ?? "click a wall line"} {/if} {#if selectedCard && WAND_IDS.has(selectedCard.cardId) && view.wandCharges[selectedCard.instanceId] == null && !attachedNumber} - — first use: tap a NUMBER card to set the wand's charges, then click a target + — first use sets the charges: tap a NUMBER card first, or cast bare for a single charge {:else if selectedDef.cardType === "attack" && !cellSelectMode && !EDGE_CARDS.has(selectedCard?.cardId ?? "")} — click a target, or a wall line to batter it{attachedNumber ? ` (powered by a ${numberTotal})` : ""} {/if}