@logic-pad/core 0.13.4 → 0.15.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 (77) hide show
  1. package/assets/logic-core.global.d.ts +60 -2
  2. package/dist/data/config.d.ts +7 -1
  3. package/dist/data/config.js +7 -0
  4. package/dist/data/configurable.d.ts +2 -0
  5. package/dist/data/instruction.d.ts +1 -0
  6. package/dist/data/instruction.js +3 -0
  7. package/dist/data/puzzle.js +3 -1
  8. package/dist/data/rules/banPatternRule.d.ts +1 -0
  9. package/dist/data/rules/banPatternRule.js +11 -1
  10. package/dist/data/rules/cellCountPerZoneRule.d.ts +2 -0
  11. package/dist/data/rules/cellCountPerZoneRule.js +9 -0
  12. package/dist/data/rules/cellCountRule.d.ts +1 -0
  13. package/dist/data/rules/cellCountRule.js +6 -0
  14. package/dist/data/rules/completePatternRule.d.ts +2 -0
  15. package/dist/data/rules/completePatternRule.js +9 -0
  16. package/dist/data/rules/connectAllRule.d.ts +1 -0
  17. package/dist/data/rules/connectAllRule.js +6 -0
  18. package/dist/data/rules/containsShapeRule.d.ts +1 -0
  19. package/dist/data/rules/containsShapeRule.js +11 -1
  20. package/dist/data/rules/customRule.d.ts +2 -0
  21. package/dist/data/rules/customRule.js +11 -0
  22. package/dist/data/rules/foresightRule.d.ts +2 -0
  23. package/dist/data/rules/foresightRule.js +13 -0
  24. package/dist/data/rules/lyingSymbolRule.d.ts +1 -0
  25. package/dist/data/rules/lyingSymbolRule.js +19 -0
  26. package/dist/data/rules/musicControlLine.d.ts +4 -0
  27. package/dist/data/rules/musicControlLine.js +29 -0
  28. package/dist/data/rules/musicGridRule.d.ts +2 -0
  29. package/dist/data/rules/musicGridRule.js +11 -0
  30. package/dist/data/rules/mysteryRule.d.ts +2 -0
  31. package/dist/data/rules/mysteryRule.js +11 -0
  32. package/dist/data/rules/offByXRule.d.ts +1 -0
  33. package/dist/data/rules/offByXRule.js +6 -0
  34. package/dist/data/rules/perfectionRule.d.ts +2 -0
  35. package/dist/data/rules/perfectionRule.js +9 -0
  36. package/dist/data/rules/regionAreaRule.d.ts +1 -0
  37. package/dist/data/rules/regionAreaRule.js +6 -0
  38. package/dist/data/rules/sameShapeRule.d.ts +1 -0
  39. package/dist/data/rules/sameShapeRule.js +6 -0
  40. package/dist/data/rules/symbolsPerRegionRule.d.ts +1 -0
  41. package/dist/data/rules/symbolsPerRegionRule.js +6 -0
  42. package/dist/data/rules/undercluedRule.d.ts +2 -0
  43. package/dist/data/rules/undercluedRule.js +9 -0
  44. package/dist/data/rules/uniqueShapeRule.d.ts +1 -0
  45. package/dist/data/rules/uniqueShapeRule.js +6 -0
  46. package/dist/data/rules/wrapAroundRule.d.ts +2 -0
  47. package/dist/data/rules/wrapAroundRule.js +9 -0
  48. package/dist/data/serializer/serializer_checksum.js +11 -1
  49. package/dist/data/serializer/serializer_v0.js +2 -0
  50. package/dist/data/shapes.js +11 -1
  51. package/dist/data/symbols/areaNumberSymbol.d.ts +1 -0
  52. package/dist/data/symbols/areaNumberSymbol.js +6 -0
  53. package/dist/data/symbols/customIconSymbol.d.ts +2 -0
  54. package/dist/data/symbols/customIconSymbol.js +13 -0
  55. package/dist/data/symbols/customTextSymbol.d.ts +2 -0
  56. package/dist/data/symbols/customTextSymbol.js +13 -0
  57. package/dist/data/symbols/dartSymbol.d.ts +1 -0
  58. package/dist/data/symbols/dartSymbol.js +6 -0
  59. package/dist/data/symbols/directionLinkerSymbol.d.ts +1 -5
  60. package/dist/data/symbols/directionLinkerSymbol.js +0 -3
  61. package/dist/data/symbols/focusSymbol.d.ts +1 -0
  62. package/dist/data/symbols/focusSymbol.js +6 -0
  63. package/dist/data/symbols/galaxySymbol.d.ts +1 -0
  64. package/dist/data/symbols/galaxySymbol.js +6 -0
  65. package/dist/data/symbols/hiddenSymbol.d.ts +2 -0
  66. package/dist/data/symbols/hiddenSymbol.js +10 -0
  67. package/dist/data/symbols/letterSymbol.d.ts +1 -0
  68. package/dist/data/symbols/letterSymbol.js +7 -0
  69. package/dist/data/symbols/lotusSymbol.d.ts +1 -0
  70. package/dist/data/symbols/lotusSymbol.js +6 -0
  71. package/dist/data/symbols/minesweeperSymbol.d.ts +1 -0
  72. package/dist/data/symbols/minesweeperSymbol.js +6 -0
  73. package/dist/data/symbols/myopiaSymbol.d.ts +1 -0
  74. package/dist/data/symbols/myopiaSymbol.js +5 -0
  75. package/dist/data/symbols/viewpointSymbol.d.ts +1 -0
  76. package/dist/data/symbols/viewpointSymbol.js +6 -0
  77. package/package.json +2 -2
