A slightly working flood iterator and a working compass iterator.
This commit is contained in:
parent
043c0d91df
commit
1295e9631d
6 changed files with 214 additions and 4 deletions
85
matrix.cpp
85
matrix.cpp
|
@ -1,5 +1,6 @@
|
|||
#include "matrix.hpp"
|
||||
#include "constants.hpp"
|
||||
#include "dbc.hpp"
|
||||
#include <fmt/core.h>
|
||||
|
||||
using namespace fmt;
|
||||
|
@ -83,6 +84,89 @@ namespace matrix {
|
|||
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) {
|
||||
println("----------------- {}", msg);
|
||||
|
||||
|
@ -102,4 +186,5 @@ namespace matrix {
|
|||
if(it.row) print("\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
48
matrix.hpp
48
matrix.hpp
|
@ -1,11 +1,18 @@
|
|||
#pragma once
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
#include <array>
|
||||
#include <fmt/core.h>
|
||||
#include "point.hpp"
|
||||
|
||||
using fmt::println;
|
||||
|
||||
namespace matrix {
|
||||
using std::vector, std::queue, std::array;
|
||||
|
||||
typedef std::vector<int> Row;
|
||||
typedef std::vector<Row> Matrix;
|
||||
typedef vector<int> Row;
|
||||
typedef vector<Row> Matrix;
|
||||
|
||||
struct each_cell {
|
||||
size_t x = ~0;
|
||||
|
@ -42,6 +49,18 @@ namespace matrix {
|
|||
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.
|
||||
*/
|
||||
|
@ -51,5 +70,28 @@ namespace matrix {
|
|||
}
|
||||
}
|
||||
|
||||
void dump(const std::string &msg, Matrix &map, int show_x=-1, int show_y=-1);
|
||||
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);
|
||||
|
||||
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:
|
||||
|
||||
* Fire icon \u2034
|
||||
* Water icon \u224b
|
||||
* Flame pillars icon \u2e3e
|
||||
* Room should always be found.
|
||||
|
||||
* 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) {
|
||||
light.render_light(lightsource, position.location);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
void System::enemy_pathing(DinkyECS::World &world, Map &game_map, Player &player) {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "matrix.hpp"
|
||||
#include "rand.hpp"
|
||||
#include "components.hpp"
|
||||
#include "worldbuilder.hpp"
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <fstream>
|
||||
|
||||
|
@ -13,7 +14,7 @@ using namespace fmt;
|
|||
using std::string;
|
||||
using matrix::Matrix;
|
||||
|
||||
TEST_CASE("basic matrix iterator", "[matrix]") {
|
||||
TEST_CASE("basic matrix iterator", "[matrix:basic]") {
|
||||
std::ifstream infile("./tests/dijkstra.json");
|
||||
json data = json::parse(infile);
|
||||
auto test = data[0];
|
||||
|
@ -61,6 +62,15 @@ TEST_CASE("basic matrix iterator", "[matrix]") {
|
|||
}
|
||||
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) {
|
||||
|
@ -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();
|
||||
|
||||
dbc::check($map.room_count() > 0, "map generated zero rooms, map too small?");
|
||||
|
||||
for(size_t i = 0; i < $map.$rooms.size() - 1; i++) {
|
||||
tunnel_doors(holes, $map.$rooms[i], $map.$rooms[i+1]);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue