about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorjbzdarkid <jbzdarkid@gmail.com>2019-11-21 10:03:34 -0800
committerjbzdarkid <jbzdarkid@gmail.com>2019-11-21 10:03:34 -0800
commit859cfdb86d57bb230f1200c3a4c76c55ca920199 (patch)
treec401dd52d097f438517bc8c26cdae0ec90dfd68f
parent4816728c4a5bcf8fd9992f32464a1707f94c3b13 (diff)
downloadwitness-tutorializer-859cfdb86d57bb230f1200c3a4c76c55ca920199.tar.gz
witness-tutorializer-859cfdb86d57bb230f1200c3a4c76c55ca920199.tar.bz2
witness-tutorializer-859cfdb86d57bb230f1200c3a4c76c55ca920199.zip
Well, got started on randomization anyways
-rw-r--r--Source/Randomizer2.cpp67
-rw-r--r--Source/Randomizer2Core.cpp28
-rw-r--r--Source/Randomizer2Core.h8
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
163void Randomizer2::RandomizeSymmetry() { 157void 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
9std::vector<Pos> Randomizer2Core::CutEdges(const Puzzle& p, size_t numEdges, bool allowEdges) { 9std::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
13std::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
17std::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
26std::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
33std::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
7class Randomizer2Core { 7class Randomizer2Core {
8public: 8public:
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
12private: 14private:
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);