summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorjbzdarkid <jbzdarkid@gmail.com>2019-11-19 09:42:45 -0800
committerjbzdarkid <jbzdarkid@gmail.com>2019-11-19 09:42:45 -0800
commit52b01775c2c94f08786696cae7836ca56f683739 (patch)
treed6d7d7604c8f5d793be28bcf21753b02d7d31bb7
parent7a13ef0a94f6ed4989677530b1b37e1af0692fc7 (diff)
downloadwitness-tutorializer-52b01775c2c94f08786696cae7836ca56f683739.tar.gz
witness-tutorializer-52b01775c2c94f08786696cae7836ca56f683739.tar.bz2
witness-tutorializer-52b01775c2c94f08786696cae7836ca56f683739.zip
Fix RNG -- this will break seeds, though.
-rw-r--r--Source/Random.cpp7
-rw-r--r--Source/Random.h2
-rw-r--r--Source/Randomizer2.cpp78
-rw-r--r--Source/Randomizer2Core.cpp13
-rw-r--r--Test/RandomTests.cpp8
5 files changed, 98 insertions, 10 deletions
diff --git a/Source/Random.cpp b/Source/Random.cpp index 61fd30f..d9fe678 100644 --- a/Source/Random.cpp +++ b/Source/Random.cpp
@@ -1,7 +1,7 @@
1#include <chrono> 1#include <chrono>
2#include "Random.h" 2#include "Random.h"
3 3
4int Random::s_seed = static_cast<int>(time(nullptr)); // Seed from the time in milliseconds 4uint32_t Random::s_seed = static_cast<int>(time(nullptr)); // Seed from the time in milliseconds
5 5
6void Random::SetSeed(int seed) { 6void Random::SetSeed(int seed) {
7 s_seed = seed; 7 s_seed = seed;
@@ -9,6 +9,7 @@ void Random::SetSeed(int seed) {
9 9
10// Returns a random integer in [min, max] 10// Returns a random integer in [min, max]
11int Random::RandInt(int min, int max) { 11int Random::RandInt(int min, int max) {
12 s_seed = (214013 * s_seed + 2531011) % 2147483648; 12 s_seed = (214013 * s_seed + 2531011); // Implicit unsigned integer overflow
13 return (s_seed % (max - min + 1)) + min; 13 int32_t maskedSeed = ((s_seed >> 16) & 0x7fff); // Only use bits 16-30
14 return (maskedSeed % (max - min + 1)) + min;
14} 15}
diff --git a/Source/Random.h b/Source/Random.h index 46287a1..a2ad706 100644 --- a/Source/Random.h +++ b/Source/Random.h
@@ -8,5 +8,5 @@ public:
8 static int RandInt(int min, int max); 8 static int RandInt(int min, int max);
9 9
10private: 10private:
11 static int s_seed; 11 static uint32_t s_seed;
12}; 12};
diff --git a/Source/Randomizer2.cpp b/Source/Randomizer2.cpp index 83427d7..adf8eb6 100644 --- a/Source/Randomizer2.cpp +++ b/Source/Randomizer2.cpp
@@ -84,6 +84,77 @@ void Randomizer2::RandomizeTutorial() {
84 } 84 }
85 _serializer.WritePuzzle(p, 0xA3B5); 85 _serializer.WritePuzzle(p, 0xA3B5);
86 } 86 }
87
88 { // Back right
89 Puzzle p;
90 p.NewGrid(6, 6);
91
92 p.grid[0][12].start = true;
93 p.grid[12][12].start = true;
94 p.grid[6][0].end = Cell::Dir::UP;
95
96 std::vector<Pos> cuts;
97 bool toTheRight;
98 // Start by generating a cut line, to ensure one of the two startpoints is inaccessible
99 int x, y;
100 switch (Random::RandInt(1, 4))
101 {
102 case 1:
103 x = 1;
104 y = 1;
105 toTheRight = true;
106 cuts.emplace_back(Pos{0, 1});
107 break;
108 case 2:
109 x = 1;
110 y = 1;
111 toTheRight = true;
112 cuts.emplace_back(Pos{1, 0});
113 break;
114 case 3:
115 x = 11;
116 y = 1;
117 toTheRight = false;
118 cuts.emplace_back(Pos{12, 1});
119 break;
120 case 4:
121 x = 11;
122 y = 1;
123 toTheRight = false;
124 cuts.emplace_back(Pos{11, 0});
125 break;
126 }
127 while (y < p.height) { // The final cut will push y below the bottom of the puzzle, which means we're done.
128 switch (Random::RandInt(1, 4)) {
129 case 1: // Go right
130 if (x < p.width-2) {
131 cuts.emplace_back(Pos{x+1, y});
132 x += 2;
133 }
134 break;
135 case 2: // Go left
136 if (x > 1) {
137 cuts.emplace_back(Pos{x-1, y});
138 x -= 2;
139 }
140 break;
141 case 3:
142 case 4: // Go down (biased)
143 cuts.emplace_back(Pos{x, y+1});
144 y += 2;
145 break;
146 }
147 }
148
149 for (Pos pos : cuts) {
150 p.grid[pos.x][pos.y].gap = Cell::Gap::BREAK;
151 }
152
153 for (Pos pos : Randomizer2Core::CutEdges(p, 30 - cuts.size(), true)) {
154 p.grid[pos.x][pos.y].gap = Cell::Gap::BREAK;
155 }
156 _serializer.WritePuzzle(p, 0xA3B2);
157 }
87} 158}
88 159
89void Randomizer2::RandomizeKeep() { 160void Randomizer2::RandomizeKeep() {
@@ -109,7 +180,7 @@ void Randomizer2::RandomizeKeep() {
109 std::vector<Pos> cutEdges = Randomizer2Core::CutEdges(p, 5, false); 180 std::vector<Pos> cutEdges = Randomizer2Core::CutEdges(p, 5, false);
110 Puzzle copy = p; 181 Puzzle copy = p;
111 std::vector<int> gates = {0x00344, 0x00488, 0x00489, 0x00495, 0x00496}; 182 std::vector<int> gates = {0x00344, 0x00488, 0x00489, 0x00495, 0x00496};
112 for (int i=0; i<gates.size(); i++) { 183 for (int i=0; i<cutEdges.size(); i++) {
113 Pos pos = cutEdges[i]; 184 Pos pos = cutEdges[i];
114 copy.grid[pos.x][pos.y].gap = Cell::Gap::BREAK; 185 copy.grid[pos.x][pos.y].gap = Cell::Gap::BREAK;
115 SetGate(gates[i], pos.x, pos.y); 186 SetGate(gates[i], pos.x, pos.y);
@@ -174,12 +245,13 @@ void Randomizer2::RandomizeKeep() {
174 p.grid[0][8].start = true; 245 p.grid[0][8].start = true;
175 p.grid[8][2].end = Cell::Dir::RIGHT; 246 p.grid[8][2].end = Cell::Dir::RIGHT;
176 247
177 std::vector<int> pebbleMarkers = {0x034a9, 0x034b1, 0x034be, 0x034c4};
178
179 std::vector<Pos> cutEdges = Randomizer2Core::CutEdges(p, 7, false); 248 std::vector<Pos> cutEdges = Randomizer2Core::CutEdges(p, 7, false);
180 for (Pos pos : cutEdges) { 249 for (Pos pos : cutEdges) {
181 p.grid[pos.x][pos.y].gap = Cell::Gap::BREAK; 250 p.grid[pos.x][pos.y].gap = Cell::Gap::BREAK;
182 } 251 }
252
253 std::vector<int> pebbleMarkers = {0x034a9, 0x034b1, 0x034be, 0x034c4};
254
183 // _serializer.WritePuzzle(p, 0x19E7); 255 // _serializer.WritePuzzle(p, 0x19E7);
184 } 256 }
185 257
diff --git a/Source/Randomizer2Core.cpp b/Source/Randomizer2Core.cpp index 0310ae2..c34fec6 100644 --- a/Source/Randomizer2Core.cpp +++ b/Source/Randomizer2Core.cpp
@@ -77,15 +77,22 @@ std::vector<Pos> Randomizer2Core::CutEdgesInternal(const Puzzle& p, std::vector<
77 return cutEdges; 77 return cutEdges;
78} 78}
79 79
80#ifndef NDEBUG
81#include <Windows.h>
82#endif
83
80void Randomizer2Core::DebugColorGrid(const std::vector<std::vector<int>>& colorGrid) { 84void Randomizer2Core::DebugColorGrid(const std::vector<std::vector<int>>& colorGrid) {
85#ifndef NDEBUG
81 for (int y=0; y<colorGrid[0].size(); y++) { 86 for (int y=0; y<colorGrid[0].size(); y++) {
82 std::string row; 87 std::string row;
83 for (int x=0; x<colorGrid.size(); x++) { 88 for (int x=0; x<colorGrid.size(); x++) {
84 row += std::to_string(colorGrid[x][y]); 89 row += std::to_string(colorGrid[x][y]);
85 } 90 }
86 std::cerr << row << std::endl; 91 row += "\n";
92 OutputDebugStringA(row.c_str());
87 } 93 }
88 std::cerr << std::endl; 94 OutputDebugStringA("\n");
95#endif
89} 96}
90 97
91void Randomizer2Core::FloodFill(const Puzzle& p, std::vector<std::vector<int>>& colorGrid, int color, int x, int y) { 98void Randomizer2Core::FloodFill(const Puzzle& p, std::vector<std::vector<int>>& colorGrid, int color, int x, int y) {
@@ -102,7 +109,7 @@ void Randomizer2Core::FloodFill(const Puzzle& p, std::vector<std::vector<int>>&
102void Randomizer2Core::FloodFillOutside(const Puzzle& p, std::vector<std::vector<int>>& colorGrid, int x, int y) { 109void Randomizer2Core::FloodFillOutside(const Puzzle& p, std::vector<std::vector<int>>& colorGrid, int x, int y) {
103 if (!p.SafeCell(x, y)) return; 110 if (!p.SafeCell(x, y)) return;
104 if (colorGrid[x][y] != 0) return; // Already processed. 111 if (colorGrid[x][y] != 0) return; // Already processed.
105 if (x%2 != y%2 && p.grid[x][y].gap != Cell::Gap::FULL) return; // Only flood-fill through full gaps 112 if (x%2 != y%2 && p.grid[x][y].gap == Cell::Gap::NONE) return; // Only flood-fill through gaps
106 colorGrid[x][y] = 1; // Outside color 113 colorGrid[x][y] = 1; // Outside color
107 114
108 FloodFillOutside(p, colorGrid, x, y+1); 115 FloodFillOutside(p, colorGrid, x, y+1);
diff --git a/Test/RandomTests.cpp b/Test/RandomTests.cpp index a4fd410..20a86e5 100644 --- a/Test/RandomTests.cpp +++ b/Test/RandomTests.cpp
@@ -32,4 +32,12 @@ TEST(RandomTests, SeedChangesInitialValue) {
32 int random3 = Random::RandInt(0, 1 << 30); 32 int random3 = Random::RandInt(0, 1 << 30);
33 ASSERT_NE(random3, random1); 33 ASSERT_NE(random3, random1);
34 ASSERT_NE(random3, random2); 34 ASSERT_NE(random3, random2);
35}
36
37TEST(RandomTests, EvenOdd) {
38 std::vector<int> outputs;
39 for (int i=0; i<100; i++) {
40 outputs.emplace_back(Random::RandInt(0, 1));
41 }
42 int k = 0;
35} \ No newline at end of file 43} \ No newline at end of file