@logic-pad/core 0.26.2 → 0.27.0
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 +3263 -3264
- package/dist/benchmark/helper.d.ts +22 -0
- package/dist/benchmark/helper.js +46 -0
- package/dist/benchmark/prepareBench.d.ts +1 -0
- package/dist/benchmark/prepareBench.js +154 -0
- package/dist/benchmark/runBench.d.ts +1 -0
- package/dist/benchmark/runBench.js +224 -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 +37 -0
- package/dist/src/data/rules/symbolsPerRegionRule.js +194 -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 +102 -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 +3 -1
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import BTModule, { BTTile, IntArray2D, createOneTileResult, getOppositeColor, } from '../data.js';
|
|
2
|
+
export default class ViewpointBTModule extends BTModule {
|
|
3
|
+
instr;
|
|
4
|
+
constructor(instr) {
|
|
5
|
+
super();
|
|
6
|
+
this.instr = instr;
|
|
7
|
+
}
|
|
8
|
+
checkGlobal(grid) {
|
|
9
|
+
const tile = grid.getTile(this.instr.x, this.instr.y);
|
|
10
|
+
if (tile === BTTile.Empty)
|
|
11
|
+
return createOneTileResult(grid, { x: this.instr.x, y: this.instr.y });
|
|
12
|
+
const tilesNeedCheck = IntArray2D.create(grid.width, grid.height);
|
|
13
|
+
const ratings = [];
|
|
14
|
+
let completed = 1;
|
|
15
|
+
let possible = 1;
|
|
16
|
+
const traverse = (dirX, dirY) => {
|
|
17
|
+
let connected = true;
|
|
18
|
+
let x = this.instr.x + dirX;
|
|
19
|
+
let y = this.instr.y + dirY;
|
|
20
|
+
while (grid.isInBound(x, y)) {
|
|
21
|
+
const curTile = grid.getTile(x, y);
|
|
22
|
+
if (connected) {
|
|
23
|
+
if (tile === curTile) {
|
|
24
|
+
completed += 1;
|
|
25
|
+
if (completed > this.instr.number)
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
if (curTile === BTTile.Empty) {
|
|
30
|
+
tilesNeedCheck.set(x, y, 1);
|
|
31
|
+
ratings.push({ pos: { x, y }, score: 1 });
|
|
32
|
+
}
|
|
33
|
+
connected = false;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (getOppositeColor(tile) === curTile ||
|
|
37
|
+
curTile === BTTile.NonExist)
|
|
38
|
+
break;
|
|
39
|
+
possible += 1;
|
|
40
|
+
x += dirX;
|
|
41
|
+
y += dirY;
|
|
42
|
+
}
|
|
43
|
+
return false;
|
|
44
|
+
};
|
|
45
|
+
if (traverse(-1, 0) || traverse(1, 0) || traverse(0, -1) || traverse(0, 1))
|
|
46
|
+
return false;
|
|
47
|
+
if (possible < this.instr.number)
|
|
48
|
+
return false;
|
|
49
|
+
return { tilesNeedCheck, ratings };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import EventIteratingSolver from '../eventIteratingSolver.js';
|
|
2
|
+
import GridData from '../../grid.js';
|
|
3
|
+
import Instruction from '../../instruction.js';
|
|
4
|
+
export default class CspuzSolver extends EventIteratingSolver {
|
|
5
|
+
private static readonly supportedInstrs;
|
|
6
|
+
readonly id = "cspuz";
|
|
7
|
+
readonly author = "semiexp";
|
|
8
|
+
readonly description = "A blazingly fast WebAssembly solver that supports most rules and symbols (including underclued).";
|
|
9
|
+
protected createWorker(): Worker;
|
|
10
|
+
isGridSupported(grid: GridData): boolean;
|
|
11
|
+
isInstructionSupported(grid: GridData, instruction: Instruction): boolean;
|
|
12
|
+
isEnvironmentSupported(): Promise<boolean>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { instance as banPatternInstance } from '../../rules/banPatternRule.js';
|
|
2
|
+
import { instance as cellCountInstance } from '../../rules/cellCountRule.js';
|
|
3
|
+
import { instance as regionAreaInstance } from '../../rules/regionAreaRule.js';
|
|
4
|
+
import { instance as sameShapeInstance } from '../../rules/sameShapeRule.js';
|
|
5
|
+
import { instance as symbolsPerRegionInstance } from '../../rules/symbolsPerRegionRule.js';
|
|
6
|
+
import { instance as undercluedInstance } from '../../rules/undercluedRule.js';
|
|
7
|
+
import { instance as uniqueShapeInstance } from '../../rules/uniqueShapeRule.js';
|
|
8
|
+
import { instance as offByXInstance } from '../../rules/offByXRule.js';
|
|
9
|
+
import AreaNumberSymbol, { instance as areaNumberInstance, } from '../../symbols/areaNumberSymbol.js';
|
|
10
|
+
import { instance as dartInstance } from '../../symbols/dartSymbol.js';
|
|
11
|
+
import GalaxySymbol, { instance as galaxyInstance, } from '../../symbols/galaxySymbol.js';
|
|
12
|
+
import LetterSymbol, { instance as letterInstance, } from '../../symbols/letterSymbol.js';
|
|
13
|
+
import LotusSymbol, { instance as lotusInstance, } from '../../symbols/lotusSymbol.js';
|
|
14
|
+
import { instance as minesweeperInstance } from '../../symbols/minesweeperSymbol.js';
|
|
15
|
+
import { instance as viewpointInstance } from '../../symbols/viewpointSymbol.js';
|
|
16
|
+
import { instance as connectAllInstance } from '../../rules/connectAllRule.js';
|
|
17
|
+
import { instance as unsupportedInstance } from '../../symbols/unsupportedSymbol.js';
|
|
18
|
+
import EventIteratingSolver from '../eventIteratingSolver.js';
|
|
19
|
+
import GridData from '../../grid.js';
|
|
20
|
+
import { Color } from '../../primitives.js';
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
22
|
+
('vite-apply-code-mod');
|
|
23
|
+
export default class CspuzSolver extends EventIteratingSolver {
|
|
24
|
+
static supportedInstrs = [
|
|
25
|
+
minesweeperInstance.id,
|
|
26
|
+
areaNumberInstance.id,
|
|
27
|
+
letterInstance.id,
|
|
28
|
+
dartInstance.id,
|
|
29
|
+
viewpointInstance.id,
|
|
30
|
+
lotusInstance.id,
|
|
31
|
+
galaxyInstance.id,
|
|
32
|
+
connectAllInstance.id,
|
|
33
|
+
banPatternInstance.id,
|
|
34
|
+
sameShapeInstance.id,
|
|
35
|
+
uniqueShapeInstance.id,
|
|
36
|
+
regionAreaInstance.id,
|
|
37
|
+
cellCountInstance.id,
|
|
38
|
+
offByXInstance.id,
|
|
39
|
+
undercluedInstance.id,
|
|
40
|
+
symbolsPerRegionInstance.id,
|
|
41
|
+
unsupportedInstance.id,
|
|
42
|
+
];
|
|
43
|
+
id = 'cspuz';
|
|
44
|
+
author = 'semiexp';
|
|
45
|
+
description = 'A blazingly fast WebAssembly solver that supports most rules and symbols (including underclued).';
|
|
46
|
+
createWorker() {
|
|
47
|
+
return new Worker(new URL('./cspuzWorker.js', import.meta.url), {
|
|
48
|
+
type: 'module',
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
isGridSupported(grid) {
|
|
52
|
+
if (!super.isGridSupported(grid)) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
// special handling for fixed gray tiles
|
|
56
|
+
if (grid.getTileCount(true, true, Color.Gray) > 0) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
// the solver doesn't count symbols correctly if some symbols are unsupported
|
|
60
|
+
if (grid.findSymbol(symbol => symbol.id === unsupportedInstance.id) &&
|
|
61
|
+
grid.findRule(rule => rule.id === symbolsPerRegionInstance.id)) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
isInstructionSupported(grid, instruction) {
|
|
67
|
+
if (instruction instanceof LotusSymbol ||
|
|
68
|
+
instruction instanceof GalaxySymbol) {
|
|
69
|
+
if (instruction.x % 1 !== 0 && instruction.y % 1 !== 0) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (instruction instanceof LotusSymbol ||
|
|
74
|
+
instruction instanceof GalaxySymbol ||
|
|
75
|
+
instruction instanceof AreaNumberSymbol ||
|
|
76
|
+
instruction instanceof LetterSymbol) {
|
|
77
|
+
if (instruction.x % 1 !== 0 || instruction.y % 1 !== 0) {
|
|
78
|
+
const minX = Math.floor(instruction.x);
|
|
79
|
+
const minY = Math.floor(instruction.y);
|
|
80
|
+
const maxX = Math.ceil(instruction.x);
|
|
81
|
+
const maxY = Math.ceil(instruction.y);
|
|
82
|
+
const connectedTiles = grid.connections.getConnectedTiles({
|
|
83
|
+
x: minX,
|
|
84
|
+
y: minY,
|
|
85
|
+
});
|
|
86
|
+
if (connectedTiles.some(tile => tile.x === minX && tile.y === maxY) &&
|
|
87
|
+
connectedTiles.some(tile => tile.x === maxX && tile.y === minY) &&
|
|
88
|
+
connectedTiles.some(tile => tile.x === maxX && tile.y === maxY)) {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
let color = Color.Gray;
|
|
92
|
+
for (let i = 0; i < 4; i++) {
|
|
93
|
+
const x = i % 2 === 0 ? minX : maxX;
|
|
94
|
+
const y = i < 2 ? minY : maxY;
|
|
95
|
+
const tile = grid.getTile(x, y);
|
|
96
|
+
if (!tile.fixed || !tile.exists) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
if (tile.color !== Color.Gray) {
|
|
100
|
+
if (color === Color.Gray) {
|
|
101
|
+
color = tile.color;
|
|
102
|
+
}
|
|
103
|
+
else if (color !== tile.color) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return CspuzSolver.supportedInstrs.includes(instruction.id);
|
|
112
|
+
}
|
|
113
|
+
async isEnvironmentSupported() {
|
|
114
|
+
try {
|
|
115
|
+
for await (const _ of this.solve(GridData.create(['.']))) {
|
|
116
|
+
// do nothing
|
|
117
|
+
}
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
catch (_ex) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { solveLogicPad } from 'logic-pad-solver-core';
|
|
2
|
+
import { Serializer } from '../../serializer/allSerializers.js';
|
|
3
|
+
import { gridToJson } from './jsonify.js';
|
|
4
|
+
import { instance as undercluedInstance } from '../../rules/undercluedRule.js';
|
|
5
|
+
import { Color } from '../../primitives.js';
|
|
6
|
+
function stringToColor(str) {
|
|
7
|
+
if (str === 'dark') {
|
|
8
|
+
return Color.Dark;
|
|
9
|
+
}
|
|
10
|
+
else if (str === 'light') {
|
|
11
|
+
return Color.Light;
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
return Color.Gray;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function postSolution(grid, solverResult) {
|
|
18
|
+
if (solverResult === null) {
|
|
19
|
+
postMessage(null);
|
|
20
|
+
}
|
|
21
|
+
else if ('error' in solverResult) {
|
|
22
|
+
throw new Error(solverResult.error);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
const solution = grid.withTiles(tiles => {
|
|
26
|
+
for (const [y, row] of solverResult.entries()) {
|
|
27
|
+
for (const [x, color] of row.entries()) {
|
|
28
|
+
tiles[y][x] = tiles[y][x].withColor(stringToColor(color));
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return tiles;
|
|
32
|
+
});
|
|
33
|
+
postMessage(Serializer.stringifyGrid(solution));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
onmessage = e => {
|
|
37
|
+
const grid = Serializer.parseGrid(e.data);
|
|
38
|
+
const isUnderclued = !!grid.findRule(r => r.id === undercluedInstance.id);
|
|
39
|
+
const puzzleData = gridToJson(grid);
|
|
40
|
+
const solverResult = solveLogicPad(puzzleData, isUnderclued);
|
|
41
|
+
postSolution(grid, solverResult);
|
|
42
|
+
if (isUnderclued) {
|
|
43
|
+
postMessage(null);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
// Make use of the underclued mode to determine solution uniqueness
|
|
47
|
+
if (solverResult !== null && !('error' in solverResult) && !isUnderclued) {
|
|
48
|
+
const undercluedResult = solveLogicPad(puzzleData, true);
|
|
49
|
+
if (undercluedResult === null) {
|
|
50
|
+
postMessage(undefined); // Shouldn't happen because underclued grids should always be solvable
|
|
51
|
+
}
|
|
52
|
+
else if ('error' in undercluedResult) {
|
|
53
|
+
throw new Error(undercluedResult.error);
|
|
54
|
+
}
|
|
55
|
+
else if (undercluedResult.every((row, y) => row.every((cell, x) => cell !== null || !grid.getTile(x, y).exists))) {
|
|
56
|
+
postMessage(null);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
let tweaked = false;
|
|
60
|
+
for (const [y, row] of undercluedResult.entries()) {
|
|
61
|
+
for (const [x, color] of row.entries()) {
|
|
62
|
+
if (color !== null) {
|
|
63
|
+
puzzleData.tiles[y][x].fixed = true;
|
|
64
|
+
puzzleData.tiles[y][x].color = color;
|
|
65
|
+
}
|
|
66
|
+
else if (!tweaked && puzzleData.tiles[y][x].exists) {
|
|
67
|
+
const positions = grid.connections.getConnectedTiles({ x, y });
|
|
68
|
+
const newColor = solverResult[y][x] === 'dark' ? 'light' : 'dark';
|
|
69
|
+
positions.forEach(({ x: px, y: py }) => {
|
|
70
|
+
puzzleData.tiles[py][px].fixed = true;
|
|
71
|
+
puzzleData.tiles[py][px].color = newColor;
|
|
72
|
+
});
|
|
73
|
+
tweaked = true;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const secondResult = solveLogicPad(puzzleData, false);
|
|
78
|
+
postSolution(grid, secondResult);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
postMessage(undefined);
|
|
82
|
+
};
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { Color, Comparison } from '../../primitives.js';
|
|
2
|
+
import BanPatternRule from '../../rules/banPatternRule.js';
|
|
3
|
+
import CellCountRule from '../../rules/cellCountRule.js';
|
|
4
|
+
import ConnectAllRule from '../../rules/connectAllRule.js';
|
|
5
|
+
import OffByXRule from '../../rules/offByXRule.js';
|
|
6
|
+
import RegionAreaRule from '../../rules/regionAreaRule.js';
|
|
7
|
+
import SameShapeRule from '../../rules/sameShapeRule.js';
|
|
8
|
+
import SymbolsPerRegionRule from '../../rules/symbolsPerRegionRule.js';
|
|
9
|
+
import UndercluedRule from '../../rules/undercluedRule.js';
|
|
10
|
+
import UniqueShapeRule from '../../rules/uniqueShapeRule.js';
|
|
11
|
+
import { instance as areaNumberInstance, } from '../../symbols/areaNumberSymbol.js';
|
|
12
|
+
import { instance as dartInstance, } from '../../symbols/dartSymbol.js';
|
|
13
|
+
import { instance as galaxyInstance, } from '../../symbols/galaxySymbol.js';
|
|
14
|
+
import { instance as letterInstance, } from '../../symbols/letterSymbol.js';
|
|
15
|
+
import { instance as lotusInstance, } from '../../symbols/lotusSymbol.js';
|
|
16
|
+
import { instance as minesweeperInstance, } from '../../symbols/minesweeperSymbol.js';
|
|
17
|
+
import { instance as viewpointInstance, } from '../../symbols/viewpointSymbol.js';
|
|
18
|
+
import { instance as unsupportedInstance } from '../../symbols/unsupportedSymbol.js';
|
|
19
|
+
import TileData from '../../tile.js';
|
|
20
|
+
function canonizeTiles(tileData) {
|
|
21
|
+
const ret = [];
|
|
22
|
+
for (const row of tileData) {
|
|
23
|
+
const newRow = [];
|
|
24
|
+
for (const tile of row) {
|
|
25
|
+
if (tile.exists) {
|
|
26
|
+
newRow.push(tile);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
newRow.push(new TileData(true, false, Color.Gray));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
ret.push(newRow);
|
|
33
|
+
}
|
|
34
|
+
return ret;
|
|
35
|
+
}
|
|
36
|
+
export function gridToJson(grid) {
|
|
37
|
+
const rules = [];
|
|
38
|
+
for (const rule of grid.rules) {
|
|
39
|
+
if (rule instanceof ConnectAllRule) {
|
|
40
|
+
rules.push({
|
|
41
|
+
type: 'connectAll',
|
|
42
|
+
color: rule.color,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
else if (rule instanceof BanPatternRule) {
|
|
46
|
+
rules.push({
|
|
47
|
+
type: 'forbiddenPattern',
|
|
48
|
+
pattern: canonizeTiles(rule.pattern.tiles),
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
else if (rule instanceof SameShapeRule) {
|
|
52
|
+
rules.push({
|
|
53
|
+
type: 'sameShape',
|
|
54
|
+
color: rule.color,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
else if (rule instanceof UniqueShapeRule) {
|
|
58
|
+
rules.push({
|
|
59
|
+
type: 'uniqueShape',
|
|
60
|
+
color: rule.color,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
else if (rule instanceof RegionAreaRule) {
|
|
64
|
+
rules.push({
|
|
65
|
+
type: 'regionArea',
|
|
66
|
+
color: rule.color,
|
|
67
|
+
size: rule.size,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
else if (rule instanceof CellCountRule) {
|
|
71
|
+
rules.push({
|
|
72
|
+
type: 'cellCount',
|
|
73
|
+
color: rule.color,
|
|
74
|
+
count: rule.count,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
else if (rule instanceof OffByXRule) {
|
|
78
|
+
rules.push({
|
|
79
|
+
type: 'offByX',
|
|
80
|
+
number: rule.number,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
else if (rule instanceof UndercluedRule) {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
else if (rule instanceof SymbolsPerRegionRule) {
|
|
87
|
+
let kind;
|
|
88
|
+
if (rule.comparison === Comparison.Equal) {
|
|
89
|
+
kind = 'exactly';
|
|
90
|
+
}
|
|
91
|
+
else if (rule.comparison === Comparison.AtLeast) {
|
|
92
|
+
kind = 'atLeast';
|
|
93
|
+
}
|
|
94
|
+
else if (rule.comparison === Comparison.AtMost) {
|
|
95
|
+
kind = 'atMost';
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
throw new Error(`Unknown comparison (${rule.comparison})`);
|
|
99
|
+
}
|
|
100
|
+
rules.push({
|
|
101
|
+
type: 'symbolCount',
|
|
102
|
+
number: rule.count,
|
|
103
|
+
kind,
|
|
104
|
+
color: rule.color,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
else if (rule.necessaryForCompletion) {
|
|
108
|
+
throw new Error(`Unknown rule type (${rule.explanation})`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
for (const [rule, symbols] of grid.symbols) {
|
|
112
|
+
if (rule === minesweeperInstance.id) {
|
|
113
|
+
rules.push({
|
|
114
|
+
type: 'minesweeper',
|
|
115
|
+
tiles: symbols.map(s => ({
|
|
116
|
+
x: Math.floor(s.x),
|
|
117
|
+
y: Math.floor(s.y),
|
|
118
|
+
number: s.number,
|
|
119
|
+
})),
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
else if (rule === areaNumberInstance.id) {
|
|
123
|
+
rules.push({
|
|
124
|
+
type: 'number',
|
|
125
|
+
tiles: symbols.map(s => ({
|
|
126
|
+
x: Math.floor(s.x),
|
|
127
|
+
y: Math.floor(s.y),
|
|
128
|
+
number: s.number,
|
|
129
|
+
})),
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
else if (rule === letterInstance.id) {
|
|
133
|
+
rules.push({
|
|
134
|
+
type: 'letter',
|
|
135
|
+
tiles: symbols.map(s => ({
|
|
136
|
+
x: Math.floor(s.x),
|
|
137
|
+
y: Math.floor(s.y),
|
|
138
|
+
letter: s.letter,
|
|
139
|
+
})),
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
else if (rule === dartInstance.id) {
|
|
143
|
+
rules.push({
|
|
144
|
+
type: 'dart',
|
|
145
|
+
tiles: symbols.map(s => ({
|
|
146
|
+
x: Math.floor(s.x),
|
|
147
|
+
y: Math.floor(s.y),
|
|
148
|
+
orientation: s.orientation,
|
|
149
|
+
number: s.number,
|
|
150
|
+
})),
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
else if (rule === viewpointInstance.id) {
|
|
154
|
+
rules.push({
|
|
155
|
+
type: 'viewpoint',
|
|
156
|
+
tiles: symbols.map(s => ({
|
|
157
|
+
x: Math.floor(s.x),
|
|
158
|
+
y: Math.floor(s.y),
|
|
159
|
+
number: s.number,
|
|
160
|
+
})),
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
else if (rule === lotusInstance.id) {
|
|
164
|
+
const tiles = symbols.map(s => ({
|
|
165
|
+
x: Math.round(s.x * 2),
|
|
166
|
+
y: Math.round(s.y * 2),
|
|
167
|
+
orientation: s.orientation,
|
|
168
|
+
}));
|
|
169
|
+
rules.push({
|
|
170
|
+
type: 'lotus',
|
|
171
|
+
tiles,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
else if (rule === galaxyInstance.id) {
|
|
175
|
+
const tiles = symbols.map(s => ({
|
|
176
|
+
x: Math.round(s.x * 2),
|
|
177
|
+
y: Math.round(s.y * 2),
|
|
178
|
+
}));
|
|
179
|
+
rules.push({
|
|
180
|
+
type: 'galaxy',
|
|
181
|
+
tiles,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
else if (rule === unsupportedInstance.id) {
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
else if (symbols.some(s => s.necessaryForCompletion)) {
|
|
188
|
+
throw new Error(`Unknown symbol type: ${rule}`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
const connections = grid.connections.edges.map(edge => {
|
|
192
|
+
return {
|
|
193
|
+
x1: edge.x1,
|
|
194
|
+
y1: edge.y1,
|
|
195
|
+
x2: edge.x2,
|
|
196
|
+
y2: edge.y2,
|
|
197
|
+
};
|
|
198
|
+
});
|
|
199
|
+
const tiles = grid.tiles.map(row => {
|
|
200
|
+
return row.map(tile => {
|
|
201
|
+
return {
|
|
202
|
+
exists: tile.exists,
|
|
203
|
+
fixed: tile.fixed,
|
|
204
|
+
color: tile.color,
|
|
205
|
+
};
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
return {
|
|
209
|
+
width: grid.width,
|
|
210
|
+
height: grid.height,
|
|
211
|
+
connections,
|
|
212
|
+
tiles,
|
|
213
|
+
rules,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import GridData from '../grid.js';
|
|
2
|
+
import Solver from './solver.js';
|
|
3
|
+
export default abstract class EventIteratingSolver extends Solver {
|
|
4
|
+
readonly supportsCancellation = true;
|
|
5
|
+
protected abstract createWorker(): Worker;
|
|
6
|
+
protected isEnvironmentSupported(): Promise<boolean>;
|
|
7
|
+
solve(grid: GridData, abortSignal?: AbortSignal): AsyncGenerator<GridData | null>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Serializer } from '../serializer/allSerializers.js';
|
|
2
|
+
import Solver from './solver.js';
|
|
3
|
+
import { EventIterator } from 'event-iterator';
|
|
4
|
+
export default class EventIteratingSolver extends Solver {
|
|
5
|
+
supportsCancellation = true;
|
|
6
|
+
isEnvironmentSupported() {
|
|
7
|
+
try {
|
|
8
|
+
const worker = this.createWorker();
|
|
9
|
+
worker.terminate();
|
|
10
|
+
return Promise.resolve(true);
|
|
11
|
+
}
|
|
12
|
+
catch (_ex) {
|
|
13
|
+
return Promise.resolve(false);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
async *solve(grid, abortSignal) {
|
|
17
|
+
const worker = this.createWorker();
|
|
18
|
+
let terminateHandler;
|
|
19
|
+
try {
|
|
20
|
+
const iterator = new EventIterator(({ push, stop, fail }) => {
|
|
21
|
+
terminateHandler = () => {
|
|
22
|
+
worker.terminate();
|
|
23
|
+
stop();
|
|
24
|
+
};
|
|
25
|
+
abortSignal?.addEventListener('abort', terminateHandler);
|
|
26
|
+
worker.postMessage(Serializer.stringifyGrid(grid.resetTiles()));
|
|
27
|
+
worker.addEventListener('message', (e) => {
|
|
28
|
+
if (e.data) {
|
|
29
|
+
push(Serializer.parseGrid(e.data));
|
|
30
|
+
}
|
|
31
|
+
else if (e.data === null) {
|
|
32
|
+
push(null);
|
|
33
|
+
stop(); // Stop after the first signal for out of solutions
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
stop();
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
worker.addEventListener('error', (e) => {
|
|
40
|
+
alert(`Error while solving!\n${e.message}`);
|
|
41
|
+
fail(e);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
for await (const solution of iterator) {
|
|
45
|
+
yield solution;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
worker.terminate();
|
|
50
|
+
if (terminateHandler)
|
|
51
|
+
abortSignal?.removeEventListener('abort', terminateHandler);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { CachedAccess } from '../dataHelper.js';
|
|
2
|
+
import GridData from '../grid.js';
|
|
3
|
+
import { Instruction } from '../../index.js';
|
|
4
|
+
/**
|
|
5
|
+
* Base class that all solvers must extend.
|
|
6
|
+
*/
|
|
7
|
+
export default abstract class Solver {
|
|
8
|
+
/**
|
|
9
|
+
* The unique identifier of the solver.
|
|
10
|
+
*
|
|
11
|
+
* This is also displayed to the user when selecting a solver.
|
|
12
|
+
*/
|
|
13
|
+
abstract get id(): string;
|
|
14
|
+
/**
|
|
15
|
+
* The author(s) of the solver.
|
|
16
|
+
*/
|
|
17
|
+
abstract get author(): string;
|
|
18
|
+
/**
|
|
19
|
+
* A short paragraph describing when the user should use this solver.
|
|
20
|
+
*/
|
|
21
|
+
abstract get description(): string;
|
|
22
|
+
/**
|
|
23
|
+
* Whether the solver supports cancellation. If `true`, the solver must respond to the abort signal if it is provided.
|
|
24
|
+
*/
|
|
25
|
+
abstract get supportsCancellation(): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Solve the given grid. The implementation should delegate long-running tasks to a worker thread and yield solutions
|
|
28
|
+
* asynchronously.
|
|
29
|
+
*
|
|
30
|
+
* The solver must yield at least once, otherwise the UI will not update.
|
|
31
|
+
*
|
|
32
|
+
* If the solver finds no solution other than those already yielded, it should yield `null`. Yielding `null` on the
|
|
33
|
+
* first iteration indicates that the grid is unsolvable. Yielding `null` on the second iteration indicates that the
|
|
34
|
+
* solution is unique.
|
|
35
|
+
*
|
|
36
|
+
* If the solve finds the trivial solution of not filling any tiles, such as in the case of an underclued grid with
|
|
37
|
+
* too many alternate solutions, it must yield the solution instead of yielding `null`.
|
|
38
|
+
*
|
|
39
|
+
* In the current UI implementation, the solver will be terminated after yielding `null`, or after 2 iterations if
|
|
40
|
+
* `null` is never yielded. The solver should perform any necessary cleanup in the `finally` block of the generator.
|
|
41
|
+
*
|
|
42
|
+
* @param grid The grid to solve. The provided grid is guaranteed to be supported by the solver. Some tiles in the
|
|
43
|
+
* grid may already be filled by the user. It is up to the solver to decide whether to respect these tiles or not.
|
|
44
|
+
* @param abortSignal An optional signal that the solver should subscribe to in order to cancel the operation. If the
|
|
45
|
+
* solver does not support cancellation, it should ignore this parameter.
|
|
46
|
+
*/
|
|
47
|
+
abstract solve(grid: GridData, abortSignal?: AbortSignal): AsyncGenerator<GridData | null>;
|
|
48
|
+
/**
|
|
49
|
+
* Check if the solver supports the current browser environment. This method is called once when the user first clicks
|
|
50
|
+
* the "Solve" button, and the result is cached for the duration of the editor session.
|
|
51
|
+
*
|
|
52
|
+
* The `solve` method will not be called if this method returns `false`, and a message will be displayed to the user
|
|
53
|
+
* indicating that the solver is not supported.
|
|
54
|
+
*
|
|
55
|
+
* @returns A promise that resolves to `true` if the environment is supported, or `false` otherwise.
|
|
56
|
+
*/
|
|
57
|
+
protected isEnvironmentSupported(): Promise<boolean>;
|
|
58
|
+
readonly environmentCheck: CachedAccess<Promise<boolean>>;
|
|
59
|
+
/**
|
|
60
|
+
* Check if the solver supports the given instruction. This is used to render a small indication in the UI for each
|
|
61
|
+
* instruction in the editor.
|
|
62
|
+
*
|
|
63
|
+
* @param instructionId The unique identifier of the instruction.
|
|
64
|
+
*/
|
|
65
|
+
isInstructionSupported(_grid: GridData, instruction: Instruction): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Check if the solver supports the given grid. This methid is frequently called when the user changes the grid, and
|
|
68
|
+
* the result is used to enable or disable the "Solve" button.
|
|
69
|
+
*
|
|
70
|
+
* The `solve` method will not be called if this method returns `false`, and a message will be displayed to the user
|
|
71
|
+
* indicating that the grid is not supported by this solver.
|
|
72
|
+
*
|
|
73
|
+
* @param grid The grid to check.
|
|
74
|
+
* @returns `true` if the grid is supported, or `false` otherwise.
|
|
75
|
+
*/
|
|
76
|
+
isGridSupported(grid: GridData): boolean;
|
|
77
|
+
}
|