UNPKG

@logic-pad/core

Version:
107 lines (106 loc) 3.64 kB
import { ConfigType } from '../config.js'; import GridData from '../grid.js'; import { Color } from '../primitives.js'; import NumberSymbol from './numberSymbol.js'; export default class MinesweeperSymbol extends NumberSymbol { title = 'Minesweeper Number'; static CONFIGS = Object.freeze([ { type: ConfigType.Number, default: 0, field: 'x', description: 'X', configurable: false, }, { type: ConfigType.Number, default: 0, field: 'y', description: 'Y', configurable: false, }, { type: ConfigType.Number, default: 1, field: 'number', description: 'Number', configurable: true, }, ]); static EXAMPLE_GRID = Object.freeze(GridData.create(['wwbww', 'wwbwb', 'wwbwb', 'bwwww']) .addSymbol(new MinesweeperSymbol(1, 1, 3)) .addSymbol(new MinesweeperSymbol(3, 1, 5)) .addSymbol(new MinesweeperSymbol(4, 1, 4)) .addSymbol(new MinesweeperSymbol(2, 3, 1))); /** * **Minesweeper Numbers count opposite cells in 8 adjacent spaces** * * @param x - The x-coordinate of the symbol. * @param y - The y-coordinate of the symbol. * @param number - The number of cells seen by the symbol. */ constructor(x, y, number) { super(x, y, number); } get id() { return `minesweeper`; } get placementStep() { return 1; } get explanation() { return `*Minesweeper Numbers* count opposite cells in 8 adjacent spaces`; } get configs() { return MinesweeperSymbol.CONFIGS; } createExampleGrid() { return MinesweeperSymbol.EXAMPLE_GRID; } countForColor(grid, color) { let gray = 0; let opposite = 0; const visited = []; for (let y = this.y - 1; y <= this.y + 1; y++) { for (let x = this.x - 1; x <= this.x + 1; x++) { if (x === this.x && y === this.y) continue; if (grid.wrapAround.value) { const pos = grid.toArrayCoordinates(x, y); if (visited.some(v => v.x === pos.x && v.y === pos.y)) continue; visited.push(pos); } const tile = grid.getTile(x, y); if (!tile.exists) continue; if (tile.color === Color.Gray) gray++; else if (tile.color !== color) opposite++; } } return { completed: opposite, possible: opposite + gray }; } countTiles(grid) { if (Math.floor(this.x) !== this.x || Math.floor(this.y) !== this.y) return { completed: 0, possible: Number.MAX_SAFE_INTEGER }; const color = grid.getTile(this.x, this.y).color; if (color === Color.Gray) { const dark = this.countForColor(grid, Color.Dark); const light = this.countForColor(grid, Color.Light); return { completed: Math.min(dark.completed, light.completed), possible: Math.max(dark.possible, light.possible), }; } return this.countForColor(grid, color); } copyWith({ x, y, number, }) { return new MinesweeperSymbol(x ?? this.x, y ?? this.y, number ?? this.number); } withNumber(number) { return this.copyWith({ number }); } } export const instance = new MinesweeperSymbol(0, 0, 1);