1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-08-15 20:03:15 +02:00

Freeze when try to bypass a few adjasent guards

This commit is contained in:
Andrii Danylchenko
2018-11-03 15:25:14 +02:00
parent 064130973f
commit 812df63aae
3 changed files with 349 additions and 362 deletions

View File

@@ -49,7 +49,7 @@ std::vector<AIPath> AIPathfinder::getPathInfo(HeroPtr hero, int3 tile)
storageMap[hero] = nodeStorage; storageMap[hero] = nodeStorage;
auto config = std::make_shared<AIPathfinderConfig>(cb, ai, nodeStorage); auto config = std::make_shared<AIPathfinding::AIPathfinderConfig>(cb, ai, nodeStorage);
nodeStorage->setHero(hero.get()); nodeStorage->setHero(hero.get());
cb->calculatePaths(config, hero.get()); cb->calculatePaths(config, hero.get());

View File

@@ -13,12 +13,14 @@
#include "../../../lib/mapping/CMap.h" #include "../../../lib/mapping/CMap.h"
#include "../../../lib/mapObjects/MapObjects.h" #include "../../../lib/mapObjects/MapObjects.h"
class BuildBoatAction : public ISpecialAction namespace AIPathfinding
{ {
private: class BuildBoatAction : public ISpecialAction
{
private:
const IShipyard * shipyard; const IShipyard * shipyard;
public: public:
BuildBoatAction(const IShipyard * shipyard) BuildBoatAction(const IShipyard * shipyard)
:shipyard(shipyard) :shipyard(shipyard)
{ {
@@ -28,17 +30,35 @@ public:
{ {
return sptr(Goals::BuildBoat(shipyard)); return sptr(Goals::BuildBoat(shipyard));
} }
}; };
class AILayerTransitionRule : public LayerTransitionRule class BattleAction : public ISpecialAction
{ {
private: private:
const int3 target;
const HeroPtr hero;
public:
BattleAction(const int3 target)
:target(target)
{
}
virtual Goals::TSubgoal whatToDo(HeroPtr hero) const override
{
return sptr(Goals::VisitTile(target).sethero(hero));
}
};
class AILayerTransitionRule : public LayerTransitionRule
{
private:
CPlayerSpecificInfoCallback * cb; CPlayerSpecificInfoCallback * cb;
VCAI * ai; VCAI * ai;
std::map<int3, std::shared_ptr<const BuildBoatAction>> virtualBoats; std::map<int3, std::shared_ptr<const BuildBoatAction>> virtualBoats;
std::shared_ptr<AINodeStorage> nodeStorage; std::shared_ptr<AINodeStorage> nodeStorage;
public: public:
AILayerTransitionRule(CPlayerSpecificInfoCallback * cb, VCAI * ai, std::shared_ptr<AINodeStorage> nodeStorage) AILayerTransitionRule(CPlayerSpecificInfoCallback * cb, VCAI * ai, std::shared_ptr<AINodeStorage> nodeStorage)
:cb(cb), ai(ai), nodeStorage(nodeStorage) :cb(cb), ai(ai), nodeStorage(nodeStorage)
{ {
@@ -92,7 +112,7 @@ public:
} }
} }
private: private:
void setup() void setup()
{ {
std::vector<const IShipyard *> shipyards; std::vector<const IShipyard *> shipyards;
@@ -122,15 +142,15 @@ private:
} }
} }
} }
}; };
class AIMovementAfterDestinationRule : public MovementAfterDestinationRule class AIMovementAfterDestinationRule : public MovementAfterDestinationRule
{ {
private: private:
CPlayerSpecificInfoCallback * cb; CPlayerSpecificInfoCallback * cb;
std::shared_ptr<AINodeStorage> nodeStorage; std::shared_ptr<AINodeStorage> nodeStorage;
public: public:
AIMovementAfterDestinationRule(CPlayerSpecificInfoCallback * cb, std::shared_ptr<AINodeStorage> nodeStorage) AIMovementAfterDestinationRule(CPlayerSpecificInfoCallback * cb, std::shared_ptr<AINodeStorage> nodeStorage)
:cb(cb), nodeStorage(nodeStorage) :cb(cb), nodeStorage(nodeStorage)
{ {
@@ -244,6 +264,8 @@ public:
battleNode->danger = danger; battleNode->danger = danger;
} }
battleNode->specialAction = std::make_shared<BattleAction>(destination.coord);
logAi->trace( logAi->trace(
"Begin bypass guard at destination with danger %s while moving %s -> %s", "Begin bypass guard at destination with danger %s while moving %s -> %s",
std::to_string(danger), std::to_string(danger),
@@ -255,15 +277,15 @@ public:
destination.blocked = true; destination.blocked = true;
} }
}; };
class AIMovementToDestinationRule : public MovementToDestinationRule class AIMovementToDestinationRule : public MovementToDestinationRule
{ {
private: private:
CPlayerSpecificInfoCallback * cb; CPlayerSpecificInfoCallback * cb;
std::shared_ptr<AINodeStorage> nodeStorage; std::shared_ptr<AINodeStorage> nodeStorage;
public: public:
AIMovementToDestinationRule(CPlayerSpecificInfoCallback * cb, std::shared_ptr<AINodeStorage> nodeStorage) AIMovementToDestinationRule(CPlayerSpecificInfoCallback * cb, std::shared_ptr<AINodeStorage> nodeStorage)
:cb(cb), nodeStorage(nodeStorage) :cb(cb), nodeStorage(nodeStorage)
{ {
@@ -288,44 +310,26 @@ public:
} }
if(blocker == BlockingReason::SOURCE_GUARDED && nodeStorage->isBattleNode(source.node)) if(blocker == BlockingReason::SOURCE_GUARDED && nodeStorage->isBattleNode(source.node))
{
auto srcGuardians = cb->getGuardingCreatures(source.coord);
auto destGuardians = cb->getGuardingCreatures(destination.coord);
for(auto srcGuard : srcGuardians)
{
if(!vstd::contains(destGuardians, srcGuard))
continue;
auto guardPos = srcGuard->visitablePos();
if(guardPos != source.coord && guardPos != destination.coord)
{
destination.blocked = true; // allow to pass monster only through guard tile
}
}
if(!destination.blocked)
{ {
logAi->trace( logAi->trace(
"Bypass src guard while moving from %s to %s", "Bypass src guard while moving from %s to %s",
source.coord.toString(), source.coord.toString(),
destination.coord.toString()); destination.coord.toString());
}
return; return;
} }
destination.blocked = true; destination.blocked = true;
} }
}; };
class AIPreviousNodeRule : public MovementToDestinationRule class AIPreviousNodeRule : public MovementToDestinationRule
{ {
private: private:
CPlayerSpecificInfoCallback * cb; CPlayerSpecificInfoCallback * cb;
std::shared_ptr<AINodeStorage> nodeStorage; std::shared_ptr<AINodeStorage> nodeStorage;
public: public:
AIPreviousNodeRule(CPlayerSpecificInfoCallback * cb, std::shared_ptr<AINodeStorage> nodeStorage) AIPreviousNodeRule(CPlayerSpecificInfoCallback * cb, std::shared_ptr<AINodeStorage> nodeStorage)
:cb(cb), nodeStorage(nodeStorage) :cb(cb), nodeStorage(nodeStorage)
{ {
@@ -337,27 +341,6 @@ public:
const PathfinderConfig * pathfinderConfig, const PathfinderConfig * pathfinderConfig,
CPathfinderHelper * pathfinderHelper) const override CPathfinderHelper * pathfinderHelper) const override
{ {
//FIXME: unused
// auto blocker = getBlockingReason(source, destination, pathfinderConfig, pathfinderHelper);
if(source.guarded)
{
auto srcGuardian = cb->guardingCreaturePosition(source.node->coord);
if(srcGuardian == source.node->coord)
{
// guardian tile is used as chain junction
destination.node->theNodeBefore = source.node;
logAi->trace(
"Link src node %s to destination node %s while bypassing guard",
source.coord.toString(),
destination.coord.toString());
return;
}
}
if(source.node->action == CGPathNode::ENodeAction::BLOCKING_VISIT || source.node->action == CGPathNode::ENodeAction::VISIT) if(source.node->action == CGPathNode::ENodeAction::BLOCKING_VISIT || source.node->action == CGPathNode::ENodeAction::VISIT)
{ {
// we can not directly bypass objects, we need to interact with them first // we can not directly bypass objects, we need to interact with them first
@@ -379,13 +362,13 @@ public:
destination.node->theNodeBefore = source.node; destination.node->theNodeBefore = source.node;
} }
} }
}; };
std::vector<std::shared_ptr<IPathfindingRule>> makeRuleset( std::vector<std::shared_ptr<IPathfindingRule>> makeRuleset(
CPlayerSpecificInfoCallback * cb, CPlayerSpecificInfoCallback * cb,
VCAI * ai, VCAI * ai,
std::shared_ptr<AINodeStorage> nodeStorage) std::shared_ptr<AINodeStorage> nodeStorage)
{ {
std::vector<std::shared_ptr<IPathfindingRule>> rules = { std::vector<std::shared_ptr<IPathfindingRule>> rules = {
std::make_shared<AILayerTransitionRule>(cb, ai, nodeStorage), std::make_shared<AILayerTransitionRule>(cb, ai, nodeStorage),
std::make_shared<DestinationActionRule>(), std::make_shared<DestinationActionRule>(),
@@ -396,12 +379,13 @@ std::vector<std::shared_ptr<IPathfindingRule>> makeRuleset(
}; };
return rules; return rules;
} }
AIPathfinderConfig::AIPathfinderConfig( AIPathfinderConfig::AIPathfinderConfig(
CPlayerSpecificInfoCallback * cb, CPlayerSpecificInfoCallback * cb,
VCAI * ai, VCAI * ai,
std::shared_ptr<AINodeStorage> nodeStorage) std::shared_ptr<AINodeStorage> nodeStorage)
:PathfinderConfig(nodeStorage, makeRuleset(cb, ai, nodeStorage)) :PathfinderConfig(nodeStorage, makeRuleset(cb, ai, nodeStorage))
{ {
}
} }

View File

@@ -13,11 +13,14 @@
#include "AINodeStorage.h" #include "AINodeStorage.h"
#include "../VCAI.h" #include "../VCAI.h"
class AIPathfinderConfig : public PathfinderConfig namespace AIPathfinding
{ {
public: class AIPathfinderConfig : public PathfinderConfig
{
public:
AIPathfinderConfig( AIPathfinderConfig(
CPlayerSpecificInfoCallback * cb, CPlayerSpecificInfoCallback * cb,
VCAI * ai, VCAI * ai,
std::shared_ptr<AINodeStorage> nodeStorage); std::shared_ptr<AINodeStorage> nodeStorage);
}; };
}