#include "Randomizer2Core.h" #include "Puzzle.h" #include "Random.h" #include #include #include std::vector Randomizer2Core::CutEdges(const Puzzle& p, size_t numEdges) { return CutEdgesInternal(p, 0, p.width, 0, p.height, numEdges); } std::vector Randomizer2Core::CutInsideEdges(const Puzzle& p, size_t numEdges) { return CutEdgesInternal(p, 1, p.width-1, 1, p.height-1, numEdges); } std::vector Randomizer2Core::CutSymmetricalEdgePairs(const Puzzle& p, size_t numEdges) { Puzzle copy = p; assert(p.symmetry != Puzzle::Symmetry::NONE); if (p.symmetry == Puzzle::Symmetry::X) { if (p.width%4 == 1) { // Puzzle is even, so we need to prevent cutting the centerline for (int y=0; y Randomizer2Core::CutEdgesInternal(const Puzzle& p, int xMin, int xMax, int yMin, int yMax, size_t numEdges) { std::vector edges; for (int x=xMin; x cutEdges; for (int i=0; i(edges.size() - 1)); Pos pos = edges[edge]; edges.erase(edges.begin() + edge); int color1 = 0; int color2 = 0; if (pos.x%2 == 0 && pos.y%2 == 1) { // Vertical if (pos.x > 0) color1 = colorGrid[pos.x-1][pos.y]; else color1 = 1; if (pos.x < p.width - 1) color2 = colorGrid[pos.x+1][pos.y]; else color2 = 1; } else { // Horizontal assert(pos.x%2 == 1 && pos.y%2 == 0); if (pos.y > 0) color1 = colorGrid[pos.x][pos.y-1]; else color1 = 1; if (pos.y < p.height - 1) color2 = colorGrid[pos.x][pos.y+1]; else color2 = 1; } // Enforce color1 < color2 if (color1 > color2) std::swap(color1, color2); // Colors mismatch, valid cut if (color1 != color2) { // @Performance... have a lookup table instead? for (int x=0; x #endif void Randomizer2Core::DebugColorGrid(const std::vector>& colorGrid) { #ifndef NDEBUG static std::string colors = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; for (int y=0; y>& colorGrid, int color, int x, int y) { if (!p.SafeCell(x, y)) return; if (colorGrid[x][y] != 0) return; // Already processed. colorGrid[x][y] = color; FloodFill(p, colorGrid, color, x, y+1); FloodFill(p, colorGrid, color, x, y-1); FloodFill(p, colorGrid, color, x+1, y); FloodFill(p, colorGrid, color, x-1, y); } void Randomizer2Core::FloodFillOutside(const Puzzle& p, std::vector>& colorGrid, int x, int y) { if (!p.SafeCell(x, y)) return; if (colorGrid[x][y] != 0) return; // Already processed. if (x%2 != y%2 && p.grid[x][y].gap == Cell::Gap::NONE) return; // Only flood-fill through gaps colorGrid[x][y] = 1; // Outside color FloodFillOutside(p, colorGrid, x, y+1); FloodFillOutside(p, colorGrid, x, y-1); FloodFillOutside(p, colorGrid, x+1, y); FloodFillOutside(p, colorGrid, x-1, y); } // Color key: // 0 (default): Uncolored // 1: Outside color and separator color // 2+: Flood-filled region color std::tuple>, int> Randomizer2Core::CreateColorGrid(const Puzzle& p) { std::vector> colorGrid; colorGrid.resize(p.width); for (int x=0; x