mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-29 23:07:48 +02:00
NKAI: reduce double army loss cases
This commit is contained in:
@@ -26,7 +26,12 @@ ExecuteHeroChain::ExecuteHeroChain(const AIPath & path, const CGObjectInstance *
|
|||||||
if(obj)
|
if(obj)
|
||||||
{
|
{
|
||||||
objid = obj->id.getNum();
|
objid = obj->id.getNum();
|
||||||
|
|
||||||
|
#if NKAI_TRACE_LEVEL >= 1
|
||||||
|
targetName = obj->getObjectName() + tile.toString();
|
||||||
|
#else
|
||||||
targetName = obj->typeName + tile.toString();
|
targetName = obj->typeName + tile.toString();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -260,7 +265,11 @@ void ExecuteHeroChain::accept(AIGateway * ai)
|
|||||||
|
|
||||||
std::string ExecuteHeroChain::toString() const
|
std::string ExecuteHeroChain::toString() const
|
||||||
{
|
{
|
||||||
|
#if NKAI_TRACE_LEVEL >= 1
|
||||||
|
return "ExecuteHeroChain " + targetName + " by " + chainPath.toString();
|
||||||
|
#else
|
||||||
return "ExecuteHeroChain " + targetName + " by " + chainPath.targetHero->getNameTranslated();
|
return "ExecuteHeroChain " + targetName + " by " + chainPath.targetHero->getNameTranslated();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExecuteHeroChain::moveHeroToTile(AIGateway * ai, const CGHeroInstance * hero, const int3 & tile)
|
bool ExecuteHeroChain::moveHeroToTile(AIGateway * ai, const CGHeroInstance * hero, const int3 & tile)
|
||||||
|
|||||||
@@ -1385,6 +1385,28 @@ void AINodeStorage::calculateChainInfo(std::vector<AIPath> & paths, const int3 &
|
|||||||
path.armyLoss = node.armyLoss;
|
path.armyLoss = node.armyLoss;
|
||||||
path.targetObjectDanger = evaluateDanger(pos, path.targetHero, !node.actor->allowBattle);
|
path.targetObjectDanger = evaluateDanger(pos, path.targetHero, !node.actor->allowBattle);
|
||||||
|
|
||||||
|
if(path.targetObjectDanger > 0)
|
||||||
|
{
|
||||||
|
if(node.theNodeBefore)
|
||||||
|
{
|
||||||
|
auto prevNode = getAINode(node.theNodeBefore);
|
||||||
|
|
||||||
|
if(node.coord == prevNode->coord && node.actor->hero == prevNode->actor->hero)
|
||||||
|
{
|
||||||
|
paths.pop_back();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
path.armyLoss = prevNode->armyLoss;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
path.armyLoss = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
path.targetObjectArmyLoss = evaluateArmyLoss(
|
path.targetObjectArmyLoss = evaluateArmyLoss(
|
||||||
path.targetHero,
|
path.targetHero,
|
||||||
getHeroArmyStrengthWithCommander(path.targetHero, path.heroArmy),
|
getHeroArmyStrengthWithCommander(path.targetHero, path.heroArmy),
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ void GraphPaths::dumpToLog() const
|
|||||||
node.previous.coord.toString(),
|
node.previous.coord.toString(),
|
||||||
tile.first.toString(),
|
tile.first.toString(),
|
||||||
node.cost,
|
node.cost,
|
||||||
node.danger);
|
node.linkDanger);
|
||||||
}
|
}
|
||||||
|
|
||||||
logBuilder.addLine(node.previous.coord, tile.first);
|
logBuilder.addLine(node.previous.coord, tile.first);
|
||||||
@@ -169,14 +169,17 @@ void GraphPaths::dumpToLog() const
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GraphPathNode::tryUpdate(const GraphPathNodePointer & pos, const GraphPathNode & prev, const ObjectLink & link)
|
bool GraphPathNode::tryUpdate(
|
||||||
|
const GraphPathNodePointer & pos,
|
||||||
|
const GraphPathNode & prev,
|
||||||
|
const ObjectLink & link)
|
||||||
{
|
{
|
||||||
auto newCost = prev.cost + link.cost;
|
auto newCost = prev.cost + link.cost;
|
||||||
|
|
||||||
if(newCost < cost)
|
if(newCost < cost)
|
||||||
{
|
{
|
||||||
previous = pos;
|
previous = pos;
|
||||||
danger = prev.danger + link.danger;
|
linkDanger = link.danger;
|
||||||
cost = newCost;
|
cost = newCost;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -199,7 +202,7 @@ void GraphPaths::addChainInfo(std::vector<AIPath> & paths, int3 tile, const CGHe
|
|||||||
|
|
||||||
std::vector<GraphPathNodePointer> tilesToPass;
|
std::vector<GraphPathNodePointer> tilesToPass;
|
||||||
|
|
||||||
uint64_t danger = node.danger;
|
uint64_t danger = node.linkDanger;
|
||||||
float cost = node.cost;
|
float cost = node.cost;
|
||||||
bool allowBattle = false;
|
bool allowBattle = false;
|
||||||
|
|
||||||
@@ -212,13 +215,13 @@ void GraphPaths::addChainInfo(std::vector<AIPath> & paths, int3 tile, const CGHe
|
|||||||
if(currentTile == pathNodes.end())
|
if(currentTile == pathNodes.end())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
auto currentNode = currentTile->second[current.nodeType];
|
auto & currentNode = currentTile->second[current.nodeType];
|
||||||
|
|
||||||
if(!currentNode.previous.valid())
|
if(!currentNode.previous.valid())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
allowBattle = allowBattle || currentNode.nodeType == GrapthPathNodeType::BATTLE;
|
allowBattle = allowBattle || currentNode.nodeType == GrapthPathNodeType::BATTLE;
|
||||||
vstd::amax(danger, currentNode.danger);
|
vstd::amax(danger, currentNode.linkDanger);
|
||||||
vstd::amax(cost, currentNode.cost);
|
vstd::amax(cost, currentNode.cost);
|
||||||
|
|
||||||
tilesToPass.push_back(current);
|
tilesToPass.push_back(current);
|
||||||
@@ -239,9 +242,13 @@ void GraphPaths::addChainInfo(std::vector<AIPath> & paths, int3 tile, const CGHe
|
|||||||
if(path.targetHero != hero)
|
if(path.targetHero != hero)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for(auto graphTile = tilesToPass.rbegin(); graphTile != tilesToPass.rend(); graphTile++)
|
uint64_t loss = 0;
|
||||||
|
uint64_t strength = getHeroArmyStrengthWithCommander(path.targetHero, path.heroArmy);
|
||||||
|
|
||||||
|
for(auto graphTile = ++tilesToPass.rbegin(); graphTile != tilesToPass.rend(); graphTile++)
|
||||||
{
|
{
|
||||||
AIPathNodeInfo n;
|
AIPathNodeInfo n;
|
||||||
|
auto & node = getNode(*graphTile);
|
||||||
|
|
||||||
n.coord = graphTile->coord;
|
n.coord = graphTile->coord;
|
||||||
n.cost = cost;
|
n.cost = cost;
|
||||||
@@ -249,7 +256,21 @@ void GraphPaths::addChainInfo(std::vector<AIPath> & paths, int3 tile, const CGHe
|
|||||||
n.danger = danger;
|
n.danger = danger;
|
||||||
n.targetHero = hero;
|
n.targetHero = hero;
|
||||||
n.parentIndex = -1;
|
n.parentIndex = -1;
|
||||||
n.specialAction = getNode(*graphTile).specialAction;
|
n.specialAction = node.specialAction;
|
||||||
|
|
||||||
|
if(node.linkDanger > 0)
|
||||||
|
{
|
||||||
|
auto additionalLoss = ai->pathfinder->getStorage()->evaluateArmyLoss(path.targetHero, strength, node.linkDanger);
|
||||||
|
loss += additionalLoss;
|
||||||
|
|
||||||
|
if(strength > additionalLoss)
|
||||||
|
strength -= additionalLoss;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strength = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(n.specialAction)
|
if(n.specialAction)
|
||||||
{
|
{
|
||||||
@@ -264,7 +285,12 @@ void GraphPaths::addChainInfo(std::vector<AIPath> & paths, int3 tile, const CGHe
|
|||||||
path.nodes.insert(path.nodes.begin(), n);
|
path.nodes.insert(path.nodes.begin(), n);
|
||||||
}
|
}
|
||||||
|
|
||||||
path.armyLoss += ai->pathfinder->getStorage()->evaluateArmyLoss(path.targetHero, path.heroArmy->getArmyStrength(), danger);
|
if(strength == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
path.armyLoss += loss;
|
||||||
path.targetObjectDanger = ai->pathfinder->getStorage()->evaluateDanger(tile, path.targetHero, !allowBattle);
|
path.targetObjectDanger = ai->pathfinder->getStorage()->evaluateDanger(tile, path.targetHero, !allowBattle);
|
||||||
path.targetObjectArmyLoss = ai->pathfinder->getStorage()->evaluateArmyLoss(path.targetHero, path.heroArmy->getArmyStrength(), path.targetObjectDanger);
|
path.targetObjectArmyLoss = ai->pathfinder->getStorage()->evaluateArmyLoss(path.targetHero, path.heroArmy->getArmyStrength(), path.targetObjectDanger);
|
||||||
|
|
||||||
@@ -287,7 +313,7 @@ void GraphPaths::quickAddChainInfoWithBlocker(std::vector<AIPath> & paths, int3
|
|||||||
|
|
||||||
std::vector<GraphPathNodePointer> tilesToPass;
|
std::vector<GraphPathNodePointer> tilesToPass;
|
||||||
|
|
||||||
uint64_t danger = targetNode.danger;
|
uint64_t danger = targetNode.linkDanger;
|
||||||
float cost = targetNode.cost;
|
float cost = targetNode.cost;
|
||||||
bool allowBattle = false;
|
bool allowBattle = false;
|
||||||
|
|
||||||
@@ -303,7 +329,7 @@ void GraphPaths::quickAddChainInfoWithBlocker(std::vector<AIPath> & paths, int3
|
|||||||
auto currentNode = currentTile->second[current.nodeType];
|
auto currentNode = currentTile->second[current.nodeType];
|
||||||
|
|
||||||
allowBattle = allowBattle || currentNode.nodeType == GrapthPathNodeType::BATTLE;
|
allowBattle = allowBattle || currentNode.nodeType == GrapthPathNodeType::BATTLE;
|
||||||
vstd::amax(danger, currentNode.danger);
|
vstd::amax(danger, currentNode.linkDanger);
|
||||||
vstd::amax(cost, currentNode.cost);
|
vstd::amax(cost, currentNode.cost);
|
||||||
|
|
||||||
tilesToPass.push_back(current);
|
tilesToPass.push_back(current);
|
||||||
@@ -341,7 +367,7 @@ void GraphPaths::quickAddChainInfoWithBlocker(std::vector<AIPath> & paths, int3
|
|||||||
// final node
|
// final node
|
||||||
n.coord = tile;
|
n.coord = tile;
|
||||||
n.cost = targetNode.cost;
|
n.cost = targetNode.cost;
|
||||||
n.danger = targetNode.danger;
|
n.danger = danger;
|
||||||
n.parentIndex = path.nodes.size();
|
n.parentIndex = path.nodes.size();
|
||||||
path.nodes.push_back(n);
|
path.nodes.push_back(n);
|
||||||
|
|
||||||
@@ -368,7 +394,7 @@ void GraphPaths::quickAddChainInfoWithBlocker(std::vector<AIPath> & paths, int3
|
|||||||
n.coord = graphTile->coord;
|
n.coord = graphTile->coord;
|
||||||
n.cost = node.cost;
|
n.cost = node.cost;
|
||||||
n.turns = static_cast<ui8>(node.cost);
|
n.turns = static_cast<ui8>(node.cost);
|
||||||
n.danger = node.danger;
|
n.danger = danger;
|
||||||
n.specialAction = node.specialAction;
|
n.specialAction = node.specialAction;
|
||||||
n.parentIndex = path.nodes.size();
|
n.parentIndex = path.nodes.size();
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ struct GraphPathNode
|
|||||||
GrapthPathNodeType nodeType = GrapthPathNodeType::NORMAL;
|
GrapthPathNodeType nodeType = GrapthPathNodeType::NORMAL;
|
||||||
GraphPathNodePointer previous;
|
GraphPathNodePointer previous;
|
||||||
float cost = BAD_COST;
|
float cost = BAD_COST;
|
||||||
uint64_t danger = 0;
|
uint64_t linkDanger = 0;
|
||||||
const CGObjectInstance * obj = nullptr;
|
const CGObjectInstance * obj = nullptr;
|
||||||
std::shared_ptr<SpecialAction> specialAction;
|
std::shared_ptr<SpecialAction> specialAction;
|
||||||
|
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ void ClientCommandManager::handleGoSoloCommand()
|
|||||||
// unlikely it will work but just in case to be consistent
|
// unlikely it will work but just in case to be consistent
|
||||||
for(auto & color : CSH->getAllClientPlayers(CSH->logicConnection->connectionID))
|
for(auto & color : CSH->getAllClientPlayers(CSH->logicConnection->connectionID))
|
||||||
{
|
{
|
||||||
if(CSH->client->getStartInfo()->playerInfos.at(color).isControlledByHuman())
|
if(color.isValidPlayer() && CSH->client->getStartInfo()->playerInfos.at(color).isControlledByHuman())
|
||||||
{
|
{
|
||||||
CSH->client->installNewPlayerInterface(std::make_shared<CPlayerInterface>(color), color);
|
CSH->client->installNewPlayerInterface(std::make_shared<CPlayerInterface>(color), color);
|
||||||
}
|
}
|
||||||
@@ -102,7 +102,7 @@ void ClientCommandManager::handleGoSoloCommand()
|
|||||||
|
|
||||||
for(auto & color : CSH->getAllClientPlayers(CSH->logicConnection->connectionID))
|
for(auto & color : CSH->getAllClientPlayers(CSH->logicConnection->connectionID))
|
||||||
{
|
{
|
||||||
if(CSH->client->getStartInfo()->playerInfos.at(color).isControlledByHuman())
|
if(color.isValidPlayer() && CSH->client->getStartInfo()->playerInfos.at(color).isControlledByHuman())
|
||||||
{
|
{
|
||||||
auto AiToGive = CSH->client->aiNameForPlayer(*CSH->client->getPlayerSettings(color), false, false);
|
auto AiToGive = CSH->client->aiNameForPlayer(*CSH->client->getPlayerSettings(color), false, false);
|
||||||
printCommandMessage("Player " + color.toString() + " will be lead by " + AiToGive, ELogLevel::INFO);
|
printCommandMessage("Player " + color.toString() + " will be lead by " + AiToGive, ELogLevel::INFO);
|
||||||
|
|||||||
Reference in New Issue
Block a user