diff options
| author | jbzdarkid <jbzdarkid@gmail.com> | 2019-11-09 14:23:42 -0800 |
|---|---|---|
| committer | jbzdarkid <jbzdarkid@gmail.com> | 2019-11-09 14:23:42 -0800 |
| commit | 98db209c9008492baec6bb482b047d386fbdd42b (patch) | |
| tree | 9f4a932ed1ff2367a98fe02908fee4c884a2d4ed /Source | |
| parent | 36be1ed32ac9a554f0b11fcc13b5699e717b81f2 (diff) | |
| download | witness-tutorializer-98db209c9008492baec6bb482b047d386fbdd42b.tar.gz witness-tutorializer-98db209c9008492baec6bb482b047d386fbdd42b.tar.bz2 witness-tutorializer-98db209c9008492baec6bb482b047d386fbdd42b.zip | |
One down, 522 to go.
Diffstat (limited to 'Source')
| -rw-r--r-- | Source/Puzzle.cpp | 12 | ||||
| -rw-r--r-- | Source/Puzzle.h | 28 | ||||
| -rw-r--r-- | Source/Randomizer2.cpp | 104 | ||||
| -rw-r--r-- | Source/Randomizer2.h | 12 | ||||
| -rw-r--r-- | Source/Solver.h | 2 | ||||
| -rw-r--r-- | Source/Source.vcxproj | 2 | ||||
| -rw-r--r-- | Source/Validator.h | 2 |
7 files changed, 147 insertions, 15 deletions
| diff --git a/Source/Puzzle.cpp b/Source/Puzzle.cpp index ee4c2e8..cc552d3 100644 --- a/Source/Puzzle.cpp +++ b/Source/Puzzle.cpp | |||
| @@ -7,16 +7,14 @@ | |||
| 7 | PuzzleSerializer::PuzzleSerializer(const std::shared_ptr<Memory>& memory) : _memory(memory) {} | 7 | PuzzleSerializer::PuzzleSerializer(const std::shared_ptr<Memory>& memory) : _memory(memory) {} |
| 8 | 8 | ||
| 9 | Puzzle PuzzleSerializer::ReadPuzzle(int id) { | 9 | Puzzle PuzzleSerializer::ReadPuzzle(int id) { |
| 10 | Puzzle p; | 10 | int width = 2 * _memory->ReadPanelData<int>(id, GRID_SIZE_X, 1)[0] - 1; |
| 11 | p.width = 2 * _memory->ReadPanelData<int>(id, GRID_SIZE_X, 1)[0] - 1; | 11 | int height = 2 * _memory->ReadPanelData<int>(id, GRID_SIZE_Y, 1)[0] - 1; |
| 12 | p.height = 2 * _memory->ReadPanelData<int>(id, GRID_SIZE_Y, 1)[0] - 1; | 12 | if (width < 0 || height < 0) return Puzzle(); // @Error: Grid size should be always positive? Looks like the starting panels break this rule, though. |
| 13 | if (p.width < 0 || p.height < 0) return p; // @Error: Grid size should be always positive? Looks like the starting panels break this rule, though. | ||
| 14 | p.grid.resize(p.width); | ||
| 15 | for (auto& row : p.grid) row.resize(p.height); | ||
| 16 | 13 | ||
| 14 | Puzzle p; | ||
| 15 | p.NewGrid(width, height); | ||
| 17 | ReadIntersections(p, id); | 16 | ReadIntersections(p, id); |
| 18 | ReadDecorations(p, id); | 17 | ReadDecorations(p, id); |
| 19 | |||
| 20 | return p; | 18 | return p; |
| 21 | } | 19 | } |
| 22 | 20 | ||
| diff --git a/Source/Puzzle.h b/Source/Puzzle.h index 7a98a78..94cb4b0 100644 --- a/Source/Puzzle.h +++ b/Source/Puzzle.h | |||
| @@ -37,7 +37,6 @@ struct Decoration { | |||
| 37 | int count = 0; | 37 | int count = 0; |
| 38 | }; | 38 | }; |
| 39 | 39 | ||
| 40 | |||
| 41 | struct Cell { | 40 | struct Cell { |
| 42 | inline static Cell Undefined() { | 41 | inline static Cell Undefined() { |
| 43 | Cell c; | 42 | Cell c; |
| @@ -63,7 +62,9 @@ struct Cell { | |||
| 63 | struct Negation {}; | 62 | struct Negation {}; |
| 64 | struct Pos {int x; int y;}; | 63 | struct Pos {int x; int y;}; |
| 65 | 64 | ||
| 66 | struct Puzzle { | 65 | #include <cassert> // TODO: Move this + impl to cpp |
| 66 | class Puzzle { | ||
| 67 | public: | ||
| 67 | int16_t height; | 68 | int16_t height; |
| 68 | int16_t width; | 69 | int16_t width; |
| 69 | bool hasDecorations = false; | 70 | bool hasDecorations = false; |
| @@ -72,6 +73,10 @@ struct Puzzle { | |||
| 72 | Symmetry sym = Symmetry::NONE; | 73 | Symmetry sym = Symmetry::NONE; |
| 73 | bool pillar = false; | 74 | bool pillar = false; |
| 74 | 75 | ||
| 76 | bool valid; | ||
| 77 | std::vector<Negation> negations; | ||
| 78 | std::vector<Pos> invalidElements; | ||
| 79 | |||
| 75 | inline Cell GetCell(int x, int y) const { | 80 | inline Cell GetCell(int x, int y) const { |
| 76 | x = Mod(x); | 81 | x = Mod(x); |
| 77 | if (!SafeCell(x, y)) return Cell::Undefined(); | 82 | if (!SafeCell(x, y)) return Cell::Undefined(); |
| @@ -80,13 +85,24 @@ struct Puzzle { | |||
| 80 | inline Cell::Color GetLine(int x, int y) const { | 85 | inline Cell::Color GetLine(int x, int y) const { |
| 81 | return grid[x][y].color; | 86 | return grid[x][y].color; |
| 82 | } | 87 | } |
| 88 | inline void NewGrid(int newWidth, int newHeight) { | ||
| 89 | if (newWidth == 0) { | ||
| 90 | assert(false); | ||
| 91 | newWidth = width; | ||
| 92 | newHeight = height; | ||
| 93 | } else { | ||
| 94 | // @Cleanup! This should be in the ctor... | ||
| 95 | width = 2*newWidth + 1; | ||
| 96 | height = 2*newHeight + 1; | ||
| 97 | } | ||
| 98 | grid.clear(); | ||
| 99 | grid.resize(width); | ||
| 100 | for (int x=0; x<width; x++) grid[x].resize(height); | ||
| 101 | } | ||
| 102 | |||
| 83 | // @TODO: | 103 | // @TODO: |
| 84 | Pos GetSymmetricalPos(int x, int y); | 104 | Pos GetSymmetricalPos(int x, int y); |
| 85 | 105 | ||
| 86 | bool valid; | ||
| 87 | std::vector<Negation> negations; | ||
| 88 | std::vector<Pos> invalidElements; | ||
| 89 | |||
| 90 | // private: | 106 | // private: |
| 91 | std::vector<std::vector<Cell>> grid; | 107 | std::vector<std::vector<Cell>> grid; |
| 92 | 108 | ||
| diff --git a/Source/Randomizer2.cpp b/Source/Randomizer2.cpp new file mode 100644 index 0000000..fcfec9a --- /dev/null +++ b/Source/Randomizer2.cpp | |||
| @@ -0,0 +1,104 @@ | |||
| 1 | #include "Randomizer2.h" | ||
| 2 | #include "Puzzle.h" | ||
| 3 | #include "Random.h" | ||
| 4 | #include "Solver.h" | ||
| 5 | |||
| 6 | Randomizer2::Randomizer2(const std::shared_ptr<Memory>& memory) : _memory(memory) {} | ||
| 7 | |||
| 8 | void Randomizer2::Randomize() { | ||
| 9 | // 4x4 | ||
| 10 | // 14 gaps | ||
| 11 | // start (x=0, y=8) | ||
| 12 | // end (x=8, y=0) Up | ||
| 13 | // 1 solution | ||
| 14 | Puzzle p; | ||
| 15 | int attemptCount = 0; | ||
| 16 | while (true) { | ||
| 17 | attemptCount++; | ||
| 18 | p.NewGrid(4, 4); | ||
| 19 | |||
| 20 | std::vector<Pos> corners; | ||
| 21 | std::vector<Pos> cells; | ||
| 22 | std::vector<Pos> edges; | ||
| 23 | for (int x=0; x<p.width; x++) { | ||
| 24 | for (int y=0; y<p.height; y++) { | ||
| 25 | if (x%2 == 0 && y%2 == 0) corners.emplace_back(Pos{x, y}); | ||
| 26 | else if (x%2 == 1 && y%2 == 1) cells.emplace_back(Pos{x, y}); | ||
| 27 | else edges.emplace_back(Pos{x, y}); | ||
| 28 | } | ||
| 29 | } | ||
| 30 | |||
| 31 | for (int i=0; i<14; i++) { | ||
| 32 | int edge = Random::RandInt(0, static_cast<int>(edges.size() - 1)); | ||
| 33 | Pos pos = edges[edge]; | ||
| 34 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | ||
| 35 | edges.erase(edges.begin() + edge); | ||
| 36 | } | ||
| 37 | |||
| 38 | p.grid[0][8].start = true; | ||
| 39 | p.grid[8][0].end = Cell::Dir::UP; | ||
| 40 | |||
| 41 | auto solutions = Solver::Solve(p); | ||
| 42 | if (solutions.size() == 1) { | ||
| 43 | auto solution = solutions[0]; | ||
| 44 | int solutionLength = 0; | ||
| 45 | for (int x=0; x<solution.width; x++) { | ||
| 46 | for (int y=0; y<solution.height; y++) { | ||
| 47 | if (solution.grid[x][y].color == Cell::Color::BLACK) solutionLength++; | ||
| 48 | } | ||
| 49 | } | ||
| 50 | if (solutionLength == 25) break; | ||
| 51 | } | ||
| 52 | } | ||
| 53 | PuzzleSerializer(_memory).WritePuzzle(p, 0x293); | ||
| 54 | |||
| 55 | |||
| 56 | |||
| 57 | |||
| 58 | // 7x7 | ||
| 59 | // 35 gaps | ||
| 60 | // start (x=8, y=8) | ||
| 61 | // end (x=4, y=0) Up | ||
| 62 | // 2 solutions, 37 & 39 | ||
| 63 | attemptCount = 0; | ||
| 64 | while (true) { | ||
| 65 | attemptCount++; | ||
| 66 | p.NewGrid(7, 7); | ||
| 67 | |||
| 68 | std::vector<Pos> corners; | ||
| 69 | std::vector<Pos> cells; | ||
| 70 | std::vector<Pos> edges; | ||
| 71 | for (int x=0; x<p.width; x++) { | ||
| 72 | for (int y=0; y<p.height; y++) { | ||
| 73 | if (x%2 == 0 && y%2 == 0) corners.emplace_back(Pos{x, y}); | ||
| 74 | else if (x%2 == 1 && y%2 == 1) cells.emplace_back(Pos{x, y}); | ||
| 75 | else edges.emplace_back(Pos{x, y}); | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | for (int i=0; i<35; i++) { | ||
| 80 | int edge = Random::RandInt(0, static_cast<int>(edges.size() - 1)); | ||
| 81 | Pos pos = edges[edge]; | ||
| 82 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | ||
| 83 | edges.erase(edges.begin() + edge); | ||
| 84 | } | ||
| 85 | |||
| 86 | p.grid[8][8].start = true; | ||
| 87 | p.grid[4][0].end = Cell::Dir::UP; | ||
| 88 | |||
| 89 | auto solutions = Solver::Solve(p); | ||
| 90 | if (solutions.size() > 0) break; | ||
| 91 | if (solutions.size() > 0 && solutions.size() < 5) { | ||
| 92 | auto solution = solutions[0]; | ||
| 93 | int solutionLength = 0; | ||
| 94 | for (int x=0; x<solution.width; x++) { | ||
| 95 | for (int y=0; y<solution.height; y++) { | ||
| 96 | if (solution.grid[x][y].color == Cell::Color::BLACK) solutionLength++; | ||
| 97 | } | ||
| 98 | } | ||
| 99 | if (solutionLength > 30 && solutionLength < 40) break; | ||
| 100 | } | ||
| 101 | } | ||
| 102 | PuzzleSerializer(_memory).WritePuzzle(p, 0x295); | ||
| 103 | |||
| 104 | } | ||
| diff --git a/Source/Randomizer2.h b/Source/Randomizer2.h new file mode 100644 index 0000000..1aeae11 --- /dev/null +++ b/Source/Randomizer2.h | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | #pragma once | ||
| 2 | #include <memory> | ||
| 3 | |||
| 4 | class Memory; | ||
| 5 | class Randomizer2 { | ||
| 6 | public: | ||
| 7 | Randomizer2(const std::shared_ptr<Memory>& memory); | ||
| 8 | void Randomize(); | ||
| 9 | |||
| 10 | private: | ||
| 11 | std::shared_ptr<Memory> _memory; | ||
| 12 | }; | ||
| diff --git a/Source/Solver.h b/Source/Solver.h index 8a021ac..09108c7 100644 --- a/Source/Solver.h +++ b/Source/Solver.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | #define MAX_SOLUTIONS 10000 | 5 | #define MAX_SOLUTIONS 10000 |
| 6 | #endif | 6 | #endif |
| 7 | 7 | ||
| 8 | struct Puzzle; | 8 | class Puzzle; |
| 9 | class Solver { | 9 | class Solver { |
| 10 | public: | 10 | public: |
| 11 | static std::vector<Puzzle> Solve(Puzzle& p); | 11 | static std::vector<Puzzle> Solve(Puzzle& p); |
| diff --git a/Source/Source.vcxproj b/Source/Source.vcxproj index 92aa9d7..aebeaeb 100644 --- a/Source/Source.vcxproj +++ b/Source/Source.vcxproj | |||
| @@ -163,6 +163,7 @@ | |||
| 163 | <ClInclude Include="Panels.h" /> | 163 | <ClInclude Include="Panels.h" /> |
| 164 | <ClInclude Include="Random.h" /> | 164 | <ClInclude Include="Random.h" /> |
| 165 | <ClInclude Include="Randomizer.h" /> | 165 | <ClInclude Include="Randomizer.h" /> |
| 166 | <ClInclude Include="Randomizer2.h" /> | ||
| 166 | <ClInclude Include="Solver.h" /> | 167 | <ClInclude Include="Solver.h" /> |
| 167 | <ClInclude Include="Validator.h" /> | 168 | <ClInclude Include="Validator.h" /> |
| 168 | </ItemGroup> | 169 | </ItemGroup> |
| @@ -172,6 +173,7 @@ | |||
| 172 | <ClCompile Include="Puzzle.cpp" /> | 173 | <ClCompile Include="Puzzle.cpp" /> |
| 173 | <ClCompile Include="Random.cpp" /> | 174 | <ClCompile Include="Random.cpp" /> |
| 174 | <ClCompile Include="Randomizer.cpp" /> | 175 | <ClCompile Include="Randomizer.cpp" /> |
| 176 | <ClCompile Include="Randomizer2.cpp" /> | ||
| 175 | <ClCompile Include="Solver.cpp" /> | 177 | <ClCompile Include="Solver.cpp" /> |
| 176 | <ClCompile Include="Validator.cpp" /> | 178 | <ClCompile Include="Validator.cpp" /> |
| 177 | </ItemGroup> | 179 | </ItemGroup> |
| diff --git a/Source/Validator.h b/Source/Validator.h index cddc293..2a102dd 100644 --- a/Source/Validator.h +++ b/Source/Validator.h | |||
| @@ -15,7 +15,7 @@ | |||
| 15 | #endif | 15 | #endif |
| 16 | 16 | ||
| 17 | struct Region{}; | 17 | struct Region{}; |
| 18 | struct Puzzle; | 18 | class Puzzle; |
| 19 | struct Pos; | 19 | struct Pos; |
| 20 | class Validator { | 20 | class Validator { |
| 21 | public: | 21 | public: |
