1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-29 23:07:48 +02:00

NKAI: improve army gathering

This commit is contained in:
Andrii Danylchenko
2023-03-05 15:42:15 +02:00
parent 8b0c7b6601
commit 148c3436df
7 changed files with 106 additions and 44 deletions

View File

@@ -45,8 +45,7 @@ Goals::TGoalVec GatherArmyBehavior::decompose() const
for(const CGHeroInstance * hero : heroes)
{
if(ai->nullkiller->heroManager->getHeroRole(hero) == HeroRole::MAIN
&& hero->getArmyStrength() >= 300)
if(ai->nullkiller->heroManager->getHeroRole(hero) == HeroRole::MAIN)
{
vstd::concatenate(tasks, deliverArmyToHero(hero));
}
@@ -70,13 +69,6 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Checking ways to gaher army for hero %s, %s", hero->getObjectName(), pos.toString());
#endif
if(ai->nullkiller->isHeroLocked(hero))
{
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Skipping locked hero %s, %s", hero->getObjectName(), pos.toString());
#endif
return tasks;
}
auto paths = ai->nullkiller->pathfinder->getPathInfo(pos);
@@ -92,6 +84,14 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her
if(path.containsHero(hero)) continue;
if(path.turn() == 0 && hero->inTownGarrison)
{
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Skipping garnisoned hero %s, %s", hero->getObjectName(), pos.toString());
#endif
continue;
}
if(ai->nullkiller->dangerHitMap->enemyCanKillOurHeroesAlongThePath(path))
{
#if NKAI_TRACE_LEVEL >= 2
@@ -124,14 +124,32 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her
// avoid trying to move bigger army to the weaker one.
if(armyValue > 1)
{
bool hasOtherMainInPath = false;
for(auto node : path.nodes)
{
if(!node.targetHero) continue;
auto heroRole = ai->nullkiller->heroManager->getHeroRole(node.targetHero);
if(heroRole == HeroRole::MAIN)
{
hasOtherMainInPath = true;
break;
}
}
if(hasOtherMainInPath)
{
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Army value is too large.");
logAi->trace("Army value is too large.");
#endif
continue;
continue;
}
}
auto danger = path.getTotalDanger();
auto isSafe = isSafeToVisit(hero, path.heroArmy, danger);
#if NKAI_TRACE_LEVEL >= 2
@@ -194,7 +212,7 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const CGTownInstance * upgrader)
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Path found %s", path.toString());
#endif
if(upgrader->visitingHero != path.targetHero)
if(upgrader->visitingHero && upgrader->visitingHero.get() != path.targetHero)
{
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Ignore path. Town has visiting hero.");
@@ -219,7 +237,10 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const CGTownInstance * upgrader)
continue;
}
if(ai->nullkiller->dangerHitMap->enemyCanKillOurHeroesAlongThePath(path))
auto heroRole = ai->nullkiller->heroManager->getHeroRole(path.targetHero);
if(heroRole == HeroRole::SCOUT
&& ai->nullkiller->dangerHitMap->enemyCanKillOurHeroesAlongThePath(path))
{
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Ignore path. Target hero can be killed by enemy. Our power %lld", path.heroArmy->getArmyStrength());
@@ -228,16 +249,22 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const CGTownInstance * upgrader)
}
auto upgrade = ai->nullkiller->armyManager->calculateCreaturesUpgrade(path.heroArmy, upgrader, availableResources);
auto armyValue = (float)upgrade.upgradeValue / path.getHeroStrength();
if(ai->nullkiller->heroManager->getHeroRole(path.targetHero) == HeroRole::MAIN)
{
upgrade.upgradeValue +=
ai->nullkiller->armyManager->howManyReinforcementsCanGet(path.targetHero, path.heroArmy, upgrader);
upgrade.upgradeValue +=
ai->nullkiller->armyManager->howManyReinforcementsCanGet(path.targetHero, path.heroArmy, upgrader);
}
if(armyValue < 0.1f || upgrade.upgradeValue < 300) // avoid small upgrades
auto armyValue = (float)upgrade.upgradeValue / path.getHeroStrength();
if(armyValue < 0.25f || upgrade.upgradeValue < 300) // avoid small upgrades
{
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Ignore path. Army value is too small (%f)", armyValue);
#endif
continue;
}
auto danger = path.getTotalDanger();