@@ -3,6 +3,9 @@ import GridData from '../grid.js';
3
3
  import { State } from '../primitives.js';
4
4
  import Rule from './rule.js';
5
5
  class CustomRule extends Rule {
6
+ get configExplanation() {
7
+ return 'A customizable rule. Your provided solution may override auto-validation.';
8
+ }
6
9
  /**
7
10
  * A custom rule with a description and thumbnail grid.
8
11
  *
@@ -25,6 +28,12 @@ class CustomRule extends Rule {
25
28
  writable: true,
26
29
  value: grid
27
30
  });
31
+ Object.defineProperty(this, "title", {
32
+ enumerable: true,
33
+ configurable: true,
34
+ writable: true,
35
+ value: 'Custom Rule'
36
+ });
28
37
  this.description = description;
29
38
  this.grid = grid;
30
39
  }
@@ -69,6 +78,7 @@ Object.defineProperty(CustomRule, "configs", {
69
78
  default: 'A *custom* rule',
70
79
  field: 'description',
71
80
  description: 'Description',
81
+ explanation: 'A short descriptive text. Use *asterisks* to highlight keywords.',
72
82
  configurable: true,
73
83
  },
74
84
  {
@@ -76,6 +86,7 @@ Object.defineProperty(CustomRule, "configs", {
76
86
  default: CustomRule.EXAMPLE_GRID,
77
87
  field: 'grid',
78
88
  description: 'Thumbnail Grid',
89
+ explanation: 'An example grid showing the rule.',
79
90
  configurable: true,
80
91
  },
81
92
  ])
@@ -7,6 +7,8 @@ export default class ForesightRule extends Rule {
7
7
  readonly regenInterval: number;
8
8
  readonly startFull: boolean;
9
9
  readonly solvePath: Position[];
10
+ readonly title = "Foresight";
11
+ get configExplanation(): string;
10
12
  private static readonly EXAMPLE_GRID;
11
13
  private static readonly CONFIGS;
12
14
  private static readonly SEARCH_VARIANTS;
@@ -4,6 +4,9 @@ import { State, Mode } from '../primitives.js';
4
4
  import CustomIconSymbol from '../symbols/customIconSymbol.js';
5
5
  import Rule from './rule.js';
6
6
  class ForesightRule extends Rule {
7
+ get configExplanation() {
8
+ return 'Provide automatic hints to the player.';
9
+ }
7
10
  /**
8
11
  * **Foresight: Show hints**
9
12
  */
@@ -33,6 +36,12 @@ class ForesightRule extends Rule {
33
36
  writable: true,
34
37
  value: solvePath
35
38
  });
39
+ Object.defineProperty(this, "title", {
40
+ enumerable: true,
41
+ configurable: true,
42
+ writable: true,
43
+ value: 'Foresight'
44
+ });
36
45
  this.count = count;
37
46
  this.regenInterval = regenInterval;
