Skip to content

Commit

Permalink
less map look ups
Browse files Browse the repository at this point in the history
  • Loading branch information
jere8184 committed Nov 15, 2024
1 parent 0763aaf commit f3003dc
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 35 deletions.
16 changes: 8 additions & 8 deletions libopenage/pathfinding/grid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,20 +109,20 @@ void Grid::init_portal_nodes()
{
for(auto& portal : sector->get_portals())
{
if(this->portal_nodes.find(portal->get_id()) == this->portal_nodes.end())
{
this->portal_nodes[portal->get_id()] = std::make_shared<PortalNode>(portal);
if(!this->portal_nodes.contains(portal->get_id()))
{
auto portal_node = std::make_shared<PortalNode>(portal);
portal_node->node_sector_0 = sector->get_id();
portal_node->node_sector_1 = portal_node->portal->get_exit_sector(sector->get_id());
this->portal_nodes[portal->get_id()] = portal_node;
}
}
}

//init portal_node exits
for(auto& sector : this->sectors)
for(auto& [id, node] : this->portal_nodes)
{
for(auto& portal : sector->get_portals())
{
this->portal_nodes[portal->get_id()]->init_exits(this->portal_nodes, sector->get_id());
}
node->init_exits(this->portal_nodes);
}
}

Expand Down
1 change: 0 additions & 1 deletion libopenage/pathfinding/grid.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include "pathfinding/pathfinder.h"
#include "pathfinding/types.h"
#include "util/vector.h"
#include "pathfinding/pathfinder.h"


