@logic-pad/core 0.7.0 → 0.10.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 +72 -13
- package/dist/data/grid.js +1 -0
- package/dist/data/primitives.d.ts +2 -1
- package/dist/data/primitives.js +2 -0
- package/dist/data/rules/banPatternRule.js +8 -0
- package/dist/data/rules/musicGridRule.d.ts +1 -1
- package/dist/data/rules/musicGridRule.js +2 -7
- package/dist/data/rules/wrapAroundRule.d.ts +0 -2
- package/dist/data/rules/wrapAroundRule.js +124 -58
- package/dist/data/solver/allSolvers.js +2 -0
- package/dist/data/solver/backtrack/backtrackSolver.d.ts +2 -1
- package/dist/data/solver/backtrack/backtrackSolver.js +10 -2
- package/dist/data/solver/backtrack/backtrackWorker.js +11 -0
- package/dist/data/solver/backtrack/symbols/focus.d.ts +9 -0
- package/dist/data/solver/backtrack/symbols/focus.js +59 -0
- package/dist/data/solver/cspuz/cspuzSolver.d.ts +12 -0
- package/dist/data/solver/cspuz/cspuzSolver.js +113 -0
- package/dist/data/solver/cspuz/cspuzWorker.d.ts +1 -0
- package/dist/data/solver/cspuz/cspuzWorker.js +44 -0
- package/dist/data/solver/cspuz/jsonify.d.ts +3 -0
- package/dist/data/solver/cspuz/jsonify.js +211 -0
- package/dist/data/solver/eventIteratingSolver.d.ts +3 -2
- package/dist/data/solver/eventIteratingSolver.js +17 -3
- package/dist/data/solver/solver.d.ts +11 -6
- package/dist/data/solver/universal/universalSolver.d.ts +1 -0
- package/dist/data/solver/universal/universalSolver.js +6 -0
- package/dist/data/solver/universal/universalWorker.js +5 -0
- package/dist/data/solver/z3/z3Solver.d.ts +3 -1
- package/dist/data/solver/z3/z3Solver.js +13 -1
- package/dist/data/symbols/directionLinkerSymbol.js +22 -13
- package/dist/data/symbols/focusSymbol.d.ts +30 -0
- package/dist/data/symbols/focusSymbol.js +110 -0
- package/dist/data/symbols/minesweeperSymbol.d.ts +1 -1
- package/dist/data/symbols/minesweeperSymbol.js +9 -2
- package/dist/data/symbols/symbols.gen.d.ts +1 -0
- package/dist/data/symbols/symbols.gen.js +1 -0
- package/dist/data/symbols/viewpointSymbol.js +9 -11
- package/dist/index.d.ts +5 -1
- package/dist/index.js +5 -1
- package/package.json +1 -1
|
@@ -9,6 +9,7 @@ declare global {
|
|
|
9
9
|
// Generated by dts-bundle-generator v9.5.1
|
|
10
10
|
|
|
11
11
|
import { RegionConstrainer, SymbolGrid } from 'grilops';
|
|
12
|
+
import { PuzzleData } from 'logic-pad-solver-core';
|
|
12
13
|
import { Optimize, Solver as Solver$1, Z3LowLevel } from 'z3-solver';
|
|
13
14
|
import { z } from 'zod';
|
|
14
15
|
|
|
@@ -86,6 +87,7 @@ declare global {
|
|
|
86
87
|
None = 'none',
|
|
87
88
|
Wrap = 'wrap',
|
|
88
89
|
WrapReverse = 'wrap-reverse',
|
|
90
|
+
ReflectReverse = 'reflect-reverse',
|
|
89
91
|
}
|
|
90
92
|
export declare const WRAPPINGS: readonly Wrapping[];
|
|
91
93
|
export declare enum Direction {
|
|
@@ -567,7 +569,7 @@ declare global {
|
|
|
567
569
|
get configs(): readonly AnyConfig[] | null;
|
|
568
570
|
createExampleGrid(): GridData;
|
|
569
571
|
get searchVariants(): SearchVariant[];
|
|
570
|
-
validateGrid(
|
|
572
|
+
validateGrid(_grid: GridData): RuleState;
|
|
571
573
|
onSetGrid(
|
|
572
574
|
_oldGrid: GridData,
|
|
573
575
|
newGrid: GridData,
|
|
@@ -650,9 +652,7 @@ declare global {
|
|
|
650
652
|
readonly vertical: Wrapping;
|
|
651
653
|
private static readonly EXAMPLE_GRID_NONE;
|
|
652
654
|
private static readonly EXAMPLE_GRID_HORIZONTAL;
|
|
653
|
-
private static readonly EXAMPLE_GRID_HORIZONTAL_REVERSE;
|
|
654
655
|
private static readonly EXAMPLE_GRID_VERTICAL;
|
|
655
|
-
private static readonly EXAMPLE_GRID_VERTICAL_REVERSE;
|
|
656
656
|
private static readonly SEARCH_VARIANTS;
|
|
657
657
|
private static readonly CONFIGS;
|
|
658
658
|
/**
|
|
@@ -2034,9 +2034,6 @@ declare global {
|
|
|
2034
2034
|
stringifyPuzzle(puzzle: Puzzle): string;
|
|
2035
2035
|
parsePuzzle(input: string): Puzzle;
|
|
2036
2036
|
}
|
|
2037
|
-
export interface CancelRef {
|
|
2038
|
-
cancel?: () => void;
|
|
2039
|
-
}
|
|
2040
2037
|
/**
|
|
2041
2038
|
* Base class that all solvers must extend.
|
|
2042
2039
|
*/
|
|
@@ -2047,10 +2044,18 @@ declare global {
|
|
|
2047
2044
|
* This is also displayed to the user when selecting a solver.
|
|
2048
2045
|
*/
|
|
2049
2046
|
abstract get id(): string;
|
|
2047
|
+
/**
|
|
2048
|
+
* The author(s) of the solver.
|
|
2049
|
+
*/
|
|
2050
|
+
abstract get author(): string;
|
|
2050
2051
|
/**
|
|
2051
2052
|
* A short paragraph describing when the user should use this solver.
|
|
2052
2053
|
*/
|
|
2053
2054
|
abstract get description(): string;
|
|
2055
|
+
/**
|
|
2056
|
+
* Whether the solver supports cancellation. If `true`, the solver must respond to the abort signal if it is provided.
|
|
2057
|
+
*/
|
|
2058
|
+
abstract get supportsCancellation(): boolean;
|
|
2054
2059
|
/**
|
|
2055
2060
|
* Solve the given grid. The implementation should delegate long-running tasks to a worker thread and yield solutions
|
|
2056
2061
|
* asynchronously.
|
|
@@ -2066,12 +2071,12 @@ declare global {
|
|
|
2066
2071
|
*
|
|
2067
2072
|
* @param grid The grid to solve. The provided grid is guaranteed to be supported by the solver. Some tiles in the
|
|
2068
2073
|
* grid may already be filled by the user. It is up to the solver to decide whether to respect these tiles or not.
|
|
2069
|
-
* @param
|
|
2070
|
-
*
|
|
2074
|
+
* @param abortSignal An optional signal that the solver should subscribe to in order to cancel the operation. If the
|
|
2075
|
+
* solver does not support cancellation, it should ignore this parameter.
|
|
2071
2076
|
*/
|
|
2072
2077
|
abstract solve(
|
|
2073
2078
|
grid: GridData,
|
|
2074
|
-
|
|
2079
|
+
abortSignal?: AbortSignal
|
|
2075
2080
|
): AsyncGenerator<GridData | null>;
|
|
2076
2081
|
/**
|
|
2077
2082
|
* Check if the solver supports the current browser environment. This method is called once when the user first clicks
|
|
@@ -2104,17 +2109,19 @@ declare global {
|
|
|
2104
2109
|
}
|
|
2105
2110
|
export declare const allSolvers: Map<string, Solver>;
|
|
2106
2111
|
export declare abstract class EventIteratingSolver extends Solver {
|
|
2112
|
+
readonly supportsCancellation = true;
|
|
2107
2113
|
protected abstract createWorker(): Worker;
|
|
2108
2114
|
solve(
|
|
2109
2115
|
grid: GridData,
|
|
2110
|
-
|
|
2116
|
+
abortSignal?: AbortSignal
|
|
2111
2117
|
): AsyncGenerator<GridData | null>;
|
|
2112
2118
|
}
|
|
2113
2119
|
export declare class BacktrackSolver extends EventIteratingSolver {
|
|
2114
2120
|
private static readonly supportedInstrs;
|
|
2115
2121
|
readonly id = 'backtrack';
|
|
2122
|
+
readonly author = 'ALaggyDev';
|
|
2116
2123
|
readonly description =
|
|
2117
|
-
'Solves puzzles using backtracking with optimizations
|
|
2124
|
+
'Solves puzzles pretty fast using backtracking with optimizations. Support most rules and symbols (including underclued).';
|
|
2118
2125
|
protected createWorker(): Worker;
|
|
2119
2126
|
isInstructionSupported(instructionId: string): boolean;
|
|
2120
2127
|
}
|
|
@@ -2357,6 +2364,43 @@ declare global {
|
|
|
2357
2364
|
y: number
|
|
2358
2365
|
): Position$1 | null;
|
|
2359
2366
|
}
|
|
2367
|
+
export declare class FocusSymbol extends NumberSymbol {
|
|
2368
|
+
private static readonly CONFIGS;
|
|
2369
|
+
private static readonly EXAMPLE_GRID;
|
|
2370
|
+
/**
|
|
2371
|
+
* **Focus Numbers count directly adjacent cells of the same color**
|
|
2372
|
+
* @param x - The x-coordinate of the symbol.
|
|
2373
|
+
* @param y - The y-coordinate of the symbol.
|
|
2374
|
+
* @param number - The focus number.
|
|
2375
|
+
*/
|
|
2376
|
+
constructor(x: number, y: number, number: number);
|
|
2377
|
+
get id(): string;
|
|
2378
|
+
get placementStep(): number;
|
|
2379
|
+
get explanation(): string;
|
|
2380
|
+
get configs(): readonly AnyConfig[] | null;
|
|
2381
|
+
createExampleGrid(): GridData;
|
|
2382
|
+
countTiles(grid: GridData): {
|
|
2383
|
+
completed: number;
|
|
2384
|
+
possible: number;
|
|
2385
|
+
};
|
|
2386
|
+
copyWith({
|
|
2387
|
+
x,
|
|
2388
|
+
y,
|
|
2389
|
+
number,
|
|
2390
|
+
}: {
|
|
2391
|
+
x?: number;
|
|
2392
|
+
y?: number;
|
|
2393
|
+
number?: number;
|
|
2394
|
+
}): this;
|
|
2395
|
+
withNumber(number: number): this;
|
|
2396
|
+
}
|
|
2397
|
+
export declare class FocusBTModule extends BTModule {
|
|
2398
|
+
instr: FocusSymbol;
|
|
2399
|
+
private cachedCheckResult?;
|
|
2400
|
+
constructor(instr: FocusSymbol);
|
|
2401
|
+
checkGlobal(grid: BTGridData): CheckResult | false;
|
|
2402
|
+
private buildCheckAndRating;
|
|
2403
|
+
}
|
|
2360
2404
|
export declare class GalaxySymbol extends DirectionLinkerSymbol {
|
|
2361
2405
|
readonly x: number;
|
|
2362
2406
|
readonly y: number;
|
|
@@ -2464,7 +2508,7 @@ declare global {
|
|
|
2464
2508
|
private static readonly CONFIGS;
|
|
2465
2509
|
private static readonly EXAMPLE_GRID;
|
|
2466
2510
|
/**
|
|
2467
|
-
* **Minesweeper
|
|
2511
|
+
* **Minesweeper Numbers count opposite cells in 8 adjacent spaces**
|
|
2468
2512
|
*
|
|
2469
2513
|
* @param x - The x-coordinate of the symbol.
|
|
2470
2514
|
* @param y - The y-coordinate of the symbol.
|
|
@@ -2586,8 +2630,21 @@ declare global {
|
|
|
2586
2630
|
constructor(instr: ViewpointSymbol);
|
|
2587
2631
|
checkGlobal(grid: BTGridData): CheckResult | false;
|
|
2588
2632
|
}
|
|
2633
|
+
export declare class CspuzSolver extends EventIteratingSolver {
|
|
2634
|
+
private static readonly supportedInstrs;
|
|
2635
|
+
readonly id = 'cspuz';
|
|
2636
|
+
readonly author = 'semiexp';
|
|
2637
|
+
readonly description =
|
|
2638
|
+
'A blazingly fast WebAssembly solver that supports most rules and symbols (including underclued). No uniqueness check yet.';
|
|
2639
|
+
protected createWorker(): Worker;
|
|
2640
|
+
isGridSupported(grid: GridData): boolean;
|
|
2641
|
+
isInstructionSupported(instructionId: string): boolean;
|
|
2642
|
+
isEnvironmentSupported(): Promise<boolean>;
|
|
2643
|
+
}
|
|
2644
|
+
export declare function gridToJson(grid: GridData): PuzzleData;
|
|
2589
2645
|
export declare class UniversalSolver extends EventIteratingSolver {
|
|
2590
2646
|
readonly id = 'universal';
|
|
2647
|
+
readonly author = 'romain22222, Lysine';
|
|
2591
2648
|
readonly description =
|
|
2592
2649
|
'A backtracking solver that supports all rules and symbols (including underclued) but is less optimized.';
|
|
2593
2650
|
protected createWorker(): Worker;
|
|
@@ -2678,8 +2735,10 @@ declare global {
|
|
|
2678
2735
|
): import('grilops').Direction;
|
|
2679
2736
|
export declare class Z3Solver extends Solver {
|
|
2680
2737
|
readonly id = 'z3';
|
|
2738
|
+
readonly author = 'Lysine';
|
|
2681
2739
|
readonly description =
|
|
2682
|
-
'
|
|
2740
|
+
'(Obsolete) A WebAssembly solver that supports a limited set of rules and symbols.';
|
|
2741
|
+
readonly supportsCancellation = false;
|
|
2683
2742
|
isEnvironmentSupported(): Promise<boolean>;
|
|
2684
2743
|
solve(grid: GridData): AsyncGenerator<GridData | null>;
|
|
2685
2744
|
isInstructionSupported(instructionId: string): boolean;
|
package/dist/data/grid.js
CHANGED
|
@@ -204,6 +204,7 @@ export default class GridData {
|
|
|
204
204
|
const tiles = this.tiles.map(row => [...row]);
|
|
205
205
|
const newTile = typeof tile === 'function' ? tile(tiles[y][x]) : tile;
|
|
206
206
|
changing.forEach(({ x, y }) => {
|
|
207
|
+
({ x, y } = this.toArrayCoordinates(x, y));
|
|
207
208
|
tiles[y][x] = tiles[y][x].withColor(newTile.color);
|
|
208
209
|
});
|
|
209
210
|
tiles[y][x] = newTile;
|
|
@@ -67,7 +67,8 @@ export declare const COMPARISONS: readonly Comparison[];
|
|
|
67
67
|
export declare enum Wrapping {
|
|
68
68
|
None = "none",
|
|
69
69
|
Wrap = "wrap",
|
|
70
|
-
WrapReverse = "wrap-reverse"
|
|
70
|
+
WrapReverse = "wrap-reverse",
|
|
71
|
+
ReflectReverse = "reflect-reverse"
|
|
71
72
|
}
|
|
72
73
|
export declare const WRAPPINGS: readonly Wrapping[];
|
|
73
74
|
export declare enum Direction {
|
package/dist/data/primitives.js
CHANGED
|
@@ -56,11 +56,13 @@ export var Wrapping;
|
|
|
56
56
|
Wrapping["None"] = "none";
|
|
57
57
|
Wrapping["Wrap"] = "wrap";
|
|
58
58
|
Wrapping["WrapReverse"] = "wrap-reverse";
|
|
59
|
+
Wrapping["ReflectReverse"] = "reflect-reverse";
|
|
59
60
|
})(Wrapping || (Wrapping = {}));
|
|
60
61
|
export const WRAPPINGS = [
|
|
61
62
|
Wrapping.None,
|
|
62
63
|
Wrapping.Wrap,
|
|
63
64
|
Wrapping.WrapReverse,
|
|
65
|
+
Wrapping.ReflectReverse,
|
|
64
66
|
];
|
|
65
67
|
export var Direction;
|
|
66
68
|
(function (Direction) {
|
|
@@ -74,7 +74,15 @@ class BanPatternRule extends Rule {
|
|
|
74
74
|
for (let y = 0; y <= grid.height - 1; y++) {
|
|
75
75
|
for (let x = 0; x <= grid.width - 1; x++) {
|
|
76
76
|
let match = true;
|
|
77
|
+
const visited = [];
|
|
77
78
|
for (const tile of pattern.elements) {
|
|
79
|
+
const pos = grid.toArrayCoordinates(x + tile.x, y + tile.y);
|
|
80
|
+
if (grid.wrapAround.value && // optimization: not need to check visited if wrapAround is disabled
|
|
81
|
+
visited.some(p => p.x === pos.x && p.y === pos.y)) {
|
|
82
|
+
match = false;
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
visited.push(pos);
|
|
78
86
|
const t = grid.getTile(x + tile.x, y + tile.y);
|
|
79
87
|
if (!t.exists || t.color !== tile.color) {
|
|
80
88
|
match = false;
|
|
@@ -25,7 +25,7 @@ export default class MusicGridRule extends Rule implements GridChangeHandler, Se
|
|
|
25
25
|
get configs(): readonly AnyConfig[] | null;
|
|
26
26
|
createExampleGrid(): GridData;
|
|
27
27
|
get searchVariants(): SearchVariant[];
|
|
28
|
-
validateGrid(
|
|
28
|
+
validateGrid(_grid: GridData): RuleState;
|
|
29
29
|
onSetGrid(_oldGrid: GridData, newGrid: GridData, _solution: GridData | null): GridData;
|
|
30
30
|
onGridChange(newGrid: GridData): this;
|
|
31
31
|
onGridResize(_grid: GridData, mode: 'insert' | 'remove', direction: 'row' | 'column', index: number): this | null;
|
|
@@ -61,13 +61,8 @@ class MusicGridRule extends Rule {
|
|
|
61
61
|
get searchVariants() {
|
|
62
62
|
return MusicGridRule.SEARCH_VARIANTS;
|
|
63
63
|
}
|
|
64
|
-
validateGrid(
|
|
65
|
-
|
|
66
|
-
return { state: State.Incomplete };
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
69
|
-
return { state: State.Satisfied };
|
|
70
|
-
}
|
|
64
|
+
validateGrid(_grid) {
|
|
65
|
+
return { state: State.Incomplete };
|
|
71
66
|
}
|
|
72
67
|
onSetGrid(_oldGrid, newGrid, _solution) {
|
|
73
68
|
if (newGrid.getTileCount(true, undefined, Color.Gray) === 0)
|
|
@@ -8,9 +8,7 @@ export default class WrapAroundRule extends Rule implements GetTileHandler {
|
|
|
8
8
|
readonly vertical: Wrapping;
|
|
9
9
|
private static readonly EXAMPLE_GRID_NONE;
|
|
10
10
|
private static readonly EXAMPLE_GRID_HORIZONTAL;
|
|
11
|
-
private static readonly EXAMPLE_GRID_HORIZONTAL_REVERSE;
|
|
12
11
|
private static readonly EXAMPLE_GRID_VERTICAL;
|
|
13
|
-
private static readonly EXAMPLE_GRID_VERTICAL_REVERSE;
|
|
14
12
|
private static readonly SEARCH_VARIANTS;
|
|
15
13
|
private static readonly CONFIGS;
|
|
16
14
|
/**
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { ConfigType } from '../config.js';
|
|
2
2
|
import { array } from '../dataHelper.js';
|
|
3
3
|
import GridData from '../grid.js';
|
|
4
|
-
import { Color, MajorRule, State, Wrapping, } from '../primitives.js';
|
|
4
|
+
import { Color, MajorRule, Orientation, State, Wrapping, orientationToggle, } from '../primitives.js';
|
|
5
5
|
import LetterSymbol from '../symbols/letterSymbol.js';
|
|
6
|
+
import MyopiaSymbol from '../symbols/myopiaSymbol.js';
|
|
6
7
|
import Rule from './rule.js';
|
|
7
8
|
class WrapAroundRule extends Rule {
|
|
8
9
|
/**
|
|
@@ -29,19 +30,32 @@ class WrapAroundRule extends Rule {
|
|
|
29
30
|
this.vertical = vertical;
|
|
30
31
|
}
|
|
31
32
|
onGetTile(x, y, grid) {
|
|
33
|
+
if (grid.width === 0 || grid.height === 0) {
|
|
34
|
+
return { x, y };
|
|
35
|
+
}
|
|
32
36
|
if (this.horizontal !== Wrapping.None) {
|
|
33
37
|
const idx = Math.abs(Math.floor(x / grid.width));
|
|
34
38
|
x = ((x % grid.width) + grid.width) % grid.width;
|
|
35
|
-
if (this.horizontal === Wrapping.WrapReverse
|
|
39
|
+
if ((this.horizontal === Wrapping.WrapReverse ||
|
|
40
|
+
this.horizontal === Wrapping.ReflectReverse) &&
|
|
41
|
+
idx % 2 === 1) {
|
|
36
42
|
y = grid.height - 1 - y;
|
|
37
43
|
}
|
|
44
|
+
if (this.horizontal === Wrapping.ReflectReverse && idx % 2 === 1) {
|
|
45
|
+
x = grid.width - 1 - x;
|
|
46
|
+
}
|
|
38
47
|
}
|
|
39
48
|
if (this.vertical !== Wrapping.None) {
|
|
40
49
|
const idx = Math.abs(Math.floor(y / grid.height));
|
|
41
50
|
y = ((y % grid.height) + grid.height) % grid.height;
|
|
42
|
-
if (this.vertical === Wrapping.WrapReverse
|
|
51
|
+
if ((this.vertical === Wrapping.WrapReverse ||
|
|
52
|
+
this.vertical === Wrapping.ReflectReverse) &&
|
|
53
|
+
idx % 2 === 1) {
|
|
43
54
|
x = grid.width - 1 - x;
|
|
44
55
|
}
|
|
56
|
+
if (this.vertical === Wrapping.ReflectReverse && idx % 2 === 1) {
|
|
57
|
+
y = grid.height - 1 - y;
|
|
58
|
+
}
|
|
45
59
|
}
|
|
46
60
|
return { x, y };
|
|
47
61
|
}
|
|
@@ -52,37 +66,48 @@ class WrapAroundRule extends Rule {
|
|
|
52
66
|
if (this.horizontal === Wrapping.None && this.vertical === Wrapping.None) {
|
|
53
67
|
return `No edges are connected.`;
|
|
54
68
|
}
|
|
55
|
-
|
|
56
|
-
|
|
69
|
+
const horizontal = this.horizontal === Wrapping.None
|
|
70
|
+
? null
|
|
71
|
+
: this.horizontal === Wrapping.Wrap ||
|
|
72
|
+
this.horizontal === Wrapping.WrapReverse
|
|
73
|
+
? 'connected'
|
|
74
|
+
: 'reflective';
|
|
75
|
+
const vertical = this.vertical === Wrapping.None
|
|
76
|
+
? null
|
|
77
|
+
: this.vertical === Wrapping.Wrap ||
|
|
78
|
+
this.vertical === Wrapping.WrapReverse
|
|
79
|
+
? 'connected'
|
|
80
|
+
: 'reflective';
|
|
81
|
+
const horizontalReverse = this.horizontal === Wrapping.WrapReverse ||
|
|
82
|
+
this.horizontal === Wrapping.ReflectReverse
|
|
83
|
+
? ' in reverse'
|
|
84
|
+
: '';
|
|
85
|
+
const verticalReverse = this.vertical === Wrapping.WrapReverse ||
|
|
86
|
+
this.vertical === Wrapping.ReflectReverse
|
|
87
|
+
? ' in reverse'
|
|
88
|
+
: '';
|
|
89
|
+
if (this.horizontal === this.vertical) {
|
|
90
|
+
return `All four edges are ${horizontal}${horizontalReverse}.`;
|
|
57
91
|
}
|
|
58
|
-
|
|
59
|
-
return `The
|
|
92
|
+
if (this.horizontal === Wrapping.None) {
|
|
93
|
+
return `The top and bottom edges are ${vertical}${verticalReverse}.`;
|
|
60
94
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
return `All four edges are connected.`;
|
|
95
|
+
if (this.vertical === Wrapping.None) {
|
|
96
|
+
return `The left and right edges are ${horizontal}${horizontalReverse}.`;
|
|
64
97
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
return `All four edges are connected in reverse.`;
|
|
98
|
+
if (horizontal === vertical) {
|
|
99
|
+
if (horizontalReverse !== '') {
|
|
100
|
+
return `All four edges are ${horizontal}, with the left and right edges${horizontalReverse}.`;
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
return `All four edges are ${horizontal}, with the top and bottom edges${verticalReverse}.`;
|
|
104
|
+
}
|
|
73
105
|
}
|
|
106
|
+
return `The left and right edges are ${horizontal}${horizontalReverse}. The top and bottom edges are ${vertical}${verticalReverse}.`;
|
|
74
107
|
}
|
|
75
108
|
createExampleGrid() {
|
|
76
|
-
const horizontal = this.horizontal
|
|
77
|
-
|
|
78
|
-
: this.horizontal === Wrapping.WrapReverse
|
|
79
|
-
? WrapAroundRule.EXAMPLE_GRID_HORIZONTAL_REVERSE
|
|
80
|
-
: WrapAroundRule.EXAMPLE_GRID_NONE;
|
|
81
|
-
const vertical = this.vertical === Wrapping.Wrap
|
|
82
|
-
? WrapAroundRule.EXAMPLE_GRID_VERTICAL
|
|
83
|
-
: this.vertical === Wrapping.WrapReverse
|
|
84
|
-
? WrapAroundRule.EXAMPLE_GRID_VERTICAL_REVERSE
|
|
85
|
-
: WrapAroundRule.EXAMPLE_GRID_NONE;
|
|
109
|
+
const horizontal = WrapAroundRule.EXAMPLE_GRID_HORIZONTAL[this.horizontal];
|
|
110
|
+
const vertical = WrapAroundRule.EXAMPLE_GRID_VERTICAL[this.vertical];
|
|
86
111
|
if (horizontal === WrapAroundRule.EXAMPLE_GRID_NONE) {
|
|
87
112
|
return vertical;
|
|
88
113
|
}
|
|
@@ -134,41 +159,79 @@ Object.defineProperty(WrapAroundRule, "EXAMPLE_GRID_HORIZONTAL", {
|
|
|
134
159
|
enumerable: true,
|
|
135
160
|
configurable: true,
|
|
136
161
|
writable: true,
|
|
137
|
-
value: Object.freeze(
|
|
138
|
-
.
|
|
139
|
-
.
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
.
|
|
151
|
-
|
|
162
|
+
value: Object.freeze({
|
|
163
|
+
[Wrapping.None]: WrapAroundRule.EXAMPLE_GRID_NONE,
|
|
164
|
+
[Wrapping.Wrap]: GridData.create([
|
|
165
|
+
'wwwww',
|
|
166
|
+
'bwwwb',
|
|
167
|
+
'wwwww',
|
|
168
|
+
'bwwwb',
|
|
169
|
+
'wwwww',
|
|
170
|
+
])
|
|
171
|
+
.addSymbol(new LetterSymbol(0, 1, 'A'))
|
|
172
|
+
.addSymbol(new LetterSymbol(4, 1, 'A'))
|
|
173
|
+
.addSymbol(new LetterSymbol(0, 3, 'B'))
|
|
174
|
+
.addSymbol(new LetterSymbol(4, 3, 'B')),
|
|
175
|
+
[Wrapping.WrapReverse]: GridData.create([
|
|
176
|
+
'wwwww',
|
|
177
|
+
'bwwwb',
|
|
178
|
+
'wwwww',
|
|
179
|
+
'bwwwb',
|
|
180
|
+
'wwwww',
|
|
181
|
+
])
|
|
182
|
+
.addSymbol(new LetterSymbol(0, 1, 'A'))
|
|
183
|
+
.addSymbol(new LetterSymbol(4, 1, 'B'))
|
|
184
|
+
.addSymbol(new LetterSymbol(0, 3, 'B'))
|
|
185
|
+
.addSymbol(new LetterSymbol(4, 3, 'A')),
|
|
186
|
+
[Wrapping.ReflectReverse]: GridData.create([
|
|
187
|
+
'wwwww',
|
|
188
|
+
'bwwww',
|
|
189
|
+
'wwwww',
|
|
190
|
+
'wwwwb',
|
|
191
|
+
'wwwww',
|
|
192
|
+
])
|
|
193
|
+
.addSymbol(new MyopiaSymbol(0, 3, false, orientationToggle(Orientation.Left)))
|
|
194
|
+
.addSymbol(new MyopiaSymbol(4, 1, false, orientationToggle(Orientation.Right))),
|
|
195
|
+
})
|
|
152
196
|
});
|
|
153
197
|
Object.defineProperty(WrapAroundRule, "EXAMPLE_GRID_VERTICAL", {
|
|
154
198
|
enumerable: true,
|
|
155
199
|
configurable: true,
|
|
156
200
|
writable: true,
|
|
157
|
-
value: Object.freeze(
|
|
158
|
-
.
|
|
159
|
-
.
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
.
|
|
171
|
-
|
|
201
|
+
value: Object.freeze({
|
|
202
|
+
[Wrapping.None]: WrapAroundRule.EXAMPLE_GRID_NONE,
|
|
203
|
+
[Wrapping.Wrap]: GridData.create([
|
|
204
|
+
'wbwbw',
|
|
205
|
+
'wwwww',
|
|
206
|
+
'wwwww',
|
|
207
|
+
'wwwww',
|
|
208
|
+
'wbwbw',
|
|
209
|
+
])
|
|
210
|
+
.addSymbol(new LetterSymbol(1, 0, 'C'))
|
|
211
|
+
.addSymbol(new LetterSymbol(3, 0, 'D'))
|
|
212
|
+
.addSymbol(new LetterSymbol(1, 4, 'C'))
|
|
213
|
+
.addSymbol(new LetterSymbol(3, 4, 'D')),
|
|
214
|
+
[Wrapping.WrapReverse]: GridData.create([
|
|
215
|
+
'wbwbw',
|
|
216
|
+
'wwwww',
|
|
217
|
+
'wwwww',
|
|
218
|
+
'wwwww',
|
|
219
|
+
'wbwbw',
|
|
220
|
+
])
|
|
221
|
+
.addSymbol(new LetterSymbol(1, 0, 'C'))
|
|
222
|
+
.addSymbol(new LetterSymbol(3, 0, 'D'))
|
|
223
|
+
.addSymbol(new LetterSymbol(1, 4, 'D'))
|
|
224
|
+
.addSymbol(new LetterSymbol(3, 4, 'C')),
|
|
225
|
+
[Wrapping.ReflectReverse]: GridData.create([
|
|
226
|
+
'wbwww',
|
|
227
|
+
'wwwww',
|
|
228
|
+
'wwwww',
|
|
229
|
+
'wwwww',
|
|
230
|
+
'wwwbw',
|
|
231
|
+
])
|
|
232
|
+
.addSymbol(new MyopiaSymbol(3, 0, false, orientationToggle(Orientation.Up)))
|
|
233
|
+
.addSymbol(new MyopiaSymbol(1, 4, false, orientationToggle(Orientation.Down))),
|
|
234
|
+
})
|
|
172
235
|
});
|
|
173
236
|
Object.defineProperty(WrapAroundRule, "SEARCH_VARIANTS", {
|
|
174
237
|
enumerable: true,
|
|
@@ -178,6 +241,9 @@ Object.defineProperty(WrapAroundRule, "SEARCH_VARIANTS", {
|
|
|
178
241
|
new WrapAroundRule(Wrapping.Wrap, Wrapping.None).searchVariant(),
|
|
179
242
|
new WrapAroundRule(Wrapping.None, Wrapping.Wrap).searchVariant(),
|
|
180
243
|
new WrapAroundRule(Wrapping.Wrap, Wrapping.Wrap).searchVariant(),
|
|
244
|
+
new WrapAroundRule(Wrapping.ReflectReverse, Wrapping.None).searchVariant(),
|
|
245
|
+
new WrapAroundRule(Wrapping.None, Wrapping.ReflectReverse).searchVariant(),
|
|
246
|
+
new WrapAroundRule(Wrapping.ReflectReverse, Wrapping.ReflectReverse).searchVariant(),
|
|
181
247
|
]
|
|
182
248
|
});
|
|
183
249
|
Object.defineProperty(WrapAroundRule, "CONFIGS", {
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import UniversalSolver from './universal/universalSolver.js';
|
|
2
2
|
import BacktrackSolver from './backtrack/backtrackSolver.js';
|
|
3
3
|
import Z3Solver from './z3/z3Solver.js';
|
|
4
|
+
import CspuzSolver from './cspuz/cspuzSolver.js';
|
|
4
5
|
const allSolvers = new Map();
|
|
5
6
|
function register(prototype) {
|
|
6
7
|
allSolvers.set(prototype.id, prototype);
|
|
7
8
|
}
|
|
9
|
+
register(new CspuzSolver());
|
|
8
10
|
register(new BacktrackSolver());
|
|
9
11
|
register(new UniversalSolver());
|
|
10
12
|
register(new Z3Solver());
|
|
@@ -2,7 +2,8 @@ import EventIteratingSolver from '../eventIteratingSolver.js';
|
|
|
2
2
|
export default class BacktrackSolver extends EventIteratingSolver {
|
|
3
3
|
private static readonly supportedInstrs;
|
|
4
4
|
readonly id = "backtrack";
|
|
5
|
-
readonly
|
|
5
|
+
readonly author = "ALaggyDev";
|
|
6
|
+
readonly description = "Solves puzzles pretty fast using backtracking with optimizations. Support most rules and symbols (including underclued).";
|
|
6
7
|
protected createWorker(): Worker;
|
|
7
8
|
isInstructionSupported(instructionId: string): boolean;
|
|
8
9
|
}
|
|
@@ -11,9 +11,10 @@ import { instance as galaxyInstance } from '../../symbols/galaxySymbol.js';
|
|
|
11
11
|
import { instance as letterInstance } from '../../symbols/letterSymbol.js';
|
|
12
12
|
import { instance as lotusInstance } from '../../symbols/lotusSymbol.js';
|
|
13
13
|
import { instance as minesweeperInstance } from '../../symbols/minesweeperSymbol.js';
|
|
14
|
+
import { instance as focusInstance } from '../../symbols/focusSymbol.js';
|
|
14
15
|
import { instance as myopiaInstance } from '../../symbols/myopiaSymbol.js';
|
|
15
16
|
import { instance as viewpointInstance } from '../../symbols/viewpointSymbol.js';
|
|
16
|
-
import { instance as connectAllInstance } from '
|
|
17
|
+
import { instance as connectAllInstance } from '../../rules/connectAllRule.js';
|
|
17
18
|
import EventIteratingSolver from '../eventIteratingSolver.js';
|
|
18
19
|
class BacktrackSolver extends EventIteratingSolver {
|
|
19
20
|
constructor() {
|
|
@@ -24,11 +25,17 @@ class BacktrackSolver extends EventIteratingSolver {
|
|
|
24
25
|
writable: true,
|
|
25
26
|
value: 'backtrack'
|
|
26
27
|
});
|
|
28
|
+
Object.defineProperty(this, "author", {
|
|
29
|
+
enumerable: true,
|
|
30
|
+
configurable: true,
|
|
31
|
+
writable: true,
|
|
32
|
+
value: 'ALaggyDev'
|
|
33
|
+
});
|
|
27
34
|
Object.defineProperty(this, "description", {
|
|
28
35
|
enumerable: true,
|
|
29
36
|
configurable: true,
|
|
30
37
|
writable: true,
|
|
31
|
-
value: 'Solves puzzles using backtracking with optimizations
|
|
38
|
+
value: 'Solves puzzles pretty fast using backtracking with optimizations. Support most rules and symbols (including underclued).'
|
|
32
39
|
});
|
|
33
40
|
}
|
|
34
41
|
createWorker() {
|
|
@@ -52,6 +59,7 @@ Object.defineProperty(BacktrackSolver, "supportedInstrs", {
|
|
|
52
59
|
lotusInstance.id,
|
|
53
60
|
myopiaInstance.id,
|
|
54
61
|
minesweeperInstance.id,
|
|
62
|
+
focusInstance.id,
|
|
55
63
|
letterInstance.id,
|
|
56
64
|
undercluedInstance.id,
|
|
57
65
|
connectAllInstance.id,
|
|
@@ -14,6 +14,7 @@ import { instance as galaxyInstance, } from '../../symbols/galaxySymbol.js';
|
|
|
14
14
|
import { instance as letterInstance, } from '../../symbols/letterSymbol.js';
|
|
15
15
|
import { instance as lotusInstance, } from '../../symbols/lotusSymbol.js';
|
|
16
16
|
import { instance as minesweeperInstance, } from '../../symbols/minesweeperSymbol.js';
|
|
17
|
+
import { instance as focusInstance, } from '../../symbols/focusSymbol.js';
|
|
17
18
|
import { instance as myopiaInstance, } from '../../symbols/myopiaSymbol.js';
|
|
18
19
|
import { instance as viewpointInstance, } from '../../symbols/viewpointSymbol.js';
|
|
19
20
|
import { instance as connectAllInstance } from '../z3/modules/connectAllModule.js';
|
|
@@ -33,6 +34,7 @@ import LotusBTModule from './symbols/lotus.js';
|
|
|
33
34
|
import MinesweeperBTModule from './symbols/minesweeper.js';
|
|
34
35
|
import MyopiaBTModule from './symbols/myopia.js';
|
|
35
36
|
import ViewpointBTModule from './symbols/viewpoint.js';
|
|
37
|
+
import FocusBTModule from './symbols/focus.js';
|
|
36
38
|
function translateToBTGridData(grid) {
|
|
37
39
|
const tiles = array(grid.width, grid.height, (x, y) => {
|
|
38
40
|
const tile = grid.getTile(x, y);
|
|
@@ -71,6 +73,9 @@ function translateToBTGridData(grid) {
|
|
|
71
73
|
else if (id === minesweeperInstance.id) {
|
|
72
74
|
module = new MinesweeperBTModule(symbol);
|
|
73
75
|
}
|
|
76
|
+
else if (id === focusInstance.id) {
|
|
77
|
+
module = new FocusBTModule(symbol);
|
|
78
|
+
}
|
|
74
79
|
else if (id === letterInstance.id) {
|
|
75
80
|
continue;
|
|
76
81
|
}
|
|
@@ -289,6 +294,12 @@ onmessage = e => {
|
|
|
289
294
|
let count = 0;
|
|
290
295
|
solve(grid, solution => {
|
|
291
296
|
// if (count === 0) console.timeLog('Solve time', 'First solution');
|
|
297
|
+
if (solution) {
|
|
298
|
+
if (solution.resetTiles().colorEquals(solution)) {
|
|
299
|
+
postMessage(null);
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
292
303
|
postMessage(Serializer.stringifyGrid(solution));
|
|
293
304
|
count += 1;
|
|
294
305
|
return count < 2;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import FocusSymbol from '../../../symbols/focusSymbol.js';
|
|
2
|
+
import BTModule, { BTGridData, CheckResult } from '../data.js';
|
|
3
|
+
export default class FocusBTModule extends BTModule {
|
|
4
|
+
instr: FocusSymbol;
|
|
5
|
+
private cachedCheckResult?;
|
|
6
|
+
constructor(instr: FocusSymbol);
|
|
7
|
+
checkGlobal(grid: BTGridData): CheckResult | false;
|
|
8
|
+
private buildCheckAndRating;
|
|
9
|
+
}
|