38
47
  this.startFull = startFull;
@@ -93,6 +102,7 @@ Object.defineProperty(ForesightRule, "CONFIGS", {
93
102
  min: 1,
94
103
  field: 'count',
95
104
  description: 'Foresight count',
105
+ explanation: 'Maximum number of foresight charges that can be stored.',
96
106
  configurable: true,
97
107
  },
98
108
  {
@@ -101,6 +111,7 @@ Object.defineProperty(ForesightRule, "CONFIGS", {
101
111
  min: 1,
102
112
  field: 'regenInterval',
103
113
  description: 'Regen Interval (seconds)',
114
+ explanation: 'Time taken for one foresight charge to regenerate.',
104
115
  configurable: true,
105
116
  },
106
117
  {
@@ -108,6 +119,7 @@ Object.defineProperty(ForesightRule, "CONFIGS", {
108
119
  default: false,
109
120
  field: 'startFull',
110
121
  description: 'Start with full foresight',
122
+ explanation: 'Whether to start with all foresight charges available.',
111
123
  configurable: true,
112
124
  },
113
125
  {
@@ -115,6 +127,7 @@ Object.defineProperty(ForesightRule, "CONFIGS", {
115
127
  default: [],
116
128
  field: 'solvePath',
117
129
  description: 'Intended solve path',
130
+ explanation: 'A logical solve path of the puzzle. Foresight will hint at the location of the next tile if this is available.',
118
131
  configurable: true,
119
132
  },
120
133
  ])
@@ -5,6 +5,7 @@ import { GridState, RuleState } from '../primitives.js';
5
5
  import Rule, { SearchVariant } from './rule.js';
6
6
  export default class LyingSymbolRule extends Rule implements FinalValidationHandler {
7
7
  readonly count: number;
8
+ readonly title = "Lying Symbols";
8
9
  private static readonly EXAMPLE_GRID;
9
10
  private static readonly CONFIGS;
10
11
  private static readonly SEARCH_VARIANTS;
@@ -23,6 +23,12 @@ class IgnoredSymbol extends Symbol {
23
23
  writable: true,
24
24
  value: state
25
25
  });
26
+ Object.defineProperty(this, "title", {
27
+ enumerable: true,
28
+ configurable: true,
29
+ writable: true,
30
+ value: 'Ignored Symbol'
31
+ });
26
32
  this.symbol = symbol;
27
33
  this.state = state;
28
34
  }
@@ -75,6 +81,12 @@ class IgnoredRule extends Rule {
75
81
  writable: true,
76
82
  value: state
77
83
  });
84
+ Object.defineProperty(this, "title", {
85
+ enumerable: true,
86
+ configurable: true,
87
+ writable: true,
88
+ value: 'Ignored Rule'
89
+ });
78
90
  this.rule = rule;
79
91
  this.state = state;
80
92
  }
@@ -129,6 +141,12 @@ class LyingSymbolRule extends Rule {
129
141
  writable: true,
130
142
  value: count
131
143
  });
144
+ Object.defineProperty(this, "title", {
145
+ enumerable: true,
146
+ configurable: true,
147
+ writable: true,
148
+ value: 'Lying Symbols'
149
+ });
132
150
  this.count = count;
133
151
  }
134
152
  get id() {
@@ -223,6 +241,7 @@ Object.defineProperty(LyingSymbolRule, "CONFIGS", {
223
241
  step: 1,
224
242
  field: 'count',
225
243
  description: 'Number of liars',
244
+ explanation: 'Number of symbols that are not satisfied in the final solution.',
226
245
  configurable: true,
227
246
  },
228
247
  ])
