1
0
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:
Andrii Danylchenko 2022-12-26 20:17:39 +02:00 committed by Andrii Danylchenko
parent e23936f6dc
commit 0829593356
8 changed files with 131 additions and 8 deletions

View File

@ -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;
}

View File

@ -114,7 +114,7 @@ const CGObjectInstance * ObjectClusterizer::getBlocker(const AIPath & path) cons
if(blockerObject)
{
blockers.push_back(blockerObject);
blockers.insert(blockers.begin(), blockerObject);
}
}

View File

@ -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;

View File

@ -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

View File

@ -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();
}
}

View File

@ -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;
};
}

View File

@ -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;

View File

@ -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(