@logic-pad/core 0.1.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.
Files changed (211) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +19 -0
  3. package/assets/logic-core.global.d.ts +5865 -0
  4. package/assets/z3-built.js +14723 -0
  5. package/assets/z3-built.wasm +0 -0
  6. package/assets/z3-built.worker.js +206 -0
  7. package/dist/data/config.d.ts +101 -0
  8. package/dist/data/config.js +55 -0
  9. package/dist/data/configurable.d.ts +12 -0
  10. package/dist/data/configurable.js +26 -0
  11. package/dist/data/dataHelper.d.ts +77 -0
  12. package/dist/data/dataHelper.js +190 -0
  13. package/dist/data/events/eventHelper.d.ts +1 -0
  14. package/dist/data/events/eventHelper.js +6 -0
  15. package/dist/data/events/onFinalValidation.d.ts +14 -0
  16. package/dist/data/events/onFinalValidation.js +4 -0
  17. package/dist/data/events/onGridChange.d.ts +6 -0
  18. package/dist/data/events/onGridChange.js +4 -0
  19. package/dist/data/events/onGridResize.d.ts +9 -0
  20. package/dist/data/events/onGridResize.js +4 -0
  21. package/dist/data/events/onSetGrid.d.ts +6 -0
  22. package/dist/data/events/onSetGrid.js +4 -0
  23. package/dist/data/events/onSymbolValidation.d.ts +18 -0
  24. package/dist/data/events/onSymbolValidation.js +4 -0
  25. package/dist/data/grid.d.ts +362 -0
  26. package/dist/data/grid.js +886 -0
  27. package/dist/data/gridConnections.d.ts +38 -0
  28. package/dist/data/gridConnections.js +328 -0
  29. package/dist/data/instruction.d.ts +19 -0
  30. package/dist/data/instruction.js +23 -0
  31. package/dist/data/primitives.d.ts +85 -0
  32. package/dist/data/primitives.js +90 -0
  33. package/dist/data/puzzle.d.ts +86 -0
  34. package/dist/data/puzzle.js +22 -0
  35. package/dist/data/rules/banPatternRule.d.ts +29 -0
  36. package/dist/data/rules/banPatternRule.js +133 -0
  37. package/dist/data/rules/cellCountRule.d.ts +32 -0
  38. package/dist/data/rules/cellCountRule.js +166 -0
  39. package/dist/data/rules/completePatternRule.d.ts +22 -0
  40. package/dist/data/rules/completePatternRule.js +53 -0
  41. package/dist/data/rules/connectAllRule.d.ts +28 -0
  42. package/dist/data/rules/connectAllRule.js +113 -0
  43. package/dist/data/rules/customRule.d.ts +32 -0
  44. package/dist/data/rules/customRule.js +92 -0
  45. package/dist/data/rules/foresightRule.d.ts +30 -0
  46. package/dist/data/rules/foresightRule.js +107 -0
  47. package/dist/data/rules/index.d.ts +3 -0
  48. package/dist/data/rules/index.js +10 -0
  49. package/dist/data/rules/musicControlLine.d.ts +64 -0
  50. package/dist/data/rules/musicControlLine.js +178 -0
  51. package/dist/data/rules/musicGridRule.d.ts +46 -0
  52. package/dist/data/rules/musicGridRule.js +211 -0
  53. package/dist/data/rules/mysteryRule.d.ts +37 -0
  54. package/dist/data/rules/mysteryRule.js +164 -0
  55. package/dist/data/rules/offByXRule.d.ts +30 -0
  56. package/dist/data/rules/offByXRule.js +134 -0
  57. package/dist/data/rules/regionAreaRule.d.ts +33 -0
  58. package/dist/data/rules/regionAreaRule.js +182 -0
  59. package/dist/data/rules/regionShapeRule.d.ts +22 -0
  60. package/dist/data/rules/regionShapeRule.js +58 -0
  61. package/dist/data/rules/rule.d.ts +18 -0
  62. package/dist/data/rules/rule.js +19 -0
  63. package/dist/data/rules/rules.gen.d.ts +14 -0
  64. package/dist/data/rules/rules.gen.js +18 -0
  65. package/dist/data/rules/sameShapeRule.d.ts +27 -0
  66. package/dist/data/rules/sameShapeRule.js +88 -0
  67. package/dist/data/rules/symbolsPerRegionRule.d.ts +37 -0
  68. package/dist/data/rules/symbolsPerRegionRule.js +211 -0
  69. package/dist/data/rules/undercluedRule.d.ts +22 -0
  70. package/dist/data/rules/undercluedRule.js +60 -0
  71. package/dist/data/rules/uniqueShapeRule.d.ts +27 -0
  72. package/dist/data/rules/uniqueShapeRule.js +85 -0
  73. package/dist/data/serializer/allSerializers.d.ts +30 -0
  74. package/dist/data/serializer/allSerializers.js +64 -0
  75. package/dist/data/serializer/compressor/allCompressors.d.ts +14 -0
  76. package/dist/data/serializer/compressor/allCompressors.js +43 -0
  77. package/dist/data/serializer/compressor/compressorBase.d.ts +16 -0
  78. package/dist/data/serializer/compressor/compressorBase.js +2 -0
  79. package/dist/data/serializer/compressor/deflateCompressor.d.ts +7 -0
  80. package/dist/data/serializer/compressor/deflateCompressor.js +17 -0
  81. package/dist/data/serializer/compressor/gzipCompressor.d.ts +5 -0
  82. package/dist/data/serializer/compressor/gzipCompressor.js +9 -0
  83. package/dist/data/serializer/compressor/streamCompressor.d.ts +6 -0
  84. package/dist/data/serializer/compressor/streamCompressor.js +36 -0
  85. package/dist/data/serializer/serializerBase.d.ts +27 -0
  86. package/dist/data/serializer/serializerBase.js +2 -0
  87. package/dist/data/serializer/serializer_v0.d.ts +36 -0
  88. package/dist/data/serializer/serializer_v0.js +426 -0
  89. package/dist/data/shapes.d.ts +17 -0
  90. package/dist/data/shapes.js +117 -0
  91. package/dist/data/solver/allSolvers.d.ts +3 -0
  92. package/dist/data/solver/allSolvers.js +11 -0
  93. package/dist/data/solver/backtrack/backtrackSolver.d.ts +9 -0
  94. package/dist/data/solver/backtrack/backtrackSolver.js +92 -0
  95. package/dist/data/solver/backtrack/backtrackWorker.d.ts +2 -0
  96. package/dist/data/solver/backtrack/backtrackWorker.js +295 -0
  97. package/dist/data/solver/backtrack/data.d.ts +46 -0
  98. package/dist/data/solver/backtrack/data.js +140 -0
  99. package/dist/data/solver/backtrack/rules/banPattern.d.ts +9 -0
  100. package/dist/data/solver/backtrack/rules/banPattern.js +66 -0
  101. package/dist/data/solver/backtrack/rules/cellCount.d.ts +7 -0
  102. package/dist/data/solver/backtrack/rules/cellCount.js +30 -0
  103. package/dist/data/solver/backtrack/rules/connectAll.d.ts +7 -0
  104. package/dist/data/solver/backtrack/rules/connectAll.js +49 -0
  105. package/dist/data/solver/backtrack/rules/regionArea.d.ts +8 -0
  106. package/dist/data/solver/backtrack/rules/regionArea.js +76 -0
  107. package/dist/data/solver/backtrack/rules/regionShape.d.ts +8 -0
  108. package/dist/data/solver/backtrack/rules/regionShape.js +62 -0
  109. package/dist/data/solver/backtrack/rules/sameShape.d.ts +8 -0
  110. package/dist/data/solver/backtrack/rules/sameShape.js +19 -0
  111. package/dist/data/solver/backtrack/rules/symbolsPerRegion.d.ts +10 -0
  112. package/dist/data/solver/backtrack/rules/symbolsPerRegion.js +92 -0
  113. package/dist/data/solver/backtrack/rules/uniqueShape.d.ts +8 -0
  114. package/dist/data/solver/backtrack/rules/uniqueShape.js +19 -0
  115. package/dist/data/solver/backtrack/symbols/areaNumber.d.ts +9 -0
  116. package/dist/data/solver/backtrack/symbols/areaNumber.js +77 -0
  117. package/dist/data/solver/backtrack/symbols/dart.d.ts +9 -0
  118. package/dist/data/solver/backtrack/symbols/dart.js +58 -0
  119. package/dist/data/solver/backtrack/symbols/directionLinker.d.ts +9 -0
  120. package/dist/data/solver/backtrack/symbols/directionLinker.js +50 -0
  121. package/dist/data/solver/backtrack/symbols/galaxy.d.ts +9 -0
  122. package/dist/data/solver/backtrack/symbols/galaxy.js +19 -0
  123. package/dist/data/solver/backtrack/symbols/letter.d.ts +9 -0
  124. package/dist/data/solver/backtrack/symbols/letter.js +100 -0
  125. package/dist/data/solver/backtrack/symbols/lotus.d.ts +9 -0
  126. package/dist/data/solver/backtrack/symbols/lotus.js +36 -0
  127. package/dist/data/solver/backtrack/symbols/minesweeper.d.ts +9 -0
  128. package/dist/data/solver/backtrack/symbols/minesweeper.js +55 -0
  129. package/dist/data/solver/backtrack/symbols/myopia.d.ts +7 -0
  130. package/dist/data/solver/backtrack/symbols/myopia.js +79 -0
  131. package/dist/data/solver/backtrack/symbols/viewpoint.d.ts +7 -0
  132. package/dist/data/solver/backtrack/symbols/viewpoint.js +56 -0
  133. package/dist/data/solver/solver.d.ts +61 -0
  134. package/dist/data/solver/solver.js +55 -0
  135. package/dist/data/solver/underclued/undercluedSolver.d.ts +8 -0
  136. package/dist/data/solver/underclued/undercluedSolver.js +55 -0
  137. package/dist/data/solver/underclued/undercluedWorker.d.ts +2 -0
  138. package/dist/data/solver/underclued/undercluedWorker.js +131 -0
  139. package/dist/data/solver/z3/modules/areaNumberModule.d.ts +9 -0
  140. package/dist/data/solver/z3/modules/areaNumberModule.js +35 -0
  141. package/dist/data/solver/z3/modules/cellCountModule.d.ts +9 -0
  142. package/dist/data/solver/z3/modules/cellCountModule.js +59 -0
  143. package/dist/data/solver/z3/modules/connectAllModule.d.ts +9 -0
  144. package/dist/data/solver/z3/modules/connectAllModule.js +32 -0
  145. package/dist/data/solver/z3/modules/dartModule.d.ts +9 -0
  146. package/dist/data/solver/z3/modules/dartModule.js +69 -0
  147. package/dist/data/solver/z3/modules/index.d.ts +3 -0
  148. package/dist/data/solver/z3/modules/index.js +10 -0
  149. package/dist/data/solver/z3/modules/letterModule.d.ts +9 -0
  150. package/dist/data/solver/z3/modules/letterModule.js +41 -0
  151. package/dist/data/solver/z3/modules/modules.gen.d.ts +8 -0
  152. package/dist/data/solver/z3/modules/modules.gen.js +12 -0
  153. package/dist/data/solver/z3/modules/myopiaModule.d.ts +9 -0
  154. package/dist/data/solver/z3/modules/myopiaModule.js +64 -0
  155. package/dist/data/solver/z3/modules/regionAreaModule.d.ts +9 -0
  156. package/dist/data/solver/z3/modules/regionAreaModule.js +48 -0
  157. package/dist/data/solver/z3/modules/viewpointModule.d.ts +9 -0
  158. package/dist/data/solver/z3/modules/viewpointModule.js +37 -0
  159. package/dist/data/solver/z3/modules/z3Module.d.ts +7 -0
  160. package/dist/data/solver/z3/modules/z3Module.js +3 -0
  161. package/dist/data/solver/z3/utils.d.ts +2 -0
  162. package/dist/data/solver/z3/utils.js +26 -0
  163. package/dist/data/solver/z3/z3Solver.d.ts +10 -0
  164. package/dist/data/solver/z3/z3Solver.js +134 -0
  165. package/dist/data/solver/z3/z3SolverContext.d.ts +808 -0
  166. package/dist/data/solver/z3/z3SolverContext.js +49 -0
  167. package/dist/data/symbols/areaNumberSymbol.d.ts +30 -0
  168. package/dist/data/symbols/areaNumberSymbol.js +88 -0
  169. package/dist/data/symbols/customIconSymbol.d.ts +35 -0
  170. package/dist/data/symbols/customIconSymbol.js +105 -0
  171. package/dist/data/symbols/customSymbol.d.ts +23 -0
  172. package/dist/data/symbols/customSymbol.js +48 -0
  173. package/dist/data/symbols/customTextSymbol.d.ts +33 -0
  174. package/dist/data/symbols/customTextSymbol.js +106 -0
  175. package/dist/data/symbols/dartSymbol.d.ts +35 -0
  176. package/dist/data/symbols/dartSymbol.js +110 -0
  177. package/dist/data/symbols/directionLinkerSymbol.d.ts +36 -0
  178. package/dist/data/symbols/directionLinkerSymbol.js +259 -0
  179. package/dist/data/symbols/galaxySymbol.d.ts +26 -0
  180. package/dist/data/symbols/galaxySymbol.js +74 -0
  181. package/dist/data/symbols/index.d.ts +3 -0
  182. package/dist/data/symbols/index.js +10 -0
  183. package/dist/data/symbols/letterSymbol.d.ts +31 -0
  184. package/dist/data/symbols/letterSymbol.js +137 -0
  185. package/dist/data/symbols/lotusSymbol.d.ts +29 -0
  186. package/dist/data/symbols/lotusSymbol.js +132 -0
  187. package/dist/data/symbols/minesweeperSymbol.d.ts +31 -0
  188. package/dist/data/symbols/minesweeperSymbol.js +100 -0
  189. package/dist/data/symbols/multiEntrySymbol.d.ts +11 -0
  190. package/dist/data/symbols/multiEntrySymbol.js +14 -0
  191. package/dist/data/symbols/myopiaSymbol.d.ts +34 -0
  192. package/dist/data/symbols/myopiaSymbol.js +187 -0
  193. package/dist/data/symbols/numberSymbol.d.ts +19 -0
  194. package/dist/data/symbols/numberSymbol.js +41 -0
  195. package/dist/data/symbols/symbol.d.ts +16 -0
  196. package/dist/data/symbols/symbol.js +51 -0
  197. package/dist/data/symbols/symbols.gen.d.ts +10 -0
  198. package/dist/data/symbols/symbols.gen.js +14 -0
  199. package/dist/data/symbols/viewpointSymbol.d.ts +31 -0
  200. package/dist/data/symbols/viewpointSymbol.js +106 -0
  201. package/dist/data/tile.d.ts +26 -0
  202. package/dist/data/tile.js +68 -0
  203. package/dist/data/tileConnections.d.ts +25 -0
  204. package/dist/data/tileConnections.js +74 -0
  205. package/dist/data/validate.d.ts +5 -0
  206. package/dist/data/validate.js +131 -0
  207. package/dist/index.d.ts +96 -0
  208. package/dist/index.js +100 -0
  209. package/dist/polyfill/streamPolyfill.d.ts +2 -0
  210. package/dist/polyfill/streamPolyfill.js +1 -0
  211. package/package.json +75 -0
