1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00

AI pathfinding loss evaluation

This commit is contained in:
Andrii Danylchenko 2021-05-15 19:23:01 +03:00 committed by Andrii Danylchenko
parent 594d1684e9
commit 1e4a086bb1
5 changed files with 37 additions and 25 deletions

View File

@ -70,7 +70,7 @@ void AINodeStorage::initialize(const PathfinderOptions & options, const CGameSta
}
}
void AINodeStorage::reset()
void AINodeStorage::clear()
{
actors.clear();
}
@ -148,6 +148,7 @@ void AINodeStorage::resetTile(const int3 & coord, EPathfindingLayer layer, CGPat
heroNode.danger = 0;
heroNode.manaCost = 0;
heroNode.specialAction.reset();
heroNode.armyLoss = 0;
heroNode.update(coord, layer, accessibility);
}
}
@ -165,6 +166,7 @@ void AINodeStorage::commit(CDestinationNodeInfo & destination, const PathNodeInf
dstNode->action = destination.action;
dstNode->theNodeBefore = srcNode->theNodeBefore;
dstNode->manaCost = srcNode->manaCost;
dstNode->armyLoss = srcNode->armyLoss;
if(dstNode->specialAction && dstNode->actor)
{
@ -213,7 +215,7 @@ const std::set<const CGHeroInstance *> AINodeStorage::getAllHeroes() const
for(auto actor : actors)
{
if(actor->hero)
heroes.insert(hero);
heroes.insert(actor->hero);
}
return heroes;
@ -255,7 +257,7 @@ std::vector<CGPathNode *> AINodeStorage::calculateTeleportations(
}
}
if(hero->getPosition(false) == source.coord)
if(source.isInitialPosition)
{
calculateTownPortalTeleportations(source, neighbours);
}
@ -270,6 +272,7 @@ void AINodeStorage::calculateTownPortalTeleportations(
SpellID spellID = SpellID::TOWN_PORTAL;
const CSpell * townPortal = spellID.toSpell();
auto srcNode = getAINode(source.node);
auto hero = srcNode->actor->hero;
if(hero->canCastThisSpell(townPortal) && hero->mana >= hero->getSpellCost(townPortal))
{
@ -384,11 +387,10 @@ std::vector<AIPath> AINodeStorage::getChainInfo(const int3 & pos, bool isOnLand)
{
std::vector<AIPath> paths;
auto chains = nodes[pos.x][pos.y][pos.z][isOnLand ? EPathfindingLayer::LAND : EPathfindingLayer::SAIL];
auto initialPos = hero->visitablePos();
for(const AIPathNode & node : chains)
{
if(node.action == CGPathNode::ENodeAction::UNKNOWN || !node.actor)
if(node.action == CGPathNode::ENodeAction::UNKNOWN || !node.actor || !node.actor->hero)
{
continue;
}
@ -397,6 +399,7 @@ std::vector<AIPath> AINodeStorage::getChainInfo(const int3 & pos, bool isOnLand)
const AIPathNode * current = &node;
path.targetHero = node.actor->hero;
auto initialPos = path.targetHero->visitablePos();
while(current != nullptr && current->coord != initialPos)
{
@ -412,7 +415,7 @@ std::vector<AIPath> AINodeStorage::getChainInfo(const int3 & pos, bool isOnLand)
current = getAINode(current->theNodeBefore);
}
path.targetObjectDanger = evaluateDanger(pos);
path.targetObjectDanger = evaluateDanger(pos, path.targetHero);
paths.push_back(path);
}
@ -471,6 +474,7 @@ ChainActor::ChainActor(const CGHeroInstance * hero, int chainMask)
layer = hero->boat ? EPathfindingLayer::SAIL : EPathfindingLayer::LAND;
initialMovement = hero->movement;
initialTurn = 0;
armyValue = hero->getTotalStrength();
setupSpecialActors();
}
@ -500,7 +504,7 @@ void ChainActor::setupSpecialActors()
allActors.push_back(&specialActor);
}
for(int i = 0; i <= 8; i++)
for(int i = 0; i < 8; i++)
{
ChainActor * actor = allActors[i];

View File

@ -40,6 +40,7 @@ public:
EPathfindingLayer layer;
uint32_t initialMovement;
uint32_t initialTurn;
uint64_t armyValue;
ChainActor()
{
@ -51,6 +52,7 @@ public:
struct AIPathNode : public CGPathNode
{
uint64_t danger;
uint64_t armyLoss;
uint32_t manaCost;
std::shared_ptr<const ISpecialAction> specialAction;
const ChainActor * actor;
@ -93,7 +95,6 @@ private:
boost::multi_array<AIPathNode, 5> nodes;
const CPlayerSpecificInfoCallback * cb;
const VCAI * ai;
const CGHeroInstance * hero;
std::unique_ptr<FuzzyHelper> dangerEvaluator;
std::vector<std::shared_ptr<ChainActor>> actors;
@ -137,9 +138,9 @@ public:
const std::set<const CGHeroInstance *> getAllHeroes() const;
void reset();
void clear();
uint64_t evaluateDanger(const int3 & tile) const
uint64_t evaluateDanger(const int3 & tile, const CGHeroInstance * hero) const
{
return dangerEvaluator->evaluateDanger(tile, hero, ai);
}

View File

@ -52,7 +52,7 @@ void AIPathfinder::updatePaths(std::vector<HeroPtr> heroes)
logAi->debug("Recalculate all paths");
storage.reset();
storage->clear();
storage->setHeroes(heroes, ai);
auto config = std::make_shared<AIPathfinding::AIPathfinderConfig>(cb, ai, storage);

View File

@ -13,7 +13,7 @@
#include "../../AIUtility.h"
#include "../../Goals/AbstractGoal.h"
class AIPathNode;
struct AIPathNode;
class ISpecialAction
{

View File

@ -121,15 +121,21 @@ namespace AIPathfinding
return;
}
auto danger = nodeStorage->evaluateDanger(destination.coord);
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;
uint64_t loss = (uint64_t)(actualArmyValue * ratio * ratio * ratio);
if(loss < actualArmyValue)
{
destination.node = battleNode;
nodeStorage->commit(destination, source);
if(battleNode->danger < danger)
{
battleNode->danger = danger;
}
battleNode->armyLoss += loss;
vstd::amax(battleNode->danger, danger);
battleNode->specialAction = std::make_shared<BattleAction>(destination.coord);
#ifdef VCMI_TRACE_PATHFINDER
@ -141,6 +147,7 @@ namespace AIPathfinding
#endif
return;
}
}
destination.blocked = true;
}