UNPKG

@logic-pad/core

Version:
96 lines (95 loc) 3.83 kB
import BTModule, { BTTile, checkSubtilePlacement, IntArray2D, } from '../data.js'; export default class LetterBTModule extends BTModule { letters; letterGrid; constructor(instrs, width, height) { super(); this.letters = []; this.letterGrid = IntArray2D.create(width, height); const letterMap = new Map(); let letterCount = 0; for (const instr of instrs) { if (!letterMap.has(instr.letter)) { letterMap.set(instr.letter, letterCount); this.letters[letterCount] = []; letterCount += 1; } const id = letterMap.get(instr.letter); this.letters[id].push(instr); this.letterGrid.set(Math.floor(instr.x), Math.floor(instr.y), id + 1); } } checkGlobal(grid) { const visited = IntArray2D.create(grid.width, grid.height); for (let id = 0; id < this.letters.length; id++) { for (const symbol of this.letters[id]) { const checkResult = checkSubtilePlacement(grid, symbol); if (checkResult !== undefined) return checkResult; } for (const symbol of this.letters[id]) { const symbolX = Math.floor(symbol.x); const symbolY = Math.floor(symbol.y); if (grid.getTile(symbolX, symbolY) === BTTile.Empty) continue; if (!this.visitArea(grid, visited, { x: symbolX, y: symbolY }, id + 1)) return false; break; } } return { tilesNeedCheck: null, ratings: null }; } visitArea(grid, visited, pos, id) { const tile = grid.getTile(pos.x, pos.y); const sameTileQueue = [pos]; const usableTileQueue = []; let letterVisited = 0; visited.set(pos.x, pos.y, id); // Count same tile while (sameTileQueue.length > 0) { const curPos = sameTileQueue.pop(); const letterId = this.letterGrid.get(curPos.x, curPos.y); if (letterId === id) { letterVisited += 1; } else if (letterId !== 0) { return false; } for (const edge of grid.getEdges(curPos)) { if ((visited.get(edge.x, edge.y) & 0b01111111) === id) continue; const edgeTile = grid.getTile(edge.x, edge.y); if (edgeTile === BTTile.Empty) { usableTileQueue.push(edge); visited.set(edge.x, edge.y, id | 0b10000000); } else if (edgeTile === tile) { sameTileQueue.push(edge); visited.set(edge.x, edge.y, id); } } } if (letterVisited === this.letters[id - 1].length) return true; // Count usable tile while (usableTileQueue.length > 0) { const curPos = usableTileQueue.pop(); const letterId = this.letterGrid.get(curPos.x, curPos.y); if (letterId === id) { letterVisited += 1; if (letterVisited === this.letters[id - 1].length) return true; } for (const edge of grid.getEdges(curPos)) { if ((visited.get(edge.x, edge.y) & 0b01111111) === id) continue; const edgeTile = grid.getTile(edge.x, edge.y); if (edgeTile === BTTile.Empty || edgeTile === tile) { usableTileQueue.push(edge); visited.set(edge.x, edge.y, id | 0b10000000); } } } return letterVisited === this.letters[id - 1].length; } }