summary refs log tree commit diff stats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/Main.cpp10
-rw-r--r--Source/Panel.cpp199
-rw-r--r--Source/Panel.h109
-rw-r--r--Source/RandomizerCore.h1
4 files changed, 225 insertions, 94 deletions
diff --git a/Source/Main.cpp b/Source/Main.cpp index 8c4bf8c..8f537f2 100644 --- a/Source/Main.cpp +++ b/Source/Main.cpp
@@ -15,9 +15,11 @@
15#define IDC_READ 0x405 15#define IDC_READ 0x405
16#define IDC_RANDOM 0x406 16#define IDC_RANDOM 0x406
17#define IDC_WRITE 0x407 17#define IDC_WRITE 0x407
18#define IDC_DUMP 0x408
18 19
19HWND hwndSeed, hwndRandomize; 20HWND hwndSeed, hwndRandomize;
20int panel = 0x12C9; 21// int panel = 0x18AF;
22int panel = 0x33D4;
21std::shared_ptr<Panel> _panel; 23std::shared_ptr<Panel> _panel;
22 24
23LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 25LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
@@ -72,6 +74,9 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
72 case IDC_WRITE: 74 case IDC_WRITE:
73 _panel->Write(panel); 75 _panel->Write(panel);
74 break; 76 break;
77 case IDC_DUMP:
78 _panel->Serialize();
79 break;
75 } 80 }
76 } 81 }
77 return DefWindowProc(hwnd, message, wParam, lParam); 82 return DefWindowProc(hwnd, message, wParam, lParam);
@@ -123,6 +128,9 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmd
123 CreateWindow(L"BUTTON", L"WRITE", 128 CreateWindow(L"BUTTON", L"WRITE",
124 WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 129 WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
125 160, 160, 100, 26, hwnd, (HMENU)IDC_WRITE, hInstance, NULL); 130 160, 160, 100, 26, hwnd, (HMENU)IDC_WRITE, hInstance, NULL);
131 CreateWindow(L"BUTTON", L"DUMP",
132 WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
133 160, 190, 100, 26, hwnd, (HMENU)IDC_DUMP, hInstance, NULL);
126 134
127 CreateWindow(L"BUTTON", L"", 135 CreateWindow(L"BUTTON", L"",
128 WS_VISIBLE | WS_CHILD | BS_CHECKBOX, 136 WS_VISIBLE | WS_CHILD | BS_CHECKBOX,
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
diff --git a/Source/Panel.h b/Source/Panel.h index fa3f750..4982f17 100644 --- a/Source/Panel.h +++ b/Source/Panel.h
@@ -6,50 +6,95 @@ class Decoration
6{ 6{
7public: 7public:
8 enum Shape { 8 enum Shape {
9 Stone = 100, 9 Stone = 0x100,
10 Star = 200, 10 Star = 0x200,
11 Poly = 400, 11 Poly = 0x400,
12 Eraser = 500, 12 Eraser = 0x500,
13 Triangle = 600, 13 Triangle = 0x600,
14 };
15 enum Color {
16 Black = 0x1,
17 White = 0x2,
18 Red = 0x3,
19 Blue = 0x4,
20 Green = 0x5,
14 }; 21 };
15 22
16 Decoration() = default; 23 static nlohmann::json to_json(int decoration) {
17 explicit Decoration(int shape); 24 nlohmann::json json = {};
18 25 int shape = decoration & 0x00000F00;
19 int GetValue(); 26 if (shape == Shape::Stone) json["type"] = "square";
27 if (shape == Shape::Star) json["type"] = "star";
28 if (shape == Shape::Poly) json["type"] = "poly";
29 if (shape == Shape::Eraser) json["type"] = "eraser";
30 if (shape == Shape::Triangle) json["type"] = "triangle";
31
32 int color = decoration & 0x0000000F;
33 if (color == Color::Black) json["color"] = "black";
34 if (color == Color::White) json["color"] = "white";
35 if (color == Color::Red) json["color"] = "red";
36 if (color == Color::Blue) json["color"] = "blue";
37 if (color == Color::Green) json["color"] = "green";
38
39 if (json.empty()) return false;
40 return json;
41 }
42};
20 43
21//private: 44enum IntersectionFlags {
22 int _shape; 45 IS_ENDPOINT = 0x1,
46 IS_STARTPOINT = 0x2,
47 IS_GAP = 0x10000,
48 HAS_DOT = 0x8,
49 DOT_IS_BLUE = 0x100,
50 DOT_IS_ORANGE = 0x200,
51 DOT_IS_INVISIBLE = 0x1000,
23}; 52};
24 53
25class Intersection 54class Endpoint {
26{
27public: 55public:
28 enum Flags { 56 enum Direction {
29 IS_ENDPOINT = 0x1, 57 LEFT,
30 IS_STARTPOINT = 0x2, 58 RIGHT,
31 IS_GAP = 0x10000, 59 UP,
32 HAS_DOT = 0x8, 60 DOWN
33 DOT_IS_BLUE = 0x100,
34 DOT_IS_ORANGE = 0x200,
35 DOT_IS_INVISIBLE = 0x1000,
36 }; 61 };
37 62
38 Intersection() = default; 63 Endpoint(int x, int y, Direction dir) {
39 explicit Intersection(float x, float y, int flags); 64 _x = x;
65 _y = y;
66 _dir = dir;
67 }
68
69 int GetX() {return _x;}
70 void SetX(int x) {_x = x;}
71 int GetY() {return _y;}
72 void SetY(int y) {_y = y;}
73 Direction GetDir() {return _dir;}
74 void SetDir(Direction dir) {_dir = dir;}
75
76 nlohmann::json to_json() {
77 nlohmann::json json = {{"x", _x}, {"y", _y}};
78 if (_dir == LEFT) json["dir"] = "left";
79 if (_dir == RIGHT) json["dir"] = "right";
80 if (_dir == UP) json["dir"] = "up";
81 if (_dir == DOWN) json["dir"] = "down";
82 return json;
83 }
40 84
41 int GetValue(); 85private:
42 86 int _x, _y;
43// private: 87 Direction _dir;
44 float _x, _y;
45 int _flags;
46}; 88};
47 89
48class Panel 90class Panel
49{ 91{
50public: 92public:
51 explicit Panel(int id); 93 explicit Panel(int id);
94 // explicit Panel(nlohmann::json json);
95
52 void Write(int id); 96 void Write(int id);
97 nlohmann::json Serialize();
53 98
54 void Random(); 99 void Random();
55 100
@@ -72,14 +117,12 @@ private:
72 // TODO: Reflection data 117 // TODO: Reflection data
73 // TODO: Decoration colors 118 // TODO: Decoration colors
74 119
75
76 Memory _memory = Memory("witness64_d3d11.exe"); 120 Memory _memory = Memory("witness64_d3d11.exe");
77 121
78 int _width, _height; 122 int _width, _height;
79 123
80 std::vector<std::vector<Decoration>> _decorations; 124 std::vector<std::vector<int>> _grid;
81 std::vector<std::vector<Intersection>> _intersections; 125 std::vector<Endpoint> _endpoints;
82 std::vector<Intersection> _endpoints; 126 std::vector<std::pair<int ,int>> _startpoints;
83 std::vector<Intersection> _gaps;
84 int _style; 127 int _style;
85}; \ No newline at end of file 128}; \ No newline at end of file
diff --git a/Source/RandomizerCore.h b/Source/RandomizerCore.h index 27e5724..82015f1 100644 --- a/Source/RandomizerCore.h +++ b/Source/RandomizerCore.h
@@ -55,6 +55,7 @@ public:
55#define CYLINDER_Z1 0x304 55#define CYLINDER_Z1 0x304
56#define CYLINDER_RADIUS 0x308 56#define CYLINDER_RADIUS 0x308
57#define CURSOR_SPEED_SCALE 0x358 57#define CURSOR_SPEED_SCALE 0x358
58#define NEEDS_REDRAW 0x384
58#define SPECULAR_ADD 0x398 59#define SPECULAR_ADD 0x398
59#define SPECULAR_POWER 0x39C 60#define SPECULAR_POWER 0x39C
60#define PATH_WIDTH_SCALE 0x3A4 61#define PATH_WIDTH_SCALE 0x3A4