From 059e44fa16b649938d79597bcf8f41bf4aa136ab Mon Sep 17 00:00:00 2001
From: jbzdarkid <jbzdarkid@gmail.com>
Date: Fri, 22 Nov 2019 10:04:19 -0800
Subject: fix more asymmetrical gap bugs

---
 Source/PuzzleSerializer.cpp | 20 ++++++++++++++------
 Source/Randomizer2.cpp      | 19 ++++++++++++++++++-
 Source/Randomizer2Core.cpp  | 23 ++++++++++++++---------
 3 files changed, 46 insertions(+), 16 deletions(-)

diff --git a/Source/PuzzleSerializer.cpp b/Source/PuzzleSerializer.cpp
index a131376..fb4166b 100644
--- a/Source/PuzzleSerializer.cpp
+++ b/Source/PuzzleSerializer.cpp
@@ -485,7 +485,6 @@ void PuzzleSerializer::WriteSymmetry(const Puzzle& p, int id) {
             reflectionData[location] = symLocation;
             reflectionData[symLocation] = location;
             if (p.grid[x][y].end != Cell::Dir::NONE) {
-                // Rely on symmetry to set the other pair
                 location = extra_xy_to_loc(p, x, y);
                 Pos sym = p.GetSymmetricalPos(x, y);
                 symLocation = extra_xy_to_loc(p, sym.x, sym.y);
@@ -503,11 +502,20 @@ void PuzzleSerializer::WriteSymmetry(const Puzzle& p, int id) {
             int location = extra_xy_to_loc(p, x, y);
             int symLocation = extra_xy_to_loc(p, sym.x, sym.y);
             // Each gap results in two intersections, @Assume they're written consecutively
-            // Rely on symmetry to set the other pairs
-            reflectionData[location] = symLocation;
-            reflectionData[location-1] = symLocation-1;
-            reflectionData[symLocation] = location;
-            reflectionData[symLocation-1] = location-1;
+
+            if ((x%2 != 0 && p.symmetry & Puzzle::Symmetry::X) || 
+                (y%2 != 0 && p.symmetry & Puzzle::Symmetry::Y)) {
+                // Write data inverted, because it's being reflected
+                reflectionData[location] = symLocation-1;
+                reflectionData[location-1] = symLocation;
+                reflectionData[symLocation] = location-1;
+                reflectionData[symLocation-1] = location;
+            } else { // Write data normally
+                reflectionData[location] = symLocation;
+                reflectionData[location-1] = symLocation-1;
+                reflectionData[symLocation] = location;
+                reflectionData[symLocation-1] = location-1;
+            }
         }
     }
 
diff --git a/Source/Randomizer2.cpp b/Source/Randomizer2.cpp
index cc23c7d..c823567 100644
--- a/Source/Randomizer2.cpp
+++ b/Source/Randomizer2.cpp
@@ -177,7 +177,24 @@ void Randomizer2::RandomizeSymmetry() {
         Puzzle p;
         p.NewGrid(4, 4);
         p.symmetry = Puzzle::Symmetry::X;
-    
+        p.grid[0][8].start = true;
+        p.grid[8][8].start = true;
+        p.grid[2][0].end = Cell::Dir::UP;
+        p.grid[6][0].end = Cell::Dir::UP;
+        // @Bug: This can still make the puzzle unsolvable, if it leaves the centerline free -- even though two lines can't pass through the centerline.
+        // ^ Try seed = 13710
+        std::vector<Pos> cutEdges = Randomizer2Core::CutSymmetricalEdgePairs(p, 4);
+        for (int i=0; i<2; i++) {
+            Pos pos = cutEdges[i];
+            p.grid[pos.x][pos.y].gap = Cell::Gap::BREAK;
+        }
+        for (int i=2; i<4; i++) {
+            Pos pos = cutEdges[i];
+            Pos sym = p.GetSymmetricalPos(pos.x, pos.y);
+            p.grid[sym.x][sym.y].gap = Cell::Gap::BREAK;
+        }
+
+        _serializer.WritePuzzle(p, 0x87);
     }
 }
 
diff --git a/Source/Randomizer2Core.cpp b/Source/Randomizer2Core.cpp
index dcb9fd2..8ef2301 100644
--- a/Source/Randomizer2Core.cpp
+++ b/Source/Randomizer2Core.cpp
@@ -15,9 +15,16 @@ std::vector<Pos> Randomizer2Core::CutInsideEdges(const Puzzle& p, size_t numEdge
 }
 
 std::vector<Pos> Randomizer2Core::CutSymmetricalEdgePairs(const Puzzle& p, size_t numEdges) {
+    Puzzle copy = p;
     assert(p.symmetry != Puzzle::Symmetry::NONE);
     if (p.symmetry == Puzzle::Symmetry::X) {
-        return CutEdgesInternal(p, 0, (p.width-1)/2, 0, p.height, numEdges);
+        if (p.width%4 == 1) { // Puzzle is even, so we need to prevent cutting the centerline
+            for (int y=0; y<p.height; y++) {
+                copy.grid[p.width/2][y].gap = Cell::Gap::FULL;
+            }
+        }
+
+        return CutEdgesInternal(copy, 0, (p.width-1)/2, 0, p.height, numEdges);
     }
     assert(false);
     return {};
@@ -93,10 +100,11 @@ std::vector<Pos> Randomizer2Core::CutEdgesInternal(const Puzzle& p, int xMin, in
 
 void Randomizer2Core::DebugColorGrid(const std::vector<std::vector<int>>& colorGrid) {
 #ifndef NDEBUG
+    static std::string colors = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
     for (int y=0; y<colorGrid[0].size(); y++) {
         std::string row;
         for (int x=0; x<colorGrid.size(); x++) {
-            row += std::to_string(colorGrid[x][y]);
+            row += colors[colorGrid[x][y]];
         }
         row += "\n";
         OutputDebugStringA(row.c_str());
@@ -128,13 +136,10 @@ void Randomizer2Core::FloodFillOutside(const Puzzle& p, std::vector<std::vector<
     FloodFillOutside(p, colorGrid, x-1, y);
 }
 
-/*
-    undefined -> 1 (color of outside) or * (any colored cell) or -1 (edge/intersection not part of any region)
-
-    0 -> {} (this is a special edge case, which I don't need right now)
-    1 -> 0 (uncolored / ready to color)
-    2 -> 
-*/
+// Color key:
+// 0 (default): Uncolored
+// 1: Outside color and separator color
+// 2+: Flood-filled region color
 std::tuple<std::vector<std::vector<int>>, int> Randomizer2Core::CreateColorGrid(const Puzzle& p) {
     std::vector<std::vector<int>> colorGrid;
     colorGrid.resize(p.width);
-- 
cgit 1.4.1