about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--App/Main.cpp10
-rw-r--r--Source/Puzzle.cpp12
-rw-r--r--Source/Puzzle.h28
-rw-r--r--Source/Randomizer2.cpp104
-rw-r--r--Source/Randomizer2.h12
-rw-r--r--Source/Solver.h2
-rw-r--r--Source/Source.vcxproj2
-rw-r--r--Source/Validator.h2
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
32HWND g_panelId; 34HWND g_panelId;
33Puzzle g_puzzle; 35Puzzle g_puzzle;
36std::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 @@
7PuzzleSerializer::PuzzleSerializer(const std::shared_ptr<Memory>& memory) : _memory(memory) {} 7PuzzleSerializer::PuzzleSerializer(const std::shared_ptr<Memory>& memory) : _memory(memory) {}
8 8
9Puzzle PuzzleSerializer::ReadPuzzle(int id) { 9Puzzle 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
41struct Cell { 40struct Cell {
42 inline static Cell Undefined() { 41 inline static Cell Undefined() {
43 Cell c; 42 Cell c;
@@ -63,7 +62,9 @@ struct Cell {
63struct Negation {}; 62struct Negation {};
64struct Pos {int x; int y;}; 63struct Pos {int x; int y;};
65 64
66struct Puzzle { 65#include <cassert> // TODO: Move this + impl to cpp
66class Puzzle {
67public:
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
6Randomizer2::Randomizer2(const std::shared_ptr<Memory>& memory) : _memory(memory) {}
7
8void 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
4class Memory;
5class Randomizer2 {
6public:
7 Randomizer2(const std::shared_ptr<Memory>& memory);
8 void Randomize();
9
10private:
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
8struct Puzzle; 8class Puzzle;
9class Solver { 9class Solver {
10public: 10public:
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
17struct Region{}; 17struct Region{};
18struct Puzzle; 18class Puzzle;
19struct Pos; 19struct Pos;
20class Validator { 20class Validator {
21public: 21public: