about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorStar Rauchenberger <fefferburbia@gmail.com>2023-11-03 00:18:41 -0400
committerStar Rauchenberger <fefferburbia@gmail.com>2023-11-03 00:18:41 -0400
commit00641f16c889093b32b8e97a6050817f6fe43780 (patch)
tree33d0279af22ac028472d5eda0b535b58757dbc05
parent13dfac7905faac21ea98b08a0948104df8411d42 (diff)
downloadwittle-00641f16c889093b32b8e97a6050817f6fe43780.tar.gz
wittle-00641f16c889093b32b8e97a6050817f6fe43780.tar.bz2
wittle-00641f16c889093b32b8e97a6050817f6fe43780.zip
added weird symmetries (and some more puzzles)
-rw-r--r--app/assets/javascripts/wittle/display2.js19
-rw-r--r--app/assets/javascripts/wittle/puzzle.js74
-rw-r--r--app/assets/javascripts/wittle/serializer.js22
-rw-r--r--app/assets/javascripts/wittle/solve.js12
-rw-r--r--app/assets/javascripts/wittle/trace2.js134
-rw-r--r--app/assets/javascripts/wittle/validate.js4
-rw-r--r--ext/wittle_generator/Panel.cpp8
-rw-r--r--ext/wittle_generator/Panel.h32
-rw-r--r--ext/wittle_generator/wittle_generator.cpp116
9 files changed, 313 insertions, 108 deletions
diff --git a/app/assets/javascripts/wittle/display2.js b/app/assets/javascripts/wittle/display2.js index 52069d6..ddf3968 100644 --- a/app/assets/javascripts/wittle/display2.js +++ b/app/assets/javascripts/wittle/display2.js
@@ -1,3 +1,20 @@
1var SYM_TYPE_NONE = 0
2var SYM_TYPE_HORIZONTAL = 1
3var SYM_TYPE_VERTICAL = 2
4var SYM_TYPE_ROTATIONAL = 3
5var SYM_TYPE_ROTATE_LEFT = 4
6var SYM_TYPE_ROTATE_RIGHT = 5
7var SYM_TYPE_FLIP_XY = 6
8var SYM_TYPE_FLIP_NEG_XY = 7
9var SYM_TYPE_PARALLEL_H = 8
10var SYM_TYPE_PARALLEL_V = 9
11var SYM_TYPE_PARALLEL_H_FLIP = 10
12var SYM_TYPE_PARALLEL_V_FLIP = 11
13var SYM_TYPE_PILLAR_PARALLEL = 12
14var SYM_TYPE_PILLAR_HORIZONTAL = 13
15var SYM_TYPE_PILLAR_VERTICAL = 14
16var SYM_TYPE_PILLAR_ROTATIONAL = 15
17
1namespace(function() { 18namespace(function() {
2 19
3window.draw = function(puzzle, target='puzzle') { 20window.draw = function(puzzle, target='puzzle') {
@@ -260,7 +277,7 @@ function drawStartAndEnd(puzzle, svg) {
260 277
261 if (cell.start === true) { 278 if (cell.start === true) {
262 var symStart = null 279 var symStart = null
263 if (puzzle.symmetry != null) { 280 if (puzzle.symType != SYM_TYPE_NONE) {
264 var sym = puzzle.getSymmetricalPos(x, y) 281 var sym = puzzle.getSymmetricalPos(x, y)
265 window.drawSymbolWithSvg(svg, { 282 window.drawSymbolWithSvg(svg, {
266 'type': 'start', 283 'type': 'start',
diff --git a/app/assets/javascripts/wittle/puzzle.js b/app/assets/javascripts/wittle/puzzle.js index 4d6b0fb..cb0b20a 100644 --- a/app/assets/javascripts/wittle/puzzle.js +++ b/app/assets/javascripts/wittle/puzzle.js
@@ -123,6 +123,7 @@ window.Puzzle = class {
123 } 123 }
124 puzzle.pillar = parsed.pillar 124 puzzle.pillar = parsed.pillar
125 puzzle.symmetry = parsed.symmetry 125 puzzle.symmetry = parsed.symmetry
126 puzzle.symType = parsed.symType
126 puzzle.largezero = puzzle.width * puzzle.height 127 puzzle.largezero = puzzle.width * puzzle.height
127 return puzzle 128 return puzzle
128 } 129 }
@@ -185,36 +186,63 @@ window.Puzzle = class {
185 } 186 }
186 187
187 getSymmetricalDir(dir) { 188 getSymmetricalDir(dir) {
188 if (this.symmetry != null) { 189 if (this.symType == SYM_TYPE_VERTICAL || this.symType == SYM_TYPE_ROTATIONAL || this.symType == SYM_TYPE_PARALLEL_H_FLIP) {
189 if (this.symmetry.x === true) { 190 if (dir === 'left') return 'right'
190 if (dir === 'left') return 'right' 191 if (dir === 'right') return 'left'
191 if (dir === 'right') return 'left' 192 }
192 } 193 if (this.symType == SYM_TYPE_HORIZONTAL || this.symType == SYM_TYPE_ROTATIONAL || this.symType == SYM_TYPE_PARALLEL_V_FLIP) {
193 if (this.symmetry.y === true) { 194 if (dir === 'top') return 'bottom'
194 if (dir === 'top') return 'bottom' 195 if (dir === 'bottom') return 'top'
195 if (dir === 'bottom') return 'top' 196 }
196 } 197 if (this.symType == SYM_TYPE_ROTATE_LEFT || this.symType == SYM_TYPE_FLIP_NEG_XY) {
198 if (dir === 'left') return 'bottom'
199 if (dir === 'right') return 'top'
200 }
201 if (this.symType == SYM_TYPE_ROTATE_RIGHT || this.symType == SYM_TYPE_FLIP_NEG_XY) {
202 if (dir === 'top') return 'right'
203 if (dir === 'bottom') return 'left'
204 }
205 if (this.symType == SYM_TYPE_ROTATE_LEFT || this.symType == SYM_TYPE_FLIP_XY) {
206 if (dir === 'top') return 'left'
207 if (dir === 'bottom') return 'right'
208 }
209 if (this.symType == SYM_TYPE_ROTATE_RIGHT || this.symType == SYM_TYPE_FLIP_XY) {
210 if (dir === 'right') return 'bottom'
211 if (dir === 'left') return 'top'
197 } 212 }
198 return dir 213 return dir
199 } 214 }
200 215
201 // The resulting position is guaranteed to be gridsafe. 216 // The resulting position is guaranteed to be gridsafe.
202 getSymmetricalPos(x, y) { 217 getSymmetricalPos(x, y) {
203 if (this.symmetry != null) { 218 var origx = x
204 if (this.pillar === true) { 219 var origy = y
205 x += this.width/2 220
206 if (this.symmetry.x === true) { 221 if (this.symType == SYM_TYPE_VERTICAL || this.symType == SYM_TYPE_ROTATIONAL || this.symType == SYM_TYPE_PARALLEL_H_FLIP) {
207 x = this.width - x 222 x = (this.width - 1) - origx
208 } 223 }
209 } else { 224 if (this.symType == SYM_TYPE_HORIZONTAL || this.symType == SYM_TYPE_ROTATIONAL || this.symType == SYM_TYPE_PARALLEL_V_FLIP) {
210 if (this.symmetry.x === true) { 225 y = (this.height - 1) - origy
211 x = (this.width - 1) - x 226 }
212 } 227 if (this.symType == SYM_TYPE_ROTATE_LEFT || this.symType == SYM_TYPE_FLIP_XY) {
213 } 228 x = origy
214 if (this.symmetry.y === true) { 229 }
215 y = (this.height - 1) - y 230 if (this.symType == SYM_TYPE_ROTATE_RIGHT || this.symType == SYM_TYPE_FLIP_XY) {
216 } 231 y = origx
217 } 232 }
233 if (this.symType == SYM_TYPE_ROTATE_LEFT || this.symType == SYM_TYPE_FLIP_NEG_XY) {
234 y = (this.width - 1) - origx
235 }
236 if (this.symType == SYM_TYPE_ROTATE_RIGHT || this.symType == SYM_TYPE_FLIP_NEG_XY) {
237 x = (this.height - 1) - origy
238 }
239 if (this.symType == SYM_TYPE_PARALLEL_H || this.symType == SYM_TYPE_PARALLEL_H_FLIP) {
240 y = (origy == this.height / 2) ? (this.height / 2) : ((origy + (this.height + 1) / 2) % (this.height + 1))
241 }
242 if (this.symType == SYM_TYPE_PARALLEL_V || this.symType == SYM_TYPE_PARALLEL_V_FLIP) {
243 x = (origx == this.width / 2) ? (this.width / 2) : ((origx + (this.width + 1) / 2) % (this.width + 1))
244 }
245
218 return {'x':this._mod(x), 'y':y} 246 return {'x':this._mod(x), 'y':y}
219 } 247 }
220 248
diff --git a/app/assets/javascripts/wittle/serializer.js b/app/assets/javascripts/wittle/serializer.js index 1598d9b..70c7f0f 100644 --- a/app/assets/javascripts/wittle/serializer.js +++ b/app/assets/javascripts/wittle/serializer.js
@@ -46,6 +46,8 @@ window.serializePuzzle = function(puzzle) {
46 if (puzzle.settings.INVISIBLE_SYMMETRY) settingsFlags |= SETTINGS_FLAG_IS 46 if (puzzle.settings.INVISIBLE_SYMMETRY) settingsFlags |= SETTINGS_FLAG_IS
47 s.writeByte(settingsFlags) 47 s.writeByte(settingsFlags)
48 48
49 s.writeByte(puzzle.symType)
50
49 return s.str() 51 return s.str()
50} 52}
51 53
@@ -64,10 +66,16 @@ window.deserializePuzzle = function(data) {
64 66
65 var genericFlags = s.readByte() 67 var genericFlags = s.readByte()
66 puzzle.autoSolved = genericFlags & GENERIC_FLAG_AUTOSOLVED 68 puzzle.autoSolved = genericFlags & GENERIC_FLAG_AUTOSOLVED
69 puzzle.symType = SYM_TYPE_NONE
67 if ((genericFlags & GENERIC_FLAG_SYMMETRICAL) != 0) { 70 if ((genericFlags & GENERIC_FLAG_SYMMETRICAL) != 0) {
68 puzzle.symmetry = { 71 if ((genericFlags & GENERIC_FLAG_SYMMETRY_X) != 0) {
69 'x': ((genericFlags & GENERIC_FLAG_SYMMETRY_X) != 0), 72 if ((genericFlags & GENERIC_FLAG_SYMMETRY_Y) != 0) {
70 'y': ((genericFlags & GENERIC_FLAG_SYMMETRY_Y) != 0), 73 puzzle.symType = SYM_TYPE_ROTATIONAL
74 } else {
75 puzzle.symType = SYM_TYPE_VERTICAL
76 }
77 } else if ((genericFlags & GENERIC_FLAG_SYMMETRY_Y) != 0) {
78 puzzle.symType = SYM_TYPE_HORIZONTAL
71 } 79 }
72 } 80 }
73 puzzle.pillar = (genericFlags & GENERIC_FLAG_PILLAR) != 0 81 puzzle.pillar = (genericFlags & GENERIC_FLAG_PILLAR) != 0
@@ -97,6 +105,10 @@ window.deserializePuzzle = function(data) {
97 INVISIBLE_SYMMETRY: (settingsFlags & SETTINGS_FLAG_IS) != 0, 105 INVISIBLE_SYMMETRY: (settingsFlags & SETTINGS_FLAG_IS) != 0,
98 } 106 }
99 107
108 if (s.hasLeft(1)) {
109 puzzle.symType = s.readByte()
110 }
111
100 s.destroy() 112 s.destroy()
101 return puzzle 113 return puzzle
102} 114}
@@ -138,6 +150,10 @@ class Serializer {
138 if (this.data.length < numBytes) throw Error('Cannot read ' + numBytes + ' bytes from a stream with only '+ this.data.length + ' bytes') 150 if (this.data.length < numBytes) throw Error('Cannot read ' + numBytes + ' bytes from a stream with only '+ this.data.length + ' bytes')
139 } 151 }
140 152
153 hasLeft(numBytes = 1) {
154 return ((this.data.length - this.index) >= numBytes)
155 }
156
141 readByte() { 157 readByte() {
142 this._checkRead() 158 this._checkRead()
143 return this.data.charCodeAt(this.index++) 159 return this.data.charCodeAt(this.index++)
diff --git a/app/assets/javascripts/wittle/solve.js b/app/assets/javascripts/wittle/solve.js index 13b9650..8695291 100644 --- a/app/assets/javascripts/wittle/solve.js +++ b/app/assets/javascripts/wittle/solve.js
@@ -28,7 +28,7 @@ function countNodes(x, y, depth) {
28 if (cell.gap > window.GAP_NONE) return 28 if (cell.gap > window.GAP_NONE) return
29 if (cell.line !== window.LINE_NONE) return 29 if (cell.line !== window.LINE_NONE) return
30 30
31 if (puzzle.symmetry == null) { 31 if (puzzle.symType == SYM_TYPE_NONE) {
32 puzzle.updateCell2(x, y, 'line', window.LINE_BLACK) 32 puzzle.updateCell2(x, y, 'line', window.LINE_BLACK)
33 } else { 33 } else {
34 var sym = puzzle.getSymmetricalPos(x, y) 34 var sym = puzzle.getSymmetricalPos(x, y)
@@ -84,7 +84,7 @@ window.solve = function(p, partialCallback, finalCallback) {
84 // Puzzles which are small enough should be solved synchronously, since the cost of asynchronizing 84 // Puzzles which are small enough should be solved synchronously, since the cost of asynchronizing
85 // is greater than the cost of the puzzle. 85 // is greater than the cost of the puzzle.
86 SOLVE_SYNC = false 86 SOLVE_SYNC = false
87 if (puzzle.symmetry != null) { // 5x5 is the max for symmetry puzzles 87 if (puzzle.symType != SYM_TYPE_NONE) { // 5x5 is the max for symmetry puzzles
88 if (puzzle.width * puzzle.height <= 121) SOLVE_SYNC = true 88 if (puzzle.width * puzzle.height <= 121) SOLVE_SYNC = true
89 } else if (puzzle.pillar === true) { // 4x5 is the max for non-symmetry, pillar puzzles 89 } else if (puzzle.pillar === true) { // 4x5 is the max for non-symmetry, pillar puzzles
90 if (puzzle.width * puzzle.height <= 108) SOLVE_SYNC = true 90 if (puzzle.width * puzzle.height <= 108) SOLVE_SYNC = true
@@ -207,7 +207,7 @@ function taskLoop(partialCallback, finalCallback) {
207function tailRecurse(x, y) { 207function tailRecurse(x, y) {
208 // Tail recursion: Back out of this cell 208 // Tail recursion: Back out of this cell
209 puzzle.updateCell2(x, y, 'line', window.LINE_NONE) 209 puzzle.updateCell2(x, y, 'line', window.LINE_NONE)
210 if (puzzle.symmetry != null) { 210 if (puzzle.symType != SYM_TYPE_NONE) {
211 var sym = puzzle.getSymmetricalPos(x, y) 211 var sym = puzzle.getSymmetricalPos(x, y)
212 puzzle.updateCell2(sym.x, sym.y, 'line', window.LINE_NONE) 212 puzzle.updateCell2(sym.x, sym.y, 'line', window.LINE_NONE)
213 } 213 }
@@ -227,7 +227,7 @@ function solveLoop(x, y, numEndpoints, earlyExitData) {
227 if (cell.gap > window.GAP_NONE) return 227 if (cell.gap > window.GAP_NONE) return
228 if (cell.line !== window.LINE_NONE) return 228 if (cell.line !== window.LINE_NONE) return
229 229
230 if (puzzle.symmetry == null) { 230 if (puzzle.symType == SYM_TYPE_NONE) {
231 puzzle.updateCell2(x, y, 'line', window.LINE_BLACK) 231 puzzle.updateCell2(x, y, 'line', window.LINE_BLACK)
232 } else { 232 } else {
233 var sym = puzzle.getSymmetricalPos(x, y) 233 var sym = puzzle.getSymmetricalPos(x, y)
@@ -379,7 +379,7 @@ window.drawPathNoUI = function(puzzle, path) {
379 x += dx 379 x += dx
380 y += dy 380 y += dy
381 // Set the cell color 381 // Set the cell color
382 if (puzzle.symmetry == null) { 382 if (puzzle.symType == SYM_TYPE_NONE) {
383 cell.line = window.LINE_BLACK 383 cell.line = window.LINE_BLACK
384 } else { 384 } else {
385 cell.line = window.LINE_BLUE 385 cell.line = window.LINE_BLUE
@@ -457,7 +457,7 @@ window.drawPath = function(puzzle, path, target='puzzle') {
457 // Unflag the cell, move into it, and reflag it 457 // Unflag the cell, move into it, and reflag it
458 cell.line = window.LINE_NONE 458 cell.line = window.LINE_NONE
459 window.onMove(41 * dx, 41 * dy) 459 window.onMove(41 * dx, 41 * dy)
460 if (puzzle.symmetry == null) { 460 if (puzzle.symType == SYM_TYPE_NONE) {
461 cell.line = window.LINE_BLACK 461 cell.line = window.LINE_BLACK
462 } else { 462 } else {
463 cell.line = window.LINE_BLUE 463 cell.line = window.LINE_BLUE
diff --git a/app/assets/javascripts/wittle/trace2.js b/app/assets/javascripts/wittle/trace2.js index 7a77564..9602a41 100644 --- a/app/assets/javascripts/wittle/trace2.js +++ b/app/assets/javascripts/wittle/trace2.js
@@ -15,7 +15,7 @@ class BoundingBox {
15 data.svg.appendChild(this.debug) 15 data.svg.appendChild(this.debug)
16 this.debug.setAttribute('opacity', 0.5) 16 this.debug.setAttribute('opacity', 0.5)
17 this.debug.setAttribute('style', 'pointer-events: none;') 17 this.debug.setAttribute('style', 'pointer-events: none;')
18 if (data.puzzle.symmetry == null) { 18 if (data.puzzle.symType == SYM_TYPE_NONE) {
19 this.debug.setAttribute('fill', 'white') 19 this.debug.setAttribute('fill', 'white')
20 } else { 20 } else {
21 if (this.sym !== true) { 21 if (this.sym !== true) {
@@ -120,7 +120,7 @@ class PathSegment {
120 } 120 }
121 } 121 }
122 122
123 if (data.puzzle.symmetry == null) { 123 if (data.puzzle.symType == SYM_TYPE_NONE) {
124 this.poly1.setAttribute('class', 'line-1 ' + data.svg.id) 124 this.poly1.setAttribute('class', 'line-1 ' + data.svg.id)
125 this.circ.setAttribute('class', 'line-1 ' + data.svg.id) 125 this.circ.setAttribute('class', 'line-1 ' + data.svg.id)
126 this.poly2.setAttribute('class', 'line-1 ' + data.svg.id) 126 this.poly2.setAttribute('class', 'line-1 ' + data.svg.id)
@@ -174,7 +174,7 @@ class PathSegment {
174 if (this.dir === MOVE_NONE) { // Start point 174 if (this.dir === MOVE_NONE) { // Start point
175 this.circ.setAttribute('r', 24) 175 this.circ.setAttribute('r', 24)
176 this.circ.setAttribute('class', this.circ.getAttribute('class') + ' start') 176 this.circ.setAttribute('class', this.circ.getAttribute('class') + ' start')
177 if (data.puzzle.symmetry != null) { 177 if (data.puzzle.symType != SYM_TYPE_NONE) {
178 this.symCirc.setAttribute('r', 24) 178 this.symCirc.setAttribute('r', 24)
179 this.symCirc.setAttribute('class', this.symCirc.getAttribute('class') + ' start') 179 this.symCirc.setAttribute('class', this.symCirc.getAttribute('class') + ' start')
180 } 180 }
@@ -182,7 +182,7 @@ class PathSegment {
182 // Only insert poly1 in non-startpoints 182 // Only insert poly1 in non-startpoints
183 data.svg.insertBefore(this.poly1, data.cursor) 183 data.svg.insertBefore(this.poly1, data.cursor)
184 this.circ.setAttribute('r', 12) 184 this.circ.setAttribute('r', 12)
185 if (data.puzzle.symmetry != null) { 185 if (data.puzzle.symType != SYM_TYPE_NONE) {
186 data.svg.insertBefore(this.symPoly1, data.cursor) 186 data.svg.insertBefore(this.symPoly1, data.cursor)
187 this.symCirc.setAttribute('r', 12) 187 this.symCirc.setAttribute('r', 12)
188 } 188 }
@@ -194,7 +194,7 @@ class PathSegment {
194 data.svg.removeChild(this.circ) 194 data.svg.removeChild(this.circ)
195 data.svg.removeChild(this.poly2) 195 data.svg.removeChild(this.poly2)
196 data.svg.removeChild(this.pillarCirc) 196 data.svg.removeChild(this.pillarCirc)
197 if (data.puzzle.symmetry != null) { 197 if (data.puzzle.symType != SYM_TYPE_NONE) {
198 data.svg.removeChild(this.symPoly1) 198 data.svg.removeChild(this.symPoly1)
199 data.svg.removeChild(this.symCirc) 199 data.svg.removeChild(this.symCirc)
200 data.svg.removeChild(this.symPoly2) 200 data.svg.removeChild(this.symPoly2)
@@ -208,19 +208,19 @@ class PathSegment {
208 var y = clamp(data.y, data.bbox.y1, data.bbox.y2) 208 var y = clamp(data.y, data.bbox.y1, data.bbox.y2)
209 data.cursor.setAttribute('cx', x) 209 data.cursor.setAttribute('cx', x)
210 data.cursor.setAttribute('cy', y) 210 data.cursor.setAttribute('cy', y)
211 if (data.puzzle.symmetry != null) { 211 if (data.puzzle.symType != SYM_TYPE_NONE) {
212 data.symcursor.setAttribute('cx', this._reflX(x)) 212 data.symcursor.setAttribute('cx', this._reflX(x,y))
213 data.symcursor.setAttribute('cy', this._reflY(y)) 213 data.symcursor.setAttribute('cy', this._reflY(x,y))
214 } 214 }
215 if (data.puzzle.pillar === true) { 215 if (data.puzzle.pillar === true) {
216 if (this.pillarCirc.getAttribute('static') == null) { 216 if (this.pillarCirc.getAttribute('static') == null) {
217 this.pillarCirc.setAttribute('cx', x) 217 this.pillarCirc.setAttribute('cx', x)
218 this.pillarCirc.setAttribute('cy', y) 218 this.pillarCirc.setAttribute('cy', y)
219 } 219 }
220 if (data.puzzle.symmetry != null) { 220 if (data.puzzle.symType != SYM_TYPE_NONE) {
221 if (this.symPillarCirc.getAttribute('static') == null) { 221 if (this.symPillarCirc.getAttribute('static') == null) {
222 this.symPillarCirc.setAttribute('cx', this._reflX(x)) 222 this.symPillarCirc.setAttribute('cx', this._reflX(x,y))
223 this.symPillarCirc.setAttribute('cy', this._reflY(y)) 223 this.symPillarCirc.setAttribute('cy', this._reflY(x,y))
224 } 224 }
225 } 225 }
226 } 226 }
@@ -296,19 +296,19 @@ class PathSegment {
296 } 296 }
297 297
298 // Draw the symmetrical path based on the original one 298 // Draw the symmetrical path based on the original one
299 if (data.puzzle.symmetry != null) { 299 if (data.puzzle.symType != SYM_TYPE_NONE) {
300 this.symPoly1.setAttribute('points', 300 this.symPoly1.setAttribute('points',
301 this._reflX(points1.x2) + ' ' + this._reflY(points1.y2) + ',' + 301 this._reflX(points1.x2, points1.y2) + ' ' + this._reflY(points1.x2, points1.y2) + ',' +
302 this._reflX(points1.x2) + ' ' + this._reflY(points1.y1) + ',' + 302 this._reflX(points1.x2, points1.y2) + ' ' + this._reflY(points1.x1, points1.y1) + ',' +
303 this._reflX(points1.x1) + ' ' + this._reflY(points1.y1) + ',' + 303 this._reflX(points1.x1, points1.y1) + ' ' + this._reflY(points1.x1, points1.y1) + ',' +
304 this._reflX(points1.x1) + ' ' + this._reflY(points1.y2) 304 this._reflX(points1.x1, points1.y1) + ' ' + this._reflY(points1.x2, points1.y2)
305 ) 305 )
306 306
307 this.symPoly2.setAttribute('points', 307 this.symPoly2.setAttribute('points',
308 this._reflX(points2.x2) + ' ' + this._reflY(points2.y2) + ',' + 308 this._reflX(points2.x2, points2.y2) + ' ' + this._reflY(points2.x2, points2.y2) + ',' +
309 this._reflX(points2.x2) + ' ' + this._reflY(points2.y1) + ',' + 309 this._reflX(points2.x2, points2.y2) + ' ' + this._reflY(points2.x1, points2.y1) + ',' +
310 this._reflX(points2.x1) + ' ' + this._reflY(points2.y1) + ',' + 310 this._reflX(points2.x1, points2.y1) + ' ' + this._reflY(points2.x1, points2.y1) + ',' +
311 this._reflX(points2.x1) + ' ' + this._reflY(points2.y2) 311 this._reflX(points2.x1, points2.y1) + ' ' + this._reflY(points2.x2, points2.y2)
312 ) 312 )
313 313
314 this.symCirc.setAttribute('opacity', this.circ.getAttribute('opacity')) 314 this.symCirc.setAttribute('opacity', this.circ.getAttribute('opacity'))
@@ -316,24 +316,46 @@ class PathSegment {
316 } 316 }
317 } 317 }
318 318
319 _reflX(x) { 319 _reflX(x,y) {
320 if (data.puzzle.symmetry == null) return x 320 if (data.puzzle.symType == SYM_TYPE_NONE) return x
321 if (data.puzzle.symmetry.x === true) { 321
322 if (data.puzzle.symType == SYM_TYPE_VERTICAL || data.puzzle.symType == SYM_TYPE_ROTATIONAL || data.puzzle.symType == SYM_TYPE_PARALLEL_H_FLIP) {
322 // Mirror position inside the bounding box 323 // Mirror position inside the bounding box
323 return (data.bbox.middle.x - x) + data.symbbox.middle.x 324 return (data.bbox.middle.x - x) + data.symbbox.middle.x
324 } 325 }
325 // Copy position inside the bounding box 326 if (data.puzzle.symType == SYM_TYPE_HORIZONTAL || data.puzzle.symType == SYM_TYPE_PARALLEL_H || data.puzzle.symType == SYM_TYPE_PARALLEL_V || data.puzzle.symType == SYM_TYPE_PARALLEL_V_FLIP) {
326 return (x - data.bbox.middle.x) + data.symbbox.middle.x 327 // Copy position inside the bounding box
328 return (x - data.bbox.middle.x) + data.symbbox.middle.x
329 }
330 if (data.puzzle.symType == SYM_TYPE_ROTATE_LEFT || data.puzzle.symType == SYM_TYPE_FLIP_XY) {
331 // Rotate position left inside the bounding box
332 return (y - data.bbox.middle.y) + data.symbbox.middle.x
333 }
334 if (data.puzzle.symType == SYM_TYPE_ROTATE_RIGHT || data.puzzle.symType == SYM_TYPE_FLIP_NEG_XY) {
335 // Rotate position right inside the bounding box
336 return (data.bbox.middle.y - y) + data.symbbox.middle.x
337 }
327 } 338 }
328 339
329 _reflY(y) { 340 _reflY(x,y) {
330 if (data.puzzle.symmetry == null) return y 341 if (data.puzzle.symType == SYM_TYPE_NONE) return y
331 if (data.puzzle.symmetry.y === true) { 342
343 if (data.puzzle.symType == SYM_TYPE_HORIZONTAL || data.puzzle.symType == SYM_TYPE_ROTATIONAL || data.puzzle.symType == SYM_TYPE_PARALLEL_V_FLIP) {
332 // Mirror position inside the bounding box 344 // Mirror position inside the bounding box
333 return (data.bbox.middle.y - y) + data.symbbox.middle.y 345 return (data.bbox.middle.y - y) + data.symbbox.middle.y
334 } 346 }
335 // Copy position inside the bounding box 347 if (data.puzzle.symType == SYM_TYPE_VERTICAL || data.puzzle.symType == SYM_TYPE_PARALLEL_V || data.puzzle.symType == SYM_TYPE_PARALLEL_H || data.puzzle.symType == SYM_TYPE_PARALLEL_H_FLIP) {
336 return (y - data.bbox.middle.y) + data.symbbox.middle.y 348 // Copy position inside the bounding box
349 return (y - data.bbox.middle.y) + data.symbbox.middle.y
350 }
351 if (data.puzzle.symType == SYM_TYPE_ROTATE_RIGHT || data.puzzle.symType == SYM_TYPE_FLIP_XY) {
352 // Rotate position left inside the bounding box
353 return (x - data.bbox.middle.x) + data.symbbox.middle.y
354 }
355 if (data.puzzle.symType == SYM_TYPE_ROTATE_LEFT || data.puzzle.symType == SYM_TYPE_FLIP_NEG_XY) {
356 // Rotate position right inside the bounding box
357 return (data.bbox.middle.x - x) + data.symbbox.middle.y
358 }
337 } 359 }
338} 360}
339 361
@@ -359,15 +381,29 @@ function clearGrid(svg, puzzle) {
359 381
360// This copy is an exact copy of puzzle.getSymmetricalDir, except that it uses MOVE_* values instead of strings 382// This copy is an exact copy of puzzle.getSymmetricalDir, except that it uses MOVE_* values instead of strings
361function getSymmetricalDir(puzzle, dir) { 383function getSymmetricalDir(puzzle, dir) {
362 if (puzzle.symmetry != null) { 384 if (puzzle.symType == SYM_TYPE_VERTICAL || puzzle.symType == SYM_TYPE_ROTATIONAL || puzzle.symType == SYM_TYPE_PARALLEL_H_FLIP) {
363 if (puzzle.symmetry.x === true) { 385 if (dir === MOVE_LEFT) return MOVE_RIGHT
364 if (dir === MOVE_LEFT) return MOVE_RIGHT 386 if (dir === MOVE_RIGHT) return MOVE_LEFT
365 if (dir === MOVE_RIGHT) return MOVE_LEFT 387 }
366 } 388 if (puzzle.symType == SYM_TYPE_HORIZONTAL || puzzle.symType == SYM_TYPE_ROTATIONAL || puzzle.symType == SYM_TYPE_PARALLEL_V_FLIP) {
367 if (puzzle.symmetry.y === true) { 389 if (dir === MOVE_TOP) return MOVE_BOTTOM
368 if (dir === MOVE_TOP) return MOVE_BOTTOM 390 if (dir === MOVE_BOTTOM) return MOVE_TOP
369 if (dir === MOVE_BOTTOM) return MOVE_TOP 391 }
370 } 392 if (puzzle.symType == SYM_TYPE_ROTATE_LEFT || puzzle.symType == SYM_TYPE_FLIP_NEG_XY) {
393 if (dir === MOVE_LEFT) return MOVE_BOTTOM
394 if (dir === MOVE_RIGHT) return MOVE_TOP
395 }
396 if (puzzle.symType == SYM_TYPE_ROTATE_RIGHT || puzzle.symType == SYM_TYPE_FLIP_NEG_XY) {
397 if (dir === MOVE_TOP) return MOVE_RIGHT
398 if (dir === MOVE_BOTTOM) return MOVE_LEFT
399 }
400 if (puzzle.symType == SYM_TYPE_ROTATE_LEFT || puzzle.symType == SYM_TYPE_FLIP_XY) {
401 if (dir === MOVE_TOP) return MOVE_LEFT
402 if (dir === MOVE_BOTTOM) return MOVE_RIGHT
403 }
404 if (puzzle.symType == SYM_TYPE_ROTATE_RIGHT || puzzle.symType == SYM_TYPE_FLIP_XY) {
405 if (dir === MOVE_RIGHT) return MOVE_BOTTOM
406 if (dir === MOVE_LEFT) return MOVE_TOP
371 } 407 }
372 return dir 408 return dir
373} 409}
@@ -495,7 +531,7 @@ window.onTraceStart = function(puzzle, pos, svg, start, symStart=null) {
495 clearAnimations() 531 clearAnimations()
496 532
497 // Add initial line segments + secondary symmetry cursor, if needed 533 // Add initial line segments + secondary symmetry cursor, if needed
498 if (puzzle.symmetry == null) { 534 if (puzzle.symType == SYM_TYPE_NONE) {
499 data.puzzle.updateCell2(data.pos.x, data.pos.y, 'type', 'line') 535 data.puzzle.updateCell2(data.pos.x, data.pos.y, 'type', 'line')
500 data.puzzle.updateCell2(data.pos.x, data.pos.y, 'line', window.LINE_BLACK) 536 data.puzzle.updateCell2(data.pos.x, data.pos.y, 'line', window.LINE_BLACK)
501 } else { 537 } else {
@@ -641,7 +677,7 @@ window.onMove = function(dx, dy) {
641 || (moveDir === MOVE_TOP && lastDir === MOVE_BOTTOM) 677 || (moveDir === MOVE_TOP && lastDir === MOVE_BOTTOM)
642 || (moveDir === MOVE_BOTTOM && lastDir === MOVE_TOP)) 678 || (moveDir === MOVE_BOTTOM && lastDir === MOVE_TOP))
643 679
644 if (data.puzzle.symmetry != null) { 680 if (data.puzzle.symType != SYM_TYPE_NONE) {
645 var symMoveDir = getSymmetricalDir(data.puzzle, moveDir) 681 var symMoveDir = getSymmetricalDir(data.puzzle, moveDir)
646 } 682 }
647 683
@@ -649,21 +685,21 @@ window.onMove = function(dx, dy) {
649 if (backedUp) { 685 if (backedUp) {
650 data.path.pop().destroy() 686 data.path.pop().destroy()
651 data.puzzle.updateCell2(data.pos.x, data.pos.y, 'line', window.LINE_NONE) 687 data.puzzle.updateCell2(data.pos.x, data.pos.y, 'line', window.LINE_NONE)
652 if (data.puzzle.symmetry != null) { 688 if (data.puzzle.symType != SYM_TYPE_NONE) {
653 data.puzzle.updateCell2(data.sym.x, data.sym.y, 'line', window.LINE_NONE) 689 data.puzzle.updateCell2(data.sym.x, data.sym.y, 'line', window.LINE_NONE)
654 } 690 }
655 } 691 }
656 692
657 // Move to the next cell 693 // Move to the next cell
658 changePos(data.bbox, data.pos, moveDir) 694 changePos(data.bbox, data.pos, moveDir)
659 if (data.puzzle.symmetry != null) { 695 if (data.puzzle.symType != SYM_TYPE_NONE) {
660 changePos(data.symbbox, data.sym, symMoveDir) 696 changePos(data.symbbox, data.sym, symMoveDir)
661 } 697 }
662 698
663 // If we didn't back up, add a path segment and mark the new cell as visited 699 // If we didn't back up, add a path segment and mark the new cell as visited
664 if (!backedUp) { 700 if (!backedUp) {
665 data.path.push(new PathSegment(moveDir)) 701 data.path.push(new PathSegment(moveDir))
666 if (data.puzzle.symmetry == null) { 702 if (data.puzzle.symType == SYM_TYPE_NONE) {
667 data.puzzle.updateCell2(data.pos.x, data.pos.y, 'line', window.LINE_BLACK) 703 data.puzzle.updateCell2(data.pos.x, data.pos.y, 'line', window.LINE_BLACK)
668 } else { 704 } else {
669 data.puzzle.updateCell2(data.pos.x, data.pos.y, 'line', window.LINE_BLUE) 705 data.puzzle.updateCell2(data.pos.x, data.pos.y, 'line', window.LINE_BLUE)
@@ -849,7 +885,7 @@ function hardCollision() {
849 } 885 }
850 } 886 }
851 887
852 if (data.puzzle.symmetry != null) { 888 if (data.puzzle.symType != SYM_TYPE_NONE) {
853 if (data.sym.x === data.pos.x && data.sym.y === data.pos.y) { 889 if (data.sym.x === data.pos.x && data.sym.y === data.pos.y) {
854 console.spam('Collided with our symmetrical line') 890 console.spam('Collided with our symmetrical line')
855 gapSize = 13 891 gapSize = 13
@@ -885,7 +921,7 @@ function move() {
885 } else if (cell.line > window.LINE_NONE && lastDir !== MOVE_RIGHT) { 921 } else if (cell.line > window.LINE_NONE && lastDir !== MOVE_RIGHT) {
886 console.spam('Collided with other line', cell.line) 922 console.spam('Collided with other line', cell.line)
887 data.x = data.bbox.x1 + 12 923 data.x = data.bbox.x1 + 12
888 } else if (data.puzzle.symmetry != null) { 924 } else if (data.puzzle.symType != SYM_TYPE_NONE) {
889 var symCell = data.puzzle.getSymmetricalCell(data.pos.x - 1, data.pos.y) 925 var symCell = data.puzzle.getSymmetricalCell(data.pos.x - 1, data.pos.y)
890 if (symCell == null || symCell.type !== 'line' || symCell.gap === window.GAP_FULL) { 926 if (symCell == null || symCell.type !== 'line' || symCell.gap === window.GAP_FULL) {
891 console.spam('Collided with symmetrical outside / gap-2', cell) 927 console.spam('Collided with symmetrical outside / gap-2', cell)
@@ -903,7 +939,7 @@ function move() {
903 } else if (cell.line > window.LINE_NONE && lastDir !== MOVE_LEFT) { 939 } else if (cell.line > window.LINE_NONE && lastDir !== MOVE_LEFT) {
904 console.spam('Collided with other line', cell.line) 940 console.spam('Collided with other line', cell.line)
905 data.x = data.bbox.x2 - 12 941 data.x = data.bbox.x2 - 12
906 } else if (data.puzzle.symmetry != null) { 942 } else if (data.puzzle.symType != SYM_TYPE_NONE) {
907 var symCell = data.puzzle.getSymmetricalCell(data.pos.x + 1, data.pos.y) 943 var symCell = data.puzzle.getSymmetricalCell(data.pos.x + 1, data.pos.y)
908 if (symCell == null || symCell.type !== 'line' || symCell.gap === window.GAP_FULL) { 944 if (symCell == null || symCell.type !== 'line' || symCell.gap === window.GAP_FULL) {
909 console.spam('Collided with symmetrical outside / gap-2', cell) 945 console.spam('Collided with symmetrical outside / gap-2', cell)
@@ -921,7 +957,7 @@ function move() {
921 } else if (cell.line > window.LINE_NONE && lastDir !== MOVE_BOTTOM) { 957 } else if (cell.line > window.LINE_NONE && lastDir !== MOVE_BOTTOM) {
922 console.spam('Collided with other line', cell.line) 958 console.spam('Collided with other line', cell.line)
923 data.y = data.bbox.y1 + 12 959 data.y = data.bbox.y1 + 12
924 } else if (data.puzzle.symmetry != null) { 960 } else if (data.puzzle.symType != SYM_TYPE_NONE) {
925 var symCell = data.puzzle.getSymmetricalCell(data.pos.x, data.pos.y - 1) 961 var symCell = data.puzzle.getSymmetricalCell(data.pos.x, data.pos.y - 1)
926 if (symCell == null || symCell.type !== 'line' || symCell.gap === window.GAP_FULL) { 962 if (symCell == null || symCell.type !== 'line' || symCell.gap === window.GAP_FULL) {
927 console.spam('Collided with symmetrical outside / gap-2', cell) 963 console.spam('Collided with symmetrical outside / gap-2', cell)
@@ -939,7 +975,7 @@ function move() {
939 } else if (cell.line > window.LINE_NONE && lastDir !== MOVE_TOP) { 975 } else if (cell.line > window.LINE_NONE && lastDir !== MOVE_TOP) {
940 console.spam('Collided with other line', cell.line) 976 console.spam('Collided with other line', cell.line)
941 data.y = data.bbox.y2 - 12 977 data.y = data.bbox.y2 - 12
942 } else if (data.puzzle.symmetry != null) { 978 } else if (data.puzzle.symType != SYM_TYPE_NONE) {
943 var symCell = data.puzzle.getSymmetricalCell(data.pos.x, data.pos.y + 1) 979 var symCell = data.puzzle.getSymmetricalCell(data.pos.x, data.pos.y + 1)
944 if (symCell == null || symCell.type !== 'line' || symCell.gap === window.GAP_FULL) { 980 if (symCell == null || symCell.type !== 'line' || symCell.gap === window.GAP_FULL) {
945 console.spam('Collided with symmetrical outside / gap-2', cell) 981 console.spam('Collided with symmetrical outside / gap-2', cell)
diff --git a/app/assets/javascripts/wittle/validate.js b/app/assets/javascripts/wittle/validate.js index 333d2e1..d6e6484 100644 --- a/app/assets/javascripts/wittle/validate.js +++ b/app/assets/javascripts/wittle/validate.js
@@ -41,7 +41,7 @@ window.validateUserData = function(puzzle, path) {
41 41
42 if (cell.start === true) { 42 if (cell.start === true) {
43 puzzleHasStart = true 43 puzzleHasStart = true
44 if (puzzle.symmetry != null) { 44 if (puzzle.symType != SYM_TYPE_NONE) {
45 var symCell = puzzle.getSymmetricalCell(x, y) 45 var symCell = puzzle.getSymmetricalCell(x, y)
46 if (symCell == null || symCell.start !== true) { 46 if (symCell == null || symCell.start !== true) {
47 throw Error('Startpoint at ' + x + ' ' + y + ' does not have a symmetrical startpoint') 47 throw Error('Startpoint at ' + x + ' ' + y + ' does not have a symmetrical startpoint')
@@ -50,7 +50,7 @@ window.validateUserData = function(puzzle, path) {
50 } 50 }
51 if (cell.end != null) { 51 if (cell.end != null) {
52 puzzleHasEnd = true 52 puzzleHasEnd = true
53 if (puzzle.symmetry != null) { 53 if (puzzle.symType != SYM_TYPE_NONE) {
54 var symCell = puzzle.getSymmetricalCell(x, y) 54 var symCell = puzzle.getSymmetricalCell(x, y)
55 if (symCell == null || symCell.end == null || symCell.end != puzzle.getSymmetricalDir(cell.end)) { 55 if (symCell == null || symCell.end == null || symCell.end != puzzle.getSymmetricalDir(cell.end)) {
56 throw Error('Endpoint at ' + x + ' ' + y + ' does not have a symmetrical endpoint') 56 throw Error('Endpoint at ' + x + ' ' + y + ' does not have a symmetrical endpoint')
diff --git a/ext/wittle_generator/Panel.cpp b/ext/wittle_generator/Panel.cpp index 879d205..3279943 100644 --- a/ext/wittle_generator/Panel.cpp +++ b/ext/wittle_generator/Panel.cpp
@@ -127,12 +127,6 @@ std::string Panel::Write() {
127 int genericFlags = 0; 127 int genericFlags = 0;
128 if (symmetry != Symmetry::None) { 128 if (symmetry != Symmetry::None) {
129 genericFlags |= Serializer::Symmetrical; 129 genericFlags |= Serializer::Symmetrical;
130 if (symmetry == Symmetry::Vertical || symmetry == Symmetry::Rotational) {
131 genericFlags |= Serializer::SymmetryX;
132 }
133 if (symmetry == Symmetry::Horizontal || symmetry == Symmetry::Rotational) {
134 genericFlags |= Serializer::SymmetryY;
135 }
136 } 130 }
137 serializer.writeByte(genericFlags); 131 serializer.writeByte(genericFlags);
138 132
@@ -233,5 +227,7 @@ std::string Panel::Write() {
233 } 227 }
234 serializer.writeByte(settings); 228 serializer.writeByte(settings);
235 229
230 serializer.writeByte(symmetry);
231
236 return serializer.str(); 232 return serializer.str();
237} 233}
diff --git a/ext/wittle_generator/Panel.h b/ext/wittle_generator/Panel.h index d152370..3bc23c9 100644 --- a/ext/wittle_generator/Panel.h +++ b/ext/wittle_generator/Panel.h
@@ -188,22 +188,22 @@ class Panel {
188 188
189 enum Symmetry { // NOTE - Not all of these are valid symmetries for certain 189 enum Symmetry { // NOTE - Not all of these are valid symmetries for certain
190 // puzzles 190 // puzzles
191 None, 191 None = 0,
192 Horizontal, 192 Horizontal = 1,
193 Vertical, 193 Vertical = 2,
194 Rotational, 194 Rotational = 3,
195 RotateLeft, 195 RotateLeft = 4,
196 RotateRight, 196 RotateRight = 5,
197 FlipXY, 197 FlipXY = 6,
198 FlipNegXY, 198 FlipNegXY = 7,
199 ParallelH, 199 ParallelH = 8,
200 ParallelV, 200 ParallelV = 9,
201 ParallelHFlip, 201 ParallelHFlip = 10,
202 ParallelVFlip, 202 ParallelVFlip = 11,
203 PillarParallel, 203 PillarParallel = 12,
204 PillarHorizontal, 204 PillarHorizontal = 13,
205 PillarVertical, 205 PillarVertical = 14,
206 PillarRotational 206 PillarRotational = 15,
207 }; 207 };
208 Symmetry symmetry; 208 Symmetry symmetry;
209 209
diff --git a/ext/wittle_generator/wittle_generator.cpp b/ext/wittle_generator/wittle_generator.cpp index c2407cf..0efac07 100644 --- a/ext/wittle_generator/wittle_generator.cpp +++ b/ext/wittle_generator/wittle_generator.cpp
@@ -420,7 +420,7 @@ Rice::Object wittle_generator_generate_easy(Rice::Object /* self */) {
420Rice::Object wittle_generator_generate_medium(Rice::Object /* self */) { 420Rice::Object wittle_generator_generate_medium(Rice::Object /* self */) {
421 Generate generator; 421 Generate generator;
422 422
423 int choice = Random::rand() % 66; 423 int choice = Random::rand() % 69;
424 std::cout << "Generate MEDIUM: choice " << std::dec << choice << std::endl; 424 std::cout << "Generate MEDIUM: choice " << std::dec << choice << std::endl;
425 425
426 switch (choice) { 426 switch (choice) {
@@ -1015,6 +1015,33 @@ Rice::Object wittle_generator_generate_medium(Rice::Object /* self */) {
1015 {Decoration::Dot_Intersection, 25}}}); 1015 {Decoration::Dot_Intersection, 25}}});
1016 break; 1016 break;
1017 } 1017 }
1018 case 66: {
1019 generator.setSymmetry(Panel::Symmetry::FlipNegXY);
1020 generator.generate(7, 7,
1021 {{{Decoration::Gap, 10},
1022 {Decoration::Dot_Intersection, 8},
1023 {Decoration::Start, 2},
1024 {Decoration::Exit, 1}}});
1025 break;
1026 }
1027 case 67: {
1028 generator.setSymmetry(Panel::Symmetry::ParallelV);
1029 generator.generate(7, 7,
1030 {{{Decoration::Gap, 12},
1031 {Decoration::Dot_Intersection, 10},
1032 {Decoration::Start, 2},
1033 {Decoration::Exit, 1}}});
1034 break;
1035 }
1036 case 68: {
1037 generator.setSymmetry(Panel::Symmetry::ParallelHFlip);
1038 generator.generate(7, 7,
1039 {{{Decoration::Gap, 12},
1040 {Decoration::Dot_Intersection, 10},
1041 {Decoration::Start, 2},
1042 {Decoration::Exit, 1}}});
1043 break;
1044 }
1018 } 1045 }
1019 1046
1020 Rice::String str(generator.AsCode()); 1047 Rice::String str(generator.AsCode());
@@ -1024,7 +1051,7 @@ Rice::Object wittle_generator_generate_medium(Rice::Object /* self */) {
1024Rice::Object wittle_generator_generate_expert(Rice::Object /* self */) { 1051Rice::Object wittle_generator_generate_expert(Rice::Object /* self */) {
1025 Generate generator; 1052 Generate generator;
1026 1053
1027 int choice = Random::rand() % 40; 1054 int choice = Random::rand() % 46;
1028 std::cout << "Generate EXPERT: choice " << std::dec << choice << std::endl; 1055 std::cout << "Generate EXPERT: choice " << std::dec << choice << std::endl;
1029 1056
1030 switch (choice) { 1057 switch (choice) {
@@ -1497,6 +1524,91 @@ Rice::Object wittle_generator_generate_expert(Rice::Object /* self */) {
1497 {Decoration::Dot_Intersection, 36}}}); 1524 {Decoration::Dot_Intersection, 36}}});
1498 break; 1525 break;
1499 } 1526 }
1527 case 40: {
1528 generator.setGridSize(7, 7);
1529 generator.setFlag(Generate::RequireCombineShapes);
1530 generator.setSymmetry(Panel::ParallelV);
1531 generator.setSymbol(Decoration::Start, 0, 14);
1532 generator.setSymbol(Decoration::Start, 8, 14);
1533 generator.setSymbol(Decoration::Exit, 6, 0);
1534 generator.setSymbol(Decoration::Exit, 14, 0);
1535 generator.generate(7, 7,
1536 {{{Decoration::Poly | Decoration::Color::Orange, 5}}});
1537 break;
1538 }
1539 case 41: {
1540 generator.setGridSize(7, 7);
1541 generator.setFlag(Generate::RequireCombineShapes);
1542 generator.setSymmetry(Panel::ParallelHFlip);
1543 generator.setSymbol(Decoration::Start, 0, 14);
1544 generator.setSymbol(Decoration::Start, 14, 6);
1545 generator.setSymbol(Decoration::Exit, 0, 0);
1546 generator.setSymbol(Decoration::Exit, 14, 8);
1547 generator.generate(7, 7,
1548 {{{Decoration::Poly | Decoration::Color::Orange, 5}}});
1549 break;
1550 }
1551 case 42: {
1552 generator.setGridSize(7, 7);
1553 generator.setFlag(Generate::RequireCombineShapes);
1554 generator.setSymmetry(Panel::ParallelVFlip);
1555 generator.setSymbol(Decoration::Start, 0, 14);
1556 generator.setSymbol(Decoration::Start, 8, 0);
1557 generator.setSymbol(Decoration::Exit, 6, 0);
1558 generator.setSymbol(Decoration::Exit, 14, 14);
1559 generator.generate(7, 7,
1560 {{{Decoration::Poly | Decoration::Color::Orange, 5}}});
1561 break;
1562 }
1563 case 43: {
1564 generator.setSymmetry(Panel::Symmetry::RotateLeft);
1565 generator.setSymbol(Decoration::Start, 4, 4);
1566 generator.setSymbol(Decoration::Start, 10, 4);
1567 generator.setSymbol(Decoration::Start, 4, 10);
1568 generator.setSymbol(Decoration::Start, 10, 10);
1569 generator.setSymbol(Decoration::Exit, 4, 0);
1570 generator.setSymbol(Decoration::Exit, 14, 4);
1571 generator.setSymbol(Decoration::Exit, 0, 10);
1572 generator.setSymbol(Decoration::Exit, 10, 14);
1573 generator.generate(
1574 7, 7,
1575 {{{Decoration::Triangle4 | Decoration::Color::Orange, 1},
1576 {Decoration::Triangle | Decoration::Color::Orange, 4}}});
1577 break;
1578 }
1579 case 44: {
1580 generator.setFlag(Generate::WriteInvisible);
1581 generator.setFlag(Generate::StartEdgeOnly);
1582 generator.setSymmetry(Panel::Symmetry::FlipXY);
1583 generator.setSymbol(Decoration::Exit, 0, 8);
1584 generator.setSymbol(Decoration::Exit, 8, 0);
1585 generator.generate(7, 7,
1586 {{{Decoration::Dot | Decoration::Color::Blue, 2},
1587 {Decoration::Dot | Decoration::Color::Yellow, 2},
1588 {Decoration::Dot, 8},
1589 {Decoration::Eraser | Decoration::Color::White, 1},
1590 {Decoration::Start, 1}}});
1591 break;
1592 }
1593 case 45: {
1594 generator.setFlag(Generate::WriteInvisible);
1595 generator.setSymmetry(Panel::Symmetry::FlipXY);
1596 generator.setSymbol(Decoration::Start, 0, 16);
1597 generator.setSymbol(Decoration::Start, 16, 0);
1598 generator.setSymbol(Decoration::Exit, 8, 0);
1599 generator.setSymbol(Decoration::Exit, 8, 16);
1600 generator.setSymbol(Decoration::Exit, 0, 8);
1601 generator.setSymbol(Decoration::Exit, 16, 8);
1602 generator.generate(
1603 8, 8,
1604 {{{Decoration::Triangle | Decoration::Color::Cyan, 3},
1605 {Decoration::Triangle | Decoration::Color::Yellow, 2},
1606 {Decoration::Star | Decoration::Color::Cyan, 3},
1607 {Decoration::Star | Decoration::Color::Yellow, 3},
1608 {Decoration::Stone | Decoration::Color::Cyan, 2},
1609 {Decoration::Stone | Decoration::Color::Yellow, 3}}});
1610 break;
1611 }
1500 } 1612 }
1501 1613
1502 Rice::String str(generator.AsCode()); 1614 Rice::String str(generator.AsCode());