@@ -11,6 +11,8 @@ export declare class Row extends Configurable {
11
11
  * Ranges from 0 to 1
12
12
  */
13
13
  readonly velocity: number | null;
14
+ readonly title = "Music Grid - Row";
15
+ readonly configExplanation = "Configure the playback settings from this tile onwards.";
14
16
  private static readonly CONFIGS;
15
17
  constructor(
16
18
  /**
@@ -35,6 +37,8 @@ export declare class ControlLine extends Configurable {
35
37
  readonly pedal: boolean | null;
36
38
  readonly checkpoint: boolean;
37
39
  readonly rows: readonly Row[];
40
+ readonly title = "Music Grid - Control Line";
41
+ readonly configExplanation = "Configure the playback settings from this point onwards.";
38
42
  private static readonly CONFIGS;
39
43
  /**
40
44
  * Configure playback settings, taking effect at the given column (inclusive)
@@ -25,6 +25,18 @@ export class Row extends Configurable {
25
25
  writable: true,
26
26
  value: velocity
27
27
  });
28
+ Object.defineProperty(this, "title", {
29
+ enumerable: true,
30
+ configurable: true,
31
+ writable: true,
32
+ value: 'Music Grid - Row'
33
+ });
34
+ Object.defineProperty(this, "configExplanation", {
35
+ enumerable: true,
36
+ configurable: true,
37
+ writable: true,
38
+ value: 'Configure the playback settings from this tile onwards.'
39
+ });
28
40
  this.note = note;
29
41
  this.velocity = velocity;
30
42
  }
@@ -45,6 +57,7 @@ Object.defineProperty(Row, "CONFIGS", {
45
57
  default: 'C4',
46
58
  field: 'note',
47
59
  description: 'Note',
60
+ explanation: 'The musical note or sample to play.',
48
61
  configurable: true,
49
62
  },
50
63
  {
@@ -55,6 +68,7 @@ Object.defineProperty(Row, "CONFIGS", {
55
68
  step: 0.2,
56
69
  field: 'velocity',
57
70
  description: 'Velocity',
71
+ explanation: 'For piano notes, how hard the note is played.',
58
72
  configurable: true,
59
73
  },
60
74
  ])
@@ -100,6 +114,18 @@ export class ControlLine extends Configurable {
100
114
  writable: true,
101
115
  value: rows
102
116
  });
117
+ Object.defineProperty(this, "title", {
118
+ enumerable: true,
119
+ configurable: true,
120
+ writable: true,
121
+ value: 'Music Grid - Control Line'
122
+ });
123
+ Object.defineProperty(this, "configExplanation", {
124
+ enumerable: true,
125
+ configurable: true,
126
+ writable: true,
127
+ value: 'Configure the playback settings from this point onwards.'
128
+ });
103
129
  this.column = Math.floor(column);
104
130
  this.bpm = bpm;
105
131
  this.pedal = pedal;
@@ -157,6 +183,7 @@ Object.defineProperty(ControlLine, "CONFIGS", {
157
183
  max: 1000,
158
184
  field: 'bpm',
159
185
  description: 'BPM',
186
+ explanation: 'Beats per minute for the playback.',
160
187
  configurable: true,
161
188
  },
162
189
  {
@@ -164,6 +191,7 @@ Object.defineProperty(ControlLine, "CONFIGS", {
164
191
  default: false,
165
192
  field: 'pedal',
166
193
  description: 'Pedal',
194
+ explanation: 'For piano notes, whether the pedal is pressed to sustain the sound.',
167
195
  configurable: true,
168
196
  },
169
197
  {
@@ -171,6 +199,7 @@ Object.defineProperty(ControlLine, "CONFIGS", {
171
199
  default: false,
172
200
  field: 'checkpoint',
173
201
  description: 'Checkpoint',
202
+ explanation: 'Whether players can start playback from this position.',
174
203
  configurable: true,
175
204
  },
176
205
  ])
@@ -10,6 +10,8 @@ export default class MusicGridRule extends Rule implements GridChangeHandler, Se
10
10
  readonly controlLines: readonly ControlLine[];
11
11
  readonly track: GridData | null;
12
12
  readonly normalizeVelocity: boolean;
13
+ readonly title = "Music Grid";
14
+ get configExplanation(): string;
13
15
  private static readonly EXAMPLE_GRID;
14
16
  private static readonly CONFIGS;
15
17
  private static readonly SEARCH_VARIANTS;
@@ -16,6 +16,9 @@ const DEFAULT_SCALLE = [
16
16
  new Row('C4', null),
17
17
  ];
18
18
  class MusicGridRule extends Rule {
19
+ get configExplanation() {
20
+ return 'Solve the grid by listening to the solution being played back.';
21
+ }
19
22
  /**
20
23
  * **Music Grid: Listen to the solution**
21
24
  * @param controlLines Denote changes in the playback settings. At least one control line at column 0 should be present to enable playback.
@@ -42,6 +45,12 @@ class MusicGridRule extends Rule {
42
45
  writable: true,
43
46
  value: normalizeVelocity
44
47
  });
48
+ Object.defineProperty(this, "title", {
49
+ enumerable: true,
50
+ configurable: true,
51
+ writable: true,
52
+ value: 'Music Grid'
53
+ });
45
54
  this.controlLines = MusicGridRule.deduplicateControlLines(controlLines);
46
55
  this.track = track;
47
56
  this.normalizeVelocity = normalizeVelocity;
@@ -208,6 +217,7 @@ Object.defineProperty(MusicGridRule, "CONFIGS", {
208
217
  ]).addRule(new MusicGridRule([new ControlLine(0, 120, false, false, DEFAULT_SCALLE)], null)),
209
218
  field: 'track',
210
219
  description: 'Track',
220
+ explanation: 'If set, this grid will be played instead of the solution.',
211
221
  configurable: true,
212
222
  },
213
223
  {
@@ -215,6 +225,7 @@ Object.defineProperty(MusicGridRule, "CONFIGS", {
215
225
  default: true,
216
226
  field: 'normalizeVelocity',
217
227
  description: 'Normalize Velocity',
228
+ explanation: 'Whether to adjust note velocities by their pitch such that every note has the same perceived loudness.',
218
229
  configurable: true,
219
230
  },
220
231
  ])
@@ -8,6 +8,8 @@ import Rule, { SearchVariant } from './rule.js';
8
8
  export default class MysteryRule extends Rule implements FinalValidationHandler, GridChangeHandler, GridResizeHandler {
9
9
  readonly solution: GridData;
10
10
  readonly visible: boolean;
11
+ readonly title = "Alternate Solution";
12
+ get configExplanation(): string;
11
13
  private static readonly EXAMPLE_GRID;
12
14
  private static readonly CONFIGS;
13
15
  private static readonly SEARCH_VARIANTS;
@@ -5,6 +5,9 @@ import { Color, State } from '../primitives.js';
5
5
  import CustomTextSymbol from '../symbols/customTextSymbol.js';
6
6
  import Rule from './rule.js';
7
7
  class MysteryRule extends Rule {
8
+ get configExplanation() {
9
+ return 'You may use multiple instances of this rule to provide multiple alternate solutions.';
10
+ }
8
11
  /**
9
12
  * **Mystery: alternate solution**
10
13
  */
@@ -22,6 +25,12 @@ class MysteryRule extends Rule {
22
25
  writable: true,
23
26
  value: visible
24
27
  });
28
+ Object.defineProperty(this, "title", {
29
+ enumerable: true,
30
+ configurable: true,
31
+ writable: true,
32
+ value: 'Alternate Solution'
33
+ });
25
34
  this.solution = MysteryRule.cleanSolution(solution);
26
35
  this.visible = visible;
27
36
  }
