1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-29 23:07:48 +02:00

AI: hero chain stabilisation

This commit is contained in:
Andrii Danylchenko
2021-05-15 21:56:08 +03:00
committed by Andrii Danylchenko
parent 3ffcef30f6
commit 37434dc4cf
5 changed files with 76 additions and 41 deletions

View File

@@ -76,6 +76,7 @@ void AINodeStorage::clear()
{
actors.clear();
heroChainPass = false;
heroChainTurn = 0;
}
const AIPathNode * AINodeStorage::getAINode(const CGPathNode * node) const
@@ -185,12 +186,13 @@ void AINodeStorage::commit(CDestinationNodeInfo & destination, const PathNodeInf
#ifdef VCMI_TRACE_PATHFINDER_EX
logAi->trace(
"Commited %s -> %s, cost: %f, hero: %s, mask: %i",
"Commited %s -> %s, cost: %f, hero: %s, mask: %x, army: %i",
source.coord.toString(),
destination.coord.toString(),
destination.cost,
dstNode->actor->toString(),
dstNode->actor->chainMask);
dstNode->actor->chainMask,
dstNode->actor->armyValue);
#endif
});
}
@@ -263,13 +265,13 @@ bool AINodeStorage::calculateHeroChain()
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)
if(node.turns <= heroChainTurn && node.action != CGPathNode::ENodeAction::UNKNOWN)
existingChains.push_back(&node);
}
for(AIPathNode * node : existingChains)
{
if(node->actor->hero)
if(node->actor->isMovable)
{
calculateHeroChain(node, existingChains, newChains);
}
@@ -301,8 +303,9 @@ void AINodeStorage::calculateHeroChain(
{
for(AIPathNode * node : variants)
{
if(node == srcNode || !node->actor || node->turns > heroChainMaxTurns
|| node->action == CGPathNode::ENodeAction::UNKNOWN && node->actor->hero)
if(node == srcNode || !node->actor || node->turns > heroChainTurn
|| node->action == CGPathNode::ENodeAction::UNKNOWN && node->actor->hero
|| (node->actor->chainMask & srcNode->actor->chainMask) != 0)
{
continue;
}
@@ -325,10 +328,7 @@ void AINodeStorage::calculateHeroChain(
AIPathNode * carrier,
AIPathNode * other,
std::vector<ExchangeCandidate> & result) const
{
if(!carrier->actor->isMovable)
return;
{
if(carrier->actor->canExchange(other->actor))
{
#ifdef VCMI_TRACE_PATHFINDER_EX
@@ -404,12 +404,13 @@ void AINodeStorage::addHeroChain(const std::vector<ExchangeCandidate> & result)
#ifdef VCMI_TRACE_PATHFINDER_EX
logAi->trace(
"Chain accepted at %s %s -> %s, mask %i, cost %f",
"Chain accepted at %s %s -> %s, mask %x, cost %f, army %i",
exchangeNode->coord.toString(),
other->actor->toString(),
exchangeNode->actor->toString(),
exchangeNode->actor->chainMask,
exchangeNode->cost);
exchangeNode->cost,
exchangeNode->actor->armyValue);
#endif
heroChain.push_back(exchangeNode);
}
@@ -496,7 +497,7 @@ void AINodeStorage::setTownsAndDwellings(
}
}
auto dayOfWeek = cb->getDate(Date::DAY_OF_WEEK);
/*auto dayOfWeek = cb->getDate(Date::DAY_OF_WEEK);
auto waitForGrowth = dayOfWeek > 4;
for(auto obj: visitableObjs)
@@ -524,7 +525,7 @@ void AINodeStorage::setTownsAndDwellings(
}
}
}
}
}*/
}
std::vector<CGPathNode *> AINodeStorage::calculateTeleportations(
@@ -636,44 +637,53 @@ bool AINodeStorage::hasBetterChain(const PathNodeInfo & source, CDestinationNode
template<class NodeRange>
bool AINodeStorage::hasBetterChain(
const CGPathNode * source,
const AIPathNode * destinationNode,
const AIPathNode * candidateNode,
const NodeRange & chains) const
{
auto dstActor = destinationNode->actor;
auto candidateActor = candidateNode->actor;
for(const AIPathNode & node : chains)
{
auto sameNode = node.actor == destinationNode->actor;
auto sameNode = node.actor == candidateNode->actor;
if(sameNode || node.action == CGPathNode::ENodeAction::UNKNOWN || !node.actor->hero)
{
continue;
}
if(node.danger <= destinationNode->danger && destinationNode->actor == node.actor->battleActor)
if(node.danger <= candidateNode->danger && candidateNode->actor == node.actor->battleActor)
{
if(node.cost < destinationNode->cost)
if(node.cost < candidateNode->cost)
{
#ifdef VCMI_TRACE_PATHFINDER
logAi->trace(
"Block ineficient move %s:->%s, mask=%i, mp diff: %i",
source->coord.toString(),
destinationNode->coord.toString(),
destinationNode->actor->chainMask,
node.moveRemains - destinationNode->moveRemains);
candidateNode->coord.toString(),
candidateNode->actor->chainMask,
node.moveRemains - candidateNode->moveRemains);
#endif
return true;
}
}
if(dstActor->actorExchangeCount == 1)
if(candidateActor->actorExchangeCount == 1
&& (candidateActor->chainMask & node.actor->chainMask) == 0)
continue;
auto nodeActor = node.actor;
auto nodeArmyValue = nodeActor->armyValue - node.armyLoss;
auto candidateArmyValue = candidateActor->armyValue - candidateNode->armyLoss;
if(nodeActor->armyValue - node.armyLoss >= dstActor->armyValue - destinationNode->armyLoss
&& nodeActor->heroFightingStrength >= dstActor->heroFightingStrength
&& node.cost >= destinationNode->cost)
if(nodeArmyValue > candidateArmyValue
&& node.cost <= candidateNode->cost)
{
return true;
}
if(nodeArmyValue == candidateArmyValue
&& nodeActor->heroFightingStrength >= candidateActor->heroFightingStrength
&& node.cost <= candidateNode->cost)
{
return true;
}