@logic-pad/core 0.10.1 → 0.11.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.
@@ -160,6 +160,11 @@ declare global {
160
160
  * @returns The deduplicated array of edges.
161
161
  */
162
162
  static deduplicateEdges(edges: readonly Edge[]): readonly Edge[];
163
+ static validateEdges(
164
+ connections: GridZones,
165
+ width: number,
166
+ height: number
167
+ ): GridZones;
163
168
  insertColumn(index: number): GridZones;
164
169
  insertRow(index: number): GridZones;
165
170
  removeColumn(index: number): GridZones;
@@ -206,6 +211,11 @@ declare global {
206
211
  * @returns The created connections. You can apply this to a GridData object using GridData.withConnections.
207
212
  */
208
213
  static create(array: string[]): GridConnections;
214
+ static validateEdges(
215
+ connections: GridConnections,
216
+ width: number,
217
+ height: number
218
+ ): GridConnections;
209
219
  insertColumn(index: number): GridConnections;
210
220
  insertRow(index: number): GridConnections;
211
221
  removeColumn(index: number): GridConnections;
@@ -1495,6 +1505,10 @@ declare global {
1495
1505
  ): Shape;
1496
1506
  export declare function getShapeVariants(shape: Shape): Shape[];
1497
1507
  export declare function normalizeShape(shape: Shape): Shape;
1508
+ export declare function sanitizePatternGrid(
1509
+ pattern: GridData,
1510
+ tileMapper?: (tile: TileData) => TileData
1511
+ ): GridData;
1498
1512
  export declare class BanPatternRule extends Rule {
1499
1513
  private static readonly EXAMPLE_GRID;
1500
1514
  private static readonly CONFIGS;
@@ -1583,6 +1597,46 @@ declare global {
1583
1597
  copyWith({ color }: { color?: Color }): this;
1584
1598
  withColor(color: Color): this;
1585
1599
  }
1600
+ export type ShapeRegions = {
1601
+ regions: {
1602
+ positions: Position$1[];
1603
+ shape: Shape;
1604
+ count: number;
1605
+ }[];
1606
+ complete: boolean;
1607
+ };
1608
+ export declare abstract class RegionShapeRule extends Rule {
1609
+ readonly color: Color;
1610
+ /**
1611
+ * @param color - The color of the regions to compare.
1612
+ */
1613
+ constructor(color: Color);
1614
+ protected getShapeRegions(grid: GridData): ShapeRegions;
1615
+ withColor(color: Color): this;
1616
+ }
1617
+ export declare class ContainsShapeRule extends RegionShapeRule {
1618
+ private static readonly EXAMPLE_GRID_LIGHT;
1619
+ private static readonly EXAMPLE_GRID_DARK;
1620
+ private static readonly CONFIGS;
1621
+ private static readonly SEARCH_VARIANTS;
1622
+ readonly pattern: GridData;
1623
+ readonly cache: Shape[];
1624
+ /**
1625
+ * **All <color> areas must contain this pattern**
1626
+ *
1627
+ * @param color - The color of the regions to compare.
1628
+ * @param pattern - GridData representing the required pattern. Only non-gray tiles are considered.
1629
+ */
1630
+ constructor(color: Color, pattern: GridData);
1631
+ get id(): string;
1632
+ get explanation(): string;
1633
+ get configs(): readonly AnyConfig[] | null;
1634
+ createExampleGrid(): GridData;
1635
+ get searchVariants(): SearchVariant[];
1636
+ validateGrid(grid: GridData): RuleState;
1637
+ copyWith({ color, pattern }: { color?: Color; pattern?: GridData }): this;
1638
+ withPattern(pattern: GridData): this;
1639
+ }
1586
1640
  export declare class CustomRule extends Rule {
1587
1641
  readonly description: string;
1588
1642
  readonly grid: GridData;
@@ -1825,23 +1879,6 @@ declare global {
1825
1879
  withColor(color: Color): this;
1826
1880
  withSize(size: number): this;
1827
1881
  }
1828
- export type ShapeRegions = {
1829
- regions: {
1830
- positions: Position$1[];
1831
- shape: Shape;
1832
- count: number;
1833
- }[];
1834
- complete: boolean;
1835
- };
1836
- export declare abstract class RegionShapeRule extends Rule {
1837
- readonly color: Color;
1838
- /**
1839
- * @param color - The color of the regions to compare.
1840
- */
1841
- constructor(color: Color);
1842
- protected getShapeRegions(grid: GridData): ShapeRegions;
1843
- withColor(color: Color): this;
1844
- }
1845
1882
  export declare class SameShapeRule extends RegionShapeRule {
1846
1883
  private static readonly CONFIGS;
1847
1884
  private static readonly EXAMPLE_GRID_LIGHT;
@@ -2087,7 +2124,8 @@ declare global {
2087
2124
  *
2088
2125
  * @returns A promise that resolves to `true` if the environment is supported, or `false` otherwise.
2089
2126
  */
2090
- isEnvironmentSupported(): Promise<boolean>;
2127
+ protected isEnvironmentSupported(): Promise<boolean>;
2128
+ readonly environmentCheck: CachedAccess<Promise<boolean>>;
2091
2129
  /**
2092
2130
  * Check if the solver supports the given instruction. This is used to render a small indication in the UI for each
2093
2131
  * instruction in the editor.
@@ -2108,9 +2146,29 @@ declare global {
2108
2146
  isGridSupported(grid: GridData): boolean;
2109
2147
  }
2110
2148
  export declare const allSolvers: Map<string, Solver>;
2149
+ export declare class AutoSolver extends Solver {
2150
+ readonly id = 'auto';
2151
+ readonly author = 'various contributors';
2152
+ readonly description =
2153
+ 'Automatically select the fastest solver based on supported instructions and environment.';
2154
+ readonly supportsCancellation = true;
2155
+ private static readonly nonAdditiveInstructions;
2156
+ isGridSupported(grid: GridData): boolean;
2157
+ isInstructionSupported(instructionId: string): boolean;
2158
+ protected isEnvironmentSupported(): Promise<boolean>;
2159
+ private fillSolution;
2160
+ private fixGrid;
2161
+ private solveWithProgress;
2162
+ private solveOne;
2163
+ solve(
2164
+ grid: GridData,
2165
+ abortSignal?: AbortSignal | undefined
2166
+ ): AsyncGenerator<GridData | null>;
2167
+ }
2111
2168
  export declare abstract class EventIteratingSolver extends Solver {
2112
2169
  readonly supportsCancellation = true;
2113
2170
  protected abstract createWorker(): Worker;
2171
+ protected isEnvironmentSupported(): Promise<boolean>;
2114
2172
  solve(
2115
2173
  grid: GridData,
2116
2174
  abortSignal?: AbortSignal
@@ -2635,7 +2693,7 @@ declare global {
2635
2693
  readonly id = 'cspuz';
2636
2694
  readonly author = 'semiexp';
2637
2695
  readonly description =
2638
- 'A blazingly fast WebAssembly solver that supports most rules and symbols (including underclued). No uniqueness check yet.';
2696
+ 'A blazingly fast WebAssembly solver that supports most rules and symbols (including underclued).';
2639
2697
  protected createWorker(): Worker;
2640
2698
  isGridSupported(grid: GridData): boolean;
2641
2699
  isInstructionSupported(instructionId: string): boolean;
@@ -2739,7 +2797,7 @@ declare global {
2739
2797
  readonly description =
2740
2798
  '(Obsolete) A WebAssembly solver that supports a limited set of rules and symbols.';
2741
2799
  readonly supportsCancellation = false;
2742
- isEnvironmentSupported(): Promise<boolean>;
2800
+ protected isEnvironmentSupported(): Promise<boolean>;
2743
2801
  solve(grid: GridData): AsyncGenerator<GridData | null>;
2744
2802
  isInstructionSupported(instructionId: string): boolean;
2745
2803
  isGridSupported(grid: GridData): boolean;
package/dist/data/grid.js CHANGED
@@ -109,7 +109,9 @@ export default class GridData {
109
109
  : new Map();
110
110
  // do not deduplicate all rules because it makes for bad editor experience
111
111
  const newRules = rules ? GridData.deduplicateSingletonRules(rules) : [];
112
- const newGrid = new GridData(arrayOrWidth, height, tiles, connections, zones, newSymbols, newRules);
112
+ const newGrid = new GridData(arrayOrWidth, height, tiles, connections
113
+ ? GridConnections.validateEdges(connections, arrayOrWidth, height)
114
+ : connections, zones ? GridZones.validateEdges(zones, arrayOrWidth, height) : zones, newSymbols, newRules);
113
115
  newSymbols.forEach(list => {
114
116
  list.forEach((sym, i) => {
115
117
  if (handlesGridChange(sym)) {
@@ -17,6 +17,7 @@ export default class GridConnections extends GridZones {
17
17
  * @returns The created connections. You can apply this to a GridData object using GridData.withConnections.
18
18
  */
19
19
  static create(array: string[]): GridConnections;
20
+ static validateEdges(connections: GridConnections, width: number, height: number): GridConnections;
20
21
  insertColumn(index: number): GridConnections;
21
22
  insertRow(index: number): GridConnections;
22
23
  removeColumn(index: number): GridConnections;
@@ -111,6 +111,25 @@ export default class GridConnections extends GridZones {
111
111
  }
112
112
  return new GridConnections(edges);
113
113
  }
114
+ static validateEdges(connections, width, height) {
115
+ const newEdges = [];
116
+ for (const edge of connections.edges) {
117
+ if (edge.x1 < 0 || edge.x1 >= width || edge.y1 < 0 || edge.y1 >= height) {
118
+ continue;
119
+ }
120
+ if (edge.x2 < 0 || edge.x2 >= width || edge.y2 < 0 || edge.y2 >= height) {
121
+ continue;
122
+ }
123
+ if (Math.abs(edge.x1 - edge.x2) + Math.abs(edge.y1 - edge.y2) !== 1) {
124
+ continue;
125
+ }
126
+ newEdges.push(edge);
127
+ }
128
+ if (newEdges.length === connections.edges.length) {
129
+ return connections;
130
+ }
131
+ return new GridConnections(newEdges);
132
+ }
114
133
  insertColumn(index) {
115
134
  return new GridConnections(this.edges.flatMap(edge => {
116
135
  if ((edge.x1 < index && edge.x2 < index) ||
@@ -18,6 +18,7 @@ export default class GridZones {
18
18
  * @returns The deduplicated array of edges.
19
19
  */
20
20
  static deduplicateEdges(edges: readonly Edge[]): readonly Edge[];
21
+ static validateEdges(connections: GridZones, width: number, height: number): GridZones;
21
22
  insertColumn(index: number): GridZones;
22
23
  insertRow(index: number): GridZones;
23
24
  removeColumn(index: number): GridZones;
@@ -48,6 +48,31 @@ export default class GridZones {
48
48
  static deduplicateEdges(edges) {
49
49
  return edges.filter((edge, index) => edges.findIndex(e => isSameEdge(e, edge)) === index);
50
50
  }
51
+ static validateEdges(connections, width, height) {
52
+ const newEdges = [];
53
+ for (const edge of connections.edges) {
54
+ if (edge.x1 < -1 ||
55
+ edge.x1 >= width + 1 ||
56
+ edge.y1 < -1 ||
57
+ edge.y1 >= height + 1) {
58
+ continue;
59
+ }
60
+ if (edge.x2 < -1 ||
61
+ edge.x2 >= width + 1 ||
62
+ edge.y2 < -1 ||
63
+ edge.y2 >= height + 1) {
64
+ continue;
65
+ }
66
+ if (Math.abs(edge.x1 - edge.x2) + Math.abs(edge.y1 - edge.y2) !== 1) {
67
+ continue;
68
+ }
69
+ newEdges.push(edge);
70
+ }
71
+ if (newEdges.length === connections.edges.length) {
72
+ return connections;
73
+ }
74
+ return new GridZones(newEdges);
75
+ }
51
76
  insertColumn(index) {
52
77
  return new GridZones(this.edges.map(edge => {
53
78
  if (edge.x1 < index || edge.x2 < index) {
@@ -2,7 +2,7 @@ import { ConfigType } from '../config.js';
2
2
  import GridData from '../grid.js';
3
3
  import { array } from '../dataHelper.js';
4
4
  import { Color, State } from '../primitives.js';
5
- import { getShapeVariants, tilesToShape } from '../shapes.js';
5
+ import { getShapeVariants, sanitizePatternGrid, tilesToShape, } from '../shapes.js';
6
6
  import Rule from './rule.js';
7
7
  class BanPatternRule extends Rule {
8
8
  /**
@@ -24,14 +24,7 @@ class BanPatternRule extends Rule {
24
24
  writable: true,
25
25
  value: void 0
26
26
  });
27
- this.pattern = pattern
28
- // unlock all tiles
29
- .withTiles(tiles => tiles.map(row => row.map(t => t.exists
30
- ? t.withFixed(false)
31
- : t.copyWith({ exists: true, color: Color.Gray, fixed: false }))))
32
- // strip all symbols and rules
33
- .withRules([])
34
- .withSymbols(new Map());
27
+ this.pattern = sanitizePatternGrid(pattern);
35
28
  this.cache = getShapeVariants(tilesToShape(this.pattern.tiles));
36
29
  }
37
30
  get id() {
@@ -0,0 +1,33 @@
1
+ import { AnyConfig } from '../config.js';
2
+ import GridData from '../grid.js';
3
+ import { Color, RuleState } from '../primitives.js';
4
+ import { Shape } from '../shapes.js';
5
+ import RegionShapeRule from './regionShapeRule.js';
6
+ import { SearchVariant } from './rule.js';
7
+ export default class ContainsShapeRule extends RegionShapeRule {
8
+ private static readonly EXAMPLE_GRID_LIGHT;
9
+ private static readonly EXAMPLE_GRID_DARK;
10
+ private static readonly CONFIGS;
11
+ private static readonly SEARCH_VARIANTS;
12
+ readonly pattern: GridData;
13
+ readonly cache: Shape[];
14
+ /**
15
+ * **All &lt;color&gt; areas must contain this pattern**
16
+ *
17
+ * @param color - The color of the regions to compare.
18
+ * @param pattern - GridData representing the required pattern. Only non-gray tiles are considered.
19
+ */
20
+ constructor(color: Color, pattern: GridData);
21
+ get id(): string;
22
+ get explanation(): string;
23
+ get configs(): readonly AnyConfig[] | null;
24
+ createExampleGrid(): GridData;
25
+ get searchVariants(): SearchVariant[];
26
+ validateGrid(grid: GridData): RuleState;
27
+ copyWith({ color, pattern, }: {
28
+ color?: Color;
29
+ pattern?: GridData;
30
+ }): this;
31
+ withPattern(pattern: GridData): this;
32
+ }
33
+ export declare const instance: ContainsShapeRule;
@@ -0,0 +1,151 @@
1
+ import { ConfigType } from '../config.js';
2
+ import { array } from '../dataHelper.js';
3
+ import GridData from '../grid.js';
4
+ import { Color, State } from '../primitives.js';
5
+ import { getShapeVariants, sanitizePatternGrid, tilesToShape, } from '../shapes.js';
6
+ import RegionShapeRule from './regionShapeRule.js';
7
+ class ContainsShapeRule extends RegionShapeRule {
8
+ /**
9
+ * **All &lt;color&gt; areas must contain this pattern**
10
+ *
11
+ * @param color - The color of the regions to compare.
12
+ * @param pattern - GridData representing the required pattern. Only non-gray tiles are considered.
13
+ */
14
+ constructor(color, pattern) {
15
+ super(color);
16
+ Object.defineProperty(this, "pattern", {
17
+ enumerable: true,
18
+ configurable: true,
19
+ writable: true,
20
+ value: void 0
21
+ });
22
+ Object.defineProperty(this, "cache", {
23
+ enumerable: true,
24
+ configurable: true,
25
+ writable: true,
26
+ value: void 0
27
+ });
28
+ this.pattern = sanitizePatternGrid(pattern, t => t.color === color ? t : t.withColor(Color.Gray));
29
+ this.cache = getShapeVariants(tilesToShape(this.pattern.tiles));
30
+ }
31
+ get id() {
32
+ return `contains_shape`;
33
+ }
34
+ get explanation() {
35
+ return `All ${this.color} areas must contain this pattern`;
36
+ }
37
+ get configs() {
38
+ return ContainsShapeRule.CONFIGS;
39
+ }
40
+ createExampleGrid() {
41
+ let minX = Number.POSITIVE_INFINITY;
42
+ let minY = Number.POSITIVE_INFINITY;
43
+ let maxX = Number.NEGATIVE_INFINITY;
44
+ let maxY = Number.NEGATIVE_INFINITY;
45
+ this.pattern.forEach((tile, x, y) => {
46
+ if (tile.color !== Color.Gray && tile.exists) {
47
+ minX = Math.min(minX, x);
48
+ minY = Math.min(minY, y);
49
+ maxX = Math.max(maxX, x);
50
+ maxY = Math.max(maxY, y);
51
+ }
52
+ });
53
+ const width = maxX - minX + 1;
54
+ const height = maxY - minY + 1;
55
+ const tiles = array(width, height, (x, y) => {
56
+ const tile = this.pattern.getTile(x + minX, y + minY);
57
+ if (!tile.exists || tile.color !== Color.Gray)
58
+ return tile;
59
+ return tile.withExists(false);
60
+ });
61
+ return GridData.create(width, height, tiles);
62
+ }
63
+ get searchVariants() {
64
+ return ContainsShapeRule.SEARCH_VARIANTS;
65
+ }
66
+ validateGrid(grid) {
67
+ const { regions, complete } = this.getShapeRegions(grid);
68
+ const errorRegion = regions.find(r => {
69
+ for (const pattern of this.cache) {
70
+ if (r.shape.elements.length < pattern.elements.length)
71
+ continue;
72
+ for (let y = 0; y <= r.shape.height - pattern.height; y++) {
73
+ for (let x = 0; x <= r.shape.width - pattern.width; x++) {
74
+ let match = true;
75
+ for (const element of pattern.elements) {
76
+ const tile = r.shape.elements.find(e => e.x === x + element.x && e.y === y + element.y);
77
+ if (!tile || tile.color !== element.color) {
78
+ match = false;
79
+ break;
80
+ }
81
+ }
82
+ if (match)
83
+ return false;
84
+ }
85
+ }
86
+ }
87
+ return true;
88
+ });
89
+ if (errorRegion) {
90
+ return {
91
+ state: State.Error,
92
+ positions: errorRegion.positions,
93
+ };
94
+ }
95
+ else {
96
+ return { state: complete ? State.Satisfied : State.Incomplete };
97
+ }
98
+ }
99
+ copyWith({ color, pattern, }) {
100
+ return new ContainsShapeRule(color ?? this.color, pattern ?? this.pattern);
101
+ }
102
+ withPattern(pattern) {
103
+ return this.copyWith({ pattern });
104
+ }
105
+ }
106
+ Object.defineProperty(ContainsShapeRule, "EXAMPLE_GRID_LIGHT", {
107
+ enumerable: true,
108
+ configurable: true,
109
+ writable: true,
110
+ value: Object.freeze(GridData.create(['nnnnn', 'nnnnn', 'wwwwn', 'nnnnn', 'nnnnn']))
111
+ });
112
+ Object.defineProperty(ContainsShapeRule, "EXAMPLE_GRID_DARK", {
113
+ enumerable: true,
114
+ configurable: true,
115
+ writable: true,
116
+ value: Object.freeze(GridData.create(['nnnnn', 'nnnnn', 'bbbbn', 'nnnnn', 'nnnnn']))
117
+ });
118
+ Object.defineProperty(ContainsShapeRule, "CONFIGS", {
119
+ enumerable: true,
120
+ configurable: true,
121
+ writable: true,
122
+ value: Object.freeze([
123
+ {
124
+ type: ConfigType.Color,
125
+ default: Color.Light,
126
+ allowGray: false,
127
+ field: 'color',
128
+ description: 'Color',
129
+ configurable: true,
130
+ },
131
+ {
132
+ type: ConfigType.Tile,
133
+ default: ContainsShapeRule.EXAMPLE_GRID_LIGHT,
134
+ resizable: true,
135
+ field: 'pattern',
136
+ description: 'Pattern',
137
+ configurable: true,
138
+ },
139
+ ])
140
+ });
141
+ Object.defineProperty(ContainsShapeRule, "SEARCH_VARIANTS", {
142
+ enumerable: true,
143
+ configurable: true,
144
+ writable: true,
145
+ value: [
146
+ new ContainsShapeRule(Color.Light, ContainsShapeRule.EXAMPLE_GRID_LIGHT).searchVariant(),
147
+ new ContainsShapeRule(Color.Dark, ContainsShapeRule.EXAMPLE_GRID_DARK).searchVariant(),
148
+ ]
149
+ });
150
+ export default ContainsShapeRule;
151
+ export const instance = new ContainsShapeRule(Color.Dark, GridData.create([]));
@@ -3,6 +3,7 @@ export { instance as CellCountPerZoneRule } from './cellCountPerZoneRule.js';
3
3
  export { instance as CellCountRule } from './cellCountRule.js';
4
4
  export { instance as CompletePatternRule } from './completePatternRule.js';
5
5
  export { instance as ConnectAllRule } from './connectAllRule.js';
6
+ export { instance as ContainsShapeRule } from './containsShapeRule.js';
6
7
  export { instance as CustomRule } from './customRule.js';
7
8
  export { instance as ForesightRule } from './foresightRule.js';
8
9
  export { instance as LyingSymbolRule } from './lyingSymbolRule.js';
@@ -7,6 +7,7 @@ export { instance as CellCountPerZoneRule } from './cellCountPerZoneRule.js';
7
7
  export { instance as CellCountRule } from './cellCountRule.js';
8
8
  export { instance as CompletePatternRule } from './completePatternRule.js';
9
9
  export { instance as ConnectAllRule } from './connectAllRule.js';
10
+ export { instance as ContainsShapeRule } from './containsShapeRule.js';
10
11
  export { instance as CustomRule } from './customRule.js';
11
12
  export { instance as ForesightRule } from './foresightRule.js';
12
13
  export { instance as LyingSymbolRule } from './lyingSymbolRule.js';
@@ -1,3 +1,4 @@
1
+ import GridData from './grid.js';
1
2
  import { Color, Position } from './primitives.js';
2
3
  import TileData from './tile.js';
3
4
  export interface ShapeElement {
@@ -15,3 +16,4 @@ export declare function tilesToShape(tiles: readonly (readonly TileData[])[]): S
15
16
  export declare function positionsToShape(positions: Position[], color: Color): Shape;
16
17
  export declare function getShapeVariants(shape: Shape): Shape[];
17
18
  export declare function normalizeShape(shape: Shape): Shape;
19
+ export declare function sanitizePatternGrid(pattern: GridData, tileMapper?: (tile: TileData) => TileData): GridData;
@@ -115,3 +115,13 @@ export function normalizeShape(shape) {
115
115
  const variants = getShapeVariants(shape);
116
116
  return variants.reduce((min, variant) => (compareShape(variant, min) < 0 ? variant : min), variants[0]);
117
117
  }
118
+ export function sanitizePatternGrid(pattern, tileMapper = t => t) {
119
+ return (pattern
120
+ // unlock all tiles
121
+ .withTiles(tiles => tiles.map(row => row.map(t => tileMapper(t.exists
122
+ ? t.withFixed(false)
123
+ : t.copyWith({ exists: true, color: Color.Gray, fixed: false })))))
124
+ // strip all symbols and rules
125
+ .withRules([])
126
+ .withSymbols(new Map()));
127
+ }
@@ -2,10 +2,12 @@ import UniversalSolver from './universal/universalSolver.js';
2
2
  import BacktrackSolver from './backtrack/backtrackSolver.js';
3
3
  import Z3Solver from './z3/z3Solver.js';
4
4
  import CspuzSolver from './cspuz/cspuzSolver.js';
5
+ import AutoSolver from './auto/autoSolver.js';
5
6
  const allSolvers = new Map();
6
7
  function register(prototype) {
7
8
  allSolvers.set(prototype.id, prototype);
8
9
  }
10
+ register(new AutoSolver());
9
11
  register(new CspuzSolver());
10
12
  register(new BacktrackSolver());
11
13
  register(new UniversalSolver());
@@ -0,0 +1,17 @@
1
+ import GridData from '../../grid.js';
2
+ import Solver from '../solver.js';
3
+ export default class AutoSolver extends Solver {
4
+ readonly id = "auto";
5
+ readonly author = "various contributors";
6
+ readonly description = "Automatically select the fastest solver based on supported instructions and environment.";
7
+ readonly supportsCancellation = true;
8
+ private static readonly nonAdditiveInstructions;
9
+ isGridSupported(grid: GridData): boolean;
10
+ isInstructionSupported(instructionId: string): boolean;
11
+ protected isEnvironmentSupported(): Promise<boolean>;
12
+ private fillSolution;
13
+ private fixGrid;
14
+ private solveWithProgress;
15
+ private solveOne;
16
+ solve(grid: GridData, abortSignal?: AbortSignal | undefined): AsyncGenerator<GridData | null>;
17
+ }
@@ -0,0 +1,181 @@
1
+ import { Color, State } from '../../primitives.js';
2
+ import { instance as lyingSymbolInstance } from '../../rules/lyingSymbolRule.js';
3
+ import { instance as offByXInstance } from '../../rules/offByXRule.js';
4
+ import { instance as lotusInstance } from '../../symbols/lotusSymbol.js';
5
+ import { instance as galaxyInstance } from '../../symbols/galaxySymbol.js';
6
+ import { allSolvers } from '../allSolvers.js';
7
+ import Solver from '../solver.js';
8
+ import UndercluedRule from '../../rules/undercluedRule.js';
9
+ import validateGrid from '../../validate.js';
10
+ class AutoSolver extends Solver {
11
+ constructor() {
12
+ super(...arguments);
13
+ Object.defineProperty(this, "id", {
14
+ enumerable: true,
15
+ configurable: true,
16
+ writable: true,
17
+ value: 'auto'
18
+ });
19
+ Object.defineProperty(this, "author", {
20
+ enumerable: true,
21
+ configurable: true,
22
+ writable: true,
23
+ value: 'various contributors'
24
+ });
25
+ Object.defineProperty(this, "description", {
26
+ enumerable: true,
27
+ configurable: true,
28
+ writable: true,
29
+ value: 'Automatically select the fastest solver based on supported instructions and environment.'
30
+ });
31
+ Object.defineProperty(this, "supportsCancellation", {
32
+ enumerable: true,
33
+ configurable: true,
34
+ writable: true,
35
+ value: true
36
+ });
37
+ }
38
+ isGridSupported(grid) {
39
+ for (const solver of allSolvers.values()) {
40
+ if (solver.id === this.id)
41
+ continue;
42
+ if (solver.isGridSupported(grid)) {
43
+ return true;
44
+ }
45
+ }
46
+ return false;
47
+ }
48
+ isInstructionSupported(instructionId) {
49
+ for (const solver of allSolvers.values()) {
50
+ if (solver.id === this.id)
51
+ continue;
52
+ if (solver.isInstructionSupported(instructionId)) {
53
+ return true;
54
+ }
55
+ }
56
+ return false;
57
+ }
58
+ async isEnvironmentSupported() {
59
+ for (const solver of allSolvers.values()) {
60
+ if (solver.id === this.id)
61
+ continue;
62
+ if (await solver.environmentCheck.value) {
63
+ return true;
64
+ }
65
+ }
66
+ return false;
67
+ }
68
+ fillSolution(grid, solution) {
69
+ return grid.withTiles(tiles => {
70
+ return tiles.map((row, y) => row.map((tile, x) => {
71
+ if (!tile.exists || tile.fixed)
72
+ return tile;
73
+ const solutionTile = solution.tiles[y][x];
74
+ return tile.withColor(solutionTile.color);
75
+ }));
76
+ });
77
+ }
78
+ fixGrid(grid) {
79
+ return grid.withTiles(tiles => {
80
+ return tiles.map(row => row.map(tile => {
81
+ if (tile.fixed)
82
+ return tile;
83
+ return tile.withFixed(tile.color !== Color.Gray);
84
+ }));
85
+ });
86
+ }
87
+ async *solveWithProgress(solver, grid, progress, abortSignal) {
88
+ for await (const updatedGrid of solver.solve(progress, abortSignal)) {
89
+ if (abortSignal?.aborted)
90
+ return;
91
+ if (!updatedGrid)
92
+ return updatedGrid;
93
+ yield this.fillSolution(grid, updatedGrid);
94
+ }
95
+ }
96
+ async solveOne(generator) {
97
+ // eslint-disable-next-line no-unreachable-loop
98
+ for await (const grid of generator) {
99
+ return grid;
100
+ }
101
+ return null;
102
+ }
103
+ async *solve(grid, abortSignal) {
104
+ if (!!grid.findRule(r => AutoSolver.nonAdditiveInstructions.has(r.id)) ||
105
+ !!grid.findSymbol(s => AutoSolver.nonAdditiveInstructions.has(s.id))) {
106
+ for (const solver of allSolvers.values()) {
107
+ if (solver.id === this.id)
108
+ continue;
109
+ if (solver.isGridSupported(grid)) {
110
+ yield* solver.solve(grid, abortSignal);
111
+ return;
112
+ }
113
+ }
114
+ throw new Error('No solver supports the given grid');
115
+ }
116
+ else {
117
+ let progressGrid = grid;
118
+ for (const solver of allSolvers.values()) {
119
+ if (solver.id === this.id)
120
+ continue;
121
+ if (solver.isGridSupported(progressGrid)) {
122
+ yield* this.solveWithProgress(solver, grid, progressGrid, abortSignal);
123
+ return;
124
+ }
125
+ else if (solver.isGridSupported(grid)) {
126
+ yield* solver.solve(grid, abortSignal);
127
+ return;
128
+ }
129
+ else {
130
+ let undercluedGrid = progressGrid
131
+ .withRules(rules => rules.filter(r => solver.isInstructionSupported(r.id)))
132
+ .withSymbols(symbols => {
133
+ for (const id of symbols.keys()) {
134
+ if (!solver.isInstructionSupported(id))
135
+ symbols.delete(id);
136
+ }
137
+ return symbols;
138
+ })
139
+ .addRule(new UndercluedRule());
140
+ if (!solver.isGridSupported(undercluedGrid)) {
141
+ // special case for solvers that support lotus and galaxy symbols but not dual-color placement
142
+ undercluedGrid = undercluedGrid.withSymbols(symbols => {
143
+ symbols.delete(lotusInstance.id);
144
+ symbols.delete(galaxyInstance.id);
145
+ return symbols;
146
+ });
147
+ }
148
+ if (!solver.isGridSupported(undercluedGrid))
149
+ continue;
150
+ const undercluedSolution = await this.solveOne(this.solveWithProgress(solver, progressGrid, undercluedGrid, abortSignal));
151
+ if (undercluedSolution === null)
152
+ continue;
153
+ if (undercluedSolution.getTileCount(true, false, Color.Gray) === 0) {
154
+ const result = this.fillSolution(grid, undercluedSolution);
155
+ if (validateGrid(result, null).final !== State.Error) {
156
+ yield result;
157
+ yield null;
158
+ return;
159
+ }
160
+ else {
161
+ yield null;
162
+ return;
163
+ }
164
+ }
165
+ progressGrid = this.fixGrid(undercluedSolution);
166
+ }
167
+ }
168
+ yield this.fillSolution(grid, progressGrid);
169
+ }
170
+ }
171
+ }
172
+ Object.defineProperty(AutoSolver, "nonAdditiveInstructions", {
173
+ enumerable: true,
174
+ configurable: true,
175
+ writable: true,
176
+ value: new Set([
177
+ offByXInstance.id,
178
+ lyingSymbolInstance.id,
179
+ ])
180
+ });
181
+ export default AutoSolver;
@@ -4,7 +4,7 @@ export default class CspuzSolver extends EventIteratingSolver {
4
4
  private static readonly supportedInstrs;
5
5
  readonly id = "cspuz";
6
6
  readonly author = "semiexp";
7
- readonly description = "A blazingly fast WebAssembly solver that supports most rules and symbols (including underclued). No uniqueness check yet.";
7
+ readonly description = "A blazingly fast WebAssembly solver that supports most rules and symbols (including underclued).";
8
8
  protected createWorker(): Worker;
9
9
  isGridSupported(grid: GridData): boolean;
10
10
  isInstructionSupported(instructionId: string): boolean;
@@ -36,7 +36,7 @@ class CspuzSolver extends EventIteratingSolver {
36
36
  enumerable: true,
37
37
  configurable: true,
38
38
  writable: true,
39
- value: 'A blazingly fast WebAssembly solver that supports most rules and symbols (including underclued). No uniqueness check yet.'
39
+ value: 'A blazingly fast WebAssembly solver that supports most rules and symbols (including underclued).'
40
40
  });
41
41
  }
42
42
  createWorker() {
@@ -14,10 +14,7 @@ function stringToColor(str) {
14
14
  return Color.Gray;
15
15
  }
16
16
  }
17
- onmessage = e => {
18
- const grid = Serializer.parseGrid(e.data);
19
- const puzzleData = gridToJson(grid);
20
- const solverResult = solveLogicPad(puzzleData, !!grid.findRule(r => r.id === undercluedInstance.id));
17
+ function postSolution(grid, solverResult) {
21
18
  if (solverResult === null) {
22
19
  postMessage(null);
23
20
  }
@@ -40,5 +37,47 @@ onmessage = e => {
40
37
  postMessage(Serializer.stringifyGrid(solution));
41
38
  }
42
39
  }
40
+ }
41
+ onmessage = e => {
42
+ const grid = Serializer.parseGrid(e.data);
43
+ const isUnderclued = !!grid.findRule(r => r.id === undercluedInstance.id);
44
+ const puzzleData = gridToJson(grid);
45
+ const solverResult = solveLogicPad(puzzleData, isUnderclued);
46
+ postSolution(grid, solverResult);
47
+ // Make use of the underclued mode to determine solution uniqueness
48
+ if (solverResult !== null && !('error' in solverResult) && !isUnderclued) {
49
+ const undercluedResult = solveLogicPad(puzzleData, true);
50
+ if (undercluedResult === null) {
51
+ postMessage(undefined); // Shouldn't happen because underclued grids should always be solvable
52
+ }
53
+ else if ('error' in undercluedResult) {
54
+ throw new Error(undercluedResult.error);
55
+ }
56
+ else if (undercluedResult.every((row, y) => row.every((cell, x) => cell !== null || !grid.getTile(x, y).exists))) {
57
+ postMessage(null);
58
+ }
59
+ else {
60
+ let tweaked = false;
61
+ for (const [y, row] of undercluedResult.entries()) {
62
+ for (const [x, color] of row.entries()) {
63
+ if (color !== null) {
64
+ puzzleData.tiles[y][x].fixed = true;
65
+ puzzleData.tiles[y][x].color = color;
66
+ }
67
+ else if (!tweaked) {
68
+ const positions = grid.connections.getConnectedTiles({ x, y });
69
+ const newColor = solverResult[y][x] === 'dark' ? 'light' : 'dark';
70
+ positions.forEach(({ x: px, y: py }) => {
71
+ puzzleData.tiles[py][px].fixed = true;
72
+ puzzleData.tiles[py][px].color = newColor;
73
+ });
74
+ tweaked = true;
75
+ }
76
+ }
77
+ }
78
+ const secondResult = solveLogicPad(puzzleData, false);
79
+ postSolution(grid, secondResult);
80
+ }
81
+ }
43
82
  postMessage(undefined);
44
83
  };
@@ -3,5 +3,6 @@ import Solver from './solver.js';
3
3
  export default abstract class EventIteratingSolver extends Solver {
4
4
  readonly supportsCancellation = true;
5
5
  protected abstract createWorker(): Worker;
6
+ protected isEnvironmentSupported(): Promise<boolean>;
6
7
  solve(grid: GridData, abortSignal?: AbortSignal): AsyncGenerator<GridData | null>;
7
8
  }
@@ -11,6 +11,16 @@ export default class EventIteratingSolver extends Solver {
11
11
  value: true
12
12
  });
13
13
  }
14
+ isEnvironmentSupported() {
15
+ try {
16
+ const worker = this.createWorker();
17
+ worker.terminate();
18
+ return Promise.resolve(true);
19
+ }
20
+ catch (ex) {
21
+ return Promise.resolve(false);
22
+ }
23
+ }
14
24
  async *solve(grid, abortSignal) {
15
25
  const worker = this.createWorker();
16
26
  const terminateHandler = () => worker.terminate();
@@ -1,3 +1,4 @@
1
+ import { CachedAccess } from '../dataHelper.js';
1
2
  import GridData from '../grid.js';
2
3
  /**
3
4
  * Base class that all solvers must extend.
@@ -49,7 +50,8 @@ export default abstract class Solver {
49
50
  *
50
51
  * @returns A promise that resolves to `true` if the environment is supported, or `false` otherwise.
51
52
  */
52
- isEnvironmentSupported(): Promise<boolean>;
53
+ protected isEnvironmentSupported(): Promise<boolean>;
54
+ readonly environmentCheck: CachedAccess<Promise<boolean>>;
53
55
  /**
54
56
  * Check if the solver supports the given instruction. This is used to render a small indication in the UI for each
55
57
  * instruction in the editor.
@@ -1,9 +1,18 @@
1
+ import { CachedAccess } from '../dataHelper.js';
1
2
  import { allRules } from '../rules/index.js';
2
3
  import { allSymbols } from '../symbols/index.js';
3
4
  /**
4
5
  * Base class that all solvers must extend.
5
6
  */
6
7
  export default class Solver {
8
+ constructor() {
9
+ Object.defineProperty(this, "environmentCheck", {
10
+ enumerable: true,
11
+ configurable: true,
12
+ writable: true,
13
+ value: CachedAccess.of(() => this.isEnvironmentSupported())
14
+ });
15
+ }
7
16
  /**
8
17
  * Check if the solver supports the current browser environment. This method is called once when the user first clicks
9
18
  * the "Solve" button, and the result is cached for the duration of the editor session.
@@ -5,7 +5,7 @@ export default class Z3Solver extends Solver {
5
5
  readonly author = "Lysine";
6
6
  readonly description = "(Obsolete) A WebAssembly solver that supports a limited set of rules and symbols.";
7
7
  readonly supportsCancellation = false;
8
- isEnvironmentSupported(): Promise<boolean>;
8
+ protected isEnvironmentSupported(): Promise<boolean>;
9
9
  solve(grid: GridData): AsyncGenerator<GridData | null>;
10
10
  isInstructionSupported(instructionId: string): boolean;
11
11
  isGridSupported(grid: GridData): boolean;
package/dist/index.d.ts CHANGED
@@ -20,6 +20,7 @@ import CellCountPerZoneRule from './data/rules/cellCountPerZoneRule.js';
20
20
  import CellCountRule from './data/rules/cellCountRule.js';
21
21
  import CompletePatternRule from './data/rules/completePatternRule.js';
22
22
  import ConnectAllRule from './data/rules/connectAllRule.js';
23
+ import ContainsShapeRule from './data/rules/containsShapeRule.js';
23
24
  import CustomRule from './data/rules/customRule.js';
24
25
  import ForesightRule from './data/rules/foresightRule.js';
25
26
  import { allRules } from './data/rules/index.js';
@@ -45,8 +46,9 @@ import GzipCompressor from './data/serializer/compressor/gzipCompressor.js';
45
46
  import StreamCompressor from './data/serializer/compressor/streamCompressor.js';
46
47
  import SerializerBase from './data/serializer/serializerBase.js';
47
48
  import SerializerV0 from './data/serializer/serializer_v0.js';
48
- import { getShapeVariants, normalizeShape, positionsToShape, shapeEquals, tilesToShape } from './data/shapes.js';
49
+ import { getShapeVariants, normalizeShape, positionsToShape, sanitizePatternGrid, shapeEquals, tilesToShape } from './data/shapes.js';
49
50
  import { allSolvers } from './data/solver/allSolvers.js';
51
+ import AutoSolver from './data/solver/auto/autoSolver.js';
50
52
  import BacktrackSolver from './data/solver/backtrack/backtrackSolver.js';
51
53
  import BTModule, { BTGridData, BTTile, IntArray2D, colorToBTTile, createOneTileResult, getOppositeColor } from './data/solver/backtrack/data.js';
52
54
  import BanPatternBTModule from './data/solver/backtrack/rules/banPattern.js';
@@ -106,4 +108,4 @@ import ViewpointSymbol from './data/symbols/viewpointSymbol.js';
106
108
  import TileData from './data/tile.js';
107
109
  import TileConnections from './data/tileConnections.js';
108
110
  import validateGrid, { aggregateState, applyFinalOverrides } from './data/validate.js';
109
- export { ConfigType, configEquals, Configurable, CachedAccess, allEqual, array, directionToRotation, escape, isSameEdge, maxBy, minBy, move, orientationToRotation, resize, unescape, isEventHandler, handlesFinalValidation, handlesGetTile, handlesGridChange, handlesGridResize, handlesSetGrid, invokeSetGrid, handlesSymbolDisplay, handlesSymbolValidation, GridData, NEIGHBOR_OFFSETS, GridConnections, GridZones, Instruction, COMPARISONS, Color, Comparison, DIRECTIONS, Direction, MajorRule, Mode, ORIENTATIONS, Orientation, State, WRAPPINGS, Wrapping, directionToggle, orientationToggle, MetadataSchema, PuzzleSchema, BanPatternRule, CellCountPerZoneRule, CellCountRule, CompletePatternRule, ConnectAllRule, CustomRule, ForesightRule, allRules, LyingSymbolRule, ControlLine, Row, MusicGridRule, MysteryRule, OffByXRule, PerfectionRule, RegionAreaRule, RegionShapeRule, Rule, SameShapeRule, SymbolsPerRegionRule, UndercluedRule, UniqueShapeRule, WrapAroundRule, Serializer, Compressor, CompressorBase, DeflateCompressor, GzipCompressor, StreamCompressor, SerializerBase, SerializerV0, getShapeVariants, normalizeShape, positionsToShape, shapeEquals, tilesToShape, allSolvers, BacktrackSolver, BTModule, BTGridData, BTTile, IntArray2D, colorToBTTile, createOneTileResult, getOppositeColor, BanPatternBTModule, CellCountBTModule, ConnectAllBTModule, RegionAreaBTModule, RegionShapeBTModule, SameShapeBTModule, SymbolsPerRegionBTModule, UniqueShapeBTModule, AreaNumberBTModule, DartBTModule, DirectionLinkerBTModule, FocusBTModule, GalaxyBTModule, LetterBTModule, LotusBTModule, MinesweeperBTModule, MyopiaBTModule, ViewpointBTModule, CspuzSolver, gridToJson, EventIteratingSolver, Solver, UniversalSolver, AreaNumberModule, CellCountModule, ConnectAllModule, DartModule, allZ3Modules, LetterModule, MyopiaModule, RegionAreaModule, ViewpointModule, Z3Module, convertDirection, Z3Solver, Z3SolverContext, AreaNumberSymbol, CustomIconSymbol, CustomSymbol, CustomTextSymbol, DartSymbol, DirectionLinkerSymbol, FocusSymbol, GalaxySymbol, HiddenSymbol, allSymbols, LetterSymbol, LotusSymbol, MinesweeperSymbol, MultiEntrySymbol, MyopiaSymbol, NumberSymbol, Symbol, ViewpointSymbol, TileData, TileConnections, validateGrid, aggregateState, applyFinalOverrides, };
111
+ export { ConfigType, configEquals, Configurable, CachedAccess, allEqual, array, directionToRotation, escape, isSameEdge, maxBy, minBy, move, orientationToRotation, resize, unescape, isEventHandler, handlesFinalValidation, handlesGetTile, handlesGridChange, handlesGridResize, handlesSetGrid, invokeSetGrid, handlesSymbolDisplay, handlesSymbolValidation, GridData, NEIGHBOR_OFFSETS, GridConnections, GridZones, Instruction, COMPARISONS, Color, Comparison, DIRECTIONS, Direction, MajorRule, Mode, ORIENTATIONS, Orientation, State, WRAPPINGS, Wrapping, directionToggle, orientationToggle, MetadataSchema, PuzzleSchema, BanPatternRule, CellCountPerZoneRule, CellCountRule, CompletePatternRule, ConnectAllRule, ContainsShapeRule, CustomRule, ForesightRule, allRules, LyingSymbolRule, ControlLine, Row, MusicGridRule, MysteryRule, OffByXRule, PerfectionRule, RegionAreaRule, RegionShapeRule, Rule, SameShapeRule, SymbolsPerRegionRule, UndercluedRule, UniqueShapeRule, WrapAroundRule, Serializer, Compressor, CompressorBase, DeflateCompressor, GzipCompressor, StreamCompressor, SerializerBase, SerializerV0, getShapeVariants, normalizeShape, positionsToShape, sanitizePatternGrid, shapeEquals, tilesToShape, allSolvers, AutoSolver, BacktrackSolver, BTModule, BTGridData, BTTile, IntArray2D, colorToBTTile, createOneTileResult, getOppositeColor, BanPatternBTModule, CellCountBTModule, ConnectAllBTModule, RegionAreaBTModule, RegionShapeBTModule, SameShapeBTModule, SymbolsPerRegionBTModule, UniqueShapeBTModule, AreaNumberBTModule, DartBTModule, DirectionLinkerBTModule, FocusBTModule, GalaxyBTModule, LetterBTModule, LotusBTModule, MinesweeperBTModule, MyopiaBTModule, ViewpointBTModule, CspuzSolver, gridToJson, EventIteratingSolver, Solver, UniversalSolver, AreaNumberModule, CellCountModule, ConnectAllModule, DartModule, allZ3Modules, LetterModule, MyopiaModule, RegionAreaModule, ViewpointModule, Z3Module, convertDirection, Z3Solver, Z3SolverContext, AreaNumberSymbol, CustomIconSymbol, CustomSymbol, CustomTextSymbol, DartSymbol, DirectionLinkerSymbol, FocusSymbol, GalaxySymbol, HiddenSymbol, allSymbols, LetterSymbol, LotusSymbol, MinesweeperSymbol, MultiEntrySymbol, MyopiaSymbol, NumberSymbol, Symbol, ViewpointSymbol, TileData, TileConnections, validateGrid, aggregateState, applyFinalOverrides, };
package/dist/index.js CHANGED
@@ -23,6 +23,7 @@ import CellCountPerZoneRule from './data/rules/cellCountPerZoneRule.js';
23
23
  import CellCountRule from './data/rules/cellCountRule.js';
24
24
  import CompletePatternRule from './data/rules/completePatternRule.js';
25
25
  import ConnectAllRule from './data/rules/connectAllRule.js';
26
+ import ContainsShapeRule from './data/rules/containsShapeRule.js';
26
27
  import CustomRule from './data/rules/customRule.js';
27
28
  import ForesightRule from './data/rules/foresightRule.js';
28
29
  import { allRules } from './data/rules/index.js';
@@ -48,8 +49,9 @@ import GzipCompressor from './data/serializer/compressor/gzipCompressor.js';
48
49
  import StreamCompressor from './data/serializer/compressor/streamCompressor.js';
49
50
  import SerializerBase from './data/serializer/serializerBase.js';
50
51
  import SerializerV0 from './data/serializer/serializer_v0.js';
51
- import { getShapeVariants, normalizeShape, positionsToShape, shapeEquals, tilesToShape } from './data/shapes.js';
52
+ import { getShapeVariants, normalizeShape, positionsToShape, sanitizePatternGrid, shapeEquals, tilesToShape } from './data/shapes.js';
52
53
  import { allSolvers } from './data/solver/allSolvers.js';
54
+ import AutoSolver from './data/solver/auto/autoSolver.js';
53
55
  import BacktrackSolver from './data/solver/backtrack/backtrackSolver.js';
54
56
  import BTModule, { BTGridData, BTTile, IntArray2D, colorToBTTile, createOneTileResult, getOppositeColor } from './data/solver/backtrack/data.js';
55
57
  import BanPatternBTModule from './data/solver/backtrack/rules/banPattern.js';
@@ -109,4 +111,4 @@ import ViewpointSymbol from './data/symbols/viewpointSymbol.js';
109
111
  import TileData from './data/tile.js';
110
112
  import TileConnections from './data/tileConnections.js';
111
113
  import validateGrid, { aggregateState, applyFinalOverrides } from './data/validate.js';
112
- export { ConfigType, configEquals, Configurable, CachedAccess, allEqual, array, directionToRotation, escape, isSameEdge, maxBy, minBy, move, orientationToRotation, resize, unescape, isEventHandler, handlesFinalValidation, handlesGetTile, handlesGridChange, handlesGridResize, handlesSetGrid, invokeSetGrid, handlesSymbolDisplay, handlesSymbolValidation, GridData, NEIGHBOR_OFFSETS, GridConnections, GridZones, Instruction, COMPARISONS, Color, Comparison, DIRECTIONS, Direction, MajorRule, Mode, ORIENTATIONS, Orientation, State, WRAPPINGS, Wrapping, directionToggle, orientationToggle, MetadataSchema, PuzzleSchema, BanPatternRule, CellCountPerZoneRule, CellCountRule, CompletePatternRule, ConnectAllRule, CustomRule, ForesightRule, allRules, LyingSymbolRule, ControlLine, Row, MusicGridRule, MysteryRule, OffByXRule, PerfectionRule, RegionAreaRule, RegionShapeRule, Rule, SameShapeRule, SymbolsPerRegionRule, UndercluedRule, UniqueShapeRule, WrapAroundRule, Serializer, Compressor, CompressorBase, DeflateCompressor, GzipCompressor, StreamCompressor, SerializerBase, SerializerV0, getShapeVariants, normalizeShape, positionsToShape, shapeEquals, tilesToShape, allSolvers, BacktrackSolver, BTModule, BTGridData, BTTile, IntArray2D, colorToBTTile, createOneTileResult, getOppositeColor, BanPatternBTModule, CellCountBTModule, ConnectAllBTModule, RegionAreaBTModule, RegionShapeBTModule, SameShapeBTModule, SymbolsPerRegionBTModule, UniqueShapeBTModule, AreaNumberBTModule, DartBTModule, DirectionLinkerBTModule, FocusBTModule, GalaxyBTModule, LetterBTModule, LotusBTModule, MinesweeperBTModule, MyopiaBTModule, ViewpointBTModule, CspuzSolver, gridToJson, EventIteratingSolver, Solver, UniversalSolver, AreaNumberModule, CellCountModule, ConnectAllModule, DartModule, allZ3Modules, LetterModule, MyopiaModule, RegionAreaModule, ViewpointModule, Z3Module, convertDirection, Z3Solver, Z3SolverContext, AreaNumberSymbol, CustomIconSymbol, CustomSymbol, CustomTextSymbol, DartSymbol, DirectionLinkerSymbol, FocusSymbol, GalaxySymbol, HiddenSymbol, allSymbols, LetterSymbol, LotusSymbol, MinesweeperSymbol, MultiEntrySymbol, MyopiaSymbol, NumberSymbol, Symbol, ViewpointSymbol, TileData, TileConnections, validateGrid, aggregateState, applyFinalOverrides, };
114
+ export { ConfigType, configEquals, Configurable, CachedAccess, allEqual, array, directionToRotation, escape, isSameEdge, maxBy, minBy, move, orientationToRotation, resize, unescape, isEventHandler, handlesFinalValidation, handlesGetTile, handlesGridChange, handlesGridResize, handlesSetGrid, invokeSetGrid, handlesSymbolDisplay, handlesSymbolValidation, GridData, NEIGHBOR_OFFSETS, GridConnections, GridZones, Instruction, COMPARISONS, Color, Comparison, DIRECTIONS, Direction, MajorRule, Mode, ORIENTATIONS, Orientation, State, WRAPPINGS, Wrapping, directionToggle, orientationToggle, MetadataSchema, PuzzleSchema, BanPatternRule, CellCountPerZoneRule, CellCountRule, CompletePatternRule, ConnectAllRule, ContainsShapeRule, CustomRule, ForesightRule, allRules, LyingSymbolRule, ControlLine, Row, MusicGridRule, MysteryRule, OffByXRule, PerfectionRule, RegionAreaRule, RegionShapeRule, Rule, SameShapeRule, SymbolsPerRegionRule, UndercluedRule, UniqueShapeRule, WrapAroundRule, Serializer, Compressor, CompressorBase, DeflateCompressor, GzipCompressor, StreamCompressor, SerializerBase, SerializerV0, getShapeVariants, normalizeShape, positionsToShape, sanitizePatternGrid, shapeEquals, tilesToShape, allSolvers, AutoSolver, BacktrackSolver, BTModule, BTGridData, BTTile, IntArray2D, colorToBTTile, createOneTileResult, getOppositeColor, BanPatternBTModule, CellCountBTModule, ConnectAllBTModule, RegionAreaBTModule, RegionShapeBTModule, SameShapeBTModule, SymbolsPerRegionBTModule, UniqueShapeBTModule, AreaNumberBTModule, DartBTModule, DirectionLinkerBTModule, FocusBTModule, GalaxyBTModule, LetterBTModule, LotusBTModule, MinesweeperBTModule, MyopiaBTModule, ViewpointBTModule, CspuzSolver, gridToJson, EventIteratingSolver, Solver, UniversalSolver, AreaNumberModule, CellCountModule, ConnectAllModule, DartModule, allZ3Modules, LetterModule, MyopiaModule, RegionAreaModule, ViewpointModule, Z3Module, convertDirection, Z3Solver, Z3SolverContext, AreaNumberSymbol, CustomIconSymbol, CustomSymbol, CustomTextSymbol, DartSymbol, DirectionLinkerSymbol, FocusSymbol, GalaxySymbol, HiddenSymbol, allSymbols, LetterSymbol, LotusSymbol, MinesweeperSymbol, MultiEntrySymbol, MyopiaSymbol, NumberSymbol, Symbol, ViewpointSymbol, TileData, TileConnections, validateGrid, aggregateState, applyFinalOverrides, };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logic-pad/core",
3
- "version": "0.10.1",
3
+ "version": "0.11.0",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",