diff options
-rw-r--r-- | App/Main.cpp | 6 | ||||
-rw-r--r-- | Installer/Installer.vdproj | 6 | ||||
-rw-r--r-- | Source/Panel.cpp | 178 | ||||
-rw-r--r-- | Source/Panel.h | 30 | ||||
-rw-r--r-- | Test/PanelExtractionTests.cpp | 119 |
5 files changed, 239 insertions, 100 deletions
diff --git a/App/Main.cpp b/App/Main.cpp index ab3e88a..6ebef7e 100644 --- a/App/Main.cpp +++ b/App/Main.cpp | |||
@@ -19,8 +19,8 @@ | |||
19 | #define IDT_RANDOMIZED 0x409 | 19 | #define IDT_RANDOMIZED 0x409 |
20 | 20 | ||
21 | HWND hwndSeed, hwndRandomize; | 21 | HWND hwndSeed, hwndRandomize; |
22 | int panel = 0x18AF; | 22 | // int panel = 0x18AF; |
23 | // int panel = 0x33D4; | 23 | int panel = 0x33D4; |
24 | std::shared_ptr<Panel> _panel; | 24 | std::shared_ptr<Panel> _panel; |
25 | std::shared_ptr<Randomizer> randomizer = std::make_shared<Randomizer>(); | 25 | std::shared_ptr<Randomizer> randomizer = std::make_shared<Randomizer>(); |
26 | 26 | ||
@@ -94,7 +94,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) | |||
94 | _panel->Write(panel); | 94 | _panel->Write(panel); |
95 | break; | 95 | break; |
96 | case IDC_DUMP: | 96 | case IDC_DUMP: |
97 | // _panel->Serialize(); | 97 | _panel->Serialize(); |
98 | break; | 98 | break; |
99 | } | 99 | } |
100 | } | 100 | } |
diff --git a/Installer/Installer.vdproj b/Installer/Installer.vdproj index 9b05e20..19d6036 100644 --- a/Installer/Installer.vdproj +++ b/Installer/Installer.vdproj | |||
@@ -125,7 +125,7 @@ | |||
125 | } | 125 | } |
126 | "{3C67513D-01DD-4637-8A68-80971EB9504F}:_8E9D847124D34D9D9008762077D816DE" | 126 | "{3C67513D-01DD-4637-8A68-80971EB9504F}:_8E9D847124D34D9D9008762077D816DE" |
127 | { | 127 | { |
128 | "DefaultLocation" = "8:[ProgramFilesFolder][Manufacturer]\\[ProductName]" | 128 | "DefaultLocation" = "8:[ProgramFiles64Folder][Manufacturer]\\[ProductName]" |
129 | "Name" = "8:#1925" | 129 | "Name" = "8:#1925" |
130 | "AlwaysCreate" = "11:FALSE" | 130 | "AlwaysCreate" = "11:FALSE" |
131 | "Condition" = "8:" | 131 | "Condition" = "8:" |
@@ -163,7 +163,7 @@ | |||
163 | "Name" = "8:Microsoft Visual Studio" | 163 | "Name" = "8:Microsoft Visual Studio" |
164 | "ProductName" = "8:Witness Randomizer" | 164 | "ProductName" = "8:Witness Randomizer" |
165 | "ProductCode" = "8:{7DD620CA-9593-4E32-9D60-9D12069DA33C}" | 165 | "ProductCode" = "8:{7DD620CA-9593-4E32-9D60-9D12069DA33C}" |
166 | "PackageCode" = "8:{90B5567A-BE63-4F98-A6C8-5FAC1942075A}" | 166 | "PackageCode" = "8:{BBA8F7F1-52D8-44B0-BC53-9AC3F0181E3D}" |
167 | "UpgradeCode" = "8:{4CB5496B-A47E-41D3-B4A7-677E29AB7513}" | 167 | "UpgradeCode" = "8:{4CB5496B-A47E-41D3-B4A7-677E29AB7513}" |
168 | "AspNetVersion" = "8:2.0.50727.0" | 168 | "AspNetVersion" = "8:2.0.50727.0" |
169 | "RestartWWWService" = "11:FALSE" | 169 | "RestartWWWService" = "11:FALSE" |
@@ -184,7 +184,7 @@ | |||
184 | "ARPIconIndex" = "3:0" | 184 | "ARPIconIndex" = "3:0" |
185 | "SearchPath" = "8:" | 185 | "SearchPath" = "8:" |
186 | "UseSystemSearchPath" = "11:TRUE" | 186 | "UseSystemSearchPath" = "11:TRUE" |
187 | "TargetPlatform" = "3:0" | 187 | "TargetPlatform" = "3:1" |
188 | "PreBuildEvent" = "8:" | 188 | "PreBuildEvent" = "8:" |
189 | "PostBuildEvent" = "8:" | 189 | "PostBuildEvent" = "8:" |
190 | "RunPostBuildEvent" = "3:0" | 190 | "RunPostBuildEvent" = "3:0" |
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 | ||
diff --git a/Test/PanelExtractionTests.cpp b/Test/PanelExtractionTests.cpp index dfb9b9e..099fab2 100644 --- a/Test/PanelExtractionTests.cpp +++ b/Test/PanelExtractionTests.cpp | |||
@@ -4,7 +4,8 @@ | |||
4 | class PanelExtractionTests : public testing::Test | 4 | class PanelExtractionTests : public testing::Test |
5 | { | 5 | { |
6 | protected: | 6 | protected: |
7 | Panel _panel; | 7 | // Test constructor, does not attach to process |
8 | Panel _panel = Panel(); | ||
8 | // std::shared_ptr<Panel> _panel; | 9 | // std::shared_ptr<Panel> _panel; |
9 | 10 | ||
10 | void SetPanelSize(int width, int height) { | 11 | void SetPanelSize(int width, int height) { |
@@ -13,22 +14,88 @@ protected: | |||
13 | _panel._height = height; | 14 | _panel._height = height; |
14 | } | 15 | } |
15 | 16 | ||
16 | std::tuple<int, int> loc_to_xy(int location) { | 17 | std::tuple<int, int> loc_to_xy(int location) {return _panel.loc_to_xy(location);} |
17 | return _panel.loc_to_xy(location); | 18 | int xy_to_loc(int x, int y) {return _panel.xy_to_loc(x, y);} |
18 | } | 19 | std::tuple<int, int> dloc_to_xy(int location) {return _panel.dloc_to_xy(location);} |
19 | 20 | int xy_to_dloc(int x, int y) {return _panel.xy_to_dloc(x, y);} | |
20 | int xy_to_loc(int x, int y) { | ||
21 | return _panel.xy_to_loc(x, y); | ||
22 | } | ||
23 | }; | 21 | }; |
24 | 22 | ||
25 | TEST_F(PanelExtractionTests, LocToXY_7x5) { | 23 | TEST_F(PanelExtractionTests, 1x1) { |
24 | SetPanelSize(1, 1); | ||
25 | /* Here's the panel, with the correct location order | ||
26 | 0(_width = 1) | ||
27 | (_height = 1) | ||
28 | */ | ||
29 | ASSERT_EQ(0, xy_to_loc(0, 0)); | ||
30 | ASSERT_EQ((std::tuple<int, int>{0, 0}), loc_to_xy(0)); | ||
31 | } | ||
32 | |||
33 | TEST_F(PanelExtractionTests, 7x1) { | ||
34 | SetPanelSize(7, 1); | ||
35 | /* Here's the panel, with the correct location order | ||
36 | 3 . 2 . 1 . 0(_width = 7) | ||
37 | (_height = 1) | ||
38 | */ | ||
39 | ASSERT_EQ(0, xy_to_loc(0, 0)); | ||
40 | ASSERT_EQ(1, xy_to_loc(2, 0)); | ||
41 | ASSERT_EQ(2, xy_to_loc(4, 0)); | ||
42 | ASSERT_EQ(3, xy_to_loc(6, 0)); | ||
43 | ASSERT_EQ((std::tuple<int, int>{0, 0}), loc_to_xy(0)); | ||
44 | ASSERT_EQ((std::tuple<int, int>{2, 0}), loc_to_xy(1)); | ||
45 | ASSERT_EQ((std::tuple<int, int>{4, 0}), loc_to_xy(2)); | ||
46 | ASSERT_EQ((std::tuple<int, int>{6, 0}), loc_to_xy(3)); | ||
47 | } | ||
48 | |||
49 | TEST_F(PanelExtractionTests, 1x7) { | ||
50 | SetPanelSize(1, 7); | ||
51 | /* Here's the panel, with the correct location order | ||
52 | 3(_width = 1) | ||
53 | . | ||
54 | 2 | ||
55 | . | ||
56 | 1 | ||
57 | . | ||
58 | 0 | ||
59 | (_height = 7) | ||
60 | */ | ||
61 | ASSERT_EQ(0, xy_to_loc(0, 6)); | ||
62 | ASSERT_EQ(1, xy_to_loc(0, 4)); | ||
63 | ASSERT_EQ(2, xy_to_loc(0, 2)); | ||
64 | ASSERT_EQ(3, xy_to_loc(0, 0)); | ||
65 | ASSERT_EQ((std::tuple<int, int>{0, 6}), loc_to_xy(0)); | ||
66 | ASSERT_EQ((std::tuple<int, int>{0, 4}), loc_to_xy(1)); | ||
67 | ASSERT_EQ((std::tuple<int, int>{0, 2}), loc_to_xy(2)); | ||
68 | ASSERT_EQ((std::tuple<int, int>{0, 0}), loc_to_xy(3)); | ||
69 | } | ||
70 | |||
71 | TEST_F(PanelExtractionTests, 3x3) { | ||
72 | SetPanelSize(3, 3); | ||
73 | /* Here's the panel, with the correct location order | ||
74 | 2 . 3 (_width = 3) | ||
75 | . A . | ||
76 | 0 . 1 | ||
77 | (_height = 3) | ||
78 | */ | ||
79 | ASSERT_EQ(0, xy_to_loc(0, 2)); | ||
80 | ASSERT_EQ(1, xy_to_loc(2, 2)); | ||
81 | ASSERT_EQ(2, xy_to_loc(0, 0)); | ||
82 | ASSERT_EQ(3, xy_to_loc(2, 0)); | ||
83 | ASSERT_EQ((std::tuple<int, int>{0, 2}), loc_to_xy(0)); | ||
84 | ASSERT_EQ((std::tuple<int, int>{2, 2}), loc_to_xy(1)); | ||
85 | ASSERT_EQ((std::tuple<int, int>{0, 0}), loc_to_xy(2)); | ||
86 | ASSERT_EQ((std::tuple<int, int>{2, 0}), loc_to_xy(3)); | ||
87 | |||
88 | ASSERT_EQ(0, xy_to_dloc(1, 1)); | ||
89 | ASSERT_EQ((std::tuple<int, int>{1, 1}), dloc_to_xy(0)); | ||
90 | } | ||
91 | |||
92 | TEST_F(PanelExtractionTests, 7x5) { | ||
26 | SetPanelSize(7, 5); | 93 | SetPanelSize(7, 5); |
27 | /* Here's the panel, with the correct location order | 94 | /* Here's the panel, with the correct location order |
28 | 8 . 9 . 10. 11 (_width = 7) | 95 | 8 . 9 . 10. 11 (_width = 7) |
29 | . . . . . . . | 96 | . D . E . F . |
30 | 4 . 5 . 6 . 7 | 97 | 4 . 5 . 6 . 7 |
31 | . . . . . . . | 98 | . A . B . C . |
32 | 0 . 1 . 2 . 3 | 99 | 0 . 1 . 2 . 3 |
33 | (_height = 5) | 100 | (_height = 5) |
34 | */ | 101 | */ |
@@ -36,28 +103,26 @@ TEST_F(PanelExtractionTests, LocToXY_7x5) { | |||
36 | ASSERT_EQ(1, xy_to_loc(2, 4)); | 103 | ASSERT_EQ(1, xy_to_loc(2, 4)); |
37 | ASSERT_EQ(2, xy_to_loc(4, 4)); | 104 | ASSERT_EQ(2, xy_to_loc(4, 4)); |
38 | ASSERT_EQ(3, xy_to_loc(6, 4)); | 105 | ASSERT_EQ(3, xy_to_loc(6, 4)); |
106 | ASSERT_EQ((std::tuple<int, int>{0, 4}), loc_to_xy(0)); | ||
107 | ASSERT_EQ((std::tuple<int, int>{2, 4}), loc_to_xy(1)); | ||
108 | ASSERT_EQ((std::tuple<int, int>{4, 4}), loc_to_xy(2)); | ||
109 | ASSERT_EQ((std::tuple<int, int>{6, 4}), loc_to_xy(3)); | ||
39 | 110 | ||
40 | ASSERT_EQ(4, xy_to_loc(0, 2)); | 111 | ASSERT_EQ(4, xy_to_loc(0, 2)); |
41 | ASSERT_EQ(5, xy_to_loc(2, 2)); | 112 | ASSERT_EQ(5, xy_to_loc(2, 2)); |
42 | ASSERT_EQ(6, xy_to_loc(4, 2)); | 113 | ASSERT_EQ(6, xy_to_loc(4, 2)); |
43 | ASSERT_EQ(7, xy_to_loc(6, 2)); | 114 | ASSERT_EQ(7, xy_to_loc(6, 2)); |
115 | ASSERT_EQ((std::tuple<int, int>{0, 2}), loc_to_xy(4)); | ||
116 | ASSERT_EQ((std::tuple<int, int>{2, 2}), loc_to_xy(5)); | ||
117 | ASSERT_EQ((std::tuple<int, int>{4, 2}), loc_to_xy(6)); | ||
118 | ASSERT_EQ((std::tuple<int, int>{6, 2}), loc_to_xy(7)); | ||
44 | 119 | ||
45 | ASSERT_EQ(8, xy_to_loc(0, 0)); | 120 | ASSERT_EQ(8, xy_to_loc(0, 0)); |
46 | ASSERT_EQ(9, xy_to_loc(2, 0)); | 121 | ASSERT_EQ(9, xy_to_loc(2, 0)); |
47 | ASSERT_EQ(10, xy_to_loc(4, 0)); | 122 | ASSERT_EQ(10, xy_to_loc(4, 0)); |
48 | ASSERT_EQ(11, xy_to_loc(6, 0)); | 123 | ASSERT_EQ(11, xy_to_loc(6, 0)); |
124 | ASSERT_EQ((std::tuple<int, int>{0, 0}), loc_to_xy(8)); | ||
125 | ASSERT_EQ((std::tuple<int, int>{2, 0}), loc_to_xy(9)); | ||
126 | ASSERT_EQ((std::tuple<int, int>{4, 0}), loc_to_xy(10)); | ||
127 | ASSERT_EQ((std::tuple<int, int>{6, 0}), loc_to_xy(11)); | ||
49 | } | 128 | } |
50 | |||
51 | TEST_F(PanelExtractionTests, LocToXY_3x3) { | ||
52 | SetPanelSize(3, 3); | ||
53 | /* Here's the panel, with the correct location order | ||
54 | 2 . 3 (_width = 3) | ||
55 | . . . | ||
56 | 0 . 1 | ||
57 | (_height = 3) | ||
58 | */ | ||
59 | ASSERT_EQ(0, xy_to_loc(0, 2)); | ||
60 | ASSERT_EQ(1, xy_to_loc(2, 2)); | ||
61 | ASSERT_EQ(2, xy_to_loc(0, 0)); | ||
62 | ASSERT_EQ(3, xy_to_loc(2, 0)); | ||
63 | } \ No newline at end of file | ||