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:
@@ -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());
|
||||||
|
@@ -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))
|
||||||
{
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
};
|
};
|
||||||
|
}
|
Reference in New Issue
Block a user