@logic-pad/core 0.26.2 → 0.26.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/logic-core.global.d.ts +3264 -3264
- package/dist/benchmark/helper.d.ts +21 -0
- package/dist/benchmark/helper.js +34 -0
- package/dist/benchmark/prepareBench.d.ts +1 -0
- package/dist/benchmark/prepareBench.js +140 -0
- package/dist/benchmark/runBench.d.ts +1 -0
- package/dist/benchmark/runBench.js +206 -0
- package/dist/src/data/config.d.ts +119 -0
- package/dist/src/data/config.js +72 -0
- package/dist/src/data/configurable.d.ts +14 -0
- package/dist/src/data/configurable.js +26 -0
- package/dist/src/data/dataHelper.d.ts +92 -0
- package/dist/src/data/dataHelper.js +217 -0
- package/dist/src/data/events/eventHelper.d.ts +1 -0
- package/dist/src/data/events/eventHelper.js +6 -0
- package/dist/src/data/events/onFinalValidation.d.ts +14 -0
- package/dist/src/data/events/onFinalValidation.js +4 -0
- package/dist/src/data/events/onGetTile.d.ts +7 -0
- package/dist/src/data/events/onGetTile.js +4 -0
- package/dist/src/data/events/onGridChange.d.ts +6 -0
- package/dist/src/data/events/onGridChange.js +4 -0
- package/dist/src/data/events/onGridResize.d.ts +9 -0
- package/dist/src/data/events/onGridResize.js +4 -0
- package/dist/src/data/events/onSetGrid.d.ts +7 -0
- package/dist/src/data/events/onSetGrid.js +19 -0
- package/dist/src/data/events/onSymbolDisplay.d.ts +16 -0
- package/dist/src/data/events/onSymbolDisplay.js +4 -0
- package/dist/src/data/events/onSymbolMerge.d.ts +10 -0
- package/dist/src/data/events/onSymbolMerge.js +4 -0
- package/dist/src/data/events/onSymbolValidation.d.ts +18 -0
- package/dist/src/data/events/onSymbolValidation.js +4 -0
- package/dist/src/data/grid.d.ts +410 -0
- package/dist/src/data/grid.js +1106 -0
- package/dist/src/data/gridConnections.d.ts +25 -0
- package/dist/src/data/gridConnections.js +309 -0
- package/dist/src/data/gridZones.d.ts +26 -0
- package/dist/src/data/gridZones.js +117 -0
- package/dist/src/data/instruction.d.ts +26 -0
- package/dist/src/data/instruction.js +29 -0
- package/dist/src/data/primitives.d.ts +138 -0
- package/dist/src/data/primitives.js +177 -0
- package/dist/src/data/puzzle.d.ts +73 -0
- package/dist/src/data/puzzle.js +105 -0
- package/dist/src/data/rules/banPatternRule.d.ts +30 -0
- package/dist/src/data/rules/banPatternRule.js +125 -0
- package/dist/src/data/rules/cellCountPerZoneRule.d.ts +23 -0
- package/dist/src/data/rules/cellCountPerZoneRule.js +39 -0
- package/dist/src/data/rules/cellCountRule.d.ts +33 -0
- package/dist/src/data/rules/cellCountRule.js +138 -0
- package/dist/src/data/rules/completePatternRule.d.ts +24 -0
- package/dist/src/data/rules/completePatternRule.js +46 -0
- package/dist/src/data/rules/connectAllRule.d.ts +29 -0
- package/dist/src/data/rules/connectAllRule.js +88 -0
- package/dist/src/data/rules/connectZonesRule.d.ts +29 -0
- package/dist/src/data/rules/connectZonesRule.js +111 -0
- package/dist/src/data/rules/containsShapeRule.d.ts +34 -0
- package/dist/src/data/rules/containsShapeRule.js +125 -0
- package/dist/src/data/rules/customRule.d.ts +34 -0
- package/dist/src/data/rules/customRule.js +74 -0
- package/dist/src/data/rules/differentCountPerZoneRule.d.ts +30 -0
- package/dist/src/data/rules/differentCountPerZoneRule.js +96 -0
- package/dist/src/data/rules/exactCountPerZoneRule.d.ts +33 -0
- package/dist/src/data/rules/exactCountPerZoneRule.js +99 -0
- package/dist/src/data/rules/foresightRule.d.ts +36 -0
- package/dist/src/data/rules/foresightRule.js +107 -0
- package/dist/src/data/rules/index.d.ts +3 -0
- package/dist/src/data/rules/index.js +10 -0
- package/dist/src/data/rules/lyingSymbolRule.d.ts +31 -0
- package/dist/src/data/rules/lyingSymbolRule.js +207 -0
- package/dist/src/data/rules/musicControlLine.d.ts +82 -0
- package/dist/src/data/rules/musicControlLine.js +167 -0
- package/dist/src/data/rules/musicGridRule.d.ts +51 -0
- package/dist/src/data/rules/musicGridRule.js +212 -0
- package/dist/src/data/rules/mysteryRule.d.ts +39 -0
- package/dist/src/data/rules/mysteryRule.js +146 -0
- package/dist/src/data/rules/noLoopsRule.d.ts +29 -0
- package/dist/src/data/rules/noLoopsRule.js +218 -0
- package/dist/src/data/rules/offByXRule.d.ts +32 -0
- package/dist/src/data/rules/offByXRule.js +124 -0
- package/dist/src/data/rules/perfectionRule.d.ts +45 -0
- package/dist/src/data/rules/perfectionRule.js +158 -0
- package/dist/src/data/rules/regionAreaRule.d.ts +34 -0
- package/dist/src/data/rules/regionAreaRule.js +149 -0
- package/dist/src/data/rules/regionShapeRule.d.ts +22 -0
- package/dist/src/data/rules/regionShapeRule.js +58 -0
- package/dist/src/data/rules/rule.d.ts +18 -0
- package/dist/src/data/rules/rule.js +19 -0
- package/dist/src/data/rules/rules.gen.d.ts +23 -0
- package/dist/src/data/rules/rules.gen.js +27 -0
- package/dist/src/data/rules/sameCountPerZoneRule.d.ts +30 -0
- package/dist/src/data/rules/sameCountPerZoneRule.js +95 -0
- package/dist/src/data/rules/sameShapeRule.d.ts +28 -0
- package/dist/src/data/rules/sameShapeRule.js +68 -0
- package/dist/src/data/rules/symbolsPerRegionRule.d.ts +38 -0
- package/dist/src/data/rules/symbolsPerRegionRule.js +181 -0
- package/dist/src/data/rules/undercluedRule.d.ts +24 -0
- package/dist/src/data/rules/undercluedRule.js +53 -0
- package/dist/src/data/rules/uniqueShapeRule.d.ts +28 -0
- package/dist/src/data/rules/uniqueShapeRule.js +65 -0
- package/dist/src/data/rules/wrapAroundRule.d.ts +36 -0
- package/dist/src/data/rules/wrapAroundRule.js +241 -0
- package/dist/src/data/serializer/allSerializers.d.ts +35 -0
- package/dist/src/data/serializer/allSerializers.js +78 -0
- package/dist/src/data/serializer/compressor/allCompressors.d.ts +14 -0
- package/dist/src/data/serializer/compressor/allCompressors.js +43 -0
- package/dist/src/data/serializer/compressor/checksumCompressor.d.ts +6 -0
- package/dist/src/data/serializer/compressor/checksumCompressor.js +21 -0
- package/dist/src/data/serializer/compressor/compressorBase.d.ts +16 -0
- package/dist/src/data/serializer/compressor/compressorBase.js +2 -0
- package/dist/src/data/serializer/compressor/deflateCompressor.d.ts +7 -0
- package/dist/src/data/serializer/compressor/deflateCompressor.js +17 -0
- package/dist/src/data/serializer/compressor/gzipCompressor.d.ts +5 -0
- package/dist/src/data/serializer/compressor/gzipCompressor.js +9 -0
- package/dist/src/data/serializer/compressor/streamCompressor.d.ts +6 -0
- package/dist/src/data/serializer/compressor/streamCompressor.js +41 -0
- package/dist/src/data/serializer/serializerBase.d.ts +32 -0
- package/dist/src/data/serializer/serializerBase.js +2 -0
- package/dist/src/data/serializer/serializer_checksum.d.ts +35 -0
- package/dist/src/data/serializer/serializer_checksum.js +179 -0
- package/dist/src/data/serializer/serializer_v0.d.ts +55 -0
- package/dist/src/data/serializer/serializer_v0.js +484 -0
- package/dist/src/data/shapes.d.ts +19 -0
- package/dist/src/data/shapes.js +137 -0
- package/dist/src/data/solver/allSolvers.d.ts +3 -0
- package/dist/src/data/solver/allSolvers.js +13 -0
- package/dist/src/data/solver/auto/autoSolver.d.ts +18 -0
- package/dist/src/data/solver/auto/autoSolver.js +156 -0
- package/dist/src/data/solver/backtrack/backtrackSolver.d.ts +11 -0
- package/dist/src/data/solver/backtrack/backtrackSolver.js +54 -0
- package/dist/src/data/solver/backtrack/backtrackWorker.d.ts +1 -0
- package/dist/src/data/solver/backtrack/backtrackWorker.js +312 -0
- package/dist/src/data/solver/backtrack/data.d.ts +47 -0
- package/dist/src/data/solver/backtrack/data.js +151 -0
- package/dist/src/data/solver/backtrack/rules/banPattern.d.ts +9 -0
- package/dist/src/data/solver/backtrack/rules/banPattern.js +77 -0
- package/dist/src/data/solver/backtrack/rules/cellCount.d.ts +7 -0
- package/dist/src/data/solver/backtrack/rules/cellCount.js +25 -0
- package/dist/src/data/solver/backtrack/rules/connectAll.d.ts +7 -0
- package/dist/src/data/solver/backtrack/rules/connectAll.js +44 -0
- package/dist/src/data/solver/backtrack/rules/regionArea.d.ts +8 -0
- package/dist/src/data/solver/backtrack/rules/regionArea.js +71 -0
- package/dist/src/data/solver/backtrack/rules/regionShape.d.ts +8 -0
- package/dist/src/data/solver/backtrack/rules/regionShape.js +57 -0
- package/dist/src/data/solver/backtrack/rules/sameShape.d.ts +8 -0
- package/dist/src/data/solver/backtrack/rules/sameShape.js +14 -0
- package/dist/src/data/solver/backtrack/rules/symbolsPerRegion.d.ts +10 -0
- package/dist/src/data/solver/backtrack/rules/symbolsPerRegion.js +82 -0
- package/dist/src/data/solver/backtrack/rules/uniqueShape.d.ts +8 -0
- package/dist/src/data/solver/backtrack/rules/uniqueShape.js +14 -0
- package/dist/src/data/solver/backtrack/symbols/areaNumber.d.ts +9 -0
- package/dist/src/data/solver/backtrack/symbols/areaNumber.js +75 -0
- package/dist/src/data/solver/backtrack/symbols/dart.d.ts +8 -0
- package/dist/src/data/solver/backtrack/symbols/dart.js +45 -0
- package/dist/src/data/solver/backtrack/symbols/directionLinker.d.ts +11 -0
- package/dist/src/data/solver/backtrack/symbols/directionLinker.js +121 -0
- package/dist/src/data/solver/backtrack/symbols/focus.d.ts +9 -0
- package/dist/src/data/solver/backtrack/symbols/focus.js +48 -0
- package/dist/src/data/solver/backtrack/symbols/galaxy.d.ts +9 -0
- package/dist/src/data/solver/backtrack/symbols/galaxy.js +14 -0
- package/dist/src/data/solver/backtrack/symbols/letter.d.ts +9 -0
- package/dist/src/data/solver/backtrack/symbols/letter.js +95 -0
- package/dist/src/data/solver/backtrack/symbols/lotus.d.ts +11 -0
- package/dist/src/data/solver/backtrack/symbols/lotus.js +55 -0
- package/dist/src/data/solver/backtrack/symbols/minesweeper.d.ts +9 -0
- package/dist/src/data/solver/backtrack/symbols/minesweeper.js +44 -0
- package/dist/src/data/solver/backtrack/symbols/myopia.d.ts +7 -0
- package/dist/src/data/solver/backtrack/symbols/myopia.js +73 -0
- package/dist/src/data/solver/backtrack/symbols/viewpoint.d.ts +7 -0
- package/dist/src/data/solver/backtrack/symbols/viewpoint.js +51 -0
- package/dist/src/data/solver/cspuz/cspuzSolver.d.ts +13 -0
- package/dist/src/data/solver/cspuz/cspuzSolver.js +124 -0
- package/dist/src/data/solver/cspuz/cspuzWorker.d.ts +1 -0
- package/dist/src/data/solver/cspuz/cspuzWorker.js +82 -0
- package/dist/src/data/solver/cspuz/jsonify.d.ts +3 -0
- package/dist/src/data/solver/cspuz/jsonify.js +215 -0
- package/dist/src/data/solver/eventIteratingSolver.d.ts +8 -0
- package/dist/src/data/solver/eventIteratingSolver.js +54 -0
- package/dist/src/data/solver/solver.d.ts +77 -0
- package/dist/src/data/solver/solver.js +59 -0
- package/dist/src/data/solver/universal/universalSolver.d.ts +7 -0
- package/dist/src/data/solver/universal/universalSolver.js +13 -0
- package/dist/src/data/solver/universal/universalWorker.d.ts +1 -0
- package/dist/src/data/solver/universal/universalWorker.js +128 -0
- package/dist/src/data/symbols/areaNumberSymbol.d.ts +31 -0
- package/dist/src/data/symbols/areaNumberSymbol.js +80 -0
- package/dist/src/data/symbols/customIconSymbol.d.ts +35 -0
- package/dist/src/data/symbols/customIconSymbol.js +94 -0
- package/dist/src/data/symbols/customSymbol.d.ts +25 -0
- package/dist/src/data/symbols/customSymbol.js +45 -0
- package/dist/src/data/symbols/customTextSymbol.d.ts +35 -0
- package/dist/src/data/symbols/customTextSymbol.js +95 -0
- package/dist/src/data/symbols/dartSymbol.d.ts +36 -0
- package/dist/src/data/symbols/dartSymbol.js +96 -0
- package/dist/src/data/symbols/directionLinkerSymbol.d.ts +29 -0
- package/dist/src/data/symbols/directionLinkerSymbol.js +232 -0
- package/dist/src/data/symbols/everyLetterSymbol.d.ts +32 -0
- package/dist/src/data/symbols/everyLetterSymbol.js +119 -0
- package/dist/src/data/symbols/focusSymbol.d.ts +40 -0
- package/dist/src/data/symbols/focusSymbol.js +159 -0
- package/dist/src/data/symbols/galaxySymbol.d.ts +27 -0
- package/dist/src/data/symbols/galaxySymbol.js +61 -0
- package/dist/src/data/symbols/hiddenSymbol.d.ts +38 -0
- package/dist/src/data/symbols/hiddenSymbol.js +113 -0
- package/dist/src/data/symbols/houseSymbol.d.ts +33 -0
- package/dist/src/data/symbols/houseSymbol.js +104 -0
- package/dist/src/data/symbols/index.d.ts +3 -0
- package/dist/src/data/symbols/index.js +10 -0
- package/dist/src/data/symbols/letterSymbol.d.ts +32 -0
- package/dist/src/data/symbols/letterSymbol.js +118 -0
- package/dist/src/data/symbols/lotusSymbol.d.ts +30 -0
- package/dist/src/data/symbols/lotusSymbol.js +132 -0
- package/dist/src/data/symbols/minesweeperSymbol.d.ts +33 -0
- package/dist/src/data/symbols/minesweeperSymbol.js +106 -0
- package/dist/src/data/symbols/myopiaSymbol.d.ts +37 -0
- package/dist/src/data/symbols/myopiaSymbol.js +182 -0
- package/dist/src/data/symbols/numberSymbol.d.ts +19 -0
- package/dist/src/data/symbols/numberSymbol.js +32 -0
- package/dist/src/data/symbols/symbol.d.ts +29 -0
- package/dist/src/data/symbols/symbol.js +87 -0
- package/dist/src/data/symbols/symbols.gen.d.ts +15 -0
- package/dist/src/data/symbols/symbols.gen.js +19 -0
- package/dist/src/data/symbols/unsupportedSymbol.d.ts +23 -0
- package/dist/src/data/symbols/unsupportedSymbol.js +47 -0
- package/dist/src/data/symbols/viewpointSymbol.d.ts +32 -0
- package/dist/src/data/symbols/viewpointSymbol.js +95 -0
- package/dist/src/data/tile.d.ts +26 -0
- package/dist/src/data/tile.js +56 -0
- package/dist/src/data/tileConnections.d.ts +25 -0
- package/dist/src/data/tileConnections.js +74 -0
- package/dist/src/data/validate.d.ts +5 -0
- package/dist/src/data/validate.js +131 -0
- package/dist/src/data/validateAsync.d.ts +15 -0
- package/dist/src/data/validateAsync.js +71 -0
- package/dist/src/data/validateAsyncWorker.d.ts +1 -0
- package/dist/src/data/validateAsyncWorker.js +9 -0
- package/dist/src/index.d.ts +109 -0
- package/dist/src/index.js +112 -0
- package/dist/src/polyfill/streamPolyfill.d.ts +2 -0
- package/dist/src/polyfill/streamPolyfill.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { Color } from '../../primitives.js';
|
|
2
|
+
export var BTTile;
|
|
3
|
+
(function (BTTile) {
|
|
4
|
+
BTTile[BTTile["Empty"] = 0] = "Empty";
|
|
5
|
+
BTTile[BTTile["Dark"] = 1] = "Dark";
|
|
6
|
+
BTTile[BTTile["Light"] = 2] = "Light";
|
|
7
|
+
BTTile[BTTile["NonExist"] = 3] = "NonExist";
|
|
8
|
+
})(BTTile || (BTTile = {}));
|
|
9
|
+
export class BTGridData {
|
|
10
|
+
tiles;
|
|
11
|
+
connections;
|
|
12
|
+
modules;
|
|
13
|
+
width;
|
|
14
|
+
height;
|
|
15
|
+
constructor(tiles, connections, modules, width, height) {
|
|
16
|
+
this.tiles = tiles;
|
|
17
|
+
this.connections = connections;
|
|
18
|
+
this.modules = modules;
|
|
19
|
+
this.width = width;
|
|
20
|
+
this.height = height;
|
|
21
|
+
this.tiles = tiles;
|
|
22
|
+
this.connections = connections;
|
|
23
|
+
this.modules = modules;
|
|
24
|
+
this.width = width;
|
|
25
|
+
this.height = height;
|
|
26
|
+
}
|
|
27
|
+
getTile(x, y) {
|
|
28
|
+
return this.tiles[y][x];
|
|
29
|
+
}
|
|
30
|
+
setTileWithConnection(x, y, tile) {
|
|
31
|
+
for (const pos of this.connections[y][x]) {
|
|
32
|
+
this.tiles[pos.y][pos.x] = tile;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
isInBound(x, y) {
|
|
36
|
+
return x >= 0 && x < this.width && y >= 0 && y < this.height;
|
|
37
|
+
}
|
|
38
|
+
getEdges(pos) {
|
|
39
|
+
const positions = [];
|
|
40
|
+
if (pos.x > 0) {
|
|
41
|
+
if (this.getTile(pos.x - 1, pos.y) !== BTTile.NonExist)
|
|
42
|
+
positions.push({ x: pos.x - 1, y: pos.y });
|
|
43
|
+
}
|
|
44
|
+
if (pos.x + 1 < this.width) {
|
|
45
|
+
if (this.getTile(pos.x + 1, pos.y) !== BTTile.NonExist)
|
|
46
|
+
positions.push({ x: pos.x + 1, y: pos.y });
|
|
47
|
+
}
|
|
48
|
+
if (pos.y > 0) {
|
|
49
|
+
if (this.getTile(pos.x, pos.y - 1) !== BTTile.NonExist)
|
|
50
|
+
positions.push({ x: pos.x, y: pos.y - 1 });
|
|
51
|
+
}
|
|
52
|
+
if (pos.y + 1 < this.height) {
|
|
53
|
+
if (this.getTile(pos.x, pos.y + 1) !== BTTile.NonExist)
|
|
54
|
+
positions.push({ x: pos.x, y: pos.y + 1 });
|
|
55
|
+
}
|
|
56
|
+
return positions;
|
|
57
|
+
}
|
|
58
|
+
clone() {
|
|
59
|
+
return new BTGridData(this.tiles.map(arr => [...arr]), this.connections, this.modules, this.width, this.height);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export class IntArray2D {
|
|
63
|
+
array;
|
|
64
|
+
width;
|
|
65
|
+
height;
|
|
66
|
+
constructor(array, width, height) {
|
|
67
|
+
this.array = array;
|
|
68
|
+
this.width = width;
|
|
69
|
+
this.height = height;
|
|
70
|
+
this.array = array;
|
|
71
|
+
this.width = width;
|
|
72
|
+
this.height = height;
|
|
73
|
+
}
|
|
74
|
+
static create(width, height) {
|
|
75
|
+
return new IntArray2D(new Uint8Array(width * height), width, height);
|
|
76
|
+
}
|
|
77
|
+
set(x, y, value) {
|
|
78
|
+
this.array[y * this.width + x] = value;
|
|
79
|
+
}
|
|
80
|
+
get(x, y) {
|
|
81
|
+
return this.array[y * this.width + x];
|
|
82
|
+
}
|
|
83
|
+
clone() {
|
|
84
|
+
return new IntArray2D(new Uint8Array(this.array), this.width, this.height);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
export default class BTModule {
|
|
88
|
+
checkLocal(grid, _) {
|
|
89
|
+
return this.checkGlobal(grid);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
export function getOppositeColor(color) {
|
|
93
|
+
return color === BTTile.Dark ? BTTile.Light : BTTile.Dark;
|
|
94
|
+
}
|
|
95
|
+
export function colorToBTTile(color) {
|
|
96
|
+
if (color === Color.Gray)
|
|
97
|
+
return BTTile.Empty;
|
|
98
|
+
else if (color === Color.Light)
|
|
99
|
+
return BTTile.Light;
|
|
100
|
+
else
|
|
101
|
+
return BTTile.Dark;
|
|
102
|
+
}
|
|
103
|
+
export function createOneTileResult(grid, pos, score = 1) {
|
|
104
|
+
const tilesNeedCheck = IntArray2D.create(grid.width, grid.height);
|
|
105
|
+
tilesNeedCheck.set(pos.x, pos.y, 1);
|
|
106
|
+
const ratings = [{ pos, score }];
|
|
107
|
+
return { tilesNeedCheck, ratings };
|
|
108
|
+
}
|
|
109
|
+
export function checkSubtilePlacement(grid, pos) {
|
|
110
|
+
const minX = Math.floor(pos.x);
|
|
111
|
+
const minY = Math.floor(pos.y);
|
|
112
|
+
if (minX === pos.x && minY === pos.y)
|
|
113
|
+
return undefined;
|
|
114
|
+
const maxX = Math.ceil(pos.x);
|
|
115
|
+
const maxY = Math.ceil(pos.y);
|
|
116
|
+
let color = null;
|
|
117
|
+
let complete = true;
|
|
118
|
+
for (let i = 0; i < 4; i++) {
|
|
119
|
+
const x = i % 2 === 0 ? minX : maxX;
|
|
120
|
+
const y = i < 2 ? minY : maxY;
|
|
121
|
+
if (!grid.isInBound(x, y))
|
|
122
|
+
return false;
|
|
123
|
+
const tile = grid.getTile(x, y);
|
|
124
|
+
if (tile === BTTile.NonExist)
|
|
125
|
+
return false;
|
|
126
|
+
if (tile !== BTTile.Empty) {
|
|
127
|
+
if (color !== null && tile !== color)
|
|
128
|
+
return false;
|
|
129
|
+
color = tile;
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
complete = false;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (complete) {
|
|
136
|
+
return undefined;
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
const tilesNeedCheck = IntArray2D.create(grid.width, grid.height);
|
|
140
|
+
const ratings = [];
|
|
141
|
+
for (let i = 0; i < 4; i++) {
|
|
142
|
+
const x = i % 2 === 0 ? minX : maxX;
|
|
143
|
+
const y = i < 2 ? minY : maxY;
|
|
144
|
+
if (grid.getTile(x, y) === BTTile.Empty) {
|
|
145
|
+
tilesNeedCheck.set(x, y, 1);
|
|
146
|
+
ratings.push({ pos: { x, y }, score: 1 });
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return { tilesNeedCheck, ratings };
|
|
150
|
+
}
|
|
151
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Position } from '../../../primitives.js';
|
|
2
|
+
import BanPatternRule from '../../../rules/banPatternRule.js';
|
|
3
|
+
import BTModule, { BTGridData, CheckResult } from '../data.js';
|
|
4
|
+
export default class BanPatternBTModule extends BTModule {
|
|
5
|
+
instr: BanPatternRule;
|
|
6
|
+
constructor(instr: BanPatternRule);
|
|
7
|
+
checkGlobal(grid: BTGridData): CheckResult | false;
|
|
8
|
+
checkLocal(grid: BTGridData, positions: Position[]): CheckResult | false;
|
|
9
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import BTModule, { BTTile, colorToBTTile, } from '../data.js';
|
|
2
|
+
export default class BanPatternBTModule extends BTModule {
|
|
3
|
+
instr;
|
|
4
|
+
constructor(instr) {
|
|
5
|
+
super();
|
|
6
|
+
this.instr = instr;
|
|
7
|
+
}
|
|
8
|
+
checkGlobal(grid) {
|
|
9
|
+
for (const pattern of this.instr.cache) {
|
|
10
|
+
for (let y = 0; y <= grid.height - pattern.height; y++) {
|
|
11
|
+
for (let x = 0; x <= grid.width - pattern.width; x++) {
|
|
12
|
+
let match = true;
|
|
13
|
+
for (const tile of pattern.elements) {
|
|
14
|
+
const t = grid.getTile(x + tile.x, y + tile.y);
|
|
15
|
+
if (t !== colorToBTTile(tile.color)) {
|
|
16
|
+
match = false;
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (match) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return { tilesNeedCheck: null, ratings: null };
|
|
27
|
+
}
|
|
28
|
+
checkLocal(grid, positions) {
|
|
29
|
+
const ratings = [];
|
|
30
|
+
// TODO: Do not iterate positions
|
|
31
|
+
for (const { x, y } of positions) {
|
|
32
|
+
const tile = grid.getTile(x, y);
|
|
33
|
+
for (const shape of this.instr.cache) {
|
|
34
|
+
for (const origin of shape.elements) {
|
|
35
|
+
if (colorToBTTile(origin.color) !== tile)
|
|
36
|
+
continue;
|
|
37
|
+
if (origin.x > x ||
|
|
38
|
+
origin.y > y ||
|
|
39
|
+
shape.width - origin.x + x > grid.width ||
|
|
40
|
+
shape.height - origin.y + y > grid.height)
|
|
41
|
+
continue;
|
|
42
|
+
// We add a tile into ratings if that tile is the only mismatched tile
|
|
43
|
+
let match = true;
|
|
44
|
+
let mismatchPos = null;
|
|
45
|
+
for (const element of shape.elements) {
|
|
46
|
+
const eleTile = grid.getTile(element.x - origin.x + x, element.y - origin.y + y);
|
|
47
|
+
if (eleTile === BTTile.Empty) {
|
|
48
|
+
if (match) {
|
|
49
|
+
match = false;
|
|
50
|
+
mismatchPos = {
|
|
51
|
+
x: element.x - origin.x + x,
|
|
52
|
+
y: element.y - origin.y + y,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
mismatchPos = null;
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else if (eleTile !== colorToBTTile(element.color)) {
|
|
61
|
+
match = false;
|
|
62
|
+
mismatchPos = null;
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (match)
|
|
67
|
+
return false;
|
|
68
|
+
if (mismatchPos)
|
|
69
|
+
ratings.push({ pos: mismatchPos, score: 10000 });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// TODO: Redesign API - This is not the best!
|
|
74
|
+
// Ratings refresh on every backtrack! Ratings should be appended on the previous result instead of over-writing!
|
|
75
|
+
return { tilesNeedCheck: null, ratings };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import CellCountRule from '../../../rules/cellCountRule.js';
|
|
2
|
+
import BTModule, { BTGridData, CheckResult } from '../data.js';
|
|
3
|
+
export default class CellCountBTModule extends BTModule {
|
|
4
|
+
instr: CellCountRule;
|
|
5
|
+
constructor(instr: CellCountRule);
|
|
6
|
+
checkGlobal(grid: BTGridData): CheckResult | false;
|
|
7
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import BTModule, { BTTile, colorToBTTile, } from '../data.js';
|
|
2
|
+
export default class CellCountBTModule extends BTModule {
|
|
3
|
+
instr;
|
|
4
|
+
constructor(instr) {
|
|
5
|
+
super();
|
|
6
|
+
this.instr = instr;
|
|
7
|
+
}
|
|
8
|
+
checkGlobal(grid) {
|
|
9
|
+
const color = colorToBTTile(this.instr.color);
|
|
10
|
+
let colored = 0;
|
|
11
|
+
let possible = 0;
|
|
12
|
+
for (let y = 0; y < grid.height; y++) {
|
|
13
|
+
for (let x = 0; x < grid.width; x++) {
|
|
14
|
+
const tile = grid.getTile(x, y);
|
|
15
|
+
if (tile === color)
|
|
16
|
+
colored += 1;
|
|
17
|
+
else if (tile === BTTile.Empty)
|
|
18
|
+
possible += 1;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (colored > this.instr.count || colored + possible < this.instr.count)
|
|
22
|
+
return false;
|
|
23
|
+
return { tilesNeedCheck: null, ratings: null };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import ConnectAllRule from '../../../rules/connectAllRule.js';
|
|
2
|
+
import BTModule, { BTGridData, CheckResult } from '../data.js';
|
|
3
|
+
export default class ConnectAllBTModule extends BTModule {
|
|
4
|
+
instr: ConnectAllRule;
|
|
5
|
+
constructor(instr: ConnectAllRule);
|
|
6
|
+
checkGlobal(grid: BTGridData): CheckResult | false;
|
|
7
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import BTModule, { IntArray2D, colorToBTTile, getOppositeColor, } from '../data.js';
|
|
2
|
+
export default class ConnectAllBTModule extends BTModule {
|
|
3
|
+
instr;
|
|
4
|
+
constructor(instr) {
|
|
5
|
+
super();
|
|
6
|
+
this.instr = instr;
|
|
7
|
+
}
|
|
8
|
+
checkGlobal(grid) {
|
|
9
|
+
const color = colorToBTTile(this.instr.color);
|
|
10
|
+
// Find all same cells
|
|
11
|
+
const sameCells = [];
|
|
12
|
+
for (let y = 0; y < grid.height; y++) {
|
|
13
|
+
for (let x = 0; x < grid.width; x++) {
|
|
14
|
+
if (grid.getTile(x, y) === color) {
|
|
15
|
+
sameCells.push({ x, y });
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
// If there are no same cells, return true
|
|
20
|
+
if (sameCells.length === 0)
|
|
21
|
+
return { tilesNeedCheck: null, ratings: null };
|
|
22
|
+
const queue = [sameCells[0]];
|
|
23
|
+
const visited = IntArray2D.create(grid.width, grid.height);
|
|
24
|
+
// Perform flood fill
|
|
25
|
+
visited.set(sameCells[0].x, sameCells[0].y, 1);
|
|
26
|
+
while (queue.length > 0) {
|
|
27
|
+
const curPos = queue.pop();
|
|
28
|
+
for (const edge of grid.getEdges(curPos)) {
|
|
29
|
+
if (visited.get(edge.x, edge.y) ||
|
|
30
|
+
grid.getTile(edge.x, edge.y) === getOppositeColor(color)) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
visited.set(edge.x, edge.y, 1);
|
|
34
|
+
queue.push(edge);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// Check if any same cell is not reachable
|
|
38
|
+
for (const cell of sameCells) {
|
|
39
|
+
if (!visited.get(cell.x, cell.y))
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
return { tilesNeedCheck: null, ratings: null };
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import RegionAreaRule from '../../../rules/regionAreaRule.js';
|
|
2
|
+
import BTModule, { BTGridData, CheckResult } from '../data.js';
|
|
3
|
+
export default class RegionAreaBTModule extends BTModule {
|
|
4
|
+
instr: RegionAreaRule;
|
|
5
|
+
constructor(instr: RegionAreaRule);
|
|
6
|
+
checkGlobal(grid: BTGridData): CheckResult | false;
|
|
7
|
+
private visitArea;
|
|
8
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import BTModule, { BTTile, IntArray2D, colorToBTTile, } from '../data.js';
|
|
2
|
+
export default class RegionAreaBTModule extends BTModule {
|
|
3
|
+
instr;
|
|
4
|
+
constructor(instr) {
|
|
5
|
+
super();
|
|
6
|
+
this.instr = instr;
|
|
7
|
+
}
|
|
8
|
+
checkGlobal(grid) {
|
|
9
|
+
const color = colorToBTTile(this.instr.color);
|
|
10
|
+
const visited = IntArray2D.create(grid.width, grid.height);
|
|
11
|
+
let id = 0;
|
|
12
|
+
for (let y = 0; y < grid.height; y++) {
|
|
13
|
+
for (let x = 0; x < grid.width; x++) {
|
|
14
|
+
if (visited.get(x, y) & 0b01111111)
|
|
15
|
+
continue;
|
|
16
|
+
if (grid.getTile(x, y) !== color)
|
|
17
|
+
continue;
|
|
18
|
+
id += 1;
|
|
19
|
+
if (id > 127)
|
|
20
|
+
throw new Error('Too many regions!');
|
|
21
|
+
if (!this.visitArea(grid, color, visited, { x, y }, id))
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return { tilesNeedCheck: null, ratings: null };
|
|
26
|
+
}
|
|
27
|
+
visitArea(grid, tile, visited, pos, id) {
|
|
28
|
+
const sameTileQueue = [pos];
|
|
29
|
+
const usableTileQueue = [];
|
|
30
|
+
let sameCellCount = 0;
|
|
31
|
+
let usableCellCount = 0;
|
|
32
|
+
visited.set(pos.x, pos.y, id);
|
|
33
|
+
// Count same tile
|
|
34
|
+
while (sameTileQueue.length > 0) {
|
|
35
|
+
const curPos = sameTileQueue.pop();
|
|
36
|
+
sameCellCount += 1;
|
|
37
|
+
for (const edge of grid.getEdges(curPos)) {
|
|
38
|
+
if ((visited.get(edge.x, edge.y) & 0b01111111) === id)
|
|
39
|
+
continue;
|
|
40
|
+
const edgeTile = grid.getTile(edge.x, edge.y);
|
|
41
|
+
if (edgeTile === BTTile.Empty) {
|
|
42
|
+
usableTileQueue.push(edge);
|
|
43
|
+
visited.set(edge.x, edge.y, id | 0b10000000);
|
|
44
|
+
}
|
|
45
|
+
else if (edgeTile === tile) {
|
|
46
|
+
sameTileQueue.push(edge);
|
|
47
|
+
visited.set(edge.x, edge.y, id);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (sameCellCount > this.instr.size)
|
|
52
|
+
return false;
|
|
53
|
+
// Count usable tile
|
|
54
|
+
while (usableTileQueue.length > 0) {
|
|
55
|
+
const curPos = usableTileQueue.pop();
|
|
56
|
+
usableCellCount += 1;
|
|
57
|
+
if (sameCellCount + usableCellCount >= this.instr.size)
|
|
58
|
+
return true;
|
|
59
|
+
for (const edge of grid.getEdges(curPos)) {
|
|
60
|
+
if ((visited.get(edge.x, edge.y) & 0b01111111) === id)
|
|
61
|
+
continue;
|
|
62
|
+
const edgeTile = grid.getTile(edge.x, edge.y);
|
|
63
|
+
if (edgeTile === BTTile.Empty || edgeTile === tile) {
|
|
64
|
+
usableTileQueue.push(edge);
|
|
65
|
+
visited.set(edge.x, edge.y, id | 0b10000000);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return sameCellCount + usableCellCount >= this.instr.size;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import RegionShapeRule, { ShapeRegions } from '../../../rules/regionShapeRule.js';
|
|
2
|
+
import BTModule, { BTGridData } from '../data.js';
|
|
3
|
+
export default abstract class RegionShapeBTModule extends BTModule {
|
|
4
|
+
instr: RegionShapeRule;
|
|
5
|
+
constructor(instr: RegionShapeRule);
|
|
6
|
+
protected getShapeRegions(grid: BTGridData): ShapeRegions['regions'];
|
|
7
|
+
private visitArea;
|
|
8
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { normalizeShape, positionsToShape, shapeEquals, } from '../../../shapes.js';
|
|
2
|
+
import BTModule, { BTTile, IntArray2D, colorToBTTile, } from '../data.js';
|
|
3
|
+
export default class RegionShapeBTModule extends BTModule {
|
|
4
|
+
instr;
|
|
5
|
+
constructor(instr) {
|
|
6
|
+
super();
|
|
7
|
+
this.instr = instr;
|
|
8
|
+
}
|
|
9
|
+
getShapeRegions(grid) {
|
|
10
|
+
// TODO: This is extremely slow, because it doesn't check shapes when shapes are not fully enclosed
|
|
11
|
+
const visited = IntArray2D.create(grid.width, grid.height);
|
|
12
|
+
const regions = [];
|
|
13
|
+
for (let y = 0; y < grid.height; y++) {
|
|
14
|
+
for (let x = 0; x < grid.width; x++) {
|
|
15
|
+
const tile = grid.getTile(x, y);
|
|
16
|
+
if (tile !== colorToBTTile(this.instr.color) || visited.get(x, y))
|
|
17
|
+
continue;
|
|
18
|
+
const positions = this.visitArea(grid, tile, visited, { x, y });
|
|
19
|
+
if (!positions)
|
|
20
|
+
continue;
|
|
21
|
+
const shape = normalizeShape(positionsToShape(positions, this.instr.color));
|
|
22
|
+
const existing = regions.find(island => shapeEquals(island.shape, shape));
|
|
23
|
+
if (existing) {
|
|
24
|
+
existing.count++;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
regions.push({ positions, shape, count: 1 });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return regions;
|
|
32
|
+
}
|
|
33
|
+
visitArea(grid, tile, visited, pos) {
|
|
34
|
+
const positions = [pos];
|
|
35
|
+
const sameTileQueue = [pos];
|
|
36
|
+
let incomplete = false;
|
|
37
|
+
visited.set(pos.x, pos.y, 1);
|
|
38
|
+
// Count same tile
|
|
39
|
+
while (sameTileQueue.length > 0) {
|
|
40
|
+
const curPos = sameTileQueue.pop();
|
|
41
|
+
for (const edge of grid.getEdges(curPos)) {
|
|
42
|
+
if (visited.get(edge.x, edge.y))
|
|
43
|
+
continue;
|
|
44
|
+
const edgeTile = grid.getTile(edge.x, edge.y);
|
|
45
|
+
if (edgeTile === BTTile.Empty) {
|
|
46
|
+
incomplete = true;
|
|
47
|
+
}
|
|
48
|
+
else if (edgeTile === tile) {
|
|
49
|
+
positions.push(edge);
|
|
50
|
+
sameTileQueue.push(edge);
|
|
51
|
+
visited.set(edge.x, edge.y, 1);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return incomplete ? null : positions;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import SameShapeRule from '../../../rules/sameShapeRule.js';
|
|
2
|
+
import { BTGridData, CheckResult } from '../data.js';
|
|
3
|
+
import RegionShapeBTModule from './regionShape.js';
|
|
4
|
+
export default class SameShapeBTModule extends RegionShapeBTModule {
|
|
5
|
+
instr: SameShapeRule;
|
|
6
|
+
constructor(instr: SameShapeRule);
|
|
7
|
+
checkGlobal(grid: BTGridData): CheckResult | false;
|
|
8
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import RegionShapeBTModule from './regionShape.js';
|
|
2
|
+
export default class SameShapeBTModule extends RegionShapeBTModule {
|
|
3
|
+
instr;
|
|
4
|
+
constructor(instr) {
|
|
5
|
+
super(instr);
|
|
6
|
+
this.instr = instr;
|
|
7
|
+
}
|
|
8
|
+
checkGlobal(grid) {
|
|
9
|
+
const regions = this.getShapeRegions(grid);
|
|
10
|
+
return regions.length <= 1
|
|
11
|
+
? { tilesNeedCheck: null, ratings: null }
|
|
12
|
+
: false;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import SymbolsPerRegionRule from '../../../rules/symbolsPerRegionRule.js';
|
|
2
|
+
import Symbol from '../../../symbols/symbol.js';
|
|
3
|
+
import BTModule, { BTGridData, CheckResult } from '../data.js';
|
|
4
|
+
export default class SymbolsPerRegionBTModule extends BTModule {
|
|
5
|
+
instr: SymbolsPerRegionRule;
|
|
6
|
+
private symbolCount;
|
|
7
|
+
constructor(instr: SymbolsPerRegionRule, width: number, height: number, allSymbols: Symbol[]);
|
|
8
|
+
checkGlobal(grid: BTGridData): CheckResult | false;
|
|
9
|
+
private visitArea;
|
|
10
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Comparison } from '../../../primitives.js';
|
|
2
|
+
import BTModule, { BTTile, IntArray2D, colorToBTTile, } from '../data.js';
|
|
3
|
+
export default class SymbolsPerRegionBTModule extends BTModule {
|
|
4
|
+
instr;
|
|
5
|
+
symbolCount;
|
|
6
|
+
constructor(instr, width, height, allSymbols) {
|
|
7
|
+
super();
|
|
8
|
+
this.instr = instr;
|
|
9
|
+
this.symbolCount = IntArray2D.create(width, height);
|
|
10
|
+
for (const symbol of allSymbols) {
|
|
11
|
+
const symbolX = Math.floor(symbol.x);
|
|
12
|
+
const symbolY = Math.floor(symbol.y);
|
|
13
|
+
this.symbolCount.set(symbolX, symbolY, this.symbolCount.get(symbolX, symbolY) + 1);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
checkGlobal(grid) {
|
|
17
|
+
const color = colorToBTTile(this.instr.color);
|
|
18
|
+
const visited = IntArray2D.create(grid.width, grid.height);
|
|
19
|
+
let id = 0;
|
|
20
|
+
for (let y = 0; y < grid.height; y++) {
|
|
21
|
+
for (let x = 0; x < grid.width; x++) {
|
|
22
|
+
if (visited.get(x, y) & 0b01111111)
|
|
23
|
+
continue;
|
|
24
|
+
if (grid.getTile(x, y) !== color)
|
|
25
|
+
continue;
|
|
26
|
+
id += 1;
|
|
27
|
+
if (id > 127)
|
|
28
|
+
throw new Error('Too many regions!');
|
|
29
|
+
if (!this.visitArea(grid, color, visited, { x, y }, id))
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return { tilesNeedCheck: null, ratings: null };
|
|
34
|
+
}
|
|
35
|
+
visitArea(grid, tile, visited, pos, id) {
|
|
36
|
+
const sameTileQueue = [pos];
|
|
37
|
+
const usableTileQueue = [];
|
|
38
|
+
let completed = 0;
|
|
39
|
+
let possible = 0;
|
|
40
|
+
visited.set(pos.x, pos.y, id);
|
|
41
|
+
// Count same tile
|
|
42
|
+
while (sameTileQueue.length > 0) {
|
|
43
|
+
const curPos = sameTileQueue.pop();
|
|
44
|
+
completed += this.symbolCount.get(curPos.x, curPos.y);
|
|
45
|
+
for (const edge of grid.getEdges(curPos)) {
|
|
46
|
+
if ((visited.get(edge.x, edge.y) & 0b01111111) === id)
|
|
47
|
+
continue;
|
|
48
|
+
const edgeTile = grid.getTile(edge.x, edge.y);
|
|
49
|
+
if (edgeTile === BTTile.Empty) {
|
|
50
|
+
usableTileQueue.push(edge);
|
|
51
|
+
visited.set(edge.x, edge.y, id | 0b10000000);
|
|
52
|
+
}
|
|
53
|
+
else if (edgeTile === tile) {
|
|
54
|
+
sameTileQueue.push(edge);
|
|
55
|
+
visited.set(edge.x, edge.y, id);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (completed > this.instr.count) {
|
|
60
|
+
return this.instr.comparison === Comparison.AtLeast;
|
|
61
|
+
}
|
|
62
|
+
if (this.instr.comparison === Comparison.AtMost)
|
|
63
|
+
return true;
|
|
64
|
+
// Count usable tile
|
|
65
|
+
while (usableTileQueue.length > 0) {
|
|
66
|
+
const curPos = usableTileQueue.pop();
|
|
67
|
+
possible += this.symbolCount.get(curPos.x, curPos.y);
|
|
68
|
+
if (completed + possible >= this.instr.count)
|
|
69
|
+
return true;
|
|
70
|
+
for (const edge of grid.getEdges(curPos)) {
|
|
71
|
+
if ((visited.get(edge.x, edge.y) & 0b01111111) === id)
|
|
72
|
+
continue;
|
|
73
|
+
const edgeTile = grid.getTile(edge.x, edge.y);
|
|
74
|
+
if (edgeTile === BTTile.Empty || edgeTile === tile) {
|
|
75
|
+
usableTileQueue.push(edge);
|
|
76
|
+
visited.set(edge.x, edge.y, id | 0b10000000);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return completed + possible >= this.instr.count;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import UniqueShapeRule from '../../../rules/uniqueShapeRule.js';
|
|
2
|
+
import { BTGridData, CheckResult } from '../data.js';
|
|
3
|
+
import RegionShapeBTModule from './regionShape.js';
|
|
4
|
+
export default class UniqueShapeBTModule extends RegionShapeBTModule {
|
|
5
|
+
instr: UniqueShapeRule;
|
|
6
|
+
constructor(instr: UniqueShapeRule);
|
|
7
|
+
checkGlobal(grid: BTGridData): CheckResult | false;
|
|
8
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import RegionShapeBTModule from './regionShape.js';
|
|
2
|
+
export default class UniqueShapeBTModule extends RegionShapeBTModule {
|
|
3
|
+
instr;
|
|
4
|
+
constructor(instr) {
|
|
5
|
+
super(instr);
|
|
6
|
+
this.instr = instr;
|
|
7
|
+
}
|
|
8
|
+
checkGlobal(grid) {
|
|
9
|
+
const regions = this.getShapeRegions(grid);
|
|
10
|
+
return regions.every(r => r.count === 1)
|
|
11
|
+
? { tilesNeedCheck: null, ratings: null }
|
|
12
|
+
: false;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Position } from '../../../primitives.js';
|
|
2
|
+
import AreaNumberSymbol from '../../../symbols/areaNumberSymbol.js';
|
|
3
|
+
import BTModule, { BTGridData, CheckResult } from '../data.js';
|
|
4
|
+
export default class AreaNumberBTModule extends BTModule {
|
|
5
|
+
instr: AreaNumberSymbol;
|
|
6
|
+
constructor(instr: AreaNumberSymbol);
|
|
7
|
+
checkGlobal(grid: BTGridData): CheckResult | false;
|
|
8
|
+
checkLocal(grid: BTGridData, positions: Position[]): CheckResult | boolean;
|
|
9
|
+
}
|