diff --git a/main.cpp b/main.cpp index 067e227..380f4ed 100644 --- a/main.cpp +++ b/main.cpp @@ -24,6 +24,9 @@ std::array tiles = { "##########", }; + + + int main() { using namespace ftxui; std::string reset_position; diff --git a/map.cpp b/map.cpp new file mode 100644 index 0000000..b89d6b5 --- /dev/null +++ b/map.cpp @@ -0,0 +1,84 @@ +#include "map.hpp" +#include +#include + +using std::vector, std::pair; +using namespace fmt; + +void dump_map(Matrix &map) { + println("-----------------"); + for(auto row : map) { + for(auto col : row) { + print("{} ", col); + } + print("\n"); + } +} + + +void add_neighbors(PairList &neighbors, Matrix &closed, size_t j, size_t i) { + size_t h = closed.size(); + size_t w = closed[0].size(); + vector rows{j - 1, j, j + 1}; + vector cols{i - 1, i, i + 1}; + + for(auto row : rows) { + for(auto col : cols) { + if((0 <= row && row < h) && + (0 <= col && col < w) && + closed[row][col] == 0) + { + closed[row][col] = 1; + neighbors.push_back({.j=row, .i=col}); + } + } + } +} + +Matrix dijkstra_map(Matrix &input_map, Matrix &walls_map, int limit) { + size_t h = input_map.size(); + size_t w = input_map[0].size(); + + // Initialize the new array with every pixel at limit distance + Matrix new_arr = Matrix(h, MatrixRow(w, 1)); + Matrix closed = walls_map; + PairList starting_pixels; + PairList open_pixels; + limit = limit == 0 ? h * w : limit; + + + // First pass: Add starting pixels and put them in closed + for(size_t counter = 0; counter < h * w; counter++) { + size_t i = counter % w; + size_t j = counter / w; + if(input_map[j][i] == 0) { + new_arr[j][i] = 0; + closed[j][i] = 1; + starting_pixels.push_back({.j=j,.i=i}); + } + } + + // Second pass: Add border to open + for(auto sp : starting_pixels) { + add_neighbors(open_pixels, closed, sp.j, sp.i); + } + + // Third pass: Iterate filling in the open list + int counter = 1; + while(counter < limit && !open_pixels.empty()) { + PairList next_open; + for(auto sp : open_pixels) { + new_arr[sp.j][sp.i] = counter; + add_neighbors(next_open, closed, sp.j, sp.i); + } + open_pixels = next_open; + ++counter; + } + + // Last pass: flood last pixels + for(auto sp : open_pixels) { + new_arr[sp.j][sp.i] = counter; + } + + return new_arr; +} diff --git a/map.hpp b/map.hpp new file mode 100644 index 0000000..cf0030c --- /dev/null +++ b/map.hpp @@ -0,0 +1,17 @@ +#pragma once +#include +#include + +struct Pair { + size_t j = 0; + size_t i = 0; +}; + +typedef std::vector PairList; +typedef std::vector MatrixRow; +typedef std::vector Matrix; + +void dump_map(Matrix &map); +void add_neighbors(Matrix &closed, size_t j, size_t i); + +Matrix dijkstra_map(Matrix &input_map, Matrix &walls_map, int limit=0); diff --git a/meson.build b/meson.build index 9c2f6a6..89deb62 100644 --- a/meson.build +++ b/meson.build @@ -14,14 +14,17 @@ dependencies = [catch2, fmt, runtests = executable('runtests', [ 'dbc.cpp', + 'map.cpp', 'tests/fsm.cpp', 'tests/dbc.cpp', + 'tests/map.cpp', ], dependencies: dependencies) roguish = executable('roguish', [ 'dbc.cpp', - 'main.cpp' + 'main.cpp', + 'map.cpp', ], dependencies: dependencies) diff --git a/tests/map.cpp b/tests/map.cpp new file mode 100644 index 0000000..1cafe62 --- /dev/null +++ b/tests/map.cpp @@ -0,0 +1,35 @@ +#include +#include "map.hpp" +#include + +using namespace fmt; + +TEST_CASE("dijkstra algo test", "[map]") { + Matrix in_map = { + {1, 1, 1, 0}, + {1, 0, 1, 1}, + {1, 0, 1, 1}, + {1, 1, 1, 1}, + }; + Matrix walls = { + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 1, 0}, + {0, 0, 1, 0}, + }; + Matrix expected = { + {1, 1, 1, 0}, + {1, 0, 1, 1}, + {1, 0, 0, 2}, + {1, 1, 0, 3}, + }; + + Matrix res = dijkstra_map(in_map, walls); + + println("--- EXPECTED:"); + dump_map(expected); + println("--- RESULT:"); + dump_map(res); + + REQUIRE(res == expected); +}