From e48ce4469cee270687e04bc1a2b91d3c2bba0789 Mon Sep 17 00:00:00 2001 From: jbzdarkid Date: Fri, 2 Nov 2018 21:22:29 -0700 Subject: arglbargl --- Source/Main.cpp | 10 ++- Source/Panel.cpp | 199 +++++++++++++++++++++++++++++++++--------------- Source/Panel.h | 109 ++++++++++++++++++-------- Source/RandomizerCore.h | 1 + 4 files changed, 225 insertions(+), 94 deletions(-) (limited to 'Source') 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 @@ #define IDC_READ 0x405 #define IDC_RANDOM 0x406 #define IDC_WRITE 0x407 +#define IDC_DUMP 0x408 HWND hwndSeed, hwndRandomize; -int panel = 0x12C9; +// int panel = 0x18AF; +int panel = 0x33D4; std::shared_ptr _panel; LRESULT 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) case IDC_WRITE: _panel->Write(panel); break; + case IDC_DUMP: + _panel->Serialize(); + break; } } return DefWindowProc(hwnd, message, wParam, lParam); @@ -123,6 +128,9 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmd CreateWindow(L"BUTTON", L"WRITE", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 160, 160, 100, 26, hwnd, (HMENU)IDC_WRITE, hInstance, NULL); + CreateWindow(L"BUTTON", L"DUMP", + WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, + 160, 190, 100, 26, hwnd, (HMENU)IDC_DUMP, hInstance, NULL); CreateWindow(L"BUTTON", L"", 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 @@ #include "Panel.h" #include "Random.h" +#include -Decoration::Decoration(int shape) { - _shape = shape; -} - -int Decoration::GetValue() { - return _shape; -} - -Intersection::Intersection(float x, float y, int flags) { - _x = x; - _y = y; - _flags = flags; -} - -int Intersection::GetValue() { - return _flags; +template +int find(const std::vector &data, T search, size_t startIndex = 0) { + for (size_t i=startIndex ; i(id, GRID_SIZE_X, 1)[0]; - _height = _memory.ReadPanelData(id, GRID_SIZE_Y, 1)[0]; + _width = 2 * _memory.ReadPanelData(id, GRID_SIZE_X, 1)[0] - 1; + _height = 2 * _memory.ReadPanelData(id, GRID_SIZE_Y, 1)[0] - 1; + _grid.resize(_width); + for (auto& row : _grid) row.resize(_height); ReadIntersections(id); ReadDecorations(id); @@ -31,67 +24,134 @@ void Panel::Write(int id) { WriteIntersections(id); WriteDecorations(id); - _memory.WritePanelData(id, GRID_SIZE_X, {_width}); - _memory.WritePanelData(id, GRID_SIZE_Y, {_height}); + _memory.WritePanelData(id, GRID_SIZE_X, {(_width + 1)/2}); + _memory.WritePanelData(id, GRID_SIZE_Y, {(_height + 1)/2}); +} + +nlohmann::json Panel::Serialize() { + nlohmann::json puzzle = { + {"pillar", false}, + {"dots", nlohmann::json::array()}, + {"gaps", nlohmann::json::array()}, + {"name", "Imported from The Witness :O"}, + {"regionCache", nlohmann::json::object()}, + }; + if (_grid.empty()) return {}; + puzzle["grid"] = nlohmann::json::array(); + + for (int x=0; x<_width; x++) { + for (int y=0; y<_height; y++) { + if (x%2 == 1 && y%2 == 1) { + puzzle["grid"][x][y] = Decoration::to_json(_grid[x][y]); + } else { + puzzle["grid"][x][y] = false; + } + } + } + + puzzle["startPoints"] = nlohmann::json::array(); + for (auto [x, y] : _startpoints) { + nlohmann::json startPoint = {{"x", x}, {"y", y}}; + puzzle["startPoints"].emplace_back(startPoint); + } + puzzle["endPoints"] = nlohmann::json::array(); + for (Endpoint endpoint : _endpoints) { + puzzle["endPoints"].emplace_back(endpoint.to_json()); + } + + std::string out = puzzle.dump(); + return puzzle; } void Panel::Random() { +/* for (auto& row : _decorations) { for (auto& cell : row) { - cell._shape &= 0xFFFFFFF0; - cell._shape |= Random::RandInt(1, 10); + cell.SetShape(cell.GetShape() & 0xFFFFFFF0); + cell.SetShape(cell.GetShape() | Random::RandInt(1, 10)); } } +*/ } void Panel::ReadDecorations(int id) { int numDecorations = _memory.ReadPanelData(id, NUM_DECORATIONS, 1)[0]; std::vector decorations = _memory.ReadArray(id, DECORATIONS, numDecorations); - _decorations.resize(_width - 1); - for (int x=0; x<_width-1; x++) { - _decorations[x].resize(_height - 1); - for (int y=0; y<_height-1; y++) { - int i = x * (_height - 1) + y; - _decorations[x][y] = Decoration(decorations[i]); + + int x = 1; + int y = _height - 2; + for (int decoration : decorations) { + _grid[x][y] = decoration; + x += 2; + if (x > _width - 1) { + x = 1; + y -= 2; } } } void Panel::WriteDecorations(int id) { - std::vector flattenedDecorations; - for (std::vector row : _decorations) { - for (Decoration decoration : row) { - flattenedDecorations.push_back(decoration.GetValue()); + std::vector decorations; + for (int y=_height - 2; y>0; y-=2) { + for (int x=1; x<_width - 1; x+=2) { + decorations.push_back(_grid[x][y]); } } - _memory.WritePanelData(id, NUM_DECORATIONS, {static_cast(flattenedDecorations.size())}); - _memory.WriteArray(id, DECORATIONS, flattenedDecorations); + _memory.WritePanelData(id, NUM_DECORATIONS, {static_cast(decorations.size())}); + _memory.WriteArray(id, DECORATIONS, decorations); } void Panel::ReadIntersections(int id) { int numIntersections = _memory.ReadPanelData(id, NUM_DOTS, 1)[0]; - std::vector intersections = _memory.ReadArray(id, DOT_POSITIONS, numIntersections*2); std::vector intersectionFlags = _memory.ReadArray(id, DOT_FLAGS, numIntersections); - _intersections.resize(_width); - int i=0; - for (int y=0; y<_height; y++) { - for (int x=0; x<_width; x++) { - _intersections[x].resize(_height); - _intersections[x][y] = Intersection(intersections[2*i], intersections[2*i+1], intersectionFlags[i]); - i++; + + int x = 0; + int y = _height - 1; + int i = 0; + for (;; i++) { + if (intersectionFlags[i] & IntersectionFlags::IS_STARTPOINT) { + _startpoints.push_back({x, y}); } + x += 2; + if (x > _width) { + x = 0; + y -= 2; + } + if (y < 0) break; } + std::pair, std::vector> connections; + int numConnections = _memory.ReadPanelData(id, NUM_CONNECTIONS, 1)[0]; + connections.first = _memory.ReadArray(id, DOT_CONNECTION_A, numConnections); + connections.second = _memory.ReadArray(id, DOT_CONNECTION_B, numConnections); + std::vector intersections = _memory.ReadArray(id, DOT_POSITIONS, numIntersections*2); + // Iterate the remaining intersections (either endpoints or gaps) for (; i < numIntersections; i++) { - if (intersectionFlags[i] & Intersection::Flags::IS_ENDPOINT) { - _endpoints.push_back(Intersection(intersections[2*i], intersections[2*i+1], intersectionFlags[i])); - } - if (intersectionFlags[i] & Intersection::Flags::IS_GAP) { - _gaps.push_back(Intersection(intersections[2*i], intersections[2*i+1], intersectionFlags[i])); + if (intersectionFlags[i] & IntersectionFlags::IS_ENDPOINT) { + for (int j=0; j intersections[2*location]) { + dir = Endpoint::Direction::RIGHT; + } else if (intersections[2*i + 1] > intersections[2*location + 1]) { // y coordinate is 0 (bottom) 1 (top), so this check is reversed. + dir = Endpoint::Direction::UP; + } else { + dir = Endpoint::Direction::DOWN; + } + int x = 2 * (location % ((_width + 1) / 2)); + int y = (_height - 1) - 2 * (location / ((_width + 1) / 2)); + _endpoints.push_back(Endpoint(x, y, dir)); + } + } } - } + } } void Panel::WriteIntersections(int id) { @@ -99,12 +159,18 @@ void Panel::WriteIntersections(int id) { std::vector intersectionFlags; std::pair, std::vector> connections; + double min = 0.1; + double max = 0.9; + double width_interval = (max - min) / (_width - 1); + double height_interval = (max - min) / (_height - 1); + for (int y=0; y<_height; y++) { for (int x=0; x<_width; x++) { - Intersection intersection = _intersections[x][y]; - intersections.push_back(intersection._x); - intersections.push_back(intersection._y); - intersectionFlags.push_back(intersection._flags); + intersections.push_back(min + x * width_interval); + intersections.push_back(min + y * height_interval); + int flags = 0; + if (find(_startpoints, {x, y}) != -1) flags |= IntersectionFlags::IS_STARTPOINT; + intersectionFlags.push_back(flags); if (y > 0) { connections.first.push_back(y * _width + x); connections.second.push_back((y - 1) * _width + x); @@ -116,19 +182,32 @@ void Panel::WriteIntersections(int id) { } } - // Endpoints go here :( + for (Endpoint endpoint : _endpoints) { + float xPos = min + endpoint.GetX() * width_interval; + float yPos = min + endpoint.GetY() * height_interval; + if (endpoint.GetDir()== Endpoint::Direction::LEFT) { + xPos -= .05f; + } else if (endpoint.GetDir() == Endpoint::Direction::RIGHT) { + xPos += .05f; + } else if (endpoint.GetDir() == Endpoint::Direction::UP) { + yPos += .05f; // Y position goes from 0 (bottom) to 1 (top), so this is reversed. + } else if (endpoint.GetDir() == Endpoint::Direction::DOWN) { + yPos -= .05f; + } + intersections.push_back(xPos); + intersections.push_back(yPos); - int a = _memory.ReadPanelData(id, NUM_DOTS, 1)[0]; - std::vector b = _memory.ReadArray(id, DOT_POSITIONS, a*2); - std::vector c = _memory.ReadArray(id, DOT_FLAGS, a); - std::pair, std::vector> d; - d.first = _memory.ReadArray(id, DOT_CONNECTION_A, a); - d.second = _memory.ReadArray(id, DOT_CONNECTION_B, a); + connections.first.push_back(endpoint.GetY() * _width + endpoint.GetX()); // Target to connect to + connections.second.push_back(intersectionFlags.size()); // This endpoint + intersectionFlags.push_back(IntersectionFlags::IS_ENDPOINT); + } - _memory.WritePanelData(id, NUM_DOTS, {_width * _height}); + _memory.WritePanelData(id, NUM_DOTS, {static_cast(intersectionFlags.size())}); _memory.WriteArray(id, DOT_POSITIONS, intersections); _memory.WriteArray(id, DOT_FLAGS, intersectionFlags); + _memory.WritePanelData(id, NUM_CONNECTIONS, {static_cast(connections.first.size())}); _memory.WriteArray(id, DOT_CONNECTION_A, connections.first); _memory.WriteArray(id, DOT_CONNECTION_B, connections.second); + _memory.WritePanelData(id, NEEDS_REDRAW, {1}); } 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 { public: enum Shape { - Stone = 100, - Star = 200, - Poly = 400, - Eraser = 500, - Triangle = 600, + Stone = 0x100, + Star = 0x200, + Poly = 0x400, + Eraser = 0x500, + Triangle = 0x600, + }; + enum Color { + Black = 0x1, + White = 0x2, + Red = 0x3, + Blue = 0x4, + Green = 0x5, }; - Decoration() = default; - explicit Decoration(int shape); - - int GetValue(); + static nlohmann::json to_json(int decoration) { + nlohmann::json json = {}; + int shape = decoration & 0x00000F00; + if (shape == Shape::Stone) json["type"] = "square"; + if (shape == Shape::Star) json["type"] = "star"; + if (shape == Shape::Poly) json["type"] = "poly"; + if (shape == Shape::Eraser) json["type"] = "eraser"; + if (shape == Shape::Triangle) json["type"] = "triangle"; + + int color = decoration & 0x0000000F; + if (color == Color::Black) json["color"] = "black"; + if (color == Color::White) json["color"] = "white"; + if (color == Color::Red) json["color"] = "red"; + if (color == Color::Blue) json["color"] = "blue"; + if (color == Color::Green) json["color"] = "green"; + + if (json.empty()) return false; + return json; + } +}; -//private: - int _shape; +enum IntersectionFlags { + IS_ENDPOINT = 0x1, + IS_STARTPOINT = 0x2, + IS_GAP = 0x10000, + HAS_DOT = 0x8, + DOT_IS_BLUE = 0x100, + DOT_IS_ORANGE = 0x200, + DOT_IS_INVISIBLE = 0x1000, }; -class Intersection -{ +class Endpoint { public: - enum Flags { - IS_ENDPOINT = 0x1, - IS_STARTPOINT = 0x2, - IS_GAP = 0x10000, - HAS_DOT = 0x8, - DOT_IS_BLUE = 0x100, - DOT_IS_ORANGE = 0x200, - DOT_IS_INVISIBLE = 0x1000, + enum Direction { + LEFT, + RIGHT, + UP, + DOWN }; - Intersection() = default; - explicit Intersection(float x, float y, int flags); + Endpoint(int x, int y, Direction dir) { + _x = x; + _y = y; + _dir = dir; + } + + int GetX() {return _x;} + void SetX(int x) {_x = x;} + int GetY() {return _y;} + void SetY(int y) {_y = y;} + Direction GetDir() {return _dir;} + void SetDir(Direction dir) {_dir = dir;} + + nlohmann::json to_json() { + nlohmann::json json = {{"x", _x}, {"y", _y}}; + if (_dir == LEFT) json["dir"] = "left"; + if (_dir == RIGHT) json["dir"] = "right"; + if (_dir == UP) json["dir"] = "up"; + if (_dir == DOWN) json["dir"] = "down"; + return json; + } - int GetValue(); - -// private: - float _x, _y; - int _flags; +private: + int _x, _y; + Direction _dir; }; class Panel { public: explicit Panel(int id); + // explicit Panel(nlohmann::json json); + void Write(int id); + nlohmann::json Serialize(); void Random(); @@ -72,14 +117,12 @@ private: // TODO: Reflection data // TODO: Decoration colors - Memory _memory = Memory("witness64_d3d11.exe"); int _width, _height; - std::vector> _decorations; - std::vector> _intersections; - std::vector _endpoints; - std::vector _gaps; + std::vector> _grid; + std::vector _endpoints; + std::vector> _startpoints; int _style; }; \ 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: #define CYLINDER_Z1 0x304 #define CYLINDER_RADIUS 0x308 #define CURSOR_SPEED_SCALE 0x358 +#define NEEDS_REDRAW 0x384 #define SPECULAR_ADD 0x398 #define SPECULAR_POWER 0x39C #define PATH_WIDTH_SCALE 0x3A4 -- cgit 1.4.1