Waves spend their force as they travel (rev 24); bots wield Destroy Wall
Rules rev 24: a waterwall wave that finds a victim dist cells from its source has only range-dist spaces of push left — a range-2 wave throws its adjacent victim two spaces but a victim at its far edge only one, and spent force never converts into crush damage. Applies to WATERWALL and both STONE TO WATER waves; older revisions keep the flat full-range wash so stored games replay unchanged. Automatons now use DESTROY WALL on the march: two BFS distance maps (from the bot, from its objectives) price every visible wall by the shortcut its removal opens; the bot blasts when it saves 4+ steps of walking — or when no road exists at all — never standing beside the blast unless trapped and healthy. The card also leaves the shed pile: discardValue 2 -> 6. 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
dfd7a2ff56
commit
2d53ba4bc0
@@ -2476,6 +2476,16 @@ function terrainEffect(kind: SquareContent["kind"]): NeutralEffect {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* How hard a wave still pushes someone it finds `dist` cells from its
|
||||
* source: the force spent reaching them is gone (rules rev 24), so a
|
||||
* range-2 wave throws its adjacent victim 2 spaces but a victim at its far
|
||||
* edge only 1 — and never converts spent force into crush damage.
|
||||
*/
|
||||
function waveForce(state: GameState, range: number, dist: number): number {
|
||||
return (state.config.deckRev ?? 1) >= 24 ? range - dist : range;
|
||||
}
|
||||
|
||||
/** A collapsing waterwall wave from an edge: wash players back `range`. */
|
||||
function waveFromEdge(state: GameState, events: GameEvent[], cell: Cell, side: Side, range: number, reason = "rushing water"): void {
|
||||
const away = (s2: Side): Side => (s2 === "N" ? "S" : s2 === "S" ? "N" : s2 === "E" ? "W" : "E");
|
||||
@@ -2486,15 +2496,16 @@ function waveFromEdge(state: GameState, events: GameEvent[], cell: Cell, side: S
|
||||
for (const { start, dir } of pushes) {
|
||||
let probe = start;
|
||||
for (let dist = 0; dist < range; dist++) {
|
||||
const force = waveForce(state, range, dist);
|
||||
for (const p of state.players) {
|
||||
if (p.alive && cellKey(p.position) === cellKey(probe)) washBackN(state, events, p, dir, range);
|
||||
if (p.alive && cellKey(p.position) === cellKey(probe)) washBackN(state, events, p, dir, force);
|
||||
}
|
||||
for (const c of [...state.creatures]) {
|
||||
if (cellKey(c.position) !== cellKey(probe)) continue;
|
||||
if (c.kind === "fire-imp") {
|
||||
destroyCreature(state, events, c, reason);
|
||||
} else if ((state.config.deckRev ?? 1) >= 17) {
|
||||
washBackCreature(state, events, c, dir, range);
|
||||
washBackCreature(state, events, c, dir, force);
|
||||
}
|
||||
}
|
||||
if (state.squareContents[cellKey(probe)]?.kind === "slime") {
|
||||
@@ -2513,15 +2524,16 @@ function waveFromCell(state: GameState, events: GameEvent[], center: Cell, range
|
||||
let probe = center;
|
||||
for (let dist = 0; dist < range; dist++) {
|
||||
probe = neighbor(probe, dir);
|
||||
const force = waveForce(state, range, dist);
|
||||
for (const p of state.players) {
|
||||
if (p.alive && cellKey(p.position) === cellKey(probe)) washBackN(state, events, p, dir, range);
|
||||
if (p.alive && cellKey(p.position) === cellKey(probe)) washBackN(state, events, p, dir, force);
|
||||
}
|
||||
for (const c of [...state.creatures]) {
|
||||
if (cellKey(c.position) !== cellKey(probe)) continue;
|
||||
if (c.kind === "fire-imp") {
|
||||
destroyCreature(state, events, c, "rushing water");
|
||||
} else if ((state.config.deckRev ?? 1) >= 17) {
|
||||
washBackCreature(state, events, c, dir, range);
|
||||
washBackCreature(state, events, c, dir, force);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user