From c60df0e75e63f488d94fd744ad70df8124dc7724 Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Sat, 21 Aug 2021 17:12:29 -0400 Subject: Souped up the UI --- Source/Randomizer2.cpp | 644 --------------------------------------------- Source/Randomizer2.h | 19 -- Source/Randomizer2Core.cpp | 203 -------------- Source/Randomizer2Core.h | 17 -- Source/Source.vcxproj | 4 - 5 files changed, 887 deletions(-) delete mode 100644 Source/Randomizer2.cpp delete mode 100644 Source/Randomizer2.h delete mode 100644 Source/Randomizer2Core.cpp delete mode 100644 Source/Randomizer2Core.h (limited to 'Source') diff --git a/Source/Randomizer2.cpp b/Source/Randomizer2.cpp deleted file mode 100644 index 421ce69..0000000 --- a/Source/Randomizer2.cpp +++ /dev/null @@ -1,644 +0,0 @@ -#include "pch.h" -#include "Randomizer2.h" -#include "PuzzleSerializer.h" -#include "Randomizer2Core.h" -#include "Random.h" -#include "Solver.h" -#include "Windows.h" - -Randomizer2::Randomizer2(const PuzzleSerializer& serializer) : _serializer(serializer) { -} - -void Randomizer2::Randomize() { - // RandomizeTutorial(); - // RandomizeGlassFactory(); - RandomizeSymmetryIsland(); - // RandomizeKeep(); -} - -void Randomizer2::RandomizeTutorial() { - { // Far center - Puzzle p; - p.NewGrid(4, 4); - p.grid[0][8].start = true; - p.grid[8][0].end = Cell::Dir::UP; - - for (Pos pos : Randomizer2Core::CutEdges(p, 14)) { - p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; - } - _serializer.WritePuzzle(p, 0x293); - } - - { // Center left - Puzzle p; - p.NewGrid(6, 6); - - int x = Random::RandInt(0, (p.width-1)/2)*2; - int y = Random::RandInt(0, (p.height-1)/2)*2; - int rng = Random::RandInt(1, 4); - if (rng == 1) p.grid[x][0].end = Cell::Dir::UP; - else if (rng == 2) p.grid[x][p.height-1].end = Cell::Dir::DOWN; - else if (rng == 3) p.grid[0][y].end = Cell::Dir::LEFT; - else if (rng == 4) p.grid[p.width-1][y].end = Cell::Dir::RIGHT; - - // [4/6/8][4/6/8] - p.grid[Random::RandInt(0, 2)*2 + 4][Random::RandInt(0, 2)*2 + 4].start = true; - - for (Pos pos : Randomizer2Core::CutEdges(p, 35)) { - p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; - } - - _serializer.WritePuzzle(p, 0x295); - } - - { // Far left - Puzzle p; - p.NewGrid(10, 10); - - p.grid[0][20].start = true; - p.grid[20][0].end = Cell::Dir::RIGHT; - - for (Pos pos : Randomizer2Core::CutEdges(p, 96)) { - p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; - } - _serializer.WritePuzzle(p, 0x2C2); - } - - { // Back left - Puzzle p; - p.NewGrid(6, 6); - - p.grid[0][12].start = true; - p.grid[12][0].end = Cell::Dir::RIGHT; - p.grid[12][12].end = Cell::Dir::RIGHT; - - for (Pos pos : Randomizer2Core::CutEdges(p, 27)) { - p.grid[pos.x][pos.y].gap = Cell::Gap::BREAK; - } - _serializer.WritePuzzle(p, 0xA3B5); - } - - { // Back right - Puzzle p; - p.NewGrid(6, 6); - - p.grid[0][12].start = true; - p.grid[12][12].start = true; - p.grid[6][0].end = Cell::Dir::UP; - - // @Cleanup - std::vector cuts; - bool toTheRight; - // Start by generating a cut line, to ensure one of the two startpoints is inaccessible - int x, y; - switch (Random::RandInt(1, 4)) { - case 1: - x = 1; y = 1; - toTheRight = true; - cuts.emplace_back(0, 1); - break; - case 2: - x = 1; y = 1; - toTheRight = true; - cuts.emplace_back(1, 0); - break; - case 3: - x = 11; y = 1; - toTheRight = false; - cuts.emplace_back(12, 1); - break; - case 4: - x = 11; y = 1; - toTheRight = false; - cuts.emplace_back(11, 0); - break; - } - while (y < p.height) { // The final cut will push y below the bottom of the puzzle, which means we're done. - switch (Random::RandInt(1, 4)) { - case 1: // Go right - if (x < p.width-2) { - cuts.emplace_back(x+1, y); - x += 2; - } - break; - case 2: // Go left - if (x > 1) { - cuts.emplace_back(x-1, y); - x -= 2; - } - break; - case 3: - case 4: // Go down (biased x2) - cuts.emplace_back(x, y+1); - y += 2; - break; - } - } - - for (Pos pos : cuts) { - p.grid[pos.x][pos.y].gap = Cell::Gap::BREAK; - } - - for (Pos pos : Randomizer2Core::CutEdges(p, 30 - cuts.size())) { - p.grid[pos.x][pos.y].gap = Cell::Gap::BREAK; - } - _serializer.WritePuzzle(p, 0xA3B2); - } -} - -void Randomizer2::RandomizeGlassFactory() { - { // Back wall 1 - Puzzle p; - p.NewGrid(3, 3); - p.symmetry = Puzzle::Symmetry::X; - p.grid[0][6].start = true; - p.grid[6][6].start = true; - p.grid[2][0].end = Cell::Dir::UP; - p.grid[4][0].end = Cell::Dir::UP; - - std::vector cutEdges = Randomizer2Core::CutSymmetricalEdgePairs(p, 2); - for (Pos pos : cutEdges) { - Pos sym = p.GetSymmetricalPos(pos.x, pos.y); - p.grid[pos.x][pos.y].gap = Cell::Gap::BREAK; - p.grid[sym.x][sym.y].gap = Cell::Gap::BREAK; - } - _serializer.WritePuzzle(p, 0x86); - } - { // Back wall 2 - 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; - std::vector cutEdges = Randomizer2Core::CutSymmetricalEdgePairs(p, 4); - for (int i=0; i cutEdges = Randomizer2Core::CutSymmetricalEdgePairs(p, 10); - for (int i=0; i cutEdges = Randomizer2Core::CutSymmetricalEdgePairs(p, 15); - for (int i=0; i cutEdges = Randomizer2Core::CutSymmetricalEdgePairs(p, 3); - for (int i=0; i cutEdges = Randomizer2Core::CutSymmetricalEdgePairs(p, 7); - for (int i=0; i cutEdges = Randomizer2Core::CutSymmetricalEdgePairs(p, 15); - for (int i=0; i corners; - std::vector cells; - std::vector edges; - for (int x=0; x dots = Random::SelectFromSet(edges, 4); - for (Pos pos : dots) p.grid[pos.x][pos.y].dot = Cell::Dot::BLACK; - - auto solutions = Solver::Solve(p); - if (solutions.size() > 0 && solutions.size() < 10) break; - - for (Pos pos : dots) p.grid[pos.x][pos.y].dot = Cell::Dot::NONE; - } - - _serializer.WritePuzzle(p, 0xB0); - } - - { // Dots 1 - Puzzle p; - p.NewGrid(3, 3); - p.symmetry = Puzzle::Symmetry::Y; - p.grid[0][2].start = true; - p.grid[0][4].start = true; - p.grid[6][2].end = Cell::Dir::RIGHT; - p.grid[6][4].end = Cell::Dir::RIGHT; - - std::vector corners; - std::vector cells; - std::vector edges; - for (int x=0; x dots; - for (int j=0;; j++) { - dots = Random::SelectFromSet(edges, 3); - for (Pos pos : dots) p.grid[pos.x][pos.y].dot = Cell::Dot::BLACK; - - auto solutions = Solver::Solve(p); - if (solutions.size() == 2) break; - - for (Pos pos : dots) p.grid[pos.x][pos.y].dot = Cell::Dot::NONE; - } - - for (Pos pos : dots) { - Pos sym = p.GetSymmetricalPos(pos.x, pos.y); - p.grid[sym.x][sym.y].dot = Cell::Dot::BLACK; - } - - _serializer.WritePuzzle(p, 0x22); - } - { // Dots 2 - Puzzle p; - p.NewGrid(3, 3); - p.symmetry = Puzzle::Symmetry::Y; - p.grid[0][2].start = true; - p.grid[0][4].start = true; - p.grid[6][2].end = Cell::Dir::RIGHT; - p.grid[6][4].end = Cell::Dir::RIGHT; - - std::vector corners; - std::vector cells; - std::vector edges; - for (int x=0; x dots; - for (int j=0;; j++) { - dots = Random::SelectFromSet(edges, 3); - for (Pos pos : dots) p.grid[pos.x][pos.y].dot = Cell::Dot::BLACK; - - auto solutions = Solver::Solve(p); - if (solutions.size() == 2) break; - - for (Pos pos : dots) p.grid[pos.x][pos.y].dot = Cell::Dot::NONE; - } - - Pos pos = dots[1]; - Pos sym = p.GetSymmetricalPos(pos.x, pos.y); - p.grid[pos.x][pos.y].dot = Cell::Dot::NONE; - p.grid[sym.x][sym.y].dot = Cell::Dot::BLACK; - - _serializer.WritePuzzle(p, 0x23); - } -} - -void Randomizer2::RandomizeKeep() { - { // Hedges 1 - Puzzle p; - p.NewGrid(4, 4); - - p.grid[2][1].gap = Cell::Gap::FULL; - p.grid[4][1].gap = Cell::Gap::FULL; - p.grid[6][1].gap = Cell::Gap::FULL; - p.grid[3][2].gap = Cell::Gap::FULL; - p.grid[5][2].gap = Cell::Gap::FULL; - p.grid[8][3].gap = Cell::Gap::FULL; - p.grid[2][5].gap = Cell::Gap::FULL; - p.grid[6][5].gap = Cell::Gap::FULL; - p.grid[7][6].gap = Cell::Gap::FULL; - p.grid[2][7].gap = Cell::Gap::FULL; - p.grid[4][7].gap = Cell::Gap::FULL; - - p.grid[4][8].start = true; - p.grid[6][0].end = Cell::Dir::UP; - - std::vector cutEdges = Randomizer2Core::CutInsideEdges(p, 5); - Puzzle copy = p; - std::vector gates = {0x00344, 0x00488, 0x00489, 0x00495, 0x00496}; - for (int i=0; i cutEdges = Randomizer2Core::CutInsideEdges(p, 7); - for (Pos pos : cutEdges) { - p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; - } - auto solution = GetUniqueSolution(p); - - Puzzle q; - q.NewGrid(4, 4); - q.grid[0][8].start = true; - q.grid[8][0].end = Cell::Dir::RIGHT; - q.sequence = solution.sequence; - for (Pos pos : cutEdges) { - q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; - } - // Cut to 6 of 9 additional edges - for (Pos pos : Randomizer2Core::CutInsideEdges(q, 6)) { - q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; - } - _serializer.WritePuzzle(q, 0x19DC); - } - - { // Hedges 3 [WIP] - Puzzle p; - p.NewGrid(4, 4); - - p.grid[2][1].gap = Cell::Gap::FULL; - p.grid[5][2].gap = Cell::Gap::FULL; - p.grid[7][2].gap = Cell::Gap::FULL; - p.grid[4][3].gap = Cell::Gap::FULL; - p.grid[1][4].gap = Cell::Gap::FULL; - p.grid[6][5].gap = Cell::Gap::FULL; - p.grid[1][6].gap = Cell::Gap::FULL; - p.grid[3][6].gap = Cell::Gap::FULL; - p.grid[6][7].gap = Cell::Gap::FULL; - - p.grid[0][8].start = true; - p.grid[8][2].end = Cell::Dir::RIGHT; - - std::vector cutEdges = Randomizer2Core::CutInsideEdges(p, 7); - for (Pos pos : cutEdges) { - p.grid[pos.x][pos.y].gap = Cell::Gap::BREAK; - } - - std::vector pebbleMarkers = {0x034a9, 0x034b1, 0x034be, 0x034c4}; - - // _serializer.WritePuzzle(p, 0x19E7); - } - - { // Hedges 4 - Puzzle p; - p.NewGrid(4, 4); - - p.grid[3][0].gap = Cell::Gap::FULL; - p.grid[4][1].gap = Cell::Gap::FULL; - p.grid[8][1].gap = Cell::Gap::FULL; - p.grid[1][2].gap = Cell::Gap::FULL; - p.grid[4][3].gap = Cell::Gap::FULL; - p.grid[8][3].gap = Cell::Gap::FULL; - p.grid[1][4].gap = Cell::Gap::FULL; - p.grid[5][4].gap = Cell::Gap::FULL; - p.grid[2][5].gap = Cell::Gap::FULL; - p.grid[6][5].gap = Cell::Gap::FULL; - p.grid[3][6].gap = Cell::Gap::FULL; - p.grid[0][7].gap = Cell::Gap::FULL; - p.grid[8][7].gap = Cell::Gap::FULL; - p.grid[5][8].gap = Cell::Gap::FULL; - - p.grid[0][8].start = true; - p.grid[4][0].end = Cell::Dir::UP; - - std::vector cutEdges = Randomizer2Core::CutInsideEdges(p, 2); - for (Pos pos : cutEdges) { - p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; - } - auto solution = GetUniqueSolution(p); - - Puzzle q; - q.NewGrid(4, 4); - q.grid[0][8].start = true; - q.grid[4][0].end = Cell::Dir::UP; - q.sequence = solution.sequence; - for (Pos pos : cutEdges) { - q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; - } - for (Pos pos : Randomizer2Core::CutInsideEdges(q, 7)) { - q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; - } - _serializer.WritePuzzle(q, 0x1A0F); - } -} - -Puzzle Randomizer2::GetUniqueSolution(Puzzle& p) { - auto solutions = Solver::Solve(p); - assert(solutions.size() == 1); - return solutions[0]; -} - -void Randomizer2::SetGate(int panel, int X, int Y) { - float x, y, z, w; - if (X%2 == 0 && Y%2 == 1) { // Horizontal - x = -1.49f * X + 0.22f * Y + 66.58f; - y = 0.275f * X + 1.6f * Y + 108.4f; - z = -.77f; - w = .63f; - } else { // Vertical - assert(X%2 == 1 && Y%2 == 0); - x = -1.6f * X + 0.35f * Y + 66.5f; - y = 0.25f * X + 1.6f * Y + 108.55f; - z = -0.1f; - w = 1.0f; - } - - SetPos(panel, x, y, 19.2f); - // _memory->WriteEntityData(panel, ORIENTATION, {0.0f, 0.0f, z, w}); -} - -void Randomizer2::SetPos(int panel, float x, float y, float z) { - // _memory->WriteEntityData(panel, POSITION, {x, y, z}); -} \ No newline at end of file diff --git a/Source/Randomizer2.h b/Source/Randomizer2.h deleted file mode 100644 index a2b5ebd..0000000 --- a/Source/Randomizer2.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include "PuzzleSerializer.h" - -class Randomizer2 { -public: - Randomizer2(const PuzzleSerializer& serializer); - void Randomize(); - void RandomizeTutorial(); - void RandomizeGlassFactory(); - void RandomizeSymmetryIsland(); - void RandomizeKeep(); - -private: - Puzzle GetUniqueSolution(Puzzle& p); - void SetGate(int panel, int X, int Y); - void SetPos(int panel, float x, float y, float z); - - PuzzleSerializer _serializer; -}; diff --git a/Source/Randomizer2Core.cpp b/Source/Randomizer2Core.cpp deleted file mode 100644 index 867fa5a..0000000 --- a/Source/Randomizer2Core.cpp +++ /dev/null @@ -1,203 +0,0 @@ -#include "pch.h" -#include "Randomizer2Core.h" -#include "Random.h" - -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; - // Prevent cuts from landing on the midline - if (p.symmetry == Puzzle::Symmetry::X) { - 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 y) continue; // Only allow cuts bottom-left of the diagonal - } - - // If the puzzle already has a sequence, don't cut along it. - bool inSequence = false; - for (Pos pos : p.sequence) inSequence |= (pos.x == x && pos.y == y); - if (inSequence) continue; - edges.emplace_back(x, y); - } - } - assert(numEdges <= edges.size()); - - auto [colorGrid, numColors] = CreateColorGrid(p); - assert(numEdges <= numColors); - - // @Hack... sort of. I couldn't think of a better way to do this. - if (p.symmetry == Puzzle::Symmetry::XY) { - // Recolor the diagonal so that opposite cells share a color. This is because we're only cutting along half their edges, - // so they are in fact two sides of the same cell. - for (int x=1; x cutEdges; - for (int i=0; i 0) { - int edge = Random::RandInt(0, static_cast(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 CutEdges(const Puzzle& p, size_t numEdges); - static std::vector CutInsideEdges(const Puzzle& p, size_t numEdges); - static std::vector CutSymmetricalEdgePairs(const Puzzle& p, size_t numEdges); - -private: - static std::vector CutEdgesInternal(const Puzzle& p, int xMin, int xMax, int yMin, int yMax, size_t numEdges); - static void DebugColorGrid(const std::vector>& colorGrid); - static void FloodFill(const Puzzle& p, std::vector>& colorGrid, int color, int x, int y); - static void FloodFillOutside(const Puzzle& p, std::vector>& colorGrid, int x, int y); - static std::tuple>, int> CreateColorGrid(const Puzzle& p); -}; - diff --git a/Source/Source.vcxproj b/Source/Source.vcxproj index 1cfb484..8d6104c 100644 --- a/Source/Source.vcxproj +++ b/Source/Source.vcxproj @@ -172,8 +172,6 @@ - - @@ -190,8 +188,6 @@ - - -- cgit 1.4.1