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 | |
| 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')
| -rw-r--r-- | Source/Panel.cpp | 178 | ||||
| -rw-r--r-- | Source/Panel.h | 30 |
2 files changed, 141 insertions, 67 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 | ||
| diff --git a/Source/Panel.h b/Source/Panel.h index 565b4c3..b8e67df 100644 --- a/Source/Panel.h +++ b/Source/Panel.h | |||
| @@ -45,7 +45,7 @@ enum IntersectionFlags { | |||
| 45 | IS_ENDPOINT = 0x1, | 45 | IS_ENDPOINT = 0x1, |
| 46 | IS_STARTPOINT = 0x2, | 46 | IS_STARTPOINT = 0x2, |
| 47 | IS_GAP = 0x10000, | 47 | IS_GAP = 0x10000, |
| 48 | HAS_DOT = 0x20, | 48 | HAS_DOT = 0x40020, |
| 49 | DOT_IS_BLUE = 0x100, | 49 | DOT_IS_BLUE = 0x100, |
| 50 | DOT_IS_ORANGE = 0x200, | 50 | DOT_IS_ORANGE = 0x200, |
| 51 | DOT_IS_INVISIBLE = 0x1000, | 51 | DOT_IS_INVISIBLE = 0x1000, |
| @@ -110,7 +110,7 @@ public: | |||
| 110 | 110 | ||
| 111 | private: | 111 | private: |
| 112 | // For testing | 112 | // For testing |
| 113 | Panel(); | 113 | Panel() = default; |
| 114 | 114 | ||
| 115 | void ReadIntersections(int id); | 115 | void ReadIntersections(int id); |
| 116 | void WriteIntersections(int id); | 116 | void WriteIntersections(int id); |
| @@ -121,8 +121,11 @@ private: | |||
| 121 | // TODO: Decoration colors | 121 | // TODO: Decoration colors |
| 122 | 122 | ||
| 123 | std::tuple<int, int> loc_to_xy(int location) { | 123 | std::tuple<int, int> loc_to_xy(int location) { |
| 124 | int x = 2 * (location % ((_width + 1) / 2)); | 124 | int height2 = (_height - 1) / 2; |
| 125 | int y = (_height - 1) - 2 * (location / ((_width + 1) / 2)); | 125 | int width2 = (_width + 1) / 2; |
| 126 | |||
| 127 | int x = 2 * (location % width2); | ||
| 128 | int y = 2 * (height2 - location / width2); | ||
| 126 | return {x, y}; | 129 | return {x, y}; |
| 127 | } | 130 | } |
| 128 | 131 | ||
| @@ -134,7 +137,24 @@ private: | |||
| 134 | return rowsFromBottom * width2 + x/2; | 137 | return rowsFromBottom * width2 + x/2; |
| 135 | } | 138 | } |
| 136 | 139 | ||
| 137 | Memory _memory = Memory("witness64_d3d11.exe"); | 140 | std::tuple<int, int> dloc_to_xy(int location) { |
| 141 | int height2 = (_height - 3) / 2; | ||
| 142 | int width2 = (_width - 1) / 2; | ||
| 143 | |||
| 144 | int x = 2 * (location % width2) + 1; | ||
| 145 | int y = 2 * (height2 - location / width2) + 1; | ||
| 146 | return {x, y}; | ||
| 147 | } | ||
| 148 | |||
| 149 | int xy_to_dloc(int x, int y) { | ||
| 150 | int height2 = (_height - 3) / 2; | ||
| 151 | int width2 = (_width - 1) / 2; | ||
| 152 | |||
| 153 | int rowsFromBottom = height2 - (y - 1)/2; | ||
| 154 | return rowsFromBottom * width2 + (x - 1)/2; | ||
| 155 | } | ||
| 156 | |||
| 157 | std::shared_ptr<Memory> _memory; | ||
| 138 | 158 | ||
| 139 | int _width, _height; | 159 | int _width, _height; |
| 140 | 160 | ||
