mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-12 02:28:11 +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);
|
auto quest = dynamic_cast<const CGKeys *>(obj);
|
||||||
|
|
||||||
if(quest->passableFor(playerColor))
|
if(quest->wasMyColorVisited(playerColor))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ const CGObjectInstance * ObjectClusterizer::getBlocker(const AIPath & path) cons
|
|||||||
|
|
||||||
if(blockerObject)
|
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)
|
AINodeStorage::AINodeStorage(const Nullkiller * ai, const int3 & Sizes)
|
||||||
: sizes(Sizes), ai(ai), cb(ai->cb.get()), nodes(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)
|
if(exchangeNode->actor->actorAction)
|
||||||
{
|
{
|
||||||
exchangeNode->theNodeBefore = carrier;
|
exchangeNode->theNodeBefore = carrier;
|
||||||
exchangeNode->specialAction = exchangeNode->actor->actorAction;
|
exchangeNode->addSpecialAction(exchangeNode->actor->actorAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
exchangeNode->chainOther = other;
|
exchangeNode->chainOther = other;
|
||||||
@ -1045,7 +1066,7 @@ struct TowmPortalFinder
|
|||||||
movementCost);
|
movementCost);
|
||||||
|
|
||||||
node->theNodeBefore = bestNode;
|
node->theNodeBefore = bestNode;
|
||||||
node->specialAction.reset(new AIPathfinding::TownPortalAction(targetTown));
|
node->addSpecialAction(std::make_shared<AIPathfinding::TownPortalAction>(targetTown));
|
||||||
}
|
}
|
||||||
|
|
||||||
return nodeOptional;
|
return nodeOptional;
|
||||||
|
@ -55,6 +55,8 @@ struct AIPathNode : public CGPathNode
|
|||||||
return accessible == CGPathNode::EAccessibility::NOT_SET
|
return accessible == CGPathNode::EAccessibility::NOT_SET
|
||||||
|| accessible == CGPathNode::EAccessibility::BLOCKED;
|
|| accessible == CGPathNode::EAccessibility::BLOCKED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addSpecialAction(std::shared_ptr<const SpecialAction> action);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AIPathNodeInfo
|
struct AIPathNodeInfo
|
||||||
|
@ -27,4 +27,67 @@ void SpecialAction::execute(const CGHeroInstance * hero) const
|
|||||||
throw cannotFulfillGoalException("Can not execute " + toString());
|
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,
|
const CGHeroInstance * hero,
|
||||||
CDestinationNodeInfo & destination,
|
CDestinationNodeInfo & destination,
|
||||||
const PathNodeInfo & source,
|
const PathNodeInfo & source,
|
||||||
AIPathNode * dstMode,
|
AIPathNode * dstNode,
|
||||||
const AIPathNode * srcNode) const
|
const AIPathNode * srcNode) const
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -44,6 +44,38 @@ public:
|
|||||||
virtual std::string toString() const = 0;
|
virtual std::string toString() const = 0;
|
||||||
|
|
||||||
virtual const CGObjectInstance * targetObject() const { return nullptr; }
|
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)
|
if(boatNode->action == CGPathNode::UNKNOWN)
|
||||||
{
|
{
|
||||||
boatNode->specialAction = virtualBoat;
|
boatNode->addSpecialAction(virtualBoat);
|
||||||
destination.blocked = false;
|
destination.blocked = false;
|
||||||
destination.action = CGPathNode::ENodeAction::EMBARK;
|
destination.action = CGPathNode::ENodeAction::EMBARK;
|
||||||
destination.node = boatNode;
|
destination.node = boatNode;
|
||||||
|
@ -157,7 +157,7 @@ namespace AIPathfinding
|
|||||||
|
|
||||||
nodeStorage->updateAINode(destination.node, [&](AIPathNode * node)
|
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(loss < actualArmyValue)
|
||||||
{
|
{
|
||||||
|
if(destNode->specialAction)
|
||||||
|
{
|
||||||
|
battleNode->specialAction = destNode->specialAction;
|
||||||
|
}
|
||||||
|
|
||||||
destination.node = battleNode;
|
destination.node = battleNode;
|
||||||
nodeStorage->commit(destination, source);
|
nodeStorage->commit(destination, source);
|
||||||
|
|
||||||
@ -288,7 +293,7 @@ namespace AIPathfinding
|
|||||||
|
|
||||||
AIPreviousNodeRule(nodeStorage).process(source, destination, pathfinderConfig, pathfinderHelper);
|
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
|
#if NKAI_PATHFINDER_TRACE_LEVEL >= 1
|
||||||
logAi->trace(
|
logAi->trace(
|
||||||
|
Loading…
Reference in New Issue
Block a user