diff options
Diffstat (limited to 'Source')
-rw-r--r-- | Source/PuzzleSerializer.cpp | 20 | ||||
-rw-r--r-- | Source/Randomizer2.cpp | 19 | ||||
-rw-r--r-- | 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) { | |||
485 | reflectionData[location] = symLocation; | 485 | reflectionData[location] = symLocation; |
486 | reflectionData[symLocation] = location; | 486 | reflectionData[symLocation] = location; |
487 | if (p.grid[x][y].end != Cell::Dir::NONE) { | 487 | if (p.grid[x][y].end != Cell::Dir::NONE) { |
488 | // Rely on symmetry to set the other pair | ||
489 | location = extra_xy_to_loc(p, x, y); | 488 | location = extra_xy_to_loc(p, x, y); |
490 | Pos sym = p.GetSymmetricalPos(x, y); | 489 | Pos sym = p.GetSymmetricalPos(x, y); |
491 | symLocation = extra_xy_to_loc(p, sym.x, sym.y); | 490 | symLocation = extra_xy_to_loc(p, sym.x, sym.y); |
@@ -503,11 +502,20 @@ void PuzzleSerializer::WriteSymmetry(const Puzzle& p, int id) { | |||
503 | int location = extra_xy_to_loc(p, x, y); | 502 | int location = extra_xy_to_loc(p, x, y); |
504 | int symLocation = extra_xy_to_loc(p, sym.x, sym.y); | 503 | int symLocation = extra_xy_to_loc(p, sym.x, sym.y); |
505 | // Each gap results in two intersections, @Assume they're written consecutively | 504 | // Each gap results in two intersections, @Assume they're written consecutively |
506 | // Rely on symmetry to set the other pairs | 505 | |
507 | reflectionData[location] = symLocation; | 506 | if ((x%2 != 0 && p.symmetry & Puzzle::Symmetry::X) || |
508 | reflectionData[location-1] = symLocation-1; | 507 | (y%2 != 0 && p.symmetry & Puzzle::Symmetry::Y)) { |
509 | reflectionData[symLocation] = location; | 508 | // Write data inverted, because it's being reflected |
510 | reflectionData[symLocation-1] = location-1; | 509 | reflectionData[location] = symLocation-1; |
510 | reflectionData[location-1] = symLocation; | ||
511 | reflectionData[symLocation] = location-1; | ||
512 | reflectionData[symLocation-1] = location; | ||
513 | } else { // Write data normally | ||
514 | reflectionData[location] = symLocation; | ||
515 | reflectionData[location-1] = symLocation-1; | ||
516 | reflectionData[symLocation] = location; | ||
517 | reflectionData[symLocation-1] = location-1; | ||
518 | } | ||
511 | } | 519 | } |
512 | } | 520 | } |
513 | 521 | ||
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() { | |||
177 | Puzzle p; | 177 | Puzzle p; |
178 | p.NewGrid(4, 4); | 178 | p.NewGrid(4, 4); |
179 | p.symmetry = Puzzle::Symmetry::X; | 179 | p.symmetry = Puzzle::Symmetry::X; |
180 | 180 | p.grid[0][8].start = true; | |
181 | p.grid[8][8].start = true; | ||
182 | p.grid[2][0].end = Cell::Dir::UP; | ||
183 | p.grid[6][0].end = Cell::Dir::UP; | ||
184 | // @Bug: This can still make the puzzle unsolvable, if it leaves the centerline free -- even though two lines can't pass through the centerline. | ||
185 | // ^ Try seed = 13710 | ||
186 | std::vector<Pos> cutEdges = Randomizer2Core::CutSymmetricalEdgePairs(p, 4); | ||
187 | for (int i=0; i<2; i++) { | ||
188 | Pos pos = cutEdges[i]; | ||
189 | p.grid[pos.x][pos.y].gap = Cell::Gap::BREAK; | ||
190 | } | ||
191 | for (int i=2; i<4; i++) { | ||
192 | Pos pos = cutEdges[i]; | ||
193 | Pos sym = p.GetSymmetricalPos(pos.x, pos.y); | ||
194 | p.grid[sym.x][sym.y].gap = Cell::Gap::BREAK; | ||
195 | } | ||
196 | |||
197 | _serializer.WritePuzzle(p, 0x87); | ||
181 | } | 198 | } |
182 | } | 199 | } |
183 | 200 | ||
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 | |||
15 | } | 15 | } |
16 | 16 | ||
17 | std::vector<Pos> Randomizer2Core::CutSymmetricalEdgePairs(const Puzzle& p, size_t numEdges) { | 17 | std::vector<Pos> Randomizer2Core::CutSymmetricalEdgePairs(const Puzzle& p, size_t numEdges) { |
18 | Puzzle copy = p; | ||
18 | assert(p.symmetry != Puzzle::Symmetry::NONE); | 19 | assert(p.symmetry != Puzzle::Symmetry::NONE); |
19 | if (p.symmetry == Puzzle::Symmetry::X) { | 20 | if (p.symmetry == Puzzle::Symmetry::X) { |
20 | return CutEdgesInternal(p, 0, (p.width-1)/2, 0, p.height, numEdges); | 21 | if (p.width%4 == 1) { // Puzzle is even, so we need to prevent cutting the centerline |
22 | for (int y=0; y<p.height; y++) { | ||
23 | copy.grid[p.width/2][y].gap = Cell::Gap::FULL; | ||
24 | } | ||
25 | } | ||
26 | |||
27 | return CutEdgesInternal(copy, 0, (p.width-1)/2, 0, p.height, numEdges); | ||
21 | } | 28 | } |
22 | assert(false); | 29 | assert(false); |
23 | return {}; | 30 | return {}; |
@@ -93,10 +100,11 @@ std::vector<Pos> Randomizer2Core::CutEdgesInternal(const Puzzle& p, int xMin, in | |||
93 | 100 | ||
94 | void Randomizer2Core::DebugColorGrid(const std::vector<std::vector<int>>& colorGrid) { | 101 | void Randomizer2Core::DebugColorGrid(const std::vector<std::vector<int>>& colorGrid) { |
95 | #ifndef NDEBUG | 102 | #ifndef NDEBUG |
103 | static std::string colors = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | ||
96 | for (int y=0; y<colorGrid[0].size(); y++) { | 104 | for (int y=0; y<colorGrid[0].size(); y++) { |
97 | std::string row; | 105 | std::string row; |
98 | for (int x=0; x<colorGrid.size(); x++) { | 106 | for (int x=0; x<colorGrid.size(); x++) { |
99 | row += std::to_string(colorGrid[x][y]); | 107 | row += colors[colorGrid[x][y]]; |
100 | } | 108 | } |
101 | row += "\n"; | 109 | row += "\n"; |
102 | OutputDebugStringA(row.c_str()); | 110 | OutputDebugStringA(row.c_str()); |
@@ -128,13 +136,10 @@ void Randomizer2Core::FloodFillOutside(const Puzzle& p, std::vector<std::vector< | |||
128 | FloodFillOutside(p, colorGrid, x-1, y); | 136 | FloodFillOutside(p, colorGrid, x-1, y); |
129 | } | 137 | } |
130 | 138 | ||
131 | /* | 139 | // Color key: |
132 | undefined -> 1 (color of outside) or * (any colored cell) or -1 (edge/intersection not part of any region) | 140 | // 0 (default): Uncolored |
133 | 141 | // 1: Outside color and separator color | |
134 | 0 -> {} (this is a special edge case, which I don't need right now) | 142 | // 2+: Flood-filled region color |
135 | 1 -> 0 (uncolored / ready to color) | ||
136 | 2 -> | ||
137 | */ | ||
138 | std::tuple<std::vector<std::vector<int>>, int> Randomizer2Core::CreateColorGrid(const Puzzle& p) { | 143 | std::tuple<std::vector<std::vector<int>>, int> Randomizer2Core::CreateColorGrid(const Puzzle& p) { |
139 | std::vector<std::vector<int>> colorGrid; | 144 | std::vector<std::vector<int>> colorGrid; |
140 | colorGrid.resize(p.width); | 145 | colorGrid.resize(p.width); |