Skip to content

Commit 4394ca1

Browse files
Cleaned BFS
1 parent beb0427 commit 4394ca1

6 files changed

Lines changed: 90 additions & 54 deletions

File tree

LocalDataStructures/Queue.ixx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ namespace LocalDataStructures {
110110
*
111111
* @return Maximum number of elements supported by this queue
112112
*/
113-
inline static Length_T maxLength() requires (staticSize > 0) { return staticSize; }
113+
static constexpr Length_T maxLength() requires (staticSize > 0) { return staticSize; }
114114

115115
/**
116116
*

LocalDataStructures/Stack.ixx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ namespace LocalDataStructures {
6161
*/
6262
void clear() { stackPointer = 0; }
6363

64-
[[nodiscard]] static inline Length_T maxLength() requires (staticSize > 0) {return staticSize; }
64+
[[nodiscard]] static constexpr Length_T maxLength() requires (staticSize > 0) {return staticSize; }
6565
[[nodiscard]] inline const Length_T& length() const {return stackPointer; };
6666
};
6767
}

Pathfind/AStar.ixx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import :HashMapBucketQueue;
2020
import :HashMapBinaryHeap;
2121
import :STDPriorityQueue;
2222

23+
//TODO keep track of best heuristic tile, and path to that it we don't get the endPoint jishin
24+
2325
//TODO make it default to heap when non-integer Grid_t::T
2426
namespace SG_Pathfind::AStar {
2527
template<bool useSTD, bool useHeap, bool tryFifo, bool useHashset, bool queensCase, bool Flowfield, typename WorkingArenaType, typename Grid_t>
@@ -103,10 +105,10 @@ export namespace SG_Pathfind::AStar {
103105
auto& directions = Utils::AvailableMoves<queensCase>();
104106
typedef std::conditional_t<useSTD, HashMap::STDHashMap<OutputArenaType,SG_Grid::u_coordinate_t>, HashMap::GridRangeHashMap<OutputArenaType,SG_Grid::u_coordinate_t>> visited_t;
105107
typedef std::conditional_t<useSTD, HashMap::STDHashMap<WorkingArenaType,SG_Grid::Point>, HashMap::GridRangeHashMap<WorkingArenaType,SG_Grid::Point, true>> flow_t;
106-
auto& flow(*outArena.template allocConstruct<flow_t>(outArena, OnGrid, startPoint, searchDistance)); //Should map a Point to a Point (x/y direction) -> Flowfield
108+
auto& flow(*outArena.template allocConstruct<flow_t>(outArena, OnGrid, startPoint, searchDistance));
107109

108110
arena.sublifetime_open();
109-
visited_t visited(arena, OnGrid, startPoint, searchDistance); //Should map a Point to a direction -> Flowfield
111+
visited_t visited(arena, OnGrid, startPoint, searchDistance);
110112
SG_PATHFIND_AStar(true)(arena, OnGrid, startPoint, searchDistance, visited, flow, directions);
111113
arena.sublifetime_rollback();
112114
return flow;
@@ -118,10 +120,10 @@ export namespace SG_Pathfind::AStar {
118120
auto& directions = Utils::AvailableMoves<queensCase>();
119121
typedef std::conditional_t<useSTD, HashMap::STDHashMap<OutputArenaType,SG_Grid::u_coordinate_t>, HashMap::GridRangeHashMap<OutputArenaType,SG_Grid::u_coordinate_t>> visited_t;
120122
typedef std::conditional_t<useSTD, HashMap::STDHashMap<WorkingArenaType,SG_Grid::Point>, HashMap::GridRangeHashMap<WorkingArenaType,SG_Grid::Point, false>> flow_t;
121-
auto& visited(*outArena.template allocConstruct<visited_t>(outArena, OnGrid, startPoint, searchDistance)); //Should map a Point to a distance -> Distance Matrix
123+
auto& visited(*outArena.template allocConstruct<visited_t>(outArena, OnGrid, startPoint, searchDistance));
122124

123125
arena.sublifetime_open();
124-
flow_t flow(arena, OnGrid, startPoint, searchDistance); //Should map a Point to a direction -> Flowfield
126+
flow_t flow(arena, OnGrid, startPoint, searchDistance);
125127
SG_PATHFIND_AStar(true)(arena, OnGrid, startPoint, searchDistance, visited, flow, directions);
126128
arena.sublifetime_rollback();
127129
return visited;

Pathfind/BFS.ixx

Lines changed: 64 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@
44
module;
55
#include <type_traits>
66
#include <algorithm>
7+
#include <cstdint>
78
#include "Logger.h"
89

9-
#include <iostream>
10-
1110
export module SG_Pathfind:BFS;
1211
import LocalDataStructures;
1312
import Logger;
@@ -20,9 +19,14 @@ import :NoPriorityQueue;
2019
import :STDNoPriorityQueue;
2120

2221

22+
//TODO keep track of best heuristic tile, and path to that it we don't get the endPoint jishin
23+
24+
25+
#define SG_PATHFIND_BFS(Flowfield, Distances) BFS_Base<useSTD, queensCase, Flowfield, Distances, WorkingArenaType, Grid_t>
26+
2327
namespace SG_Pathfind::BFS {
2428
template<bool useSTD, bool queensCase, bool Flowfield, bool Distances, typename WorkingArenaType, typename Grid_t>
25-
SG_Grid::Point BFS_Base(WorkingArenaType& arena, const Grid_t& OnGrid, const SG_Grid::Point& startPoint, const SG_Grid::u_coordinate_t& searchDistance, auto& visited, auto& directions, const SG_Grid::Point& endPoint_ = {0,0}){
29+
inline SG_Grid::Point BFS_Base(WorkingArenaType& arena, const Grid_t& OnGrid, const SG_Grid::Point& startPoint, const SG_Grid::u_coordinate_t& searchDistance, auto& visited, auto& directions, const SG_Grid::Point& endPoint_ = {0,0}){
2630
typedef std::conditional_t<useSTD, PriorityQueue::STDNoPriorityQueue<WorkingArenaType, Grid_t, queensCase, !Distances, false, false>, PriorityQueue::NoPriorityQueue<WorkingArenaType, Grid_t, queensCase, !Distances, false, false>> queue_t; \
2731
queue_t frontier(arena, OnGrid, startPoint, searchDistance);
2832
frontier.insert(startPoint,0,true);
@@ -52,57 +56,76 @@ namespace SG_Pathfind::BFS {
5256
found: /* The last remaining use for goto :) */
5357
return examine;
5458
}
55-
}
56-
57-
#define SG_PATHFIND_BFS(Flowfield, Distances) BFS_Base<useSTD, queensCase, Flowfield, Distances, WorkingArenaType, Grid_t>
58-
59-
60-
export namespace SG_Pathfind::BFS {
61-
template<typename WorkingArenaType, typename OutputArenaType, typename Grid_t, bool queensCase = true, const SG_Grid::u_coordinate_t maxOutputNodes = 256, bool useSTD = false> //TODO make a default number for maxOutputNodes in a config file
62-
LocalDataStructures::Stack<SG_Grid::Point, maxOutputNodes>& BFS_Point(const Grid_t& OnGrid, WorkingArenaType& arena, OutputArenaType& outArena, const SG_Grid::Point& startPoint, const SG_Grid::Point& endPoint, const SG_Grid::u_coordinate_t& searchDistance) {
59+
60+
template<std::uint8_t type, typename WorkingArenaType, typename Grid_t, bool queensCase = true, bool useSTD = false> //TODO make a default number for maxOutputNodes in a config file
61+
inline auto& BFS_Pathfind(auto& out, WorkingArenaType& arena, const Grid_t& OnGrid, const SG_Grid::Point& startPoint, const SG_Grid::u_coordinate_t& searchDistance, const SG_Grid::Point& endPoint = {0,0}) {
6362
LOGGER_ASSERT_EXCEPT(startPoint.on(OnGrid));
64-
LOGGER_ASSERT_EXCEPT(endPoint.on(OnGrid));
63+
if constexpr (type == 0) {LOGGER_ASSERT_EXCEPT(endPoint.on(OnGrid));}
6564
auto& directions = Utils::AvailableMoves<queensCase>();
66-
typedef std::conditional_t<useSTD, HashMap::STDHashMap<WorkingArenaType,SG_Grid::Point>, HashMap::GridRangeHashMap<WorkingArenaType,SG_Grid::Point>> visited_t;
67-
auto& out(*(outArena.template allocConstruct<LocalDataStructures::Stack<SG_Grid::Point, maxOutputNodes>>()));
6865

6966
arena.sublifetime_open();
70-
visited_t visited(arena, OnGrid, startPoint, searchDistance); //Should map a Point to a direction -> Flowfield
71-
auto examine = SG_PATHFIND_BFS(false, false)(arena, OnGrid, startPoint, searchDistance, visited, directions, endPoint);
72-
Utils::FlowfieldToPath(out, examine, startPoint, endPoint, visited);
67+
if constexpr (type == 0) { // 0 = P2P
68+
Utils::Flowfield_t<WorkingArenaType, useSTD> visited(arena, OnGrid, startPoint, searchDistance);
69+
auto examine = SG_PATHFIND_BFS(false, false)(arena, OnGrid, startPoint, searchDistance, visited, directions, endPoint);
70+
Utils::FlowfieldToPath(out, examine, startPoint, endPoint, visited);
71+
}
72+
if constexpr (type == 1) // 1 = Flowfield
73+
SG_PATHFIND_BFS(true, false)(arena, OnGrid, startPoint, searchDistance, out, directions);
74+
if constexpr (type == 2) // 2 = Distance Matrix
75+
SG_PATHFIND_BFS(true, true)(arena, OnGrid, startPoint, searchDistance, out, directions);
76+
if constexpr (type == 4) { // 4 = Flowfield + Distance
77+
// (TODO!!!!)
78+
}
7379
arena.sublifetime_rollback();
7480
return out;
7581
}
76-
77-
template<typename WorkingArenaType, typename OutputArenaType, typename Grid_t, bool queensCase = true, bool useSTD = false>
78-
auto& BFS_Flowfield(Grid_t& OnGrid, WorkingArenaType& arena, OutputArenaType& outArena, const SG_Grid::Point& startPoint, const SG_Grid::u_coordinate_t& searchDistance) {
79-
LOGGER_ASSERT_EXCEPT(startPoint.on(OnGrid));
80-
auto& directions = Utils::AvailableMoves<queensCase>();
81-
typedef std::conditional_t<useSTD, HashMap::STDHashMap<OutputArenaType,SG_Grid::Point>, HashMap::GridRangeHashMap<OutputArenaType,SG_Grid::Point>> visited_t;
82-
auto& visited(*outArena.template allocConstruct<visited_t>(outArena, OnGrid, startPoint, searchDistance)); //Should map a Point to a Point (x/y direction) -> Flowfield
82+
}
8383

84-
arena.sublifetime_open();
85-
SG_PATHFIND_BFS(true, false)(arena, OnGrid, startPoint, searchDistance, visited, directions);
86-
arena.sublifetime_rollback();
87-
return visited;
84+
85+
export namespace SG_Pathfind::BFS {
86+
template<typename WorkingArenaType, typename Grid_t, bool queensCase = true, const SG_Grid::u_coordinate_t maxOutputNodes = 256, bool useSTD = false> //TODO make a default number for maxOutputNodes in a config file
87+
auto& BFS_Point(Utils::Path_t<maxOutputNodes>& out, WorkingArenaType& arena, const Grid_t& OnGrid, const SG_Grid::Point& startPoint, const SG_Grid::Point& endPoint, const SG_Grid::u_coordinate_t& searchDistance) {
88+
return BFS_Pathfind<0, WorkingArenaType, Grid_t, queensCase, useSTD>(out, arena, OnGrid, startPoint, searchDistance, endPoint);
8889
}
8990

90-
template<typename WorkingArenaType, typename OutputArenaType, typename Grid_t, bool queensCase = true, bool useSTD = false>
91-
auto& BFS_Dmatrix(Grid_t& OnGrid, WorkingArenaType& arena, OutputArenaType& outArena, const SG_Grid::Point& startPoint, const SG_Grid::u_coordinate_t& searchDistance) {
92-
LOGGER_ASSERT_EXCEPT(startPoint.on(OnGrid));
93-
auto& directions = Utils::AvailableMoves<queensCase>();
94-
typedef std::conditional_t<useSTD, HashMap::STDHashMap<OutputArenaType,SG_Grid::u_coordinate_t>, HashMap::GridRangeHashMap<OutputArenaType,SG_Grid::u_coordinate_t>> visited_t;
95-
auto& visited(*outArena.template allocConstruct<visited_t>(outArena, OnGrid, startPoint, searchDistance)); //Should map a Point to a distance -> Distance Matrix
96-
97-
arena.sublifetime_open();
98-
SG_PATHFIND_BFS(true, true)(arena, OnGrid, startPoint, searchDistance, visited, directions);
99-
arena.sublifetime_rollback();
100-
return visited;
91+
template<typename OutputArenaType, typename WorkingArenaType, typename Grid_t, bool queensCase = true, bool useSTD = false>
92+
auto& BFS_Flowfield(Utils::Flowfield_t<OutputArenaType, useSTD>& out, WorkingArenaType& arena, const Grid_t& OnGrid, const SG_Grid::Point& startPoint, const SG_Grid::u_coordinate_t& searchDistance) {
93+
return BFS_Pathfind<1, WorkingArenaType, Grid_t, queensCase, useSTD>(out, arena, OnGrid, startPoint, searchDistance);
94+
}
95+
96+
template<typename OutputArenaType, typename WorkingArenaType, typename Grid_t, bool queensCase = true, bool useSTD = false>
97+
auto& BFS_Dmatrix(Utils::Dmat_t<OutputArenaType, useSTD>& out, WorkingArenaType& arena, const Grid_t& OnGrid, const SG_Grid::Point& startPoint, const SG_Grid::u_coordinate_t& searchDistance) {
98+
return BFS_Pathfind<2, WorkingArenaType, Grid_t, queensCase, useSTD>(out, arena, OnGrid, startPoint, searchDistance);
99+
}
100+
101+
102+
103+
namespace Bench{
104+
template<typename WorkingArenaType, typename OutputArenaType, typename Grid_t, bool queensCase = true, const SG_Grid::u_coordinate_t maxOutputNodes = 256, bool useSTD = false> //TODO make a default number for maxOutputNodes in a config file
105+
auto& BFS_Point_(const Grid_t& OnGrid, WorkingArenaType& arena, OutputArenaType& outArena, const SG_Grid::Point& startPoint, const SG_Grid::Point& endPoint, const SG_Grid::u_coordinate_t& searchDistance) {
106+
auto& out(*(outArena.template allocConstruct<Utils::Path_t<maxOutputNodes>>()));
107+
return BFS_Point<WorkingArenaType, Grid_t, queensCase, maxOutputNodes, useSTD>(out, arena, OnGrid, startPoint, endPoint, searchDistance);
108+
}
109+
110+
template<typename WorkingArenaType, typename OutputArenaType, typename Grid_t, bool queensCase = true, bool useSTD = false>
111+
auto& BFS_Flowfield_(Grid_t& OnGrid, WorkingArenaType& arena, OutputArenaType& outArena, const SG_Grid::Point& startPoint, const SG_Grid::u_coordinate_t& searchDistance) {
112+
auto& out(*outArena.template allocConstruct<Utils::Flowfield_t<OutputArenaType, useSTD>>(outArena, OnGrid, startPoint, searchDistance));
113+
return BFS_Flowfield<OutputArenaType, WorkingArenaType, Grid_t, queensCase, useSTD>(out, arena, OnGrid, startPoint, searchDistance);
114+
}
115+
116+
template<typename WorkingArenaType, typename OutputArenaType, typename Grid_t, bool queensCase = true, bool useSTD = false>
117+
auto& BFS_Dmatrix_(Grid_t& OnGrid, WorkingArenaType& arena, OutputArenaType& outArena, const SG_Grid::Point& startPoint, const SG_Grid::u_coordinate_t& searchDistance) {
118+
auto& out(*outArena.template allocConstruct<Utils::Dmat_t<OutputArenaType, useSTD>>(outArena, OnGrid, startPoint, searchDistance)); //Should map a Point to a distance -> Distance Matrix
119+
return BFS_Dmatrix<OutputArenaType, WorkingArenaType, Grid_t, queensCase, useSTD>(out, arena, OnGrid, startPoint, searchDistance);
120+
}
101121
}
102122

103123
//TODO make new function that uses an std::pair of u_coordinate_t (distance) AND Point (flow) -> make it so you only need one call instead of 2
104-
105124
//TODO add 'inRange' variants -> Takes additional grid specifying 'ignorable' tiles for the 'withinRange' check (e.g. walls block shots, but rivers don't) -> Add options for 'ignoreAll', and make default just use all walls of the base map
106-
107125
//TODO add variants that somehow work the same but use a pre-allocated output matrix/stack -> reduce need to copy and also reduce chance of OutputArena fragmentation
126+
127+
128+
//TODO templates are getting too much!!!
129+
//TODO 'almost always use auto!'
130+
// Use 'auto' with 'concepts' and clean up all the templates in this project!!
108131
}

Pathfind/Utils.ixx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,21 @@
33
//
44
module;
55
#include "Logger.h"
6+
#include <algorithm>
7+
#include <type_traits>
68

79
export module SG_Pathfind:Utils;
810
import LocalDataStructures;
911
import SG_Grid;
12+
import :GridRangeHashMap;
13+
import :STDHashMap;
1014

1115
export namespace SG_Pathfind::Utils {
16+
template <const SG_Grid::u_coordinate_t maxOutputNodes = 256> using Path_t = LocalDataStructures::Stack<SG_Grid::Point, maxOutputNodes>;
17+
template <typename ArenaType, bool useSTD = false> using Flowfield_t = std::conditional_t<useSTD, HashMap::STDHashMap<ArenaType,SG_Grid::Point>, HashMap::GridRangeHashMap<ArenaType,SG_Grid::Point>>;
18+
template <typename ArenaType, bool useSTD = false> using Dmat_t = std::conditional_t<useSTD, HashMap::STDHashMap<ArenaType,SG_Grid::u_coordinate_t>, HashMap::GridRangeHashMap<ArenaType,SG_Grid::u_coordinate_t>>;
19+
20+
1221
//TODO probably prioritise horizontal movement first (reduces weird movement for queen's case) -> might need to update unit tests to account
1322
LocalDataStructures::Stack<SG_Grid::Point,8> QueenMoves({
1423
{ 0,-1},
@@ -29,6 +38,8 @@ export namespace SG_Pathfind::Utils {
2938
template <bool QueensCase> const auto& AvailableMoves(){ if constexpr (QueensCase) return QueenMoves; else return RookMoves; }
3039

3140
//TODO add some string-pulling logic, so we can get nicer paths esp in QueensCase
41+
// Add a grid-bound string pull function
42+
// Add an any-direction string pull function
3243
template <typename HashMap_t, typename Out_t, const SG_Grid::u_coordinate_t maxOutputNodes = 256>
3344
auto FlowfieldToPath(Out_t& out, const SG_Grid::Point& examine, const SG_Grid::Point& startPoint, const SG_Grid::Point& endPoint, const HashMap_t& visited){
3445
if (examine == endPoint){ // Only return a path if we found one
@@ -43,5 +54,5 @@ export namespace SG_Pathfind::Utils {
4354
}
4455
}
4556

46-
//TODO add a 'threatMatrix' function based on a min/max distance matrix and a 'blocker' matrix -> return a new grid showing distance to put tiles within that range without hitting a 'blocker' -> e.g. calculating Fire Emblem archer movement
57+
//TODO add a 'threatMatrix' function based on a min/max distance, a distance matrix and a 'blocker' matrix -> return a new grid showing distance to put tiles within that range without hitting a 'blocker' -> e.g. showing Fire Emblem archer attackable squares
4758
}

tests/test_BFS.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ import SG_Allocator;
1111
import SG_Grid;
1212
import SG_Pathfind;
1313

14-
#define BFS1_1(STD) SG_Pathfind::BFS::BFS_Point<decltype(arena),decltype(arena), decltype(grid), true, 256, STD>
15-
#define BFS2_1(STD) SG_Pathfind::BFS::BFS_Flowfield<decltype(arena),decltype(arena), decltype(grid), true, STD>
16-
#define BFS3_1(STD) SG_Pathfind::BFS::BFS_Dmatrix<decltype(arena),decltype(arena), decltype(grid), true, STD>
14+
#define BFS1_1(STD) SG_Pathfind::BFS::Bench::BFS_Point_<decltype(arena),decltype(arena), decltype(grid), true, 256, STD>
15+
#define BFS2_1(STD) SG_Pathfind::BFS::Bench::BFS_Flowfield_<decltype(arena),decltype(arena), decltype(grid), true, STD>
16+
#define BFS3_1(STD) SG_Pathfind::BFS::Bench::BFS_Dmatrix_<decltype(arena),decltype(arena), decltype(grid), true, STD>
1717

18-
#define BFS1_2(STD) SG_Pathfind::BFS::BFS_Point<decltype(arena),decltype(arena), decltype(grid), false, 256, STD>
19-
#define BFS2_2(STD) SG_Pathfind::BFS::BFS_Flowfield<decltype(arena),decltype(arena), decltype(grid), false, STD>
20-
#define BFS3_2(STD) SG_Pathfind::BFS::BFS_Dmatrix<decltype(arena),decltype(arena), decltype(grid), false, STD>
18+
#define BFS1_2(STD) SG_Pathfind::BFS::Bench::BFS_Point_<decltype(arena),decltype(arena), decltype(grid), false, 256, STD>
19+
#define BFS2_2(STD) SG_Pathfind::BFS::Bench::BFS_Flowfield_<decltype(arena),decltype(arena), decltype(grid), false, STD>
20+
#define BFS3_2(STD) SG_Pathfind::BFS::Bench::BFS_Dmatrix_<decltype(arena),decltype(arena), decltype(grid), false, STD>
2121

2222

2323
template <typename T, bool useSTD>

0 commit comments

Comments
 (0)