namespace openage::path {
Expand Down
62 changes: 47 additions & 15 deletions libopenage/pathfinding/pathfinder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "pathfinding/integrator.h"
#include "pathfinding/portal.h"
#include "pathfinding/sector.h"
#include "error/error.h"


namespace openage::path {
Expand Down Expand Up @@ -211,9 +212,7 @@ const Pathfinder::portal_star_t Pathfinder::portal_a_star(const PathRequest &req
// path node storage, always provides cheapest next node.
heap_t node_candidates;

// list of known portals and corresponding node.
std::unordered_set<portal_id_t> visited_portals;
std::unordered_set<portal_id_t> was_best;

// TODO: Compute cost to travel from one portal to another when creating portals
// const int distance_cost = 1;
Expand All @@ -226,7 +225,6 @@ const Pathfinder::portal_star_t Pathfinder::portal_a_star(const PathRequest &req
}

auto& portal_node = portal_map.at(portal->get_id());
portal_node->prev_portal = nullptr;
portal_node->entry_sector = start_sector->get_id();

auto sector_pos = grid->get_sector(portal->get_exit_sector(start_sector->get_id()))->get_position().to_tile(sector_size);
Expand All @@ -239,6 +237,8 @@ const Pathfinder::portal_star_t Pathfinder::portal_a_star(const PathRequest &req
portal_node->future_cost = portal_node->current_cost + heuristic_cost;

portal_node->heap_node = node_candidates.push(portal_node);
portal_node->prev_portal = nullptr;
portal_node->was_best = false;
visited_portals.insert(portal->get_id());
}

Expand All @@ -250,7 +250,7 @@ const Pathfinder::portal_star_t Pathfinder::portal_a_star(const PathRequest &req
while (not node_candidates.empty()) {
auto current_node = node_candidates.pop();

was_best.insert(current_node->portal->get_id());
current_node->was_best = true;

// check if the current node is a portal in the target sector that can
// be reached from the target cell
Expand All @@ -270,18 +270,23 @@ const Pathfinder::portal_star_t Pathfinder::portal_a_star(const PathRequest &req
}

// get the exits of the current node
const auto& exits = current_node->exits.at(current_node->entry_sector);
const auto& exits = current_node->get_exits(current_node->entry_sector);

// evaluate all neighbors of the current candidate for further progress
for (auto &[exit_id, distance_cost] : exits) {
auto& exit = portal_map.at(exit_id);
for (auto &[exit, distance_cost] : exits) {
exit->entry_sector = current_node->portal->get_exit_sector(current_node->entry_sector);
if (was_best.contains(exit->portal->get_id())) {
bool not_visited = !visited_portals.contains(exit->portal->get_id());

if(not_visited)
{
exit->was_best = false;
}
else if(exit->was_best)
{
continue;
}


bool not_visited = !visited_portals.contains(exit->portal->get_id());
auto tentative_cost = current_node->current_cost + distance_cost;

if (not_visited or tentative_cost < exit->current_cost) {
Expand Down Expand Up @@ -471,6 +476,7 @@ PortalNode::PortalNode(const std::shared_ptr<Portal> &portal) :
future_cost{std::numeric_limits<int>::max()},
current_cost{std::numeric_limits<int>::max()},
heuristic_cost{std::numeric_limits<int>::max()},
was_best{false},
prev_portal{nullptr},
heap_node{nullptr} {}

Expand All @@ -482,6 +488,7 @@ PortalNode::PortalNode(const std::shared_ptr<Portal> &portal,
future_cost{std::numeric_limits<int>::max()},
current_cost{std::numeric_limits<int>::max()},
heuristic_cost{std::numeric_limits<int>::max()},
was_best{false},
prev_portal{prev_portal},
heap_node{nullptr} {}

Expand All @@ -495,6 +502,7 @@ PortalNode::PortalNode(const std::shared_ptr<Portal> &portal,
future_cost{past_cost + heuristic_cost},
current_cost{past_cost},
heuristic_cost{heuristic_cost},
was_best{false},
prev_portal{prev_portal},
heap_node{nullptr} {
}
Expand All @@ -520,15 +528,39 @@ std::vector<node_t> PortalNode::generate_backtrace() {
return waypoints;
}

void PortalNode::init_exits(sector_id_t entry_sector) {
auto &exits = this->portal->get_exits(entry_sector);
sector_id_t exit_sector = this->portal->get_exit_sector(entry_sector);
void PortalNode::init_exits(const nodemap_t& node_map) {
auto exits = this->portal->get_exits(this->node_sector_0);
for (auto &exit : exits) {
int distance_cost = Pathfinder::distance_cost(
this->portal->get_exit_center(this->node_sector_0),
exit->get_entry_center(this->node_sector_1));

auto exit_node = node_map.at(exit->get_id());
this->exits_1[exit_node] = distance_cost;
}

exits = this->portal->get_exits(this->node_sector_1);
for (auto &exit : exits) {
int distance_cost = Pathfinder::distance_cost(
this->portal->get_exit_center(entry_sector),
exit->get_entry_center(exit_sector));
this->portal->get_exit_center(this->node_sector_1),
exit->get_entry_center(this->node_sector_0));

auto exit_node = node_map.at(exit->get_id());
this->exits_0[exit_node] = distance_cost;
}
}

const PortalNode::exits_t& PortalNode::get_exits(sector_id_t entry_sector)
{
ENSURE(entry_sector == this->node_sector_0 || entry_sector == this->node_sector_1, "Invalid entry sector");

this->exits[entry_sector][exit->get_id()] = distance_cost;
if(this->node_sector_0 == entry_sector)
{
return exits_1;
}
else
{
return exits_0;
}
}

Expand Down
48 changes: 37 additions & 11 deletions libopenage/pathfinding/pathfinder.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

#include <memory>
#include <unordered_map>
#include <unordered_set>
#include <map>

#include "coord/tile.h"
#include "datastructure/pairing_heap.h"
Expand Down Expand Up @@ -150,7 +150,6 @@ using nodemap_t = std::unordered_map<portal_id_t, node_t>;
class PortalNode : public std::enable_shared_from_this<PortalNode> {
public:
PortalNode(const std::shared_ptr<Portal> &portal);

PortalNode(const std::shared_ptr<Portal> &portal,
sector_id_t entry_sector,
const node_t &prev_portal);
Expand Down Expand Up @@ -184,7 +183,25 @@ class PortalNode : public std::enable_shared_from_this<PortalNode> {
/**
* init PortalNode::exits.
*/
void init_exits(sector_id_t entry_sector);
void init_exits(const nodemap_t& node_map);




/**
* maps node_t of a neigbhour portal to the distance cost to travel between the portals
*/
using exits_t = std::map<const node_t, int>;


/**
* Get the exit portals reachable via the portal when entering from a specified sector.
*
* @param entry_sector Sector from which the portal is entered.
*
* @return Exit portals nodes reachable from the portal.
*/
const exits_t& get_exits(sector_id_t entry_sector);

/**
* The portal this node is associated to.
Expand Down Expand Up @@ -232,16 +249,25 @@ class PortalNode : public std::enable_shared_from_this<PortalNode> {
heap_t::element_t heap_node;

/**
* maps portal_id_t of a neigbhour portal to the distance cost to travel between the portals
*/
using neighbours_t = std::unordered_map<portal_id_t, int>;
* First sector connected by the portal.
*/
sector_id_t node_sector_0;

/**
* Second sector connected by the portal.
*/
sector_id_t node_sector_1;

/**
* Exits in sector 0 reachable from the portal.
*/
exits_t exits_0;

/**
* Exits in sector 1 reachable from the portal.
*/
exits_t exits_1;

/*
* maps a sector_id that the portal can be entered from
* to a set of portal_ids that connect to the sector the portal will be exited from and the cost to travel to them.
*/
std::unordered_map<sector_id_t, neighbours_t> exits;
};


Expand Down

0 comments on commit f3003dc

Please sign in to comment.