|
|
|
#include <catch2/catch_test_macros.hpp>
|
|
|
|
#include <fmt/core.h>
|
|
|
|
#include <string>
|
|
|
|
#include "config.hpp"
|
|
|
|
#include "matrix.hpp"
|
|
|
|
#include "rand.hpp"
|
|
|
|
#include "components.hpp"
|
|
|
|
#include "worldbuilder.hpp"
|
|
|
|
#include <nlohmann/json.hpp>
|
|
|
|
#include <fstream>
|
|
|
|
|
|
|
|
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<int>(-10,10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_CASE("thash matrix iterators", "[matrix]") {
|
|
|
|
for(int count = 0; count < Random::uniform<int>(10,30); count++) {
|
|
|
|
size_t width = Random::uniform<size_t>(1, 100);
|
|
|
|
size_t height = Random::uniform<size_t>(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<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
|
|
|
|
size_t size = Random::uniform<int>(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 < 20; 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 < 20; 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();
|
|
|
|
|
|
|
|
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<size_t>(10, 12);
|
|
|
|
size_t height = Random::uniform<size_t>(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<size_t>(10, 13);
|
|
|
|
size_t height = Random::uniform<size_t>(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);
|
|
|
|
}
|
|
|
|
}
|