@@ -0,0 +1,182 @@
1
+ import { ConfigType } from '../config';
2
+ import GridData from '../grid';
3
+ import { array } from '../dataHelper';
4
+ import { Color, State } from '../primitives';
5
+ import TileData from '../tile';
6
+ import Rule from './rule';
7
+ class RegionAreaRule extends Rule {
8
+ /**
9
+ * **All <color> regions have area <size>**
10
+ *
11
+ * @param color - The color of the regions.
12
+ * @param size - The area of the regions.
13
+ */
14
+ constructor(color, size) {
15
+ super();
16
+ Object.defineProperty(this, "color", {
17
+ enumerable: true,
18
+ configurable: true,
19
+ writable: true,
20
+ value: color
21
+ });
22
+ Object.defineProperty(this, "size", {
23
+ enumerable: true,
24
+ configurable: true,
25
+ writable: true,
26
+ value: size
27
+ });
28
+ this.color = color;
29
+ this.size = size;
30
+ }
31
+ get id() {
32
+ return `region_area`;
33
+ }
34
+ get explanation() {
35
+ return `All ${this.color} regions have area ${this.size}`;
36
+ }
37
+ get configs() {
38
+ return RegionAreaRule.CONFIGS;
39
+ }
40
+ createExampleGrid() {
41
+ if (this.size < RegionAreaRule.EXAMPLE_GRID_DARK.length) {
42
+ switch (this.color) {
43
+ case Color.Dark:
44
+ return RegionAreaRule.EXAMPLE_GRID_DARK[this.size];
45
+ case Color.Light:
46
+ return RegionAreaRule.EXAMPLE_GRID_LIGHT[this.size];
47
+ case Color.Gray:
48
+ return RegionAreaRule.EXAMPLE_GRID_GRAY[this.size];
49
+ }
50
+ }
51
+ else {
52
+ let count = this.size;
53
+ const tiles = array(5, 4, (x, y) => {
54
+ count--;
55
+ return new TileData(true, false, count >= 0
56
+ ? this.color
57
+ : this.color === Color.Gray
58
+ ? x % 2 !== y % 2
59
+ ? Color.Dark
60
+ : Color.Light
61
+ : this.color === Color.Light
62
+ ? Color.Dark
63
+ : Color.Light);
64
+ });
65
+ return new GridData(5, 4, tiles);
66
+ }
67
+ }
68
+ get searchVariants() {
69
+ return RegionAreaRule.SEARCH_VARIANTS;
70
+ }
71
+ validateGrid(grid) {
72
+ const visited = array(grid.width, grid.height, (i, j) => !(grid.getTile(i, j).exists && grid.getTile(i, j).color === this.color));
73
+ let complete = true;
74
+ while (true) {
75
+ const seed = grid.find((_tile, x, y) => !visited[y][x]);
76
+ if (!seed)
77
+ break;
78
+ const completed = [];
79
+ const gray = [];
80
+ grid.iterateArea({ x: seed.x, y: seed.y }, tile => tile.color === this.color, (_, x, y) => {
81
+ completed.push({ x, y });
82
+ visited[y][x] = true;
83
+ });
84
+ if (this.color === Color.Gray) {
85
+ gray.push(...completed);
86
+ }
87
+ else {
88
+ grid.iterateArea({ x: seed.x, y: seed.y }, tile => tile.color === Color.Gray || tile.color === this.color, (_, x, y) => {
89
+ gray.push({ x, y });
90
+ });
91
+ }
92
+ if (completed.length > this.size) {
93
+ return { state: State.Error, positions: completed };
94
+ }
95
+ else if (gray.length < this.size) {
96
+ return { state: State.Error, positions: gray };
97
+ }
98
+ else if (completed.length !== this.size ||
99
+ completed.length !== gray.length) {
100
+ complete = false;
101
+ }
102
+ }
103
+ return complete ? { state: State.Satisfied } : { state: State.Incomplete };
104
+ }
105
+ copyWith({ color, size }) {
106
+ return new RegionAreaRule(color ?? this.color, size ?? this.size);
107
+ }
108
+ withColor(color) {
109
+ return this.copyWith({ color });
110
+ }
111
+ withSize(size) {
112
+ return this.copyWith({ size });
113
+ }
114
+ }
115
+ Object.defineProperty(RegionAreaRule, "CONFIGS", {
116
+ enumerable: true,
117
+ configurable: true,
118
+ writable: true,
119
+ value: Object.freeze([
120
+ {
121
+ type: ConfigType.Color,
122
+ default: Color.Dark,
123
+ allowGray: false,
124
+ field: 'color',
125
+ description: 'Color',
126
+ configurable: true,
127
+ },
128
+ {
129
+ type: ConfigType.Number,
130
+ default: 2,
131
+ min: 0,
132
+ field: 'size',
133
+ description: 'Region Size',
134
+ configurable: true,
135
+ },
136
+ ])
137
+ });
138
+ Object.defineProperty(RegionAreaRule, "EXAMPLE_GRID_DARK", {
139
+ enumerable: true,
140
+ configurable: true,
141
+ writable: true,
142
+ value: Object.freeze([
143
+ GridData.create(['wwwww', 'wwwww', 'wwwww', 'wwwww']),
144
+ GridData.create(['bwwbw', 'wbwwb', 'bwbww', 'wbwwb']),
145
+ GridData.create(['bbwbb', 'wwbww', 'wwbww', 'wwwbb']),
146
+ GridData.create(['bbwww', 'bwbwb', 'wbbwb', 'wwwwb']),
147
+ GridData.create(['bwbbb', 'bbwwb', 'bwbbw', 'wwbbw']),
148
+ GridData.create(['bbbww', 'bbwbw', 'wwbbb', 'wwwbw']),
149
+ GridData.create(['bbbww', 'bbbwb', 'wwwbb', 'wwbbb']),
150
+ GridData.create(['bbbbb', 'bbwww', 'wwwbb', 'bbbbb']),
151
+ GridData.create(['bbbbw', 'bbbww', 'bwwww', 'wwwww']),
152
+ GridData.create(['wwwww', 'bbbbb', 'bbwbb', 'wwwww']),
153
+ GridData.create(['bbbbb', 'bbbww', 'bbwww', 'wwwww']),
154
+ ])
155
+ });
156
+ Object.defineProperty(RegionAreaRule, "EXAMPLE_GRID_LIGHT", {
157
+ enumerable: true,
158
+ configurable: true,
159
+ writable: true,
160
+ value: Object.freeze(RegionAreaRule.EXAMPLE_GRID_DARK.map(grid => new GridData(grid.width, grid.height, grid.tiles.map(row => row.map(tile => tile.withColor(tile.color === Color.Dark ? Color.Light : Color.Dark))))))
161
+ });
162
+ Object.defineProperty(RegionAreaRule, "EXAMPLE_GRID_GRAY", {
163
+ enumerable: true,
164
+ configurable: true,
165
+ writable: true,
166
+ value: Object.freeze(RegionAreaRule.EXAMPLE_GRID_DARK.map(grid => new GridData(grid.width, grid.height, grid.tiles.map((row, y) => row.map((tile, x) => tile.withColor(tile.color === Color.Dark
167
+ ? Color.Gray
168
+ : x % 2 !== y % 2
169
+ ? Color.Dark
170
+ : Color.Light))))))
171
+ });
172
+ Object.defineProperty(RegionAreaRule, "SEARCH_VARIANTS", {
173
+ enumerable: true,
174
+ configurable: true,
175
+ writable: true,
176
+ value: [
177
+ new RegionAreaRule(Color.Dark, 2).searchVariant(),
178
+ new RegionAreaRule(Color.Light, 2).searchVariant(),
179
+ ]
180
+ });
181
+ export default RegionAreaRule;
182
+ export const instance = new RegionAreaRule(Color.Dark, 2);
@@ -0,0 +1,22 @@
1
+ import GridData from '../grid';
2
+ import { Color, Position } from '../primitives';
3
+ import { Shape } from '../shapes';
4
+ import Rule from './rule';
5
+ export type ShapeRegions = {
6
+ regions: {
7
+ positions: Position[];
8
+ shape: Shape;
9
+ count: number;
10
+ }[];
11
+ complete: boolean;
12
+ };
13
+ export default abstract class RegionShapeRule extends Rule {
14
+ readonly color: Color;
15
+ /**
16
+ * @param color - The color of the regions to compare.
17
+ */
18
+ constructor(color: Color);
19
+ protected getShapeRegions(grid: GridData): ShapeRegions;
20
+ withColor(color: Color): this;
21
+ }
22
+ export declare const instance: undefined;
@@ -0,0 +1,58 @@
1
+ import { array } from '../dataHelper';
2
+ import { Color } from '../primitives';
3
+ import { normalizeShape, positionsToShape, shapeEquals, } from '../shapes';
4
+ import Rule from './rule';
5
+ export default class RegionShapeRule extends Rule {
6
+ /**
7
+ * @param color - The color of the regions to compare.
8
+ */
9
+ constructor(color) {
10
+ super();
11
+ Object.defineProperty(this, "color", {
12
+ enumerable: true,
13
+ configurable: true,
14
+ writable: true,
15
+ value: color
16
+ });
17
+ this.color = color;
18
+ }
19
+ getShapeRegions(grid) {
20
+ let complete = true;
21
+ const visited = array(grid.width, grid.height, (i, j) => {
22
+ const tile = grid.getTile(i, j);
23
+ if (tile.exists && tile.color === Color.Gray)
24
+ complete = false;
25
+ return !(tile.exists && tile.color === this.color);
26
+ });
27
+ const regions = [];
28
+ while (true) {
29
+ const seed = grid.find((_tile, x, y) => !visited[y][x]);
30
+ if (!seed)
31
+ break;
32
+ const positions = [];
33
+ grid.iterateArea(seed, tile => tile.color === this.color, (_, x, y) => {
34
+ visited[y][x] = true;
35
+ positions.push({ x, y });
36
+ });
37
+ const incomplete = grid.iterateArea(seed, tile => tile.color === this.color || tile.color === Color.Gray, tile => {
38
+ if (tile.color === Color.Gray)
39
+ return true;
40
+ });
41
+ if (incomplete)
42
+ continue;
43
+ const shape = normalizeShape(positionsToShape(positions, this.color));
44
+ const existing = regions.find(island => shapeEquals(island.shape, shape));
45
+ if (existing) {
46
+ existing.count++;
47
+ }
48
+ else {
49
+ regions.push({ positions, shape, count: 1 });
50
+ }
51
+ }
52
+ return { regions, complete };
53
+ }
54
+ withColor(color) {
55
+ return this.copyWith({ color });
56
+ }
57
+ }
58
+ export const instance = undefined;
@@ -0,0 +1,18 @@
1
+ import GridData from '../grid';
2
+ import { RuleState } from '../primitives';
3
+ import Instruction from '../instruction';
4
+ export interface SearchVariant {
5
+ description: string;
6
+ rule: Rule;
7
+ }
8
+ export default abstract class Rule extends Instruction {
9
+ abstract validateGrid(grid: GridData): RuleState;
10
+ abstract get searchVariants(): SearchVariant[];
11
+ searchVariant(): SearchVariant;
12
+ get visibleWhenSolving(): boolean;
13
+ /**
14
+ * Whether only one instance of this rule is allowed in a grid.
15
+ */
16
+ get isSingleton(): boolean;
17
+ }
18
+ export declare const instance: undefined;
@@ -0,0 +1,19 @@
1
+ import Instruction from '../instruction';
2
+ export default class Rule extends Instruction {
3
+ searchVariant() {
4
+ return {
5
+ description: this.explanation,
6
+ rule: this,
7
+ };
8
+ }
9
+ get visibleWhenSolving() {
10
+ return true;
11
+ }
12
+ /**
13
+ * Whether only one instance of this rule is allowed in a grid.
14
+ */
15
+ get isSingleton() {
16
+ return false;
17
+ }
18
+ }
19
+ export const instance = undefined;
@@ -0,0 +1,14 @@
1
+ export { instance as BanPatternRule } from './banPatternRule';
2
+ export { instance as CellCountRule } from './cellCountRule';
3
+ export { instance as CompletePatternRule } from './completePatternRule';
4
+ export { instance as ConnectAllRule } from './connectAllRule';
5
+ export { instance as CustomRule } from './customRule';
6
+ export { instance as ForesightRule } from './foresightRule';
7
+ export { instance as MusicGridRule } from './musicGridRule';
8
+ export { instance as MysteryRule } from './mysteryRule';
9
+ export { instance as OffByXRule } from './offByXRule';
10
+ export { instance as RegionAreaRule } from './regionAreaRule';
11
+ export { instance as SameShapeRule } from './sameShapeRule';
12
+ export { instance as SymbolsPerRegionRule } from './symbolsPerRegionRule';
13
+ export { instance as UndercluedRule } from './undercluedRule';
14
+ export { instance as UniqueShapeRule } from './uniqueShapeRule';
@@ -0,0 +1,18 @@
1
+ /* prettier-ignore-start */
2
+ /* eslint-disable */
3
+ // @ts-nocheck
4
+ // noinspection JSUnusedGlobalSymbols
5
+ export { instance as BanPatternRule } from './banPatternRule';
6
+ export { instance as CellCountRule } from './cellCountRule';
7
+ export { instance as CompletePatternRule } from './completePatternRule';
8
+ export { instance as ConnectAllRule } from './connectAllRule';
9
+ export { instance as CustomRule } from './customRule';
10
+ export { instance as ForesightRule } from './foresightRule';
11
+ export { instance as MusicGridRule } from './musicGridRule';
12
+ export { instance as MysteryRule } from './mysteryRule';
13
+ export { instance as OffByXRule } from './offByXRule';
14
+ export { instance as RegionAreaRule } from './regionAreaRule';
15
+ export { instance as SameShapeRule } from './sameShapeRule';
16
+ export { instance as SymbolsPerRegionRule } from './symbolsPerRegionRule';
17
+ export { instance as UndercluedRule } from './undercluedRule';
18
+ export { instance as UniqueShapeRule } from './uniqueShapeRule';
@@ -0,0 +1,27 @@
1
+ import { AnyConfig } from '../config';
2
+ import GridData from '../grid';
3
+ import { Color, RuleState } from '../primitives';
4
+ import RegionShapeRule from './regionShapeRule';
5
+ import { SearchVariant } from './rule';
6
+ export default class SameShapeRule extends RegionShapeRule {
7
+ private static readonly CONFIGS;
8
+ private static readonly EXAMPLE_GRID_LIGHT;
9
+ private static readonly EXAMPLE_GRID_DARK;
10
+ private static readonly SEARCH_VARIANTS;
11
+ /**
12
+ * **All &lt;color&gt; areas have the same shape and size**
13
+ *
14
+ * @param color - The color of the regions to compare.
15
+ */
16
+ constructor(color: Color);
17
+ get id(): string;
18
+ get explanation(): string;
19
+ get configs(): readonly AnyConfig[] | null;
20
+ createExampleGrid(): GridData;
21
+ get searchVariants(): SearchVariant[];
22
+ validateGrid(grid: GridData): RuleState;
23
+ copyWith({ color }: {
24
+ color?: Color;
25
+ }): this;
26
+ }
27
+ export declare const instance: SameShapeRule;
@@ -0,0 +1,88 @@
1
+ import { ConfigType } from '../config';
2
+ import GridData from '../grid';
3
+ import { minBy } from '../dataHelper';
4
+ import { Color, State } from '../primitives';
5
+ import RegionShapeRule from './regionShapeRule';
6
+ class SameShapeRule extends RegionShapeRule {
7
+ /**
8
+ * **All &lt;color&gt; areas have the same shape and size**
9
+ *
10
+ * @param color - The color of the regions to compare.
11
+ */
12
+ constructor(color) {
13
+ super(color);
14
+ }
15
+ get id() {
16
+ return `same_shape`;
17
+ }
18
+ get explanation() {
19
+ return `All ${this.color} areas have the same shape and size`;
20
+ }
21
+ get configs() {
22
+ return SameShapeRule.CONFIGS;
23
+ }
24
+ createExampleGrid() {
25
+ return this.color === Color.Light
26
+ ? SameShapeRule.EXAMPLE_GRID_LIGHT
27
+ : SameShapeRule.EXAMPLE_GRID_DARK;
28
+ }
29
+ get searchVariants() {
30
+ return SameShapeRule.SEARCH_VARIANTS;
31
+ }
32
+ validateGrid(grid) {
33
+ const { regions, complete } = this.getShapeRegions(grid);
34
+ if (regions.length > 1) {
35
+ return {
36
+ state: State.Error,
37
+ positions: minBy(regions, island => island.count).positions,
38
+ };
39
+ }
40
+ else if (regions.length <= 1) {
41
+ return { state: complete ? State.Satisfied : State.Incomplete };
42
+ }
43
+ else {
44
+ return { state: State.Incomplete }; // not reachable but the TS is not happy
45
+ }
46
+ }
47
+ copyWith({ color }) {
48
+ return new SameShapeRule(color ?? this.color);
49
+ }
50
+ }
51
+ Object.defineProperty(SameShapeRule, "CONFIGS", {
52
+ enumerable: true,
53
+ configurable: true,
54
+ writable: true,
55
+ value: Object.freeze([
56
+ {
57
+ type: ConfigType.Color,
58
+ default: Color.Light,
59
+ allowGray: false,
60
+ field: 'color',
61
+ description: 'Color',
62
+ configurable: true,
63
+ },
64
+ ])
65
+ });
66
+ Object.defineProperty(SameShapeRule, "EXAMPLE_GRID_LIGHT", {
67
+ enumerable: true,
68
+ configurable: true,
69
+ writable: true,
70
+ value: Object.freeze(GridData.create(['wwbww', 'wbwbw', 'wbwbw', 'bwwbb']))
71
+ });
72
+ Object.defineProperty(SameShapeRule, "EXAMPLE_GRID_DARK", {
73
+ enumerable: true,
74
+ configurable: true,
75
+ writable: true,
76
+ value: Object.freeze(GridData.create(['bbwbb', 'bwbwb', 'bwbwb', 'wbbww']))
77
+ });
78
+ Object.defineProperty(SameShapeRule, "SEARCH_VARIANTS", {
79
+ enumerable: true,
80
+ configurable: true,
81
+ writable: true,
82
+ value: [
83
+ new SameShapeRule(Color.Light).searchVariant(),
84
+ new SameShapeRule(Color.Dark).searchVariant(),
85
+ ]
86
+ });
87
+ export default SameShapeRule;
88
+ export const instance = new SameShapeRule(Color.Dark);
@@ -0,0 +1,37 @@
1
+ import Rule, { SearchVariant } from './rule';
2
+ import GridData from '../grid';
3
+ import { AnyConfig } from '../config';
4
+ import { Color, Comparison, RuleState } from '../primitives';
5
+ export default class SymbolsPerRegionRule extends Rule {
6
+ readonly color: Color;
7
+ readonly count: number;
8
+ readonly comparison: Comparison;
9
+ private static readonly SYMBOL_POSITIONS;
10
+ private static readonly CONFIGS;
11
+ private static readonly EXAMPLE_GRIDS;
12
+ private static readonly SEARCH_VARIANTS;
13
+ /**
14
+ * **Exactly &lt;count&gt; symbols per &lt;color&gt; area**
15
+ *
16
+ * @param color - Color of the region affected by the rule
17
+ * @param count - Number of symbols to have in each region
18
+ * @param comparison - Comparison to use when checking the number of symbols
19
+ */
20
+ constructor(color: Color, count: number, comparison?: Comparison);
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({ count, color, comparison, }: {
28
+ count?: number;
29
+ color?: Color;
30
+ comparison?: Comparison;
31
+ }): this;
32
+ withColor(color: Color): this;
33
+ withCount(count: number): this;
34
+ withComparison(comparison: Comparison): this;
35
+ private static countAllSymbolsOfPosition;
36
+ }
37
+ export declare const instance: SymbolsPerRegionRule;