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.cpp199
1 files changed, 139 insertions, 60 deletions
diff --git a/Source/Panel.cpp b/Source/Panel.cpp index 0f62664..5465bef 100644 --- a/Source/Panel.cpp +++ b/Source/Panel.cpp
@@ -1,27 +1,20 @@
1#include "Panel.h" 1#include "Panel.h"
2#include "Random.h" 2#include "Random.h"
3#include <sstream>
3 4
4Decoration::Decoration(int shape) { 5template <class T>
5 _shape = shape; 6int find(const std::vector<T> &data, T search, size_t startIndex = 0) {
6} 7 for (size_t i=startIndex ; i<data.size(); i++) {
7 8 if (data[i] == search) return i;
8int Decoration::GetValue() { 9 }
9 return _shape; 10 return -1;
10}
11
12Intersection::Intersection(float x, float y, int flags) {
13 _x = x;
14 _y = y;
15 _flags = flags;
16}
17
18int Intersection::GetValue() {
19 return _flags;
20} 11}
21 12
22Panel::Panel(int id) { 13Panel::Panel(int id) {
23 _width = _memory.ReadPanelData<int>(id, GRID_SIZE_X, 1)[0]; 14 _width = 2 * _memory.ReadPanelData<int>(id, GRID_SIZE_X, 1)[0] - 1;
24 _height = _memory.ReadPanelData<int>(id, GRID_SIZE_Y, 1)[0]; 15 _height = 2 * _memory.ReadPanelData<int>(id, GRID_SIZE_Y, 1)[0] - 1;
16 _grid.resize(_width);
17 for (auto& row : _grid) row.resize(_height);
25 18
26 ReadIntersections(id); 19 ReadIntersections(id);
27 ReadDecorations(id); 20 ReadDecorations(id);
@@ -31,67 +24,134 @@ void Panel::Write(int id) {
31 WriteIntersections(id); 24 WriteIntersections(id);
32 WriteDecorations(id); 25 WriteDecorations(id);
33 26
34 _memory.WritePanelData<int>(id, GRID_SIZE_X, {_width}); 27 _memory.WritePanelData<int>(id, GRID_SIZE_X, {(_width + 1)/2});
35 _memory.WritePanelData<int>(id, GRID_SIZE_Y, {_height}); 28 _memory.WritePanelData<int>(id, GRID_SIZE_Y, {(_height + 1)/2});
29}
30
31nlohmann::json Panel::Serialize() {
32 nlohmann::json puzzle = {
33 {"pillar", false},
34 {"dots", nlohmann::json::array()},
35 {"gaps", nlohmann::json::array()},
36 {"name", "Imported from The Witness :O"},
37 {"regionCache", nlohmann::json::object()},
38 };
39 if (_grid.empty()) return {};
40 puzzle["grid"] = nlohmann::json::array();
41
42 for (int x=0; x<_width; x++) {
43 for (int y=0; y<_height; y++) {
44 if (x%2 == 1 && y%2 == 1) {
45 puzzle["grid"][x][y] = Decoration::to_json(_grid[x][y]);
46 } else {
47 puzzle["grid"][x][y] = false;
48 }
49 }
50 }
51
52 puzzle["startPoints"] = nlohmann::json::array();
53 for (auto [x, y] : _startpoints) {
54 nlohmann::json startPoint = {{"x", x}, {"y", y}};
55 puzzle["startPoints"].emplace_back(startPoint);
56 }
57 puzzle["endPoints"] = nlohmann::json::array();
58 for (Endpoint endpoint : _endpoints) {
59 puzzle["endPoints"].emplace_back(endpoint.to_json());
60 }
61
62 std::string out = puzzle.dump();
63 return puzzle;
36} 64}
37 65
38void Panel::Random() { 66void Panel::Random() {
67/*
39 for (auto& row : _decorations) { 68 for (auto& row : _decorations) {
40 for (auto& cell : row) { 69 for (auto& cell : row) {
41 cell._shape &= 0xFFFFFFF0; 70 cell.SetShape(cell.GetShape() & 0xFFFFFFF0);
42 cell._shape |= Random::RandInt(1, 10); 71 cell.SetShape(cell.GetShape() | Random::RandInt(1, 10));
43 } 72 }
44 } 73 }
74*/
45} 75}
46 76
47void Panel::ReadDecorations(int id) { 77void Panel::ReadDecorations(int id) {
48 int numDecorations = _memory.ReadPanelData<int>(id, NUM_DECORATIONS, 1)[0]; 78 int numDecorations = _memory.ReadPanelData<int>(id, NUM_DECORATIONS, 1)[0];
49 std::vector<int> decorations = _memory.ReadArray<int>(id, DECORATIONS, numDecorations); 79 std::vector<int> decorations = _memory.ReadArray<int>(id, DECORATIONS, numDecorations);
50 _decorations.resize(_width - 1); 80
51 for (int x=0; x<_width-1; x++) { 81 int x = 1;
52 _decorations[x].resize(_height - 1); 82 int y = _height - 2;
53 for (int y=0; y<_height-1; y++) { 83 for (int decoration : decorations) {
54 int i = x * (_height - 1) + y; 84 _grid[x][y] = decoration;
55 _decorations[x][y] = Decoration(decorations[i]); 85 x += 2;
86 if (x > _width - 1) {
87 x = 1;
88 y -= 2;
56 } 89 }
57 } 90 }
58} 91}
59 92
60void Panel::WriteDecorations(int id) { 93void Panel::WriteDecorations(int id) {
61 std::vector<int> flattenedDecorations; 94 std::vector<int> decorations;
62 for (std::vector<Decoration> row : _decorations) { 95 for (int y=_height - 2; y>0; y-=2) {
63 for (Decoration decoration : row) { 96 for (int x=1; x<_width - 1; x+=2) {
64 flattenedDecorations.push_back(decoration.GetValue()); 97 decorations.push_back(_grid[x][y]);
65 } 98 }
66 } 99 }
67 100
68 _memory.WritePanelData<int>(id, NUM_DECORATIONS, {static_cast<int>(flattenedDecorations.size())}); 101 _memory.WritePanelData<int>(id, NUM_DECORATIONS, {static_cast<int>(decorations.size())});
69 _memory.WriteArray<int>(id, DECORATIONS, flattenedDecorations); 102 _memory.WriteArray<int>(id, DECORATIONS, decorations);
70} 103}
71 104
72void Panel::ReadIntersections(int id) { 105void Panel::ReadIntersections(int id) {
73 int numIntersections = _memory.ReadPanelData<int>(id, NUM_DOTS, 1)[0]; 106 int numIntersections = _memory.ReadPanelData<int>(id, NUM_DOTS, 1)[0];
74 std::vector<float> intersections = _memory.ReadArray<float>(id, DOT_POSITIONS, numIntersections*2);
75 std::vector<int> intersectionFlags = _memory.ReadArray<int>(id, DOT_FLAGS, numIntersections); 107 std::vector<int> intersectionFlags = _memory.ReadArray<int>(id, DOT_FLAGS, numIntersections);
76 _intersections.resize(_width); 108
77 int i=0; 109 int x = 0;
78 for (int y=0; y<_height; y++) { 110 int y = _height - 1;
79 for (int x=0; x<_width; x++) { 111 int i = 0;
80 _intersections[x].resize(_height); 112 for (;; i++) {
81 _intersections[x][y] = Intersection(intersections[2*i], intersections[2*i+1], intersectionFlags[i]); 113 if (intersectionFlags[i] & IntersectionFlags::IS_STARTPOINT) {
82 i++; 114 _startpoints.push_back({x, y});
83 } 115 }
116 x += 2;
117 if (x > _width) {
118 x = 0;
119 y -= 2;
120 }
121 if (y < 0) break;
84 } 122 }
85 123
124 std::pair<std::vector<int>, std::vector<int>> connections;
125 int numConnections = _memory.ReadPanelData<int>(id, NUM_CONNECTIONS, 1)[0];
126 connections.first = _memory.ReadArray<int>(id, DOT_CONNECTION_A, numConnections);
127 connections.second = _memory.ReadArray<int>(id, DOT_CONNECTION_B, numConnections);
128 std::vector<float> intersections = _memory.ReadArray<float>(id, DOT_POSITIONS, numIntersections*2);
129
86 // Iterate the remaining intersections (either endpoints or gaps) 130 // Iterate the remaining intersections (either endpoints or gaps)
87 for (; i < numIntersections; i++) { 131 for (; i < numIntersections; i++) {
88 if (intersectionFlags[i] & Intersection::Flags::IS_ENDPOINT) { 132 if (intersectionFlags[i] & IntersectionFlags::IS_ENDPOINT) {
89 _endpoints.push_back(Intersection(intersections[2*i], intersections[2*i+1], intersectionFlags[i])); 133 for (int j=0; j<numConnections; j++) {
90 } 134 int location = 0;
91 if (intersectionFlags[i] & Intersection::Flags::IS_GAP) { 135 if (connections.first[j] == i) location = connections.second[j];
92 _gaps.push_back(Intersection(intersections[2*i], intersections[2*i+1], intersectionFlags[i])); 136 if (connections.second[j] == i) location = connections.first[j];
137 if (location != 0) {
138 Endpoint::Direction dir;
139 if (intersections[2*i] < intersections[2*location]) { // Our (i) x coordinate is less than the target's (location)
140 dir = Endpoint::Direction::LEFT;
141 } else if (intersections[2*i] > intersections[2*location]) {
142 dir = Endpoint::Direction::RIGHT;
143 } else if (intersections[2*i + 1] > intersections[2*location + 1]) { // y coordinate is 0 (bottom) 1 (top), so this check is reversed.
144 dir = Endpoint::Direction::UP;
145 } else {
146 dir = Endpoint::Direction::DOWN;
147 }
148 int x = 2 * (location % ((_width + 1) / 2));
149 int y = (_height - 1) - 2 * (location / ((_width + 1) / 2));
150 _endpoints.push_back(Endpoint(x, y, dir));
151 }
152 }
93 } 153 }
94 } 154 }
95} 155}
96 156
97void Panel::WriteIntersections(int id) { 157void Panel::WriteIntersections(int id) {
@@ -99,12 +159,18 @@ void Panel::WriteIntersections(int id) {
99 std::vector<int> intersectionFlags; 159 std::vector<int> intersectionFlags;
100 std::pair<std::vector<int>, std::vector<int>> connections; 160 std::pair<std::vector<int>, std::vector<int>> connections;
101 161
162 double min = 0.1;
163 double max = 0.9;
164 double width_interval = (max - min) / (_width - 1);
165 double height_interval = (max - min) / (_height - 1);
166
102 for (int y=0; y<_height; y++) { 167 for (int y=0; y<_height; y++) {
103 for (int x=0; x<_width; x++) { 168 for (int x=0; x<_width; x++) {
104 Intersection intersection = _intersections[x][y]; 169 intersections.push_back(min + x * width_interval);
105 intersections.push_back(intersection._x); 170 intersections.push_back(min + y * height_interval);
106 intersections.push_back(intersection._y); 171 int flags = 0;
107 intersectionFlags.push_back(intersection._flags); 172 if (find(_startpoints, {x, y}) != -1) flags |= IntersectionFlags::IS_STARTPOINT;
173 intersectionFlags.push_back(flags);
108 if (y > 0) { 174 if (y > 0) {
109 connections.first.push_back(y * _width + x); 175 connections.first.push_back(y * _width + x);
110 connections.second.push_back((y - 1) * _width + x); 176 connections.second.push_back((y - 1) * _width + x);
@@ -116,19 +182,32 @@ void Panel::WriteIntersections(int id) {
116 } 182 }
117 } 183 }
118 184
119 // Endpoints go here :( 185 for (Endpoint endpoint : _endpoints) {
186 float xPos = min + endpoint.GetX() * width_interval;
187 float yPos = min + endpoint.GetY() * height_interval;
188 if (endpoint.GetDir()== Endpoint::Direction::LEFT) {
189 xPos -= .05f;
190 } else if (endpoint.GetDir() == Endpoint::Direction::RIGHT) {
191 xPos += .05f;
192 } else if (endpoint.GetDir() == Endpoint::Direction::UP) {
193 yPos += .05f; // Y position goes from 0 (bottom) to 1 (top), so this is reversed.
194 } else if (endpoint.GetDir() == Endpoint::Direction::DOWN) {
195 yPos -= .05f;
196 }
197 intersections.push_back(xPos);
198 intersections.push_back(yPos);
120 199
121 int a = _memory.ReadPanelData<int>(id, NUM_DOTS, 1)[0]; 200 connections.first.push_back(endpoint.GetY() * _width + endpoint.GetX()); // Target to connect to
122 std::vector<float> b = _memory.ReadArray<float>(id, DOT_POSITIONS, a*2); 201 connections.second.push_back(intersectionFlags.size()); // This endpoint
123 std::vector<int> c = _memory.ReadArray<int>(id, DOT_FLAGS, a); 202 intersectionFlags.push_back(IntersectionFlags::IS_ENDPOINT);
124 std::pair<std::vector<int>, std::vector<int>> d; 203 }
125 d.first = _memory.ReadArray<int>(id, DOT_CONNECTION_A, a);
126 d.second = _memory.ReadArray<int>(id, DOT_CONNECTION_B, a);
127 204
128 _memory.WritePanelData<int>(id, NUM_DOTS, {_width * _height}); 205 _memory.WritePanelData<int>(id, NUM_DOTS, {static_cast<int>(intersectionFlags.size())});
129 _memory.WriteArray<float>(id, DOT_POSITIONS, intersections); 206 _memory.WriteArray<float>(id, DOT_POSITIONS, intersections);
130 _memory.WriteArray<int>(id, DOT_FLAGS, intersectionFlags); 207 _memory.WriteArray<int>(id, DOT_FLAGS, intersectionFlags);
208 _memory.WritePanelData<int>(id, NUM_CONNECTIONS, {static_cast<int>(connections.first.size())});
131 _memory.WriteArray<int>(id, DOT_CONNECTION_A, connections.first); 209 _memory.WriteArray<int>(id, DOT_CONNECTION_A, connections.first);
132 _memory.WriteArray<int>(id, DOT_CONNECTION_B, connections.second); 210 _memory.WriteArray<int>(id, DOT_CONNECTION_B, connections.second);
211 _memory.WritePanelData<int>(id, NEEDS_REDRAW, {1});
133} 212}
134 213