diff --git a/lights.cpp b/lights.cpp index 769fceb..a77f6b4 100644 --- a/lights.cpp +++ b/lights.cpp @@ -20,7 +20,7 @@ namespace lighting { const int wall_light = source.strength + WALL_LIGHT_LEVEL; for(auto point : has_light) { - for(matrix::in_box it{$lightmap, point.x, point.y, 1}; it.next();) { + for(matrix::compass it{$lightmap, point.x, point.y}; it.next();) { if($paths.$paths[it.y][it.x] == WALL_PATH_LIMIT) { $lightmap[it.y][it.x] = light_level(wall_light, point.x, point.y); } diff --git a/matrix.cpp b/matrix.cpp index ec27ab8..6701a46 100644 --- a/matrix.cpp +++ b/matrix.cpp @@ -2,6 +2,8 @@ #include "constants.hpp" #include "dbc.hpp" #include +#include +#include using namespace fmt; using std::min, std::max; @@ -114,7 +116,7 @@ namespace matrix { 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} + x(start.x), y(start.y), dirs{mat, start.x, start.y} { dbc::check(old_val != new_val, "what you doing?"); current_loc = start; @@ -133,8 +135,8 @@ namespace matrix { } // get the next thing - if(mat[dirs.y][dirs.x] == old_val) { - mat[dirs.y][dirs.x] += new_val; + if(mat[dirs.y][dirs.x] <= old_val) { + mat[dirs.y][dirs.x] = new_val; x = dirs.x; y = dirs.y; @@ -147,20 +149,30 @@ namespace matrix { } } - 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}); - } + line::line(Point start, Point end) : + x(start.x), y(start.y), + x1(end.x), y1(end.y) + { + dx = std::abs(x1 - x); + sx = x < x1 ? 1 : -1; + dy = std::abs(y1 - y) * -1; + sy = y < y1 ? 1 : -1; + error = dx + dy; + } + + bool line::next() { + if(x != x1 || y != y1) { + int e2 = 2 * error; + + if(e2 >= dy) { + error = error + dy; + x = x + sx; } + if(e2 <= dx) { + error = error + dx; + y = y + sy; + } return true; } else { return false; @@ -186,5 +198,4 @@ namespace matrix { if(it.row) print("\n"); } } - } diff --git a/matrix.hpp b/matrix.hpp index 83f6607..acb475e 100644 --- a/matrix.hpp +++ b/matrix.hpp @@ -94,4 +94,18 @@ namespace matrix { bool next_working(); }; + struct line { + int x; + int y; + int x1; + int y1; + int sx; + int sy; + int dx; + int dy; + int error; + + line(Point start, Point end); + bool next(); + }; } diff --git a/tests/lighting.cpp b/tests/lighting.cpp index 40049c2..ae71cec 100644 --- a/tests/lighting.cpp +++ b/tests/lighting.cpp @@ -35,7 +35,10 @@ TEST_CASE("lighting a map works", "[lighting]") { lr.clear_light_target(light1); lr.clear_light_target(light2); - const auto &lighting = lr.lighting(); + Matrix &lighting = lr.lighting(); + + matrix::dump("WALLS=====", map.walls()); + matrix::dump("LIGHT PATHS======", lr.$paths.$paths); // confirm light is set at least at and around the two points REQUIRE(lighting[light1.y][light1.x] == lighting::LEVELS[source1.strength]); diff --git a/tests/matrix.cpp b/tests/matrix.cpp index 7115dd1..d708525 100644 --- a/tests/matrix.cpp +++ b/tests/matrix.cpp @@ -163,7 +163,7 @@ TEST_CASE("thrash compass iterators", "[matrix:compass]") { } TEST_CASE("prototype flood algorithm", "[matrix:flood]") { - for(int count = 0; count < 1; count++) { + for(int count = 0; count < 1000; count++) { size_t width = Random::uniform(10, 25); size_t height = Random::uniform(10, 33); @@ -171,32 +171,56 @@ TEST_CASE("prototype flood algorithm", "[matrix:flood]") { WorldBuilder builder(map); builder.generate(); - REQUIRE(map.room_count() > 0); + 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(); - // BUG: place_entity should not put things in walls - map.$walls[start.y][start.x] = 0; + // matrix::dump("WALLS BEFORE FLOOD", result, start.x, start.y); - 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{result, start, 3, 15}; it.next();) { + REQUIRE(matrix::inbounds(result, it.x, it.y)); + result[it.y][it.x] = 15; } - */ - 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", 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; } - matrix::dump("WALLS AFTER FLOOD", map.walls(), start.x, start.y); + result[start.y][start.x] = 15; + + // matrix::dump("RESULT AFTER LINE", result, end.x, end.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); + 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); } }