From 1f85741c8d12d9b1fbd55b29f334de572f9eea9b Mon Sep 17 00:00:00 2001 From: jbzdarkid Date: Fri, 9 Nov 2018 10:08:03 -0800 Subject: Reading & writing to tutorial vault works! --- Source/Panel.cpp | 178 ++++++++++++++++++++++++++++++++++++------------------- Source/Panel.h | 30 ++++++++-- 2 files changed, 141 insertions(+), 67 deletions(-) (limited to 'Source') diff --git a/Source/Panel.cpp b/Source/Panel.cpp index b6aa504..c0fb7ec 100644 --- a/Source/Panel.cpp +++ b/Source/Panel.cpp @@ -13,8 +13,9 @@ int find(const std::vector &data, T search, size_t startIndex = 0) { } Panel::Panel(int id) { - _width = 2 * _memory.ReadPanelData(id, GRID_SIZE_X, 1)[0] - 1; - _height = 2 * _memory.ReadPanelData(id, GRID_SIZE_Y, 1)[0] - 1; + _memory = std::make_shared("witness64_d3d11.exe"); + _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); @@ -22,15 +23,12 @@ Panel::Panel(int id) { ReadDecorations(id); } -// For testing -Panel::Panel() {} - void Panel::Write(int id) { WriteIntersections(id); WriteDecorations(id); - _memory.WritePanelData(id, GRID_SIZE_X, {(_width + 1)/2}); - _memory.WritePanelData(id, GRID_SIZE_Y, {(_height + 1)/2}); + _memory->WritePanelData(id, GRID_SIZE_X, {(_width + 1)/2}); + _memory->WritePanelData(id, GRID_SIZE_Y, {(_height + 1)/2}); } nlohmann::json Panel::Serialize() { @@ -49,6 +47,9 @@ nlohmann::json Panel::Serialize() { if (x%2 == 1 && y%2 == 1) { puzzle["grid"][x][y] = Decoration::to_json(_grid[x][y]); } else { + if (_grid[x][y] & IntersectionFlags::HAS_DOT) { + puzzle["dots"].emplace_back(nlohmann::json({{"x", x}, {"y", y}})); + } puzzle["grid"][x][y] = false; } } @@ -80,65 +81,52 @@ void Panel::Random() { } void Panel::ReadDecorations(int id) { - int numDecorations = _memory.ReadPanelData(id, NUM_DECORATIONS, 1)[0]; - std::vector decorations = _memory.ReadArray(id, DECORATIONS, numDecorations); - - 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; - } + int numDecorations = _memory->ReadPanelData(id, NUM_DECORATIONS, 1)[0]; + std::vector decorations = _memory->ReadArray(id, DECORATIONS, numDecorations); + + for (int i=0; i decorations; - for (int y=_height - 2; y>0; y-=2) { + 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(decorations.size())}); - _memory.WriteArray(id, DECORATIONS, decorations); + _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 intersectionFlags = _memory.ReadArray(id, DOT_FLAGS, numIntersections); + int numIntersections = _memory->ReadPanelData(id, NUM_DOTS, 1)[0]; + std::vector intersectionFlags = _memory->ReadArray(id, DOT_FLAGS, numIntersections); - int x = 0; - int y = _height - 1; int i = 0; for (;; i++) { + auto [x, y] = loc_to_xy(i); + if (y < 0) break; 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); + int numConnections = _memory->ReadPanelData(id, NUM_CONNECTIONS, 1)[0]; + std::vector connections_a = _memory->ReadArray(id, DOT_CONNECTION_A, numConnections); + std::vector connections_b = _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) + // Iterate the remaining intersections (endpoints, dots, gaps) for (; i < numIntersections; i++) { if (intersectionFlags[i] & IntersectionFlags::IS_ENDPOINT) { for (int j=0; j intersections[2*location]) { // To the right + x++; + } else if (intersections[2*i + 1] > intersections[2*location + 1]) { + // y coordinate is 0 (bottom) 1 (top), so this check is reversed. We are above the target (location) + y--; + } else { // Beleow the target + y++; + } + + _grid[x][y] |= IntersectionFlags::HAS_DOT; + break; } } } @@ -161,34 +177,41 @@ void Panel::ReadIntersections(int id) { void Panel::WriteIntersections(int id) { std::vector intersections; std::vector intersectionFlags; - std::pair, std::vector> connections; + std::vector connections_a; + std::vector connections_b; double min = 0.1; double max = 0.9; double width_interval = (max - min) / (_width/2); double height_interval = (max - min) / (_height/2); - for (int y=0; y<_height/2; y++) { - for (int x=0; x<_width/2; x++) { - intersections.push_back(static_cast(min + x * width_interval)); - intersections.push_back(static_cast(min + y * height_interval)); + // TODO(future): Stop using push_back and set these into explicit locations, unrequires loop iteration order + for (int y=_height-1; y>=0; y-=2) { + for (int x=0; x<_width; x+=2) { + intersections.push_back(static_cast(min + (x/2) * width_interval)); + intersections.push_back(static_cast(max - (y/2) * height_interval)); int flags = 0; - if (find(_startpoints, {2*x, 2*y}) != -1) flags |= IntersectionFlags::IS_STARTPOINT; + if (find(_startpoints, {x, y}) != -1) flags |= IntersectionFlags::IS_STARTPOINT; intersectionFlags.push_back(flags); + + // Create connections for this intersection -- always write low -> high if (y > 0) { - connections.first.push_back(y * _width + x); - connections.second.push_back((y - 1) * _width + x); + connections_a.push_back(xy_to_loc(x, y-2)); + connections_b.push_back(xy_to_loc(x, y)); } if (x > 0) { - connections.first.push_back(y * _width + x); - connections.second.push_back(y * _width + (x - 1)); + connections_a.push_back(xy_to_loc(x-2, y)); + connections_b.push_back(xy_to_loc(x, y)); } } } for (Endpoint endpoint : _endpoints) { - double xPos = min + endpoint.GetX() * width_interval; - double yPos = min + endpoint.GetY() * height_interval; + connections_a.push_back(xy_to_loc(endpoint.GetX(), endpoint.GetY())); // Target to connect to + connections_b.push_back(static_cast(intersectionFlags.size())); // This endpoint + + double xPos = min + (endpoint.GetX()/2) * width_interval; + double yPos = max - (endpoint.GetY()/2) * height_interval; if (endpoint.GetDir()== Endpoint::Direction::LEFT) { xPos -= .05; } else if (endpoint.GetDir() == Endpoint::Direction::RIGHT) { @@ -200,18 +223,49 @@ void Panel::WriteIntersections(int id) { } intersections.push_back(static_cast(xPos)); intersections.push_back(static_cast(yPos)); - - connections.first.push_back(endpoint.GetY() * _width + endpoint.GetX()); // Target to connect to - connections.second.push_back(static_cast(intersectionFlags.size())); // This endpoint intersectionFlags.push_back(IntersectionFlags::IS_ENDPOINT); } - _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}); + // Dots + for (int y=0; y<_height; y++) { + for (int x=0; x<_width; x++) { + if (!(_grid[x][y] & IntersectionFlags::HAS_DOT)) continue; + if (x%2 == 1 && y%2 == 1) continue; + if (x%2 == 0 && y%2 == 0) { + intersectionFlags[xy_to_loc(x, y)] |= _grid[x][y]; + continue; + } + + // Locate the segment we're breaking + for (int i=0; i(intersectionFlags.size()); // This endpoint + + connections_a.push_back(static_cast(intersectionFlags.size())); // This endpoint + connections_b.push_back(other_connection); + break; + } + } + // Add this dot to the end + double xPos = min + (x/2.0) * width_interval; + double yPos = max - (y/2.0) * height_interval; + intersections.push_back(static_cast(xPos)); + intersections.push_back(static_cast(yPos)); + intersectionFlags.push_back(_grid[x][y]); + } + } + + + _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_a.size())}); + _memory->WriteArray(id, DOT_CONNECTION_A, connections_a); + _memory->WriteArray(id, DOT_CONNECTION_B, connections_b); + _memory->WritePanelData(id, NEEDS_REDRAW, {1}); } diff --git a/Source/Panel.h b/Source/Panel.h index 565b4c3..b8e67df 100644 --- a/Source/Panel.h +++ b/Source/Panel.h @@ -45,7 +45,7 @@ enum IntersectionFlags { IS_ENDPOINT = 0x1, IS_STARTPOINT = 0x2, IS_GAP = 0x10000, - HAS_DOT = 0x20, + HAS_DOT = 0x40020, DOT_IS_BLUE = 0x100, DOT_IS_ORANGE = 0x200, DOT_IS_INVISIBLE = 0x1000, @@ -110,7 +110,7 @@ public: private: // For testing - Panel(); + Panel() = default; void ReadIntersections(int id); void WriteIntersections(int id); @@ -121,8 +121,11 @@ private: // TODO: Decoration colors std::tuple loc_to_xy(int location) { - int x = 2 * (location % ((_width + 1) / 2)); - int y = (_height - 1) - 2 * (location / ((_width + 1) / 2)); + int height2 = (_height - 1) / 2; + int width2 = (_width + 1) / 2; + + int x = 2 * (location % width2); + int y = 2 * (height2 - location / width2); return {x, y}; } @@ -134,7 +137,24 @@ private: return rowsFromBottom * width2 + x/2; } - Memory _memory = Memory("witness64_d3d11.exe"); + std::tuple dloc_to_xy(int location) { + int height2 = (_height - 3) / 2; + int width2 = (_width - 1) / 2; + + int x = 2 * (location % width2) + 1; + int y = 2 * (height2 - location / width2) + 1; + return {x, y}; + } + + int xy_to_dloc(int x, int y) { + int height2 = (_height - 3) / 2; + int width2 = (_width - 1) / 2; + + int rowsFromBottom = height2 - (y - 1)/2; + return rowsFromBottom * width2 + (x - 1)/2; + } + + std::shared_ptr _memory; int _width, _height; -- cgit 1.4.1