1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-03-25 21:38:59 +02:00

AI: hero chain stabilisation

This commit is contained in:
Andrii Danylchenko 2021-05-15 21:54:28 +03:00 committed by Andrii Danylchenko
parent 3a0d9fe14e
commit 0e328ab3c2
6 changed files with 55 additions and 38 deletions

View File

@ -172,6 +172,12 @@ void AINodeStorage::commit(CDestinationNodeInfo & destination, const PathNodeInf
{
commit(dstNode, srcNode, destination.action, destination.turn, destination.movementLeft, destination.cost);
if(srcNode->specialAction || srcNode->chainOther)
{
// there is some action on source tile which should be performed before we can bypass it
destination.node->theNodeBefore = source.node;
}
if(dstNode->specialAction && dstNode->actor)
{
dstNode->specialAction->applyOnDestination(dstNode->actor->hero, destination, source, dstNode, srcNode);
@ -183,7 +189,7 @@ void AINodeStorage::commit(CDestinationNodeInfo & destination, const PathNodeInf
source.coord.toString(),
destination.coord.toString(),
destination.cost,
dstNode->actor->hero->name,
dstNode->actor->toString(),
dstNode->actor->chainMask);
#endif
});
@ -251,13 +257,19 @@ bool AINodeStorage::calculateHeroChain()
for(AIPathNode & node : chains)
{
if(node.coord.x == 60 && node.coord.y == 56 && node.actor)
logAi->trace(node.actor->toString());
if(node.turns <= heroChainMaxTurns && node.action != CGPathNode::ENodeAction::UNKNOWN)
buffer.push_back(&node);
}
for(AIPathNode * node : buffer)
{
addHeroChain(node, buffer);
if(node->actor->hero)
{
addHeroChain(node, buffer);
}
}
});
@ -277,9 +289,9 @@ void AINodeStorage::addHeroChain(AIPathNode * srcNode, std::vector<AIPathNode *>
#ifdef VCMI_TRACE_PATHFINDER_EX
logAi->trace(
"Thy exchange %s[%i] -> %s[%i] at %s",
node->actor->hero->name,
node->actor->toString(),
node->actor->chainMask,
srcNode->actor->hero->name,
srcNode->actor->toString(),
srcNode->actor->chainMask,
srcNode->coord.toString());
#endif
@ -299,9 +311,9 @@ void AINodeStorage::addHeroChain(AIPathNode * carrier, AIPathNode * other)
#ifdef VCMI_TRACE_PATHFINDER_EX
logAi->trace(
"Exchange allowed %s[%i] -> %s[%i] at %s",
other->actor->hero->name,
other->actor->toString(),
other->actor->chainMask,
carrier->actor->hero->name,
carrier->actor->toString(),
carrier->actor->chainMask,
carrier->coord.toString());
#endif
@ -344,8 +356,8 @@ void AINodeStorage::addHeroChain(AIPathNode * carrier, AIPathNode * other)
logAi->trace(
"Chain accepted at %s %s -> %s, mask %i, cost %f",
chainNode->coord.toString(),
other->actor->hero->name,
chainNode->actor->hero->name,
other->actor->toString(),
chainNode->actor->toString(),
chainNode->actor->chainMask,
chainNode->cost);
#endif
@ -430,7 +442,7 @@ void AINodeStorage::setHeroes(std::vector<HeroPtr> heroes, const VCAI * _ai)
void AINodeStorage::setTownsAndDwellings(
const std::vector<const CGTownInstance *> & towns,
const std::vector<const CGObjectInstance *> & visitableObjs)
const std::set<const CGObjectInstance *> & visitableObjs)
{
for(auto town : towns)
{

View File

@ -85,7 +85,7 @@ private:
public:
/// more than 1 chain layer for each hero allows us to have more than 1 path to each tile so we can chose more optimal one.
static const int NUM_CHAINS = 3 * GameConstants::MAX_HEROES_PER_PLAYER;
static const int NUM_CHAINS = 5 * GameConstants::MAX_HEROES_PER_PLAYER;
AINodeStorage(const int3 & sizes);
~AINodeStorage();
@ -116,7 +116,7 @@ public:
void setHeroes(std::vector<HeroPtr> heroes, const VCAI * ai);
void setTownsAndDwellings(
const std::vector<const CGTownInstance *> & towns,
const std::vector<const CGObjectInstance *> & visitableObjs);
const std::set<const CGObjectInstance *> & visitableObjs);
const CGHeroInstance * getHero(const CGPathNode * node) const;
const std::set<const CGHeroInstance *> getAllHeroes() const;
void clear();

View File

@ -56,6 +56,11 @@ void AIPathfinder::updatePaths(std::vector<HeroPtr> heroes, bool useHeroChain)
storage->clear();
storage->setHeroes(heroes, ai);
if(useHeroChain)
{
storage->setTownsAndDwellings(cb->getTownsInfo(), ai->visitableObjs);
}
auto config = std::make_shared<AIPathfinding::AIPathfinderConfig>(cb, ai, storage);
do {

View File

@ -16,23 +16,6 @@
#include "../../../lib/mapping/CMap.h"
#include "../../../lib/mapObjects/MapObjects.h"
class ExchangeAction : public ISpecialAction
{
private:
const CGHeroInstance * target;
const CGHeroInstance * source;
public:
ExchangeAction(const CGHeroInstance * target, const CGHeroInstance * source)
:target(target), source(source)
{ }
virtual Goals::TSubgoal whatToDo(const HeroPtr & hero) const override
{
return Goals::sptr(Goals::VisitHero(target->id.getNum()).sethero(hero));
}
};
ChainActor::ChainActor(const CGHeroInstance * hero, uint64_t chainMask)
:hero(hero), isMovable(true), chainMask(chainMask), creatureSet(hero),
baseActor(this), carrierParent(nullptr), otherParent(nullptr)
@ -60,6 +43,11 @@ ChainActor::ChainActor(const CGObjectInstance * obj, const CCreatureSet * creatu
armyValue = creatureSet->getArmyStrength();
}
std::string ChainActor::toString() const
{
return hero->name;
}
HeroActor::HeroActor(const CGHeroInstance * hero, uint64_t chainMask, const VCAI * ai)
:ChainActor(hero, chainMask)
{
@ -213,7 +201,8 @@ DwellingActor::DwellingActor(const CGDwelling * dwelling, uint64_t chainMask, bo
dwelling,
getDwellingCreatures(dwelling, waitForGrowth),
chainMask,
getInitialTurn(waitForGrowth, dayOfWeek))
getInitialTurn(waitForGrowth, dayOfWeek)),
dwelling(dwelling)
{
}
@ -230,6 +219,11 @@ int DwellingActor::getInitialTurn(bool waitForGrowth, int dayOfWeek)
return 8 - dayOfWeek;
}
std::string DwellingActor::toString() const
{
return dwelling->typeName + dwelling->visitablePos().toString();
}
CCreatureSet * DwellingActor::getDwellingCreatures(const CGDwelling * dwelling, bool waitForGrowth)
{
CCreatureSet * dwellingCreatures = new CCreatureSet();
@ -259,6 +253,11 @@ CCreatureSet * DwellingActor::getDwellingCreatures(const CGDwelling * dwelling,
}
TownGarrisonActor::TownGarrisonActor(const CGTownInstance * town, uint64_t chainMask)
:ChainActor(town, town->getUpperArmy(), chainMask, 0)
:ChainActor(town, town->getUpperArmy(), chainMask, 0), town(town)
{
}
std::string TownGarrisonActor::toString() const
{
return town->name;
}

View File

@ -48,6 +48,7 @@ public:
ChainActor(){}
virtual bool canExchange(const ChainActor * other) const;
virtual std::string toString() const;
ChainActor * exchange(const ChainActor * other) const { return exchange(this, other); }
void setBaseActor(HeroActor * base);
@ -102,9 +103,13 @@ protected:
class DwellingActor : public ChainActor
{
private:
const CGDwelling * dwelling;
public:
DwellingActor(const CGDwelling * dwelling, uint64_t chainMask, bool waitForGrowth, int dayOfWeek);
~DwellingActor();
virtual std::string toString() const override;
protected:
int getInitialTurn(bool waitForGrowth, int dayOfWeek);
@ -113,6 +118,10 @@ protected:
class TownGarrisonActor : public ChainActor
{
private:
const CGTownInstance * town;
public:
TownGarrisonActor(const CGTownInstance * town, uint64_t chainMask);
virtual std::string toString() const override;
};

View File

@ -35,13 +35,5 @@ namespace AIPathfinding
#endif
return;
}
auto srcNode = nodeStorage->getAINode(source.node);
if(srcNode->specialAction || srcNode->chainOther)
{
// there is some action on source tile which should be performed before we can bypass it
destination.node->theNodeBefore = source.node;
}
}
}