mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-13 19:54:17 +02:00
Nullkiller: dismising and hiring hero in order to defend town
This commit is contained in:
committed by
Andrii Danylchenko
parent
84e5e6ac17
commit
e6eb9ccc03
@@ -134,7 +134,10 @@ Goals::TGoalVec CaptureObjectsBehavior::getTasks()
|
||||
way->evaluationContext.closestWayRatio
|
||||
= way->evaluationContext.movementCost / closestWay->evaluationContext.movementCost;
|
||||
|
||||
tasks.push_back(sptr(*way));
|
||||
if(way->hero && ai->nullkiller->canMove(way->hero.h))
|
||||
{
|
||||
tasks.push_back(sptr(*way));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@@ -16,6 +16,7 @@
|
||||
#include "../Goals/BuyArmy.h"
|
||||
#include "../Goals/VisitTile.h"
|
||||
#include "../Goals/ExecuteHeroChain.h"
|
||||
#include "../Goals/DismissHero.h"
|
||||
#include "../Goals/ExchangeSwapTownHeroes.h"
|
||||
#include "lib/mapping/CMap.h" //for victory conditions
|
||||
#include "lib/CPathfinder.h"
|
||||
@@ -109,13 +110,6 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
|
||||
|
||||
auto paths = ai->ah->getPathsToTile(town->visitablePos());
|
||||
|
||||
if(paths.empty())
|
||||
{
|
||||
logAi->debug("No ways to defend town %s", town->name);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for(auto & treat : treats)
|
||||
{
|
||||
logAi->debug(
|
||||
@@ -131,7 +125,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
|
||||
{
|
||||
if(path.getHeroStrength() > treat.danger)
|
||||
{
|
||||
if(dayOfWeek + treat.turn < 6 && isSafeToVisit(path.targetHero, path.heroArmy, treat.danger)
|
||||
if(path.turn() <= treat.turn && dayOfWeek + treat.turn < 6 && isSafeToVisit(path.targetHero, path.heroArmy, treat.danger)
|
||||
|| path.exchangeCount == 1 && path.turn() < treat.turn
|
||||
|| path.turn() < treat.turn - 1)
|
||||
{
|
||||
@@ -150,7 +144,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
|
||||
if(treatIsUnderControl)
|
||||
continue;
|
||||
|
||||
if(ai->canRecruitAnyHero(town))
|
||||
if(cb->getResourceAmount(Res::GOLD) > GameConstants::HERO_GOLD_COST)
|
||||
{
|
||||
auto heroesInTavern = cb->getAvailableHeroes(town);
|
||||
|
||||
@@ -158,12 +152,49 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
|
||||
{
|
||||
if(hero->getTotalStrength() > treat.danger)
|
||||
{
|
||||
tasks.push_back(Goals::sptr(Goals::RecruitHero().settown(town).setobjid(hero->id.getNum()).setpriority(1)));
|
||||
continue;
|
||||
auto myHeroes = cb->getHeroesInfo();
|
||||
|
||||
if(cb->getHeroesInfo().size() < ALLOWED_ROAMING_HEROES)
|
||||
{
|
||||
logAi->debug("Hero %s can be recruited to defend %s", hero->name, town->name);
|
||||
tasks.push_back(Goals::sptr(Goals::RecruitHero().settown(town).setobjid(hero->id.getNum()).setpriority(1)));
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
const CGHeroInstance * weakestHero = nullptr;
|
||||
|
||||
for(auto existingHero : myHeroes)
|
||||
{
|
||||
if(ai->nullkiller->isHeroLocked(existingHero)
|
||||
|| existingHero->getArmyStrength() > hero->getArmyStrength()
|
||||
|| ai->ah->getHeroRole(existingHero) == HeroRole::MAIN
|
||||
|| existingHero->movement
|
||||
|| existingHero->artifactsWorn.size() > (existingHero->hasSpellbook() ? 2 : 1))
|
||||
continue;
|
||||
|
||||
if(!weakestHero || weakestHero->getFightingStrength() > existingHero->getFightingStrength())
|
||||
{
|
||||
weakestHero = existingHero;
|
||||
}
|
||||
|
||||
if(weakestHero)
|
||||
{
|
||||
tasks.push_back(Goals::sptr(Goals::DismissHero(weakestHero)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(paths.empty())
|
||||
{
|
||||
logAi->debug("No ways to defend town %s", town->name);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
for(AIPath & path : paths)
|
||||
{
|
||||
#if AI_TRACE_LEVEL >= 1
|
||||
|
@@ -30,6 +30,7 @@ set(VCAI_SRCS
|
||||
Goals/BuildThis.cpp
|
||||
Goals/Explore.cpp
|
||||
Goals/GatherArmy.cpp
|
||||
Goals/DismissHero.cpp
|
||||
Goals/GatherTroops.cpp
|
||||
Goals/BuyArmy.cpp
|
||||
Goals/AdventureSpellCast.cpp
|
||||
@@ -96,6 +97,7 @@ set(VCAI_HEADERS
|
||||
Goals/BuildThis.h
|
||||
Goals/Explore.h
|
||||
Goals/GatherArmy.h
|
||||
Goals/DismissHero.h
|
||||
Goals/GatherTroops.h
|
||||
Goals/BuyArmy.h
|
||||
Goals/AdventureSpellCast.h
|
||||
|
@@ -31,6 +31,7 @@ public:
|
||||
void setActive(const CGHeroInstance * hero) { activeHero = hero; }
|
||||
void lockHero(const CGHeroInstance * hero) { lockedHeroes.insert(hero); }
|
||||
void unlockHero(const CGHeroInstance * hero) { lockedHeroes.erase(hero); }
|
||||
bool canMove(const CGHeroInstance * hero) { return hero->movement; }
|
||||
|
||||
private:
|
||||
void resetAiState();
|
||||
|
@@ -66,7 +66,8 @@ namespace Goals
|
||||
COMPLETE_QUEST,
|
||||
ADVENTURE_SPELL_CAST,
|
||||
EXECUTE_HERO_CHAIN,
|
||||
EXCHANGE_SWAP_TOWN_HEROES
|
||||
EXCHANGE_SWAP_TOWN_HEROES,
|
||||
DISMISS_HERO
|
||||
};
|
||||
|
||||
class DLL_EXPORT TSubgoal : public std::shared_ptr<AbstractGoal>
|
||||
|
55
AI/Nullkiller/Goals/DismissHero.cpp
Normal file
55
AI/Nullkiller/Goals/DismissHero.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* DismissHero.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 "DismissHero.h"
|
||||
#include "../VCAI.h"
|
||||
#include "../FuzzyHelper.h"
|
||||
#include "../AIhelper.h"
|
||||
#include "../../../lib/mapping/CMap.h" //for victory conditions
|
||||
#include "../../../lib/CPathfinder.h"
|
||||
|
||||
extern boost::thread_specific_ptr<CCallback> cb;
|
||||
extern boost::thread_specific_ptr<VCAI> ai;
|
||||
extern FuzzyHelper * fh;
|
||||
|
||||
using namespace Goals;
|
||||
|
||||
bool DismissHero::operator==(const DismissHero & other) const
|
||||
{
|
||||
return hero.h == other.hero.h;
|
||||
}
|
||||
|
||||
TSubgoal DismissHero::whatToDoToAchieve()
|
||||
{
|
||||
if(!hero.validAndSet())
|
||||
throw cannotFulfillGoalException("Invalid hero!");
|
||||
|
||||
return iAmElementar();
|
||||
}
|
||||
|
||||
void DismissHero::accept(VCAI * ai)
|
||||
{
|
||||
if(!hero.validAndSet())
|
||||
throw cannotFulfillGoalException("Invalid hero!");
|
||||
|
||||
cb->dismissHero(hero.h);
|
||||
|
||||
throw goalFulfilledException(sptr(*this));
|
||||
}
|
||||
|
||||
std::string DismissHero::name() const
|
||||
{
|
||||
return "DismissHero " + hero.name;
|
||||
}
|
||||
|
||||
std::string DismissHero::completeMessage() const
|
||||
{
|
||||
return "Hero dismissed successfully " + hero.name;
|
||||
}
|
36
AI/Nullkiller/Goals/DismissHero.h
Normal file
36
AI/Nullkiller/Goals/DismissHero.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* DismissHero.h, 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
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "CGoal.h"
|
||||
|
||||
namespace Goals
|
||||
{
|
||||
class DLL_EXPORT DismissHero : public CGoal<DismissHero>
|
||||
{
|
||||
public:
|
||||
DismissHero(HeroPtr hero)
|
||||
: CGoal(Goals::DISMISS_HERO)
|
||||
{
|
||||
sethero(hero);
|
||||
}
|
||||
|
||||
TGoalVec getAllPossibleSubgoals() override
|
||||
{
|
||||
return TGoalVec();
|
||||
}
|
||||
|
||||
TSubgoal whatToDoToAchieve() override;
|
||||
void accept(VCAI * ai) override;
|
||||
std::string name() const override;
|
||||
std::string completeMessage() const override;
|
||||
virtual bool operator==(const DismissHero & other) const override;
|
||||
};
|
||||
}
|
@@ -126,6 +126,10 @@ void ExecuteHeroChain::accept(VCAI * ai)
|
||||
return;
|
||||
}
|
||||
|
||||
// do not lock hero if it is simple one hero chain
|
||||
if(chainPath.exchangeCount == 1)
|
||||
return;
|
||||
|
||||
// no exception means we were not able to rich the tile
|
||||
ai->nullkiller->lockHero(hero.get());
|
||||
blockedIndexes.insert(node.parentIndex);
|
||||
|
@@ -2035,7 +2035,11 @@ void VCAI::tryRealize(Goals::Explore & g)
|
||||
|
||||
void VCAI::tryRealize(Goals::RecruitHero & g)
|
||||
{
|
||||
if(const CGTownInstance * t = findTownWithTavern())
|
||||
const CGTownInstance * t = g.town;
|
||||
|
||||
if(!t) t = findTownWithTavern();
|
||||
|
||||
if(t)
|
||||
{
|
||||
recruitHero(t, true);
|
||||
//TODO try to free way to blocked town
|
||||
|
Reference in New Issue
Block a user