1
0
mirror of https://github.com/vcmi/vcmi.git synced 2026-05-22 09:55:17 +02:00

Merge pull request #3700 from vcmi/object-graph

NKAI: parallel capture objects
This commit is contained in:
Andrii Danylchenko
2024-04-01 12:59:08 +03:00
committed by GitHub
63 changed files with 434 additions and 415 deletions
+2 -1
View File
@@ -21,6 +21,7 @@ namespace NKAI
struct HeroPtr;
class AIGateway;
class FuzzyHelper;
class Nullkiller;
namespace Goals
{
@@ -128,7 +129,7 @@ namespace Goals
return const_cast<AbstractGoal *>(this);
}
virtual TGoalVec decompose() const
virtual TGoalVec decompose(const Nullkiller * ai) const
{
return TGoalVec();
}
+3 -3
View File
@@ -54,9 +54,9 @@ namespace Goals
virtual bool operator==(const T & other) const = 0;
TGoalVec decompose() const override
TGoalVec decompose(const Nullkiller * ai) const override
{
TSubgoal single = decomposeSingle();
TSubgoal single = decomposeSingle(ai);
if(!single || single->invalid())
return {};
@@ -65,7 +65,7 @@ namespace Goals
}
protected:
virtual TSubgoal decomposeSingle() const
virtual TSubgoal decomposeSingle(const Nullkiller * ai) const
{
return TSubgoal();
}
+2 -2
View File
@@ -35,9 +35,9 @@ std::string CaptureObject::toString() const
return "Capture " + name + " at " + tile.toString();
}
TGoalVec CaptureObject::decompose() const
TGoalVec CaptureObject::decompose(const Nullkiller * ai) const
{
return CaptureObjectsBehavior(cb->getObj(ObjectInstanceID(objid))).decompose();
return CaptureObjectsBehavior(ai->cb->getObj(ObjectInstanceID(objid))).decompose(ai);
}
}
+1 -1
View File
@@ -35,7 +35,7 @@ namespace Goals
}
bool operator==(const CaptureObject & other) const override;
Goals::TGoalVec decompose() const override;
Goals::TGoalVec decompose(const Nullkiller * ai) const override;
std::string toString() const override;
bool hasHash() const override { return true; }
uint64_t getHash() const override;
+34 -34
View File
@@ -29,36 +29,36 @@ std::string CompleteQuest::toString() const
return "Complete quest " + questToString();
}
TGoalVec CompleteQuest::decompose() const
TGoalVec CompleteQuest::decompose(const Nullkiller * ai) const
{
if(isKeyMaster(q))
{
return missionKeymaster();
return missionKeymaster(ai);
}
logAi->debug("Trying to realize quest: %s", questToString());
if(!q.quest->mission.artifacts.empty())
return missionArt();
return missionArt(ai);
if(!q.quest->mission.heroes.empty())
return missionHero();
return missionHero(ai);
if(!q.quest->mission.creatures.empty())
return missionArmy();
return missionArmy(ai);
if(q.quest->mission.resources.nonZero())
return missionResources();
return missionResources(ai);
if(q.quest->killTarget != ObjectInstanceID::NONE)
return missionDestroyObj();
return missionDestroyObj(ai);
for(auto & s : q.quest->mission.primary)
if(s)
return missionIncreasePrimaryStat();
return missionIncreasePrimaryStat(ai);
if(q.quest->mission.heroLevel > 0)
return missionLevel();
return missionLevel(ai);
return TGoalVec();
}
@@ -103,21 +103,21 @@ std::string CompleteQuest::questToString() const
return ms.toString();
}
TGoalVec CompleteQuest::tryCompleteQuest() const
TGoalVec CompleteQuest::tryCompleteQuest(const Nullkiller * ai) const
{
auto paths = ai->nullkiller->pathfinder->getPathInfo(q.obj->visitablePos());
auto paths = ai->pathfinder->getPathInfo(q.obj->visitablePos());
vstd::erase_if(paths, [&](const AIPath & path) -> bool
{
return !q.quest->checkQuest(path.targetHero);
});
return CaptureObjectsBehavior::getVisitGoals(paths, q.obj);
return CaptureObjectsBehavior::getVisitGoals(paths, ai, q.obj);
}
TGoalVec CompleteQuest::missionArt() const
TGoalVec CompleteQuest::missionArt(const Nullkiller * ai) const
{
TGoalVec solutions = tryCompleteQuest();
TGoalVec solutions = tryCompleteQuest(ai);
if(!solutions.empty())
return solutions;
@@ -132,9 +132,9 @@ TGoalVec CompleteQuest::missionArt() const
return solutions;
}
TGoalVec CompleteQuest::missionHero() const
TGoalVec CompleteQuest::missionHero(const Nullkiller * ai) const
{
TGoalVec solutions = tryCompleteQuest();
TGoalVec solutions = tryCompleteQuest(ai);
if(solutions.empty())
{
@@ -145,43 +145,43 @@ TGoalVec CompleteQuest::missionHero() const
return solutions;
}
TGoalVec CompleteQuest::missionArmy() const
TGoalVec CompleteQuest::missionArmy(const Nullkiller * ai) const
{
auto paths = ai->nullkiller->pathfinder->getPathInfo(q.obj->visitablePos());
auto paths = ai->pathfinder->getPathInfo(q.obj->visitablePos());
vstd::erase_if(paths, [&](const AIPath & path) -> bool
{
return !CQuest::checkMissionArmy(q.quest, path.heroArmy);
});
return CaptureObjectsBehavior::getVisitGoals(paths, q.obj);
return CaptureObjectsBehavior::getVisitGoals(paths, ai, q.obj);
}
TGoalVec CompleteQuest::missionIncreasePrimaryStat() const
TGoalVec CompleteQuest::missionIncreasePrimaryStat(const Nullkiller * ai) const
{
return tryCompleteQuest();
return tryCompleteQuest(ai);
}
TGoalVec CompleteQuest::missionLevel() const
TGoalVec CompleteQuest::missionLevel(const Nullkiller * ai) const
{
return tryCompleteQuest();
return tryCompleteQuest(ai);
}
TGoalVec CompleteQuest::missionKeymaster() const
TGoalVec CompleteQuest::missionKeymaster(const Nullkiller * ai) const
{
if(isObjectPassable(q.obj))
if(isObjectPassable(ai, q.obj))
{
return CaptureObjectsBehavior(q.obj).decompose();
return CaptureObjectsBehavior(q.obj).decompose(ai);
}
else
{
return CaptureObjectsBehavior().ofType(Obj::KEYMASTER, q.obj->subID).decompose();
return CaptureObjectsBehavior().ofType(Obj::KEYMASTER, q.obj->subID).decompose(ai);
}
}
TGoalVec CompleteQuest::missionResources() const
TGoalVec CompleteQuest::missionResources(const Nullkiller * ai) const
{
TGoalVec solutions = tryCompleteQuest();
TGoalVec solutions = tryCompleteQuest(ai);
/*auto heroes = cb->getHeroesInfo(); //TODO: choose best / free hero from among many possibilities?
@@ -208,14 +208,14 @@ TGoalVec CompleteQuest::missionResources() const
return solutions;
}
TGoalVec CompleteQuest::missionDestroyObj() const
TGoalVec CompleteQuest::missionDestroyObj(const Nullkiller * ai) const
{
auto obj = cb->getObj(q.quest->killTarget);
auto obj = ai->cb->getObj(q.quest->killTarget);
if(!obj)
return CaptureObjectsBehavior(q.obj).decompose();
return CaptureObjectsBehavior(q.obj).decompose(ai);
auto relations = cb->getPlayerRelations(ai->playerID, obj->tempOwner);
auto relations = ai->cb->getPlayerRelations(ai->playerID, obj->tempOwner);
//if(relations == PlayerRelations::SAME_PLAYER)
//{
@@ -226,7 +226,7 @@ TGoalVec CompleteQuest::missionDestroyObj() const
//else
if(relations == PlayerRelations::ENEMIES)
{
return CaptureObjectsBehavior(obj).decompose();
return CaptureObjectsBehavior(obj).decompose(ai);
}
return TGoalVec();
+10 -10
View File
@@ -29,7 +29,7 @@ namespace Goals
{
}
Goals::TGoalVec decompose() const override;
Goals::TGoalVec decompose(const Nullkiller * ai) const override;
std::string toString() const override;
bool hasHash() const override { return true; }
uint64_t getHash() const override;
@@ -37,15 +37,15 @@ namespace Goals
bool operator==(const CompleteQuest & other) const override;
private:
TGoalVec tryCompleteQuest() const;
TGoalVec missionArt() const;
TGoalVec missionHero() const;
TGoalVec missionArmy() const;
TGoalVec missionResources() const;
TGoalVec missionDestroyObj() const;
TGoalVec missionIncreasePrimaryStat() const;
TGoalVec missionLevel() const;
TGoalVec missionKeymaster() const;
TGoalVec tryCompleteQuest(const Nullkiller * ai) const;
TGoalVec missionArt(const Nullkiller * ai) const;
TGoalVec missionHero(const Nullkiller * ai) const;
TGoalVec missionArmy(const Nullkiller * ai) const;
TGoalVec missionResources(const Nullkiller * ai) const;
TGoalVec missionDestroyObj(const Nullkiller * ai) const;
TGoalVec missionIncreasePrimaryStat(const Nullkiller * ai) const;
TGoalVec missionLevel(const Nullkiller * ai) const;
TGoalVec missionKeymaster(const Nullkiller * ai) const;
std::string questToString() const;
};
}
+1 -1
View File
@@ -59,7 +59,7 @@ void Composition::accept(AIGateway * ai)
}
}
TGoalVec Composition::decompose() const
TGoalVec Composition::decompose(const Nullkiller * ai) const
{
TGoalVec result;
+1 -1
View File
@@ -32,7 +32,7 @@ namespace Goals
Composition & addNext(const AbstractGoal & goal);
Composition & addNext(TSubgoal goal);
Composition & addNextSequence(const TGoalVec & taskSequence);
TGoalVec decompose() const override;
TGoalVec decompose(const Nullkiller * ai) const override;
bool isElementar() const override;
int getHeroExchangeCount() const override;
};
+4 -4
View File
@@ -100,7 +100,7 @@ void ExecuteHeroChain::accept(AIGateway * ai)
throw cannotFulfillGoalException("Path is nondeterministic.");
}
node->specialAction->execute(hero);
node->specialAction->execute(ai, hero);
if(!heroPtr.validAndSet())
{
@@ -156,7 +156,7 @@ void ExecuteHeroChain::accept(AIGateway * ai)
{
try
{
if(moveHeroToTile(hero, node->coord))
if(moveHeroToTile(ai, hero, node->coord))
{
continue;
}
@@ -224,9 +224,9 @@ std::string ExecuteHeroChain::toString() const
return "ExecuteHeroChain " + targetName + " by " + chainPath.targetHero->getNameTranslated();
}
bool ExecuteHeroChain::moveHeroToTile(const CGHeroInstance * hero, const int3 & tile)
bool ExecuteHeroChain::moveHeroToTile(AIGateway * ai, const CGHeroInstance * hero, const int3 & tile)
{
if(tile == hero->visitablePos() && cb->getVisitableObjs(hero->visitablePos()).size() < 2)
if(tile == hero->visitablePos() && ai->myCb->getVisitableObjs(hero->visitablePos()).size() < 2)
{
logAi->warn("Why do I want to move hero %s to tile %s? Already standing on that tile! ", hero->getNameTranslated(), tile.toString());
+1 -2
View File
@@ -27,7 +27,6 @@ namespace Goals
ExecuteHeroChain(const AIPath & path, const CGObjectInstance * obj = nullptr);
void accept(AIGateway * ai) override;
std::string toString() const override;
bool operator==(const ExecuteHeroChain & other) const override;
@@ -36,7 +35,7 @@ namespace Goals
int getHeroExchangeCount() const override { return chainPath.exchangeCount; }
private:
bool moveHeroToTile(const CGHeroInstance * hero, const int3 & tile);
bool moveHeroToTile(AIGateway * ai, const CGHeroInstance * hero, const int3 & tile);
};
}
+1 -1
View File
@@ -27,7 +27,7 @@ namespace Goals
{
priority = -1;
}
TGoalVec decompose() const override
TGoalVec decompose(const Nullkiller * ai) const override
{
return TGoalVec();
}