diff options
Diffstat (limited to 'Source/Panel.cpp')
-rw-r--r-- | Source/Panel.cpp | 199 |
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 | ||
4 | Decoration::Decoration(int shape) { | 5 | template <class T> |
5 | _shape = shape; | 6 | int 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; | |
8 | int Decoration::GetValue() { | 9 | } |
9 | return _shape; | 10 | return -1; |
10 | } | ||
11 | |||
12 | Intersection::Intersection(float x, float y, int flags) { | ||
13 | _x = x; | ||
14 | _y = y; | ||
15 | _flags = flags; | ||
16 | } | ||
17 | |||
18 | int Intersection::GetValue() { | ||
19 | return _flags; | ||
20 | } | 11 | } |
21 | 12 | ||
22 | Panel::Panel(int id) { | 13 | Panel::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 | |||
31 | nlohmann::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 | ||
38 | void Panel::Random() { | 66 | void 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 | ||
47 | void Panel::ReadDecorations(int id) { | 77 | void 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 | ||
60 | void Panel::WriteDecorations(int id) { | 93 | void 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 | ||
72 | void Panel::ReadIntersections(int id) { | 105 | void 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 | ||
97 | void Panel::WriteIntersections(int id) { | 157 | void 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 | ||