From 8e470df5541095d5c0fa6ad7bfa13d92b593fae2 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Sat, 14 Dec 2024 11:00:52 -0500 Subject: [PATCH] A bit of late night work designing the little iterators. --- lights.hpp | 2 +- map.cpp | 6 +- matrix.cpp | 53 ++++++++--- matrix.hpp | 49 +++++++--- pathing.cpp | 22 ++--- pathing.hpp | 5 +- tests/map.cpp | 4 +- tests/matrix.cpp | 199 ++++------------------------------------- tests/pathing.cpp | 4 +- tests/worldbuilder.cpp | 2 +- worldbuilder.cpp | 8 +- 11 files changed, 117 insertions(+), 237 deletions(-) diff --git a/lights.hpp b/lights.hpp index b69523e..7a4abe3 100644 --- a/lights.hpp +++ b/lights.hpp @@ -40,7 +40,7 @@ namespace lighting { LightRender(size_t width, size_t height) : $width(width), $height(height), - $lightmap(height, MatrixRow(width, 0)), + $lightmap(height, matrix::Row(width, 0)), $paths(width, height) {} diff --git a/map.cpp b/map.cpp index 0bb06c6..3b0959a 100644 --- a/map.cpp +++ b/map.cpp @@ -13,7 +13,7 @@ using namespace fmt; Map::Map(size_t width, size_t height) : $width(width), $height(height), - $walls(height, MatrixRow(width, INV_WALL)), + $walls(height, matrix::Row(width, INV_WALL)), $paths(height, width) {} @@ -54,8 +54,8 @@ bool Map::iswall(size_t x, size_t y) { } void Map::dump(int show_x, int show_y) { - matrix_dump("WALLS", walls(), show_x, show_y); - matrix_dump("PATHS", paths(), show_x, show_y); + matrix::dump("WALLS", walls(), show_x, show_y); + matrix::dump("PATHS", paths(), show_x, show_y); } bool Map::can_move(Point move_to) { diff --git a/matrix.cpp b/matrix.cpp index 3c45046..75ab418 100644 --- a/matrix.cpp +++ b/matrix.cpp @@ -3,23 +3,54 @@ #include using namespace fmt; +using matrix::Matrix; -void matrix_dump(const std::string &msg, Matrix &map, int show_x, int show_y) { - println("----------------- {}", msg); - for(size_t y = 0; y < map.size(); y++) { - for(size_t x = 0; x < map[y].size(); x++) { - int col = map[y][x]; +namespace matrix { - if(int(x) == show_x && int(y) == show_y) { - print("{:x}<", col); - } else if(col == WALL_PATH_LIMIT) { + each_cell::each_cell(Matrix &mat) + { + height = mat.size(); + width = mat[0].size(); + } + + bool each_cell::next() { + x++; + x *= (x < width); + y = y + (x == 0); + return y < height; + } + + each_row::each_row(Matrix &mat) : + $mat(mat) + { + height = $mat.size(); + width = $mat[0].size(); + } + + bool each_row::next() { + x++; + x *= (x < width); + y = y + (x == 0); + row = x == width - 1; + cell = y < height ? $mat[y][x] : -1; + return y < height; + } + + void dump(const std::string &msg, Matrix &map, int show_x, int show_y) { + println("----------------- {}", msg); + + for(each_row it{map}; it.next();) { + if(int(it.x) == show_x && int(it.y) == show_y) { + print("{:x}<", it.cell); + } else if(it.cell == WALL_PATH_LIMIT) { print("# "); - } else if(col > 15) { + } else if(it.cell > 15) { print("* "); } else { - print("{:x} ", col); + print("{:x} ", it.cell); } + + if(it.row) print("\n"); } - print("\n"); } } diff --git a/matrix.hpp b/matrix.hpp index df39410..fb13b01 100644 --- a/matrix.hpp +++ b/matrix.hpp @@ -2,16 +2,43 @@ #include #include -typedef std::vector MatrixRow; -typedef std::vector Matrix; - -/* - * Just a quick thing to reset a matrix to a value. - */ -inline void matrix_assign(Matrix &out, int new_value) { - for(auto &row : out) { - row.assign(row.size(), new_value); +namespace matrix { + + typedef std::vector Row; + typedef std::vector Matrix; + + struct each_cell { + size_t x = ~0; + size_t y = ~0; + size_t width = 0; + size_t height = 0; + int cell = 0; + + each_cell(Matrix &mat); + bool next(); + }; + + struct each_row { + Matrix &$mat; + size_t x = ~0; + size_t y = ~0; + size_t width = 0; + size_t height = 0; + int cell = 0; + bool row = false; + + each_row(Matrix &mat); + bool next(); + }; + + /* + * Just a quick thing to reset a matrix to a value. + */ + inline void assign(Matrix &out, int new_value) { + for(auto &row : out) { + row.assign(row.size(), new_value); + } } -} -void matrix_dump(const std::string &msg, Matrix &map, int show_x=-1, int show_y=-1); + void dump(const std::string &msg, Matrix &map, int show_x=-1, int show_y=-1); +} diff --git a/pathing.cpp b/pathing.cpp index 6de97b8..473f206 100644 --- a/pathing.cpp +++ b/pathing.cpp @@ -28,7 +28,7 @@ inline void add_neighbors(PointList &neighbors, Matrix &closed, size_t y, size_t void Pathing::compute_paths(Matrix &walls) { INVARIANT(); // Initialize the new array with every pixel at limit distance - matrix_assign($paths, WALL_PATH_LIMIT); + matrix::assign($paths, WALL_PATH_LIMIT); Matrix closed = walls; PointList starting_pixels; @@ -77,19 +77,13 @@ void Pathing::clear_target(const Point &at) { } void Pathing::random_flood(const Point from, std::function cb) { - int from_x = from.x; - int from_y = from.y; - int dnum = $paths[from.y][from.x]; - cb(from, dnum); - - for(int y = from_y - 1; y <= from_y + 1; y++) { - if(y < 0 || y >= int($height)) continue; - for(int x = from_x - 1; x <= from_x + 1; x++) { - if(x >= 0 && x <= int($width)) { - dnum = $paths[y][x]; - cb({size_t(x), size_t(y)}, dnum); - } - } + // quick hack to try the idea + matrix::each_cell it{$paths}; + it.x = from.x; + it.y = from.y; + + while(it.next()) { + cb({it.x, it.y}, $paths[it.y][it.x]); } } diff --git a/pathing.hpp b/pathing.hpp index 45162f3..2f58035 100644 --- a/pathing.hpp +++ b/pathing.hpp @@ -3,6 +3,7 @@ #include "matrix.hpp" #include +using matrix::Matrix; class Pathing { public: @@ -14,8 +15,8 @@ public: Pathing(size_t width, size_t height) : $width(width), $height(height), - $paths(height, MatrixRow(width, 1)), - $input(height, MatrixRow(width, 1)) + $paths(height, matrix::Row(width, 1)), + $input(height, matrix::Row(width, 1)) {} void compute_paths(Matrix &walls); diff --git a/tests/map.cpp b/tests/map.cpp index 68cf2fd..2ac78d8 100644 --- a/tests/map.cpp +++ b/tests/map.cpp @@ -48,8 +48,8 @@ TEST_CASE("dijkstra algo test", "[map]") { if(paths != expected) { println("ERROR! ------"); - matrix_dump("EXPECTED", expected); - matrix_dump("RESULT", paths); + matrix::dump("EXPECTED", expected); + matrix::dump("RESULT", paths); } REQUIRE(map.INVARIANT()); diff --git a/tests/matrix.cpp b/tests/matrix.cpp index 3ee0ddc..bb07bc1 100644 --- a/tests/matrix.cpp +++ b/tests/matrix.cpp @@ -10,117 +10,7 @@ using namespace nlohmann; using namespace fmt; using std::string; - - - -#include -#include - -struct ItStep { - int cell; - size_t x; - size_t y; - bool row; -}; - -class MatrixIterator1 { - public: - class iterator - { - public: - Matrix &mat; - size_t x = 0; - size_t y = 0; - - using iterator_category = std::input_iterator_tag; - using value_type = ItStep; - using difference_type = ItStep; - using pointer = ItStep *; - using reference = ItStep; - - explicit iterator(Matrix &_mat) - : mat(_mat) {} - - iterator& operator++() { - x++; - if(x < mat[0].size()) { - return *this; - } else { - x = 0; - y++; - return *this; - } - } - - iterator operator++(int) { - iterator retval = *this; - ++(*this); - return retval; - } - - bool operator==(iterator other) const { - return x == other.x && y == other.y; - } - - reference operator*() const { - return { - .cell = mat[y][x], - .x = x, - .y = y, - .row = x >= mat[0].size() - 1 - }; - } - }; - - Matrix &mat; - - MatrixIterator1(Matrix &mat_) : - mat(mat_) - { - } - - iterator begin() { - return iterator(mat); - } - - iterator end() { - iterator it(mat); - it.y = mat.size(); - it.x = 0; - return it; - } -}; - -struct MatrixIterator2 { - Matrix &$mat; - size_t x = ~0; - size_t y = ~0; - size_t width = 0; - size_t height = 0; - int cell = 0; - bool row = false; - - MatrixIterator2(Matrix &mat) : - $mat(mat) - { - height = $mat.size(); - width = $mat[0].size(); - } - - bool next() { - x++; - x *= (x < width); - y = y + (x == 0); - row = x == width - 1; - - if(y < height) { - cell = $mat[y][x]; - return true; - } else { - return false; - } - } -}; +using matrix::Matrix; TEST_CASE("basic matrix iterator", "[matrix]") { std::ifstream infile("./tests/dijkstra.json"); @@ -129,89 +19,30 @@ TEST_CASE("basic matrix iterator", "[matrix]") { Matrix walls = test["walls"]; - matrix_dump("ITERATOR DUMP", walls); + matrix::dump("ITERATOR DUMP", walls); - println("VS Matrix1 ------"); + println("VS matrix::each_row ------"); - for(auto [cell, x, y, row] : MatrixIterator1(walls)) { - REQUIRE(walls[y][x] == cell); - print("{} ", cell); - if(row) print("\n"); + for(matrix::each_row it{walls}; it.next();) { + REQUIRE(walls[it.y][it.x] == it.cell); + print("{} ", it.cell); + if(it.row) print("\n"); } - println("VS Matrix2------"); + // tests going through straight cells but also + // using two iterators on one matrix (or two) + matrix::each_cell cells{walls}; + cells.next(); // kick it off - for(MatrixIterator2 mit{walls}; mit.next();) { - REQUIRE(walls[mit.y][mit.x] == mit.cell); - print("{} ", mit.cell); - if(mit.row) print("\n"); + for(matrix::each_row it{walls}; + it.next(); cells.next()) + { + REQUIRE(walls[cells.y][cells.x] == it.cell); } println("END TEST============="); } - -template -class Range { - public: - class iterator - { - long num = FROM; - - public: - using iterator_category = std::input_iterator_tag; - using value_type = long; - using difference_type = long; - using pointer = const long *; - using reference = long; - - explicit iterator(long _num = 0) : num(_num) {} - - iterator& operator++() { - num = TO >= FROM ? num + 1 : num - 1; - return *this; - } - - iterator operator++(int) { - iterator retval = *this; - ++(*this); - return retval; - } - - bool operator==(iterator other) const { - return num == other.num; - } - - bool operator!=(iterator other) const { - return !(*this == other); - } - - reference operator*() const { - return num; - } - }; - - iterator begin() { - return iterator(FROM); - } - - iterator end() { - return iterator(TO >= FROM ? TO + 1 : TO - 1); - } -}; - -TEST_CASE("basic matrix example", "[matrix]") { - auto range = Range<15, 25>(); - auto itr = std::find(range.begin(), range.end(), 18); - std::cout << *itr << '\n'; - - for(long l : Range<3, 5>()) { - std::cout << l << ' '; - } - - std::cout << '\n'; -} - TEST_CASE("matrix_assign works", "[matrix]") { } diff --git a/tests/pathing.cpp b/tests/pathing.cpp index 62989be..d29a7ec 100644 --- a/tests/pathing.cpp +++ b/tests/pathing.cpp @@ -30,8 +30,8 @@ TEST_CASE("dijkstra algo test", "[pathing]") { REQUIRE(pathing.INVARIANT()); - matrix_dump("PATHING RESULT", pathing.$paths); - matrix_dump("PATHING EXPECTED", expected); + matrix::dump("PATHING RESULT", pathing.$paths); + matrix::dump("PATHING EXPECTED", expected); REQUIRE(pathing.$paths == expected); } } diff --git a/tests/worldbuilder.cpp b/tests/worldbuilder.cpp index 052c6ed..c96513e 100644 --- a/tests/worldbuilder.cpp +++ b/tests/worldbuilder.cpp @@ -20,7 +20,7 @@ TEST_CASE("dumping and debugging", "[builder]") { WorldBuilder builder(map); builder.generate(); - matrix_dump("GENERATED", map.paths()); + matrix::dump("GENERATED", map.paths()); map.dump(); } diff --git a/worldbuilder.cpp b/worldbuilder.cpp index b7cefc4..b926969 100644 --- a/worldbuilder.cpp +++ b/worldbuilder.cpp @@ -131,12 +131,8 @@ void WorldBuilder::generate() { $map.$walls[hole.y][hole.x] = INV_SPACE; } - // invert the whole map to finish it - for(size_t y = 0; y < $map.$height; ++y) { - for(size_t x = 0; x < $map.$width; ++x) { - // invert the map - $map.$walls[y][x] = !$map.$walls[y][x]; - } + for(matrix::each_cell it{$map.$walls}; it.next();) { + $map.$walls[it.y][it.x] = !$map.$walls[it.y][it.x]; } }