diff options
-rw-r--r-- | Source/Puzzle.h | 4 | ||||
-rw-r--r-- | Source/PuzzleSerializer.cpp | 15 | ||||
-rw-r--r-- | Source/Randomizer2.cpp | 20 | ||||
-rw-r--r-- | Source/Randomizer2Core.cpp | 30 | ||||
-rw-r--r-- | Source/Randomizer2Core.h | 3 |
5 files changed, 37 insertions, 35 deletions
diff --git a/Source/Puzzle.h b/Source/Puzzle.h index 962874e..1e00ef4 100644 --- a/Source/Puzzle.h +++ b/Source/Puzzle.h | |||
@@ -65,8 +65,8 @@ struct Pos {int x; int y;}; | |||
65 | 65 | ||
66 | class Puzzle { | 66 | class Puzzle { |
67 | public: | 67 | public: |
68 | int16_t height = 0; | 68 | int height = 0; |
69 | int16_t width = 0; | 69 | int width = 0; |
70 | bool hasDecorations = false; | 70 | bool hasDecorations = false; |
71 | 71 | ||
72 | enum class Symmetry {NONE, X, Y, XY}; | 72 | enum class Symmetry {NONE, X, Y, XY}; |
diff --git a/Source/PuzzleSerializer.cpp b/Source/PuzzleSerializer.cpp index c1e93a5..e845578 100644 --- a/Source/PuzzleSerializer.cpp +++ b/Source/PuzzleSerializer.cpp | |||
@@ -1,5 +1,6 @@ | |||
1 | #include "PuzzleSerializer.h" | 1 | #include "PuzzleSerializer.h" |
2 | #include "Memory.h" | 2 | #include "Memory.h" |
3 | #include <cassert> | ||
3 | 4 | ||
4 | #pragma warning (disable:26451) | 5 | #pragma warning (disable:26451) |
5 | #pragma warning (disable:26812) | 6 | #pragma warning (disable:26812) |
@@ -47,6 +48,16 @@ void PuzzleSerializer::WritePuzzle(const Puzzle& p, int id) { | |||
47 | WriteDecorations(p, id); | 48 | WriteDecorations(p, id); |
48 | WriteSequence(p, id); | 49 | WriteSequence(p, id); |
49 | 50 | ||
51 | #ifndef NDEBUG | ||
52 | int maxDots = _memory->ReadEntityData<int>(id, NUM_DOTS, 1)[0]; | ||
53 | assert(_intersectionFlags.size() <= maxDots); | ||
54 | assert(_intersectionLocations.size() <= maxDots*2); | ||
55 | |||
56 | int maxConnections = _memory->ReadEntityData<int>(id, NUM_CONNECTIONS, 1)[0]; | ||
57 | assert(_connectionsA.size() <= maxConnections); | ||
58 | assert(_connectionsB.size() <= maxConnections); | ||
59 | #endif | ||
60 | |||
50 | _memory->WriteEntityData<int>(id, GRID_SIZE_X, {(p.width + 1)/2}); | 61 | _memory->WriteEntityData<int>(id, GRID_SIZE_X, {(p.width + 1)/2}); |
51 | _memory->WriteEntityData<int>(id, GRID_SIZE_Y, {(p.height + 1)/2}); | 62 | _memory->WriteEntityData<int>(id, GRID_SIZE_Y, {(p.height + 1)/2}); |
52 | _memory->WriteEntityData<int>(id, NUM_DOTS, {static_cast<int>(_intersectionFlags.size())}); | 63 | _memory->WriteEntityData<int>(id, NUM_DOTS, {static_cast<int>(_intersectionFlags.size())}); |
@@ -376,6 +387,10 @@ void PuzzleSerializer::WriteDecorations(const Puzzle& p, int id) { | |||
376 | } | 387 | } |
377 | } | 388 | } |
378 | 389 | ||
390 | #ifndef NDEBUG | ||
391 | int maxDecorations = _memory->ReadEntityData<int>(id, NUM_DECORATIONS, 1)[0]; | ||
392 | assert(decorations.size() < maxDecorations); | ||
393 | #endif | ||
379 | _memory->WriteEntityData<int>(id, NUM_DECORATIONS, {static_cast<int>(decorations.size())}); | 394 | _memory->WriteEntityData<int>(id, NUM_DECORATIONS, {static_cast<int>(decorations.size())}); |
380 | _memory->WriteArray<int>(id, DECORATIONS, decorations); | 395 | _memory->WriteArray<int>(id, DECORATIONS, decorations); |
381 | } | 396 | } |
diff --git a/Source/Randomizer2.cpp b/Source/Randomizer2.cpp index 7a50c7b..c28795a 100644 --- a/Source/Randomizer2.cpp +++ b/Source/Randomizer2.cpp | |||
@@ -14,7 +14,7 @@ Randomizer2::Randomizer2(const std::shared_ptr<Memory>& memory) : _memory(memory | |||
14 | 14 | ||
15 | void Randomizer2::Randomize() { | 15 | void Randomizer2::Randomize() { |
16 | RandomizeTutorial(); | 16 | RandomizeTutorial(); |
17 | RandomizeKeep(); | 17 | // RandomizeKeep(); |
18 | } | 18 | } |
19 | 19 | ||
20 | void Randomizer2::RandomizeTutorial() { | 20 | void Randomizer2::RandomizeTutorial() { |
@@ -24,7 +24,7 @@ void Randomizer2::RandomizeTutorial() { | |||
24 | p.grid[0][8].start = true; | 24 | p.grid[0][8].start = true; |
25 | p.grid[8][0].end = Cell::Dir::UP; | 25 | p.grid[8][0].end = Cell::Dir::UP; |
26 | 26 | ||
27 | for (Pos pos : Randomizer2Core::CutEdges(p, 14)) { | 27 | for (Pos pos : Randomizer2Core::CutEdges(p, 14, true)) { |
28 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | 28 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; |
29 | } | 29 | } |
30 | _serializer.WritePuzzle(p, 0x293); | 30 | _serializer.WritePuzzle(p, 0x293); |
@@ -32,7 +32,7 @@ void Randomizer2::RandomizeTutorial() { | |||
32 | 32 | ||
33 | { | 33 | { |
34 | Puzzle p; | 34 | Puzzle p; |
35 | p.NewGrid(7, 7); | 35 | p.NewGrid(6, 6); |
36 | 36 | ||
37 | switch (Random::RandInt(1, 4)) { | 37 | switch (Random::RandInt(1, 4)) { |
38 | case 1: | 38 | case 1: |
@@ -60,7 +60,7 @@ void Randomizer2::RandomizeTutorial() { | |||
60 | break; | 60 | break; |
61 | } | 61 | } |
62 | 62 | ||
63 | for (Pos pos : Randomizer2Core::CutEdges(p, 35)) { | 63 | for (Pos pos : Randomizer2Core::CutEdges(p, 35, true)) { |
64 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | 64 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; |
65 | } | 65 | } |
66 | 66 | ||
@@ -88,7 +88,7 @@ void Randomizer2::RandomizeKeep() { | |||
88 | p.grid[4][8].start = true; | 88 | p.grid[4][8].start = true; |
89 | p.grid[6][0].end = Cell::Dir::UP; | 89 | p.grid[6][0].end = Cell::Dir::UP; |
90 | 90 | ||
91 | std::vector<Pos> cutEdges = Randomizer2Core::CutEdges2(p, 5); | 91 | std::vector<Pos> cutEdges = Randomizer2Core::CutEdges(p, 5, false); |
92 | Puzzle copy = p; | 92 | Puzzle copy = p; |
93 | std::vector<int> gates = {0x00344, 0x00488, 0x00489, 0x00495, 0x00496}; | 93 | std::vector<int> gates = {0x00344, 0x00488, 0x00489, 0x00495, 0x00496}; |
94 | for (int i=0; i<gates.size(); i++) { | 94 | for (int i=0; i<gates.size(); i++) { |
@@ -118,7 +118,7 @@ void Randomizer2::RandomizeKeep() { | |||
118 | p.grid[0][8].start = true; | 118 | p.grid[0][8].start = true; |
119 | p.grid[8][0].end = Cell::Dir::RIGHT; | 119 | p.grid[8][0].end = Cell::Dir::RIGHT; |
120 | 120 | ||
121 | std::vector<Pos> cutEdges = Randomizer2Core::CutEdges2(p, 7); | 121 | std::vector<Pos> cutEdges = Randomizer2Core::CutEdges(p, 7, false); |
122 | for (Pos pos : cutEdges) { | 122 | for (Pos pos : cutEdges) { |
123 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | 123 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; |
124 | } | 124 | } |
@@ -133,7 +133,7 @@ void Randomizer2::RandomizeKeep() { | |||
133 | q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | 133 | q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; |
134 | } | 134 | } |
135 | // Cut to 6 of 9 additional edges | 135 | // Cut to 6 of 9 additional edges |
136 | for (Pos pos : Randomizer2Core::CutEdges2(q, 6)) { | 136 | for (Pos pos : Randomizer2Core::CutEdges(q, 6, false)) { |
137 | q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | 137 | q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; |
138 | } | 138 | } |
139 | _serializer.WritePuzzle(q, 0x19DC); | 139 | _serializer.WritePuzzle(q, 0x19DC); |
@@ -158,7 +158,7 @@ void Randomizer2::RandomizeKeep() { | |||
158 | 158 | ||
159 | std::vector<int> pebbleMarkers = {0x034a9, 0x034b1, 0x034be, 0x034c4}; | 159 | std::vector<int> pebbleMarkers = {0x034a9, 0x034b1, 0x034be, 0x034c4}; |
160 | 160 | ||
161 | std::vector<Pos> cutEdges = Randomizer2Core::CutEdges2(p, 7); | 161 | std::vector<Pos> cutEdges = Randomizer2Core::CutEdges(p, 7, false); |
162 | for (Pos pos : cutEdges) { | 162 | for (Pos pos : cutEdges) { |
163 | p.grid[pos.x][pos.y].gap = Cell::Gap::BREAK; | 163 | p.grid[pos.x][pos.y].gap = Cell::Gap::BREAK; |
164 | } | 164 | } |
@@ -187,7 +187,7 @@ void Randomizer2::RandomizeKeep() { | |||
187 | p.grid[0][8].start = true; | 187 | p.grid[0][8].start = true; |
188 | p.grid[4][0].end = Cell::Dir::UP; | 188 | p.grid[4][0].end = Cell::Dir::UP; |
189 | 189 | ||
190 | std::vector<Pos> cutEdges = Randomizer2Core::CutEdges2(p, 2); | 190 | std::vector<Pos> cutEdges = Randomizer2Core::CutEdges(p, 2, false); |
191 | for (Pos pos : cutEdges) { | 191 | for (Pos pos : cutEdges) { |
192 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | 192 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; |
193 | } | 193 | } |
@@ -201,7 +201,7 @@ void Randomizer2::RandomizeKeep() { | |||
201 | for (Pos pos : cutEdges) { | 201 | for (Pos pos : cutEdges) { |
202 | q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | 202 | q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; |
203 | } | 203 | } |
204 | for (Pos pos : Randomizer2Core::CutEdges2(q, 7)) { | 204 | for (Pos pos : Randomizer2Core::CutEdges(q, 7, false)) { |
205 | q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | 205 | q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; |
206 | } | 206 | } |
207 | _serializer.WritePuzzle(q, 0x1A0F); | 207 | _serializer.WritePuzzle(q, 0x1A0F); |
diff --git a/Source/Randomizer2Core.cpp b/Source/Randomizer2Core.cpp index 8bd5765..0310ae2 100644 --- a/Source/Randomizer2Core.cpp +++ b/Source/Randomizer2Core.cpp | |||
@@ -6,31 +6,19 @@ | |||
6 | #include <iostream> | 6 | #include <iostream> |
7 | #include <cassert> | 7 | #include <cassert> |
8 | 8 | ||
9 | // @Cutnpaste | 9 | std::vector<Pos> Randomizer2Core::CutEdges(const Puzzle& p, size_t numEdges, bool allowEdges) { |
10 | std::vector<Pos> Randomizer2Core::CutEdges(const Puzzle& p, size_t numEdges) { | ||
11 | std::vector<Pos> edges; | 10 | std::vector<Pos> edges; |
12 | for (int x=0; x<p.width; x++) { | 11 | int xMin = allowEdges ? 0 : 1; |
13 | for (int y=0; y<p.height; y++) { | 12 | int xMax = allowEdges ? p.width : p.width-1; |
14 | if (x%2 == y%2) continue; | 13 | int yMin = allowEdges ? 0 : 1; |
15 | if (p.grid[x][y].gap != Cell::Gap::NONE) continue; | 14 | int yMax = allowEdges ? p.height : p.height-1; |
16 | 15 | ||
17 | // If the puzzle already has a sequence, don't cut along it. | 16 | for (int x=xMin; x<xMax; x++) { |
18 | bool inSequence = false; | 17 | for (int y=yMin; y<yMax; y++) { |
19 | for (Pos pos : p.sequence) inSequence |= (pos.x == x && pos.y == y); | ||
20 | if (inSequence) continue; | ||
21 | edges.emplace_back(Pos{x, y}); | ||
22 | } | ||
23 | } | ||
24 | return CutEdgesInternal(p, edges, numEdges); | ||
25 | } | ||
26 | |||
27 | std::vector<Pos> Randomizer2Core::CutEdges2(const Puzzle& p, size_t numEdges) { | ||
28 | std::vector<Pos> edges; | ||
29 | // Note the iterator bounds; we skip the outer edges. | ||
30 | for (int x=1; x<p.width-1; x++) { | ||
31 | for (int y=1; y<p.height-1; y++) { | ||
32 | if (x%2 == y%2) continue; | 18 | if (x%2 == y%2) continue; |
33 | if (p.grid[x][y].gap != Cell::Gap::NONE) continue; | 19 | if (p.grid[x][y].gap != Cell::Gap::NONE) continue; |
20 | if (p.grid[x][y].start) continue; | ||
21 | if (p.grid[x][y].end != Cell::Dir::NONE) continue; | ||
34 | 22 | ||
35 | // If the puzzle already has a sequence, don't cut along it. | 23 | // If the puzzle already has a sequence, don't cut along it. |
36 | bool inSequence = false; | 24 | bool inSequence = false; |
diff --git a/Source/Randomizer2Core.h b/Source/Randomizer2Core.h index 63ba6a8..443f893 100644 --- a/Source/Randomizer2Core.h +++ b/Source/Randomizer2Core.h | |||
@@ -7,8 +7,7 @@ class Puzzle; | |||
7 | class Randomizer2Core { | 7 | class Randomizer2Core { |
8 | public: | 8 | public: |
9 | // CAUTION: Does not actually cut edges, just returns a list of suggested cuts. | 9 | // CAUTION: Does not actually cut edges, just returns a list of suggested cuts. |
10 | static std::vector<Pos> CutEdges(const Puzzle& p, size_t numEdges); | 10 | static std::vector<Pos> CutEdges(const Puzzle& p, size_t numEdges, bool allowEdges); |
11 | static std::vector<Pos> CutEdges2(const Puzzle& p, size_t numEdges); | ||
12 | 11 | ||
13 | private: | 12 | private: |
14 | static std::vector<Pos> CutEdgesInternal(const Puzzle& p, std::vector<Pos>& edges, size_t numEdges); | 13 | static std::vector<Pos> CutEdgesInternal(const Puzzle& p, std::vector<Pos>& edges, size_t numEdges); |