about summary refs log tree commit diff stats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/Panel.cpp178
-rw-r--r--Source/Panel.h30
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
15Panel::Panel(int id) { 15Panel::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
26Panel::Panel() {}
27
28void Panel::Write(int id) { 26void 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
36nlohmann::json Panel::Serialize() { 34nlohmann::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
82void Panel::ReadDecorations(int id) { 83void 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
98void Panel::WriteDecorations(int id) { 93void 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
110void Panel::ReadIntersections(int id) { 105void 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) {
161void Panel::WriteIntersections(int id) { 177void 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
111private: 111private:
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