Rev 13: monsters roll to hit the hidden — the invented exception dies

"The creature shares your square — there is nowhere to hide" appeared
on no card and in no rulebook. Neither did the convention beneath it:
the engine skipped INVISIBLE and SHRINK miss rolls for creature blows
on the theory that a monster in your square has nothing to aim. The
cards say otherwise — SHRINK reduces the chance to hit "in any
attack", and INVISIBLE's D4 carves out no exception for monsters.

From rev 13, creature blows roll the same dice as every other attack
(1 finds the unseen; 1-2 find the tiny), INVISIBLE may be counter-
cast against a creature's blow, and the automatons will do so. The
rolls consume RNG, so earlier games keep their certainty and replay
without them — the refusal survives only there, reworded to blame the
revision instead of inventing a rule.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Eric Wagoner
2026-08-16 21:11:30 -04:00
co-authored by Claude Fable 5
parent 4d8584ae44
commit e0da97627b
5 changed files with 57 additions and 8 deletions
+9 -5
View File
@@ -4644,7 +4644,9 @@ function doCounteract(
// The spell truly goes up — duration from an attached NUMBER card — and
// the attacker's 1-in-4 hit roll happens at resolution.
if (card.cardId === "invisible") {
if (stack.creatureId) return err("the creature shares your square — there is nowhere to hide");
if (stack.creatureId && (state.config.deckRev ?? 1) < 13) {
return err("in this game's revision, creatures are not fooled by the vanishing");
}
let duration = 1;
const attached = (numberInstanceIds ?? [])
.map((id) => player.hand.find((c) => c.instanceId === id))
@@ -4810,9 +4812,11 @@ function resolveStack(state: GameState, events: GameEvent[]): void {
const effect = attackId ? (CARD_EFFECTS[attackId] as AttackEffect) : null;
// Hit rolls against INVISIBLE (attacker guesses a direction: 1-in-4) and
// SHRINK (50% miss). "If a spell misses, it dissipates harmlessly." A
// creature sharing the square has nothing to aim: no miss rolls.
if (!stack.creatureId && sustainedOn(state, defender.id, "invisible").length > 0) {
// SHRINK ("Reduces opponent's chance to hit you by 50% in any attack").
// Creature blows roll the same dice from rev 13 — the cards carve out no
// exception for monsters; earlier games skipped the rolls and replay so.
const missRolls = !stack.creatureId || (state.config.deckRev ?? 1) >= 13;
if (missRolls && sustainedOn(state, defender.id, "invisible").length > 0) {
const roll = rollD4(state, events, attacker.id, "aiming at the unseen — only a 1 finds them");
if (roll !== 1) {
events.push({ type: "attackMissed", attacker: attacker.id, defender: defender.id, attackCardId: attackId, because: "invisible" });
@@ -4820,7 +4824,7 @@ function resolveStack(state: GameState, events: GameEvent[]): void {
return;
}
}
if (!stack.creatureId && sustainedOn(state, defender.id, "shrink").length > 0) {
if (missRolls && sustainedOn(state, defender.id, "shrink").length > 0) {
const roll = rollD4(state, events, attacker.id, "aiming at the tiny — 1-2 hits");
if (roll > 2) {
events.push({ type: "attackMissed", attacker: attacker.id, defender: defender.id, attackCardId: attackId, because: "shrink" });