diff options
author | jbzdarkid <jbzdarkid@gmail.com> | 2018-11-09 10:08:03 -0800 |
---|---|---|
committer | jbzdarkid <jbzdarkid@gmail.com> | 2018-11-09 10:08:03 -0800 |
commit | 1f85741c8d12d9b1fbd55b29f334de572f9eea9b (patch) | |
tree | 098ec2630e40ed9f0a2fabf11f49f05111653bde /Source/Panel.cpp | |
parent | c388759ed67b792201b99bf7d73d036c34b47d87 (diff) | |
download | witness-tutorializer-1f85741c8d12d9b1fbd55b29f334de572f9eea9b.tar.gz witness-tutorializer-1f85741c8d12d9b1fbd55b29f334de572f9eea9b.tar.bz2 witness-tutorializer-1f85741c8d12d9b1fbd55b29f334de572f9eea9b.zip |
Reading & writing to tutorial vault works!
Diffstat (limited to 'Source/Panel.cpp')
-rw-r--r-- | Source/Panel.cpp | 178 |
1 files changed, 116 insertions, 62 deletions
diff --git a/Source/Panel.cpp b/Source/Panel.cpp index b6aa504..c0fb7ec 100644 --- a/Source/Panel.cpp +++ b/Source/Panel.cpp | |||
@@ -13,8 +13,9 @@ int find(const std::vector<T> &data, T search, size_t startIndex = 0) { | |||
13 | } | 13 | } |
14 | 14 | ||
15 | Panel::Panel(int id) { | 15 | Panel::Panel(int id) { |
16 | _width = 2 * _memory.ReadPanelData<int>(id, GRID_SIZE_X, 1)[0] - 1; | 16 | _memory = std::make_shared<Memory>("witness64_d3d11.exe"); |
17 | _height = 2 * _memory.ReadPanelData<int>(id, GRID_SIZE_Y, 1)[0] - 1; | 17 | _width = 2 * _memory->ReadPanelData<int>(id, GRID_SIZE_X, 1)[0] - 1; |
18 | _height = 2 * _memory->ReadPanelData<int>(id, GRID_SIZE_Y, 1)[0] - 1; | ||
18 | _grid.resize(_width); | 19 | _grid.resize(_width); |
19 | for (auto& row : _grid) row.resize(_height); | 20 | for (auto& row : _grid) row.resize(_height); |
20 | 21 | ||
@@ -22,15 +23,12 @@ Panel::Panel(int id) { | |||
22 | ReadDecorations(id); | 23 | ReadDecorations(id); |
23 | } | 24 | } |
24 | 25 | ||
25 | // For testing | ||
26 | Panel::Panel() {} | ||
27 | |||
28 | void Panel::Write(int id) { | 26 | void Panel::Write(int id) { |
29 | WriteIntersections(id); | 27 | WriteIntersections(id); |
30 | WriteDecorations(id); | 28 | WriteDecorations(id); |
31 | 29 | ||
32 | _memory.WritePanelData<int>(id, GRID_SIZE_X, {(_width + 1)/2}); | 30 | _memory->WritePanelData<int>(id, GRID_SIZE_X, {(_width + 1)/2}); |
33 | _memory.WritePanelData<int>(id, GRID_SIZE_Y, {(_height + 1)/2}); | 31 | _memory->WritePanelData<int>(id, GRID_SIZE_Y, {(_height + 1)/2}); |
34 | } | 32 | } |
35 | 33 | ||
36 | nlohmann::json Panel::Serialize() { | 34 | nlohmann::json Panel::Serialize() { |
@@ -49,6 +47,9 @@ nlohmann::json Panel::Serialize() { | |||
49 | if (x%2 == 1 && y%2 == 1) { | 47 | if (x%2 == 1 && y%2 == 1) { |
50 | puzzle["grid"][x][y] = Decoration::to_json(_grid[x][y]); | 48 | puzzle["grid"][x][y] = Decoration::to_json(_grid[x][y]); |
51 | } else { | 49 | } else { |
50 | if (_grid[x][y] & IntersectionFlags::HAS_DOT) { | ||
51 | puzzle["dots"].emplace_back(nlohmann::json({{"x", x}, {"y", y}})); | ||
52 | } | ||
52 | puzzle["grid"][x][y] = false; | 53 | puzzle["grid"][x][y] = false; |
53 | } | 54 | } |
54 | } | 55 | } |
@@ -80,65 +81,52 @@ void Panel::Random() { | |||
80 | } | 81 | } |
81 | 82 | ||
82 | void Panel::ReadDecorations(int id) { | 83 | void Panel::ReadDecorations(int id) { |
83 | int numDecorations = _memory.ReadPanelData<int>(id, NUM_DECORATIONS, 1)[0]; | 84 | int numDecorations = _memory->ReadPanelData<int>(id, NUM_DECORATIONS, 1)[0]; |
84 | std::vector<int> decorations = _memory.ReadArray<int>(id, DECORATIONS, numDecorations); | 85 | std::vector<int> decorations = _memory->ReadArray<int>(id, DECORATIONS, numDecorations); |
85 | 86 | ||
86 | int x = 1; | 87 | for (int i=0; i<numDecorations; i++) { |
87 | int y = _height - 2; | 88 | auto [x, y] = dloc_to_xy(i); |
88 | for (int decoration : decorations) { | 89 | _grid[x][y] = decorations[i]; |
89 | _grid[x][y] = decoration; | ||
90 | x += 2; | ||
91 | if (x > _width - 1) { | ||
92 | x = 1; | ||
93 | y -= 2; | ||
94 | } | ||
95 | } | 90 | } |
96 | } | 91 | } |
97 | 92 | ||
98 | void Panel::WriteDecorations(int id) { | 93 | void Panel::WriteDecorations(int id) { |
99 | std::vector<int> decorations; | 94 | std::vector<int> decorations; |
100 | for (int y=_height - 2; y>0; y-=2) { | 95 | for (int y=_height-2; y>0; y-=2) { |
101 | for (int x=1; x<_width - 1; x+=2) { | 96 | for (int x=1; x<_width - 1; x+=2) { |
102 | decorations.push_back(_grid[x][y]); | 97 | decorations.push_back(_grid[x][y]); |
103 | } | 98 | } |
104 | } | 99 | } |
105 | 100 | ||
106 | _memory.WritePanelData<int>(id, NUM_DECORATIONS, {static_cast<int>(decorations.size())}); | 101 | _memory->WritePanelData<int>(id, NUM_DECORATIONS, {static_cast<int>(decorations.size())}); |
107 | _memory.WriteArray<int>(id, DECORATIONS, decorations); | 102 | _memory->WriteArray<int>(id, DECORATIONS, decorations); |
108 | } | 103 | } |
109 | 104 | ||
110 | void Panel::ReadIntersections(int id) { | 105 | void Panel::ReadIntersections(int id) { |
111 | int numIntersections = _memory.ReadPanelData<int>(id, NUM_DOTS, 1)[0]; | 106 | int numIntersections = _memory->ReadPanelData<int>(id, NUM_DOTS, 1)[0]; |
112 | std::vector<int> intersectionFlags = _memory.ReadArray<int>(id, DOT_FLAGS, numIntersections); | 107 | std::vector<int> intersectionFlags = _memory->ReadArray<int>(id, DOT_FLAGS, numIntersections); |
113 | 108 | ||
114 | int x = 0; | ||
115 | int y = _height - 1; | ||
116 | int i = 0; | 109 | int i = 0; |
117 | for (;; i++) { | 110 | for (;; i++) { |
111 | auto [x, y] = loc_to_xy(i); | ||
112 | if (y < 0) break; | ||
118 | if (intersectionFlags[i] & IntersectionFlags::IS_STARTPOINT) { | 113 | if (intersectionFlags[i] & IntersectionFlags::IS_STARTPOINT) { |
119 | _startpoints.push_back({x, y}); | 114 | _startpoints.push_back({x, y}); |
120 | } | 115 | } |
121 | x += 2; | ||
122 | if (x > _width) { | ||
123 | x = 0; | ||
124 | y -= 2; | ||
125 | } | ||
126 | if (y < 0) break; | ||
127 | } | 116 | } |
128 | 117 | ||
129 | std::pair<std::vector<int>, std::vector<int>> connections; | 118 | int numConnections = _memory->ReadPanelData<int>(id, NUM_CONNECTIONS, 1)[0]; |
130 | int numConnections = _memory.ReadPanelData<int>(id, NUM_CONNECTIONS, 1)[0]; | 119 | std::vector<int> connections_a = _memory->ReadArray<int>(id, DOT_CONNECTION_A, numConnections); |
131 | connections.first = _memory.ReadArray<int>(id, DOT_CONNECTION_A, numConnections); | 120 | std::vector<int> connections_b = _memory->ReadArray<int>(id, DOT_CONNECTION_B, numConnections); |
132 | connections.second = _memory.ReadArray<int>(id, DOT_CONNECTION_B, numConnections); | 121 | std::vector<float> intersections = _memory->ReadArray<float>(id, DOT_POSITIONS, numIntersections*2); |
133 | std::vector<float> intersections = _memory.ReadArray<float>(id, DOT_POSITIONS, numIntersections*2); | ||
134 | 122 | ||
135 | // Iterate the remaining intersections (either endpoints or gaps) | 123 | // Iterate the remaining intersections (endpoints, dots, gaps) |
136 | for (; i < numIntersections; i++) { | 124 | for (; i < numIntersections; i++) { |
137 | if (intersectionFlags[i] & IntersectionFlags::IS_ENDPOINT) { | 125 | if (intersectionFlags[i] & IntersectionFlags::IS_ENDPOINT) { |
138 | for (int j=0; j<numConnections; j++) { | 126 | for (int j=0; j<numConnections; j++) { |
139 | int location = 0; | 127 | int location = 0; |
140 | if (connections.first[j] == i) location = connections.second[j]; | 128 | if (connections_a[j] == i) location = connections_b[j]; |
141 | if (connections.second[j] == i) location = connections.first[j]; | 129 | if (connections_b[j] == i) location = connections_a[j]; |
142 | if (location != 0) { | 130 | if (location != 0) { |
143 | Endpoint::Direction dir; | 131 | Endpoint::Direction dir; |
144 | if (intersections[2*i] < intersections[2*location]) { // Our (i) x coordinate is less than the target's (location) | 132 | if (intersections[2*i] < intersections[2*location]) { // Our (i) x coordinate is less than the target's (location) |
@@ -152,6 +140,34 @@ void Panel::ReadIntersections(int id) { | |||
152 | } | 140 | } |
153 | auto [x, y] = loc_to_xy(location); | 141 | auto [x, y] = loc_to_xy(location); |
154 | _endpoints.push_back(Endpoint(x, y, dir)); | 142 | _endpoints.push_back(Endpoint(x, y, dir)); |
143 | break; | ||
144 | } | ||
145 | } | ||
146 | } else if (intersectionFlags[i] & IntersectionFlags::HAS_DOT) { | ||
147 | for (int j=0; j<numConnections; j++) { | ||
148 | int location = 0; | ||
149 | if (connections_a[j] == i) location = connections_b[j]; | ||
150 | if (connections_b[j] == i) location = connections_a[j]; | ||
151 | if (location != 0) { | ||
152 | auto [x, y] = loc_to_xy(location); | ||
153 | float x1 = intersections[2*i]; | ||
154 | float y1 = intersections[2*i+1]; | ||
155 | float x2 = intersections[2*location]; | ||
156 | float y2 = intersections[2*location+1]; | ||
157 | if (intersections[2*i] < intersections[2*location]) { | ||
158 | // Our (i) x coordinate is less than the target's (location), so we are to the left | ||
159 | x--; | ||
160 | } else if (intersections[2*i] > intersections[2*location]) { // To the right | ||
161 | x++; | ||
162 | } else if (intersections[2*i + 1] > intersections[2*location + 1]) { | ||
163 | // y coordinate is 0 (bottom) 1 (top), so this check is reversed. We are above the target (location) | ||
164 | y--; | ||
165 | } else { // Beleow the target | ||
166 | y++; | ||
167 | } | ||
168 | |||
169 | _grid[x][y] |= IntersectionFlags::HAS_DOT; | ||
170 | break; | ||
155 | } | 171 | } |
156 | } | 172 | } |
157 | } | 173 | } |
@@ -161,34 +177,41 @@ void Panel::ReadIntersections(int id) { | |||
161 | void Panel::WriteIntersections(int id) { | 177 | void Panel::WriteIntersections(int id) { |
162 | std::vector<float> intersections; | 178 | std::vector<float> intersections; |
163 | std::vector<int> intersectionFlags; | 179 | std::vector<int> intersectionFlags; |
164 | std::pair<std::vector<int>, std::vector<int>> connections; | 180 | std::vector<int> connections_a; |
181 | std::vector<int> connections_b; | ||
165 | 182 | ||
166 | double min = 0.1; | 183 | double min = 0.1; |
167 | double max = 0.9; | 184 | double max = 0.9; |
168 | double width_interval = (max - min) / (_width/2); | 185 | double width_interval = (max - min) / (_width/2); |
169 | double height_interval = (max - min) / (_height/2); | 186 | double height_interval = (max - min) / (_height/2); |
170 | 187 | ||
171 | for (int y=0; y<_height/2; y++) { | 188 | // TODO(future): Stop using push_back and set these into explicit locations, unrequires loop iteration order |
172 | for (int x=0; x<_width/2; x++) { | 189 | for (int y=_height-1; y>=0; y-=2) { |
173 | intersections.push_back(static_cast<float>(min + x * width_interval)); | 190 | for (int x=0; x<_width; x+=2) { |
174 | intersections.push_back(static_cast<float>(min + y * height_interval)); | 191 | intersections.push_back(static_cast<float>(min + (x/2) * width_interval)); |
192 | intersections.push_back(static_cast<float>(max - (y/2) * height_interval)); | ||
175 | int flags = 0; | 193 | int flags = 0; |
176 | if (find(_startpoints, {2*x, 2*y}) != -1) flags |= IntersectionFlags::IS_STARTPOINT; | 194 | if (find(_startpoints, {x, y}) != -1) flags |= IntersectionFlags::IS_STARTPOINT; |
177 | intersectionFlags.push_back(flags); | 195 | intersectionFlags.push_back(flags); |
196 | |||
197 | // Create connections for this intersection -- always write low -> high | ||
178 | if (y > 0) { | 198 | if (y > 0) { |
179 | connections.first.push_back(y * _width + x); | 199 | connections_a.push_back(xy_to_loc(x, y-2)); |
180 | connections.second.push_back((y - 1) * _width + x); | 200 | connections_b.push_back(xy_to_loc(x, y)); |
181 | } | 201 | } |
182 | if (x > 0) { | 202 | if (x > 0) { |
183 | connections.first.push_back(y * _width + x); | 203 | connections_a.push_back(xy_to_loc(x-2, y)); |
184 | connections.second.push_back(y * _width + (x - 1)); | 204 | connections_b.push_back(xy_to_loc(x, y)); |
185 | } | 205 | } |
186 | } | 206 | } |
187 | } | 207 | } |
188 | 208 | ||
189 | for (Endpoint endpoint : _endpoints) { | 209 | for (Endpoint endpoint : _endpoints) { |
190 | double xPos = min + endpoint.GetX() * width_interval; | 210 | connections_a.push_back(xy_to_loc(endpoint.GetX(), endpoint.GetY())); // Target to connect to |
191 | double yPos = min + endpoint.GetY() * height_interval; | 211 | connections_b.push_back(static_cast<int>(intersectionFlags.size())); // This endpoint |
212 | |||
213 | double xPos = min + (endpoint.GetX()/2) * width_interval; | ||
214 | double yPos = max - (endpoint.GetY()/2) * height_interval; | ||
192 | if (endpoint.GetDir()== Endpoint::Direction::LEFT) { | 215 | if (endpoint.GetDir()== Endpoint::Direction::LEFT) { |
193 | xPos -= .05; | 216 | xPos -= .05; |
194 | } else if (endpoint.GetDir() == Endpoint::Direction::RIGHT) { | 217 | } else if (endpoint.GetDir() == Endpoint::Direction::RIGHT) { |
@@ -200,18 +223,49 @@ void Panel::WriteIntersections(int id) { | |||
200 | } | 223 | } |
201 | intersections.push_back(static_cast<float>(xPos)); | 224 | intersections.push_back(static_cast<float>(xPos)); |
202 | intersections.push_back(static_cast<float>(yPos)); | 225 | intersections.push_back(static_cast<float>(yPos)); |
203 | |||
204 | connections.first.push_back(endpoint.GetY() * _width + endpoint.GetX()); // Target to connect to | ||
205 | connections.second.push_back(static_cast<int>(intersectionFlags.size())); // This endpoint | ||
206 | intersectionFlags.push_back(IntersectionFlags::IS_ENDPOINT); | 226 | intersectionFlags.push_back(IntersectionFlags::IS_ENDPOINT); |
207 | } | 227 | } |
208 | 228 | ||
209 | _memory.WritePanelData<int>(id, NUM_DOTS, {static_cast<int>(intersectionFlags.size())}); | 229 | // Dots |
210 | _memory.WriteArray<float>(id, DOT_POSITIONS, intersections); | 230 | for (int y=0; y<_height; y++) { |
211 | _memory.WriteArray<int>(id, DOT_FLAGS, intersectionFlags); | 231 | for (int x=0; x<_width; x++) { |
212 | _memory.WritePanelData<int>(id, NUM_CONNECTIONS, {static_cast<int>(connections.first.size())}); | 232 | if (!(_grid[x][y] & IntersectionFlags::HAS_DOT)) continue; |
213 | _memory.WriteArray<int>(id, DOT_CONNECTION_A, connections.first); | 233 | if (x%2 == 1 && y%2 == 1) continue; |
214 | _memory.WriteArray<int>(id, DOT_CONNECTION_B, connections.second); | 234 | if (x%2 == 0 && y%2 == 0) { |
215 | _memory.WritePanelData<int>(id, NEEDS_REDRAW, {1}); | 235 | intersectionFlags[xy_to_loc(x, y)] |= _grid[x][y]; |
236 | continue; | ||
237 | } | ||
238 | |||
239 | // Locate the segment we're breaking | ||
240 | for (int i=0; i<connections_a.size(); i++) { | ||
241 | auto [x1, y1] = loc_to_xy(connections_a[i]); | ||
242 | auto [x2, y2] = loc_to_xy(connections_b[i]); | ||
243 | if ((x1+1 == x && x2-1 == x && y1 == y && y2 == y) || | ||
244 | (y1+1 == y && y2-1 == y && x1 == x && x2 == x)) { | ||
245 | int other_connection = connections_b[i]; | ||
246 | connections_b[i] = static_cast<int>(intersectionFlags.size()); // This endpoint | ||
247 | |||
248 | connections_a.push_back(static_cast<int>(intersectionFlags.size())); // This endpoint | ||
249 | connections_b.push_back(other_connection); | ||
250 | break; | ||
251 | } | ||
252 | } | ||
253 | // Add this dot to the end | ||
254 | double xPos = min + (x/2.0) * width_interval; | ||
255 | double yPos = max - (y/2.0) * height_interval; | ||
256 | intersections.push_back(static_cast<float>(xPos)); | ||
257 | intersections.push_back(static_cast<float>(yPos)); | ||
258 | intersectionFlags.push_back(_grid[x][y]); | ||
259 | } | ||
260 | } | ||
261 | |||
262 | |||
263 | _memory->WritePanelData<int>(id, NUM_DOTS, {static_cast<int>(intersectionFlags.size())}); | ||
264 | _memory->WriteArray<float>(id, DOT_POSITIONS, intersections); | ||
265 | _memory->WriteArray<int>(id, DOT_FLAGS, intersectionFlags); | ||
266 | _memory->WritePanelData<int>(id, NUM_CONNECTIONS, {static_cast<int>(connections_a.size())}); | ||
267 | _memory->WriteArray<int>(id, DOT_CONNECTION_A, connections_a); | ||
268 | _memory->WriteArray<int>(id, DOT_CONNECTION_B, connections_b); | ||
269 | _memory->WritePanelData<int>(id, NEEDS_REDRAW, {1}); | ||
216 | } | 270 | } |
217 | 271 | ||