1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-16 10:19:47 +02:00
vcmi/AI/Nullkiller/Behaviors/RecruitHeroBehavior.cpp
Xilmi fdaac9d3c3 Hero-hiring
When we have no hero, we will definitely want to hire one.
We will also want to hire heroes who already pay for more than themselves by coming with an army that has more value than the hero costs.
2024-07-12 15:39:50 +02:00

101 lines
2.4 KiB
C++

/*
* RecruitHeroBehavior.cpp, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#include "StdInc.h"
#include "RecruitHeroBehavior.h"
#include "../AIGateway.h"
#include "../AIUtility.h"
#include "../Goals/RecruitHero.h"
#include "../Goals/ExecuteHeroChain.h"
namespace NKAI
{
using namespace Goals;
std::string RecruitHeroBehavior::toString() const
{
return "Recruit hero";
}
Goals::TGoalVec RecruitHeroBehavior::decompose(const Nullkiller * ai) const
{
Goals::TGoalVec tasks;
auto towns = ai->cb->getTownsInfo();
auto ourHeroes = ai->heroManager->getHeroRoles();
auto minScoreToHireMain = std::numeric_limits<float>::max();
for(auto hero : ourHeroes)
{
if(hero.second != HeroRole::MAIN)
continue;
auto newScore = ai->heroManager->evaluateHero(hero.first.get());
if(minScoreToHireMain > newScore)
{
// weakest main hero score
minScoreToHireMain = newScore;
}
}
// If we don't have any heros we might want to lower our expectations.
if (ourHeroes.empty())
minScoreToHireMain = 0;
for(auto town : towns)
{
if(ai->heroManager->canRecruitHero(town))
{
auto availableHeroes = ai->cb->getAvailableHeroes(town);
for(auto hero : availableHeroes)
{
auto score = ai->heroManager->evaluateHero(hero);
if(score > minScoreToHireMain || hero->getArmyCost() > GameConstants::HERO_GOLD_COST)
{
tasks.push_back(Goals::sptr(Goals::RecruitHero(town, hero).setpriority(200)));
break;
}
}
int treasureSourcesCount = 0;
for(auto obj : ai->objectClusterizer->getNearbyObjects())
{
if((obj->ID == Obj::RESOURCE)
|| obj->ID == Obj::TREASURE_CHEST
|| obj->ID == Obj::CAMPFIRE
|| isWeeklyRevisitable(ai, obj)
|| obj->ID ==Obj::ARTIFACT)
{
auto tile = obj->visitablePos();
auto closestTown = ai->dangerHitMap->getClosestTown(tile);
if(town == closestTown)
treasureSourcesCount++;
}
}
if(treasureSourcesCount < 5 && (town->garrisonHero || town->getUpperArmy()->getArmyStrength() < 10000))
continue;
if(ai->cb->getHeroesInfo().size() < ai->cb->getTownsInfo().size() + 1
|| (ai->getFreeResources()[EGameResID::GOLD] > 10000 && !ai->buildAnalyzer->isGoldPressureHigh()))
{
tasks.push_back(Goals::sptr(Goals::RecruitHero(town).setpriority(3)));
}
}
}
return tasks;
}
}