Re-formatted files

This commit is contained in:
Jan Mrna
2025-10-30 15:10:00 +01:00
parent 193310f704
commit 9c1ec01ce0
28 changed files with 523 additions and 636 deletions

View File

@@ -1,5 +1,5 @@
#include <memory>
#include <cassert>
#include <memory>
#include <queue>
#include "pathfinder/base.hpp"
@@ -9,14 +9,15 @@
namespace pathfinder {
PathFinderBase::PathFinderBase(const Map* map) : m_Map(map) {}
PathFinderBase::PathFinderBase(const Map *map) : m_Map(map) {}
// LinearPathFinder also lives here, since it is too small to get it's
// own implementation file
Path LinearPathFinder::CalculatePath(WorldPos, WorldPos end) // first argument (start pos) not used
Path LinearPathFinder::CalculatePath(
WorldPos, WorldPos end) // first argument (start pos) not used
{
auto path = Path{end};
return path;
}
} // pathfinder namespace
} // namespace pathfinder

View File

@@ -1,11 +1,11 @@
#pragma once
#include <vector>
#include <memory>
#include <unordered_map>
#include <vector>
#include "math.hpp"
#include "map.hpp"
#include "math.hpp"
namespace pathfinder {
@@ -21,32 +21,30 @@ enum class PathFinderType {
class PathFinderBase {
public:
PathFinderBase(const Map* m);
PathFinderBase(const Map *m);
~PathFinderBase() = default;
PathFinderBase(const PathFinderBase&) = delete;
PathFinderBase(PathFinderBase&&) = delete;
PathFinderBase& operator=(const PathFinderBase&) = delete;
PathFinderBase& operator=(PathFinderBase&&) = delete;
PathFinderBase(const PathFinderBase &) = delete;
PathFinderBase(PathFinderBase &&) = delete;
PathFinderBase &operator=(const PathFinderBase &) = delete;
PathFinderBase &operator=(PathFinderBase &&) = delete;
virtual const std::string_view& GetName() const = 0;
virtual const std::string_view &GetName() const = 0;
virtual Path CalculatePath(WorldPos start, WorldPos end) = 0;
protected:
const Map* m_Map;
const Map *m_Map;
};
class LinearPathFinder : public PathFinderBase {
public:
LinearPathFinder(const Map* m): PathFinderBase(m) {}
LinearPathFinder(const Map *m) : PathFinderBase(m) {}
Path CalculatePath(WorldPos start, WorldPos end) override;
const std::string_view& GetName() const override { return m_Name; }
const std::string_view &GetName() const override { return m_Name; }
private:
const std::string_view m_Name = "Linear Path";
};
} // pathfinder namespace
} // namespace pathfinder

View File

