mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
NKAI: composite pathfinder actions and fix for guarded bordergate
This commit is contained in:
parent
e23936f6dc
commit
0829593356
@ -255,7 +255,7 @@ bool isObjectPassable(const CGObjectInstance * obj, PlayerColor playerColor, Pla
|
||||
{
|
||||
auto quest = dynamic_cast<const CGKeys *>(obj);
|
||||
|
||||
if(quest->passableFor(playerColor))
|
||||
if(quest->wasMyColorVisited(playerColor))
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -114,7 +114,7 @@ const CGObjectInstance * ObjectClusterizer::getBlocker(const AIPath & path) cons
|
||||
|
||||
if(blockerObject)
|
||||
{
|
||||
blockers.push_back(blockerObject);
|
||||
blockers.insert(blockers.begin(), blockerObject);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,6 +52,27 @@ AISharedStorage::~AISharedStorage()
|
||||
}
|
||||
}
|
||||
|
||||
void AIPathNode::addSpecialAction(std::shared_ptr<const SpecialAction> action)
|
||||
{
|
||||
if(!specialAction)
|
||||
{
|
||||
specialAction = action;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto parts = specialAction->getParts();
|
||||
|
||||
if(parts.empty())
|
||||
{
|
||||
parts.push_back(specialAction);
|
||||
}
|
||||
|
||||
parts.push_back(action);
|
||||
|
||||
specialAction = std::make_shared<CompositeAction>(parts);
|
||||
}
|
||||
}
|
||||
|
||||
AINodeStorage::AINodeStorage(const Nullkiller * ai, const int3 & Sizes)
|
||||
: sizes(Sizes), ai(ai), cb(ai->cb.get()), nodes(Sizes)
|
||||
{
|
||||
@ -765,7 +786,7 @@ void HeroChainCalculationTask::addHeroChain(const std::vector<ExchangeCandidate>
|
||||
if(exchangeNode->actor->actorAction)
|
||||
{
|
||||
exchangeNode->theNodeBefore = carrier;
|
||||
exchangeNode->specialAction = exchangeNode->actor->actorAction;
|
||||
exchangeNode->addSpecialAction(exchangeNode->actor->actorAction);
|
||||
}
|
||||
|
||||
exchangeNode->chainOther = other;
|
||||
@ -1045,7 +1066,7 @@ struct TowmPortalFinder
|
||||
movementCost);
|
||||
|
||||
node->theNodeBefore = bestNode;
|
||||
node->specialAction.reset(new AIPathfinding::TownPortalAction(targetTown));
|
||||
node->addSpecialAction(std::make_shared<AIPathfinding::TownPortalAction>(targetTown));
|
||||
}
|
||||
|
||||
return nodeOptional;
|
||||
|
@ -55,6 +55,8 @@ struct AIPathNode : public CGPathNode
|
||||
return accessible == CGPathNode::EAccessibility::NOT_SET
|
||||
|| accessible == CGPathNode::EAccessibility::BLOCKED;
|
||||
}
|
||||
|
||||
void addSpecialAction(std::shared_ptr<const SpecialAction> action);
|
||||
};
|
||||
|
||||
struct AIPathNodeInfo
|
||||
|
@ -27,4 +27,67 @@ void SpecialAction::execute(const CGHeroInstance * hero) const
|
||||
throw cannotFulfillGoalException("Can not execute " + toString());
|
||||
}
|
||||
|
||||
bool CompositeAction::canAct(const AIPathNode * source) const
|
||||
{
|
||||
for(auto part : parts)
|
||||
{
|
||||
if(!part->canAct(source)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Goals::TSubgoal CompositeAction::decompose(const CGHeroInstance * hero) const
|
||||
{
|
||||
for(auto part : parts)
|
||||
{
|
||||
auto goal = part->decompose(hero);
|
||||
|
||||
if(!goal->invalid()) return goal;
|
||||
}
|
||||
|
||||
return SpecialAction::decompose(hero);
|
||||
}
|
||||
|
||||
void CompositeAction::execute(const CGHeroInstance * hero) const
|
||||
{
|
||||
for(auto part : parts)
|
||||
{
|
||||
part->execute(hero);
|
||||
}
|
||||
}
|
||||
|
||||
void CompositeAction::applyOnDestination(
|
||||
const CGHeroInstance * hero,
|
||||
CDestinationNodeInfo & destination,
|
||||
const PathNodeInfo & source,
|
||||
AIPathNode * dstNode,
|
||||
const AIPathNode * srcNode) const
|
||||
{
|
||||
for(auto part : parts)
|
||||
{
|
||||
part->applyOnDestination(hero, destination, source, dstNode, srcNode);
|
||||
}
|
||||
}
|
||||
|
||||
std::string CompositeAction::toString() const
|
||||
{
|
||||
std::string result = "";
|
||||
|
||||
for(auto part : parts)
|
||||
{
|
||||
result += ", " + part->toString();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const CGObjectInstance * CompositeAction::targetObject() const
|
||||
{
|
||||
if(parts.empty())
|
||||
return nullptr;
|
||||
|
||||
return parts.front()->targetObject();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ public:
|
||||
const CGHeroInstance * hero,
|
||||
CDestinationNodeInfo & destination,
|
||||
const PathNodeInfo & source,
|
||||
AIPathNode * dstMode,
|
||||
AIPathNode * dstNode,
|
||||
const AIPathNode * srcNode) const
|
||||
{
|
||||
}
|
||||
@ -44,6 +44,38 @@ public:
|
||||
virtual std::string toString() const = 0;
|
||||
|
||||
virtual const CGObjectInstance * targetObject() const { return nullptr; }
|
||||
|
||||
virtual std::vector<std::shared_ptr<const SpecialAction>> getParts() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
class CompositeAction : public SpecialAction
|
||||
{
|
||||
private:
|
||||
std::vector<std::shared_ptr<const SpecialAction>> parts;
|
||||
|
||||
public:
|
||||
CompositeAction(std::vector<std::shared_ptr<const SpecialAction>> parts) : parts(parts) {}
|
||||
|
||||
bool canAct(const AIPathNode * source) const override;
|
||||
void execute(const CGHeroInstance * hero) const override;
|
||||
std::string toString() const override;
|
||||
const CGObjectInstance * targetObject() const override;
|
||||
Goals::TSubgoal decompose(const CGHeroInstance * hero) const override;
|
||||
|
||||
std::vector<std::shared_ptr<const SpecialAction>> getParts() const override
|
||||
{
|
||||
return parts;
|
||||
}
|
||||
|
||||
void applyOnDestination(
|
||||
const CGHeroInstance * hero,
|
||||
CDestinationNodeInfo & destination,
|
||||
const PathNodeInfo & source,
|
||||
AIPathNode * dstNode,
|
||||
const AIPathNode * srcNode) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ namespace AIPathfinding
|
||||
|
||||
if(boatNode->action == CGPathNode::UNKNOWN)
|
||||
{
|
||||
boatNode->specialAction = virtualBoat;
|
||||
boatNode->addSpecialAction(virtualBoat);
|
||||
destination.blocked = false;
|
||||
destination.action = CGPathNode::ENodeAction::EMBARK;
|
||||
destination.node = boatNode;
|
||||
|
@ -157,7 +157,7 @@ namespace AIPathfinding
|
||||
|
||||
nodeStorage->updateAINode(destination.node, [&](AIPathNode * node)
|
||||
{
|
||||
node->specialAction.reset(new QuestAction(questAction));
|
||||
node->addSpecialAction(std::make_shared<QuestAction>(questAction));
|
||||
});
|
||||
}
|
||||
|
||||
@ -279,6 +279,11 @@ namespace AIPathfinding
|
||||
|
||||
if(loss < actualArmyValue)
|
||||
{
|
||||
if(destNode->specialAction)
|
||||
{
|
||||
battleNode->specialAction = destNode->specialAction;
|
||||
}
|
||||
|
||||
destination.node = battleNode;
|
||||
nodeStorage->commit(destination, source);
|
||||
|
||||
@ -288,7 +293,7 @@ namespace AIPathfinding
|
||||
|
||||
AIPreviousNodeRule(nodeStorage).process(source, destination, pathfinderConfig, pathfinderHelper);
|
||||
|
||||
battleNode->specialAction = std::make_shared<BattleAction>(destination.coord);
|
||||
battleNode->addSpecialAction(std::make_shared<BattleAction>(destination.coord));
|
||||
|
||||
#if NKAI_PATHFINDER_TRACE_LEVEL >= 1
|
||||
logAi->trace(
|
||||
|
Loading…
Reference in New Issue
Block a user