diff --git a/.playwright-mcp/console-2026-08-16T19-04-55-807Z.log b/.playwright-mcp/console-2026-08-16T19-04-55-807Z.log index a8dcc41..a806254 100644 --- a/.playwright-mcp/console-2026-08-16T19-04-55-807Z.log +++ b/.playwright-mcp/console-2026-08-16T19-04-55-807Z.log @@ -295,3 +295,68 @@ [ 1194642ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 [ 1197213ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 [ 1202483ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1205053ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1211337ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1217603ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1222257ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1228017ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1230586ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1234756ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1241044ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1246986ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1250672ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1253955ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1257042ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1262105ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1267671ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1272574ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1275340ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1279286ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1285505ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1291182ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1297631ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1301928ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1305765ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1308479ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1312882ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1318669ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1322416ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1327478ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1331288ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1335858ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1339718ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1343574ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1346446ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1352867ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1358790ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1363759ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1366710ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1370961ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1376653ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1379396ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1383377ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1384881ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1386390ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1387895ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1389407ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1390917ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1392426ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1393937ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1395459ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1396995ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1398541ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1400159ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1401910ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1403957ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1405787ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1408494ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1411369ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1414797ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1421173ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1424677ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1429773ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1432811ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1436872ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1439648ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1444751ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 +[ 1448652ms] [ERROR] WebSocket connection to 'ws://127.0.0.1:8899/ws' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED @ http://127.0.0.1:8899/assets/index-Di4XAJUy.js:1 diff --git a/packages/engine/src/board.ts b/packages/engine/src/board.ts index 2c8b82b..6b49e6b 100644 --- a/packages/engine/src/board.ts +++ b/packages/engine/src/board.ts @@ -27,12 +27,7 @@ export interface Warp { from: { cell: Cell; side: Side }; /** ...you arrive at this cell (entering through `side`). */ to: { cell: Cell; side: Side }; - /** - * An aisle (AUTO) warp joins two edges that physically meet at a corner: - * "for all purposes, treat the connected board edges as though they are - * adjacent" — including line of sight. The lettered wraparounds carry - * movement only; no rule grants sight across the map. - */ + /** An aisle (AUTO) warp joins two edges that meet at a corner. */ aisle?: boolean; } @@ -45,8 +40,6 @@ export interface AssembledBoard { /** Cells that are part of the map (all cells inside placed sectors). */ cells: Record; warps: Warp[]; - /** Pre-rev-7 games saw through every warp; their replays keep that sight. */ - sightThroughAllWarps?: boolean; /** Per player-sector info, in placement order. */ homes: Cell[]; treasureSpaces: Cell[][]; @@ -353,10 +346,12 @@ function onSegment(ax: number, ay: number, bx: number, by: number, px: number, p } /** - * Sight through a wraparound opening. Rulebook: "If casting a spell, or - * checking line of sight through the AUTO WARP, treat it as a straight - * line, and the two connected boards as though they were adjacent" — and - * the lettered openings reconnect edges the same way. So the far side is + * Sight through a wraparound opening — the boards "have open sides", and + * the AUTO WARP rule shows how to trace sight across a join: "treat it as + * a straight line, and the two connected boards as though they were + * adjacent". The texts never deny the lettered openings what they grant + * the aisle (only DIMENSIONAL WARP's tokens carry an explicit "no L.O.S." + * — and those are not board warps). So the far side is * virtually abutted at the mouth (rotated if the pairing turns a corner, * as the aisle warps do), and the center-to-center line must pass through * the one-cell opening: diagonals through the gap are as legal as they are @@ -373,7 +368,6 @@ export function hasWarpLineOfSight( }; const EPS = 1e-9; for (const w of board.warps) { - if (!w.aisle && !board.sightThroughAllWarps) continue; const mouthA = w.from.cell; const sideA = w.from.side; const mouthB = w.to.cell; diff --git a/packages/engine/src/game.ts b/packages/engine/src/game.ts index 830ef65..ca4cfd4 100644 --- a/packages/engine/src/game.ts +++ b/packages/engine/src/game.ts @@ -218,8 +218,10 @@ export interface GameConfig { * BIG MAN pushes occupants ahead, steps over floor hazards for 2 points, * and bars monsters from his square. Rev 6: ANTI-ANTI cannot pin a * teleport escape ("does not work against escape" — the card face). - * Rev 7: sight passes only through aisle-warp corners, not the lettered - * wraparounds ("no rule grants it; DIMENSIONAL WARP explicitly denies it"). + * Rev 7 briefly restricted warp sight to aisle corners; the table's + * reading prevailed and all board openings carry sight in every revision. + * DIMENSIONAL WARP's tokens never do ("There is no L.O.S. through the + * warp." — the card face). */ deckRev?: number; } @@ -292,17 +294,8 @@ export interface GameState { /** The board with dynamic wall changes applied — use for movement and LOS. */ export function boardView(state: GameState): AssembledBoard { - // Rev 7 restricts warp sight to the aisle corners; earlier games keep the - // wider sight their commands were validated against. - const legacySight = (state.config.deckRev ?? 1) < 7; - if (Object.keys(state.edgeOverrides).length === 0) { - return legacySight ? { ...state.board, sightThroughAllWarps: true } : state.board; - } - return { - ...state.board, - edges: { ...state.board.edges, ...state.edgeOverrides }, - ...(legacySight ? { sightThroughAllWarps: true } : {}), - }; + if (Object.keys(state.edgeOverrides).length === 0) return state.board; + return { ...state.board, edges: { ...state.board.edges, ...state.edgeOverrides } }; } export function sustainedOn(state: GameState, playerId: PlayerId, cardId?: string): SustainedEffect[] { diff --git a/packages/engine/test/board.test.ts b/packages/engine/test/board.test.ts index c7cf5e7..a2bddaa 100644 --- a/packages/engine/test/board.test.ts +++ b/packages/engine/test/board.test.ts @@ -144,18 +144,15 @@ describe("sight and the wraparound openings", () => { { boardId: "board-b", origin: { x: 0, y: 5 }, rotation: 0 }, ]; - it("lettered wraparounds carry movement only — no sight across the map", () => { + it("the open sides carry sight: mouths see each other through the join", () => { const board = assembleBoard(twoSector); - // (2,0) N wraps to (2,9) for walking, but no rule grants sight there, - // and DIMENSIONAL WARP's own face denies it for warps generally. - expect(sightBetween(board, { x: 2, y: 0 }, { x: 2, y: 9 })).toBe(false); - expect(sightBetween(board, { x: 2, y: 9 }, { x: 2, y: 0 })).toBe(false); + expect(hasLineOfSight(board, { x: 2, y: 0 }, { x: 2, y: 9 })).toBe(false); + expect(sightBetween(board, { x: 2, y: 0 }, { x: 2, y: 9 })).toBe(true); + expect(sightBetween(board, { x: 2, y: 9 }, { x: 2, y: 0 })).toBe(true); }); - it("pre-rev-7 games keep the wider sight their commands were validated under", () => { - const board = { ...assembleBoard(twoSector), sightThroughAllWarps: true }; - expect(sightBetween(board, { x: 2, y: 0 }, { x: 2, y: 9 })).toBe(true); - // Even then: walls inside the corridor still block, and a filled mouth chokes. + it("walls inside the corridor still block, and a filled mouth chokes", () => { + const board = assembleBoard(twoSector); expect(sightBetween(board, { x: 2, y: 2 }, { x: 2, y: 9 })).toBe(false); expect(sightBetween(board, { x: 2, y: 0 }, { x: 2, y: 8 }, { "2,9": true })).toBe(false); }); @@ -244,14 +241,5 @@ describe("the aisle warp treats its corner as adjacent — sight included", () = } expect(seen).toBeGreaterThan(0); expect(offAxis).toBeGreaterThan(0); - // A lettered (non-aisle) mouth on the same board sees nothing extra. - const lettered = board.warps.find((w) => !w.aisle)!; - const lm = lettered.from.cell; - let extra = 0; - for (const key of Object.keys(board.cells)) { - const [x, y] = key.split(",").map(Number) as [number, number]; - if (!hasLineOfSight(board, lm, { x, y }) && sightBetween(board, lm, { x, y })) extra++; - } - expect(extra).toBe(0); }); });