diff --git a/AI/Nullkiller/AIhelper.cpp b/AI/Nullkiller/AIhelper.cpp index 07fb206cc..783f92143 100644 --- a/AI/Nullkiller/AIhelper.cpp +++ b/AI/Nullkiller/AIhelper.cpp @@ -148,9 +148,9 @@ std::vector AIhelper::getPathsToTile(const HeroPtr & hero, const int3 & return pathfindingManager->getPathsToTile(hero, tile); } -void AIhelper::updatePaths(std::vector heroes) +void AIhelper::updatePaths(std::vector heroes, bool useHeroChain) { - pathfindingManager->updatePaths(heroes); + pathfindingManager->updatePaths(heroes, useHeroChain); } void AIhelper::updatePaths(const HeroPtr & hero) diff --git a/AI/Nullkiller/AIhelper.h b/AI/Nullkiller/AIhelper.h index b3328ba93..ed8986b2b 100644 --- a/AI/Nullkiller/AIhelper.h +++ b/AI/Nullkiller/AIhelper.h @@ -60,7 +60,7 @@ public: Goals::TGoalVec howToVisitTile(const int3 & tile, bool allowGatherArmy = true) const override; Goals::TGoalVec howToVisitObj(ObjectIdRef obj, bool allowGatherArmy = true) const override; std::vector getPathsToTile(const HeroPtr & hero, const int3 & tile) const override; - void updatePaths(std::vector heroes) override; + void updatePaths(std::vector heroes, bool useHeroChain = false) override; void updatePaths(const HeroPtr & hero) override; STRONG_INLINE diff --git a/AI/Nullkiller/Engine/Nullkiller.cpp b/AI/Nullkiller/Engine/Nullkiller.cpp index 9d72bf5b0..1511a9363 100644 --- a/AI/Nullkiller/Engine/Nullkiller.cpp +++ b/AI/Nullkiller/Engine/Nullkiller.cpp @@ -26,6 +26,8 @@ Goals::TSubgoal Nullkiller::choseBestTask(Goals::TGoalVec tasks) Goals::TSubgoal Nullkiller::choseBestTask(Behavior & behavior) { + logAi->debug("Checking behavior %s", behavior.toString()); + auto tasks = behavior.getTasks(); if(tasks.empty()) @@ -51,7 +53,7 @@ void Nullkiller::makeTurn() { while(true) { - ai->ah->updatePaths(ai->getMyHeroes()); + ai->ah->updatePaths(ai->getMyHeroes(), true); Goals::TGoalVec bestTasks = { choseBestTask(CaptureObjectsBehavior()), @@ -71,6 +73,8 @@ void Nullkiller::makeTurn() try { + activeHero = bestTask->hero; + bestTask->accept(ai.get()); } catch(goalFulfilledException &) diff --git a/AI/Nullkiller/Engine/Nullkiller.h b/AI/Nullkiller/Engine/Nullkiller.h index 713842a18..f1edc6b63 100644 --- a/AI/Nullkiller/Engine/Nullkiller.h +++ b/AI/Nullkiller/Engine/Nullkiller.h @@ -8,10 +8,12 @@ class Nullkiller { private: std::unique_ptr priorityEvaluator; + HeroPtr activeHero; public: Nullkiller(); void makeTurn(); + bool isActive(const CGHeroInstance * hero) const { return activeHero.h == hero; } private: Goals::TSubgoal choseBestTask(Behavior & behavior); diff --git a/AI/Nullkiller/VCAI.cpp b/AI/Nullkiller/VCAI.cpp index 77cf6be5a..5013205bf 100644 --- a/AI/Nullkiller/VCAI.cpp +++ b/AI/Nullkiller/VCAI.cpp @@ -323,6 +323,13 @@ void VCAI::heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2, Q { logAi->debug("Heroes owned by different players. Do not exchange army or artifacts."); } + else if(nullkiller) + { + if(nullkiller->isActive(firstHero)) + transferFrom2to1(secondHero, firstHero); + else + transferFrom2to1(firstHero, secondHero); + } else if(goalpriority1 > goalpriority2) { transferFrom2to1(firstHero, secondHero); @@ -1172,7 +1179,8 @@ void VCAI::pickBestCreatures(const CArmedInstance * destinationArmy, const CArme { if(armyPtr->getCreature(SlotID(j)) == bestArmy[i] && (i != j || armyPtr != destinationArmy)) //it's a searched creature not in dst SLOT { - if(!(armyPtr->needsLastStack() && armyPtr->stacksCount() == 1)) //can't take away last creature without split + if(!armyPtr->needsLastStack() || armyPtr->stacksCount() != 1 + || armyPtr == destinationArmy || 0 < destinationArmy->getStackCount(SlotID(i))) //can't take away last creature without split { cb->mergeOrSwapStacks(armyPtr, destinationArmy, SlotID(j), SlotID(i)); }