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 | |
parent | 36be1ed32ac9a554f0b11fcc13b5699e717b81f2 (diff) | |
download | witness-tutorializer-98db209c9008492baec6bb482b047d386fbdd42b.tar.gz witness-tutorializer-98db209c9008492baec6bb482b047d386fbdd42b.tar.bz2 witness-tutorializer-98db209c9008492baec6bb482b047d386fbdd42b.zip |
One down, 522 to go.
-rw-r--r-- | App/Main.cpp | 10 | ||||
-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 |
8 files changed, 156 insertions, 16 deletions
diff --git a/App/Main.cpp b/App/Main.cpp index 5213a79..3fb9df4 100644 --- a/App/Main.cpp +++ b/App/Main.cpp | |||
@@ -23,14 +23,17 @@ | |||
23 | /* ------- Temp ------- */ | 23 | /* ------- Temp ------- */ |
24 | #include "Puzzle.h" | 24 | #include "Puzzle.h" |
25 | #include "Solver.h" | 25 | #include "Solver.h" |
26 | #include "Randomizer2.h" | ||
26 | #include <sstream> | 27 | #include <sstream> |
27 | 28 | ||
28 | #define TMP1 0x501 | 29 | #define TMP1 0x501 |
29 | #define TMP2 0x502 | 30 | #define TMP2 0x502 |
30 | #define TMP3 0x503 | 31 | #define TMP3 0x503 |
32 | #define TMP4 0x504 | ||
31 | 33 | ||
32 | HWND g_panelId; | 34 | HWND g_panelId; |
33 | Puzzle g_puzzle; | 35 | Puzzle g_puzzle; |
36 | std::shared_ptr<Randomizer2> g_randomizer2; | ||
34 | /* ------- Temp ------- */ | 37 | /* ------- Temp ------- */ |
35 | 38 | ||
36 | // Globals | 39 | // Globals |
@@ -61,12 +64,14 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) | |||
61 | // Shut down randomizer, wait for startup | 64 | // Shut down randomizer, wait for startup |
62 | if (g_randomizer) { | 65 | if (g_randomizer) { |
63 | g_randomizer = nullptr; | 66 | g_randomizer = nullptr; |
67 | g_randomizer2 = nullptr; | ||
64 | EnableWindow(g_randomizerStatus, FALSE); | 68 | EnableWindow(g_randomizerStatus, FALSE); |
65 | } | 69 | } |
66 | break; | 70 | break; |
67 | case ProcStatus::Running: | 71 | case ProcStatus::Running: |
68 | if (!g_randomizer) { | 72 | if (!g_randomizer) { |
69 | g_randomizer = std::make_shared<Randomizer>(g_witnessProc); | 73 | g_randomizer = std::make_shared<Randomizer>(g_witnessProc); |
74 | g_randomizer2 = std::make_shared<Randomizer2>(g_witnessProc); | ||
70 | PostMessage(g_hwnd, WM_COMMAND, RANDOMIZE_READY, NULL); | 75 | PostMessage(g_hwnd, WM_COMMAND, RANDOMIZE_READY, NULL); |
71 | } | 76 | } |
72 | break; | 77 | break; |
@@ -159,6 +164,8 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) | |||
159 | case TMP3: | 164 | case TMP3: |
160 | Solver::Solve(g_puzzle); | 165 | Solver::Solve(g_puzzle); |
161 | break; | 166 | break; |
167 | case TMP4: | ||
168 | g_randomizer2->Randomize(); | ||
162 | } | 169 | } |
163 | } | 170 | } |
164 | return DefWindowProc(hwnd, message, wParam, lParam); | 171 | return DefWindowProc(hwnd, message, wParam, lParam); |
@@ -244,7 +251,8 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance | |||
244 | g_panelId = CreateText(200, 100, 100, L"A3B2"); | 251 | g_panelId = CreateText(200, 100, 100, L"A3B2"); |
245 | CreateButton(200, 130, 100, L"Read", TMP1); | 252 | CreateButton(200, 130, 100, L"Read", TMP1); |
246 | CreateButton(200, 160, 100, L"Write", TMP2); | 253 | CreateButton(200, 160, 100, L"Write", TMP2); |
247 | CreateButton(200, 190, 100, L"Validate", TMP3); | 254 | CreateButton(200, 190, 100, L"Solve", TMP3); |
255 | CreateButton(200, 220, 100, L"Randomize2", TMP4); | ||
248 | 256 | ||
249 | g_witnessProc->StartHeartbeat(g_hwnd); | 257 | g_witnessProc->StartHeartbeat(g_hwnd); |
250 | 258 | ||
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: |