UNPKG

@logic-pad/core

Version:
83 lines (82 loc) 3.2 kB
import { solveLogicPad } from 'logic-pad-solver-core'; import { Serializer } from '../../serializer/allSerializers.js'; import { gridToJson } from './jsonify.js'; import { instance as undercluedInstance } from '../../rules/undercluedRule.js'; import { Color } from '../../primitives.js'; function stringToColor(str) { if (str === 'dark') { return Color.Dark; } else if (str === 'light') { return Color.Light; } else { return Color.Gray; } } function postSolution(grid, solverResult) { if (solverResult === null) { postMessage(null); } else if ('error' in solverResult) { throw new Error(solverResult.error); } else { const solution = grid.withTiles(tiles => { for (const [y, row] of solverResult.entries()) { for (const [x, color] of row.entries()) { tiles[y][x] = tiles[y][x].withColor(stringToColor(color)); } } return tiles; }); postMessage(Serializer.stringifyGrid(solution)); } } onmessage = e => { const grid = Serializer.parseGrid(e.data); const isUnderclued = !!grid.findRule(r => r.id === undercluedInstance.id); const puzzleData = gridToJson(grid); const solverResult = solveLogicPad(puzzleData, isUnderclued); postSolution(grid, solverResult); if (isUnderclued) { postMessage(null); return; } // Make use of the underclued mode to determine solution uniqueness if (solverResult !== null && !('error' in solverResult) && !isUnderclued) { const undercluedResult = solveLogicPad(puzzleData, true); if (undercluedResult === null) { postMessage(undefined); // Shouldn't happen because underclued grids should always be solvable } else if ('error' in undercluedResult) { throw new Error(undercluedResult.error); } else if (undercluedResult.every((row, y) => row.every((cell, x) => cell !== null || !grid.getTile(x, y).exists))) { postMessage(null); } else { let tweaked = false; for (const [y, row] of undercluedResult.entries()) { for (const [x, color] of row.entries()) { if (color !== null) { puzzleData.tiles[y][x].fixed = true; puzzleData.tiles[y][x].color = color; } else if (!tweaked && puzzleData.tiles[y][x].exists) { const positions = grid.connections.getConnectedTiles({ x, y }); const newColor = solverResult[y][x] === 'dark' ? 'light' : 'dark'; positions.forEach(({ x: px, y: py }) => { puzzleData.tiles[py][px].fixed = true; puzzleData.tiles[py][px].color = newColor; }); tweaked = true; } } } const secondResult = solveLogicPad(puzzleData, false); postSolution(grid, secondResult); } } postMessage(undefined); };