@@ -141,6 +150,7 @@ Object.defineProperty(MysteryRule, "CONFIGS", {
141
150
  resizable: false,
142
151
  field: 'solution',
143
152
  description: 'Solution',
153
+ explanation: 'The alternate solution to the puzzle. Does not need to satisfy puzzle rules / symbols.',
144
154
  configurable: true,
145
155
  },
146
156
  {
@@ -148,6 +158,7 @@ Object.defineProperty(MysteryRule, "CONFIGS", {
148
158
  default: true,
149
159
  field: 'visible',
150
160
  description: 'Visible',
161
+ explanation: 'Display this rule to the player.',
151
162
  configurable: true,
152
163
  },
153
164
  ])
@@ -6,6 +6,7 @@ import Symbol from '../symbols/symbol.js';
6
6
  import Rule, { SearchVariant } from './rule.js';
7
7
  export default class OffByXRule extends Rule implements SymbolValidationHandler {
8
8
  readonly number: number;
9
+ readonly title = "Off By X";
9
10
  private static readonly CONFIGS;
10
11
  private static readonly EXAMPLE_GRID;
11
12
  private static readonly SEARCH_VARIANTS;
@@ -18,6 +18,12 @@ class OffByXRule extends Rule {
18
18
  writable: true,
19
19
  value: number
20
20
  });
21
+ Object.defineProperty(this, "title", {
22
+ enumerable: true,
23
+ configurable: true,
24
+ writable: true,
25
+ value: 'Off By X'
26
+ });
21
27
  this.number = number;
22
28
  }
