瀏覽代碼

Being less dismissive

Reduced the amount of circumstances under which the AI dismisses heroes. Among others to prevent a loop through all passes where it repeatedly hires and dismisses heroes.
Xilmi 1 年之前
父節點
當前提交
f2b8b40925

+ 2 - 1
AI/Nullkiller/Analyzers/HeroManager.cpp

@@ -284,7 +284,7 @@ const CGHeroInstance * HeroManager::findHeroWithGrail() const
 	return nullptr;
 }
 
-const CGHeroInstance * HeroManager::findWeakHeroToDismiss(uint64_t armyLimit) const
+const CGHeroInstance * HeroManager::findWeakHeroToDismiss(uint64_t armyLimit, const CGTownInstance* townToSpare) const
 {
 	const CGHeroInstance * weakestHero = nullptr;
 	auto myHeroes = ai->cb->getHeroesInfo();
@@ -295,6 +295,7 @@ const CGHeroInstance * HeroManager::findWeakHeroToDismiss(uint64_t armyLimit) co
 			|| existingHero->getArmyStrength() >armyLimit
 			|| getHeroRole(existingHero) == HeroRole::MAIN
 			|| existingHero->movementPointsRemaining()
+			|| (townToSpare != nullptr && existingHero->visitedTown == townToSpare)
 			|| existingHero->artifactsWorn.size() > (existingHero->hasSpellbook() ? 2 : 1))
 		{
 			continue;

+ 1 - 1
AI/Nullkiller/Analyzers/HeroManager.h

@@ -58,7 +58,7 @@ public:
 	bool canRecruitHero(const CGTownInstance * t = nullptr) const;
 	bool heroCapReached(bool includeGarrisoned = true) const;
 	const CGHeroInstance * findHeroWithGrail() const;
-	const CGHeroInstance * findWeakHeroToDismiss(uint64_t armyLimit) const;
+	const CGHeroInstance * findWeakHeroToDismiss(uint64_t armyLimit, const CGTownInstance * townToSpare = nullptr) const;
 	float getMagicStrength(const CGHeroInstance * hero) const;
 	float getFightingStrengthCached(const CGHeroInstance * hero) const;
 

+ 6 - 15
AI/Nullkiller/Behaviors/DefenceBehavior.cpp

@@ -354,21 +354,12 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
 			{
 				if(town->garrisonHero && town->garrisonHero != path.targetHero)
 				{
-					if(ai->heroManager->getHeroRole(town->visitingHero.get()) == HeroRole::SCOUT
-						&& town->visitingHero->getArmyStrength() < path.heroArmy->getArmyStrength() / 20)
-					{
-						if(path.turn() == 0)
-							sequence.push_back(sptr(DismissHero(town->visitingHero.get())));
-					}
-					else
-					{
 #if NKAI_TRACE_LEVEL >= 1
-						logAi->trace("Cancel moving %s to defend town %s as the town has garrison hero",
-							path.targetHero->getObjectName(),
-							town->getObjectName());
+					logAi->trace("Cancel moving %s to defend town %s as the town has garrison hero",
+						path.targetHero->getObjectName(),
+						town->getObjectName());
 #endif
-						continue;
-					}
+					continue;
 				}
 				else if(path.turn() == 0)
 				{
@@ -414,7 +405,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
 
 void DefenceBehavior::evaluateRecruitingHero(Goals::TGoalVec & tasks, const HitMapInfo & threat, const CGTownInstance * town, const Nullkiller * ai) const
 {
-	if (threat.turn > 0)
+	if (threat.turn > 0 || town->garrisonHero || town->visitingHero)
 		return;
 	
 	if(town->hasBuilt(BuildingID::TAVERN)
@@ -463,7 +454,7 @@ void DefenceBehavior::evaluateRecruitingHero(Goals::TGoalVec & tasks, const HitM
 			}
 			else if(ai->heroManager->heroCapReached())
 			{
-				heroToDismiss = ai->heroManager->findWeakHeroToDismiss(hero->getArmyStrength());
+				heroToDismiss = ai->heroManager->findWeakHeroToDismiss(hero->getArmyStrength(), town);
 
 				if(!heroToDismiss)
 					continue;