diff options
author | jbzdarkid <jbzdarkid@gmail.com> | 2019-11-16 15:08:14 -0800 |
---|---|---|
committer | jbzdarkid <jbzdarkid@gmail.com> | 2019-11-16 15:08:14 -0800 |
commit | ee426c3bde4b4c7fb1ea38a953d849e8893d8311 (patch) | |
tree | 35307ccba67f55f628be5df47dedf8a11d516c94 | |
parent | fc8649b12fc1280d81e8dd4d35736ed69c0d9909 (diff) | |
download | witness-tutorializer-ee426c3bde4b4c7fb1ea38a953d849e8893d8311.tar.gz witness-tutorializer-ee426c3bde4b4c7fb1ea38a953d849e8893d8311.tar.bz2 witness-tutorializer-ee426c3bde4b4c7fb1ea38a953d849e8893d8311.zip |
Some cleanup + bugfixes
-rw-r--r-- | Source/Puzzle.h | 25 | ||||
-rw-r--r-- | Source/PuzzlerSerializer.cpp | 63 | ||||
-rw-r--r-- | Source/PuzzlerSerializer.h | 2 |
3 files changed, 54 insertions, 36 deletions
diff --git a/Source/Puzzle.h b/Source/Puzzle.h index fdf51be..962874e 100644 --- a/Source/Puzzle.h +++ b/Source/Puzzle.h | |||
@@ -38,25 +38,26 @@ struct Decoration { | |||
38 | }; | 38 | }; |
39 | 39 | ||
40 | struct Cell { | 40 | struct Cell { |
41 | inline static Cell Undefined() { | ||
42 | Cell c; | ||
43 | c.undefined = true; | ||
44 | return c; | ||
45 | } | ||
46 | bool undefined = false; | ||
47 | |||
48 | bool start = false; | ||
49 | enum class Dir {NONE, LEFT, RIGHT, UP, DOWN}; | ||
50 | Dir end = Dir::NONE; | ||
51 | std::shared_ptr<Decoration> decoration = nullptr; | ||
52 | enum class Dot {NONE, BLACK, BLUE, YELLOW, INVISIBLE}; | 41 | enum class Dot {NONE, BLACK, BLUE, YELLOW, INVISIBLE}; |
53 | Dot dot = Dot::NONE; | 42 | Dot dot = Dot::NONE; |
54 | enum class Gap {NONE, BREAK, FULL}; | 43 | enum class Gap {NONE, BREAK, FULL}; |
55 | Gap gap = Gap::NONE; | 44 | Gap gap = Gap::NONE; |
56 | |||
57 | // Line color | 45 | // Line color |
58 | enum class Color {NONE, BLACK, BLUE, YELLOW}; | 46 | enum class Color {NONE, BLACK, BLUE, YELLOW}; |
59 | Color color = Color::NONE; | 47 | Color color = Color::NONE; |
48 | |||
49 | std::shared_ptr<Decoration> decoration = nullptr; | ||
50 | |||
51 | bool start = false; | ||
52 | enum class Dir {NONE, LEFT, RIGHT, UP, DOWN}; | ||
53 | Dir end = Dir::NONE; | ||
54 | |||
55 | inline static Cell Undefined() { | ||
56 | Cell c; | ||
57 | c.undefined = true; | ||
58 | return c; | ||
59 | } | ||
60 | bool undefined = false; | ||
60 | }; | 61 | }; |
61 | 62 | ||
62 | struct Negation {}; | 63 | struct Negation {}; |
diff --git a/Source/PuzzlerSerializer.cpp b/Source/PuzzlerSerializer.cpp index 8ab1649..abdfafd 100644 --- a/Source/PuzzlerSerializer.cpp +++ b/Source/PuzzlerSerializer.cpp | |||
@@ -95,7 +95,7 @@ void PuzzleSerializer::ReadExtras(Puzzle& p) { | |||
95 | p.grid[x][y].start = true; | 95 | p.grid[x][y].start = true; |
96 | } | 96 | } |
97 | p.grid[x][y].dot = FlagsToDot(flags); | 97 | p.grid[x][y].dot = FlagsToDot(flags); |
98 | if (flags & Flags::IS_FULL_GAP) { | 98 | if (flags & Flags::HAS_NO_CONN) { |
99 | p.grid[x][y].gap = Cell::Gap::FULL; | 99 | p.grid[x][y].gap = Cell::Gap::FULL; |
100 | } | 100 | } |
101 | } | 101 | } |
@@ -175,15 +175,13 @@ void PuzzleSerializer::WriteIntersections(const Puzzle& p) { | |||
175 | // Grided intersections | 175 | // Grided intersections |
176 | for (int y=p.height-1; y>=0; y-=2) { | 176 | for (int y=p.height-1; y>=0; y-=2) { |
177 | for (int x=0; x<p.width; x+=2) { | 177 | for (int x=0; x<p.width; x+=2) { |
178 | _intersectionLocations.push_back(MIN + (x/2) * WIDTH_INTERVAL); | 178 | auto [xPos, yPos] = xy_to_pos(p, x, y); |
179 | _intersectionLocations.push_back(MAX - (y/2) * HEIGHT_INTERVAL); | 179 | _intersectionLocations.push_back(xPos); |
180 | _intersectionLocations.push_back(yPos); | ||
180 | int flags = 0; | 181 | int flags = 0; |
181 | if (p.grid[x][y].start) { | 182 | if (p.grid[x][y].start) { |
182 | flags |= Flags::IS_STARTPOINT; | 183 | flags |= Flags::IS_STARTPOINT; |
183 | } | 184 | } |
184 | if (p.grid[x][y].gap == Cell::Gap::FULL) { | ||
185 | flags |= Flags::IS_FULL_GAP; | ||
186 | } | ||
187 | switch (p.grid[x][y].dot) { | 185 | switch (p.grid[x][y].dot) { |
188 | case Cell::Dot::BLACK: | 186 | case Cell::Dot::BLACK: |
189 | flags |= Flags::HAS_DOT; | 187 | flags |= Flags::HAS_DOT; |
@@ -201,15 +199,15 @@ void PuzzleSerializer::WriteIntersections(const Puzzle& p) { | |||
201 | 199 | ||
202 | int numConnections = 0; | 200 | int numConnections = 0; |
203 | if (p.grid[x][y].end != Cell::Dir::NONE) numConnections++; | 201 | if (p.grid[x][y].end != Cell::Dir::NONE) numConnections++; |
204 | // Create connections for this intersection for bottom/left only. | 202 | // Create connections for this intersection for top/left only. |
205 | // Bottom connection | 203 | // Top connection |
206 | if (y > 0 && p.grid[x][y-1].gap != Cell::Gap::FULL) { | 204 | if (y > 0 && p.grid[x][y-1].gap != Cell::Gap::FULL) { |
207 | _connectionsA.push_back(xy_to_loc(p, x, y-2)); | 205 | _connectionsA.push_back(xy_to_loc(p, x, y-2)); |
208 | _connectionsB.push_back(xy_to_loc(p, x, y)); | 206 | _connectionsB.push_back(xy_to_loc(p, x, y)); |
209 | flags |= Flags::HAS_VERTI_CONN; | 207 | flags |= Flags::HAS_VERTI_CONN; |
210 | numConnections++; | 208 | numConnections++; |
211 | } | 209 | } |
212 | // Top connection | 210 | // Bottom connection |
213 | if (y < p.height - 1 && p.grid[x][y+1].gap != Cell::Gap::FULL) { | 211 | if (y < p.height - 1 && p.grid[x][y+1].gap != Cell::Gap::FULL) { |
214 | flags |= Flags::HAS_VERTI_CONN; | 212 | flags |= Flags::HAS_VERTI_CONN; |
215 | numConnections++; | 213 | numConnections++; |
@@ -226,7 +224,9 @@ void PuzzleSerializer::WriteIntersections(const Puzzle& p) { | |||
226 | flags |= Flags::HAS_HORIZ_CONN; | 224 | flags |= Flags::HAS_HORIZ_CONN; |
227 | numConnections++; | 225 | numConnections++; |
228 | } | 226 | } |
227 | if (numConnections == 0) flags |= HAS_NO_CONN; | ||
229 | if (numConnections == 1) flags |= HAS_ONE_CONN; | 228 | if (numConnections == 1) flags |= HAS_ONE_CONN; |
229 | |||
230 | _intersectionFlags.push_back(flags); | 230 | _intersectionFlags.push_back(flags); |
231 | } | 231 | } |
232 | } | 232 | } |
@@ -268,21 +268,25 @@ void PuzzleSerializer::WriteDots(const Puzzle& p) { | |||
268 | if (x%2 == y%2) continue; // Cells are invalid, intersections are already handled. | 268 | if (x%2 == y%2) continue; // Cells are invalid, intersections are already handled. |
269 | if (p.grid[x][y].dot == Cell::Dot::NONE) continue; | 269 | if (p.grid[x][y].dot == Cell::Dot::NONE) continue; |
270 | 270 | ||
271 | // We need to introduce a new segment -- | 271 | // We need to introduce a new segment which contains this dot. Break the existing segment, and add one. |
272 | // Locate the segment we're breaking | 272 | int connectionLocation = -1; |
273 | for (int i=0; i<_connectionsA.size(); i++) { | 273 | for (int i=0; i<_connectionsA.size(); i++) { |
274 | auto [x1, y1] = loc_to_xy(p, _connectionsA[i]); | 274 | auto [x1, y1] = loc_to_xy(p, _connectionsA[i]); |
275 | auto [x2, y2] = loc_to_xy(p, _connectionsB[i]); | 275 | auto [x2, y2] = loc_to_xy(p, _connectionsB[i]); |
276 | if ((x1+1 == x && x2-1 == x && y1 == y && y2 == y) || | 276 | if ((x1+1 == x && x2-1 == x && y1 == y && y2 == y) || |
277 | (y1+1 == y && y2-1 == y && x1 == x && x2 == x)) { | 277 | (y1+1 == y && y2-1 == y && x1 == x && x2 == x)) { |
278 | int other_connection = _connectionsB[i]; | 278 | connectionLocation = i; |
279 | _connectionsB[i] = static_cast<int>(_intersectionFlags.size()); | 279 | break; |
280 | |||
281 | _connectionsA.push_back(other_connection); | ||
282 | _connectionsB.push_back(static_cast<int>(_intersectionFlags.size())); | ||
283 | break; | ||
284 | } | 280 | } |
285 | } | 281 | } |
282 | if (connectionLocation == -1) continue; // @Error | ||
283 | |||
284 | // @Assume: B > A for connections. To remove, add the horiz/verti check, see gaps. | ||
285 | int other_connection = _connectionsB[connectionLocation]; | ||
286 | _connectionsB[connectionLocation] = static_cast<int>(_intersectionFlags.size()); | ||
287 | _connectionsA.push_back(other_connection); | ||
288 | _connectionsB.push_back(static_cast<int>(_intersectionFlags.size())); | ||
289 | |||
286 | // Add this dot to the end | 290 | // Add this dot to the end |
287 | auto [xPos, yPos] = xy_to_pos(p, x, y); | 291 | auto [xPos, yPos] = xy_to_pos(p, x, y); |
288 | _intersectionLocations.push_back(xPos); | 292 | _intersectionLocations.push_back(xPos); |
@@ -313,11 +317,24 @@ void PuzzleSerializer::WriteGaps(const Puzzle& p) { | |||
313 | if (x%2 == y%2) continue; // Cells are invalid, intersections are already handled. | 317 | if (x%2 == y%2) continue; // Cells are invalid, intersections are already handled. |
314 | if (p.grid[x][y].gap != Cell::Gap::BREAK) continue; | 318 | if (p.grid[x][y].gap != Cell::Gap::BREAK) continue; |
315 | 319 | ||
320 | // We need to introduce a new segment which contains this dot. Break the existing segment, and add one. | ||
321 | int connectionLocation = -1; | ||
322 | for (int i=0; i<_connectionsA.size(); i++) { | ||
323 | auto [x1, y1] = loc_to_xy(p, _connectionsA[i]); | ||
324 | auto [x2, y2] = loc_to_xy(p, _connectionsB[i]); | ||
325 | if ((x1+1 == x && x2-1 == x && y1 == y && y2 == y) || | ||
326 | (y1+1 == y && y2-1 == y && x1 == x && x2 == x)) { | ||
327 | connectionLocation = i; | ||
328 | break; | ||
329 | } | ||
330 | } | ||
331 | if (connectionLocation == -1) continue; // @Error | ||
332 | |||
316 | auto [xPos, yPos] = xy_to_pos(p, x, y); | 333 | auto [xPos, yPos] = xy_to_pos(p, x, y); |
317 | // Reminder: Y goes from 0.0 (bottom) to 1.0 (top) | 334 | // Reminder: Y goes from 0.0 (bottom) to 1.0 (top) |
318 | if (x%2 == 0) { // Vertical gap | 335 | if (x%2 == 0) { // Vertical gap |
319 | _connectionsA.push_back(xy_to_loc(p, x, y-1)); | 336 | _connectionsA[connectionLocation] = xy_to_loc(p, x, y-1); |
320 | _connectionsB.push_back(static_cast<int>(_intersectionFlags.size())); | 337 | _connectionsB[connectionLocation] = static_cast<int>(_intersectionFlags.size()); |
321 | _intersectionLocations.push_back(xPos); | 338 | _intersectionLocations.push_back(xPos); |
322 | _intersectionLocations.push_back(yPos + VERTI_GAP_SIZE / 2); | 339 | _intersectionLocations.push_back(yPos + VERTI_GAP_SIZE / 2); |
323 | _intersectionFlags.push_back(Flags::HAS_ONE_CONN | Flags::HAS_VERTI_CONN); | 340 | _intersectionFlags.push_back(Flags::HAS_ONE_CONN | Flags::HAS_VERTI_CONN); |
@@ -328,8 +345,8 @@ void PuzzleSerializer::WriteGaps(const Puzzle& p) { | |||
328 | _intersectionLocations.push_back(yPos - VERTI_GAP_SIZE / 2); | 345 | _intersectionLocations.push_back(yPos - VERTI_GAP_SIZE / 2); |
329 | _intersectionFlags.push_back(Flags::HAS_ONE_CONN | Flags::HAS_VERTI_CONN); | 346 | _intersectionFlags.push_back(Flags::HAS_ONE_CONN | Flags::HAS_VERTI_CONN); |
330 | } else if (y%2 == 0) { // Horizontal gap | 347 | } else if (y%2 == 0) { // Horizontal gap |
331 | _connectionsA.push_back(xy_to_loc(p, x-1, y)); | 348 | _connectionsA[connectionLocation] = xy_to_loc(p, x-1, y); |
332 | _connectionsB.push_back(static_cast<int>(_intersectionFlags.size())); | 349 | _connectionsB[connectionLocation] = static_cast<int>(_intersectionFlags.size()); |
333 | _intersectionLocations.push_back(xPos - HORIZ_GAP_SIZE / 2); | 350 | _intersectionLocations.push_back(xPos - HORIZ_GAP_SIZE / 2); |
334 | _intersectionLocations.push_back(yPos); | 351 | _intersectionLocations.push_back(yPos); |
335 | _intersectionFlags.push_back(Flags::HAS_ONE_CONN | Flags::HAS_HORIZ_CONN); | 352 | _intersectionFlags.push_back(Flags::HAS_ONE_CONN | Flags::HAS_HORIZ_CONN); |
@@ -422,8 +439,8 @@ int PuzzleSerializer::xy_to_dloc(const Puzzle& p, int x, int y) const { | |||
422 | 439 | ||
423 | std::tuple<float, float> PuzzleSerializer::xy_to_pos(const Puzzle& p, int x, int y) const { | 440 | std::tuple<float, float> PuzzleSerializer::xy_to_pos(const Puzzle& p, int x, int y) const { |
424 | return { | 441 | return { |
425 | MIN + (x/2) * WIDTH_INTERVAL, | 442 | MIN + (x/2.0f) * WIDTH_INTERVAL, |
426 | MAX - (y/2) * HEIGHT_INTERVAL | 443 | MAX - (y/2.0f) * HEIGHT_INTERVAL |
427 | }; | 444 | }; |
428 | } | 445 | } |
429 | 446 | ||
diff --git a/Source/PuzzlerSerializer.h b/Source/PuzzlerSerializer.h index a49dd90..a3d821c 100644 --- a/Source/PuzzlerSerializer.h +++ b/Source/PuzzlerSerializer.h | |||
@@ -17,7 +17,7 @@ private: | |||
17 | enum Flags { | 17 | enum Flags { |
18 | IS_ENDPOINT = 0x1, | 18 | IS_ENDPOINT = 0x1, |
19 | IS_STARTPOINT = 0x2, | 19 | IS_STARTPOINT = 0x2, |
20 | IS_FULL_GAP = 0x8, | 20 | HAS_NO_CONN = 0x8, |
21 | HAS_DOT = 0x20, | 21 | HAS_DOT = 0x20, |
22 | DOT_IS_BLUE = 0x100, | 22 | DOT_IS_BLUE = 0x100, |
23 | DOT_IS_ORANGE = 0x200, | 23 | DOT_IS_ORANGE = 0x200, |