mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
NKAI: hire retreated hero
This commit is contained in:
parent
82a9f82e1c
commit
153cccdf46
@ -1401,7 +1401,7 @@ void AIGateway::tryRealize(Goals::Trade & g) //trade
|
||||
const CGTownInstance * AIGateway::findTownWithTavern() const
|
||||
{
|
||||
for(const CGTownInstance * t : cb->getTownsInfo())
|
||||
if(t->hasBuilt(BuildingID::TAVERN) && !t->visitingHero)
|
||||
if(t->hasBuilt(BuildingID::TAVERN) && (!t->visitingHero || !t->garrisonHero))
|
||||
return t;
|
||||
|
||||
return nullptr;
|
||||
@ -1432,34 +1432,6 @@ void AIGateway::buildArmyIn(const CGTownInstance * t)
|
||||
moveCreaturesToHero(t);
|
||||
}
|
||||
|
||||
void AIGateway::recruitHero(const CGTownInstance * t, bool throwing)
|
||||
{
|
||||
logAi->debug("Trying to recruit a hero in %s at %s", t->name, t->visitablePos().toString());
|
||||
|
||||
auto heroes = cb->getAvailableHeroes(t);
|
||||
if(heroes.size())
|
||||
{
|
||||
auto hero = heroes[0];
|
||||
if(heroes.size() >= 2) //makes sense to recruit two heroes with starting amries in first week
|
||||
{
|
||||
if(heroes[1]->getTotalStrength() > hero->getTotalStrength())
|
||||
hero = heroes[1];
|
||||
}
|
||||
|
||||
cb->recruitHero(t, hero);
|
||||
nullkiller->heroManager->update();
|
||||
|
||||
if(t->visitingHero)
|
||||
moveHeroToTile(t->visitablePos(), t->visitingHero.get());
|
||||
|
||||
throw goalFulfilledException(sptr(Goals::RecruitHero(t)));
|
||||
}
|
||||
else if(throwing)
|
||||
{
|
||||
throw cannotFulfillGoalException("No available heroes in tavern in " + t->nodeName());
|
||||
}
|
||||
}
|
||||
|
||||
void AIGateway::finish()
|
||||
{
|
||||
//we want to lock to avoid multiple threads from calling makingTurn->join() at same time
|
||||
|
@ -177,7 +177,6 @@ public:
|
||||
void endTurn();
|
||||
|
||||
// TODO: all the routines like recruiting hero or building army should be removed from here and extracted to elementar goals or whatever
|
||||
void recruitHero(const CGTownInstance * t, bool throwing = false);
|
||||
void recruitCreatures(const CGDwelling * d, const CArmedInstance * recruiter);
|
||||
void pickBestCreatures(const CArmedInstance * army, const CArmedInstance * source); //called when we can't find a slot for new stack
|
||||
void pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * other = nullptr);
|
||||
|
@ -34,10 +34,40 @@ Goals::TGoalVec RecruitHeroBehavior::decompose() const
|
||||
Goals::TGoalVec tasks;
|
||||
auto towns = cb->getTownsInfo();
|
||||
|
||||
auto ourHeroes = ai->nullkiller->heroManager->getHeroRoles();
|
||||
auto minScoreToHireMain = std::numeric_limits<float>::max();
|
||||
|
||||
for(auto hero : ourHeroes)
|
||||
{
|
||||
if(hero.second != HeroRole::MAIN)
|
||||
continue;
|
||||
|
||||
auto newScore = ai->nullkiller->heroManager->evaluateHero(hero.first.get());
|
||||
|
||||
if(minScoreToHireMain > newScore)
|
||||
{
|
||||
// weakest main hero score
|
||||
minScoreToHireMain = newScore;
|
||||
}
|
||||
}
|
||||
|
||||
for(auto town : towns)
|
||||
{
|
||||
if(!town->garrisonHero && !town->visitingHero && ai->canRecruitAnyHero(town))
|
||||
if((!town->garrisonHero || !town->visitingHero) && ai->canRecruitAnyHero(town))
|
||||
{
|
||||
auto availableHeroes = cb->getAvailableHeroes(town);
|
||||
|
||||
for(auto hero : availableHeroes)
|
||||
{
|
||||
auto score = ai->nullkiller->heroManager->evaluateHero(hero);
|
||||
|
||||
if(score > minScoreToHireMain)
|
||||
{
|
||||
tasks.push_back(Goals::sptr(Goals::RecruitHero(town, hero).setpriority(200)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(cb->getHeroesInfo().size() < cb->getTownsInfo().size() + 1
|
||||
|| (ai->nullkiller->getFreeResources()[Res::GOLD] > 10000
|
||||
&& ai->nullkiller->buildAnalyzer->getGoldPreasure() < MAX_GOLD_PEASURE))
|
||||
|
@ -35,16 +35,47 @@ void RecruitHero::accept(AIGateway * ai)
|
||||
|
||||
if(!t) t = ai->findTownWithTavern();
|
||||
|
||||
if(t)
|
||||
{
|
||||
ai->recruitHero(t, true);
|
||||
//TODO try to free way to blocked town
|
||||
//TODO: adventure map tavern or prison?
|
||||
}
|
||||
else
|
||||
if(!t)
|
||||
{
|
||||
throw cannotFulfillGoalException("No town to recruit hero!");
|
||||
}
|
||||
|
||||
logAi->debug("Trying to recruit a hero in %s at %s", t->name, t->visitablePos().toString());
|
||||
|
||||
auto heroes = cb->getAvailableHeroes(t);
|
||||
|
||||
if(!heroes.size())
|
||||
{
|
||||
throw cannotFulfillGoalException("No available heroes in tavern in " + t->nodeName());
|
||||
}
|
||||
|
||||
auto heroToHire = heroes[0];
|
||||
|
||||
for(auto hero : heroes)
|
||||
{
|
||||
if(objid == hero->id.getNum())
|
||||
{
|
||||
heroToHire = hero;
|
||||
break;
|
||||
}
|
||||
|
||||
if(hero->getTotalStrength() > heroToHire->getTotalStrength())
|
||||
heroToHire = hero;
|
||||
}
|
||||
|
||||
if(t->visitingHero)
|
||||
{
|
||||
if(t->garrisonHero)
|
||||
throw cannotFulfillGoalException("Town " + t->nodeName() + " is occupied. Cannot recruit hero!");
|
||||
|
||||
cb->swapGarrisonHero(t);
|
||||
}
|
||||
|
||||
cb->recruitHero(t, heroToHire);
|
||||
ai->nullkiller->heroManager->update();
|
||||
|
||||
if(t->visitingHero)
|
||||
ai->moveHeroToTile(t->visitablePos(), t->visitingHero.get());
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user