Rev 19: a dust cloud blinds whoever stands in it (CPU7)
The automaton stood in Kestrel's DUST CLOUD and filled a square with stone three rows away. The cloud blocked only sight lines passing through it; the square a line began or ended in was never asked. The FAQ is plain: no LOS spell may be cast by a wizard in a cloud, nor at one, though a spell upon oneself still works, and VISIONSTONE does not see through dust. From rev 19 the engine's sight and the view's — the targeting aid the client and the automaton both read — refuse a line with dust at either end. Older games keep their sight. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
3d4bf1fa6d
commit
f859d90af8
@@ -220,8 +220,14 @@ export function sightedCellsFor(view: GameView): Set<string> {
|
||||
const me = view.players.find((p) => p.id === view.you);
|
||||
if (!me) return out;
|
||||
const { board, blockers } = sightBasis(view);
|
||||
// In a dust cloud a wizard sees only their own square (rev 19).
|
||||
if (dustAtEnd(view, me.position, me.position, true)) {
|
||||
out.add(`${me.position.x},${me.position.y}`);
|
||||
return out;
|
||||
}
|
||||
for (const key of Object.keys(board.cells)) {
|
||||
const [x, y] = key.split(",").map(Number) as [number, number];
|
||||
if (dustAtEnd(view, me.position, { x, y })) continue;
|
||||
if (sightBetween(board, me.position, { x, y }, blockers)) out.add(key);
|
||||
}
|
||||
// VISIONSTONE lets its bearer see through exactly one wall or door —
|
||||
@@ -314,16 +320,29 @@ function sightBasis(view: GameView): { board: GameView["board"]; blockers: Recor
|
||||
* exists — the renderer's material for drawing the line an attack traveled.
|
||||
*/
|
||||
export function traceSightFor(view: GameView, from: Cell, to: Cell): SightTrace | null {
|
||||
if (dustAtEnd(view, from, to)) return null;
|
||||
const { board, blockers } = sightBasis(view);
|
||||
return traceSight(board, from, to, blockers);
|
||||
}
|
||||
|
||||
/** Rev 19: DUST CLOUD blinds its occupant and hides them from LOS spells;
|
||||
* a square sees itself still. `standing` asks only whether the viewer's
|
||||
* own square is dust. */
|
||||
function dustAtEnd(view: GameView, from: Cell, to: Cell, standing = false): boolean {
|
||||
if (view.deckRev < 19) return false;
|
||||
const dust = (c: Cell) => view.squareContents[`${c.x},${c.y}`]?.kind === "dust";
|
||||
if (standing) return dust(from);
|
||||
if (from.x === to.x && from.y === to.y) return false;
|
||||
return dust(from) || dust(to);
|
||||
}
|
||||
|
||||
/**
|
||||
* AROUND THE CORNER's bent sight, from this viewer's knowledge: the caster
|
||||
* sees a middle square which sees the target — mirroring the engine's
|
||||
* bentLos so a client can predict whether the modifier will land.
|
||||
*/
|
||||
export function bentSightFor(view: GameView, from: Cell, to: Cell): boolean {
|
||||
if (dustAtEnd(view, from, to)) return false;
|
||||
const { board, blockers } = sightBasis(view);
|
||||
if (sightBetween(board, from, to, blockers)) return true;
|
||||
for (const key of Object.keys(board.cells)) {
|
||||
|
||||
Reference in New Issue
Block a user