diff --git a/Makefile b/Makefile index 736e35d..adb9559 100644 --- a/Makefile +++ b/Makefile @@ -26,8 +26,11 @@ run: build test clean: meson compile --clean -C builddir -debug: - gdb --nx -x .gdbinit builddir/roguish.exe +debug_test: build + gdb --nx -x .gdbinit --ex run --args builddir/runtests.exe + +debug_run: build + gdb --nx -x .gdbinit --batch --ex run --ex bt --ex q --args builddir/roguish.exe cover: gcovr --html coverage/index.html --gcov-ignore-errors=no_working_dir_found --exclude "scratchpad.*" --exclude "subprojects.*" --html-nested coverage/ diff --git a/map.cpp b/map.cpp index 4357f09..2f941ea 100644 --- a/map.cpp +++ b/map.cpp @@ -64,26 +64,36 @@ Map::Map(Matrix input_map, Matrix walls_map, int limit) : { $width = $walls[0].size(); $height = $walls.size(); + $paths = Matrix($height, MatrixRow($width, 1)); + $lightmap = Matrix($height, MatrixRow($width, 0)); } -void Map::make_paths() { - size_t h = $input_map.size(); - size_t w = $input_map[0].size(); +inline void matrix_assign(Matrix &out, int new_value) { + for(auto &row : out) { + row.assign(row.size(), new_value); + } +} +/* + * Used https://github.com/HenrYxZ/dijkstra-map as a reference. + */ +void Map::make_paths() { + INVARIANT(); // Initialize the new array with every pixel at limit distance // NOTE: this is normally ones() * limit - int limit = $limit == 0 ? h * w : $limit; - Matrix new_arr = Matrix(h, MatrixRow(w, limit)); + int limit = $limit == 0 ? $height * $width : $limit; + matrix_assign($paths, limit); + Matrix closed = $walls; PointList starting_pixels; PointList open_pixels; // First pass: Add starting pixels and put them in closed - for(size_t counter = 0; counter < h * w; counter++) { - size_t x = counter % w; - size_t y = counter / w; + for(size_t counter = 0; counter < $height * $width; counter++) { + size_t x = counter % $width; // BUG: is this right? + size_t y = counter / $width; if($input_map[y][x] == 0) { - new_arr[y][x] = 0; + $paths[y][x] = 0; closed[y][x] = 1; starting_pixels.push_back({.x=x,.y=y}); } @@ -99,7 +109,7 @@ void Map::make_paths() { for(; counter < limit && !open_pixels.empty(); ++counter) { PointList next_open; for(auto sp : open_pixels) { - new_arr[sp.y][sp.x] = counter; + $paths[sp.y][sp.x] = counter; add_neighbors(next_open, closed, sp.y, sp.x); } open_pixels = next_open; @@ -107,22 +117,17 @@ void Map::make_paths() { // Last pass: flood last pixels for(auto sp : open_pixels) { - new_arr[sp.y][sp.x] = counter; + $paths[sp.y][sp.x] = counter; } - - $paths = new_arr; } void Map::make_room(size_t origin_x, size_t origin_y, size_t w, size_t h) { - dbc::pre("x out of bounds", origin_x < $width); - dbc::pre("y out of bounds", origin_y < $height); - dbc::pre("w out of bounds", w <= $width); - dbc::pre("h out of bounds", h <= $height); + INVARIANT(); + dbc::pre("y out of bounds", origin_y + h < $height); + dbc::pre("x out of bounds", origin_x + w < $width); for(size_t y = origin_y; y < origin_y + h; ++y) { - dbc::check(y < $walls.size(), "y is out of bounds"); for(size_t x = origin_x; x < origin_x + w; ++x) { - dbc::check(x < $walls[y].size(), "x is out of bounds"); $walls[y][x] = INV_SPACE; } } @@ -375,11 +380,7 @@ Point Map::center_camera(const Point &around, size_t view_x, size_t view_y) { } void Map::reset_light() { - for(auto &row : $lightmap) { - for(size_t i = 0; i < row.size(); i++) { - row[i] = lighting::MIN; - } - } + matrix_assign($lightmap, lighting::MIN); } void Map::clear_light_target(const Point &at) { @@ -390,7 +391,6 @@ void Map::set_light_target(const Point &at, int value) { set_target(at, value); } - void Map::path_light() { make_paths(); } @@ -417,10 +417,13 @@ void Map::render_light(LightSource source, Point at) { clear_light_target(at); vector has_light; - for(size_t x = min.x; x <= max.x; ++x) { - for(size_t y = min.y; y <= max.y; ++y) { - if($paths[y][x] != UNPATH) { - $lightmap[y][x] = light_level(source.strength, x, y); + for(size_t y = min.y; y <= max.y; ++y) { + auto &light_row = $lightmap[y]; + auto &path_row = $paths[y]; + + for(size_t x = min.x; x <= max.x; ++x) { + if(path_row[x] != UNPATH) { + light_row[x] = light_level(source.strength, x, y); has_light.push_back({x,y}); } } @@ -428,14 +431,30 @@ void Map::render_light(LightSource source, Point at) { const int wall_light = source.strength + WALL_LIGHT_LEVEL; for(auto point : has_light) { - for(int i = -1; i <= 1; i++) { - for(int j = -1; j <= 1; j++) { - if(!inmap(point.x+i, point.y+j)) continue; + for(int j = -1;point.y+j >= 0 && j <= 1 && point.y+j < $height; j++) { + auto &path_row = $paths[point.y+j]; + auto &light_row = $lightmap[point.y+j]; - if($paths[point.y+j][point.x+i] == UNPATH) { - $lightmap[point.y+j][point.x+i] = light_level(wall_light, point.x, point.y); + for(int i = -1; point.x+i >= 0 && i <= 1 && point.x+i < $width; i++) { + if(path_row[point.x+i] == UNPATH) { + light_row[point.x+i] = light_level(wall_light, point.x, point.y); } } } } } + +bool Map::INVARIANT() { + using dbc::check; + + check($paths.size() == height(), "paths wrong height"); + check($paths[0].size() == width(), "paths wrong width"); + check($input_map.size() == height(), "input_map wrong height"); + check($input_map[0].size() == width(), "input_map wrong width"); + check($walls.size() == height(), "walls wrong height"); + check($walls[0].size() == width(), "walls wrong width"); + check($lightmap.size() == height(), "lightmap wrong height"); + check($lightmap[0].size() == width(), "lightmap wrong width"); + + return true; +} diff --git a/map.hpp b/map.hpp index 378efb9..f3d4085 100644 --- a/map.hpp +++ b/map.hpp @@ -92,4 +92,5 @@ public: void render_light(LightSource source, Point at); void dump(); + bool INVARIANT(); }; diff --git a/meson.build b/meson.build index 0b52c9b..a08d553 100644 --- a/meson.build +++ b/meson.build @@ -35,13 +35,13 @@ runtests = executable('runtests', [ 'tests/map.cpp', 'tests/collider.cpp', 'tests/components.cpp', - 'tests/sound.cpp', 'tests/dinkyecs.cpp', 'tests/ansi_parser.cpp', 'tests/config.cpp', 'tests/save.cpp', 'tests/render.cpp', 'tests/panel.cpp', + 'tests/sound.cpp', ], dependencies: dependencies) diff --git a/tests/map.cpp b/tests/map.cpp index 35327f9..c17b209 100644 --- a/tests/map.cpp +++ b/tests/map.cpp @@ -22,6 +22,8 @@ TEST_CASE("dijkstra algo test", "[map]") { test["walls"], test["limit"]); + REQUIRE(map.INVARIANT()); + map.make_paths(); Matrix &paths = map.paths(); @@ -31,6 +33,7 @@ TEST_CASE("dijkstra algo test", "[map]") { dump_map("RESULT", paths); } + REQUIRE(map.INVARIANT()); REQUIRE(paths == expected); } }