A slightly working flood iterator and a working compass iterator.

main
Zed A. Shaw 4 days ago
parent 043c0d91df
commit 1295e9631d
  1. 85
      matrix.cpp
  2. 46
      matrix.hpp
  3. 3
      status.txt
  4. 1
      systems.cpp
  5. 81
      tests/matrix.cpp
  6. 2
      worldbuilder.cpp

@ -1,5 +1,6 @@
#include "matrix.hpp" #include "matrix.hpp"
#include "constants.hpp" #include "constants.hpp"
#include "dbc.hpp"
#include <fmt/core.h> #include <fmt/core.h>
using namespace fmt; using namespace fmt;
@ -83,6 +84,89 @@ namespace matrix {
x, y, left, right, top, bottom); x, y, left, right, top, bottom);
} }
compass::compass(Matrix &mat, size_t x, size_t y) :
x(x), y(y)
{
array<int, 4> x_in{0, 1, 0, -1};
array<int, 4> y_in{-1, 0, 1, 0};
for(size_t i = 0; i < 4; i++) {
int nx = x + x_in[i];
int ny = y + y_in[i];
if(matrix::inbounds(mat, nx, ny)) {
x_dirs[max_dirs] = nx;
y_dirs[max_dirs] = ny;
max_dirs++;
}
}
}
bool compass::next() {
dir++;
if(dir < max_dirs) {
x = x_dirs[dir];
y = y_dirs[dir];
return true;
} else {
return false;
}
}
flood::flood(Matrix &mat, Point start, int old_val, int new_val) :
mat(mat), start(start), old_val(old_val), new_val(new_val),
dirs{mat, start.x, start.y}
{
dbc::check(old_val != new_val, "what you doing?");
current_loc = start;
q.push(start);
}
bool flood::next() {
if(!q.empty()) {
if(!dirs.next()) {
// box is done reset it
auto current_loc = q.front();
q.pop();
dirs = matrix::compass{mat, current_loc.x, current_loc.y};
dirs.next();
}
// get the next thing
if(mat[dirs.y][dirs.x] == old_val) {
mat[dirs.y][dirs.x] += new_val;
x = dirs.x;
y = dirs.y;
q.push({.x=dirs.x, .y=dirs.y});
}
return true;
} else {
return false;
}
}
bool flood::next_working() {
if(!q.empty()) {
auto current_loc = q.front();
q.pop();
for(matrix::in_box box{mat, current_loc.x, current_loc.y, 1};
box.next();)
{
if(mat[box.y][box.x] == old_val) {
mat[box.y][box.x] += new_val;
q.push({.x=box.x, .y=box.y});
}
}
return true;
} else {
return false;
}
}
void dump(const std::string &msg, Matrix &map, int show_x, int show_y) { void dump(const std::string &msg, Matrix &map, int show_x, int show_y) {
println("----------------- {}", msg); println("----------------- {}", msg);
@ -102,4 +186,5 @@ namespace matrix {
if(it.row) print("\n"); if(it.row) print("\n");
} }
} }
} }

@ -1,11 +1,18 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include <queue>
#include <string> #include <string>
#include <array>
#include <fmt/core.h>
#include "point.hpp"
using fmt::println;
namespace matrix { namespace matrix {
using std::vector, std::queue, std::array;
typedef std::vector<int> Row; typedef vector<int> Row;
typedef std::vector<Row> Matrix; typedef vector<Row> Matrix;
struct each_cell { struct each_cell {
size_t x = ~0; size_t x = ~0;
@ -42,6 +49,18 @@ namespace matrix {
void dump(); void dump();
}; };
struct compass {
size_t x = 0; // these are set in constructor
size_t y = 0; // again, no fancy ~ trick needed
array<int, 4> x_dirs{0, 1, 0, -1};
array<int, 4> y_dirs{-1, 0, 1, 0};
size_t max_dirs=0;
size_t dir = ~0;
compass(Matrix &mat, size_t x, size_t y);
bool next();
};
/* /*
* Just a quick thing to reset a matrix to a value. * Just a quick thing to reset a matrix to a value.
*/ */
@ -51,5 +70,28 @@ namespace matrix {
} }
} }
inline bool inbounds(Matrix &mat, size_t x, size_t y) {
// since Point.x and Point.y are size_t any negatives are massive
bool res = (y < mat.size()) && (x < mat[0].size());
return res;
}
void 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);
struct flood {
Matrix &mat;
Point start;
int old_val;
int new_val;
queue<Point> q;
Point current_loc;
int x;
int y;
matrix::compass dirs;
flood(Matrix &mat, Point start, int old_val, int new_val);
bool next();
bool next_working();
};
} }

@ -1,5 +1,8 @@
TODAY'S GOAL: TODAY'S GOAL:
* Fire icon \u2034
* Water icon \u224b
* Flame pillars icon \u2e3e
* Room should always be found. * Room should always be found.
* Change the test matrix to be irregular dimensions. * Change the test matrix to be irregular dimensions.

