diff options
| -rw-r--r-- | Source/Randomizer2.cpp | 47 | ||||
| -rw-r--r-- | Source/Randomizer2Core.cpp | 38 |
2 files changed, 63 insertions, 22 deletions
| diff --git a/Source/Randomizer2.cpp b/Source/Randomizer2.cpp index b1cdc1f..db90f4c 100644 --- a/Source/Randomizer2.cpp +++ b/Source/Randomizer2.cpp | |||
| @@ -307,15 +307,12 @@ void Randomizer2::RandomizeSymmetry() { | |||
| 307 | Puzzle p; | 307 | Puzzle p; |
| 308 | p.NewGrid(4, 4); | 308 | p.NewGrid(4, 4); |
| 309 | p.symmetry = Puzzle::Symmetry::XY; | 309 | p.symmetry = Puzzle::Symmetry::XY; |
| 310 | p.grid[6][0].start = true; | 310 | p.grid[8][0].start = true; |
| 311 | p.grid[0][6].start = true; | 311 | p.grid[0][8].start = true; |
| 312 | p.grid[4][0].end = Cell::Dir::UP; | 312 | p.grid[0][0].end = Cell::Dir::LEFT; |
| 313 | p.grid[2][6].end = Cell::Dir::DOWN; | 313 | p.grid[8][8].end = Cell::Dir::RIGHT; |
| 314 | |||
| 315 | p.grid[5][0].gap = Cell::Gap::BREAK; | ||
| 316 | p.grid[1][6].gap = Cell::Gap::BREAK; | ||
| 317 | 314 | ||
| 318 | std::vector<Pos> cutEdges = Randomizer2Core::CutSymmetricalEdgePairs(p, 3); | 315 | std::vector<Pos> cutEdges = Randomizer2Core::CutSymmetricalEdgePairs(p, 7); |
| 319 | for (int i=0; i<cutEdges.size(); i++) { | 316 | for (int i=0; i<cutEdges.size(); i++) { |
| 320 | Pos pos = cutEdges[i]; | 317 | Pos pos = cutEdges[i]; |
| 321 | if (i%2 == 0) { | 318 | if (i%2 == 0) { |
| @@ -326,9 +323,39 @@ void Randomizer2::RandomizeSymmetry() { | |||
| 326 | } | 323 | } |
| 327 | } | 324 | } |
| 328 | 325 | ||
| 329 | p.grid[1][6].gap = Cell::Gap::NONE; | 326 | _serializer.WritePuzzle(p, 0x83); |
| 327 | } | ||
| 328 | { // Melting | ||
| 329 | Puzzle p; | ||
| 330 | p.NewGrid(6, 6); | ||
| 331 | p.symmetry = Puzzle::Symmetry::XY; | ||
| 332 | p.grid[12][0].start = true; | ||
| 333 | p.grid[0][12].start = true; | ||
| 334 | p.grid[0][0].end = Cell::Dir::LEFT; | ||
| 335 | p.grid[12][12].end = Cell::Dir::RIGHT; | ||
| 336 | Puzzle q = p; | ||
| 330 | 337 | ||
| 331 | _serializer.WritePuzzle(p, 0x81); | 338 | std::vector<Pos> cutEdges = Randomizer2Core::CutSymmetricalEdgePairs(p, 15); |
| 339 | for (int i=0; i<cutEdges.size(); i++) { | ||
| 340 | Pos pos = cutEdges[i]; | ||
| 341 | Pos sym = p.GetSymmetricalPos(pos.x, pos.y); | ||
| 342 | |||
| 343 | if (i%2 == 0) { | ||
| 344 | p.grid[pos.x][pos.y].gap = Cell::Gap::BREAK; | ||
| 345 | } else { | ||
| 346 | p.grid[sym.x][sym.y].gap = Cell::Gap::BREAK; | ||
| 347 | } | ||
| 348 | |||
| 349 | if (pos.x < sym.x) { | ||
| 350 | q.grid[pos.x][pos.y].gap = Cell::Gap::BREAK; | ||
| 351 | } else { | ||
| 352 | q.grid[sym.x][sym.y].gap = Cell::Gap::BREAK; | ||
| 353 | } | ||
| 354 | } | ||
| 355 | |||
| 356 | _serializer.WritePuzzle(p, 0x84); // Melting 1 | ||
| 357 | _serializer.WritePuzzle(q, 0x82); // Melting 2 | ||
| 358 | _serializer.WritePuzzle(q, 0x343A); // Melting 3 | ||
| 332 | } | 359 | } |
| 333 | } | 360 | } |
| 334 | 361 | ||
| diff --git a/Source/Randomizer2Core.cpp b/Source/Randomizer2Core.cpp index 2a2c6ff..867fa5a 100644 --- a/Source/Randomizer2Core.cpp +++ b/Source/Randomizer2Core.cpp | |||
| @@ -25,17 +25,17 @@ std::vector<Pos> Randomizer2Core::CutSymmetricalEdgePairs(const Puzzle& p, size_ | |||
| 25 | return CutEdgesInternal(copy, 0, p.width, 0, (p.height-1)/2, numEdges); | 25 | return CutEdgesInternal(copy, 0, p.width, 0, (p.height-1)/2, numEdges); |
| 26 | } else { | 26 | } else { |
| 27 | assert(p.symmetry == Puzzle::Symmetry::XY); | 27 | assert(p.symmetry == Puzzle::Symmetry::XY); |
| 28 | if (p.width%4 == 1) { | 28 | int midX = p.width/2; |
| 29 | assert(p.width == 9); | 29 | int midY = p.height/2; |
| 30 | copy.grid[2][3]; | 30 | if (p.width%4 == 1 && p.height%4 == 1) { // For double-even grids, cut around the center |
| 31 | copy.grid[3][4]; | 31 | copy.grid[midX-1][midY].gap = Cell::Gap::FULL; |
| 32 | copy.grid[3][6]; | 32 | copy.grid[midX][midY-1].gap = Cell::Gap::FULL; |
| 33 | copy.grid[4][3]; | 33 | copy.grid[midX][midY+1].gap = Cell::Gap::FULL; |
| 34 | // For odd grids, cut the center out. | 34 | copy.grid[midX+1][midY].gap = Cell::Gap::FULL; |
| 35 | // for (int x=0; x<p.width; x++) { | 35 | } else if (p.width%4 == 1 && p.height%4 == 3) { // For half-even grids, there's only one line to cut |
| 36 | // copy.grid[x][p.height/2].gap = Cell::Gap::FULL; | 36 | copy.grid[midX][midY].gap = Cell::Gap::FULL; |
| 37 | // } | 37 | } else if (p.width%4 == 3 && p.height%4 == 1) { // For half-even grids, there's only one line to cut |
| 38 | 38 | copy.grid[midX][midY].gap = Cell::Gap::FULL; | |
| 39 | } | 39 | } |
| 40 | return CutEdgesInternal(copy, 0, p.width, 0, p.height, numEdges); | 40 | return CutEdgesInternal(copy, 0, p.width, 0, p.height, numEdges); |
| 41 | } | 41 | } |
| @@ -49,7 +49,11 @@ std::vector<Pos> Randomizer2Core::CutEdgesInternal(const Puzzle& p, int xMin, in | |||
| 49 | if (p.grid[x][y].gap != Cell::Gap::NONE) continue; | 49 | if (p.grid[x][y].gap != Cell::Gap::NONE) continue; |
| 50 | if (p.grid[x][y].start) continue; | 50 | if (p.grid[x][y].start) continue; |
| 51 | if (p.grid[x][y].end != Cell::Dir::NONE) continue; | 51 | if (p.grid[x][y].end != Cell::Dir::NONE) continue; |
| 52 | if (p.symmetry == Puzzle::Symmetry::XY && x > y) continue; // Only allow cuts bottom-left of the diagonal | 52 | |
| 53 | if (p.symmetry == Puzzle::Symmetry::XY) { | ||
| 54 | assert(p.width == p.height); // TODO: This solution only supports square rotational symmetry. | ||
| 55 | if (x > y) continue; // Only allow cuts bottom-left of the diagonal | ||
| 56 | } | ||
| 53 | 57 | ||
| 54 | // If the puzzle already has a sequence, don't cut along it. | 58 | // If the puzzle already has a sequence, don't cut along it. |
| 55 | bool inSequence = false; | 59 | bool inSequence = false; |
| @@ -63,6 +67,16 @@ std::vector<Pos> Randomizer2Core::CutEdgesInternal(const Puzzle& p, int xMin, in | |||
| 63 | auto [colorGrid, numColors] = CreateColorGrid(p); | 67 | auto [colorGrid, numColors] = CreateColorGrid(p); |
| 64 | assert(numEdges <= numColors); | 68 | assert(numEdges <= numColors); |
| 65 | 69 | ||
| 70 | // @Hack... sort of. I couldn't think of a better way to do this. | ||
| 71 | if (p.symmetry == Puzzle::Symmetry::XY) { | ||
| 72 | // Recolor the diagonal so that opposite cells share a color. This is because we're only cutting along half their edges, | ||
| 73 | // so they are in fact two sides of the same cell. | ||
| 74 | for (int x=1; x<p.width/2; x+=2) { | ||
| 75 | assert(p.width == p.height); // TODO: This solution only supports square rotational symmetry. | ||
| 76 | colorGrid[x][x] = colorGrid[p.width-x-1][p.width-x-1]; | ||
| 77 | } | ||
| 78 | } | ||
| 79 | |||
| 66 | std::vector<Pos> cutEdges; | 80 | std::vector<Pos> cutEdges; |
| 67 | for (int i=0; i<numEdges; i++) { | 81 | for (int i=0; i<numEdges; i++) { |
| 68 | while (edges.size() > 0) { | 82 | while (edges.size() > 0) { |
