From 4d55d7d9aad8d3c2bedec371c165bbb848c3786b Mon Sep 17 00:00:00 2001 From: jbzdarkid Date: Fri, 8 Nov 2019 22:06:07 -0800 Subject: Looks like chained read/write isn't working --- Source/Panel.cpp | 337 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 193 insertions(+), 144 deletions(-) (limited to 'Source/Panel.cpp') diff --git a/Source/Panel.cpp b/Source/Panel.cpp index 43e9763..b6f0403 100644 --- a/Source/Panel.cpp +++ b/Source/Panel.cpp @@ -1,108 +1,36 @@ #include "Panel.h" -#include "Random.h" #include "Memory.h" -#include "Randomizer.h" -#include #pragma warning (disable:26451) +#pragma warning (disable:26812) -template -int find(const std::vector &data, T search, size_t startIndex = 0) { - for (size_t i=startIndex ; i(i); - } - return -1; -} - -Panel::Panel(const std::shared_ptr& memory, int id) : _memory(memory) { - _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); -} - -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}); -} - -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 { - if (_grid[x][y] & IntersectionFlags::HAS_DOT) { - puzzle["dots"].emplace_back(nlohmann::json({{"x", x}, {"y", y}})); - } - 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; -} +PuzzleSerializer::PuzzleSerializer(const std::shared_ptr& memory) : _memory(memory) {} -void Panel::ReadDecorations(int id) { - int numDecorations = _memory->ReadPanelData(id, NUM_DECORATIONS, 1)[0]; - std::vector decorations = _memory->ReadArray(id, DECORATIONS, numDecorations); +Puzzle PuzzleSerializer::ReadPuzzle(int id) { + Puzzle p; + p.width = 2 * _memory->ReadPanelData(id, GRID_SIZE_X, 1)[0] - 1; + p.height = 2 * _memory->ReadPanelData(id, GRID_SIZE_Y, 1)[0] - 1; + p.grid.resize(p.width); + for (auto& row : p.grid) row.resize(p.height); - for (int i=0; i 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]); - } - } + ReadIntersections(p, id); + ReadDecorations(p, id); - _memory->WritePanelData(id, NUM_DECORATIONS, {static_cast(decorations.size())}); - _memory->WriteArray(id, DECORATIONS, decorations); + return p; } -void Panel::ReadIntersections(int id) { +void PuzzleSerializer::ReadIntersections(Puzzle& p, int id) { int numIntersections = _memory->ReadPanelData(id, NUM_DOTS, 1)[0]; std::vector intersectionFlags = _memory->ReadArray(id, DOT_FLAGS, numIntersections); int i = 0; for (;; i++) { - auto [x, y] = loc_to_xy(i); + auto [x, y] = loc_to_xy(p, i); if (y < 0) break; - if (intersectionFlags[i] & IntersectionFlags::IS_STARTPOINT) { - _startpoints.push_back({x, y}); + if (intersectionFlags[i] & Flags::IS_STARTPOINT) { + p.grid[x][y].start = true; } + p.grid[x][y].dot = FlagsToDot(intersectionFlags[i]); } int numConnections = _memory->ReadPanelData(id, NUM_CONNECTIONS, 1)[0]; @@ -112,34 +40,32 @@ void Panel::ReadIntersections(int id) { // Iterate the remaining intersections (endpoints, dots, gaps) for (; i < numIntersections; i++) { - if (intersectionFlags[i] & IntersectionFlags::IS_ENDPOINT) { + if (intersectionFlags[i] & Flags::IS_ENDPOINT) { for (int j=0; j intersections[2*location]) { - dir = Endpoint::Direction::RIGHT; + p.grid[x][y].end = Cell::Dir::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; + p.grid[x][y].end = Cell::Dir::UP; } else { - dir = Endpoint::Direction::DOWN; + p.grid[x][y].end = Cell::Dir::DOWN; } - auto [x, y] = loc_to_xy(location); - _endpoints.push_back(Endpoint(x, y, dir)); break; } } - } else if (intersectionFlags[i] & IntersectionFlags::HAS_DOT) { + } else if (intersectionFlags[i] & Flags::HAS_DOT) { for (int j=0; jReadPanelData(id, NUM_DECORATIONS, 1)[0]; + std::vector decorations = _memory->ReadArray(id, DECORATIONS, numDecorations); + if (numDecorations != decorations.size()) return; // @Error! + + for (int i=0; i(); + p.grid[x][y].decoration = d; + d->type = static_cast(decorations[i] & 0xFF00); + switch(d->type) { + case Shape::Poly: + case Shape::RPoly: + case Shape::Ylop: + d->polyshape = decorations[i] & 0xFFFF0000; + break; + case Shape::Triangle: + d->count = decorations[i] & 0x000F0000; + break; + } + d->color = static_cast(decorations[i] & 0xF); + } +} + +void PuzzleSerializer::WritePuzzle(const Puzzle& p, int id) { + _memory->WritePanelData(id, GRID_SIZE_X, {(p.width + 1)/2}); + _memory->WritePanelData(id, GRID_SIZE_Y, {(p.height + 1)/2}); + + WriteIntersections(p, id); + WriteDecorations(p, id); + + _memory->WritePanelData(id, NEEDS_REDRAW, {1}); +} + +void PuzzleSerializer::WriteIntersections(const Puzzle& p, int id) { std::vector intersections; std::vector intersectionFlags; 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); + float min = 0.1f; + float max = 0.9f; + float width_interval = (max - min) / (p.width/2); + float height_interval = (max - min) / (p.height/2); - // 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) { + // @Cleanup: If I write directly to locations, then I can remove this gross loop iterator. + for (int y=p.height-1; y>=0; y-=2) { + for (int x=0; x(min + (x/2) * width_interval)); intersections.push_back(static_cast(max - (y/2) * height_interval)); int flags = 0; - if (find(_startpoints, {x, y}) != -1) flags |= IntersectionFlags::IS_STARTPOINT; + if (p.grid[x][y].start) { + flags |= Flags::IS_STARTPOINT; + } intersectionFlags.push_back(flags); // Create connections for this intersection -- always write low -> high if (y > 0) { - connections_a.push_back(xy_to_loc(x, y-2)); - connections_b.push_back(xy_to_loc(x, y)); + connections_a.push_back(xy_to_loc(p, x, y-2)); + connections_b.push_back(xy_to_loc(p, x, y)); } if (x > 0) { - connections_a.push_back(xy_to_loc(x-2, y)); - connections_b.push_back(xy_to_loc(x, y)); + connections_a.push_back(xy_to_loc(p, x-2, y)); + connections_b.push_back(xy_to_loc(p, x, y)); } } } - for (Endpoint endpoint : _endpoints) { - 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) { - xPos += .05; - } else if (endpoint.GetDir() == Endpoint::Direction::UP) { - yPos += .05; // Y position goes from 0 (bottom) to 1 (top), so this is reversed. - } else if (endpoint.GetDir() == Endpoint::Direction::DOWN) { - yPos -= .05; - } - intersections.push_back(static_cast(xPos)); - intersections.push_back(static_cast(yPos)); - intersectionFlags.push_back(IntersectionFlags::IS_ENDPOINT); - } + for (int x=0; x(intersectionFlags.size())); // This endpoint + + float xPos = min + (x/2) * width_interval; + float yPos = max - (y/2) * height_interval; + switch (p.grid[x][y].end) { + case Cell::Dir::LEFT: + xPos -= .05f; + break; + case Cell::Dir::RIGHT: + xPos += .05f; + break; + case Cell::Dir::UP: + yPos += .05f; // Y position goes from 0 (bottom) to 1 (top), so this is reversed. + break; + case Cell::Dir::DOWN: + yPos -= .05f; + break; + } + intersections.push_back(xPos); + intersections.push_back(yPos); + intersectionFlags.push_back(Flags::IS_ENDPOINT); + } + } // Dots - for (int y=0; y<_height; y++) { - for (int x=0; x<_width; x++) { - if (!(_grid[x][y] & IntersectionFlags::HAS_DOT)) continue; + for (int x=0; x(xPos)); - intersections.push_back(static_cast(yPos)); - intersectionFlags.push_back(_grid[x][y]); + float xPos = min + (x/2.0f) * width_interval; + float yPos = max - (y/2.0f) * height_interval; + intersections.push_back(xPos); + intersections.push_back(yPos); + intersectionFlags.push_back(flags); } } - _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}); } +void PuzzleSerializer::WriteDecorations(const Puzzle& p, int id) { + std::vector decorations; + for (int y=p.height-2; y>0; y-=2) { + for (int x=1; xcolor | d->type | d->count | d->polyshape); + } else { + decorations.push_back(0); + } + } + } + + _memory->WritePanelData(id, NUM_DECORATIONS, {static_cast(decorations.size())}); + _memory->WriteArray(id, DECORATIONS, decorations); +} + +std::tuple PuzzleSerializer::loc_to_xy(const Puzzle& p, int location) { + int height2 = (p.height - 1) / 2; + int width2 = (p.width + 1) / 2; + + int x = 2 * (location % width2); + int y = 2 * (height2 - location / width2); + return {x, y}; +} + +int PuzzleSerializer::xy_to_loc(const Puzzle& p, int x, int y) { + int height2 = (p.height - 1) / 2; + int width2 = (p.width + 1) / 2; + + int rowsFromBottom = height2 - y/2; + return rowsFromBottom * width2 + x/2; +} + +std::tuple PuzzleSerializer::dloc_to_xy(const Puzzle& p, int location) { + int height2 = (p.height - 3) / 2; + int width2 = (p.width - 1) / 2; + + int x = 2 * (location % width2) + 1; + int y = 2 * (height2 - location / width2) + 1; + return {x, y}; +} + +int PuzzleSerializer::xy_to_dloc(const Puzzle& p, int x, int y) { + int height2 = (p.height - 3) / 2; + int width2 = (p.width - 1) / 2; + + int rowsFromBottom = height2 - (y - 1)/2; + return rowsFromBottom * width2 + (x - 1)/2; +} + +Cell::Dot PuzzleSerializer::FlagsToDot(int flags) { + if (!(flags & Flags::HAS_DOT)) return Cell::Dot::NONE; + if (flags & Flags::DOT_IS_BLUE) { + return Cell::Dot::BLUE; + } else if (flags & Flags::DOT_IS_ORANGE) { + return Cell::Dot::YELLOW; + } else if (flags & Flags::DOT_IS_INVISIBLE) { + return Cell::Dot::INVISIBLE; + } else { + return Cell::Dot::BLACK; + } +} -- cgit 1.4.1