23
29
  get id() {
@@ -6,6 +6,8 @@ import { SetGridHandler } from '../events/onSetGrid.js';
6
6
  import { FinalValidationHandler } from '../events/onFinalValidation.js';
7
7
  export default class PerfectionRule extends Rule implements SetGridHandler, FinalValidationHandler {
8
8
  readonly editor: boolean;
9
+ readonly title = "Perfection";
10
+ get configExplanation(): string;
9
11
  private static readonly EXAMPLE_GRID;
10
12
  private static readonly SEARCH_VARIANTS;
11
13
  /**
@@ -4,6 +4,9 @@ import Rule from './rule.js';
4
4
  import CustomIconSymbol from '../symbols/customIconSymbol.js';
5
5
  import validateGrid from '../validate.js';
6
6
  class PerfectionRule extends Rule {
7
+ get configExplanation() {
8
+ return 'You should allow players to enable perfection mode themselves instead of enforcing this rule.';
9
+ }
7
10
  /**
8
11
  * **Quest for Perfection: cell colors are final**
9
12
  *
@@ -17,6 +20,12 @@ class PerfectionRule extends Rule {
17
20
  writable: true,
18
21
  value: editor
19
22
  });
23
+ Object.defineProperty(this, "title", {
24
+ enumerable: true,
25
+ configurable: true,
26
+ writable: true,
27
+ value: 'Perfection'
28
+ });
20
29
  this.editor = editor;
21
30
  }
22
31
  get id() {
@@ -5,6 +5,7 @@ import Rule, { SearchVariant } from './rule.js';
5
5
  export default class RegionAreaRule extends Rule {
6
6
  readonly color: Color;
7
7
  readonly size: number;
8
+ readonly title = "Region Area Size";
8
9
  private static readonly CONFIGS;
9
10
  private static readonly EXAMPLE_GRID_DARK;
10
11
  private static readonly EXAMPLE_GRID_LIGHT;
@@ -25,6 +25,12 @@ class RegionAreaRule extends Rule {
25
25
  writable: true,
26
26
  value: size
27
27
  });
28
+ Object.defineProperty(this, "title", {
29
+ enumerable: true,
30
+ configurable: true,
31
+ writable: true,
32
+ value: 'Region Area Size'
33
+ });
28
34
  this.color = color;
29
35
  this.size = size;
30
36
  }
@@ -4,6 +4,7 @@ import { Color, RuleState } from '../primitives.js';
4
4
  import RegionShapeRule from './regionShapeRule.js';
5
5
  import { SearchVariant } from './rule.js';
6
6
  export default class SameShapeRule extends RegionShapeRule {
7
+ readonly title = "Same Shape Areas";
7
8
  private static readonly CONFIGS;
8
9
  private static readonly EXAMPLE_GRID_LIGHT;
9
10
  private static readonly EXAMPLE_GRID_DARK;
@@ -11,6 +11,12 @@ class SameShapeRule extends RegionShapeRule {
11
11
  */
12
12
  constructor(color) {
13
13
  super(color);
14
+ Object.defineProperty(this, "title", {
15
+ enumerable: true,
16
+ configurable: true,
17
+ writable: true,
18
+ value: 'Same Shape Areas'
19
+ });
14
20
  }
15
21
  get id() {
16
22
  return `same_shape`;
@@ -6,6 +6,7 @@ export default class SymbolsPerRegionRule extends Rule {
6
6
  readonly color: Color;
7
7
  readonly count: number;
8
8
  readonly comparison: Comparison;
9
+ readonly title = "Symbols Per Area";
9
10
  private static readonly SYMBOL_POSITIONS;
10
11
  private static readonly CONFIGS;
11
12
  private static readonly EXAMPLE_GRIDS;
@@ -33,6 +33,12 @@ class SymbolsPerRegionRule extends Rule {
33
33
  writable: true,
34
34
  value: comparison
35
35
  });
36
+ Object.defineProperty(this, "title", {
37
+ enumerable: true,
38
+ configurable: true,
39
+ writable: true,
40
+ value: 'Symbols Per Area'
41
+ });
36
42
  this.color = color;
37
43
  this.count = count;
38
44
  this.comparison = comparison;
@@ -2,6 +2,8 @@ import GridData from '../grid.js';
2
2
  import { RuleState } from '../primitives.js';
3
3
  import Rule, { SearchVariant } from './rule.js';
4
4
  export default class UndercluedRule extends Rule {
5
+ readonly title = "Underclued";
6
+ get configExplanation(): string;
5
7
  private static readonly EXAMPLE_GRID;
6
8
  private static readonly SEARCH_VARIANTS;
7
9
  /**
@@ -4,6 +4,9 @@ import AreaNumberSymbol from '../symbols/areaNumberSymbol.js';
4
4
  import CustomTextSymbol from '../symbols/customTextSymbol.js';
5
5
  import Rule from './rule.js';
6
6
  class UndercluedRule extends Rule {
7
+ get configExplanation() {
8
+ return 'A solution must be provided. The solvers may be used to generate one automatically.';
9
+ }
7
10
  /**
8
11
  * **Underclued Grid: Mark only what is definitely true**
9
12
  *
@@ -11,6 +14,12 @@ class UndercluedRule extends Rule {
11
14
  */
12
15
  constructor() {
13
16
  super();
17
+ Object.defineProperty(this, "title", {
18
+ enumerable: true,
19
+ configurable: true,
20
+ writable: true,
21
+ value: 'Underclued'
22
+ });
14
23
  }
15
24
  get id() {
16
25
  return MajorRule.Underclued;
@@ -4,6 +4,7 @@ import { Color, RuleState } from '../primitives.js';
4
4
  import RegionShapeRule from './regionShapeRule.js';
5
5
  import { SearchVariant } from './rule.js';
6
6
  export default class UniqueShapeRule extends RegionShapeRule {
7
+ readonly title = "Unique Shape Areas";
7
8
  private static readonly CONFIGS;
8
9
  private static readonly EXAMPLE_GRID_LIGHT;
9
10
  private static readonly EXAMPLE_GRID_DARK;
@@ -10,6 +10,12 @@ class UniqueShapeRule extends RegionShapeRule {
10
10
  */
11
11
  constructor(color) {
12
12
  super(color);
13
+ Object.defineProperty(this, "title", {
14
+ enumerable: true,
15
+ configurable: true,
16
+ writable: true,
17
+ value: 'Unique Shape Areas'
18
+ });
13
19
  }
14
20
  get id() {
15
21
  return `unique_shape`;
@@ -6,6 +6,8 @@ import Rule, { SearchVariant } from './rule.js';
6
6
  export default class WrapAroundRule extends Rule implements GetTileHandler {
7
7
  readonly horizontal: Wrapping;
8
8
  readonly vertical: Wrapping;
9
+ readonly title = "Wrap Around";
10
+ get configExplanation(): string;
9
11
  private static readonly EXAMPLE_GRID_NONE;
10
12
  private static readonly EXAMPLE_GRID_HORIZONTAL;
11
13
  private static readonly EXAMPLE_GRID_VERTICAL;
@@ -6,6 +6,9 @@ import LetterSymbol from '../symbols/letterSymbol.js';
6
6
  import MyopiaSymbol from '../symbols/myopiaSymbol.js';
7
7
  import Rule from './rule.js';
8
8
  class WrapAroundRule extends Rule {
9
+ get configExplanation() {
10
+ return 'Allow edges to connect with each other and symbols / rules to take effect across edges.';
11
+ }
9
12
  /**
10
13
  * **The left and right edges are connected (in reverse)**
11
14
  *
@@ -26,6 +29,12 @@ class WrapAroundRule extends Rule {
26
29
  writable: true,
27
30
  value: vertical
28
31
  });
32
+ Object.defineProperty(this, "title", {
33
+ enumerable: true,
34
+ configurable: true,
35
+ writable: true,
36
+ value: 'Wrap Around'
37
+ });
29
38
  this.horizontal = horizontal;
30
39
  this.vertical = vertical;
31
40
  }
@@ -2,6 +2,7 @@ import { ConfigType, } from '../config.js';
2
2
  import SerializerV0, { orientationChars } from './serializer_v0.js';
3
3
  import { DIRECTIONS, ORIENTATIONS, } from '../primitives.js';
4
4
  import { escape } from '../dataHelper.js';
5
+ import { normalizeShape, tilesToShape } from '../shapes.js';
5
6
  export default class SerializerChecksum extends SerializerV0 {
6
7
  constructor() {
7
8
  super(...arguments);
@@ -9,7 +10,7 @@ export default class SerializerChecksum extends SerializerV0 {
9
10
  enumerable: true,
10
11
  configurable: true,
11
12
  writable: true,
12
- value: 2
13
+ value: 3
13
14
  });
14
15
  }
15
16
  parseTile(_str) {
@@ -91,6 +92,13 @@ export default class SerializerChecksum extends SerializerV0 {
91
92
  return (config.field +
92
93
  '=' +
93
94
  escape(this.stringifyGrid(instruction[config.field])));
95
+ case ConfigType.Shape:
96
+ return (config.field +
97
+ '=' +
98
+ escape(normalizeShape(tilesToShape(instruction[config.field].tiles))
99
+ .elements.map(elm => `${elm.x}-${elm.y}-${elm.color}`)
100
+ .sort()
101
+ .join('/')));
94
102
  case ConfigType.NullableGrid:
95
103
  return (config.field +
96
104
  '=' +
@@ -137,6 +145,7 @@ export default class SerializerChecksum extends SerializerV0 {
137
145
  }
138
146
  stringifyRules(rules) {
139
147
  return `R${rules
148
+ .filter(rule => rule.necessaryForCompletion)
140
149
  .map(rule => this.stringifyRule(rule))
141
150
  .sort()
142
151
  .join(':')}`;
@@ -147,6 +156,7 @@ export default class SerializerChecksum extends SerializerV0 {
147
156
  stringifySymbols(symbols) {
148
157
  return `S${Array.from(symbols.values())
149
158
  .flat()
159
+ .filter(symbol => symbol.necessaryForCompletion)
150
160
  .map(symbol => this.stringifySymbol(symbol))
151
161
  .sort()
152
162
  .join(':')}`;
@@ -147,6 +147,7 @@ export default class SerializerV0 extends SerializerBase {
147
147
  ? ''
148
148
  : escape(String(instruction[config.field]))));
149
149
  case ConfigType.Tile:
150
+ case ConfigType.Shape:
150
151
  case ConfigType.Grid:
151
152
  return (config.field +
152
153
  '=' +
@@ -215,6 +216,7 @@ export default class SerializerV0 extends SerializerBase {
215
216
  case ConfigType.Icon:
216
217
  return [config.field, unescape(value)];
217
218
  case ConfigType.Tile:
219
+ case ConfigType.Shape:
218
220
  case ConfigType.Grid:
219
221
  return [config.field, this.parseGrid(unescape(value))];
220
222
  case ConfigType.NullableGrid:
@@ -1,3 +1,5 @@
1
+ import GridConnections from './gridConnections.js';
2
+ import GridZones from './gridZones.js';
1
3
  import { Color } from './primitives.js';
2
4
  const colorIndex = {
3
5
  [Color.Dark]: 2,
@@ -44,6 +46,12 @@ function recenterShape(shape) {
44
46
  }
45
47
  shape.width = maxX - minX + 1;
46
48
  shape.height = maxY - minY + 1;
49
+ if (!Number.isFinite(shape.width)) {
50
+ shape.width = 0;
51
+ }
52
+ if (!Number.isFinite(shape.height)) {
53
+ shape.height = 0;
54
+ }
47
55
  return shape;
48
56
  }
49
57
  export function tilesToShape(tiles) {
@@ -123,5 +131,7 @@ export function sanitizePatternGrid(pattern, tileMapper = t => t) {
123
131
  : t.copyWith({ exists: true, color: Color.Gray, fixed: false })))))
124
132
  // strip all symbols and rules
125
133
  .withRules([])
126
- .withSymbols(new Map()));
134
+ .withSymbols(new Map())
135
+ .withConnections(new GridConnections())
136
+ .withZones(new GridZones()));
127
137
  }
@@ -2,6 +2,7 @@ import { AnyConfig } from '../config.js';
2
2
  import GridData from '../grid.js';
3
3
  import NumberSymbol from './numberSymbol.js';
4
4
  export default class AreaNumberSymbol extends NumberSymbol {
5
+ readonly title = "Area Number";
5
6
  private static readonly CONFIGS;
6
7
  private static readonly EXAMPLE_GRID;
7
8
  /**