Visionstone shots draw their ray and mark the pierced wall

A stone-bearing automaton fired Blind through a warp mouth and one
wall, and the table saw nothing but the attack modal — the sight trace
only knew plain and bent-corner lines, so a legal shot read as a cheat.
When the attacker displays VISIONSTONE and no plain line exists,
stackSightTrace now finds the single edge whose removal opens the line
(warp legs included), draws the ray through it, and the keymap pulses
the dissolved wall so the answer to "how can he even see me?" is on
the board. Verified against the live LZ5R blind moment: warp mouths
at (0,2)W and (4,7)E, pierced wall V:3,8.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015RCWSTnb1KYTPyL4GmhGnF
This commit is contained in:
Eric Wagoner
2026-08-27 18:52:46 -04:00
co-authored by Claude Fable 5
parent 358633022c
commit 773f0a7d21
2 changed files with 43 additions and 2 deletions
+22 -1
View File
@@ -75,9 +75,18 @@
effects?: BoardFx[] | null;
/** The sight line an attack in progress traveled — proof against "how
* can he even see me?", drawn leg by leg through any warp mouth. */
sightTrace?: { from: { x: number; y: number }; to: { x: number; y: number }; trace: SightTrace; bend?: { mid: { x: number; y: number }; trace: SightTrace } } | null;
sightTrace?: { from: { x: number; y: number }; to: { x: number; y: number }; trace: SightTrace; bend?: { mid: { x: number; y: number }; trace: SightTrace }; pierced?: string } | null;
} = $props();
/** The wall segment a VISIONSTONE shot pierced, from its edge key. */
function piercedSegment(key: string): { x1: number; y1: number; x2: number; y2: number } {
const [kind, xy] = key.split(":") as [string, string];
const [x, y] = xy.split(",").map(Number) as [number, number];
return kind === "V"
? { x1: (x + 1) * CELL, y1: y * CELL, x2: (x + 1) * CELL, y2: (y + 1) * CELL }
: { x1: x * CELL, y1: (y + 1) * CELL, x2: (x + 1) * CELL, y2: (y + 1) * CELL };
}
const SECTOR = 5;
/** Ghost slots can lie beyond the assembled maze — on any side, including
@@ -701,6 +710,11 @@
{:else}
<SightTraceOverlay from={sightTrace.from} to={sightTrace.to} trace={sightTrace.trace} />
{/if}
{#if sightTrace.pierced}
<!-- the one wall VISIONSTONE dissolved for this shot -->
{@const seg = piercedSegment(sightTrace.pierced)}
<line x1={seg.x1} y1={seg.y1} x2={seg.x2} y2={seg.y2} class="sight-pierced" />
{/if}
{/if}
<!-- spell flourishes: one sprite component per effect (src/fx-sprites/) -->
<g class="fx-layer" aria-hidden="true">
@@ -804,6 +818,13 @@
stroke-width: 2;
animation: sight-pulse 1.6s ease-in-out infinite;
}
.sight-pierced {
stroke: #c9a72a;
stroke-width: 5;
stroke-linecap: round;
stroke-dasharray: 2 5;
animation: sight-pulse 1.6s ease-in-out infinite;
}
@keyframes sight-pulse {
0%, 100% { opacity: 0.9; }
50% { opacity: 0.35; }