mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-24 08:32:34 +02:00
NKAI: fix defense tasks priority evaluation
This commit is contained in:
parent
06fcbf891b
commit
ab84cb9931
@ -70,7 +70,7 @@ void DangerHitMapAnalyzer::updateHitMap()
|
||||
auto turn = path.turn();
|
||||
auto & node = hitMap[pos.x][pos.y][pos.z];
|
||||
|
||||
if(tileDanger / (turn + 1) > node.maximumDanger.danger / (node.maximumDanger.turn + 1)
|
||||
if(tileDanger / (turn / 3 + 1) > node.maximumDanger.danger / (node.maximumDanger.turn / 3 + 1)
|
||||
|| (tileDanger == node.maximumDanger.danger && node.maximumDanger.turn > turn))
|
||||
{
|
||||
node.maximumDanger.danger = tileDanger;
|
||||
|
@ -244,7 +244,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
|
||||
continue;
|
||||
}
|
||||
|
||||
if(path.targetHero == town->visitingHero && path.exchangeCount == 1)
|
||||
if(path.targetHero == town->visitingHero.get() && path.exchangeCount == 1)
|
||||
{
|
||||
#if NKAI_TRACE_LEVEL >= 1
|
||||
logAi->trace("Put %s to garrison of town %s",
|
||||
@ -265,6 +265,24 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// main without army and visiting scout with army, very specific case
|
||||
if(town->visitingHero && town->getUpperArmy()->stacksCount() == 0
|
||||
&& path.targetHero != town->visitingHero.get() && path.exchangeCount == 1 && path.turn() == 0
|
||||
&& ai->nullkiller->heroManager->evaluateHero(path.targetHero) > ai->nullkiller->heroManager->evaluateHero(town->visitingHero.get())
|
||||
&& 10 * path.targetHero->getTotalStrength() < town->visitingHero->getTotalStrength())
|
||||
{
|
||||
path.heroArmy = town->visitingHero.get();
|
||||
|
||||
tasks.push_back(
|
||||
Goals::sptr(Composition()
|
||||
.addNext(DefendTown(town, treat, path))
|
||||
.addNext(ExchangeSwapTownHeroes(town, town->visitingHero.get()))
|
||||
.addNext(ExecuteHeroChain(path, town))
|
||||
.addNext(ExchangeSwapTownHeroes(town, path.targetHero, HeroLockedReason::DEFENCE))));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if(treat.turn == 0 || (path.turn() <= treat.turn && path.getHeroStrength() * SAFE_ATTACK_CONSTANT >= treat.danger))
|
||||
{
|
||||
|
@ -65,6 +65,7 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her
|
||||
{
|
||||
Goals::TGoalVec tasks;
|
||||
const int3 pos = hero->visitablePos();
|
||||
auto targetHeroScore = ai->nullkiller->heroManager->evaluateHero(hero);
|
||||
|
||||
#if NKAI_TRACE_LEVEL >= 1
|
||||
logAi->trace("Checking ways to gaher army for hero %s, %s", hero->getObjectName(), pos.toString());
|
||||
@ -113,7 +114,7 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her
|
||||
float armyValue = (float)heroExchange.getReinforcementArmyStrength() / hero->getArmyStrength();
|
||||
|
||||
// avoid transferring very small amount of army
|
||||
if(armyValue < 0.1f)
|
||||
if(armyValue < 0.1f && armyValue < 20000)
|
||||
{
|
||||
#if NKAI_TRACE_LEVEL >= 2
|
||||
logAi->trace("Army value is too small.");
|
||||
@ -122,31 +123,33 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her
|
||||
}
|
||||
|
||||
// avoid trying to move bigger army to the weaker one.
|
||||
if(armyValue > 1)
|
||||
bool hasOtherMainInPath = false;
|
||||
|
||||
for(auto node : path.nodes)
|
||||
{
|
||||
bool hasOtherMainInPath = false;
|
||||
if(!node.targetHero) continue;
|
||||
|
||||
for(auto node : path.nodes)
|
||||
auto heroRole = ai->nullkiller->heroManager->getHeroRole(node.targetHero);
|
||||
|
||||
if(heroRole == HeroRole::MAIN)
|
||||
{
|
||||
if(!node.targetHero) continue;
|
||||
auto score = ai->nullkiller->heroManager->evaluateHero(node.targetHero);
|
||||
|
||||
auto heroRole = ai->nullkiller->heroManager->getHeroRole(node.targetHero);
|
||||
|
||||
if(heroRole == HeroRole::MAIN)
|
||||
if(score >= targetHeroScore)
|
||||
{
|
||||
hasOtherMainInPath = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(hasOtherMainInPath)
|
||||
{
|
||||
if(hasOtherMainInPath)
|
||||
{
|
||||
#if NKAI_TRACE_LEVEL >= 2
|
||||
logAi->trace("Army value is too large.");
|
||||
logAi->trace("Army value is too large.");
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
auto danger = path.getTotalDanger();
|
||||
@ -180,7 +183,17 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her
|
||||
#if NKAI_TRACE_LEVEL >= 2
|
||||
logAi->trace("Action is blocked. Considering decomposition.");
|
||||
#endif
|
||||
composition.addNext(blockedAction->decompose(path.targetHero));
|
||||
auto subGoal = blockedAction->decompose(path.targetHero);
|
||||
|
||||
if(subGoal->invalid())
|
||||
{
|
||||
#if NKAI_TRACE_LEVEL >= 1
|
||||
logAi->trace("Path is invalid. Skipping");
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
composition.addNext(subGoal);
|
||||
}
|
||||
|
||||
tasks.push_back(sptr(composition));
|
||||
@ -261,7 +274,7 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const CGTownInstance * upgrader)
|
||||
|
||||
auto armyValue = (float)upgrade.upgradeValue / path.getHeroStrength();
|
||||
|
||||
if(armyValue < 0.25f || upgrade.upgradeValue < 300) // avoid small upgrades
|
||||
if((armyValue < 0.1f && armyValue < 20000) || upgrade.upgradeValue < 300) // avoid small upgrades
|
||||
{
|
||||
#if NKAI_TRACE_LEVEL >= 2
|
||||
logAi->trace("Ignore path. Army value is too small (%f)", armyValue);
|
||||
|
@ -299,6 +299,7 @@ void Nullkiller::makeTurn()
|
||||
|
||||
void Nullkiller::executeTask(Goals::TTask task)
|
||||
{
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
std::string taskDescr = task->toString();
|
||||
|
||||
boost::this_thread::interruption_point();
|
||||
@ -307,10 +308,11 @@ void Nullkiller::executeTask(Goals::TTask task)
|
||||
try
|
||||
{
|
||||
task->accept(ai.get());
|
||||
logAi->trace("Task %s completed in %lld", taskDescr, timeElapsed(start));
|
||||
}
|
||||
catch(goalFulfilledException &)
|
||||
{
|
||||
logAi->trace("Task %s completed", task->toString());
|
||||
logAi->trace("Task %s completed in %lld", taskDescr, timeElapsed(start));
|
||||
}
|
||||
catch(cannotFulfillGoalException & e)
|
||||
{
|
||||
|
@ -591,7 +591,7 @@ public:
|
||||
uint64_t upgradeValue = armyUpgrade.getUpgradeValue();
|
||||
|
||||
evaluationContext.armyReward += upgradeValue;
|
||||
evaluationContext.strategicalValue += upgradeValue / armyUpgrade.hero->getTotalStrength();
|
||||
evaluationContext.strategicalValue += upgradeValue / (float)armyUpgrade.hero->getArmyStrength();
|
||||
}
|
||||
};
|
||||
|
||||
@ -627,7 +627,7 @@ private:
|
||||
continue;
|
||||
|
||||
auto creature = creatureInfo.second.back().toCreature();
|
||||
result += creature->AIValue * town->getGrowthInfo(creature->level).totalGrowth();
|
||||
result += creature->AIValue * town->getGrowthInfo(creature->getLevel() - 1).totalGrowth();
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -648,6 +648,9 @@ public:
|
||||
|
||||
auto strategicalValue = std::sqrt(armyIncome / 20000.0f) + dailyIncome / 3000.0f;
|
||||
|
||||
if(evaluationContext.evaluator.ai->buildAnalyzer->getDevelopmentInfo().size() == 1)
|
||||
strategicalValue = 1;
|
||||
|
||||
float multiplier = 1;
|
||||
|
||||
if(treat.turn < defendTown.getTurn())
|
||||
|
Loading…
Reference in New Issue
Block a user