mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-13 19:54:17 +02:00
Nullkiller: capture guarded artifacts and other fixes
This commit is contained in:
committed by
Andrii Danylchenko
parent
1fd838a5b9
commit
5344df51c6
@@ -123,9 +123,6 @@ Goals::TGoalVec CaptureObjectsBehavior::getTasks()
|
||||
if(ai->nullkiller->arePathHeroesLocked(way->getPath()))
|
||||
continue;
|
||||
|
||||
if(ai->nullkiller->getHeroLockedReason(way->hero.get()) == HeroLockedReason::STARTUP)
|
||||
continue;
|
||||
|
||||
way->evaluationContext.closestWayRatio
|
||||
= closestWay->evaluationContext.movementCost / way->evaluationContext.movementCost;
|
||||
|
||||
@@ -149,7 +146,6 @@ Goals::TGoalVec CaptureObjectsBehavior::getTasks()
|
||||
bool CaptureObjectsBehavior::shouldVisitObject(ObjectIdRef obj) const
|
||||
{
|
||||
const CGObjectInstance* objInstance = obj;
|
||||
|
||||
if(!objInstance)
|
||||
return false;
|
||||
|
||||
@@ -162,6 +158,11 @@ bool CaptureObjectsBehavior::shouldVisitObject(ObjectIdRef obj) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(isObjectRemovable(obj))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const int3 pos = objInstance->visitablePos();
|
||||
|
||||
|
@@ -148,9 +148,6 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her
|
||||
if(ai->nullkiller->arePathHeroesLocked(way->getPath()))
|
||||
continue;
|
||||
|
||||
if(ai->nullkiller->getHeroLockedReason(way->hero.get()) == HeroLockedReason::STARTUP)
|
||||
continue;
|
||||
|
||||
way->evaluationContext.closestWayRatio = 1;
|
||||
|
||||
tasks.push_back(sptr(*way));
|
||||
@@ -246,9 +243,6 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const CGTownInstance * upgrader)
|
||||
if(ai->nullkiller->arePathHeroesLocked(way->getPath()))
|
||||
continue;
|
||||
|
||||
if(ai->nullkiller->getHeroLockedReason(way->hero.get()) == HeroLockedReason::STARTUP)
|
||||
continue;
|
||||
|
||||
way->evaluationContext.closestWayRatio = 1;
|
||||
|
||||
tasks.push_back(sptr(*way));
|
||||
|
@@ -69,12 +69,13 @@ Goals::TSubgoal Nullkiller::choseBestTask(std::shared_ptr<Behavior> behavior) co
|
||||
void Nullkiller::resetAiState()
|
||||
{
|
||||
lockedHeroes.clear();
|
||||
|
||||
dangerHitMap->reset();
|
||||
}
|
||||
|
||||
void Nullkiller::updateAiState()
|
||||
{
|
||||
activeHero = nullptr;
|
||||
|
||||
ai->validateVisitableObjs();
|
||||
dangerHitMap->updateHitMap();
|
||||
|
||||
@@ -94,17 +95,44 @@ void Nullkiller::updateAiState()
|
||||
buildAnalyzer->update();
|
||||
}
|
||||
|
||||
bool Nullkiller::isHeroLocked(const CGHeroInstance * hero) const
|
||||
{
|
||||
return getHeroLockedReason(hero) != HeroLockedReason::NOT_LOCKED;
|
||||
}
|
||||
|
||||
bool Nullkiller::arePathHeroesLocked(const AIPath & path) const
|
||||
{
|
||||
if(getHeroLockedReason(path.targetHero) == HeroLockedReason::STARTUP)
|
||||
{
|
||||
#if AI_TRACE_LEVEL >= 1
|
||||
logAi->trace("Hero %s is locked by STARTUP. Discarding %s", path.targetHero->name, path.toString());
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
for(auto & node : path.nodes)
|
||||
{
|
||||
if(isHeroLocked(node.targetHero))
|
||||
auto lockReason = getHeroLockedReason(node.targetHero);
|
||||
|
||||
if(lockReason != HeroLockedReason::NOT_LOCKED)
|
||||
{
|
||||
#if AI_TRACE_LEVEL >= 1
|
||||
logAi->trace("Hero %s is locked by STARTUP. Discarding %s", path.targetHero->name, path.toString());
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
HeroLockedReason Nullkiller::getHeroLockedReason(const CGHeroInstance * hero) const
|
||||
{
|
||||
auto found = lockedHeroes.find(hero);
|
||||
|
||||
return found != lockedHeroes.end() ? found->second : HeroLockedReason::NOT_LOCKED;
|
||||
}
|
||||
|
||||
void Nullkiller::makeTurn()
|
||||
{
|
||||
resetAiState();
|
||||
@@ -149,7 +177,7 @@ void Nullkiller::makeTurn()
|
||||
{
|
||||
if(bestTask->hero)
|
||||
{
|
||||
activeHero = bestTask->hero.get();
|
||||
setActive(bestTask->hero.get(), bestTask->tile);
|
||||
}
|
||||
|
||||
bestTask->accept(ai.get());
|
||||
|
@@ -34,6 +34,7 @@ class Nullkiller
|
||||
private:
|
||||
std::unique_ptr<PriorityEvaluator> priorityEvaluator;
|
||||
const CGHeroInstance * activeHero;
|
||||
int3 targetTile;
|
||||
std::map<const CGHeroInstance *, HeroLockedReason> lockedHeroes;
|
||||
|
||||
public:
|
||||
@@ -43,9 +44,11 @@ public:
|
||||
Nullkiller();
|
||||
void makeTurn();
|
||||
bool isActive(const CGHeroInstance * hero) const { return activeHero == hero; }
|
||||
bool isHeroLocked(const CGHeroInstance * hero) const { return vstd::contains(lockedHeroes, hero); }
|
||||
HeroLockedReason getHeroLockedReason(const CGHeroInstance * hero) const { return isHeroLocked(hero) ? lockedHeroes.at(hero) : HeroLockedReason::NOT_LOCKED; }
|
||||
void setActive(const CGHeroInstance * hero) { activeHero = hero; }
|
||||
bool isHeroLocked(const CGHeroInstance * hero) const;
|
||||
HeroPtr getActiveHero() { return activeHero; }
|
||||
HeroLockedReason getHeroLockedReason(const CGHeroInstance * hero) const;
|
||||
int3 getTargetTile() const { return targetTile; }
|
||||
void setActive(const CGHeroInstance * hero, int3 tile) { activeHero = hero; targetTile = tile; }
|
||||
void lockHero(const CGHeroInstance * hero, HeroLockedReason lockReason) { lockedHeroes[hero] = lockReason; }
|
||||
void unlockHero(const CGHeroInstance * hero) { lockedHeroes.erase(hero); }
|
||||
bool arePathHeroesLocked(const AIPath & path) const;
|
||||
|
@@ -289,6 +289,15 @@ ui64 FuzzyHelper::evaluateDanger(const CGObjectInstance * obj, const VCAI * ai)
|
||||
const CGTownInstance * cre = dynamic_cast<const CGTownInstance *>(obj);
|
||||
return cre->getUpperArmy()->getArmyStrength();
|
||||
}
|
||||
case Obj::ARTIFACT:
|
||||
case Obj::RESOURCE:
|
||||
{
|
||||
if(!vstd::contains(ai->alreadyVisited, obj))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
// passthrough
|
||||
}
|
||||
case Obj::MONSTER:
|
||||
case Obj::HERO:
|
||||
case Obj::GARRISON:
|
||||
|
@@ -88,7 +88,7 @@ void ExecuteHeroChain::accept(VCAI * ai)
|
||||
{
|
||||
if(hero->movement)
|
||||
{
|
||||
ai->nullkiller->setActive(hero.get());
|
||||
ai->nullkiller->setActive(hero.get(), node.coord);
|
||||
|
||||
if(node.specialAction)
|
||||
{
|
||||
|
@@ -652,8 +652,34 @@ void VCAI::showBlockingDialog(const std::string & text, const std::vector<Compon
|
||||
if(selection) //select from multiple components -> take the last one (they're indexed [1-size])
|
||||
sel = components.size();
|
||||
|
||||
if(!selection && cancel) //yes&no -> always answer yes, we are a brave AI :)
|
||||
sel = 1;
|
||||
if(!selection && cancel)
|
||||
{
|
||||
requestActionASAP([=]()
|
||||
{
|
||||
//yes&no -> always answer yes, we are a brave AI :)
|
||||
auto answer = 1;
|
||||
if(nullkiller)
|
||||
{
|
||||
auto hero = nullkiller->getActiveHero();
|
||||
auto target = nullkiller->getTargetTile();
|
||||
|
||||
if(hero.validAndSet() && target.valid())
|
||||
{
|
||||
auto ratio = (float)fh->evaluateDanger(target, hero.get()) / (float)hero->getTotalStrength();
|
||||
bool dangerUnknown = ratio == 0;
|
||||
bool dangerTooHigh = ratio > (1 / SAFE_ATTACK_CONSTANT);
|
||||
|
||||
logAi->trace("Guarded object query hook: %s by %s danger ratio %f", target.toString(), hero.name, ratio);
|
||||
|
||||
if(text.find("guarded") >= 0 && (dangerUnknown || dangerTooHigh))
|
||||
answer = 0; // no
|
||||
}
|
||||
}
|
||||
|
||||
answerQuery(askID, answer);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Find better way to understand it is Chest of Treasures
|
||||
if(components.size() == 2 && components.front().id == Component::RESOURCE)
|
||||
|
Reference in New Issue
Block a user