UNPKG

@logic-pad/core

Version:
133 lines (132 loc) 5.37 kB
import BTModule, { BTTile, IntArray2D, } from '../data.js'; export default class DirectionLinkerBTModule extends BTModule { constructor(instr) { super(); Object.defineProperty(this, "instr", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "initialPositions", { enumerable: true, configurable: true, writable: true, value: null }); this.instr = instr; } getInitialPositions() { if (this.instr.x % 1 !== 0 && this.instr.y % 1 !== 0) return [ { x: Math.floor(this.instr.x), y: Math.floor(this.instr.y) }, { x: Math.ceil(this.instr.x), y: Math.ceil(this.instr.y) }, { x: Math.floor(this.instr.x), y: Math.ceil(this.instr.y) }, { x: Math.ceil(this.instr.x), y: Math.floor(this.instr.y) }, ]; else if (this.instr.x % 1 !== 0) return [ { x: Math.floor(this.instr.x), y: this.instr.y }, { x: Math.ceil(this.instr.x), y: this.instr.y }, ]; else if (this.instr.y % 1 !== 0) return [ { x: this.instr.x, y: Math.floor(this.instr.y) }, { x: this.instr.x, y: Math.ceil(this.instr.y) }, ]; else return [{ x: this.instr.x, y: this.instr.y }]; } checkGlobal(grid) { if (this.initialPositions === null) this.initialPositions = this.getInitialPositions(); const tilesNeedCheck = IntArray2D.create(grid.width, grid.height); const ratings = []; for (const pos of this.initialPositions) { const tile = grid.isInBound(pos.x, pos.y) ? grid.getTile(pos.x, pos.y) : BTTile.NonExist; if (tile === BTTile.Empty) { const oppoPos = this.movePos(grid, pos.x, pos.y); if (oppoPos === null || grid.getTile(oppoPos.x, oppoPos.y) === BTTile.NonExist) return false; else { if (grid.getTile(oppoPos.x, oppoPos.y) === BTTile.Empty) { tilesNeedCheck.set(oppoPos.x, oppoPos.y, 1); ratings.push({ pos: oppoPos, score: 1 }); } tilesNeedCheck.set(pos.x, pos.y, 1); ratings.push({ pos, score: 1 }); } } else if (tile === BTTile.NonExist) { const oppoPos = this.movePos(grid, pos.x, pos.y); if (oppoPos !== null && grid.getTile(oppoPos.x, oppoPos.y) !== BTTile.NonExist) { return false; } } else { const oppoPos = this.movePos(grid, pos.x, pos.y); if (oppoPos !== null) { const oppoTile = grid.getTile(oppoPos.x, oppoPos.y); if (oppoTile === BTTile.Empty) { tilesNeedCheck.set(oppoPos.x, oppoPos.y, 1); ratings.push({ pos: oppoPos, score: 1 }); } else if (oppoTile === BTTile.NonExist) return false; } else { return false; } } } if (ratings.length > 0) { return { tilesNeedCheck, ratings }; } const queue = this.initialPositions .filter(pos => grid.isInBound(pos.x, pos.y) && grid.getTile(pos.x, pos.y) !== BTTile.NonExist) .map(pos => { const oppoPos = this.movePos(grid, pos.x, pos.y); return { pos, color: grid.getTile(pos.x, pos.y), oppoColor: grid.getTile(oppoPos.x, oppoPos.y), }; }); const visited = IntArray2D.create(grid.width, grid.height); // Visit all connected tiles while (queue.length > 0) { const curPos = queue.pop(); if (visited.get(curPos.pos.x, curPos.pos.y)) continue; visited.set(curPos.pos.x, curPos.pos.y, 1); const oppoPos = this.movePos(grid, curPos.pos.x, curPos.pos.y); if (oppoPos === null) return false; const oppoTile = grid.getTile(oppoPos.x, oppoPos.y); if (!(oppoTile === BTTile.Empty || oppoTile === curPos.oppoColor)) return false; for (const edge of grid.getEdges(curPos.pos)) { if (visited.get(edge.x, edge.y)) continue; const edgeTile = grid.getTile(edge.x, edge.y); if (edgeTile === BTTile.Empty) { tilesNeedCheck.set(edge.x, edge.y, 1); ratings.push({ pos: edge, score: 1 }); } else if (edgeTile === curPos.color) { queue.push({ pos: edge, color: curPos.color, oppoColor: curPos.oppoColor, }); } } } return { tilesNeedCheck, ratings }; } }