UNPKG

@logic-pad/core

Version:
89 lines (88 loc) 2.92 kB
import { ConfigType } from '../config.js'; import GridData from '../grid.js'; import { array, minBy } from '../dataHelper.js'; import { Color, State } from '../primitives.js'; import Rule from './rule.js'; export default class ConnectAllRule extends Rule { color; title = 'Connect All'; static CONFIGS = Object.freeze([ { type: ConfigType.Color, default: Color.Light, allowGray: false, field: 'color', description: 'Color', configurable: true, }, ]); static EXAMPLE_GRID_LIGHT = Object.freeze(GridData.create(['bwwwb', 'bwbww', 'wwwbb', 'wbwww'])); static EXAMPLE_GRID_DARK = Object.freeze(GridData.create(['wbbbw', 'wbwbb', 'bbbww', 'bwbbb'])); static SEARCH_VARIANTS = [ new ConnectAllRule(Color.Light).searchVariant(), new ConnectAllRule(Color.Dark).searchVariant(), ]; /** * **Connect all &lt;color&gt; cells** * * @param color - The color of the cells to connect. */ constructor(color) { super(); this.color = color; this.color = color; } get id() { return `connect_all`; } get explanation() { return `Connect all ${this.color} cells`; } get configs() { return ConnectAllRule.CONFIGS; } createExampleGrid() { return this.color === Color.Light ? ConnectAllRule.EXAMPLE_GRID_LIGHT : ConnectAllRule.EXAMPLE_GRID_DARK; } get searchVariants() { return ConnectAllRule.SEARCH_VARIANTS; } validateGrid(grid) { let complete = true; const visited = array(grid.width, grid.height, (i, j) => !grid.getTile(i, j).exists); const islands = []; while (true) { const seed = grid.find((tile, x, y) => !visited[y][x] && tile.color === this.color); if (!seed) break; const positions = []; grid.iterateArea(seed, tile => tile.color === this.color || tile.color === Color.Gray, (tile, x, y) => { if (tile.color === Color.Gray) complete = false; positions.push({ x, y }); }, visited); islands.push(positions); } if (islands.length > 1) { return { state: State.Error, positions: minBy(islands, island => island.length), }; } else if (islands.length <= 1) { return { state: complete ? State.Satisfied : State.Incomplete }; } else { return { state: State.Incomplete }; // not reachable but the TS is not happy } } copyWith({ color }) { return new ConnectAllRule(color ?? this.color); } withColor(color) { return this.copyWith({ color }); } } export const instance = new ConnectAllRule(Color.Dark);