@ -31,7 +31,6 @@ void System::lighting(DinkyECS::World &world, Map &game_map, LightRender &light,
world.query<Position, LightSource>([&](const auto &ent, auto &position, auto &lightsource) { world.query<Position, LightSource>([&](const auto &ent, auto &position, auto &lightsource) {
light.render_light(lightsource, position.location); light.render_light(lightsource, position.location);
}); });
} }
void System::enemy_pathing(DinkyECS::World &world, Map &game_map, Player &player) { void System::enemy_pathing(DinkyECS::World &world, Map &game_map, Player &player) {

@ -5,6 +5,7 @@
#include "matrix.hpp" #include "matrix.hpp"
#include "rand.hpp" #include "rand.hpp"
#include "components.hpp" #include "components.hpp"
#include "worldbuilder.hpp"
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <fstream> #include <fstream>
@ -13,7 +14,7 @@ using namespace fmt;
using std::string; using std::string;
using matrix::Matrix; using matrix::Matrix;
TEST_CASE("basic matrix iterator", "[matrix]") { TEST_CASE("basic matrix iterator", "[matrix:basic]") {
std::ifstream infile("./tests/dijkstra.json"); std::ifstream infile("./tests/dijkstra.json");
json data = json::parse(infile); json data = json::parse(infile);
auto test = data[0]; auto test = data[0];
@ -61,6 +62,15 @@ TEST_CASE("basic matrix iterator", "[matrix]") {
} }
REQUIRE(row_count == 3); REQUIRE(row_count == 3);
} }
{
matrix::compass star{walls, 1, 1};
while(star.next()) {
println("START IS {},{}=={}", star.x, star.y, walls[star.y][star.x]);
walls[star.y][star.x] = 11;
}
matrix::dump("STAR POINT", walls, 1,1);
}
} }
inline void random_matrix(Matrix &out) { inline void random_matrix(Matrix &out) {
@ -121,3 +131,72 @@ TEST_CASE("thrash box iterators", "[matrix]") {
} }
} }
} }
TEST_CASE("thrash compass iterators", "[matrix:compass]") {
for(int count = 0; count < 2000; count++) {
size_t width = Random::uniform<size_t>(1, 25);
size_t height = Random::uniform<size_t>(1, 33);
Matrix test(height, matrix::Row(width));
random_matrix(test);
// this will be greater than the random_matrix cells
int test_i = Random::uniform<size_t>(20,30);
// go through every cell
for(matrix::each_cell target{test}; target.next();) {
PointList result;
// make a random size box
matrix::compass compass{test, target.x, target.y};
while(compass.next()) {
test[compass.y][compass.x] = test_i;
result.push_back({compass.x, compass.y});
}
for(auto point : result) {
REQUIRE(test[point.y][point.x] == test_i);
test[point.y][point.x] = 10; // kind of reset it for another try
}
}
}
}
TEST_CASE("prototype flood algorithm", "[matrix:flood]") {
for(int count = 0; count < 1; count++) {
size_t width = Random::uniform<size_t>(10, 25);
size_t height = Random::uniform<size_t>(10, 33);
Map map(width,height);
WorldBuilder builder(map);
builder.generate();
REQUIRE(map.room_count() > 0);
Point start = map.place_entity(map.room_count() / 2);
// BUG: place_entity should not put things in walls
map.$walls[start.y][start.x] = 0;
matrix::dump("WALLS BEFORE FLOOD", map.walls(), start.x, start.y);
/*
for(matrix::flood it{map.$walls, start, 0, 10}; it.next_working(); tick++) {
println("TEST WORKING");
}
*/
for(matrix::flood it{map.$walls, start, 0, 15}; it.next();) {
REQUIRE(matrix::inbounds(map.$walls, it.x, it.y));
map.$walls[it.y][it.x] = 15;
}
matrix::dump("WALLS AFTER FLOOD", map.walls(), start.x, start.y);
// confirm that everything is 1 or 2 which confirms
// every cell possible is visited and nothing is visited twice
for(matrix::each_cell it{map.$walls}; it.next();) {
REQUIRE(map.$walls[it.y][it.x] <= 15);
}
}
}

@ -120,6 +120,8 @@ void WorldBuilder::generate() {
place_rooms(); place_rooms();
dbc::check($map.room_count() > 0, "map generated zero rooms, map too small?");
for(size_t i = 0; i < $map.$rooms.size() - 1; i++) { for(size_t i = 0; i < $map.$rooms.size() - 1; i++) {
tunnel_doors(holes, $map.$rooms[i], $map.$rooms[i+1]); tunnel_doors(holes, $map.$rooms[i], $map.$rooms[i+1]);
} }

Loading…
Cancel
Save