From fa9e1d2d83aa7577f3ddac30d82024997584e056 Mon Sep 17 00:00:00 2001 From: Andrii Danylchenko Date: Sat, 11 Mar 2023 13:54:05 +0200 Subject: [PATCH] NKAI: fix crash --- AI/Nullkiller/Analyzers/ArmyManager.cpp | 4 ++- .../Behaviors/GatherArmyBehavior.cpp | 7 +++-- AI/Nullkiller/Pathfinding/Actors.cpp | 29 +++++++++++-------- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/AI/Nullkiller/Analyzers/ArmyManager.cpp b/AI/Nullkiller/Analyzers/ArmyManager.cpp index 0a876bbe9..05c1ecc68 100644 --- a/AI/Nullkiller/Analyzers/ArmyManager.cpp +++ b/AI/Nullkiller/Analyzers/ArmyManager.cpp @@ -182,8 +182,10 @@ std::vector ArmyManager::getBestArmy(const IBonusBearer * armyCarrier, { auto weakest = getWeakestCreature(resultingArmy); - if(weakest != resultingArmy.end() && weakest->count == 1) //we check iterator validity for playing with settings that allow 0 stacks armies + if(weakest->count == 1) { + assert(resultingArmy.size() > 1); + resultingArmy.erase(weakest); } else diff --git a/AI/Nullkiller/Behaviors/GatherArmyBehavior.cpp b/AI/Nullkiller/Behaviors/GatherArmyBehavior.cpp index 2ed9e21f1..b1a46d555 100644 --- a/AI/Nullkiller/Behaviors/GatherArmyBehavior.cpp +++ b/AI/Nullkiller/Behaviors/GatherArmyBehavior.cpp @@ -250,10 +250,13 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const CGTownInstance * upgrader) auto upgrade = ai->nullkiller->armyManager->calculateCreaturesUpgrade(path.heroArmy, upgrader, availableResources); - if(ai->nullkiller->heroManager->getHeroRole(path.targetHero) == HeroRole::MAIN) + if(!upgrader->garrisonHero && ai->nullkiller->heroManager->getHeroRole(path.targetHero) == HeroRole::MAIN) { upgrade.upgradeValue += - ai->nullkiller->armyManager->howManyReinforcementsCanGet(path.targetHero, path.heroArmy, upgrader); + ai->nullkiller->armyManager->howManyReinforcementsCanGet( + path.targetHero, + path.heroArmy, + upgrader->getUpperArmy()); } auto armyValue = (float)upgrade.upgradeValue / path.getHeroStrength(); diff --git a/AI/Nullkiller/Pathfinding/Actors.cpp b/AI/Nullkiller/Pathfinding/Actors.cpp index aedcc1e6b..81596c0bd 100644 --- a/AI/Nullkiller/Pathfinding/Actors.cpp +++ b/AI/Nullkiller/Pathfinding/Actors.cpp @@ -274,12 +274,12 @@ ExchangeResult HeroExchangeMap::tryExchangeNoLock(const ChainActor * other) return result; } - if(other->isMovable && other->armyValue <= actor->armyValue / 10 && other->armyValue < MIN_ARMY_STRENGTH_FOR_CHAIN) - return result; + if(other->isMovable && other->armyValue <= actor->armyValue / 10 && other->armyValue < MIN_ARMY_STRENGTH_FOR_CHAIN) + return result; - TResources availableResources = resources - actor->armyCost - other->armyCost; - HeroExchangeArmy * upgradedInitialArmy = tryUpgrade(actor->creatureSet, other->getActorObject(), availableResources); - HeroExchangeArmy * newArmy; + TResources availableResources = resources - actor->armyCost - other->armyCost; + HeroExchangeArmy * upgradedInitialArmy = tryUpgrade(actor->creatureSet, other->getActorObject(), availableResources); + HeroExchangeArmy * newArmy; if(other->creatureSet->Slots().size()) { @@ -303,20 +303,25 @@ ExchangeResult HeroExchangeMap::tryExchangeNoLock(const ChainActor * other) if(!newArmy) return result; - auto reinforcement = newArmy->getArmyStrength() - actor->creatureSet->getArmyStrength(); + auto newArmyStrength = newArmy->getArmyStrength(); + auto oldArmyStrength = actor->creatureSet->getArmyStrength(); -#if NKAI_PATHFINDER_TRACE_LEVEL >= 2 + if(newArmyStrength <= oldArmyStrength) return result; + + auto reinforcement = newArmyStrength - oldArmyStrength; + + #if NKAI_PATHFINDER_TRACE_LEVEL >= 2 logAi->trace( "Exchange %s->%s reinforcement: %d, %f%%", actor->toString(), other->toString(), reinforcement, 100.0f * reinforcement / actor->armyValue); -#endif + #endif - if(reinforcement <= actor->armyValue / 10 && reinforcement < MIN_ARMY_STRENGTH_FOR_CHAIN) - { - delete newArmy; + if(reinforcement <= actor->armyValue / 10 && reinforcement < MIN_ARMY_STRENGTH_FOR_CHAIN) + { + delete newArmy; return result; } @@ -365,7 +370,7 @@ HeroExchangeArmy * HeroExchangeMap::tryUpgrade( { auto buyArmy = ai->armyManager->getArmyAvailableToBuy(target, ai->cb->getTown(upgrader->id), resources); - for(auto creatureToBuy : buyArmy) + for(auto & creatureToBuy : buyArmy) { auto targetSlot = target->getSlotFor(creatureToBuy.cre);