mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-06 09:09:40 +02:00
Use containers with pre-allocations to improve pathfinding speed
This commit is contained in:
@@ -320,11 +320,9 @@ void AINodeStorage::calculateNeighbours(
|
|||||||
const PathfinderConfig * pathfinderConfig,
|
const PathfinderConfig * pathfinderConfig,
|
||||||
const CPathfinderHelper * pathfinderHelper)
|
const CPathfinderHelper * pathfinderHelper)
|
||||||
{
|
{
|
||||||
std::vector<int3> accessibleNeighbourTiles;
|
NeighbourTilesVector accessibleNeighbourTiles;
|
||||||
|
|
||||||
result.clear();
|
result.clear();
|
||||||
accessibleNeighbourTiles.reserve(8);
|
|
||||||
|
|
||||||
pathfinderHelper->calculateNeighbourTiles(accessibleNeighbourTiles, source);
|
pathfinderHelper->calculateNeighbourTiles(accessibleNeighbourTiles, source);
|
||||||
|
|
||||||
const AIPathNode * srcNode = getAINode(source.node);
|
const AIPathNode * srcNode = getAINode(source.node);
|
||||||
|
|||||||
@@ -162,10 +162,9 @@ void AINodeStorage::calculateNeighbours(
|
|||||||
const PathfinderConfig * pathfinderConfig,
|
const PathfinderConfig * pathfinderConfig,
|
||||||
const CPathfinderHelper * pathfinderHelper)
|
const CPathfinderHelper * pathfinderHelper)
|
||||||
{
|
{
|
||||||
std::vector<int3> accessibleNeighbourTiles;
|
NeighbourTilesVector accessibleNeighbourTiles;
|
||||||
|
|
||||||
result.clear();
|
result.clear();
|
||||||
accessibleNeighbourTiles.reserve(8);
|
|
||||||
|
|
||||||
pathfinderHelper->calculateNeighbourTiles(accessibleNeighbourTiles, source);
|
pathfinderHelper->calculateNeighbourTiles(accessibleNeighbourTiles, source);
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ bool CPathfinderHelper::canMoveFromNode(const PathNodeInfo & source) const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPathfinderHelper::calculateNeighbourTiles(std::vector<int3> & result, const PathNodeInfo & source) const
|
void CPathfinderHelper::calculateNeighbourTiles(NeighbourTilesVector & result, const PathNodeInfo & source) const
|
||||||
{
|
{
|
||||||
result.clear();
|
result.clear();
|
||||||
|
|
||||||
@@ -239,9 +239,9 @@ void CPathfinder::calculatePaths()
|
|||||||
logAi->trace("CPathfinder finished with %s iterations", std::to_string(counter));
|
logAi->trace("CPathfinder finished with %s iterations", std::to_string(counter));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int3> CPathfinderHelper::getAllowedTeleportChannelExits(const TeleportChannelID & channelID) const
|
TeleporterTilesVector CPathfinderHelper::getAllowedTeleportChannelExits(const TeleportChannelID & channelID) const
|
||||||
{
|
{
|
||||||
std::vector<int3> allowedExits;
|
TeleporterTilesVector allowedExits;
|
||||||
|
|
||||||
for(const auto & objId : getTeleportChannelExits(channelID, hero->tempOwner))
|
for(const auto & objId : getTeleportChannelExits(channelID, hero->tempOwner))
|
||||||
{
|
{
|
||||||
@@ -262,9 +262,9 @@ std::vector<int3> CPathfinderHelper::getAllowedTeleportChannelExits(const Telepo
|
|||||||
return allowedExits;
|
return allowedExits;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int3> CPathfinderHelper::getCastleGates(const PathNodeInfo & source) const
|
TeleporterTilesVector CPathfinderHelper::getCastleGates(const PathNodeInfo & source) const
|
||||||
{
|
{
|
||||||
std::vector<int3> allowedExits;
|
TeleporterTilesVector allowedExits;
|
||||||
|
|
||||||
auto towns = getPlayerState(hero->tempOwner)->towns;
|
auto towns = getPlayerState(hero->tempOwner)->towns;
|
||||||
for(const auto & town : towns)
|
for(const auto & town : towns)
|
||||||
@@ -279,9 +279,9 @@ std::vector<int3> CPathfinderHelper::getCastleGates(const PathNodeInfo & source)
|
|||||||
return allowedExits;
|
return allowedExits;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int3> CPathfinderHelper::getTeleportExits(const PathNodeInfo & source) const
|
TeleporterTilesVector CPathfinderHelper::getTeleportExits(const PathNodeInfo & source) const
|
||||||
{
|
{
|
||||||
std::vector<int3> teleportationExits;
|
TeleporterTilesVector teleportationExits;
|
||||||
|
|
||||||
const auto * objTeleport = dynamic_cast<const CGTeleport *>(source.nodeObject);
|
const auto * objTeleport = dynamic_cast<const CGTeleport *>(source.nodeObject);
|
||||||
if(isAllowedTeleportEntrance(objTeleport))
|
if(isAllowedTeleportEntrance(objTeleport))
|
||||||
@@ -578,7 +578,7 @@ int CPathfinderHelper::getMaxMovePoints(const EPathfindingLayer & layer) const
|
|||||||
void CPathfinderHelper::getNeighbours(
|
void CPathfinderHelper::getNeighbours(
|
||||||
const TerrainTile & srcTile,
|
const TerrainTile & srcTile,
|
||||||
const int3 & srcCoord,
|
const int3 & srcCoord,
|
||||||
std::vector<int3> & vec,
|
NeighbourTilesVector & vec,
|
||||||
const boost::logic::tribool & onLand,
|
const boost::logic::tribool & onLand,
|
||||||
const bool limitCoastSailing) const
|
const bool limitCoastSailing) const
|
||||||
{
|
{
|
||||||
@@ -702,8 +702,8 @@ int CPathfinderHelper::getMovementCost(
|
|||||||
constexpr auto maxCostOfOneStep = static_cast<int>(175 * M_SQRT2); // diagonal move on Swamp - 247 MP
|
constexpr auto maxCostOfOneStep = static_cast<int>(175 * M_SQRT2); // diagonal move on Swamp - 247 MP
|
||||||
if(checkLast && left > 0 && left <= maxCostOfOneStep) //it might be the last tile - if no further move possible we take all move points
|
if(checkLast && left > 0 && left <= maxCostOfOneStep) //it might be the last tile - if no further move possible we take all move points
|
||||||
{
|
{
|
||||||
std::vector<int3> vec;
|
NeighbourTilesVector vec;
|
||||||
vec.reserve(8); //optimization
|
|
||||||
getNeighbours(*dt, dst, vec, ct->terType->isLand(), true);
|
getNeighbours(*dt, dst, vec, ct->terType->isLand(), true);
|
||||||
for(const auto & elem : vec)
|
for(const auto & elem : vec)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,12 +13,23 @@
|
|||||||
#include "../IGameCallback.h"
|
#include "../IGameCallback.h"
|
||||||
#include "../bonuses/BonusEnum.h"
|
#include "../bonuses/BonusEnum.h"
|
||||||
|
|
||||||
|
#include <boost/container/static_vector.hpp>
|
||||||
|
#include <boost/container/small_vector.hpp>
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
class CGWhirlpool;
|
class CGWhirlpool;
|
||||||
struct TurnInfo;
|
struct TurnInfo;
|
||||||
struct PathfinderOptions;
|
struct PathfinderOptions;
|
||||||
|
|
||||||
|
// Optimized storage - tile can have 0-8 neighbour tiles
|
||||||
|
// static_vector uses fixed, preallocated storage (capacity) and dynamic size
|
||||||
|
// this avoid dynamic allocations on huge number of neighbour list queries
|
||||||
|
using NeighbourTilesVector = boost::container::static_vector<int3, 8>;
|
||||||
|
|
||||||
|
// Optimized storage to minimize dynamic allocations - most of teleporters have only one exit, but some may have more (premade maps, castle gates)
|
||||||
|
using TeleporterTilesVector = boost::container::small_vector<int3, 4>;
|
||||||
|
|
||||||
class DLL_LINKAGE CPathfinder
|
class DLL_LINKAGE CPathfinder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -87,22 +98,22 @@ public:
|
|||||||
bool hasBonusOfType(BonusType type) const;
|
bool hasBonusOfType(BonusType type) const;
|
||||||
int getMaxMovePoints(const EPathfindingLayer & layer) const;
|
int getMaxMovePoints(const EPathfindingLayer & layer) const;
|
||||||
|
|
||||||
std::vector<int3> getCastleGates(const PathNodeInfo & source) const;
|
TeleporterTilesVector getCastleGates(const PathNodeInfo & source) const;
|
||||||
bool isAllowedTeleportEntrance(const CGTeleport * obj) const;
|
bool isAllowedTeleportEntrance(const CGTeleport * obj) const;
|
||||||
std::vector<int3> getAllowedTeleportChannelExits(const TeleportChannelID & channelID) const;
|
TeleporterTilesVector getAllowedTeleportChannelExits(const TeleportChannelID & channelID) const;
|
||||||
bool addTeleportTwoWay(const CGTeleport * obj) const;
|
bool addTeleportTwoWay(const CGTeleport * obj) const;
|
||||||
bool addTeleportOneWay(const CGTeleport * obj) const;
|
bool addTeleportOneWay(const CGTeleport * obj) const;
|
||||||
bool addTeleportOneWayRandom(const CGTeleport * obj) const;
|
bool addTeleportOneWayRandom(const CGTeleport * obj) const;
|
||||||
bool addTeleportWhirlpool(const CGWhirlpool * obj) const;
|
bool addTeleportWhirlpool(const CGWhirlpool * obj) const;
|
||||||
bool canMoveBetween(const int3 & a, const int3 & b) const; //checks only for visitable objects that may make moving between tiles impossible, not other conditions (like tiles itself accessibility)
|
bool canMoveBetween(const int3 & a, const int3 & b) const; //checks only for visitable objects that may make moving between tiles impossible, not other conditions (like tiles itself accessibility)
|
||||||
|
|
||||||
void calculateNeighbourTiles(std::vector<int3> & result, const PathNodeInfo & source) const;
|
void calculateNeighbourTiles(NeighbourTilesVector & result, const PathNodeInfo & source) const;
|
||||||
std::vector<int3> getTeleportExits(const PathNodeInfo & source) const;
|
TeleporterTilesVector getTeleportExits(const PathNodeInfo & source) const;
|
||||||
|
|
||||||
void getNeighbours(
|
void getNeighbours(
|
||||||
const TerrainTile & srcTile,
|
const TerrainTile & srcTile,
|
||||||
const int3 & srcCoord,
|
const int3 & srcCoord,
|
||||||
std::vector<int3> & vec,
|
NeighbourTilesVector & vec,
|
||||||
const boost::logic::tribool & onLand,
|
const boost::logic::tribool & onLand,
|
||||||
const bool limitCoastSailing) const;
|
const bool limitCoastSailing) const;
|
||||||
|
|
||||||
|
|||||||
@@ -67,10 +67,9 @@ void NodeStorage::calculateNeighbours(
|
|||||||
const PathfinderConfig * pathfinderConfig,
|
const PathfinderConfig * pathfinderConfig,
|
||||||
const CPathfinderHelper * pathfinderHelper)
|
const CPathfinderHelper * pathfinderHelper)
|
||||||
{
|
{
|
||||||
std::vector<int3> accessibleNeighbourTiles;
|
NeighbourTilesVector accessibleNeighbourTiles;
|
||||||
|
|
||||||
result.clear();
|
result.clear();
|
||||||
accessibleNeighbourTiles.reserve(8);
|
|
||||||
|
|
||||||
pathfinderHelper->calculateNeighbourTiles(accessibleNeighbourTiles, source);
|
pathfinderHelper->calculateNeighbourTiles(accessibleNeighbourTiles, source);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user