#include #include #include #include "config.hpp" #include "matrix.hpp" #include "rand.hpp" #include "components.hpp" #include "worldbuilder.hpp" #include #include using namespace nlohmann; using namespace fmt; using std::string; using matrix::Matrix; TEST_CASE("basic matrix iterator", "[matrix:basic]") { std::ifstream infile("./tests/dijkstra.json"); json data = json::parse(infile); auto test = data[0]; Matrix walls = test["walls"]; // 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 size_t row_count = 0; for(matrix::each_row it{walls}; it.next(); cells.next()) { REQUIRE(walls[cells.y][cells.x] == walls[it.y][it.x]); row_count += it.row; } REQUIRE(row_count == walls.size()); { // test getting the correct height in the middle row_count = 0; matrix::in_box box{walls, 2,2, 1}; while(box.next()) { row_count += box.x == box.left; walls[box.y][box.x] = 3; } matrix::dump("2,2 WALLS", walls, 2, 2); REQUIRE(row_count == 3); } { matrix::dump("1:1 POINT", walls, 1,1); // confirm boxes have the right number of rows // when x goes to 0 on first next call row_count = 0; matrix::in_box box{walls, 1, 1, 1}; while(box.next()) { row_count += box.x == box.left; } 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) { for(size_t y = 0; y < out.size(); y++) { for(size_t x = 0; x < out[0].size(); x++) { out[y][x] = Random::uniform(-10,10); } } } TEST_CASE("thash matrix iterators", "[matrix]") { for(int count = 0; count < Random::uniform(10,30); count++) { size_t width = Random::uniform(1, 100); size_t height = Random::uniform(1, 100); Matrix test(width, matrix::Row(height)); random_matrix(test); // first make a randomized matrix matrix::each_cell cells{test}; cells.next(); // kick off the other iterator for(matrix::each_row it{test}; it.next(); cells.next()) { REQUIRE(test[cells.y][cells.x] == test[it.y][it.x]); } } } TEST_CASE("thrash box iterators", "[matrix]") { for(int count = 0; count < 20; count++) { size_t width = Random::uniform(1, 25); size_t height = Random::uniform(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(20,30); // go through every cell for(matrix::each_cell target{test}; target.next();) { PointList result; // make a random size box size_t size = Random::uniform(1, 33); matrix::in_box box{test, target.x, target.y, size}; while(box.next()) { test[box.y][box.x] = test_i; result.push_back({box.x, box.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("thrash compass iterators", "[matrix:compass]") { for(int count = 0; count < 2000; count++) { size_t width = Random::uniform(1, 25); size_t height = Random::uniform(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(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 < 1000; count++) { size_t width = Random::uniform(10, 25); size_t height = Random::uniform(10, 33); Map map(width,height); WorldBuilder builder(map); builder.generate(); if(map.room_count() < 2) continue; Point start = map.place_entity(map.room_count() / 2); map.set_target(start); map.make_paths(); Matrix result = map.paths(); // matrix::dump("WALLS BEFORE FLOOD", result, start.x, start.y); for(matrix::flood it{result, start, 3, 15}; it.next();) { REQUIRE(matrix::inbounds(result, it.x, it.y)); result[it.y][it.x] = 15; } // matrix::dump("WALLS AFTER FLOOD", result, start.x, start.y); } } TEST_CASE("prototype line algorithm", "[matrix:line]") { size_t width = Random::uniform(10, 12); size_t height = Random::uniform(10, 15); Map map(width,height); // create a target for the paths Point start{.x=map.width() / 2, .y=map.height()/2}; for(matrix::in_box box{map.walls(), start.x, start.y, 3}; box.next();) { Matrix result = map.walls(); result[start.y][start.x] = 1; Point end{.x=box.x, .y=box.y}; for(matrix::line it{start, end}; it.next();) { REQUIRE(map.inmap(it.x, it.y)); result[it.y][it.x] = 15; } result[start.y][start.x] = 15; // matrix::dump("RESULT AFTER LINE", result, end.x, end.y); bool f_found = false; for(matrix::each_cell it{result}; it.next();) { if(result[it.y][it.x] == 15) { f_found = true; break; } } REQUIRE(f_found); } } TEST_CASE("prototype circle algorithm", "[matrix:circle]") { size_t width = Random::uniform(10, 13); size_t height = Random::uniform(10, 15); Map map(width,height); // create a target for the paths Point start{.x=map.width() / 2, .y=map.height()/2}; for(int radius = 2; radius < 5; radius++) { // use an empty map Matrix result = map.walls(); for(matrix::circle it{start, radius}; it.next();) { for(int i = it.x0; i < it.x1; i++) { result[it.y][i] += 1; } } // matrix::dump("RESULT AFTER CIRCLE", result, start.x, start.y); } }