@logic-pad/core 0.2.2 → 0.4.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 +118 -4
- package/dist/data/config.d.ts +11 -3
- package/dist/data/config.js +17 -0
- package/dist/data/dataHelper.d.ts +8 -1
- package/dist/data/dataHelper.js +10 -0
- package/dist/data/events/onSetGrid.d.ts +1 -1
- package/dist/data/grid.d.ts +9 -0
- package/dist/data/grid.js +27 -7
- package/dist/data/gridConnections.js +1 -4
- package/dist/data/rules/cellCountPerZoneRule.d.ts +33 -0
- package/dist/data/rules/cellCountPerZoneRule.js +183 -0
- package/dist/data/rules/foresightRule.d.ts +5 -3
- package/dist/data/rules/foresightRule.js +17 -3
- package/dist/data/rules/musicGridRule.d.ts +1 -1
- package/dist/data/rules/musicGridRule.js +1 -1
- package/dist/data/rules/perfectionRule.d.ts +35 -0
- package/dist/data/rules/perfectionRule.js +113 -0
- package/dist/data/rules/rules.gen.d.ts +2 -0
- package/dist/data/rules/rules.gen.js +2 -0
- package/dist/data/serializer/serializer_v0.js +37 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.js +5 -3
- package/package.json +1 -1
|
@@ -188,6 +188,13 @@ declare global {
|
|
|
188
188
|
x: number;
|
|
189
189
|
y: number;
|
|
190
190
|
};
|
|
191
|
+
/**
|
|
192
|
+
* Check if two edges are the same, regardless of direction.
|
|
193
|
+
* @param a The first edge.
|
|
194
|
+
* @param b The second edge.
|
|
195
|
+
* @returns Whether the edges are the same.
|
|
196
|
+
*/
|
|
197
|
+
export declare function isSameEdge(a: Edge, b: Edge): boolean;
|
|
191
198
|
/**
|
|
192
199
|
* Convert the given direction to a rotation in degrees.
|
|
193
200
|
* @param direction The direction to convert.
|
|
@@ -401,7 +408,11 @@ declare global {
|
|
|
401
408
|
val: T
|
|
402
409
|
): val is T & GridChangeHandler;
|
|
403
410
|
export interface SetGridHandler {
|
|
404
|
-
onSetGrid(
|
|
411
|
+
onSetGrid(
|
|
412
|
+
oldGrid: GridData,
|
|
413
|
+
newGrid: GridData,
|
|
414
|
+
solution: GridData | null
|
|
415
|
+
): GridData;
|
|
405
416
|
}
|
|
406
417
|
export declare function handlesSetGrid<T extends Instruction>(
|
|
407
418
|
val: T
|
|
@@ -504,7 +515,11 @@ declare global {
|
|
|
504
515
|
createExampleGrid(): GridData;
|
|
505
516
|
get searchVariants(): SearchVariant[];
|
|
506
517
|
validateGrid(_grid: GridData): RuleState;
|
|
507
|
-
onSetGrid(
|
|
518
|
+
onSetGrid(
|
|
519
|
+
_oldGrid: GridData,
|
|
520
|
+
newGrid: GridData,
|
|
521
|
+
_solution: GridData | null
|
|
522
|
+
): GridData;
|
|
508
523
|
onGridChange(newGrid: GridData): this;
|
|
509
524
|
onGridResize(
|
|
510
525
|
_grid: GridData,
|
|
@@ -569,6 +584,7 @@ declare global {
|
|
|
569
584
|
get validateWithSolution(): boolean;
|
|
570
585
|
get isSingleton(): boolean;
|
|
571
586
|
}
|
|
587
|
+
export declare const NEIGHBOR_OFFSETS: Position$1[];
|
|
572
588
|
export declare class GridData {
|
|
573
589
|
readonly width: number;
|
|
574
590
|
readonly height: number;
|
|
@@ -944,6 +960,14 @@ declare global {
|
|
|
944
960
|
* @returns True if the grids are equal in size and tile colors, false otherwise.
|
|
945
961
|
*/
|
|
946
962
|
colorEquals(grid: GridData): boolean;
|
|
963
|
+
/**
|
|
964
|
+
* Check if this grid conforms to the given solution, or an incomplete version of the solution.
|
|
965
|
+
* Symbols and rules are not validated.
|
|
966
|
+
*
|
|
967
|
+
* @param solution The solution to compare with.
|
|
968
|
+
* @returns True if the grid conforms to the solution, false otherwise.
|
|
969
|
+
*/
|
|
970
|
+
solutionMatches(solution: GridData): boolean;
|
|
947
971
|
/**
|
|
948
972
|
* Check if this grid is equal to another grid in terms of size, tile colors, connections, symbols, and rules.
|
|
949
973
|
*
|
|
@@ -1014,6 +1038,8 @@ declare global {
|
|
|
1014
1038
|
Icon = 'icon',
|
|
1015
1039
|
ControlLines = 'controlLines',
|
|
1016
1040
|
NullableNote = 'nullableNote',
|
|
1041
|
+
SolvePath = 'solvePath',
|
|
1042
|
+
Edges = 'edges',
|
|
1017
1043
|
}
|
|
1018
1044
|
export interface Config<T> {
|
|
1019
1045
|
readonly type: ConfigType;
|
|
@@ -1084,6 +1110,12 @@ declare global {
|
|
|
1084
1110
|
export interface NullableNoteConfig extends Config<string | null> {
|
|
1085
1111
|
readonly type: ConfigType.NullableNote;
|
|
1086
1112
|
}
|
|
1113
|
+
export interface SolvePathConfig extends Config<Position$1[]> {
|
|
1114
|
+
readonly type: ConfigType.SolvePath;
|
|
1115
|
+
}
|
|
1116
|
+
export interface EdgesConfig extends Config<Edge[]> {
|
|
1117
|
+
readonly type: ConfigType.Edges;
|
|
1118
|
+
}
|
|
1087
1119
|
export type AnyConfig =
|
|
1088
1120
|
| BooleanConfig
|
|
1089
1121
|
| NullableBooleanConfig
|
|
@@ -1101,7 +1133,9 @@ declare global {
|
|
|
1101
1133
|
| NullableGridConfig
|
|
1102
1134
|
| IconConfig
|
|
1103
1135
|
| ControlLinesConfig
|
|
1104
|
-
| NullableNoteConfig
|
|
1136
|
+
| NullableNoteConfig
|
|
1137
|
+
| SolvePathConfig
|
|
1138
|
+
| EdgesConfig;
|
|
1105
1139
|
/**
|
|
1106
1140
|
* Compare two config values for equality, using an appropriate method for the config type.
|
|
1107
1141
|
*
|
|
@@ -1311,6 +1345,39 @@ declare global {
|
|
|
1311
1345
|
copyWith({ pattern }: { pattern?: GridData }): this;
|
|
1312
1346
|
withPattern(pattern: GridData): this;
|
|
1313
1347
|
}
|
|
1348
|
+
export declare class CellCountPerZoneRule extends Rule {
|
|
1349
|
+
readonly color: Color;
|
|
1350
|
+
readonly edges: readonly Edge[];
|
|
1351
|
+
private static readonly CONFIGS;
|
|
1352
|
+
private static readonly EXAMPLE_GRID_LIGHT;
|
|
1353
|
+
private static readonly EXAMPLE_GRID_DARK;
|
|
1354
|
+
private static readonly EXAMPLE_GRID_GRAY;
|
|
1355
|
+
private static readonly SEARCH_VARIANTS;
|
|
1356
|
+
/**
|
|
1357
|
+
* **Every zone has the same number of <color> cells.**
|
|
1358
|
+
*
|
|
1359
|
+
* @param color - The color of the cells to count.
|
|
1360
|
+
* @param edges - The edges of the zones to count.
|
|
1361
|
+
*/
|
|
1362
|
+
constructor(color: Color, edges: readonly Edge[]);
|
|
1363
|
+
get id(): string;
|
|
1364
|
+
get explanation(): string;
|
|
1365
|
+
get configs(): readonly AnyConfig[] | null;
|
|
1366
|
+
createExampleGrid(): GridData;
|
|
1367
|
+
get searchVariants(): SearchVariant[];
|
|
1368
|
+
validateGrid(grid: GridData): RuleState;
|
|
1369
|
+
copyWith({
|
|
1370
|
+
color,
|
|
1371
|
+
edges,
|
|
1372
|
+
}: {
|
|
1373
|
+
color?: Color;
|
|
1374
|
+
edges?: readonly Edge[];
|
|
1375
|
+
}): this;
|
|
1376
|
+
withColor(color: Color): this;
|
|
1377
|
+
withEdges(
|
|
1378
|
+
edges: readonly Edge[] | ((edges: readonly Edge[]) => readonly Edge[])
|
|
1379
|
+
): this;
|
|
1380
|
+
}
|
|
1314
1381
|
export declare class CellCountRule extends Rule {
|
|
1315
1382
|
readonly color: Color;
|
|
1316
1383
|
readonly count: number;
|
|
@@ -1390,13 +1457,19 @@ declare global {
|
|
|
1390
1457
|
readonly count: number;
|
|
1391
1458
|
readonly regenInterval: number;
|
|
1392
1459
|
readonly startFull: boolean;
|
|
1460
|
+
readonly solvePath: Position$1[];
|
|
1393
1461
|
private static readonly EXAMPLE_GRID;
|
|
1394
1462
|
private static readonly CONFIGS;
|
|
1395
1463
|
private static readonly SEARCH_VARIANTS;
|
|
1396
1464
|
/**
|
|
1397
1465
|
* **Foresight: Show hints**
|
|
1398
1466
|
*/
|
|
1399
|
-
constructor(
|
|
1467
|
+
constructor(
|
|
1468
|
+
count: number,
|
|
1469
|
+
regenInterval: number,
|
|
1470
|
+
startFull: boolean,
|
|
1471
|
+
solvePath?: Position$1[]
|
|
1472
|
+
);
|
|
1400
1473
|
get id(): string;
|
|
1401
1474
|
get explanation(): string;
|
|
1402
1475
|
get visibleWhenSolving(): boolean;
|
|
@@ -1410,10 +1483,12 @@ declare global {
|
|
|
1410
1483
|
count,
|
|
1411
1484
|
regenInterval,
|
|
1412
1485
|
startFull,
|
|
1486
|
+
solvePath,
|
|
1413
1487
|
}: {
|
|
1414
1488
|
count?: number;
|
|
1415
1489
|
regenInterval?: number;
|
|
1416
1490
|
startFull?: boolean;
|
|
1491
|
+
solvePath?: Position$1[];
|
|
1417
1492
|
}): this;
|
|
1418
1493
|
}
|
|
1419
1494
|
export declare const allRules: Map<string, Rule>;
|
|
@@ -1490,6 +1565,45 @@ declare global {
|
|
|
1490
1565
|
copyWith({ number }: { number?: number }): this;
|
|
1491
1566
|
withNumber(number: number): this;
|
|
1492
1567
|
}
|
|
1568
|
+
export declare class PerfectionRule
|
|
1569
|
+
extends Rule
|
|
1570
|
+
implements SetGridHandler, FinalValidationHandler
|
|
1571
|
+
{
|
|
1572
|
+
private static readonly EXAMPLE_GRID;
|
|
1573
|
+
private static readonly SEARCH_VARIANTS;
|
|
1574
|
+
/**
|
|
1575
|
+
* **Quest for Perfection: cell colors are final**
|
|
1576
|
+
*/
|
|
1577
|
+
constructor();
|
|
1578
|
+
get id(): string;
|
|
1579
|
+
get explanation(): string;
|
|
1580
|
+
get configs(): readonly AnyConfig[] | null;
|
|
1581
|
+
createExampleGrid(): GridData;
|
|
1582
|
+
get searchVariants(): SearchVariant[];
|
|
1583
|
+
get necessaryForCompletion(): boolean;
|
|
1584
|
+
get isSingleton(): boolean;
|
|
1585
|
+
validateGrid(grid: GridData): RuleState;
|
|
1586
|
+
/**
|
|
1587
|
+
* If the grid passes validation but is different from the solution, indicate the error in the final state.
|
|
1588
|
+
*/
|
|
1589
|
+
onFinalValidation(
|
|
1590
|
+
grid: GridData,
|
|
1591
|
+
solution: GridData | null,
|
|
1592
|
+
state: GridState
|
|
1593
|
+
): GridState;
|
|
1594
|
+
private fixTiles;
|
|
1595
|
+
/**
|
|
1596
|
+
* Force all tiles to be fixed.
|
|
1597
|
+
*
|
|
1598
|
+
* If the grid is already wrong, prevent the player from changing it further.
|
|
1599
|
+
*/
|
|
1600
|
+
onSetGrid(
|
|
1601
|
+
oldGrid: GridData,
|
|
1602
|
+
newGrid: GridData,
|
|
1603
|
+
solution: GridData | null
|
|
1604
|
+
): GridData;
|
|
1605
|
+
copyWith(_: object): this;
|
|
1606
|
+
}
|
|
1493
1607
|
export declare class RegionAreaRule extends Rule {
|
|
1494
1608
|
readonly color: Color;
|
|
1495
1609
|
readonly size: number;
|
package/dist/data/config.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import GridData from './grid.js';
|
|
2
|
-
import { Color, Comparison, Direction, DirectionToggle, Orientation, OrientationToggle } from './primitives.js';
|
|
2
|
+
import { Color, Comparison, Direction, DirectionToggle, Edge, Orientation, OrientationToggle, Position } from './primitives.js';
|
|
3
3
|
import { ControlLine } from './rules/musicControlLine.js';
|
|
4
4
|
export declare enum ConfigType {
|
|
5
5
|
Boolean = "boolean",
|
|
@@ -18,7 +18,9 @@ export declare enum ConfigType {
|
|
|
18
18
|
NullableGrid = "nullableGrid",
|
|
19
19
|
Icon = "icon",
|
|
20
20
|
ControlLines = "controlLines",
|
|
21
|
-
NullableNote = "nullableNote"
|
|
21
|
+
NullableNote = "nullableNote",
|
|
22
|
+
SolvePath = "solvePath",
|
|
23
|
+
Edges = "edges"
|
|
22
24
|
}
|
|
23
25
|
export interface Config<T> {
|
|
24
26
|
readonly type: ConfigType;
|
|
@@ -89,7 +91,13 @@ export interface ControlLinesConfig extends Config<ControlLine[]> {
|
|
|
89
91
|
export interface NullableNoteConfig extends Config<string | null> {
|
|
90
92
|
readonly type: ConfigType.NullableNote;
|
|
91
93
|
}
|
|
92
|
-
export
|
|
94
|
+
export interface SolvePathConfig extends Config<Position[]> {
|
|
95
|
+
readonly type: ConfigType.SolvePath;
|
|
96
|
+
}
|
|
97
|
+
export interface EdgesConfig extends Config<Edge[]> {
|
|
98
|
+
readonly type: ConfigType.Edges;
|
|
99
|
+
}
|
|
100
|
+
export type AnyConfig = BooleanConfig | NullableBooleanConfig | NumberConfig | NullableNumberConfig | StringConfig | ColorConfig | ComparisonConfig | DirectionConfig | DirectionToggleConfig | OrientationConfig | OrientationToggleConfig | TileConfig | GridConfig | NullableGridConfig | IconConfig | ControlLinesConfig | NullableNoteConfig | SolvePathConfig | EdgesConfig;
|
|
93
101
|
/**
|
|
94
102
|
* Compare two config values for equality, using an appropriate method for the config type.
|
|
95
103
|
*
|
package/dist/data/config.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isSameEdge } from './dataHelper.js';
|
|
1
2
|
import { DIRECTIONS, ORIENTATIONS, } from './primitives.js';
|
|
2
3
|
export var ConfigType;
|
|
3
4
|
(function (ConfigType) {
|
|
@@ -18,6 +19,8 @@ export var ConfigType;
|
|
|
18
19
|
ConfigType["Icon"] = "icon";
|
|
19
20
|
ConfigType["ControlLines"] = "controlLines";
|
|
20
21
|
ConfigType["NullableNote"] = "nullableNote";
|
|
22
|
+
ConfigType["SolvePath"] = "solvePath";
|
|
23
|
+
ConfigType["Edges"] = "edges";
|
|
21
24
|
})(ConfigType || (ConfigType = {}));
|
|
22
25
|
/**
|
|
23
26
|
* Compare two config values for equality, using an appropriate method for the config type.
|
|
@@ -51,5 +54,19 @@ export function configEquals(type, a, b) {
|
|
|
51
54
|
if (type === ConfigType.OrientationToggle) {
|
|
52
55
|
return ORIENTATIONS.every(dir => a[dir] === b[dir]);
|
|
53
56
|
}
|
|
57
|
+
if (type === ConfigType.SolvePath) {
|
|
58
|
+
const aPath = a;
|
|
59
|
+
const bPath = b;
|
|
60
|
+
if (aPath.length !== bPath.length)
|
|
61
|
+
return false;
|
|
62
|
+
return aPath.every((pos, i) => pos.x === bPath[i].x && pos.y === bPath[i].y);
|
|
63
|
+
}
|
|
64
|
+
if (type === ConfigType.Edges) {
|
|
65
|
+
const aEdges = a;
|
|
66
|
+
const bEdges = b;
|
|
67
|
+
if (aEdges.length !== bEdges.length)
|
|
68
|
+
return false;
|
|
69
|
+
return aEdges.every(aEdge => bEdges.some(bEdge => isSameEdge(aEdge, bEdge)));
|
|
70
|
+
}
|
|
54
71
|
return a === b;
|
|
55
72
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Direction, Orientation, Position } from './primitives.js';
|
|
1
|
+
import { Direction, Edge, Orientation, Position } from './primitives.js';
|
|
2
2
|
/**
|
|
3
3
|
* Offset the given position by a given step in the given direction.
|
|
4
4
|
* @param position The position to offset.
|
|
@@ -10,6 +10,13 @@ export declare function move(position: Position, direction: Direction | Orientat
|
|
|
10
10
|
x: number;
|
|
11
11
|
y: number;
|
|
12
12
|
};
|
|
13
|
+
/**
|
|
14
|
+
* Check if two edges are the same, regardless of direction.
|
|
15
|
+
* @param a The first edge.
|
|
16
|
+
* @param b The second edge.
|
|
17
|
+
* @returns Whether the edges are the same.
|
|
18
|
+
*/
|
|
19
|
+
export declare function isSameEdge(a: Edge, b: Edge): boolean;
|
|
13
20
|
/**
|
|
14
21
|
* Convert the given direction to a rotation in degrees.
|
|
15
22
|
* @param direction The direction to convert.
|
package/dist/data/dataHelper.js
CHANGED
|
@@ -30,6 +30,16 @@ export function move(position, direction, step = 1) {
|
|
|
30
30
|
return { x: position.x + step, y: position.y + step };
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Check if two edges are the same, regardless of direction.
|
|
35
|
+
* @param a The first edge.
|
|
36
|
+
* @param b The second edge.
|
|
37
|
+
* @returns Whether the edges are the same.
|
|
38
|
+
*/
|
|
39
|
+
export function isSameEdge(a, b) {
|
|
40
|
+
return ((a.x1 === b.x1 && a.y1 === b.y1 && a.x2 === b.x2 && a.y2 === b.y2) ||
|
|
41
|
+
(a.x1 === b.x2 && a.y1 === b.y2 && a.x2 === b.x1 && a.y2 === b.y1));
|
|
42
|
+
}
|
|
33
43
|
/**
|
|
34
44
|
* Convert the given direction to a rotation in degrees.
|
|
35
45
|
* @param direction The direction to convert.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import GridData from '../grid.js';
|
|
2
2
|
import Instruction from '../instruction.js';
|
|
3
3
|
export interface SetGridHandler {
|
|
4
|
-
onSetGrid(oldGrid: GridData, newGrid: GridData): GridData;
|
|
4
|
+
onSetGrid(oldGrid: GridData, newGrid: GridData, solution: GridData | null): GridData;
|
|
5
5
|
}
|
|
6
6
|
export declare function handlesSetGrid<T extends Instruction>(val: T): val is T & SetGridHandler;
|
package/dist/data/grid.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ import TileData from './tile.js';
|
|
|
7
7
|
import MusicGridRule from './rules/musicGridRule.js';
|
|
8
8
|
import CompletePatternRule from './rules/completePatternRule.js';
|
|
9
9
|
import UndercluedRule from './rules/undercluedRule.js';
|
|
10
|
+
export declare const NEIGHBOR_OFFSETS: Position[];
|
|
10
11
|
export default class GridData {
|
|
11
12
|
readonly width: number;
|
|
12
13
|
readonly height: number;
|
|
@@ -321,6 +322,14 @@ export default class GridData {
|
|
|
321
322
|
* @returns True if the grids are equal in size and tile colors, false otherwise.
|
|
322
323
|
*/
|
|
323
324
|
colorEquals(grid: GridData): boolean;
|
|
325
|
+
/**
|
|
326
|
+
* Check if this grid conforms to the given solution, or an incomplete version of the solution.
|
|
327
|
+
* Symbols and rules are not validated.
|
|
328
|
+
*
|
|
329
|
+
* @param solution The solution to compare with.
|
|
330
|
+
* @returns True if the grid conforms to the solution, false otherwise.
|
|
331
|
+
*/
|
|
332
|
+
solutionMatches(solution: GridData): boolean;
|
|
324
333
|
/**
|
|
325
334
|
* Check if this grid is equal to another grid in terms of size, tile colors, connections, symbols, and rules.
|
|
326
335
|
*
|
package/dist/data/grid.js
CHANGED
|
@@ -5,7 +5,7 @@ import GridConnections from './gridConnections.js';
|
|
|
5
5
|
import { CachedAccess, array, move } from './dataHelper.js';
|
|
6
6
|
import { Color, MajorRule, } from './primitives.js';
|
|
7
7
|
import TileData from './tile.js';
|
|
8
|
-
const NEIGHBOR_OFFSETS = [
|
|
8
|
+
export const NEIGHBOR_OFFSETS = [
|
|
9
9
|
{ x: -1, y: 0 },
|
|
10
10
|
{ x: 1, y: 0 },
|
|
11
11
|
{ x: 0, y: -1 },
|
|
@@ -573,10 +573,7 @@ export default class GridData {
|
|
|
573
573
|
return ret;
|
|
574
574
|
for (const offset of NEIGHBOR_OFFSETS) {
|
|
575
575
|
const next = { x: x + offset.x, y: y + offset.y };
|
|
576
|
-
if (next.x
|
|
577
|
-
next.x < this.width &&
|
|
578
|
-
next.y >= 0 &&
|
|
579
|
-
next.y < this.height) {
|
|
576
|
+
if (this.isPositionValid(next.x, next.y)) {
|
|
580
577
|
const nextTile = this.getTile(next.x, next.y);
|
|
581
578
|
if (nextTile.exists && predicate(nextTile))
|
|
582
579
|
stack.push(next);
|
|
@@ -709,13 +706,13 @@ export default class GridData {
|
|
|
709
706
|
this.symbols.forEach(list => {
|
|
710
707
|
list.forEach(symbol => {
|
|
711
708
|
if (handlesSetGrid(symbol)) {
|
|
712
|
-
newGrid = symbol.onSetGrid(this, newGrid);
|
|
709
|
+
newGrid = symbol.onSetGrid(this, newGrid, null);
|
|
713
710
|
}
|
|
714
711
|
});
|
|
715
712
|
});
|
|
716
713
|
this.rules.forEach(rule => {
|
|
717
714
|
if (handlesSetGrid(rule)) {
|
|
718
|
-
newGrid = rule.onSetGrid(this, newGrid);
|
|
715
|
+
newGrid = rule.onSetGrid(this, newGrid, null);
|
|
719
716
|
}
|
|
720
717
|
});
|
|
721
718
|
return newGrid;
|
|
@@ -801,6 +798,29 @@ export default class GridData {
|
|
|
801
798
|
this.tiles.every((row, y) => row.every((tile, x) => (!tile.exists && !grid.getTile(x, y).exists) ||
|
|
802
799
|
tile.color === grid.getTile(x, y).color)));
|
|
803
800
|
}
|
|
801
|
+
/**
|
|
802
|
+
* Check if this grid conforms to the given solution, or an incomplete version of the solution.
|
|
803
|
+
* Symbols and rules are not validated.
|
|
804
|
+
*
|
|
805
|
+
* @param solution The solution to compare with.
|
|
806
|
+
* @returns True if the grid conforms to the solution, false otherwise.
|
|
807
|
+
*/
|
|
808
|
+
solutionMatches(solution) {
|
|
809
|
+
if (this.width !== solution.width)
|
|
810
|
+
return false;
|
|
811
|
+
if (this.height !== solution.height)
|
|
812
|
+
return false;
|
|
813
|
+
return this.tiles.every((row, y) => row.every((tile, x) => {
|
|
814
|
+
const solutionTile = solution.getTile(x, y);
|
|
815
|
+
if (!solutionTile.exists)
|
|
816
|
+
return true;
|
|
817
|
+
if (tile.color === Color.Gray)
|
|
818
|
+
return true;
|
|
819
|
+
if (solutionTile.color !== tile.color)
|
|
820
|
+
return false;
|
|
821
|
+
return true;
|
|
822
|
+
}));
|
|
823
|
+
}
|
|
804
824
|
/**
|
|
805
825
|
* Check if this grid is equal to another grid in terms of size, tile colors, connections, symbols, and rules.
|
|
806
826
|
*
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
+
import { isSameEdge } from './dataHelper.js';
|
|
1
2
|
import TileConnections from './tileConnections.js';
|
|
2
|
-
function isSameEdge(a, b) {
|
|
3
|
-
return ((a.x1 === b.x1 && a.y1 === b.y1 && a.x2 === b.x2 && a.y2 === b.y2) ||
|
|
4
|
-
(a.x1 === b.x2 && a.y1 === b.y2 && a.x2 === b.x1 && a.y2 === b.y1));
|
|
5
|
-
}
|
|
6
3
|
export default class GridConnections {
|
|
7
4
|
constructor(edges) {
|
|
8
5
|
Object.defineProperty(this, "edges", {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { AnyConfig } from '../config.js';
|
|
2
|
+
import GridData from '../grid.js';
|
|
3
|
+
import { Color, Edge, RuleState } from '../primitives.js';
|
|
4
|
+
import Rule, { SearchVariant } from './rule.js';
|
|
5
|
+
export default class CellCountPerZoneRule extends Rule {
|
|
6
|
+
readonly color: Color;
|
|
7
|
+
readonly edges: readonly Edge[];
|
|
8
|
+
private static readonly CONFIGS;
|
|
9
|
+
private static readonly EXAMPLE_GRID_LIGHT;
|
|
10
|
+
private static readonly EXAMPLE_GRID_DARK;
|
|
11
|
+
private static readonly EXAMPLE_GRID_GRAY;
|
|
12
|
+
private static readonly SEARCH_VARIANTS;
|
|
13
|
+
/**
|
|
14
|
+
* **Every zone has the same number of <color> cells.**
|
|
15
|
+
*
|
|
16
|
+
* @param color - The color of the cells to count.
|
|
17
|
+
* @param edges - The edges of the zones to count.
|
|
18
|
+
*/
|
|
19
|
+
constructor(color: Color, edges: readonly Edge[]);
|
|
20
|
+
get id(): string;
|
|
21
|
+
get explanation(): string;
|
|
22
|
+
get configs(): readonly AnyConfig[] | null;
|
|
23
|
+
createExampleGrid(): GridData;
|
|
24
|
+
get searchVariants(): SearchVariant[];
|
|
25
|
+
validateGrid(grid: GridData): RuleState;
|
|
26
|
+
copyWith({ color, edges, }: {
|
|
27
|
+
color?: Color;
|
|
28
|
+
edges?: readonly Edge[];
|
|
29
|
+
}): this;
|
|
30
|
+
withColor(color: Color): this;
|
|
31
|
+
withEdges(edges: readonly Edge[] | ((edges: readonly Edge[]) => readonly Edge[])): this;
|
|
32
|
+
}
|
|
33
|
+
export declare const instance: CellCountPerZoneRule;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { ConfigType } from '../config.js';
|
|
2
|
+
import { array } from '../dataHelper.js';
|
|
3
|
+
import GridData, { NEIGHBOR_OFFSETS } from '../grid.js';
|
|
4
|
+
import GridConnections from '../gridConnections.js';
|
|
5
|
+
import { Color, State } from '../primitives.js';
|
|
6
|
+
import Rule from './rule.js';
|
|
7
|
+
class CellCountPerZoneRule extends Rule {
|
|
8
|
+
/**
|
|
9
|
+
* **Every zone has the same number of <color> cells.**
|
|
10
|
+
*
|
|
11
|
+
* @param color - The color of the cells to count.
|
|
12
|
+
* @param edges - The edges of the zones to count.
|
|
13
|
+
*/
|
|
14
|
+
constructor(color, edges) {
|
|
15
|
+
super();
|
|
16
|
+
Object.defineProperty(this, "color", {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
configurable: true,
|
|
19
|
+
writable: true,
|
|
20
|
+
value: color
|
|
21
|
+
});
|
|
22
|
+
Object.defineProperty(this, "edges", {
|
|
23
|
+
enumerable: true,
|
|
24
|
+
configurable: true,
|
|
25
|
+
writable: true,
|
|
26
|
+
value: edges
|
|
27
|
+
});
|
|
28
|
+
this.color = color;
|
|
29
|
+
this.edges = GridConnections.deduplicateEdges(edges);
|
|
30
|
+
}
|
|
31
|
+
get id() {
|
|
32
|
+
return `zone_cell_count`;
|
|
33
|
+
}
|
|
34
|
+
get explanation() {
|
|
35
|
+
return `Every zone has the same number of ${this.color} cells`;
|
|
36
|
+
}
|
|
37
|
+
get configs() {
|
|
38
|
+
return CellCountPerZoneRule.CONFIGS;
|
|
39
|
+
}
|
|
40
|
+
createExampleGrid() {
|
|
41
|
+
if (this.color === Color.Light) {
|
|
42
|
+
return CellCountPerZoneRule.EXAMPLE_GRID_LIGHT;
|
|
43
|
+
}
|
|
44
|
+
else if (this.color === Color.Dark) {
|
|
45
|
+
return CellCountPerZoneRule.EXAMPLE_GRID_DARK;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
return CellCountPerZoneRule.EXAMPLE_GRID_GRAY;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
get searchVariants() {
|
|
52
|
+
return CellCountPerZoneRule.SEARCH_VARIANTS;
|
|
53
|
+
}
|
|
54
|
+
validateGrid(grid) {
|
|
55
|
+
let complete = true;
|
|
56
|
+
const visited = array(grid.width, grid.height, (i, j) => !grid.getTile(i, j).exists);
|
|
57
|
+
const zones = [];
|
|
58
|
+
while (true) {
|
|
59
|
+
const seed = grid.find((_tile, x, y) => !visited[y][x]);
|
|
60
|
+
if (!seed)
|
|
61
|
+
break;
|
|
62
|
+
const zone = {
|
|
63
|
+
positions: [],
|
|
64
|
+
completed: 0,
|
|
65
|
+
possible: 0,
|
|
66
|
+
};
|
|
67
|
+
const stack = [seed];
|
|
68
|
+
while (stack.length > 0) {
|
|
69
|
+
const { x, y } = stack.pop();
|
|
70
|
+
if (visited[y][x])
|
|
71
|
+
continue;
|
|
72
|
+
visited[y][x] = true;
|
|
73
|
+
zone.positions.push({ x, y });
|
|
74
|
+
if (grid.getTile(x, y).color === this.color) {
|
|
75
|
+
zone.completed++;
|
|
76
|
+
}
|
|
77
|
+
else if (grid.getTile(x, y).color === Color.Gray) {
|
|
78
|
+
zone.possible++;
|
|
79
|
+
complete = false;
|
|
80
|
+
}
|
|
81
|
+
for (const offset of NEIGHBOR_OFFSETS) {
|
|
82
|
+
const next = { x: x + offset.x, y: y + offset.y };
|
|
83
|
+
if (!this.edges.some(e => (e.x1 === x &&
|
|
84
|
+
e.y1 === y &&
|
|
85
|
+
e.x2 === next.x &&
|
|
86
|
+
e.y2 === next.y) ||
|
|
87
|
+
(e.x1 === next.x && e.y1 === next.y && e.x2 === x && e.y2 === y))) {
|
|
88
|
+
const nextTile = grid.getTile(next.x, next.y);
|
|
89
|
+
if (nextTile.exists) {
|
|
90
|
+
stack.push(next);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
zones.push(zone);
|
|
96
|
+
}
|
|
97
|
+
if (zones.length <= 1) {
|
|
98
|
+
return { state: complete ? State.Satisfied : State.Incomplete };
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
const errorZone = zones.find(z => zones.some(zz => zz !== z &&
|
|
102
|
+
(zz.completed > z.completed + z.possible ||
|
|
103
|
+
zz.completed + zz.possible < z.completed)));
|
|
104
|
+
if (errorZone) {
|
|
105
|
+
return {
|
|
106
|
+
state: State.Error,
|
|
107
|
+
positions: errorZone.positions,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
return { state: complete ? State.Satisfied : State.Incomplete };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
copyWith({ color, edges, }) {
|
|
116
|
+
return new CellCountPerZoneRule(color ?? this.color, edges ?? this.edges);
|
|
117
|
+
}
|
|
118
|
+
withColor(color) {
|
|
119
|
+
return this.copyWith({ color });
|
|
120
|
+
}
|
|
121
|
+
withEdges(edges) {
|
|
122
|
+
return this.copyWith({
|
|
123
|
+
edges: typeof edges === 'function' ? edges(this.edges) : edges,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
Object.defineProperty(CellCountPerZoneRule, "CONFIGS", {
|
|
128
|
+
enumerable: true,
|
|
129
|
+
configurable: true,
|
|
130
|
+
writable: true,
|
|
131
|
+
value: Object.freeze([
|
|
132
|
+
{
|
|
133
|
+
type: ConfigType.Color,
|
|
134
|
+
default: Color.Light,
|
|
135
|
+
allowGray: true,
|
|
136
|
+
field: 'color',
|
|
137
|
+
description: 'Color',
|
|
138
|
+
configurable: true,
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
type: ConfigType.Edges,
|
|
142
|
+
default: [],
|
|
143
|
+
field: 'edges',
|
|
144
|
+
description: 'Edges',
|
|
145
|
+
configurable: false,
|
|
146
|
+
},
|
|
147
|
+
])
|
|
148
|
+
});
|
|
149
|
+
Object.defineProperty(CellCountPerZoneRule, "EXAMPLE_GRID_LIGHT", {
|
|
150
|
+
enumerable: true,
|
|
151
|
+
configurable: true,
|
|
152
|
+
writable: true,
|
|
153
|
+
value: Object.freeze(GridData.create(['bwbbb', 'wbbwb', 'bbbwb', 'bwbwb']).addRule(new CellCountPerZoneRule(Color.Light, [
|
|
154
|
+
{ x1: 0, y1: 1, x2: 0, y2: 2 },
|
|
155
|
+
{ x1: 1, y1: 1, x2: 1, y2: 2 },
|
|
156
|
+
{ x1: 2, y1: 1, x2: 2, y2: 2 },
|
|
157
|
+
{ x1: 3, y1: 1, x2: 3, y2: 2 },
|
|
158
|
+
{ x1: 4, y1: 1, x2: 4, y2: 2 },
|
|
159
|
+
])))
|
|
160
|
+
});
|
|
161
|
+
Object.defineProperty(CellCountPerZoneRule, "EXAMPLE_GRID_DARK", {
|
|
162
|
+
enumerable: true,
|
|
163
|
+
configurable: true,
|
|
164
|
+
writable: true,
|
|
165
|
+
value: Object.freeze(CellCountPerZoneRule.EXAMPLE_GRID_LIGHT.withTiles(tiles => tiles.map(row => row.map(tile => tile.withColor(tile.color === Color.Dark ? Color.Light : Color.Dark)))))
|
|
166
|
+
});
|
|
167
|
+
Object.defineProperty(CellCountPerZoneRule, "EXAMPLE_GRID_GRAY", {
|
|
168
|
+
enumerable: true,
|
|
169
|
+
configurable: true,
|
|
170
|
+
writable: true,
|
|
171
|
+
value: Object.freeze(CellCountPerZoneRule.EXAMPLE_GRID_LIGHT.withTiles(tiles => tiles.map(row => row.map(tile => tile.withColor(tile.color === Color.Light ? Color.Gray : tile.color)))))
|
|
172
|
+
});
|
|
173
|
+
Object.defineProperty(CellCountPerZoneRule, "SEARCH_VARIANTS", {
|
|
174
|
+
enumerable: true,
|
|
175
|
+
configurable: true,
|
|
176
|
+
writable: true,
|
|
177
|
+
value: [
|
|
178
|
+
new CellCountPerZoneRule(Color.Light, []).searchVariant(),
|
|
179
|
+
new CellCountPerZoneRule(Color.Dark, []).searchVariant(),
|
|
180
|
+
]
|
|
181
|
+
});
|
|
182
|
+
export default CellCountPerZoneRule;
|
|
183
|
+
export const instance = new CellCountPerZoneRule(Color.Light, []);
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import { AnyConfig } from '../config.js';
|
|
2
2
|
import GridData from '../grid.js';
|
|
3
|
-
import { RuleState } from '../primitives.js';
|
|
3
|
+
import { RuleState, Position } from '../primitives.js';
|
|
4
4
|
import Rule, { SearchVariant } from './rule.js';
|
|
5
5
|
export default class ForesightRule extends Rule {
|
|
6
6
|
readonly count: number;
|
|
7
7
|
readonly regenInterval: number;
|
|
8
8
|
readonly startFull: boolean;
|
|
9
|
+
readonly solvePath: Position[];
|
|
9
10
|
private static readonly EXAMPLE_GRID;
|
|
10
11
|
private static readonly CONFIGS;
|
|
11
12
|
private static readonly SEARCH_VARIANTS;
|
|
12
13
|
/**
|
|
13
14
|
* **Foresight: Show hints**
|
|
14
15
|
*/
|
|
15
|
-
constructor(count: number, regenInterval: number, startFull: boolean);
|
|
16
|
+
constructor(count: number, regenInterval: number, startFull: boolean, solvePath?: Position[]);
|
|
16
17
|
get id(): string;
|
|
17
18
|
get explanation(): string;
|
|
18
19
|
get visibleWhenSolving(): boolean;
|
|
@@ -22,10 +23,11 @@ export default class ForesightRule extends Rule {
|
|
|
22
23
|
validateGrid(_grid: GridData): RuleState;
|
|
23
24
|
get necessaryForCompletion(): boolean;
|
|
24
25
|
get isSingleton(): boolean;
|
|
25
|
-
copyWith({ count, regenInterval, startFull, }: {
|
|
26
|
+
copyWith({ count, regenInterval, startFull, solvePath, }: {
|
|
26
27
|
count?: number;
|
|
27
28
|
regenInterval?: number;
|
|
28
29
|
startFull?: boolean;
|
|
30
|
+
solvePath?: Position[];
|
|
29
31
|
}): this;
|
|
30
32
|
}
|
|
31
33
|
export declare const instance: ForesightRule;
|
|
@@ -7,7 +7,7 @@ class ForesightRule extends Rule {
|
|
|
7
7
|
/**
|
|
8
8
|
* **Foresight: Show hints**
|
|
9
9
|
*/
|
|
10
|
-
constructor(count, regenInterval, startFull) {
|
|
10
|
+
constructor(count, regenInterval, startFull, solvePath = []) {
|
|
11
11
|
super();
|
|
12
12
|
Object.defineProperty(this, "count", {
|
|
13
13
|
enumerable: true,
|
|
@@ -27,9 +27,16 @@ class ForesightRule extends Rule {
|
|
|
27
27
|
writable: true,
|
|
28
28
|
value: startFull
|
|
29
29
|
});
|
|
30
|
+
Object.defineProperty(this, "solvePath", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
configurable: true,
|
|
33
|
+
writable: true,
|
|
34
|
+
value: solvePath
|
|
35
|
+
});
|
|
30
36
|
this.count = count;
|
|
31
37
|
this.regenInterval = regenInterval;
|
|
32
38
|
this.startFull = startFull;
|
|
39
|
+
this.solvePath = solvePath;
|
|
33
40
|
}
|
|
34
41
|
get id() {
|
|
35
42
|
return `foresight`;
|
|
@@ -58,8 +65,8 @@ class ForesightRule extends Rule {
|
|
|
58
65
|
get isSingleton() {
|
|
59
66
|
return true;
|
|
60
67
|
}
|
|
61
|
-
copyWith({ count, regenInterval, startFull, }) {
|
|
62
|
-
return new ForesightRule(count ?? this.count, regenInterval ?? this.regenInterval, startFull ?? this.startFull);
|
|
68
|
+
copyWith({ count, regenInterval, startFull, solvePath, }) {
|
|
69
|
+
return new ForesightRule(count ?? this.count, regenInterval ?? this.regenInterval, startFull ?? this.startFull, solvePath ?? this.solvePath);
|
|
63
70
|
}
|
|
64
71
|
}
|
|
65
72
|
Object.defineProperty(ForesightRule, "EXAMPLE_GRID", {
|
|
@@ -96,6 +103,13 @@ Object.defineProperty(ForesightRule, "CONFIGS", {
|
|
|
96
103
|
description: 'Start with full foresight',
|
|
97
104
|
configurable: true,
|
|
98
105
|
},
|
|
106
|
+
{
|
|
107
|
+
type: ConfigType.SolvePath,
|
|
108
|
+
default: [],
|
|
109
|
+
field: 'solvePath',
|
|
110
|
+
description: 'Intended solve path',
|
|
111
|
+
configurable: true,
|
|
112
|
+
},
|
|
99
113
|
])
|
|
100
114
|
});
|
|
101
115
|
Object.defineProperty(ForesightRule, "SEARCH_VARIANTS", {
|
|
@@ -24,7 +24,7 @@ export default class MusicGridRule extends Rule implements GridChangeHandler, Se
|
|
|
24
24
|
createExampleGrid(): GridData;
|
|
25
25
|
get searchVariants(): SearchVariant[];
|
|
26
26
|
validateGrid(_grid: GridData): RuleState;
|
|
27
|
-
onSetGrid(_oldGrid: GridData, newGrid: GridData): GridData;
|
|
27
|
+
onSetGrid(_oldGrid: GridData, newGrid: GridData, _solution: GridData | null): GridData;
|
|
28
28
|
onGridChange(newGrid: GridData): this;
|
|
29
29
|
onGridResize(_grid: GridData, mode: 'insert' | 'remove', direction: 'row' | 'column', index: number): this | null;
|
|
30
30
|
/**
|
|
@@ -56,7 +56,7 @@ class MusicGridRule extends Rule {
|
|
|
56
56
|
validateGrid(_grid) {
|
|
57
57
|
return { state: State.Incomplete };
|
|
58
58
|
}
|
|
59
|
-
onSetGrid(_oldGrid, newGrid) {
|
|
59
|
+
onSetGrid(_oldGrid, newGrid, _solution) {
|
|
60
60
|
if (newGrid.getTileCount(true, undefined, Color.Gray) === 0)
|
|
61
61
|
return newGrid;
|
|
62
62
|
const tiles = newGrid.tiles.map(row => row.map(tile => tile.color === Color.Gray ? tile.withColor(Color.Light) : tile));
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { AnyConfig } from '../config.js';
|
|
2
|
+
import GridData from '../grid.js';
|
|
3
|
+
import { GridState, RuleState } from '../primitives.js';
|
|
4
|
+
import Rule, { SearchVariant } from './rule.js';
|
|
5
|
+
import { SetGridHandler } from '../events/onSetGrid.js';
|
|
6
|
+
import { FinalValidationHandler } from '../events/onFinalValidation.js';
|
|
7
|
+
export default class PerfectionRule extends Rule implements SetGridHandler, FinalValidationHandler {
|
|
8
|
+
private static readonly EXAMPLE_GRID;
|
|
9
|
+
private static readonly SEARCH_VARIANTS;
|
|
10
|
+
/**
|
|
11
|
+
* **Quest for Perfection: cell colors are final**
|
|
12
|
+
*/
|
|
13
|
+
constructor();
|
|
14
|
+
get id(): string;
|
|
15
|
+
get explanation(): string;
|
|
16
|
+
get configs(): readonly AnyConfig[] | null;
|
|
17
|
+
createExampleGrid(): GridData;
|
|
18
|
+
get searchVariants(): SearchVariant[];
|
|
19
|
+
get necessaryForCompletion(): boolean;
|
|
20
|
+
get isSingleton(): boolean;
|
|
21
|
+
validateGrid(grid: GridData): RuleState;
|
|
22
|
+
/**
|
|
23
|
+
* If the grid passes validation but is different from the solution, indicate the error in the final state.
|
|
24
|
+
*/
|
|
25
|
+
onFinalValidation(grid: GridData, solution: GridData | null, state: GridState): GridState;
|
|
26
|
+
private fixTiles;
|
|
27
|
+
/**
|
|
28
|
+
* Force all tiles to be fixed.
|
|
29
|
+
*
|
|
30
|
+
* If the grid is already wrong, prevent the player from changing it further.
|
|
31
|
+
*/
|
|
32
|
+
onSetGrid(oldGrid: GridData, newGrid: GridData, solution: GridData | null): GridData;
|
|
33
|
+
copyWith(_: object): this;
|
|
34
|
+
}
|
|
35
|
+
export declare const instance: PerfectionRule;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import GridData from '../grid.js';
|
|
2
|
+
import { Color, State } from '../primitives.js';
|
|
3
|
+
import Rule from './rule.js';
|
|
4
|
+
import CustomIconSymbol from '../symbols/customIconSymbol.js';
|
|
5
|
+
class PerfectionRule extends Rule {
|
|
6
|
+
/**
|
|
7
|
+
* **Quest for Perfection: cell colors are final**
|
|
8
|
+
*/
|
|
9
|
+
constructor() {
|
|
10
|
+
super();
|
|
11
|
+
}
|
|
12
|
+
get id() {
|
|
13
|
+
return `perfection`;
|
|
14
|
+
}
|
|
15
|
+
get explanation() {
|
|
16
|
+
return `*Quest for Perfection*: cell colors are final`;
|
|
17
|
+
}
|
|
18
|
+
get configs() {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
createExampleGrid() {
|
|
22
|
+
return PerfectionRule.EXAMPLE_GRID;
|
|
23
|
+
}
|
|
24
|
+
get searchVariants() {
|
|
25
|
+
return PerfectionRule.SEARCH_VARIANTS;
|
|
26
|
+
}
|
|
27
|
+
get necessaryForCompletion() {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
get isSingleton() {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
validateGrid(grid) {
|
|
34
|
+
if (grid.getTileCount(true, undefined, Color.Gray) > 0) {
|
|
35
|
+
return { state: State.Incomplete };
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
return { state: State.Satisfied };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* If the grid passes validation but is different from the solution, indicate the error in the final state.
|
|
43
|
+
*/
|
|
44
|
+
onFinalValidation(grid, solution, state) {
|
|
45
|
+
if (state.final === State.Error)
|
|
46
|
+
return state;
|
|
47
|
+
if (solution === null)
|
|
48
|
+
return state;
|
|
49
|
+
const positions = [];
|
|
50
|
+
grid.tiles.forEach((row, y) => row.forEach((t, x) => {
|
|
51
|
+
if (t.exists &&
|
|
52
|
+
t.color !== Color.Gray &&
|
|
53
|
+
t.color !== solution.getTile(x, y).color) {
|
|
54
|
+
positions.push({ x, y });
|
|
55
|
+
}
|
|
56
|
+
}));
|
|
57
|
+
if (positions.length > 0) {
|
|
58
|
+
const ruleId = grid.rules.indexOf(this);
|
|
59
|
+
return {
|
|
60
|
+
final: State.Error,
|
|
61
|
+
rules: state.rules.map((r, idx) => {
|
|
62
|
+
if (idx === ruleId) {
|
|
63
|
+
return { state: State.Error, positions };
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
return r;
|
|
67
|
+
}
|
|
68
|
+
}),
|
|
69
|
+
symbols: state.symbols,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
return state;
|
|
73
|
+
}
|
|
74
|
+
fixTiles(grid) {
|
|
75
|
+
if (grid.getTileCount(true, false, Color.Light) > 0 ||
|
|
76
|
+
grid.getTileCount(true, false, Color.Dark) > 0) {
|
|
77
|
+
return grid.withTiles(tiles => tiles.map(row => row.map(t => t.exists && t.color !== Color.Gray ? t.withFixed(true) : t)));
|
|
78
|
+
}
|
|
79
|
+
return grid;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Force all tiles to be fixed.
|
|
83
|
+
*
|
|
84
|
+
* If the grid is already wrong, prevent the player from changing it further.
|
|
85
|
+
*/
|
|
86
|
+
onSetGrid(oldGrid, newGrid, solution) {
|
|
87
|
+
if (!solution) {
|
|
88
|
+
return this.fixTiles(newGrid);
|
|
89
|
+
}
|
|
90
|
+
if (!oldGrid.solutionMatches(solution) &&
|
|
91
|
+
!newGrid.solutionMatches(solution)) {
|
|
92
|
+
return this.fixTiles(oldGrid);
|
|
93
|
+
}
|
|
94
|
+
return this.fixTiles(newGrid);
|
|
95
|
+
}
|
|
96
|
+
copyWith(_) {
|
|
97
|
+
return new PerfectionRule();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
Object.defineProperty(PerfectionRule, "EXAMPLE_GRID", {
|
|
101
|
+
enumerable: true,
|
|
102
|
+
configurable: true,
|
|
103
|
+
writable: true,
|
|
104
|
+
value: Object.freeze(GridData.create(['w']).addSymbol(new CustomIconSymbol('', GridData.create(['w']), 0, 0, 'MdStars')))
|
|
105
|
+
});
|
|
106
|
+
Object.defineProperty(PerfectionRule, "SEARCH_VARIANTS", {
|
|
107
|
+
enumerable: true,
|
|
108
|
+
configurable: true,
|
|
109
|
+
writable: true,
|
|
110
|
+
value: []
|
|
111
|
+
}); // this rule is not searchable
|
|
112
|
+
export default PerfectionRule;
|
|
113
|
+
export const instance = new PerfectionRule();
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { instance as BanPatternRule } from './banPatternRule.js';
|
|
2
|
+
export { instance as CellCountPerZoneRule } from './cellCountPerZoneRule.js';
|
|
2
3
|
export { instance as CellCountRule } from './cellCountRule.js';
|
|
3
4
|
export { instance as CompletePatternRule } from './completePatternRule.js';
|
|
4
5
|
export { instance as ConnectAllRule } from './connectAllRule.js';
|
|
@@ -7,6 +8,7 @@ export { instance as ForesightRule } from './foresightRule.js';
|
|
|
7
8
|
export { instance as MusicGridRule } from './musicGridRule.js';
|
|
8
9
|
export { instance as MysteryRule } from './mysteryRule.js';
|
|
9
10
|
export { instance as OffByXRule } from './offByXRule.js';
|
|
11
|
+
export { instance as PerfectionRule } from './perfectionRule.js';
|
|
10
12
|
export { instance as RegionAreaRule } from './regionAreaRule.js';
|
|
11
13
|
export { instance as SameShapeRule } from './sameShapeRule.js';
|
|
12
14
|
export { instance as SymbolsPerRegionRule } from './symbolsPerRegionRule.js';
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// @ts-nocheck
|
|
4
4
|
// noinspection JSUnusedGlobalSymbols
|
|
5
5
|
export { instance as BanPatternRule } from './banPatternRule.js';
|
|
6
|
+
export { instance as CellCountPerZoneRule } from './cellCountPerZoneRule.js';
|
|
6
7
|
export { instance as CellCountRule } from './cellCountRule.js';
|
|
7
8
|
export { instance as CompletePatternRule } from './completePatternRule.js';
|
|
8
9
|
export { instance as ConnectAllRule } from './connectAllRule.js';
|
|
@@ -11,6 +12,7 @@ export { instance as ForesightRule } from './foresightRule.js';
|
|
|
11
12
|
export { instance as MusicGridRule } from './musicGridRule.js';
|
|
12
13
|
export { instance as MysteryRule } from './mysteryRule.js';
|
|
13
14
|
export { instance as OffByXRule } from './offByXRule.js';
|
|
15
|
+
export { instance as PerfectionRule } from './perfectionRule.js';
|
|
14
16
|
export { instance as RegionAreaRule } from './regionAreaRule.js';
|
|
15
17
|
export { instance as SameShapeRule } from './sameShapeRule.js';
|
|
16
18
|
export { instance as SymbolsPerRegionRule } from './symbolsPerRegionRule.js';
|
|
@@ -161,6 +161,18 @@ export default class SerializerV0 extends SerializerBase {
|
|
|
161
161
|
escape(instruction[config.field]
|
|
162
162
|
.map(line => this.stringifyControlLine(line))
|
|
163
163
|
.join(':')));
|
|
164
|
+
case ConfigType.SolvePath:
|
|
165
|
+
return (config.field +
|
|
166
|
+
'=' +
|
|
167
|
+
escape(instruction[config.field]
|
|
168
|
+
?.map(pos => `${pos.x}_${pos.y}`)
|
|
169
|
+
.join('/') ?? ''));
|
|
170
|
+
case ConfigType.Edges:
|
|
171
|
+
return (config.field +
|
|
172
|
+
'=' +
|
|
173
|
+
instruction[config.field]
|
|
174
|
+
.map(edge => `${edge.x1}_${edge.y1}_${edge.x2}_${edge.y2}`)
|
|
175
|
+
.join('/'));
|
|
164
176
|
}
|
|
165
177
|
}
|
|
166
178
|
parseConfig(configs, entry) {
|
|
@@ -219,6 +231,31 @@ export default class SerializerV0 extends SerializerBase {
|
|
|
219
231
|
];
|
|
220
232
|
case ConfigType.NullableNote:
|
|
221
233
|
return [config.field, value === '' ? null : unescape(value)];
|
|
234
|
+
case ConfigType.SolvePath:
|
|
235
|
+
return [
|
|
236
|
+
config.field,
|
|
237
|
+
value === ''
|
|
238
|
+
? []
|
|
239
|
+
: value.split('/').map(pos => {
|
|
240
|
+
const [x, y] = pos.split('_');
|
|
241
|
+
return { x: Number(x), y: Number(y) };
|
|
242
|
+
}),
|
|
243
|
+
];
|
|
244
|
+
case ConfigType.Edges:
|
|
245
|
+
return [
|
|
246
|
+
config.field,
|
|
247
|
+
value === ''
|
|
248
|
+
? []
|
|
249
|
+
: value.split('/').map(edge => {
|
|
250
|
+
const [x1, y1, x2, y2] = edge.split('_');
|
|
251
|
+
return {
|
|
252
|
+
x1: Number(x1),
|
|
253
|
+
y1: Number(y1),
|
|
254
|
+
x2: Number(x2),
|
|
255
|
+
y2: Number(y2),
|
|
256
|
+
};
|
|
257
|
+
}),
|
|
258
|
+
];
|
|
222
259
|
}
|
|
223
260
|
}
|
|
224
261
|
stringifyInstruction(instruction) {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ConfigType, configEquals } from './data/config.js';
|
|
2
2
|
import Configurable from './data/configurable.js';
|
|
3
|
-
import { CachedAccess, allEqual, array, directionToRotation, escape, maxBy, minBy, move, orientationToRotation, resize, unescape } from './data/dataHelper.js';
|
|
3
|
+
import { CachedAccess, allEqual, array, directionToRotation, escape, isSameEdge, maxBy, minBy, move, orientationToRotation, resize, unescape } from './data/dataHelper.js';
|
|
4
4
|
import { isEventHandler } from './data/events/eventHelper.js';
|
|
5
5
|
import { handlesFinalValidation } from './data/events/onFinalValidation.js';
|
|
6
6
|
import { handlesGridChange } from './data/events/onGridChange.js';
|
|
@@ -8,12 +8,13 @@ import { handlesGridResize } from './data/events/onGridResize.js';
|
|
|
8
8
|
import { handlesSetGrid } from './data/events/onSetGrid.js';
|
|
9
9
|
import { handlesSymbolDisplay } from './data/events/onSymbolDisplay.js';
|
|
10
10
|
import { handlesSymbolValidation } from './data/events/onSymbolValidation.js';
|
|
11
|
-
import GridData from './data/grid.js';
|
|
11
|
+
import GridData, { NEIGHBOR_OFFSETS } from './data/grid.js';
|
|
12
12
|
import GridConnections from './data/gridConnections.js';
|
|
13
13
|
import Instruction from './data/instruction.js';
|
|
14
14
|
import { COMPARISONS, Color, Comparison, DIRECTIONS, Direction, MajorRule, Mode, ORIENTATIONS, Orientation, State, directionToggle, orientationToggle } from './data/primitives.js';
|
|
15
15
|
import { MetadataSchema, PuzzleSchema } from './data/puzzle.js';
|
|
16
16
|
import BanPatternRule from './data/rules/banPatternRule.js';
|
|
17
|
+
import CellCountPerZoneRule from './data/rules/cellCountPerZoneRule.js';
|
|
17
18
|
import CellCountRule from './data/rules/cellCountRule.js';
|
|
18
19
|
import CompletePatternRule from './data/rules/completePatternRule.js';
|
|
19
20
|
import ConnectAllRule from './data/rules/connectAllRule.js';
|
|
@@ -24,6 +25,7 @@ import { ControlLine, Row } from './data/rules/musicControlLine.js';
|
|
|
24
25
|
import MusicGridRule from './data/rules/musicGridRule.js';
|
|
25
26
|
import MysteryRule from './data/rules/mysteryRule.js';
|
|
26
27
|
import OffByXRule from './data/rules/offByXRule.js';
|
|
28
|
+
import PerfectionRule from './data/rules/perfectionRule.js';
|
|
27
29
|
import RegionAreaRule from './data/rules/regionAreaRule.js';
|
|
28
30
|
import RegionShapeRule from './data/rules/regionShapeRule.js';
|
|
29
31
|
import Rule from './data/rules/rule.js';
|
|
@@ -95,4 +97,4 @@ import ViewpointSymbol from './data/symbols/viewpointSymbol.js';
|
|
|
95
97
|
import TileData from './data/tile.js';
|
|
96
98
|
import TileConnections from './data/tileConnections.js';
|
|
97
99
|
import validateGrid, { aggregateState, applyFinalOverrides } from './data/validate.js';
|
|
98
|
-
export { ConfigType, configEquals, Configurable, CachedAccess, allEqual, array, directionToRotation, escape, maxBy, minBy, move, orientationToRotation, resize, unescape, isEventHandler, handlesFinalValidation, handlesGridChange, handlesGridResize, handlesSetGrid, handlesSymbolDisplay, handlesSymbolValidation, GridData, GridConnections, Instruction, COMPARISONS, Color, Comparison, DIRECTIONS, Direction, MajorRule, Mode, ORIENTATIONS, Orientation, State, directionToggle, orientationToggle, MetadataSchema, PuzzleSchema, BanPatternRule, CellCountRule, CompletePatternRule, ConnectAllRule, CustomRule, ForesightRule, allRules, ControlLine, Row, MusicGridRule, MysteryRule, OffByXRule, RegionAreaRule, RegionShapeRule, Rule, SameShapeRule, SymbolsPerRegionRule, UndercluedRule, UniqueShapeRule, 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, GalaxyBTModule, LetterBTModule, LotusBTModule, MinesweeperBTModule, MyopiaBTModule, ViewpointBTModule, Solver, UndercluedSolver, AreaNumberModule, CellCountModule, ConnectAllModule, DartModule, allZ3Modules, LetterModule, MyopiaModule, RegionAreaModule, ViewpointModule, Z3Module, convertDirection, Z3Solver, Z3SolverContext, AreaNumberSymbol, CustomIconSymbol, CustomSymbol, CustomTextSymbol, DartSymbol, DirectionLinkerSymbol, GalaxySymbol, HiddenSymbol, allSymbols, LetterSymbol, LotusSymbol, MinesweeperSymbol, MultiEntrySymbol, MyopiaSymbol, NumberSymbol, Symbol, ViewpointSymbol, TileData, TileConnections, validateGrid, aggregateState, applyFinalOverrides, };
|
|
100
|
+
export { ConfigType, configEquals, Configurable, CachedAccess, allEqual, array, directionToRotation, escape, isSameEdge, maxBy, minBy, move, orientationToRotation, resize, unescape, isEventHandler, handlesFinalValidation, handlesGridChange, handlesGridResize, handlesSetGrid, handlesSymbolDisplay, handlesSymbolValidation, GridData, NEIGHBOR_OFFSETS, GridConnections, Instruction, COMPARISONS, Color, Comparison, DIRECTIONS, Direction, MajorRule, Mode, ORIENTATIONS, Orientation, State, directionToggle, orientationToggle, MetadataSchema, PuzzleSchema, BanPatternRule, CellCountPerZoneRule, CellCountRule, CompletePatternRule, ConnectAllRule, CustomRule, ForesightRule, allRules, ControlLine, Row, MusicGridRule, MysteryRule, OffByXRule, PerfectionRule, RegionAreaRule, RegionShapeRule, Rule, SameShapeRule, SymbolsPerRegionRule, UndercluedRule, UniqueShapeRule, 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, GalaxyBTModule, LetterBTModule, LotusBTModule, MinesweeperBTModule, MyopiaBTModule, ViewpointBTModule, Solver, UndercluedSolver, AreaNumberModule, CellCountModule, ConnectAllModule, DartModule, allZ3Modules, LetterModule, MyopiaModule, RegionAreaModule, ViewpointModule, Z3Module, convertDirection, Z3Solver, Z3SolverContext, AreaNumberSymbol, CustomIconSymbol, CustomSymbol, CustomTextSymbol, DartSymbol, DirectionLinkerSymbol, GalaxySymbol, HiddenSymbol, allSymbols, LetterSymbol, LotusSymbol, MinesweeperSymbol, MultiEntrySymbol, MyopiaSymbol, NumberSymbol, Symbol, ViewpointSymbol, TileData, TileConnections, validateGrid, aggregateState, applyFinalOverrides, };
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// noinspection JSUnusedGlobalSymbols
|
|
4
4
|
import { ConfigType, configEquals } from './data/config.js';
|
|
5
5
|
import Configurable from './data/configurable.js';
|
|
6
|
-
import { CachedAccess, allEqual, array, directionToRotation, escape, maxBy, minBy, move, orientationToRotation, resize, unescape } from './data/dataHelper.js';
|
|
6
|
+
import { CachedAccess, allEqual, array, directionToRotation, escape, isSameEdge, maxBy, minBy, move, orientationToRotation, resize, unescape } from './data/dataHelper.js';
|
|
7
7
|
import { isEventHandler } from './data/events/eventHelper.js';
|
|
8
8
|
import { handlesFinalValidation } from './data/events/onFinalValidation.js';
|
|
9
9
|
import { handlesGridChange } from './data/events/onGridChange.js';
|
|
@@ -11,12 +11,13 @@ import { handlesGridResize } from './data/events/onGridResize.js';
|
|
|
11
11
|
import { handlesSetGrid } from './data/events/onSetGrid.js';
|
|
12
12
|
import { handlesSymbolDisplay } from './data/events/onSymbolDisplay.js';
|
|
13
13
|
import { handlesSymbolValidation } from './data/events/onSymbolValidation.js';
|
|
14
|
-
import GridData from './data/grid.js';
|
|
14
|
+
import GridData, { NEIGHBOR_OFFSETS } from './data/grid.js';
|
|
15
15
|
import GridConnections from './data/gridConnections.js';
|
|
16
16
|
import Instruction from './data/instruction.js';
|
|
17
17
|
import { COMPARISONS, Color, Comparison, DIRECTIONS, Direction, MajorRule, Mode, ORIENTATIONS, Orientation, State, directionToggle, orientationToggle } from './data/primitives.js';
|
|
18
18
|
import { MetadataSchema, PuzzleSchema } from './data/puzzle.js';
|
|
19
19
|
import BanPatternRule from './data/rules/banPatternRule.js';
|
|
20
|
+
import CellCountPerZoneRule from './data/rules/cellCountPerZoneRule.js';
|
|
20
21
|
import CellCountRule from './data/rules/cellCountRule.js';
|
|
21
22
|
import CompletePatternRule from './data/rules/completePatternRule.js';
|
|
22
23
|
import ConnectAllRule from './data/rules/connectAllRule.js';
|
|
@@ -27,6 +28,7 @@ import { ControlLine, Row } from './data/rules/musicControlLine.js';
|
|
|
27
28
|
import MusicGridRule from './data/rules/musicGridRule.js';
|
|
28
29
|
import MysteryRule from './data/rules/mysteryRule.js';
|
|
29
30
|
import OffByXRule from './data/rules/offByXRule.js';
|
|
31
|
+
import PerfectionRule from './data/rules/perfectionRule.js';
|
|
30
32
|
import RegionAreaRule from './data/rules/regionAreaRule.js';
|
|
31
33
|
import RegionShapeRule from './data/rules/regionShapeRule.js';
|
|
32
34
|
import Rule from './data/rules/rule.js';
|
|
@@ -98,4 +100,4 @@ import ViewpointSymbol from './data/symbols/viewpointSymbol.js';
|
|
|
98
100
|
import TileData from './data/tile.js';
|
|
99
101
|
import TileConnections from './data/tileConnections.js';
|
|
100
102
|
import validateGrid, { aggregateState, applyFinalOverrides } from './data/validate.js';
|
|
101
|
-
export { ConfigType, configEquals, Configurable, CachedAccess, allEqual, array, directionToRotation, escape, maxBy, minBy, move, orientationToRotation, resize, unescape, isEventHandler, handlesFinalValidation, handlesGridChange, handlesGridResize, handlesSetGrid, handlesSymbolDisplay, handlesSymbolValidation, GridData, GridConnections, Instruction, COMPARISONS, Color, Comparison, DIRECTIONS, Direction, MajorRule, Mode, ORIENTATIONS, Orientation, State, directionToggle, orientationToggle, MetadataSchema, PuzzleSchema, BanPatternRule, CellCountRule, CompletePatternRule, ConnectAllRule, CustomRule, ForesightRule, allRules, ControlLine, Row, MusicGridRule, MysteryRule, OffByXRule, RegionAreaRule, RegionShapeRule, Rule, SameShapeRule, SymbolsPerRegionRule, UndercluedRule, UniqueShapeRule, 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, GalaxyBTModule, LetterBTModule, LotusBTModule, MinesweeperBTModule, MyopiaBTModule, ViewpointBTModule, Solver, UndercluedSolver, AreaNumberModule, CellCountModule, ConnectAllModule, DartModule, allZ3Modules, LetterModule, MyopiaModule, RegionAreaModule, ViewpointModule, Z3Module, convertDirection, Z3Solver, Z3SolverContext, AreaNumberSymbol, CustomIconSymbol, CustomSymbol, CustomTextSymbol, DartSymbol, DirectionLinkerSymbol, GalaxySymbol, HiddenSymbol, allSymbols, LetterSymbol, LotusSymbol, MinesweeperSymbol, MultiEntrySymbol, MyopiaSymbol, NumberSymbol, Symbol, ViewpointSymbol, TileData, TileConnections, validateGrid, aggregateState, applyFinalOverrides, };
|
|
103
|
+
export { ConfigType, configEquals, Configurable, CachedAccess, allEqual, array, directionToRotation, escape, isSameEdge, maxBy, minBy, move, orientationToRotation, resize, unescape, isEventHandler, handlesFinalValidation, handlesGridChange, handlesGridResize, handlesSetGrid, handlesSymbolDisplay, handlesSymbolValidation, GridData, NEIGHBOR_OFFSETS, GridConnections, Instruction, COMPARISONS, Color, Comparison, DIRECTIONS, Direction, MajorRule, Mode, ORIENTATIONS, Orientation, State, directionToggle, orientationToggle, MetadataSchema, PuzzleSchema, BanPatternRule, CellCountPerZoneRule, CellCountRule, CompletePatternRule, ConnectAllRule, CustomRule, ForesightRule, allRules, ControlLine, Row, MusicGridRule, MysteryRule, OffByXRule, PerfectionRule, RegionAreaRule, RegionShapeRule, Rule, SameShapeRule, SymbolsPerRegionRule, UndercluedRule, UniqueShapeRule, 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, GalaxyBTModule, LetterBTModule, LotusBTModule, MinesweeperBTModule, MyopiaBTModule, ViewpointBTModule, Solver, UndercluedSolver, AreaNumberModule, CellCountModule, ConnectAllModule, DartModule, allZ3Modules, LetterModule, MyopiaModule, RegionAreaModule, ViewpointModule, Z3Module, convertDirection, Z3Solver, Z3SolverContext, AreaNumberSymbol, CustomIconSymbol, CustomSymbol, CustomTextSymbol, DartSymbol, DirectionLinkerSymbol, GalaxySymbol, HiddenSymbol, allSymbols, LetterSymbol, LotusSymbol, MinesweeperSymbol, MultiEntrySymbol, MyopiaSymbol, NumberSymbol, Symbol, ViewpointSymbol, TileData, TileConnections, validateGrid, aggregateState, applyFinalOverrides, };
|