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
@@ -238,7 +238,7 @@ export interface CastParams {
|
||||
}
|
||||
|
||||
/** The revision new games are dealt under; GameConfig.deckRev pins it per game. */
|
||||
export const CURRENT_RULES_REV = 18;
|
||||
export const CURRENT_RULES_REV = 19;
|
||||
|
||||
/** Every rulings revision since the baseline, newest last — the entries a
|
||||
* game's deckRev freezes it before or after. Shown to players as the house
|
||||
@@ -261,6 +261,7 @@ export const RULES_REVISIONS: { rev: number; note: string }[] = [
|
||||
{ rev: 16, note: "BUTT-HEAD's charge is measured as far as the goat's legs reach. Older games searched only six steps of corridor and refused a longer ram as unreachable, even with the legs to make it." },
|
||||
{ rev: 17, note: "A warp mouth on a pit's rim is a way off it like any square: a bare step beside one square and one mouth is a fork the walker names. In every game the mouth may be named, and is taken when no square offers; only an older game's bare step still lands on the square unasked." },
|
||||
{ rev: 18, note: "REFLECTION's returning half is an attack on the caster in its own right, with the caster's own counteraction window — an ABSORB or a BLUNT meets it as it would any blow. Before, the half landed the instant the spell resolved." },
|
||||
{ rev: 19, note: "DUST CLOUD blinds whoever stands in it: no LOS spell may be cast from inside a cloud, nor at anyone standing in one, and VISIONSTONE does not see through it. Spells cast on oneself still work. Before, the cloud blocked only sight lines passing through it." },
|
||||
];
|
||||
|
||||
export interface GameConfig {
|
||||
@@ -438,7 +439,18 @@ function sightThroughOneEdge(
|
||||
return throughOneEdge(board, (b) => sightBetween(b, from, to, blockers));
|
||||
}
|
||||
|
||||
/** Rev 19: DUST CLOUD blinds whoever stands in it and hides them — "an
|
||||
* LOS spell cannot be cast upon a player in DUST CLOUD, or by a player
|
||||
* who is in a DUST CLOUD" (official FAQ); a spell cast upon oneself
|
||||
* still works, and VISIONSTONE does not see through dust either. Before
|
||||
* it the cloud blocked only sight lines passing through. */
|
||||
function dustAtEnd(state: GameState, from: Cell, to: Cell): boolean {
|
||||
if ((state.config.deckRev ?? 1) < 19 || cellKey(from) === cellKey(to)) return false;
|
||||
return state.squareContents[cellKey(from)]?.kind === "dust" || state.squareContents[cellKey(to)]?.kind === "dust";
|
||||
}
|
||||
|
||||
function losWith(state: GameState, from: Cell, to: Cell, viewerId: PlayerId | undefined, stone: boolean): boolean {
|
||||
if (dustAtEnd(state, from, to)) return false;
|
||||
const board = doorsAjar(state, viewerId, openedDoors(state, boardView(state)));
|
||||
const blockers = losBlockers(state);
|
||||
if (sightBetween(board, from, to, blockers)) return true;
|
||||
|
||||
Reference in New Issue
Block a user