A bit of late night work designing the little iterators.
This commit is contained in:
parent
da0b941dfd
commit
8e470df554
11 changed files with 115 additions and 235 deletions
|
@ -40,7 +40,7 @@ namespace lighting {
|
||||||
LightRender(size_t width, size_t height) :
|
LightRender(size_t width, size_t height) :
|
||||||
$width(width),
|
$width(width),
|
||||||
$height(height),
|
$height(height),
|
||||||
$lightmap(height, MatrixRow(width, 0)),
|
$lightmap(height, matrix::Row(width, 0)),
|
||||||
$paths(width, height)
|
$paths(width, height)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
6
map.cpp
6
map.cpp
|
@ -13,7 +13,7 @@ using namespace fmt;
|
||||||
Map::Map(size_t width, size_t height) :
|
Map::Map(size_t width, size_t height) :
|
||||||
$width(width),
|
$width(width),
|
||||||
$height(height),
|
$height(height),
|
||||||
$walls(height, MatrixRow(width, INV_WALL)),
|
$walls(height, matrix::Row(width, INV_WALL)),
|
||||||
$paths(height, width)
|
$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) {
|
void Map::dump(int show_x, int show_y) {
|
||||||
matrix_dump("WALLS", walls(), show_x, show_y);
|
matrix::dump("WALLS", walls(), show_x, show_y);
|
||||||
matrix_dump("PATHS", paths(), show_x, show_y);
|
matrix::dump("PATHS", paths(), show_x, show_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Map::can_move(Point move_to) {
|
bool Map::can_move(Point move_to) {
|
||||||
|
|
53
matrix.cpp
53
matrix.cpp
|
@ -3,23 +3,54 @@
|
||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
|
|
||||||
using namespace fmt;
|
using namespace fmt;
|
||||||
|
using matrix::Matrix;
|
||||||
|
|
||||||
void matrix_dump(const std::string &msg, Matrix &map, int show_x, int show_y) {
|
namespace matrix {
|
||||||
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];
|
|
||||||
|
|
||||||
if(int(x) == show_x && int(y) == show_y) {
|
each_cell::each_cell(Matrix &mat)
|
||||||
print("{:x}<", col);
|
{
|
||||||
} else if(col == WALL_PATH_LIMIT) {
|
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("# ");
|
print("# ");
|
||||||
} else if(col > 15) {
|
} else if(it.cell > 15) {
|
||||||
print("* ");
|
print("* ");
|
||||||
} else {
|
} else {
|
||||||
print("{:x} ", col);
|
print("{:x} ", it.cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(it.row) print("\n");
|
||||||
}
|
}
|
||||||
print("\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
47
matrix.hpp
47
matrix.hpp
|
@ -2,16 +2,43 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
typedef std::vector<int> MatrixRow;
|
namespace matrix {
|
||||||
typedef std::vector<MatrixRow> Matrix;
|
|
||||||
|
|
||||||
/*
|
typedef std::vector<int> Row;
|
||||||
* Just a quick thing to reset a matrix to a value.
|
typedef std::vector<Row> Matrix;
|
||||||
*/
|
|
||||||
inline void matrix_assign(Matrix &out, int new_value) {
|
struct each_cell {
|
||||||
for(auto &row : out) {
|
size_t x = ~0;
|
||||||
row.assign(row.size(), new_value);
|
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);
|
||||||
|
}
|
||||||
|
|
20
pathing.cpp
20
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) {
|
void Pathing::compute_paths(Matrix &walls) {
|
||||||
INVARIANT();
|
INVARIANT();
|
||||||
// Initialize the new array with every pixel at limit distance
|
// 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;
|
Matrix closed = walls;
|
||||||
PointList starting_pixels;
|
PointList starting_pixels;
|
||||||
|
@ -77,19 +77,13 @@ void Pathing::clear_target(const Point &at) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Pathing::random_flood(const Point from, std::function<void(Point at, int dnum)> cb) {
|
void Pathing::random_flood(const Point from, std::function<void(Point at, int dnum)> cb) {
|
||||||
int from_x = from.x;
|
// quick hack to try the idea
|
||||||
int from_y = from.y;
|
matrix::each_cell it{$paths};
|
||||||
int dnum = $paths[from.y][from.x];
|
it.x = from.x;
|
||||||
cb(from, dnum);
|
it.y = from.y;
|
||||||
|
|
||||||
for(int y = from_y - 1; y <= from_y + 1; y++) {
|
while(it.next()) {
|
||||||
if(y < 0 || y >= int($height)) continue;
|
cb({it.x, it.y}, $paths[it.y][it.x]);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "matrix.hpp"
|
#include "matrix.hpp"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
using matrix::Matrix;
|
||||||
|
|
||||||
class Pathing {
|
class Pathing {
|
||||||
public:
|
public:
|
||||||
|
@ -14,8 +15,8 @@ public:
|
||||||
Pathing(size_t width, size_t height) :
|
Pathing(size_t width, size_t height) :
|
||||||
$width(width),
|
$width(width),
|
||||||
$height(height),
|
$height(height),
|
||||||
$paths(height, MatrixRow(width, 1)),
|
$paths(height, matrix::Row(width, 1)),
|
||||||
$input(height, MatrixRow(width, 1))
|
$input(height, matrix::Row(width, 1))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void compute_paths(Matrix &walls);
|
void compute_paths(Matrix &walls);
|
||||||
|
|
|
@ -48,8 +48,8 @@ TEST_CASE("dijkstra algo test", "[map]") {
|
||||||
|
|
||||||
if(paths != expected) {
|
if(paths != expected) {
|
||||||
println("ERROR! ------");
|
println("ERROR! ------");
|
||||||
matrix_dump("EXPECTED", expected);
|
matrix::dump("EXPECTED", expected);
|
||||||
matrix_dump("RESULT", paths);
|
matrix::dump("RESULT", paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
REQUIRE(map.INVARIANT());
|
REQUIRE(map.INVARIANT());
|
||||||
|
|
199
tests/matrix.cpp
199
tests/matrix.cpp
|
@ -10,117 +10,7 @@
|
||||||
using namespace nlohmann;
|
using namespace nlohmann;
|
||||||
using namespace fmt;
|
using namespace fmt;
|
||||||
using std::string;
|
using std::string;
|
||||||
|
using matrix::Matrix;
|
||||||
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_CASE("basic matrix iterator", "[matrix]") {
|
TEST_CASE("basic matrix iterator", "[matrix]") {
|
||||||
std::ifstream infile("./tests/dijkstra.json");
|
std::ifstream infile("./tests/dijkstra.json");
|
||||||
|
@ -129,89 +19,30 @@ TEST_CASE("basic matrix iterator", "[matrix]") {
|
||||||
|
|
||||||
Matrix walls = test["walls"];
|
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)) {
|
for(matrix::each_row it{walls}; it.next();) {
|
||||||
REQUIRE(walls[y][x] == cell);
|
REQUIRE(walls[it.y][it.x] == it.cell);
|
||||||
print("{} ", cell);
|
print("{} ", it.cell);
|
||||||
if(row) print("\n");
|
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();) {
|
for(matrix::each_row it{walls};
|
||||||
REQUIRE(walls[mit.y][mit.x] == mit.cell);
|
it.next(); cells.next())
|
||||||
print("{} ", mit.cell);
|
{
|
||||||
if(mit.row) print("\n");
|
REQUIRE(walls[cells.y][cells.x] == it.cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
println("END TEST=============");
|
println("END TEST=============");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<long FROM, long TO>
|
|
||||||
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]") {
|
TEST_CASE("matrix_assign works", "[matrix]") {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,8 +30,8 @@ TEST_CASE("dijkstra algo test", "[pathing]") {
|
||||||
|
|
||||||
REQUIRE(pathing.INVARIANT());
|
REQUIRE(pathing.INVARIANT());
|
||||||
|
|
||||||
matrix_dump("PATHING RESULT", pathing.$paths);
|
matrix::dump("PATHING RESULT", pathing.$paths);
|
||||||
matrix_dump("PATHING EXPECTED", expected);
|
matrix::dump("PATHING EXPECTED", expected);
|
||||||
REQUIRE(pathing.$paths == expected);
|
REQUIRE(pathing.$paths == expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ TEST_CASE("dumping and debugging", "[builder]") {
|
||||||
WorldBuilder builder(map);
|
WorldBuilder builder(map);
|
||||||
builder.generate();
|
builder.generate();
|
||||||
|
|
||||||
matrix_dump("GENERATED", map.paths());
|
matrix::dump("GENERATED", map.paths());
|
||||||
map.dump();
|
map.dump();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -131,12 +131,8 @@ void WorldBuilder::generate() {
|
||||||
$map.$walls[hole.y][hole.x] = INV_SPACE;
|
$map.$walls[hole.y][hole.x] = INV_SPACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// invert the whole map to finish it
|
for(matrix::each_cell it{$map.$walls}; it.next();) {
|
||||||
for(size_t y = 0; y < $map.$height; ++y) {
|
$map.$walls[it.y][it.x] = !$map.$walls[it.y][it.x];
|
||||||
for(size_t x = 0; x < $map.$width; ++x) {
|
|
||||||
// invert the map
|
|
||||||
$map.$walls[y][x] = !$map.$walls[y][x];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue