Fear measures as the card says: through walls, never diagonal, no warps
The FAQ is exact: 'The 3 spaces away is measured as a Wizard walks (if he could walk through walls), not diagonally' — manhattan, at every vintage. The walking-distance detour is reverted (no rev-32 ledger ever recorded under it); the rev-32 gains stand: monsters, warp-steps, and teleports all honor the dread. The aura returns to the true diamond, now as a wash on its member squares. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0138A8CjeQRpvzKxuMfz1Bqc
This commit is contained in:
co-authored by
Claude Fable 5
parent
724d178636
commit
fdb44ab09f
@@ -3726,16 +3726,11 @@ function fearRepels(state: GameState, moverId: PlayerId | null, from: Cell, to:
|
||||
for (const other of state.players) {
|
||||
if (!other.alive || other.id === moverId) continue;
|
||||
if (sustainedOn(state, other.id, "fear").length === 0) continue;
|
||||
// "Spaces" are counted through the maze — warps included, walls
|
||||
// respected — exactly as feet would walk them (rules rev 32). Earlier
|
||||
// games measured as the crow flies, and their ledgers replay so.
|
||||
const walked = (state.config.deckRev ?? 1) >= 32;
|
||||
const d = walked
|
||||
? walkingDistance(state, other.position, to)
|
||||
: Math.abs(other.position.x - to.x) + Math.abs(other.position.y - to.y);
|
||||
const dBefore = walked
|
||||
? walkingDistance(state, other.position, from)
|
||||
: Math.abs(other.position.x - from.x) + Math.abs(other.position.y - from.y);
|
||||
// FAQ: "The 3 spaces away is measured as a Wizard walks (if he could
|
||||
// walk through walls), not diagonally" — orthogonal steps, walls
|
||||
// ignored. Warps do not carry the dread; walls do not shield from it.
|
||||
const d = Math.abs(other.position.x - to.x) + Math.abs(other.position.y - to.y);
|
||||
const dBefore = Math.abs(other.position.x - from.x) + Math.abs(other.position.y - from.y);
|
||||
if (d <= 3 && d < dBefore) return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script lang="ts">
|
||||
import type { Component } from "svelte";
|
||||
import { stepTarget } from "@wizwar/engine";
|
||||
import type { GameView, SightTrace } from "@wizwar/engine";
|
||||
import type { Side } from "@wizwar/engine";
|
||||
import type { BoardFx } from "./fx";
|
||||
@@ -181,29 +180,20 @@
|
||||
return boxes;
|
||||
});
|
||||
|
||||
// FEAR's dread reaches three WALKED spaces (through warps, around walls) —
|
||||
// the same BFS the engine's refusal runs, so the wash never lies.
|
||||
// FEAR's dread: three spaces in every direction, straight through walls
|
||||
// ("even if walls separate you"), never diagonally — a manhattan diamond,
|
||||
// the same measure the engine's refusal takes.
|
||||
const fearCells = $derived.by(() => {
|
||||
const out = new Set<string>();
|
||||
for (const fp of view.players) {
|
||||
if (!fp.alive) continue;
|
||||
if (!view.sustained.some((e) => e.cardId === "fear" && e.targetId === fp.id)) continue;
|
||||
const seen = new Map<string, number>([[`${fp.position.x},${fp.position.y}`, 0]]);
|
||||
const queue = [fp.position];
|
||||
while (queue.length > 0) {
|
||||
const cur = queue.shift()!;
|
||||
const d = seen.get(`${cur.x},${cur.y}`)!;
|
||||
if (d >= 3) continue;
|
||||
for (const side of ["N", "S", "E", "W"] as const) {
|
||||
const t = stepTarget(view.board, cur, side);
|
||||
if (t.kind === "blocked") continue;
|
||||
const k = `${t.to.x},${t.to.y}`;
|
||||
if (seen.has(k) || view.squareContents[k]?.kind === "stone") continue;
|
||||
seen.set(k, d + 1);
|
||||
queue.push(t.to);
|
||||
for (let dx = -3; dx <= 3; dx++) {
|
||||
for (let dy = -3 + Math.abs(dx); dy <= 3 - Math.abs(dx); dy++) {
|
||||
const k = `${fp.position.x + dx},${fp.position.y + dy}`;
|
||||
if (view.board.cells[k]) out.add(k);
|
||||
}
|
||||
}
|
||||
for (const k of seen.keys()) out.add(k);
|
||||
}
|
||||
return out;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user