UNPKG

@logic-pad/core

Version:
125 lines (124 loc) 5.47 kB
import { instance as banPatternInstance } from '../../rules/banPatternRule.js'; import { instance as cellCountInstance } from '../../rules/cellCountRule.js'; import { instance as regionAreaInstance } from '../../rules/regionAreaRule.js'; import { instance as sameShapeInstance } from '../../rules/sameShapeRule.js'; import { instance as symbolsPerRegionInstance } from '../../rules/symbolsPerRegionRule.js'; import { instance as undercluedInstance } from '../../rules/undercluedRule.js'; import { instance as uniqueShapeInstance } from '../../rules/uniqueShapeRule.js'; import { instance as offByXInstance } from '../../rules/offByXRule.js'; import AreaNumberSymbol, { instance as areaNumberInstance, } from '../../symbols/areaNumberSymbol.js'; import { instance as dartInstance } from '../../symbols/dartSymbol.js'; import GalaxySymbol, { instance as galaxyInstance, } from '../../symbols/galaxySymbol.js'; import LetterSymbol, { instance as letterInstance, } from '../../symbols/letterSymbol.js'; import LotusSymbol, { instance as lotusInstance, } from '../../symbols/lotusSymbol.js'; import { instance as minesweeperInstance } from '../../symbols/minesweeperSymbol.js'; import { instance as viewpointInstance } from '../../symbols/viewpointSymbol.js'; import { instance as connectAllInstance } from '../../rules/connectAllRule.js'; import { instance as unsupportedInstance } from '../../symbols/unsupportedSymbol.js'; import EventIteratingSolver from '../eventIteratingSolver.js'; import GridData from '../../grid.js'; import { Color } from '../../primitives.js'; // eslint-disable-next-line @typescript-eslint/no-unused-expressions ('vite-apply-code-mod'); export default class CspuzSolver extends EventIteratingSolver { static supportedInstrs = [ minesweeperInstance.id, areaNumberInstance.id, letterInstance.id, dartInstance.id, viewpointInstance.id, lotusInstance.id, galaxyInstance.id, connectAllInstance.id, banPatternInstance.id, sameShapeInstance.id, uniqueShapeInstance.id, regionAreaInstance.id, cellCountInstance.id, offByXInstance.id, undercluedInstance.id, symbolsPerRegionInstance.id, unsupportedInstance.id, ]; id = 'cspuz'; author = 'semiexp'; description = 'A blazingly fast WebAssembly solver that supports most rules and symbols (including underclued).'; createWorker() { return new Worker(new URL('./cspuzWorker.js', import.meta.url), { type: 'module', }); } isGridSupported(grid) { if (!super.isGridSupported(grid)) { return false; } // special handling for fixed gray tiles if (grid.getTileCount(true, true, Color.Gray) > 0) { return false; } // the solver doesn't count symbols correctly if some symbols are unsupported if (grid.findSymbol(symbol => symbol.id === unsupportedInstance.id) && grid.findRule(rule => rule.id === symbolsPerRegionInstance.id)) { return false; } return true; } isInstructionSupported(grid, instruction) { if (instruction instanceof LotusSymbol || instruction instanceof GalaxySymbol) { if (instruction.x % 1 !== 0 && instruction.y % 1 !== 0) { return false; } } if (instruction instanceof LotusSymbol || instruction instanceof GalaxySymbol || instruction instanceof AreaNumberSymbol || instruction instanceof LetterSymbol) { if (instruction.x % 1 !== 0 || instruction.y % 1 !== 0) { const minX = Math.floor(instruction.x); const minY = Math.floor(instruction.y); const maxX = Math.ceil(instruction.x); const maxY = Math.ceil(instruction.y); const connectedTiles = grid.connections.getConnectedTiles({ x: minX, y: minY, }); if (connectedTiles.some(tile => tile.x === minX && tile.y === maxY) && connectedTiles.some(tile => tile.x === maxX && tile.y === minY) && connectedTiles.some(tile => tile.x === maxX && tile.y === maxY)) { return true; } let color = Color.Gray; for (let i = 0; i < 4; i++) { const x = i % 2 === 0 ? minX : maxX; const y = i < 2 ? minY : maxY; const tile = grid.getTile(x, y); if (!tile.fixed || !tile.exists) { return false; } if (tile.color !== Color.Gray) { if (color === Color.Gray) { color = tile.color; } else if (color !== tile.color) { return false; } } } return true; } } return CspuzSolver.supportedInstrs.includes(instruction.id); } async isEnvironmentSupported() { try { for await (const _ of this.solve(GridData.create(['.']))) { // do nothing } return true; } catch (_ex) { return false; } } }