about summary refs log tree commit diff stats
path: root/Source/Panel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Panel.cpp')
-rw-r--r--Source/Panel.cpp178
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
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