@logic-pad/core 0.4.0 → 0.4.2

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.
@@ -112,6 +112,30 @@ declare global {
112
112
  Create = 'create',
113
113
  Solve = 'solve',
114
114
  }
115
+ export declare class GridZones {
116
+ readonly edges: readonly Edge[];
117
+ constructor(edges?: readonly Edge[]);
118
+ addEdge(edge: Edge): GridZones;
119
+ removeEdge(edge: Edge): GridZones;
120
+ hasEdge(edge: Edge): boolean;
121
+ getEdgesAt({ x, y }: Position$1): readonly Edge[];
122
+ /**
123
+ * Check if two GridZones objects are equal.
124
+ * @param other The other GridZones object to compare to.
125
+ * @returns Whether the two objects are equal.
126
+ */
127
+ equals(other: GridZones): boolean;
128
+ /**
129
+ * Deduplicate an array of edges.
130
+ * @param edges The array of edges to deduplicate.
131
+ * @returns The deduplicated array of edges.
132
+ */
133
+ static deduplicateEdges(edges: readonly Edge[]): readonly Edge[];
134
+ insertColumn(index: number): GridZones;
135
+ insertRow(index: number): GridZones;
136
+ removeColumn(index: number): GridZones;
137
+ removeRow(index: number): GridZones;
138
+ }
115
139
  export declare class TileConnections {
116
140
  [y: number]: {
117
141
  [x: number]: boolean;
@@ -137,13 +161,10 @@ declare global {
137
161
  set bottomRight(value: boolean);
138
162
  equals(other: TileConnections): boolean;
139
163
  }
140
- export declare class GridConnections {
141
- readonly edges: readonly Edge[];
164
+ export declare class GridConnections extends GridZones {
142
165
  constructor(edges?: readonly Edge[]);
143
166
  addEdge(edge: Edge): GridConnections;
144
167
  removeEdge(edge: Edge): GridConnections;
145
- isConnected(edge: Edge): boolean;
146
- getConnectionsAt({ x, y }: Position$1): readonly Edge[];
147
168
  getForTile({ x, y }: Position$1): TileConnections;
148
169
  getConnectedTiles({ x, y }: Position$1): readonly Position$1[];
149
170
  /**
@@ -156,18 +177,6 @@ declare global {
156
177
  * @returns The created connections. You can apply this to a GridData object using GridData.withConnections.
157
178
  */
158
179
  static create(array: string[]): GridConnections;
159
- /**
160
- * Check if two GridConnections objects are equal.
161
- * @param other The other GridConnections object to compare to.
162
- * @returns Whether the two objects are equal.
163
- */
164
- equals(other: GridConnections): boolean;
165
- /**
166
- * Deduplicate an array of edges.
167
- * @param edges The array of edges to deduplicate.
168
- * @returns The deduplicated array of edges.
169
- */
170
- static deduplicateEdges(edges: readonly Edge[]): readonly Edge[];
171
180
  insertColumn(index: number): GridConnections;
172
181
  insertRow(index: number): GridConnections;
173
182
  removeColumn(index: number): GridConnections;
@@ -590,6 +599,7 @@ declare global {
590
599
  readonly height: number;
591
600
  readonly tiles: readonly (readonly TileData[])[];
592
601
  readonly connections: GridConnections;
602
+ readonly zones: GridZones;
593
603
  readonly symbols: ReadonlyMap<string, readonly Symbol$1[]>;
594
604
  readonly rules: readonly Rule[];
595
605
  readonly musicGrid: CachedAccess<MusicGridRule | undefined>;
@@ -601,6 +611,7 @@ declare global {
601
611
  * @param height The height of the grid.
602
612
  * @param tiles The tiles of the grid.
603
613
  * @param connections The connections of the grid, which determines which tiles are merged.
614
+ * @param zones The zones of the grid.
604
615
  * @param symbols The symbols in the grid.
605
616
  * @param rules The rules of the grid.
606
617
  */
@@ -609,6 +620,7 @@ declare global {
609
620
  height: number,
610
621
  tiles?: readonly (readonly TileData[])[],
611
622
  connections?: GridConnections,
623
+ zones?: GridZones,
612
624
  symbols?: ReadonlyMap<string, readonly Symbol$1[]>,
613
625
  rules?: readonly Rule[]
614
626
  );
@@ -622,6 +634,7 @@ declare global {
622
634
  height,
623
635
  tiles,
624
636
  connections,
637
+ zones,
625
638
  symbols,
626
639
  rules,
627
640
  }: {
@@ -629,6 +642,7 @@ declare global {
629
642
  height?: number;
630
643
  tiles?: readonly (readonly TileData[])[];
631
644
  connections?: GridConnections;
645
+ zones?: GridZones;
632
646
  symbols?: ReadonlyMap<string, readonly Symbol$1[]>;
633
647
  rules?: readonly Rule[];
634
648
  }): GridData;
@@ -676,6 +690,12 @@ declare global {
676
690
  | GridConnections
677
691
  | ((value: GridConnections) => GridConnections)
678
692
  ): GridData;
693
+ /**
694
+ * Add or modify the zones in the grid.
695
+ * @param zones The new zones to add or modify.
696
+ * @returns The new grid with the new zones.
697
+ */
698
+ withZones(zones: GridZones | ((value: GridZones) => GridZones)): GridData;
679
699
  /**
680
700
  * Add or modify the symbols in the grid.
681
701
  * @param symbols The new symbols to add or modify.
@@ -1039,7 +1059,6 @@ declare global {
1039
1059
  ControlLines = 'controlLines',
1040
1060
  NullableNote = 'nullableNote',
1041
1061
  SolvePath = 'solvePath',
1042
- Edges = 'edges',
1043
1062
  }
1044
1063
  export interface Config<T> {
1045
1064
  readonly type: ConfigType;
@@ -1113,9 +1132,6 @@ declare global {
1113
1132
  export interface SolvePathConfig extends Config<Position$1[]> {
1114
1133
  readonly type: ConfigType.SolvePath;
1115
1134
  }
1116
- export interface EdgesConfig extends Config<Edge[]> {
1117
- readonly type: ConfigType.Edges;
1118
- }
1119
1135
  export type AnyConfig =
1120
1136
  | BooleanConfig
1121
1137
  | NullableBooleanConfig
@@ -1134,8 +1150,7 @@ declare global {
1134
1150
  | IconConfig
1135
1151
  | ControlLinesConfig
1136
1152
  | NullableNoteConfig
1137
- | SolvePathConfig
1138
- | EdgesConfig;
1153
+ | SolvePathConfig;
1139
1154
  /**
1140
1155
  * Compare two config values for equality, using an appropriate method for the config type.
1141
1156
  *
@@ -1226,9 +1241,9 @@ declare global {
1226
1241
  */
1227
1242
  link: string;
1228
1243
  /**
1229
- * The difficulty of the puzzle, from 1 to 10. (required)
1244
+ * The difficulty of the puzzle, from 0 to 10. (required)
1230
1245
  *
1231
- * 6-10 represent star difficulties.
1246
+ * 0 represents an unrated puzzle, 6-10 represent star difficulties.
1232
1247
  */
1233
1248
  difficulty: number;
1234
1249
  };
@@ -1347,7 +1362,6 @@ declare global {
1347
1362
  }
1348
1363
  export declare class CellCountPerZoneRule extends Rule {
1349
1364
  readonly color: Color;
1350
- readonly edges: readonly Edge[];
1351
1365
  private static readonly CONFIGS;
1352
1366
  private static readonly EXAMPLE_GRID_LIGHT;
1353
1367
  private static readonly EXAMPLE_GRID_DARK;
@@ -1357,26 +1371,16 @@ declare global {
1357
1371
  * **Every zone has the same number of &lt;color&gt; cells.**
1358
1372
  *
1359
1373
  * @param color - The color of the cells to count.
1360
- * @param edges - The edges of the zones to count.
1361
1374
  */
1362
- constructor(color: Color, edges: readonly Edge[]);
1375
+ constructor(color: Color);
1363
1376
  get id(): string;
1364
1377
  get explanation(): string;
1365
1378
  get configs(): readonly AnyConfig[] | null;
1366
1379
  createExampleGrid(): GridData;
1367
1380
  get searchVariants(): SearchVariant[];
1368
1381
  validateGrid(grid: GridData): RuleState;
1369
- copyWith({
1370
- color,
1371
- edges,
1372
- }: {
1373
- color?: Color;
1374
- edges?: readonly Edge[];
1375
- }): this;
1382
+ copyWith({ color }: { color?: Color }): this;
1376
1383
  withColor(color: Color): this;
1377
- withEdges(
1378
- edges: readonly Edge[] | ((edges: readonly Edge[]) => readonly Edge[])
1379
- ): this;
1380
1384
  }
1381
1385
  export declare class CellCountRule extends Rule {
1382
1386
  readonly color: Color;
@@ -1792,6 +1796,8 @@ declare global {
1792
1796
  abstract parseSymbol(str: string): Symbol$1;
1793
1797
  abstract stringifyConnections(connections: GridConnections): string;
1794
1798
  abstract parseConnections(input: string): GridConnections;
1799
+ abstract stringifyZones(zones: GridZones): string;
1800
+ abstract parseZones(input: string): GridZones;
1795
1801
  abstract stringifyTiles(tiles: readonly (readonly TileData[])[]): string;
1796
1802
  abstract parseTiles(input: string): TileData[][];
1797
1803
  abstract stringifyRules(rules: readonly Rule[]): string;
@@ -1823,6 +1829,8 @@ declare global {
1823
1829
  parseSymbol(str: string): Symbol$1;
1824
1830
  stringifyConnections(connections: GridConnections): string;
1825
1831
  parseConnections(input: string): GridConnections;
1832
+ stringifyZones(zones: GridZones): string;
1833
+ parseZones(input: string): GridZones;
1826
1834
  stringifyTiles(tiles: readonly (readonly TileData[])[]): string;
1827
1835
  parseTiles(input: string): TileData[][];
1828
1836
  stringifyRules(rules: readonly Rule[]): string;
@@ -1,5 +1,5 @@
1
1
  import GridData from './grid.js';
2
- import { Color, Comparison, Direction, DirectionToggle, Edge, Orientation, OrientationToggle, Position } from './primitives.js';
2
+ import { Color, Comparison, Direction, DirectionToggle, Orientation, OrientationToggle, Position } from './primitives.js';
3
3
  import { ControlLine } from './rules/musicControlLine.js';
4
4
  export declare enum ConfigType {
5
5
  Boolean = "boolean",
@@ -19,8 +19,7 @@ export declare enum ConfigType {
19
19
  Icon = "icon",
20
20
  ControlLines = "controlLines",
21
21
  NullableNote = "nullableNote",
22
- SolvePath = "solvePath",
23
- Edges = "edges"
22
+ SolvePath = "solvePath"
24
23
  }
25
24
  export interface Config<T> {
26
25
  readonly type: ConfigType;
@@ -94,10 +93,7 @@ export interface NullableNoteConfig extends Config<string | null> {
94
93
  export interface SolvePathConfig extends Config<Position[]> {
95
94
  readonly type: ConfigType.SolvePath;
96
95
  }
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;
96
+ export type AnyConfig = BooleanConfig | NullableBooleanConfig | NumberConfig | NullableNumberConfig | StringConfig | ColorConfig | ComparisonConfig | DirectionConfig | DirectionToggleConfig | OrientationConfig | OrientationToggleConfig | TileConfig | GridConfig | NullableGridConfig | IconConfig | ControlLinesConfig | NullableNoteConfig | SolvePathConfig;
101
97
  /**
102
98
  * Compare two config values for equality, using an appropriate method for the config type.
103
99
  *
@@ -1,4 +1,3 @@
1
- import { isSameEdge } from './dataHelper.js';
2
1
  import { DIRECTIONS, ORIENTATIONS, } from './primitives.js';
3
2
  export var ConfigType;
4
3
  (function (ConfigType) {
@@ -20,7 +19,6 @@ export var ConfigType;
20
19
  ConfigType["ControlLines"] = "controlLines";
21
20
  ConfigType["NullableNote"] = "nullableNote";
22
21
  ConfigType["SolvePath"] = "solvePath";
23
- ConfigType["Edges"] = "edges";
24
22
  })(ConfigType || (ConfigType = {}));
25
23
  /**
26
24
  * Compare two config values for equality, using an appropriate method for the config type.
@@ -61,12 +59,5 @@ export function configEquals(type, a, b) {
61
59
  return false;
62
60
  return aPath.every((pos, i) => pos.x === bPath[i].x && pos.y === bPath[i].y);
63
61
  }
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
- }
71
62
  return a === b;
72
63
  }
@@ -7,12 +7,14 @@ 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
+ import GridZones from './gridZones.js';
10
11
  export declare const NEIGHBOR_OFFSETS: Position[];
11
12
  export default class GridData {
12
13
  readonly width: number;
13
14
  readonly height: number;
14
15
  readonly tiles: readonly (readonly TileData[])[];
15
16
  readonly connections: GridConnections;
17
+ readonly zones: GridZones;
16
18
  readonly symbols: ReadonlyMap<string, readonly Symbol[]>;
17
19
  readonly rules: readonly Rule[];
18
20
  readonly musicGrid: CachedAccess<MusicGridRule | undefined>;
@@ -24,20 +26,22 @@ export default class GridData {
24
26
  * @param height The height of the grid.
25
27
  * @param tiles The tiles of the grid.
26
28
  * @param connections The connections of the grid, which determines which tiles are merged.
29
+ * @param zones The zones of the grid.
27
30
  * @param symbols The symbols in the grid.
28
31
  * @param rules The rules of the grid.
29
32
  */
30
- constructor(width: number, height: number, tiles?: readonly (readonly TileData[])[], connections?: GridConnections, symbols?: ReadonlyMap<string, readonly Symbol[]>, rules?: readonly Rule[]);
33
+ constructor(width: number, height: number, tiles?: readonly (readonly TileData[])[], connections?: GridConnections, zones?: GridZones, symbols?: ReadonlyMap<string, readonly Symbol[]>, rules?: readonly Rule[]);
31
34
  /**
32
35
  * Copy the current grid while modifying the provided properties.
33
36
  * @param param0 The properties to modify.
34
37
  * @returns The new grid with the modified properties.
35
38
  */
36
- copyWith({ width, height, tiles, connections, symbols, rules, }: {
39
+ copyWith({ width, height, tiles, connections, zones, symbols, rules, }: {
37
40
  width?: number;
38
41
  height?: number;
39
42
  tiles?: readonly (readonly TileData[])[];
40
43
  connections?: GridConnections;
44
+ zones?: GridZones;
41
45
  symbols?: ReadonlyMap<string, readonly Symbol[]>;
42
46
  rules?: readonly Rule[];
43
47
  }): GridData;
@@ -73,6 +77,12 @@ export default class GridData {
73
77
  * @returns The new grid with the new connections.
74
78
  */
75
79
  withConnections(connections: GridConnections | ((value: GridConnections) => GridConnections)): GridData;
80
+ /**
81
+ * Add or modify the zones in the grid.
82
+ * @param zones The new zones to add or modify.
83
+ * @returns The new grid with the new zones.
84
+ */
85
+ withZones(zones: GridZones | ((value: GridZones) => GridZones)): GridData;
76
86
  /**
77
87
  * Add or modify the symbols in the grid.
78
88
  * @param symbols The new symbols to add or modify.
package/dist/data/grid.js CHANGED
@@ -5,6 +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
+ import GridZones from './gridZones.js';
8
9
  export const NEIGHBOR_OFFSETS = [
9
10
  { x: -1, y: 0 },
10
11
  { x: 1, y: 0 },
@@ -19,10 +20,11 @@ export default class GridData {
19
20
  * @param height The height of the grid.
20
21
  * @param tiles The tiles of the grid.
21
22
  * @param connections The connections of the grid, which determines which tiles are merged.
23
+ * @param zones The zones of the grid.
22
24
  * @param symbols The symbols in the grid.
23
25
  * @param rules The rules of the grid.
24
26
  */
25
- constructor(width, height, tiles, connections, symbols, rules) {
27
+ constructor(width, height, tiles, connections, zones, symbols, rules) {
26
28
  Object.defineProperty(this, "width", {
27
29
  enumerable: true,
28
30
  configurable: true,
@@ -47,6 +49,12 @@ export default class GridData {
47
49
  writable: true,
48
50
  value: void 0
49
51
  });
52
+ Object.defineProperty(this, "zones", {
53
+ enumerable: true,
54
+ configurable: true,
55
+ writable: true,
56
+ value: void 0
57
+ });
50
58
  Object.defineProperty(this, "symbols", {
51
59
  enumerable: true,
52
60
  configurable: true,
@@ -83,6 +91,7 @@ export default class GridData {
83
91
  this.height = height;
84
92
  this.tiles = tiles ?? array(width, height, () => TileData.empty());
85
93
  this.connections = connections ?? new GridConnections();
94
+ this.zones = zones ?? new GridZones();
86
95
  const newSymbols = symbols
87
96
  ? GridData.deduplicateSymbols(symbols)
88
97
  : new Map();
@@ -108,8 +117,8 @@ export default class GridData {
108
117
  * @param param0 The properties to modify.
109
118
  * @returns The new grid with the modified properties.
110
119
  */
111
- copyWith({ width, height, tiles, connections, symbols, rules, }) {
112
- return new GridData(width ?? this.width, height ?? this.height, tiles ?? this.tiles, connections ?? this.connections, symbols ?? this.symbols, rules ?? this.rules);
120
+ copyWith({ width, height, tiles, connections, zones, symbols, rules, }) {
121
+ return new GridData(width ?? this.width, height ?? this.height, tiles ?? this.tiles, connections ?? this.connections, zones ?? this.zones, symbols ?? this.symbols, rules ?? this.rules);
113
122
  }
114
123
  isPositionValid(x, y) {
115
124
  return x >= 0 && x < this.width && y >= 0 && y < this.height;
@@ -173,6 +182,16 @@ export default class GridData {
173
182
  : connections,
174
183
  });
175
184
  }
185
+ /**
186
+ * Add or modify the zones in the grid.
187
+ * @param zones The new zones to add or modify.
188
+ * @returns The new grid with the new zones.
189
+ */
190
+ withZones(zones) {
191
+ return this.copyWith({
192
+ zones: typeof zones === 'function' ? zones(this.zones) : zones,
193
+ });
194
+ }
176
195
  /**
177
196
  * Add or modify the symbols in the grid.
178
197
  * @param symbols The new symbols to add or modify.
@@ -346,6 +365,7 @@ export default class GridData {
346
365
  return this.getTile(x - 1, y);
347
366
  });
348
367
  const connections = this.connections.insertColumn(index);
368
+ const zones = this.zones.insertColumn(index);
349
369
  const rules = this.rules
350
370
  .map(rule => {
351
371
  if (handlesGridResize(rule))
@@ -366,6 +386,7 @@ export default class GridData {
366
386
  width: this.width + 1,
367
387
  tiles,
368
388
  connections,
389
+ zones,
369
390
  rules,
370
391
  symbols,
371
392
  });
@@ -386,6 +407,7 @@ export default class GridData {
386
407
  return this.getTile(x, y - 1);
387
408
  });
388
409
  const connections = this.connections.insertRow(index);
410
+ const zones = this.zones.insertRow(index);
389
411
  const rules = this.rules
390
412
  .map(rule => {
391
413
  if (handlesGridResize(rule))
@@ -406,6 +428,7 @@ export default class GridData {
406
428
  height: this.height + 1,
407
429
  tiles,
408
430
  connections,
431
+ zones,
409
432
  rules,
410
433
  symbols,
411
434
  });
@@ -420,6 +443,7 @@ export default class GridData {
420
443
  return this;
421
444
  const tiles = array(this.width - 1, this.height, (x, y) => x < index ? this.getTile(x, y) : this.getTile(x + 1, y));
422
445
  const connections = this.connections.removeColumn(index);
446
+ const zones = this.zones.removeColumn(index);
423
447
  const rules = this.rules
424
448
  .map(rule => {
425
449
  if (handlesGridResize(rule))
@@ -440,6 +464,7 @@ export default class GridData {
440
464
  width: this.width - 1,
441
465
  tiles,
442
466
  connections,
467
+ zones,
443
468
  rules,
444
469
  symbols,
445
470
  });
@@ -454,6 +479,7 @@ export default class GridData {
454
479
  return this;
455
480
  const tiles = array(this.width, this.height - 1, (x, y) => y < index ? this.getTile(x, y) : this.getTile(x, y + 1));
456
481
  const connections = this.connections.removeRow(index);
482
+ const zones = this.zones.removeRow(index);
457
483
  const rules = this.rules
458
484
  .map(rule => {
459
485
  if (handlesGridResize(rule))
@@ -474,6 +500,7 @@ export default class GridData {
474
500
  height: this.height - 1,
475
501
  tiles,
476
502
  connections,
503
+ zones,
477
504
  rules,
478
505
  symbols,
479
506
  });
@@ -744,6 +771,21 @@ export default class GridData {
744
771
  x2: edge.x2 - origin.x,
745
772
  y2: edge.y2 - origin.y,
746
773
  })));
774
+ const zones = new GridZones(this.zones.edges
775
+ .filter(edge => edge.x1 >= origin.x &&
776
+ edge.y1 >= origin.y &&
777
+ edge.x2 >= origin.x &&
778
+ edge.y2 >= origin.y &&
779
+ edge.x1 < origin.x + width &&
780
+ edge.y1 < origin.y + height &&
781
+ edge.x2 < origin.x + width &&
782
+ edge.y2 < origin.y + height)
783
+ .map(edge => ({
784
+ x1: edge.x1 - origin.x,
785
+ y1: edge.y1 - origin.y,
786
+ x2: edge.x2 - origin.x,
787
+ y2: edge.y2 - origin.y,
788
+ })));
747
789
  const symbols = new Map();
748
790
  for (const [id, symbolList] of this.symbols) {
749
791
  const newSymbolList = symbolList.filter(symbol => symbol.x >= origin.x &&
@@ -753,7 +795,7 @@ export default class GridData {
753
795
  if (newSymbolList.length > 0)
754
796
  symbols.set(id, newSymbolList);
755
797
  }
756
- return new GridData(width, height, newTiles, connections, symbols, this.rules);
798
+ return new GridData(width, height, newTiles, connections, zones, symbols, this.rules);
757
799
  }
758
800
  pasteTiles(origin, grid) {
759
801
  if (!(grid instanceof GridData))
@@ -772,6 +814,15 @@ export default class GridData {
772
814
  y2: edge.y2 + origin.y,
773
815
  })),
774
816
  ]);
817
+ const zones = new GridZones([
818
+ ...this.zones.edges,
819
+ ...grid.zones.edges.map(edge => ({
820
+ x1: edge.x1 + origin.x,
821
+ y1: edge.y1 + origin.y,
822
+ x2: edge.x2 + origin.x,
823
+ y2: edge.y2 + origin.y,
824
+ })),
825
+ ]);
775
826
  const symbols = new Map(this.symbols);
776
827
  for (const [id, sourceList] of grid.symbols) {
777
828
  const symbolList = sourceList.map(symbol => symbol.copyWith({ x: symbol.x + origin.x, y: symbol.y + origin.y }));
@@ -783,7 +834,13 @@ export default class GridData {
783
834
  }
784
835
  }
785
836
  const rules = [...this.rules, ...grid.rules];
786
- return this.copyWith({ tiles: newTiles, connections, symbols, rules });
837
+ return this.copyWith({
838
+ tiles: newTiles,
839
+ connections,
840
+ zones,
841
+ symbols,
842
+ rules,
843
+ });
787
844
  }
788
845
  /**
789
846
  * Check if this grid is equal to another grid in terms of size and tile colors.
@@ -836,6 +893,8 @@ export default class GridData {
836
893
  return false;
837
894
  if (!this.connections.equals(other.connections))
838
895
  return false;
896
+ if (!this.zones.equals(other.zones))
897
+ return false;
839
898
  if (this.symbols.size !== other.symbols.size)
840
899
  return false;
841
900
  for (const [id, symbols] of this.symbols) {
@@ -1,12 +1,10 @@
1
+ import GridZones from './gridZones.js';
1
2
  import { Edge, Position } from './primitives.js';
2
3
  import TileConnections from './tileConnections.js';
3
- export default class GridConnections {
4
- readonly edges: readonly Edge[];
4
+ export default class GridConnections extends GridZones {
5
5
  constructor(edges?: readonly Edge[]);
6
6
  addEdge(edge: Edge): GridConnections;
7
7
  removeEdge(edge: Edge): GridConnections;
8
- isConnected(edge: Edge): boolean;
9
- getConnectionsAt({ x, y }: Position): readonly Edge[];
10
8
  getForTile({ x, y }: Position): TileConnections;
11
9
  getConnectedTiles({ x, y }: Position): readonly Position[];
12
10
  /**
@@ -19,18 +17,6 @@ export default class GridConnections {
19
17
  * @returns The created connections. You can apply this to a GridData object using GridData.withConnections.
20
18
  */
21
19
  static create(array: string[]): GridConnections;
22
- /**
23
- * Check if two GridConnections objects are equal.
24
- * @param other The other GridConnections object to compare to.
25
- * @returns Whether the two objects are equal.
26
- */
27
- equals(other: GridConnections): boolean;
28
- /**
29
- * Deduplicate an array of edges.
30
- * @param edges The array of edges to deduplicate.
31
- * @returns The deduplicated array of edges.
32
- */
33
- static deduplicateEdges(edges: readonly Edge[]): readonly Edge[];
34
20
  insertColumn(index: number): GridConnections;
35
21
  insertRow(index: number): GridConnections;
36
22
  removeColumn(index: number): GridConnections;
@@ -1,14 +1,9 @@
1
1
  import { isSameEdge } from './dataHelper.js';
2
+ import GridZones from './gridZones.js';
2
3
  import TileConnections from './tileConnections.js';
3
- export default class GridConnections {
4
+ export default class GridConnections extends GridZones {
4
5
  constructor(edges) {
5
- Object.defineProperty(this, "edges", {
6
- enumerable: true,
7
- configurable: true,
8
- writable: true,
9
- value: void 0
10
- });
11
- this.edges = GridConnections.deduplicateEdges(edges ?? []);
6
+ super(edges);
12
7
  }
13
8
  addEdge(edge) {
14
9
  if (this.edges.some(e => isSameEdge(e, edge))) {
@@ -19,26 +14,18 @@ export default class GridConnections {
19
14
  removeEdge(edge) {
20
15
  return new GridConnections(this.edges.filter(e => !isSameEdge(e, edge)));
21
16
  }
22
- isConnected(edge) {
23
- if (edge.x1 === edge.x2 && edge.y1 === edge.y2)
24
- return true;
25
- return this.edges.some(e => isSameEdge(e, edge));
26
- }
27
- getConnectionsAt({ x, y }) {
28
- return this.edges.filter(e => (e.x1 === x && e.y1 === y) || (e.x2 === x && e.y2 === y));
29
- }
30
17
  getForTile({ x, y }) {
31
18
  const result = new TileConnections();
32
19
  // Get all connections within 2 steps of the tile
33
- const edges = this.getConnectionsAt({ x, y });
20
+ const edges = this.getEdgesAt({ x, y });
34
21
  const edges2 = [
35
22
  ...edges,
36
23
  ...edges.flatMap(edge => {
37
24
  if (edge.x1 === x && edge.y1 === y) {
38
- return this.getConnectionsAt({ x: edge.x2, y: edge.y2 });
25
+ return this.getEdgesAt({ x: edge.x2, y: edge.y2 });
39
26
  }
40
27
  else {
41
- return this.getConnectionsAt({ x: edge.x1, y: edge.y1 });
28
+ return this.getEdgesAt({ x: edge.x1, y: edge.y1 });
42
29
  }
43
30
  }),
44
31
  ];
@@ -86,7 +73,7 @@ export default class GridConnections {
86
73
  }
87
74
  visited.add(`${current.x},${current.y}`);
88
75
  result.push(current);
89
- const edges = this.getConnectionsAt(current);
76
+ const edges = this.getEdgesAt(current);
90
77
  for (const edge of edges) {
91
78
  if (edge.x1 === current.x && edge.y1 === current.y) {
92
79
  queue.push({ x: edge.x2, y: edge.y2 });
@@ -124,28 +111,6 @@ export default class GridConnections {
124
111
  }
125
112
  return new GridConnections(edges);
126
113
  }
127
- /**
128
- * Check if two GridConnections objects are equal.
129
- * @param other The other GridConnections object to compare to.
130
- * @returns Whether the two objects are equal.
131
- */
132
- equals(other) {
133
- if (this.edges.length !== other.edges.length)
134
- return false;
135
- for (const edge of this.edges) {
136
- if (!other.isConnected(edge))
137
- return false;
138
- }
139
- return true;
140
- }
141
- /**
142
- * Deduplicate an array of edges.
143
- * @param edges The array of edges to deduplicate.
144
- * @returns The deduplicated array of edges.
145
- */
146
- static deduplicateEdges(edges) {
147
- return edges.filter((edge, index) => edges.findIndex(e => isSameEdge(e, edge)) === index);
148
- }
149
114
  insertColumn(index) {
150
115
  return new GridConnections(this.edges.flatMap(edge => {
151
116
  if ((edge.x1 < index && edge.x2 < index) ||
@@ -0,0 +1,25 @@
1
+ import { Edge, Position } from './primitives.js';
2
+ export default class GridZones {
3
+ readonly edges: readonly Edge[];
4
+ constructor(edges?: readonly Edge[]);
5
+ addEdge(edge: Edge): GridZones;
6
+ removeEdge(edge: Edge): GridZones;
7
+ hasEdge(edge: Edge): boolean;
8
+ getEdgesAt({ x, y }: Position): readonly Edge[];
9
+ /**
10
+ * Check if two GridZones objects are equal.
11
+ * @param other The other GridZones object to compare to.
12
+ * @returns Whether the two objects are equal.
13
+ */
14
+ equals(other: GridZones): boolean;
15
+ /**
16
+ * Deduplicate an array of edges.
17
+ * @param edges The array of edges to deduplicate.
18
+ * @returns The deduplicated array of edges.
19
+ */
20
+ static deduplicateEdges(edges: readonly Edge[]): readonly Edge[];
21
+ insertColumn(index: number): GridZones;
22
+ insertRow(index: number): GridZones;
23
+ removeColumn(index: number): GridZones;
24
+ removeRow(index: number): GridZones;
25
+ }
@@ -0,0 +1,91 @@
1
+ import { isSameEdge } from './dataHelper.js';
2
+ export default class GridZones {
3
+ constructor(edges) {
4
+ Object.defineProperty(this, "edges", {
5
+ enumerable: true,
6
+ configurable: true,
7
+ writable: true,
8
+ value: void 0
9
+ });
10
+ this.edges = GridZones.deduplicateEdges(edges ?? []);
11
+ }
12
+ addEdge(edge) {
13
+ if (this.edges.some(e => isSameEdge(e, edge))) {
14
+ return this;
15
+ }
16
+ return new GridZones([...this.edges, edge]);
17
+ }
18
+ removeEdge(edge) {
19
+ return new GridZones(this.edges.filter(e => !isSameEdge(e, edge)));
20
+ }
21
+ hasEdge(edge) {
22
+ if (edge.x1 === edge.x2 && edge.y1 === edge.y2)
23
+ return true;
24
+ return this.edges.some(e => isSameEdge(e, edge));
25
+ }
26
+ getEdgesAt({ x, y }) {
27
+ return this.edges.filter(e => (e.x1 === x && e.y1 === y) || (e.x2 === x && e.y2 === y));
28
+ }
29
+ /**
30
+ * Check if two GridZones objects are equal.
31
+ * @param other The other GridZones object to compare to.
32
+ * @returns Whether the two objects are equal.
33
+ */
34
+ equals(other) {
35
+ if (this.edges.length !== other.edges.length)
36
+ return false;
37
+ for (const edge of this.edges) {
38
+ if (!other.hasEdge(edge))
39
+ return false;
40
+ }
41
+ return true;
42
+ }
43
+ /**
44
+ * Deduplicate an array of edges.
45
+ * @param edges The array of edges to deduplicate.
46
+ * @returns The deduplicated array of edges.
47
+ */
48
+ static deduplicateEdges(edges) {
49
+ return edges.filter((edge, index) => edges.findIndex(e => isSameEdge(e, edge)) === index);
50
+ }
51
+ insertColumn(index) {
52
+ return new GridZones(this.edges.map(edge => {
53
+ if (edge.x1 < index || edge.x2 < index) {
54
+ return edge;
55
+ }
56
+ else {
57
+ return { x1: edge.x1 + 1, y1: edge.y1, x2: edge.x2 + 1, y2: edge.y2 };
58
+ }
59
+ }));
60
+ }
61
+ insertRow(index) {
62
+ return new GridZones(this.edges.map(edge => {
63
+ if (edge.y1 < index || edge.y2 < index) {
64
+ return edge;
65
+ }
66
+ else {
67
+ return { x1: edge.x1, y1: edge.y1 + 1, x2: edge.x2, y2: edge.y2 + 1 };
68
+ }
69
+ }));
70
+ }
71
+ removeColumn(index) {
72
+ return new GridZones(this.edges.map(edge => {
73
+ if (edge.x1 > index || edge.x2 > index) {
74
+ return { x1: edge.x1 - 1, y1: edge.y1, x2: edge.x2 - 1, y2: edge.y2 };
75
+ }
76
+ else {
77
+ return edge;
78
+ }
79
+ }));
80
+ }
81
+ removeRow(index) {
82
+ return new GridZones(this.edges.map(edge => {
83
+ if (edge.y1 > index || edge.y2 > index) {
84
+ return { x1: edge.x1, y1: edge.y1 - 1, x2: edge.x2, y2: edge.y2 - 1 };
85
+ }
86
+ else {
87
+ return edge;
88
+ }
89
+ }));
90
+ }
91
+ }
@@ -18,9 +18,9 @@ export type PuzzleMetadata = {
18
18
  */
19
19
  link: string;
20
20
  /**
21
- * The difficulty of the puzzle, from 1 to 10. (required)
21
+ * The difficulty of the puzzle, from 0 to 10. (required)
22
22
  *
23
- * 6-10 represent star difficulties.
23
+ * 0 represents an unrated puzzle, 6-10 represent star difficulties.
24
24
  */
25
25
  difficulty: number;
26
26
  };
@@ -6,7 +6,7 @@ export const MetadataSchema = z
6
6
  author: z.string().min(1),
7
7
  description: z.string(),
8
8
  link: z.string(),
9
- difficulty: z.number().int().min(1).max(10),
9
+ difficulty: z.number().int().min(0).max(10),
10
10
  })
11
11
  .strict();
12
12
  export const PuzzleSchema = z
@@ -15,7 +15,7 @@ export const PuzzleSchema = z
15
15
  author: z.string().min(1),
16
16
  description: z.string(),
17
17
  link: z.string(),
18
- difficulty: z.number().int().min(1).max(10),
18
+ difficulty: z.number().int().min(0).max(10),
19
19
  grid: z.instanceof(GridData),
20
20
  solution: z.instanceof(GridData).nullable(),
21
21
  })
@@ -1,10 +1,9 @@
1
1
  import { AnyConfig } from '../config.js';
2
2
  import GridData from '../grid.js';
3
- import { Color, Edge, RuleState } from '../primitives.js';
3
+ import { Color, RuleState } from '../primitives.js';
4
4
  import Rule, { SearchVariant } from './rule.js';
5
5
  export default class CellCountPerZoneRule extends Rule {
6
6
  readonly color: Color;
7
- readonly edges: readonly Edge[];
8
7
  private static readonly CONFIGS;
9
8
  private static readonly EXAMPLE_GRID_LIGHT;
10
9
  private static readonly EXAMPLE_GRID_DARK;
@@ -14,20 +13,17 @@ export default class CellCountPerZoneRule extends Rule {
14
13
  * **Every zone has the same number of &lt;color&gt; cells.**
15
14
  *
16
15
  * @param color - The color of the cells to count.
17
- * @param edges - The edges of the zones to count.
18
16
  */
19
- constructor(color: Color, edges: readonly Edge[]);
17
+ constructor(color: Color);
20
18
  get id(): string;
21
19
  get explanation(): string;
22
20
  get configs(): readonly AnyConfig[] | null;
23
21
  createExampleGrid(): GridData;
24
22
  get searchVariants(): SearchVariant[];
25
23
  validateGrid(grid: GridData): RuleState;
26
- copyWith({ color, edges, }: {
24
+ copyWith({ color }: {
27
25
  color?: Color;
28
- edges?: readonly Edge[];
29
26
  }): this;
30
27
  withColor(color: Color): this;
31
- withEdges(edges: readonly Edge[] | ((edges: readonly Edge[]) => readonly Edge[])): this;
32
28
  }
33
29
  export declare const instance: CellCountPerZoneRule;
@@ -1,7 +1,7 @@
1
1
  import { ConfigType } from '../config.js';
2
2
  import { array } from '../dataHelper.js';
3
3
  import GridData, { NEIGHBOR_OFFSETS } from '../grid.js';
4
- import GridConnections from '../gridConnections.js';
4
+ import GridZones from '../gridZones.js';
5
5
  import { Color, State } from '../primitives.js';
6
6
  import Rule from './rule.js';
7
7
  class CellCountPerZoneRule extends Rule {
@@ -9,9 +9,8 @@ class CellCountPerZoneRule extends Rule {
9
9
  * **Every zone has the same number of &lt;color&gt; cells.**
10
10
  *
11
11
  * @param color - The color of the cells to count.
12
- * @param edges - The edges of the zones to count.
13
12
  */
14
- constructor(color, edges) {
13
+ constructor(color) {
15
14
  super();
16
15
  Object.defineProperty(this, "color", {
17
16
  enumerable: true,
@@ -19,14 +18,7 @@ class CellCountPerZoneRule extends Rule {
19
18
  writable: true,
20
19
  value: color
21
20
  });
22
- Object.defineProperty(this, "edges", {
23
- enumerable: true,
24
- configurable: true,
25
- writable: true,
26
- value: edges
27
- });
28
21
  this.color = color;
29
- this.edges = GridConnections.deduplicateEdges(edges);
30
22
  }
31
23
  get id() {
32
24
  return `zone_cell_count`;
@@ -80,7 +72,7 @@ class CellCountPerZoneRule extends Rule {
80
72
  }
81
73
  for (const offset of NEIGHBOR_OFFSETS) {
82
74
  const next = { x: x + offset.x, y: y + offset.y };
83
- if (!this.edges.some(e => (e.x1 === x &&
75
+ if (!grid.zones.edges.some(e => (e.x1 === x &&
84
76
  e.y1 === y &&
85
77
  e.x2 === next.x &&
86
78
  e.y2 === next.y) ||
@@ -112,17 +104,12 @@ class CellCountPerZoneRule extends Rule {
112
104
  }
113
105
  }
114
106
  }
115
- copyWith({ color, edges, }) {
116
- return new CellCountPerZoneRule(color ?? this.color, edges ?? this.edges);
107
+ copyWith({ color }) {
108
+ return new CellCountPerZoneRule(color ?? this.color);
117
109
  }
118
110
  withColor(color) {
119
111
  return this.copyWith({ color });
120
112
  }
121
- withEdges(edges) {
122
- return this.copyWith({
123
- edges: typeof edges === 'function' ? edges(this.edges) : edges,
124
- });
125
- }
126
113
  }
127
114
  Object.defineProperty(CellCountPerZoneRule, "CONFIGS", {
128
115
  enumerable: true,
@@ -137,26 +124,21 @@ Object.defineProperty(CellCountPerZoneRule, "CONFIGS", {
137
124
  description: 'Color',
138
125
  configurable: true,
139
126
  },
140
- {
141
- type: ConfigType.Edges,
142
- default: [],
143
- field: 'edges',
144
- description: 'Edges',
145
- configurable: false,
146
- },
147
127
  ])
148
128
  });
149
129
  Object.defineProperty(CellCountPerZoneRule, "EXAMPLE_GRID_LIGHT", {
150
130
  enumerable: true,
151
131
  configurable: true,
152
132
  writable: true,
153
- value: Object.freeze(GridData.create(['bwbbb', 'wbbwb', 'bbbwb', 'bwbwb']).addRule(new CellCountPerZoneRule(Color.Light, [
133
+ value: Object.freeze(GridData.create(['bwbbb', 'wbbwb', 'bbbwb', 'bwbwb'])
134
+ .withZones(new GridZones([
154
135
  { x1: 0, y1: 1, x2: 0, y2: 2 },
155
136
  { x1: 1, y1: 1, x2: 1, y2: 2 },
156
137
  { x1: 2, y1: 1, x2: 2, y2: 2 },
157
138
  { x1: 3, y1: 1, x2: 3, y2: 2 },
158
139
  { x1: 4, y1: 1, x2: 4, y2: 2 },
159
- ])))
140
+ ]))
141
+ .addRule(new CellCountPerZoneRule(Color.Light)))
160
142
  });
161
143
  Object.defineProperty(CellCountPerZoneRule, "EXAMPLE_GRID_DARK", {
162
144
  enumerable: true,
@@ -175,9 +157,9 @@ Object.defineProperty(CellCountPerZoneRule, "SEARCH_VARIANTS", {
175
157
  configurable: true,
176
158
  writable: true,
177
159
  value: [
178
- new CellCountPerZoneRule(Color.Light, []).searchVariant(),
179
- new CellCountPerZoneRule(Color.Dark, []).searchVariant(),
160
+ new CellCountPerZoneRule(Color.Light).searchVariant(),
161
+ new CellCountPerZoneRule(Color.Dark).searchVariant(),
180
162
  ]
181
163
  });
182
164
  export default CellCountPerZoneRule;
183
- export const instance = new CellCountPerZoneRule(Color.Light, []);
165
+ export const instance = new CellCountPerZoneRule(Color.Light);
@@ -4,6 +4,7 @@ import Rule from '../rules/rule.js';
4
4
  import TileData from '../tile.js';
5
5
  import Symbol from '../symbols/symbol.js';
6
6
  import { Puzzle } from '../puzzle.js';
7
+ import GridZones from '../gridZones.js';
7
8
  export default abstract class SerializerBase {
8
9
  abstract get version(): number;
9
10
  abstract stringifyTile(tile: TileData): string;
@@ -14,6 +15,8 @@ export default abstract class SerializerBase {
14
15
  abstract parseSymbol(str: string): Symbol;
15
16
  abstract stringifyConnections(connections: GridConnections): string;
16
17
  abstract parseConnections(input: string): GridConnections;
18
+ abstract stringifyZones(zones: GridZones): string;
19
+ abstract parseZones(input: string): GridZones;
17
20
  abstract stringifyTiles(tiles: readonly (readonly TileData[])[]): string;
18
21
  abstract parseTiles(input: string): TileData[][];
19
22
  abstract stringifyRules(rules: readonly Rule[]): string;
@@ -8,6 +8,7 @@ import { AnyConfig } from '../config.js';
8
8
  import SerializerBase from './serializerBase.js';
9
9
  import { Puzzle } from '../puzzle.js';
10
10
  import { ControlLine } from '../rules/musicControlLine.js';
11
+ import GridZones from '../gridZones.js';
11
12
  export default class SerializerV0 extends SerializerBase {
12
13
  readonly version = 0;
13
14
  stringifyTile(tile: TileData): string;
@@ -23,6 +24,8 @@ export default class SerializerV0 extends SerializerBase {
23
24
  parseSymbol(str: string): Symbol;
24
25
  stringifyConnections(connections: GridConnections): string;
25
26
  parseConnections(input: string): GridConnections;
27
+ stringifyZones(zones: GridZones): string;
28
+ parseZones(input: string): GridZones;
26
29
  stringifyTiles(tiles: readonly (readonly TileData[])[]): string;
27
30
  parseTiles(input: string): TileData[][];
28
31
  stringifyRules(rules: readonly Rule[]): string;
@@ -8,6 +8,7 @@ import { allRules } from '../rules/index.js';
8
8
  import { allSymbols } from '../symbols/index.js';
9
9
  import SerializerBase from './serializerBase.js';
10
10
  import { ControlLine, Row } from '../rules/musicControlLine.js';
11
+ import GridZones from '../gridZones.js';
11
12
  const OFFSETS = [
12
13
  { x: 0, y: -1 },
13
14
  { x: -1, y: 0 },
@@ -167,12 +168,6 @@ export default class SerializerV0 extends SerializerBase {
167
168
  escape(instruction[config.field]
168
169
  ?.map(pos => `${pos.x}_${pos.y}`)
169
170
  .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('/'));
176
171
  }
177
172
  }
178
173
  parseConfig(configs, entry) {
@@ -241,21 +236,6 @@ export default class SerializerV0 extends SerializerBase {
241
236
  return { x: Number(x), y: Number(y) };
242
237
  }),
243
238
  ];
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
- ];
259
239
  }
260
240
  }
261
241
  stringifyInstruction(instruction) {
@@ -335,6 +315,19 @@ export default class SerializerV0 extends SerializerBase {
335
315
  const tiles = array(width, Math.ceil(data.length / width), (x, y) => data[y * width + x]);
336
316
  return GridConnections.create(tiles.map(row => row.join('')));
337
317
  }
318
+ stringifyZones(zones) {
319
+ return `Z${zones.edges.map(edge => `${edge.x1}_${edge.y1}_${edge.x2 - edge.x1}_${edge.y2 - edge.y1}`).join(':')}`;
320
+ }
321
+ parseZones(input) {
322
+ if (!input.startsWith('Z')) {
323
+ throw new Error('Invalid grid zones\n' + input);
324
+ }
325
+ const data = input.slice(1).split(':');
326
+ return new GridZones(data.map(entry => {
327
+ const [x1, y1, w, h] = entry.split('_').map(Number);
328
+ return { x1, y1, x2: x1 + w, y2: y1 + h };
329
+ }));
330
+ }
338
331
  stringifyTiles(tiles) {
339
332
  return `T${tiles[0]?.length ?? 0}:${tiles.map(row => row.map(tile => this.stringifyTile(tile)).join('')).join('')}`;
340
333
  }
@@ -389,6 +382,7 @@ export default class SerializerV0 extends SerializerBase {
389
382
  const data = [
390
383
  this.stringifyTiles(grid.tiles),
391
384
  this.stringifyConnections(grid.connections),
385
+ this.stringifyZones(grid.zones),
392
386
  this.stringifySymbols(grid.symbols),
393
387
  this.stringifyRules(grid.rules),
394
388
  ];
@@ -400,6 +394,7 @@ export default class SerializerV0 extends SerializerBase {
400
394
  let height;
401
395
  let tiles;
402
396
  let connections;
397
+ let zones;
403
398
  let symbols;
404
399
  let rules;
405
400
  for (const d of data) {
@@ -412,6 +407,9 @@ export default class SerializerV0 extends SerializerBase {
412
407
  else if (d.startsWith('C')) {
413
408
  connections = this.parseConnections(d);
414
409
  }
410
+ else if (d.startsWith('Z')) {
411
+ zones = this.parseZones(d);
412
+ }
415
413
  else if (d.startsWith('S')) {
416
414
  symbols = this.parseSymbols(d);
417
415
  }
@@ -422,7 +420,7 @@ export default class SerializerV0 extends SerializerBase {
422
420
  throw new Error(`Invalid data: ${d}`);
423
421
  }
424
422
  }
425
- return new GridData(width ?? tiles?.[0].length ?? 0, height ?? tiles?.length ?? 0, tiles, connections, symbols, rules);
423
+ return new GridData(width ?? tiles?.[0].length ?? 0, height ?? tiles?.length ?? 0, tiles, connections, zones, symbols, rules);
426
424
  }
427
425
  stringifyPuzzle(puzzle) {
428
426
  let grid = puzzle.grid;
package/dist/index.d.ts CHANGED
@@ -10,6 +10,7 @@ import { handlesSymbolDisplay } from './data/events/onSymbolDisplay.js';
10
10
  import { handlesSymbolValidation } from './data/events/onSymbolValidation.js';
11
11
  import GridData, { NEIGHBOR_OFFSETS } from './data/grid.js';
12
12
  import GridConnections from './data/gridConnections.js';
13
+ import GridZones from './data/gridZones.js';
13
14
  import Instruction from './data/instruction.js';
14
15
  import { COMPARISONS, Color, Comparison, DIRECTIONS, Direction, MajorRule, Mode, ORIENTATIONS, Orientation, State, directionToggle, orientationToggle } from './data/primitives.js';
15
16
  import { MetadataSchema, PuzzleSchema } from './data/puzzle.js';
@@ -97,4 +98,4 @@ import ViewpointSymbol from './data/symbols/viewpointSymbol.js';
97
98
  import TileData from './data/tile.js';
98
99
  import TileConnections from './data/tileConnections.js';
99
100
  import validateGrid, { aggregateState, applyFinalOverrides } from './data/validate.js';
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, };
101
+ 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, GridZones, 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
@@ -13,6 +13,7 @@ import { handlesSymbolDisplay } from './data/events/onSymbolDisplay.js';
13
13
  import { handlesSymbolValidation } from './data/events/onSymbolValidation.js';
14
14
  import GridData, { NEIGHBOR_OFFSETS } from './data/grid.js';
15
15
  import GridConnections from './data/gridConnections.js';
16
+ import GridZones from './data/gridZones.js';
16
17
  import Instruction from './data/instruction.js';
17
18
  import { COMPARISONS, Color, Comparison, DIRECTIONS, Direction, MajorRule, Mode, ORIENTATIONS, Orientation, State, directionToggle, orientationToggle } from './data/primitives.js';
18
19
  import { MetadataSchema, PuzzleSchema } from './data/puzzle.js';
@@ -100,4 +101,4 @@ import ViewpointSymbol from './data/symbols/viewpointSymbol.js';
100
101
  import TileData from './data/tile.js';
101
102
  import TileConnections from './data/tileConnections.js';
102
103
  import validateGrid, { aggregateState, applyFinalOverrides } from './data/validate.js';
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, };
104
+ 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, GridZones, 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logic-pad/core",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",