@@ -7,60 +7,61 @@
#include "math.hpp"
namespace pathfinder {
Path BFS::CalculatePath(WorldPos start_world, WorldPos end_world) {
if (m_Map == nullptr) return {};
if (m_Map == nullptr)
return {};
const TilePos start = m_Map->WorldToTile(start_world);
const TilePos end = m_Map->WorldToTile(end_world);
const TilePos start = m_Map->WorldToTile(start_world);
const TilePos end = m_Map->WorldToTile(end_world);
if (!m_Map->IsTilePosValid(start) || !m_Map->IsTilePosValid(end))
return {};
if (start == end) {
return {};
}
// clear previous run
m_CameFrom.clear();
m_Distance.clear();
if (!m_Map->IsTilePosValid(start) || !m_Map->IsTilePosValid(end))
return {};
if (start == end) {
return {};
}
// clear previous run
m_CameFrom.clear();
m_Distance.clear();
std::queue<TilePos> frontier;
frontier.push(start);
m_CameFrom[start] = start;
m_Distance[start] = 0.0f;
std::queue<TilePos> frontier;
frontier.push(start);
m_CameFrom[start] = start;
m_Distance[start] = 0.0f;
// ---------------- build flow-field ----------------
bool early_exit = false;
while (!frontier.empty() && !early_exit) {
TilePos current = frontier.front();
frontier.pop();
// ---------------- build flow-field ----------------
bool early_exit = false;
while (!frontier.empty() && !early_exit) {
TilePos current = frontier.front();
frontier.pop();
for (TilePos next : m_Map->GetNeighbors(current)) {
if (m_CameFrom.find(next) == m_CameFrom.end()) { // not visited
frontier.push(next);
m_Distance[next] = m_Distance[current] + 1.0f;
m_CameFrom[next] = current;
for (TilePos next : m_Map->GetNeighbors(current)) {
if (m_CameFrom.find(next) == m_CameFrom.end()) { // not visited
frontier.push(next);
m_Distance[next] = m_Distance[current] + 1.0f;
m_CameFrom[next] = current;
if (next == end) { // early exit
early_exit = true;
break;
}
}
if (next == end) { // early exit
early_exit = true;
break;
}
}
}
}
// --------------- reconstruct path -----------------
if (m_CameFrom.find(end) == m_CameFrom.end())
return {}; // end not reached
// --------------- reconstruct path -----------------
if (m_CameFrom.find(end) == m_CameFrom.end())
return {}; // end not reached
Path path;
TilePos cur = end;
Path path;
TilePos cur = end;
path.push_back(m_Map->TileToWorld(cur));
while (cur != start) {
cur = m_CameFrom[cur];
path.push_back(m_Map->TileToWorld(cur));
while (cur != start) {
cur = m_CameFrom[cur];
path.push_back(m_Map->TileToWorld(cur));
}
std::reverse(path.begin(), path.end());
return path;
}
std::reverse(path.begin(), path.end());
return path;
}
} // pathfinder namespace
} // namespace pathfinder

View File

@@ -8,13 +8,13 @@
#include "math.hpp"
namespace pathfinder {
class BFS: public PathFinderBase {
class BFS : public PathFinderBase {
public:
BFS(const Map* m): PathFinderBase(m) {}
BFS(const Map *m) : PathFinderBase(m) {}
Path CalculatePath(WorldPos start, WorldPos end) override;
const std::string_view& GetName() const override { return m_Name; }
const std::string_view &GetName() const override { return m_Name; }
private:
const std::string_view m_Name = "Breadth First Search";
@@ -22,4 +22,4 @@ private:
std::unordered_map<TilePos, TilePos, TilePosHash> m_CameFrom;
};
}
} // namespace pathfinder

View File

@@ -3,71 +3,69 @@
#include "dijkstra.hpp"
#include "base.hpp"
#include "utils.hpp"
#include "math.hpp"
#include "map.hpp"
#include "math.hpp"
#include "utils.hpp"
namespace pathfinder {
Path Dijkstra::CalculatePath(WorldPos start_world, WorldPos end_world)
{
Path Dijkstra::CalculatePath(WorldPos start_world, WorldPos end_world) {
using QueueEntry = utils::QueueEntry;
if (!m_Map) return {};
if (!m_Map)
return {};
const TilePos start = m_Map->WorldToTile(start_world);
const TilePos end = m_Map->WorldToTile(end_world);
const TilePos end = m_Map->WorldToTile(end_world);
if (!m_Map->IsTilePosValid(start) || !m_Map->IsTilePosValid(end))
return {};
if (start == end) return {};
return {};
if (start == end)
return {};
// clear previous run
m_CameFrom.clear();
m_Cost.clear();
std::priority_queue<QueueEntry, std::vector<QueueEntry>, std::greater<>> frontier;
std::priority_queue<QueueEntry, std::vector<QueueEntry>, std::greater<>>
frontier;
frontier.push({0.0f, start});
m_CameFrom[start] = start; // sentinel
m_Cost[start] = 0.0f;
m_CameFrom[start] = start; // sentinel
m_Cost[start] = 0.0f;
while (!frontier.empty())
{
const QueueEntry current = frontier.top();
frontier.pop();
while (!frontier.empty()) {
const QueueEntry current = frontier.top();
frontier.pop();
if (current.tile == end) // early exit
break;
if (current.tile == end) // early exit
break;
for (TilePos next : m_Map->GetNeighbors(current.tile))
{
// cost of moving to neighbour (uniform 1.0 matches original BFS)
const float newCost = m_Cost[current.tile] + m_Map->GetCost(next);
for (TilePos next : m_Map->GetNeighbors(current.tile)) {
// cost of moving to neighbour (uniform 1.0 matches original BFS)
const float newCost = m_Cost[current.tile] + m_Map->GetCost(next);
if (!m_Cost.count(next) || newCost < m_Cost[next])
{
m_Cost[next] = newCost;
m_CameFrom[next] = current.tile;
frontier.push({newCost, next});
}
if (!m_Cost.count(next) || newCost < m_Cost[next]) {
m_Cost[next] = newCost;
m_CameFrom[next] = current.tile;
frontier.push({newCost, next});
}
}
}
// reconstruct path
if (!m_CameFrom.count(end))
return {}; // goal never reached
return {}; // goal never reached
Path path;
TilePos cur = end;
path.push_back(m_Map->TileToWorld(cur));
while (cur != start)
{
cur = m_CameFrom[cur];
path.push_back(m_Map->TileToWorld(cur));
while (cur != start) {
cur = m_CameFrom[cur];
path.push_back(m_Map->TileToWorld(cur));
}
std::reverse(path.begin(), path.end());
return path;
}
} // pathfinder namespace
} // namespace pathfinder

View File

@@ -10,12 +10,12 @@
namespace pathfinder {
class Dijkstra: public PathFinderBase {
class Dijkstra : public PathFinderBase {
public:
Dijkstra(const Map* m): PathFinderBase(m) {}
Dijkstra(const Map *m) : PathFinderBase(m) {}
Path CalculatePath(WorldPos start, WorldPos end) override;
const std::string_view& GetName() const override { return m_Name; }
const std::string_view &GetName() const override { return m_Name; }
private:
const std::string_view m_Name = "Dijkstra's Algorithm";
@@ -23,4 +23,4 @@ private:
std::unordered_map<TilePos, TilePos, TilePosHash> m_CameFrom;
};
} // pathfinder namespace
} // namespace pathfinder

View File

@@ -3,69 +3,67 @@
#include "gbfs.hpp"
#include "base.hpp"
#include "math.hpp"
#include "map.hpp"
#include "math.hpp"
#include "pathfinder/utils.hpp"
namespace pathfinder {
float GBFS::Heuristic(const TilePos& a, const TilePos& b)
{
return static_cast<float>(std::abs(a.x() - b.x()) + std::abs(a.y() - b.y()));
float GBFS::Heuristic(const TilePos &a, const TilePos &b) {
return static_cast<float>(std::abs(a.x() - b.x()) + std::abs(a.y() - b.y()));
}
Path GBFS::CalculatePath(WorldPos start_world, WorldPos end_world)
{
Path GBFS::CalculatePath(WorldPos start_world, WorldPos end_world) {
using QueueEntry = pathfinder::utils::QueueEntry;
if (!m_Map) return {};
if (!m_Map)
return {};
const TilePos start = m_Map->WorldToTile(start_world);
const TilePos end = m_Map->WorldToTile(end_world);
const TilePos end = m_Map->WorldToTile(end_world);
if (!m_Map->IsTilePosValid(start) || !m_Map->IsTilePosValid(end))
return {};
if (start == end) return {};
return {};
if (start == end)
return {};
m_CameFrom.clear();
std::priority_queue<QueueEntry, std::vector<QueueEntry>, std::greater<>> frontier;
std::priority_queue<QueueEntry, std::vector<QueueEntry>, std::greater<>>
frontier;
frontier.push({Heuristic(start, end), start});
m_CameFrom[start] = start; // sentinel
m_CameFrom[start] = start; // sentinel
while (!frontier.empty())
{
const QueueEntry current = frontier.top();
frontier.pop();
while (!frontier.empty()) {
const QueueEntry current = frontier.top();
frontier.pop();
if (current.tile == end) // early exit
break;
if (current.tile == end) // early exit
break;
for (TilePos next : m_Map->GetNeighbors(current.tile))
for (TilePos next : m_Map->GetNeighbors(current.tile)) {
if (!m_CameFrom.count(next)) // not visited
{
if (!m_CameFrom.count(next)) // not visited
{
m_CameFrom[next] = current.tile;
frontier.push({Heuristic(end, next), next});
}
m_CameFrom[next] = current.tile;
frontier.push({Heuristic(end, next), next});
}
}
}
// reconstruct path
if (!m_CameFrom.count(end))
return {}; // goal never reached
return {}; // goal never reached
Path path;
TilePos cur = end;
path.push_back(m_Map->TileToWorld(cur));
while (cur != start)
{
cur = m_CameFrom[cur];
path.push_back(m_Map->TileToWorld(cur));
while (cur != start) {
cur = m_CameFrom[cur];
path.push_back(m_Map->TileToWorld(cur));
}
std::reverse(path.begin(), path.end());
return path;
}
} // pathfinder namespace
} // namespace pathfinder

View File

@@ -10,17 +10,17 @@
namespace pathfinder {
class GBFS: public PathFinderBase {
class GBFS : public PathFinderBase {
public:
GBFS(const Map* m): PathFinderBase(m) {}
GBFS(const Map *m) : PathFinderBase(m) {}
Path CalculatePath(WorldPos start, WorldPos end) override;
const std::string_view& GetName() const override { return m_Name; }
const std::string_view &GetName() const override { return m_Name; }
private:
static float Heuristic(const TilePos& a, const TilePos& b);
static float Heuristic(const TilePos &a, const TilePos &b);
const std::string_view m_Name = "Greedy Best First Search";
std::unordered_map<TilePos, TilePos, TilePosHash> m_CameFrom;
};
} // pathfinder namespace
} // namespace pathfinder

View File

@@ -3,9 +3,9 @@
#include "utils.hpp"
#include "base.hpp"
#include "log.hpp"
#include "map.hpp"
#include "math.hpp"
#include "log.hpp"
#include "pathfinder/bfs.hpp"
#include "pathfinder/dijkstra.hpp"
#include "pathfinder/gbfs.hpp"
@@ -13,23 +13,23 @@
namespace pathfinder {
namespace utils {
std::unique_ptr<PathFinderBase> create(PathFinderType type, const Map* map) {
std::unique_ptr<PathFinderBase> create(PathFinderType type, const Map *map) {
using namespace pathfinder;
switch (type) {
case PathFinderType::LINEAR:
return std::move(std::make_unique<LinearPathFinder>(map));
case PathFinderType::BFS:
return std::move(std::make_unique<BFS>(map));
case PathFinderType::DIJKSTRA:
return std::move(std::make_unique<Dijkstra>(map));
case PathFinderType::GBFS:
return std::move(std::make_unique<GBFS>(map));
case PathFinderType::COUNT:
LOG_WARNING("Incorrect pathfinder type");
return nullptr;
case PathFinderType::LINEAR:
return std::move(std::make_unique<LinearPathFinder>(map));
case PathFinderType::BFS:
return std::move(std::make_unique<BFS>(map));
case PathFinderType::DIJKSTRA:
return std::move(std::make_unique<Dijkstra>(map));
case PathFinderType::GBFS:
return std::move(std::make_unique<GBFS>(map));
case PathFinderType::COUNT:
LOG_WARNING("Incorrect pathfinder type");
return nullptr;
};
return nullptr;
}
} // utils namespace
} // pathfinding namespace
} // namespace utils
} // namespace pathfinder

View File

@@ -10,16 +10,16 @@
namespace pathfinder {
namespace utils {
struct QueueEntry
{
float cost;
TilePos tile;
struct QueueEntry {
float cost;
TilePos tile;
// min-heap -> smallest cost on top
bool operator>(const QueueEntry& o) const noexcept { return cost > o.cost; }
// min-heap -> smallest cost on top
bool operator>(const QueueEntry &o) const noexcept { return cost > o.cost; }
};
std::unique_ptr<pathfinder::PathFinderBase> create(pathfinder::PathFinderType type, const Map* map);
std::unique_ptr<pathfinder::PathFinderBase>
create(pathfinder::PathFinderType type, const Map *map);
} // utils namespace
} // pathfinding namespace
} // namespace utils
} // namespace pathfinder