From cbdf87bb8aaebca9c969dfec3c1664b9b6355a0d Mon Sep 17 00:00:00 2001 From: jbzdarkid Date: Fri, 22 Nov 2019 09:37:10 -0800 Subject: Asymmetrical gaps --- Source/Puzzle.h | 6 +++-- Source/PuzzleSerializer.cpp | 65 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 59 insertions(+), 12 deletions(-) diff --git a/Source/Puzzle.h b/Source/Puzzle.h index 8afb9ca..b7dedd5 100644 --- a/Source/Puzzle.h +++ b/Source/Puzzle.h @@ -62,10 +62,12 @@ struct Cell { struct Negation {}; struct Pos { + Pos() = default; // Required for use in std::maps Pos(int x_, int y_) : x(x_), y(y_) {} Pos(const std::tuple& xy) : x(std::get<0>(xy)), y(std::get<1>(xy)) {} - int x; - int y; + bool operator==(Pos other) {return x == other.x && y == other.y;} + int x = 0; + int y = 0; }; class Puzzle { diff --git a/Source/PuzzleSerializer.cpp b/Source/PuzzleSerializer.cpp index f0ddf0b..a131376 100644 --- a/Source/PuzzleSerializer.cpp +++ b/Source/PuzzleSerializer.cpp @@ -44,7 +44,7 @@ void PuzzleSerializer::WritePuzzle(const Puzzle& p, int id) { WIDTH_INTERVAL = (MAX - MIN) / (p.width/2); HEIGHT_INTERVAL = (MAX - MIN) / (p.height/2); GAP_SIZE = min(WIDTH_INTERVAL, HEIGHT_INTERVAL) / 2; - // @Improvement: This will make grid cells square... but how do I keep the puzzle centered? + // @Improvement: This will make grid cells square... but how do I keep the puzzle centered? Maybe save extra metadata? // INTERVAL = (MAX - MIN) / (max(p.width, p.height) / 2); // GAP_SIZE = INTERVAL / 2; @@ -78,7 +78,8 @@ void PuzzleSerializer::WritePuzzle(const Puzzle& p, int id) { } void PuzzleSerializer::ReadIntersections(Puzzle& p) { - // @Cleanup: Change defaults? + // @Cleanup: Just change the defaults, instead of this? + // Mark every edge as a full gap for (int x=0; x locationB) std::swap(locationA, locationB); // A < B @@ -121,6 +123,9 @@ void PuzzleSerializer::ReadExtras(Puzzle& p) { } } + // Maps "extra gap intersection location" -> grid location. Note that there should be two locations for each position. + std::unordered_map gapLocations; + // Iterate the remaining intersections (endpoints, dots, gaps) for (; i < _numIntersections; i++) { int location = FindConnection(i); @@ -152,6 +157,21 @@ void PuzzleSerializer::ReadExtras(Puzzle& p) { else if (y1 < y2) y++; else if (y1 > y2) y--; p.grid[x][y].gap = Cell::Gap::BREAK; + gapLocations[i] = Pos{x, y}; + } + } + + // Fixups for asymmetrical gaps + for (int i=0; i<_connectionsA.size(); i++) { + // Only consider connections to non-grid locations + int locationA = _connectionsA[i]; + if (locationA < _numGridLocations) continue; + int locationB = _connectionsB[i]; + if (locationB < _numGridLocations) continue; + + Pos pos = gapLocations[locationA]; + if (pos == gapLocations[locationB]) { + p.grid[pos.x][pos.y].gap = Cell::Gap::NONE; } } } @@ -343,7 +363,18 @@ void PuzzleSerializer::WriteGaps(const Puzzle& p) { for (int x=0; x(_intersectionFlags.size()); _connectionsA[connectionLocation] = xy_to_loc(p, x, y-1); - _connectionsB[connectionLocation] = static_cast(_intersectionFlags.size()); + _connectionsB[connectionLocation] = gap1Location; AddIntersection(p, x, y, xPos, yPos + GAP_SIZE / 2, Flags::HAS_ONE_CONN | Flags::HAS_VERTI_CONN); + gap2Location = static_cast(_intersectionFlags.size()); _connectionsA.push_back(xy_to_loc(p, x, y+1)); - _connectionsB.push_back(static_cast(_intersectionFlags.size())); + _connectionsB.push_back(gap2Location); AddIntersection(p, x, y, xPos, yPos - GAP_SIZE / 2, Flags::HAS_ONE_CONN | Flags::HAS_VERTI_CONN); } else if (y%2 == 0) { // Horizontal gap + gap1Location = static_cast(_intersectionFlags.size()); _connectionsA[connectionLocation] = xy_to_loc(p, x-1, y); - _connectionsB[connectionLocation] = static_cast(_intersectionFlags.size()); + _connectionsB[connectionLocation] = gap1Location; AddIntersection(p, x, y, xPos - GAP_SIZE / 2, yPos, Flags::HAS_ONE_CONN | Flags::HAS_HORIZ_CONN); + gap2Location = static_cast(_intersectionFlags.size()); _connectionsA.push_back(xy_to_loc(p, x+1, y)); - _connectionsB.push_back(static_cast(_intersectionFlags.size())); + _connectionsB.push_back(gap2Location); AddIntersection(p, x, y, xPos + GAP_SIZE / 2, yPos, Flags::HAS_ONE_CONN | Flags::HAS_HORIZ_CONN); } + if (p.symmetry != Puzzle::Symmetry::NONE) { + if (p.grid[x][y].gap == Cell::Gap::NONE) { + // A gap was asked to be introduced strictly for interaction reasons, but it shouldn't look like a gap. + // Add a connection between two halves of the gap to cover it graphically. + _connectionsA.push_back(gap1Location); + _connectionsB.push_back(gap2Location); + } + } } } } @@ -446,7 +489,7 @@ void PuzzleSerializer::WriteSymmetry(const Puzzle& p, int id) { location = extra_xy_to_loc(p, x, y); Pos sym = p.GetSymmetricalPos(x, y); symLocation = extra_xy_to_loc(p, sym.x, sym.y); - reflectionData[location] = symLocation; + reflectionData[location] = symLocation; // @Assume the symmetrical endpoint will write the other pair } } } @@ -463,6 +506,8 @@ void PuzzleSerializer::WriteSymmetry(const Puzzle& p, int id) { // Rely on symmetry to set the other pairs reflectionData[location] = symLocation; reflectionData[location-1] = symLocation-1; + reflectionData[symLocation] = location; + reflectionData[symLocation-1] = location-1; } } -- cgit 1.4.1