mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-24 08:32:34 +02:00
Nullkiller AI: new prioritization engine
This commit is contained in:
parent
66ed1a2901
commit
b261734905
@ -97,7 +97,7 @@ Goals::TGoalVec CaptureObjectsBehavior::getTasks()
|
||||
continue;
|
||||
|
||||
auto hero = path.targetHero;
|
||||
auto danger = path.getTotalDanger(hero);
|
||||
auto danger = path.getTotalDanger();
|
||||
|
||||
if(danger == 0 && path.exchangeCount > 1)
|
||||
continue;
|
||||
|
@ -206,6 +206,14 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
|
||||
path.movementCost(),
|
||||
path.toString());
|
||||
#endif
|
||||
if(path.turn() <= treat.turn - 2)
|
||||
{
|
||||
logAi->trace("Deffer defence of %s by %s because he has enough time to rich the town next trun",
|
||||
town->name,
|
||||
path.targetHero->name);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
float priority = basicPriority
|
||||
+ std::min(SAFE_ATTACK_CONSTANT, (float)path.getHeroStrength() / treat.danger) / (treat.turn + 1);
|
||||
|
@ -26,9 +26,9 @@ using namespace Goals;
|
||||
ExecuteHeroChain::ExecuteHeroChain(const AIPath & path, const CGObjectInstance * obj)
|
||||
:CGoal(Goals::EXECUTE_HERO_CHAIN), chainPath(path)
|
||||
{
|
||||
evaluationContext.danger = path.getTotalDanger(hero);
|
||||
evaluationContext.danger = path.getTotalDanger();
|
||||
evaluationContext.movementCost = path.movementCost();
|
||||
evaluationContext.armyLoss = path.armyLoss;
|
||||
evaluationContext.armyLoss = path.getTotalArmyLoss();
|
||||
evaluationContext.heroStrength = path.getHeroStrength();
|
||||
hero = path.targetHero;
|
||||
tile = path.targetTile();
|
||||
@ -112,8 +112,29 @@ void ExecuteHeroChain::accept(VCAI * ai)
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Goals::VisitTile(node.coord).sethero(hero).accept(ai);
|
||||
}
|
||||
catch(cannotFulfillGoalException)
|
||||
{
|
||||
if(hero->movement > 0)
|
||||
{
|
||||
CGPath path;
|
||||
bool isOk = cb->getPathsInfo(hero.get())->getPath(path, node.coord);
|
||||
|
||||
if(isOk && path.nodes.back().turns > 0)
|
||||
{
|
||||
logAi->warn("Hero %s has %d mp which is not enough to continue his way towards %s.", hero.name, hero->movement, node.coord.toString());
|
||||
|
||||
ai->nullkiller->lockHero(hero.get());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
if(node.turns == 0)
|
||||
{
|
||||
|
@ -875,6 +875,7 @@ std::vector<AIPath> AINodeStorage::getChainInfo(const int3 & pos, bool isOnLand)
|
||||
path.heroArmy = node.actor->creatureSet;
|
||||
path.armyLoss = node.armyLoss;
|
||||
path.targetObjectDanger = evaluateDanger(pos, path.targetHero);
|
||||
path.targetObjectArmyLoss = evaluateArmyLoss(path.targetHero, path.heroArmy->getArmyStrength(), path.targetObjectDanger);
|
||||
path.chainMask = node.actor->chainMask;
|
||||
path.exchangeCount = node.actor->actorExchangeCount;
|
||||
|
||||
@ -985,7 +986,7 @@ uint64_t AIPath::getHeroStrength() const
|
||||
return targetHero->getFightingStrength() * heroArmy->getArmyStrength();
|
||||
}
|
||||
|
||||
uint64_t AIPath::getTotalDanger(HeroPtr hero) const
|
||||
uint64_t AIPath::getTotalDanger() const
|
||||
{
|
||||
uint64_t pathDanger = getPathDanger();
|
||||
uint64_t danger = pathDanger > targetObjectDanger ? pathDanger : targetObjectDanger;
|
||||
@ -993,6 +994,11 @@ uint64_t AIPath::getTotalDanger(HeroPtr hero) const
|
||||
return danger;
|
||||
}
|
||||
|
||||
uint64_t AIPath::getTotalArmyLoss() const
|
||||
{
|
||||
return armyLoss + targetObjectArmyLoss;
|
||||
}
|
||||
|
||||
std::string AIPath::toString()
|
||||
{
|
||||
std::stringstream str;
|
||||
|
@ -49,6 +49,7 @@ struct AIPath
|
||||
std::shared_ptr<const ISpecialAction> specialAction;
|
||||
uint64_t targetObjectDanger;
|
||||
uint64_t armyLoss;
|
||||
uint64_t targetObjectArmyLoss;
|
||||
const CGHeroInstance * targetHero;
|
||||
const CCreatureSet * heroArmy;
|
||||
uint64_t chainMask;
|
||||
@ -60,7 +61,10 @@ struct AIPath
|
||||
uint64_t getPathDanger() const;
|
||||
|
||||
/// Gets danger of path including danger of visiting the target object like creature bank
|
||||
uint64_t getTotalDanger(HeroPtr hero) const;
|
||||
uint64_t getTotalDanger() const;
|
||||
|
||||
/// Gets danger of path including danger of visiting the target object like creature bank
|
||||
uint64_t getTotalArmyLoss() const;
|
||||
|
||||
int3 firstTileToGet() const;
|
||||
int3 targetTile() const;
|
||||
@ -168,6 +172,13 @@ public:
|
||||
return dangerEvaluator->evaluateDanger(tile, hero, ai);
|
||||
}
|
||||
|
||||
uint64_t evaluateArmyLoss(const CGHeroInstance * hero, uint64_t armyValue, uint64_t danger) const
|
||||
{
|
||||
double ratio = (double)danger / (armyValue * hero->getFightingStrength());
|
||||
|
||||
return (uint64_t)(armyValue * ratio * ratio * ratio);
|
||||
}
|
||||
|
||||
private:
|
||||
STRONG_INLINE
|
||||
void resetTile(const int3 & tile, EPathfindingLayer layer, CGPathNode::EAccessibility accessibility);
|
||||
|
@ -154,7 +154,7 @@ Goals::TGoalVec PathfindingManager::findPaths(
|
||||
#endif
|
||||
if(ai->isTileNotReserved(hero.get(), firstTileToGet))
|
||||
{
|
||||
danger = path.getTotalDanger(hero);
|
||||
danger = path.getTotalDanger();
|
||||
|
||||
if(isSafeToVisit(hero, path.heroArmy, danger))
|
||||
{
|
||||
@ -178,7 +178,7 @@ Goals::TGoalVec PathfindingManager::findPaths(
|
||||
solution->evaluationContext.danger = danger;
|
||||
|
||||
solution->evaluationContext.movementCost += path.movementCost();
|
||||
solution->evaluationContext.armyLoss += path.armyLoss;
|
||||
solution->evaluationContext.armyLoss += path.getTotalArmyLoss();
|
||||
solution->evaluationContext.heroStrength = path.getHeroStrength();
|
||||
#ifdef VCMI_TRACE_PATHFINDER
|
||||
logAi->trace("It's safe for %s to visit tile %s with danger %s, loss %s, army strength %s, goal %s",
|
||||
|
@ -163,9 +163,7 @@ namespace AIPathfinding
|
||||
auto hero = nodeStorage->getHero(source.node);
|
||||
auto danger = nodeStorage->evaluateDanger(destination.coord, hero);
|
||||
double actualArmyValue = srcNode->actor->armyValue - srcNode->armyLoss;
|
||||
double ratio = (double)danger / (actualArmyValue * hero->getFightingStrength());
|
||||
|
||||
uint64_t loss = (uint64_t)(actualArmyValue * ratio * ratio * ratio);
|
||||
double loss = nodeStorage->evaluateArmyLoss(hero, actualArmyValue, danger);
|
||||
|
||||
if(loss < actualArmyValue)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user