diff options
-rw-r--r-- | Source/Randomizer2.cpp | 67 | ||||
-rw-r--r-- | Source/Randomizer2Core.cpp | 28 | ||||
-rw-r--r-- | Source/Randomizer2Core.h | 8 |
3 files changed, 65 insertions, 38 deletions
diff --git a/Source/Randomizer2.cpp b/Source/Randomizer2.cpp index e4f2b9f..cc23c7d 100644 --- a/Source/Randomizer2.cpp +++ b/Source/Randomizer2.cpp | |||
@@ -25,7 +25,7 @@ void Randomizer2::RandomizeTutorial() { | |||
25 | p.grid[0][8].start = true; | 25 | p.grid[0][8].start = true; |
26 | p.grid[8][0].end = Cell::Dir::UP; | 26 | p.grid[8][0].end = Cell::Dir::UP; |
27 | 27 | ||
28 | for (Pos pos : Randomizer2Core::CutEdges(p, 14, true)) { | 28 | for (Pos pos : Randomizer2Core::CutEdges(p, 14)) { |
29 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | 29 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; |
30 | } | 30 | } |
31 | _serializer.WritePuzzle(p, 0x293); | 31 | _serializer.WritePuzzle(p, 0x293); |
@@ -36,24 +36,18 @@ void Randomizer2::RandomizeTutorial() { | |||
36 | p.NewGrid(6, 6); | 36 | p.NewGrid(6, 6); |
37 | 37 | ||
38 | // @Bug: Mid-segment endpoints are not yet supported. | 38 | // @Bug: Mid-segment endpoints are not yet supported. |
39 | switch (Random::RandInt(1, 4)) { | 39 | int x = Random::RandInt(0, (p.width-1)/2)*2; |
40 | case 1: | 40 | int y = Random::RandInt(0, (p.height-1)/2)*2; |
41 | p.grid[Random::RandInt(0, p.width-1)][0].end = Cell::Dir::UP; | 41 | int rng = Random::RandInt(1, 4); |
42 | break; | 42 | if (rng == 1) p.grid[x][0].end = Cell::Dir::UP; |
43 | case 2: | 43 | else if (rng == 2) p.grid[x][p.height-1].end = Cell::Dir::DOWN; |
44 | p.grid[Random::RandInt(0, p.width-1)][p.height-1].end = Cell::Dir::DOWN; | 44 | else if (rng == 3) p.grid[0][y].end = Cell::Dir::LEFT; |
45 | break; | 45 | else if (rng == 4) p.grid[p.width-1][y].end = Cell::Dir::RIGHT; |
46 | case 3: | 46 | |
47 | p.grid[0][Random::RandInt(0, p.height-1)].end = Cell::Dir::LEFT; | ||
48 | break; | ||
49 | case 4: | ||
50 | p.grid[p.width-1][Random::RandInt(0, p.height-1)].end = Cell::Dir::RIGHT; | ||
51 | break; | ||
52 | } | ||
53 | // [4/6/8][4/6/8] | 47 | // [4/6/8][4/6/8] |
54 | p.grid[Random::RandInt(0, 2)*2 + 4][Random::RandInt(0, 2)*2 + 4].start = true; | 48 | p.grid[Random::RandInt(0, 2)*2 + 4][Random::RandInt(0, 2)*2 + 4].start = true; |
55 | 49 | ||
56 | for (Pos pos : Randomizer2Core::CutEdges(p, 35, true)) { | 50 | for (Pos pos : Randomizer2Core::CutEdges(p, 35)) { |
57 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | 51 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; |
58 | } | 52 | } |
59 | 53 | ||
@@ -67,7 +61,7 @@ void Randomizer2::RandomizeTutorial() { | |||
67 | p.grid[0][20].start = true; | 61 | p.grid[0][20].start = true; |
68 | p.grid[20][0].end = Cell::Dir::RIGHT; | 62 | p.grid[20][0].end = Cell::Dir::RIGHT; |
69 | 63 | ||
70 | for (Pos pos : Randomizer2Core::CutEdges(p, 96, true)) { | 64 | for (Pos pos : Randomizer2Core::CutEdges(p, 96)) { |
71 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | 65 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; |
72 | } | 66 | } |
73 | _serializer.WritePuzzle(p, 0x2C2); | 67 | _serializer.WritePuzzle(p, 0x2C2); |
@@ -81,7 +75,7 @@ void Randomizer2::RandomizeTutorial() { | |||
81 | p.grid[12][0].end = Cell::Dir::RIGHT; | 75 | p.grid[12][0].end = Cell::Dir::RIGHT; |
82 | p.grid[12][12].end = Cell::Dir::RIGHT; | 76 | p.grid[12][12].end = Cell::Dir::RIGHT; |
83 | 77 | ||
84 | for (Pos pos : Randomizer2Core::CutEdges(p, 27, true)) { | 78 | for (Pos pos : Randomizer2Core::CutEdges(p, 27)) { |
85 | p.grid[pos.x][pos.y].gap = Cell::Gap::BREAK; | 79 | p.grid[pos.x][pos.y].gap = Cell::Gap::BREAK; |
86 | } | 80 | } |
87 | _serializer.WritePuzzle(p, 0xA3B5); | 81 | _serializer.WritePuzzle(p, 0xA3B5); |
@@ -153,7 +147,7 @@ void Randomizer2::RandomizeTutorial() { | |||
153 | p.grid[pos.x][pos.y].gap = Cell::Gap::BREAK; | 147 | p.grid[pos.x][pos.y].gap = Cell::Gap::BREAK; |
154 | } | 148 | } |
155 | 149 | ||
156 | for (Pos pos : Randomizer2Core::CutEdges(p, 30 - cuts.size(), true)) { | 150 | for (Pos pos : Randomizer2Core::CutEdges(p, 30 - cuts.size())) { |
157 | p.grid[pos.x][pos.y].gap = Cell::Gap::BREAK; | 151 | p.grid[pos.x][pos.y].gap = Cell::Gap::BREAK; |
158 | } | 152 | } |
159 | _serializer.WritePuzzle(p, 0xA3B2); | 153 | _serializer.WritePuzzle(p, 0xA3B2); |
@@ -161,7 +155,28 @@ void Randomizer2::RandomizeTutorial() { | |||
161 | } | 155 | } |
162 | 156 | ||
163 | void Randomizer2::RandomizeSymmetry() { | 157 | void Randomizer2::RandomizeSymmetry() { |
164 | { // | 158 | // Back wall |
159 | { | ||
160 | Puzzle p; | ||
161 | p.NewGrid(3, 3); | ||
162 | p.symmetry = Puzzle::Symmetry::X; | ||
163 | p.grid[0][6].start = true; | ||
164 | p.grid[6][6].start = true; | ||
165 | p.grid[2][0].end = Cell::Dir::UP; | ||
166 | p.grid[4][0].end = Cell::Dir::UP; | ||
167 | |||
168 | std::vector<Pos> cutEdges = Randomizer2Core::CutSymmetricalEdgePairs(p, 2); | ||
169 | for (Pos pos : cutEdges) { | ||
170 | Pos sym = p.GetSymmetricalPos(pos.x, pos.y); | ||
171 | p.grid[pos.x][pos.y].gap = Cell::Gap::BREAK; | ||
172 | p.grid[sym.x][sym.y].gap = Cell::Gap::BREAK; | ||
173 | } | ||
174 | _serializer.WritePuzzle(p, 0x86); | ||
175 | } | ||
176 | { | ||
177 | Puzzle p; | ||
178 | p.NewGrid(4, 4); | ||
179 | p.symmetry = Puzzle::Symmetry::X; | ||
165 | 180 | ||
166 | } | 181 | } |
167 | } | 182 | } |
@@ -186,7 +201,7 @@ void Randomizer2::RandomizeKeep() { | |||
186 | p.grid[4][8].start = true; | 201 | p.grid[4][8].start = true; |
187 | p.grid[6][0].end = Cell::Dir::UP; | 202 | p.grid[6][0].end = Cell::Dir::UP; |
188 | 203 | ||
189 | std::vector<Pos> cutEdges = Randomizer2Core::CutEdges(p, 5, false); | 204 | std::vector<Pos> cutEdges = Randomizer2Core::CutInsideEdges(p, 5); |
190 | Puzzle copy = p; | 205 | Puzzle copy = p; |
191 | std::vector<int> gates = {0x00344, 0x00488, 0x00489, 0x00495, 0x00496}; | 206 | std::vector<int> gates = {0x00344, 0x00488, 0x00489, 0x00495, 0x00496}; |
192 | for (int i=0; i<cutEdges.size(); i++) { | 207 | for (int i=0; i<cutEdges.size(); i++) { |
@@ -216,7 +231,7 @@ void Randomizer2::RandomizeKeep() { | |||
216 | p.grid[0][8].start = true; | 231 | p.grid[0][8].start = true; |
217 | p.grid[8][0].end = Cell::Dir::RIGHT; | 232 | p.grid[8][0].end = Cell::Dir::RIGHT; |
218 | 233 | ||
219 | std::vector<Pos> cutEdges = Randomizer2Core::CutEdges(p, 7, false); | 234 | std::vector<Pos> cutEdges = Randomizer2Core::CutInsideEdges(p, 7); |
220 | for (Pos pos : cutEdges) { | 235 | for (Pos pos : cutEdges) { |
221 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | 236 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; |
222 | } | 237 | } |
@@ -231,7 +246,7 @@ void Randomizer2::RandomizeKeep() { | |||
231 | q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | 246 | q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; |
232 | } | 247 | } |
233 | // Cut to 6 of 9 additional edges | 248 | // Cut to 6 of 9 additional edges |
234 | for (Pos pos : Randomizer2Core::CutEdges(q, 6, false)) { | 249 | for (Pos pos : Randomizer2Core::CutInsideEdges(q, 6)) { |
235 | q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | 250 | q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; |
236 | } | 251 | } |
237 | _serializer.WritePuzzle(q, 0x19DC); | 252 | _serializer.WritePuzzle(q, 0x19DC); |
@@ -254,7 +269,7 @@ void Randomizer2::RandomizeKeep() { | |||
254 | p.grid[0][8].start = true; | 269 | p.grid[0][8].start = true; |
255 | p.grid[8][2].end = Cell::Dir::RIGHT; | 270 | p.grid[8][2].end = Cell::Dir::RIGHT; |
256 | 271 | ||
257 | std::vector<Pos> cutEdges = Randomizer2Core::CutEdges(p, 7, false); | 272 | std::vector<Pos> cutEdges = Randomizer2Core::CutInsideEdges(p, 7); |
258 | for (Pos pos : cutEdges) { | 273 | for (Pos pos : cutEdges) { |
259 | p.grid[pos.x][pos.y].gap = Cell::Gap::BREAK; | 274 | p.grid[pos.x][pos.y].gap = Cell::Gap::BREAK; |
260 | } | 275 | } |
@@ -286,7 +301,7 @@ void Randomizer2::RandomizeKeep() { | |||
286 | p.grid[0][8].start = true; | 301 | p.grid[0][8].start = true; |
287 | p.grid[4][0].end = Cell::Dir::UP; | 302 | p.grid[4][0].end = Cell::Dir::UP; |
288 | 303 | ||
289 | std::vector<Pos> cutEdges = Randomizer2Core::CutEdges(p, 2, false); | 304 | std::vector<Pos> cutEdges = Randomizer2Core::CutInsideEdges(p, 2); |
290 | for (Pos pos : cutEdges) { | 305 | for (Pos pos : cutEdges) { |
291 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | 306 | p.grid[pos.x][pos.y].gap = Cell::Gap::FULL; |
292 | } | 307 | } |
@@ -300,7 +315,7 @@ void Randomizer2::RandomizeKeep() { | |||
300 | for (Pos pos : cutEdges) { | 315 | for (Pos pos : cutEdges) { |
301 | q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | 316 | q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; |
302 | } | 317 | } |
303 | for (Pos pos : Randomizer2Core::CutEdges(q, 7, false)) { | 318 | for (Pos pos : Randomizer2Core::CutInsideEdges(q, 7)) { |
304 | q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; | 319 | q.grid[pos.x][pos.y].gap = Cell::Gap::FULL; |
305 | } | 320 | } |
306 | _serializer.WritePuzzle(q, 0x1A0F); | 321 | _serializer.WritePuzzle(q, 0x1A0F); |
diff --git a/Source/Randomizer2Core.cpp b/Source/Randomizer2Core.cpp index f8d1312..dcb9fd2 100644 --- a/Source/Randomizer2Core.cpp +++ b/Source/Randomizer2Core.cpp | |||
@@ -6,13 +6,25 @@ | |||
6 | #include <iostream> | 6 | #include <iostream> |
7 | #include <cassert> | 7 | #include <cassert> |
8 | 8 | ||
9 | std::vector<Pos> Randomizer2Core::CutEdges(const Puzzle& p, size_t numEdges, bool allowEdges) { | 9 | std::vector<Pos> Randomizer2Core::CutEdges(const Puzzle& p, size_t numEdges) { |
10 | std::vector<Pos> edges; | 10 | return CutEdgesInternal(p, 0, p.width, 0, p.height, numEdges); |
11 | int xMin = allowEdges ? 0 : 1; | 11 | } |
12 | int xMax = allowEdges ? p.width : p.width-1; | ||
13 | int yMin = allowEdges ? 0 : 1; | ||
14 | int yMax = allowEdges ? p.height : p.height-1; | ||
15 | 12 | ||
13 | std::vector<Pos> Randomizer2Core::CutInsideEdges(const Puzzle& p, size_t numEdges) { | ||
14 | return CutEdgesInternal(p, 1, p.width-1, 1, p.height-1, numEdges); | ||
15 | } | ||
16 | |||
17 | std::vector<Pos> Randomizer2Core::CutSymmetricalEdgePairs(const Puzzle& p, size_t numEdges) { | ||
18 | assert(p.symmetry != Puzzle::Symmetry::NONE); | ||
19 | if (p.symmetry == Puzzle::Symmetry::X) { | ||
20 | return CutEdgesInternal(p, 0, (p.width-1)/2, 0, p.height, numEdges); | ||
21 | } | ||
22 | assert(false); | ||
23 | return {}; | ||
24 | } | ||
25 | |||
26 | std::vector<Pos> Randomizer2Core::CutEdgesInternal(const Puzzle& p, int xMin, int xMax, int yMin, int yMax, size_t numEdges) { | ||
27 | std::vector<Pos> edges; | ||
16 | for (int x=xMin; x<xMax; x++) { | 28 | for (int x=xMin; x<xMax; x++) { |
17 | for (int y=yMin; y<yMax; y++) { | 29 | for (int y=yMin; y<yMax; y++) { |
18 | if (x%2 == y%2) continue; | 30 | if (x%2 == y%2) continue; |
@@ -27,10 +39,8 @@ std::vector<Pos> Randomizer2Core::CutEdges(const Puzzle& p, size_t numEdges, boo | |||
27 | edges.emplace_back(x, y); | 39 | edges.emplace_back(x, y); |
28 | } | 40 | } |
29 | } | 41 | } |
30 | return CutEdgesInternal(p, edges, numEdges); | 42 | assert(numEdges <= edges.size()); |
31 | } | ||
32 | 43 | ||
33 | std::vector<Pos> Randomizer2Core::CutEdgesInternal(const Puzzle& p, std::vector<Pos>& edges, size_t numEdges) { | ||
34 | auto [colorGrid, numColors] = CreateColorGrid(p); | 44 | auto [colorGrid, numColors] = CreateColorGrid(p); |
35 | assert(numEdges <= numColors); | 45 | assert(numEdges <= numColors); |
36 | 46 | ||
diff --git a/Source/Randomizer2Core.h b/Source/Randomizer2Core.h index 443f893..674e4ea 100644 --- a/Source/Randomizer2Core.h +++ b/Source/Randomizer2Core.h | |||
@@ -6,11 +6,13 @@ class Puzzle; | |||
6 | 6 | ||
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: These do not actually cut edges, they just returns a list of suggested cuts. |
10 | static std::vector<Pos> CutEdges(const Puzzle& p, size_t numEdges, bool allowEdges); | 10 | static std::vector<Pos> CutEdges(const Puzzle& p, size_t numEdges); |
11 | static std::vector<Pos> CutInsideEdges(const Puzzle& p, size_t numEdges); | ||
12 | static std::vector<Pos> CutSymmetricalEdgePairs(const Puzzle& p, size_t numEdges); | ||
11 | 13 | ||
12 | private: | 14 | private: |
13 | static std::vector<Pos> CutEdgesInternal(const Puzzle& p, std::vector<Pos>& edges, size_t numEdges); | 15 | static std::vector<Pos> CutEdgesInternal(const Puzzle& p, int xMin, int xMax, int yMin, int yMax, size_t numEdges); |
14 | static void DebugColorGrid(const std::vector<std::vector<int>>& colorGrid); | 16 | static void DebugColorGrid(const std::vector<std::vector<int>>& colorGrid); |
15 | static void FloodFill(const Puzzle& p, std::vector<std::vector<int>>& colorGrid, int color, int x, int y); | 17 | static void FloodFill(const Puzzle& p, std::vector<std::vector<int>>& colorGrid, int color, int x, int y); |
16 | static void FloodFillOutside(const Puzzle& p, std::vector<std::vector<int>>& colorGrid, int x, int y); | 18 | static void FloodFillOutside(const Puzzle& p, std::vector<std::vector<int>>& colorGrid, int x, int y); |