summary refs log tree commit diff stats
path: root/Source/PuzzleSerializer.cpp
diff options
context:
space:
mode:
authorjbzdarkid <jbzdarkid@gmail.com>2019-11-20 10:05:59 -0800
committerjbzdarkid <jbzdarkid@gmail.com>2019-11-20 10:05:59 -0800
commit6f0a34bfb761d965bd961dc1f880b84e35f9959f (patch)
tree9fad4b4d98f5cb644b635c017a959dd3752a0399 /Source/PuzzleSerializer.cpp
parentab5652329d3e6bbaaf338e47fb3d84d89bf9b7b1 (diff)
downloadwitness-tutorializer-6f0a34bfb761d965bd961dc1f880b84e35f9959f.tar.gz
witness-tutorializer-6f0a34bfb761d965bd961dc1f880b84e35f9959f.tar.bz2
witness-tutorializer-6f0a34bfb761d965bd961dc1f880b84e35f9959f.zip
Understanding symmetry, but nothing else.
Diffstat (limited to 'Source/PuzzleSerializer.cpp')
-rw-r--r--Source/PuzzleSerializer.cpp98
1 files changed, 70 insertions, 28 deletions
diff --git a/Source/PuzzleSerializer.cpp b/Source/PuzzleSerializer.cpp index 5c91b56..132ebb7 100644 --- a/Source/PuzzleSerializer.cpp +++ b/Source/PuzzleSerializer.cpp
@@ -14,12 +14,12 @@ Puzzle PuzzleSerializer::ReadPuzzle(int id) {
14 if (height == 0) height = width; 14 if (height == 0) height = width;
15 if (width < 0 || height < 0) return Puzzle(); // @Error: Grid size should be always positive? Looks like the starting panels break this rule, though. 15 if (width < 0 || height < 0) return Puzzle(); // @Error: Grid size should be always positive? Looks like the starting panels break this rule, though.
16 16
17 int numIntersections = _memory->ReadEntityData<int>(id, NUM_DOTS, 1)[0]; 17 _numIntersections = _memory->ReadEntityData<int>(id, NUM_DOTS, 1)[0];
18 _intersectionFlags = _memory->ReadArray<int>(id, DOT_FLAGS, numIntersections); 18 _intersectionFlags = _memory->ReadArray<int>(id, DOT_FLAGS, _numIntersections);
19 int numConnections = _memory->ReadEntityData<int>(id, NUM_CONNECTIONS, 1)[0]; 19 int numConnections = _memory->ReadEntityData<int>(id, NUM_CONNECTIONS, 1)[0];
20 _connectionsA = _memory->ReadArray<int>(id, DOT_CONNECTION_A, numConnections); 20 _connectionsA = _memory->ReadArray<int>(id, DOT_CONNECTION_A, numConnections);
21 _connectionsB = _memory->ReadArray<int>(id, DOT_CONNECTION_B, numConnections); 21 _connectionsB = _memory->ReadArray<int>(id, DOT_CONNECTION_B, numConnections);
22 _intersectionLocations = _memory->ReadArray<float>(id, DOT_POSITIONS, numIntersections*2); 22 _intersectionLocations = _memory->ReadArray<float>(id, DOT_POSITIONS, _numIntersections*2);
23 23
24 Puzzle p; 24 Puzzle p;
25 p.NewGrid(width, height); 25 p.NewGrid(width, height);
@@ -27,6 +27,7 @@ Puzzle PuzzleSerializer::ReadPuzzle(int id) {
27 ReadExtras(p); 27 ReadExtras(p);
28 ReadDecorations(p, id); 28 ReadDecorations(p, id);
29 ReadSequence(p, id); 29 ReadSequence(p, id);
30 ReadSymmetry(p, id);
30 return p; 31 return p;
31} 32}
32 33
@@ -80,7 +81,7 @@ void PuzzleSerializer::ReadIntersections(Puzzle& p) {
80 } 81 }
81 } 82 }
82 83
83 for (int j=0; j<_intersectionFlags.size(); j++) { 84 for (int j=0; j<_numIntersections; j++) {
84 if (_intersectionFlags[_connectionsA[j]] & Flags::IS_ENDPOINT) break; 85 if (_intersectionFlags[_connectionsA[j]] & Flags::IS_ENDPOINT) break;
85 if (_intersectionFlags[_connectionsB[j]] & Flags::IS_ENDPOINT) break; 86 if (_intersectionFlags[_connectionsB[j]] & Flags::IS_ENDPOINT) break;
86 float x1 = _intersectionLocations[2*_connectionsA[j]]; 87 float x1 = _intersectionLocations[2*_connectionsA[j]];
@@ -100,7 +101,7 @@ void PuzzleSerializer::ReadIntersections(Puzzle& p) {
100void PuzzleSerializer::ReadExtras(Puzzle& p) { 101void PuzzleSerializer::ReadExtras(Puzzle& p) {
101 // This iterates bottom-top, left-right 102 // This iterates bottom-top, left-right
102 int i = 0; 103 int i = 0;
103 for (; i < _intersectionFlags.size(); i++) { 104 for (; i < _numIntersections; i++) {
104 int flags = _intersectionFlags[i]; 105 int flags = _intersectionFlags[i];
105 auto [x, y] = loc_to_xy(p, i); 106 auto [x, y] = loc_to_xy(p, i);
106 if (y < 0) break; // This is the expected exit point 107 if (y < 0) break; // This is the expected exit point
@@ -114,7 +115,7 @@ void PuzzleSerializer::ReadExtras(Puzzle& p) {
114 } 115 }
115 116
116 // Iterate the remaining intersections (endpoints, dots, gaps) 117 // Iterate the remaining intersections (endpoints, dots, gaps)
117 for (; i < _intersectionFlags.size(); i++) { 118 for (; i < _numIntersections; i++) {
118 int location = FindConnection(i); 119 int location = FindConnection(i);
119 if (location == -1) continue; // @Error: Unable to find connection point 120 if (location == -1) continue; // @Error: Unable to find connection point
120 // (x1, y1) location of this intersection 121 // (x1, y1) location of this intersection
@@ -177,8 +178,23 @@ void PuzzleSerializer::ReadSequence(Puzzle& p, int id) {
177 std::vector<int> sequence = _memory->ReadArray<int>(id, SEQUENCE, sequenceLength); 178 std::vector<int> sequence = _memory->ReadArray<int>(id, SEQUENCE, sequenceLength);
178 179
179 for (int location : sequence) { 180 for (int location : sequence) {
180 auto [x, y] = loc_to_xy(p, location); 181 p.sequence.emplace_back(loc_to_xy(p, location));
181 p.sequence.emplace_back(Pos{x, y}); 182 }
183}
184
185void PuzzleSerializer::ReadSymmetry(Puzzle& p, int id) {
186 int hasSymmetry = _memory->ReadEntityData<int>(id, REFLECTION_DATA, 1)[0];
187 if (hasSymmetry == 0) return; // Array is null, no puzzle symmetry
188
189 std::vector<int> reflectionData = _memory->ReadArray<int>(id, REFLECTION_DATA, _numIntersections);
190 Pos p1 = loc_to_xy(p, reflectionData[0]);
191 Pos p2 = loc_to_xy(p, reflectionData[reflectionData[0]]);
192 if (p1.x != p2.x) {
193 p.symmetry = Puzzle::Symmetry::Y;
194 } else if (p1.y != p2.y) {
195 p.symmetry = Puzzle::Symmetry::X;
196 } else {
197 p.symmetry = Puzzle::Symmetry::XY;
182 } 198 }
183} 199}
184 200
@@ -188,9 +204,6 @@ void PuzzleSerializer::WriteIntersections(const Puzzle& p) {
188 // Grided intersections 204 // Grided intersections
189 for (int y=p.height-1; y>=0; y-=2) { 205 for (int y=p.height-1; y>=0; y-=2) {
190 for (int x=0; x<p.width; x+=2) { 206 for (int x=0; x<p.width; x+=2) {
191 auto [xPos, yPos] = xy_to_pos(p, x, y);
192 _intersectionLocations.push_back(xPos);
193 _intersectionLocations.push_back(yPos);
194 int flags = 0; 207 int flags = 0;
195 if (p.grid[x][y].start) { 208 if (p.grid[x][y].start) {
196 flags |= Flags::IS_STARTPOINT; 209 flags |= Flags::IS_STARTPOINT;
@@ -240,7 +253,8 @@ void PuzzleSerializer::WriteIntersections(const Puzzle& p) {
240 if (numConnections == 0) flags |= HAS_NO_CONN; 253 if (numConnections == 0) flags |= HAS_NO_CONN;
241 if (numConnections == 1) flags |= HAS_ONE_CONN; 254 if (numConnections == 1) flags |= HAS_ONE_CONN;
242 255
243 _intersectionFlags.push_back(flags); 256 auto [xPos, yPos] = xy_to_pos(p, x, y);
257 AddIntersection(x, y, xPos, yPos, flags);
244 } 258 }
245 } 259 }
246} 260}
@@ -267,10 +281,7 @@ void PuzzleSerializer::WriteEndpoints(const Puzzle& p) {
267 yPos -= .05f; 281 yPos -= .05f;
268 break; 282 break;
269 } 283 }
270 _endpointLocations.emplace_back(x, y, static_cast<int>(_intersectionFlags.size())); 284 AddIntersection(x, y, xPos, yPos, Flags::IS_ENDPOINT);
271 _intersectionLocations.push_back(xPos);
272 _intersectionLocations.push_back(yPos);
273 _intersectionFlags.push_back(Flags::IS_ENDPOINT);
274 } 285 }
275 } 286 }
276} 287}
@@ -300,11 +311,6 @@ void PuzzleSerializer::WriteDots(const Puzzle& p) {
300 _connectionsA.push_back(other_connection); 311 _connectionsA.push_back(other_connection);
301 _connectionsB.push_back(static_cast<int>(_intersectionFlags.size())); 312 _connectionsB.push_back(static_cast<int>(_intersectionFlags.size()));
302 313
303 // Add this dot to the end
304 auto [xPos, yPos] = xy_to_pos(p, x, y);
305 _intersectionLocations.push_back(xPos);
306 _intersectionLocations.push_back(yPos);
307
308 int flags = Flags::HAS_DOT; 314 int flags = Flags::HAS_DOT;
309 switch (p.grid[x][y].dot) { 315 switch (p.grid[x][y].dot) {
310 case Cell::Dot::BLACK: 316 case Cell::Dot::BLACK:
@@ -319,7 +325,9 @@ void PuzzleSerializer::WriteDots(const Puzzle& p) {
319 flags |= DOT_IS_INVISIBLE; 325 flags |= DOT_IS_INVISIBLE;
320 break; 326 break;
321 } 327 }
322 _intersectionFlags.push_back(flags); 328
329 auto [xPos, yPos] = xy_to_pos(p, x, y);
330 AddIntersection(x, y, xPos, yPos, flags);
323 } 331 }
324 } 332 }
325} 333}
@@ -409,17 +417,36 @@ void PuzzleSerializer::WriteSequence(const Puzzle& p, int id) {
409 } 417 }
410 418
411 Pos endpoint = p.sequence[p.sequence.size() - 1]; 419 Pos endpoint = p.sequence[p.sequence.size() - 1];
412 for (auto [x, y, location] : _endpointLocations) { 420 int location = extra_xy_to_loc(endpoint);
413 if (x == endpoint.x && y == endpoint.y) {
414 sequence.emplace_back(location);
415 break;
416 }
417 }
418 421
419 _memory->WriteEntityData<int>(id, SEQUENCE_LEN, {static_cast<int>(sequence.size())}); 422 _memory->WriteEntityData<int>(id, SEQUENCE_LEN, {static_cast<int>(sequence.size())});
420 _memory->WriteNewArray<int>(id, SEQUENCE, sequence); 423 _memory->WriteNewArray<int>(id, SEQUENCE, sequence);
421} 424}
422 425
426void PuzzleSerializer::WriteSymmetry(const Puzzle& p, int id) {
427 if (p.symmetry == Puzzle::Symmetry::NONE) {
428 _memory->WriteEntityData<int>(id, REFLECTION_DATA, {0});
429 return;
430 }
431
432 // TODO: This. Probably 3 different sections for the different types?
433 // The idea is simple, though, just write symmetry data for all endpoints.
434 // Handle the default grid... then just separate iterators for dots/gaps/endpoints? Gross, but might work.
435 // I think this might put constraints on how I build the dots/gaps, actually. Let me see.
436 /*
437 Pos p1 = loc_to_xy(p, reflectionData[0]);
438 Pos p2 = loc_to_xy(p, reflectionData[reflectionData[0]]);
439 if (p1.x != p2.x) {
440 p.symmetry = Puzzle::Symmetry::Y;
441 } else if (p1.y != p2.y) {
442 p.symmetry = Puzzle::Symmetry::X;
443 } else {
444 p.symmetry = Puzzle::Symmetry::XY;
445 }
446
447 */
448}
449
423std::tuple<int, int> PuzzleSerializer::loc_to_xy(const Puzzle& p, int location) const { 450std::tuple<int, int> PuzzleSerializer::loc_to_xy(const Puzzle& p, int location) const {
424 int height2 = (p.height - 1) / 2; 451 int height2 = (p.height - 1) / 2;
425 int width2 = (p.width + 1) / 2; 452 int width2 = (p.width + 1) / 2;
@@ -437,6 +464,14 @@ int PuzzleSerializer::xy_to_loc(const Puzzle& p, int x, int y) const {
437 return rowsFromBottom * width2 + x/2; 464 return rowsFromBottom * width2 + x/2;
438} 465}
439 466
467int PuzzleSerializer::extra_xy_to_loc(Pos pos) const {
468 for (auto [x, y, location] : _extraLocations) {
469 if (pos.x == x && pos.y == y) return location;
470 }
471
472 return -1; // @Error
473}
474
440std::tuple<int, int> PuzzleSerializer::dloc_to_xy(const Puzzle& p, int location) const { 475std::tuple<int, int> PuzzleSerializer::dloc_to_xy(const Puzzle& p, int location) const {
441 int height2 = (p.height - 3) / 2; 476 int height2 = (p.height - 3) / 2;
442 int width2 = (p.width - 1) / 2; 477 int width2 = (p.width - 1) / 2;
@@ -476,3 +511,10 @@ int PuzzleSerializer::FindConnection(int location) const {
476 } 511 }
477 return -1; 512 return -1;
478} 513}
514
515void PuzzleSerializer::AddIntersection(int x, int y, float xPos, float yPos, int flags) {
516 _extraLocations.emplace_back(x, y, static_cast<int>(_intersectionFlags.size()));
517 _intersectionLocations.push_back(xPos);
518 _intersectionLocations.push_back(yPos);
519 _intersectionFlags.push_back(flags);
520}