1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

NKAI: object graph fixes

This commit is contained in:
Andrii Danylchenko 2024-03-25 17:05:24 +02:00
parent 3820f6f78b
commit adfcb650e2
7 changed files with 44 additions and 57 deletions

View File

@ -50,7 +50,6 @@
#include <chrono>
using namespace tbb;
using dwellingContent = std::pair<ui32, std::vector<CreatureID>>;
@ -246,48 +245,6 @@ uint64_t timeElapsed(std::chrono::time_point<std::chrono::high_resolution_clock>
// todo: move to obj manager
bool shouldVisit(const Nullkiller * ai, const CGHeroInstance * h, const CGObjectInstance * obj);
template<typename TFunc>
void pforeachTilePos(const int3 & mapSize, TFunc fn)
{
for(int z = 0; z < mapSize.z; ++z)
{
parallel_for(blocked_range<size_t>(0, mapSize.x), [&](const blocked_range<size_t>& r)
{
int3 pos(0, 0, z);
for(pos.x = r.begin(); pos.x != r.end(); ++pos.x)
{
for(pos.y = 0; pos.y < mapSize.y; ++pos.y)
{
fn(pos);
}
}
});
}
}
template<typename TFunc>
void pforeachTilePaths(const int3 & mapSize, const Nullkiller * ai, TFunc fn)
{
for(int z = 0; z < mapSize.z; ++z)
{
parallel_for(blocked_range<size_t>(0, mapSize.x), [&](const blocked_range<size_t> & r)
{
int3 pos(0, 0, z);
std::vector<AIPath> paths;
for(pos.x = r.begin(); pos.x != r.end(); ++pos.x)
{
for(pos.y = 0; pos.y < mapSize.y; ++pos.y)
{
ai->pathfinder->calculatePathInfo(paths, pos);
fn(pos, paths);
}
}
});
}
}
class CDistanceSorter
{
const CGHeroInstance * hero;

View File

@ -11,6 +11,7 @@
#include "DangerHitMapAnalyzer.h"
#include "../Engine/Nullkiller.h"
#include "../pforeach.h"
#include "../../../lib/CRandomGenerator.h"
namespace NKAI

View File

@ -235,9 +235,9 @@ void ObjectClusterizer::clusterize()
ai->memory->visitableObjs.end());
#if NKAI_TRACE_LEVEL == 0
parallel_for(blocked_range<size_t>(0, objs.size()), [&](const blocked_range<size_t> & r) {
tbb::parallel_for(tbb::blocked_range<size_t>(0, objs.size()), [&](const tbb::blocked_range<size_t> & r) {
#else
blocked_range<size_t> r(0, objs.size());
tbb::blocked_range<size_t> r(0, objs.size());
#endif
auto priorityEvaluator = ai->priorityEvaluators->acquire();
auto heroes = ai->cb->getHeroesInfo();

View File

@ -69,7 +69,7 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her
logAi->trace("Checking ways to gaher army for hero %s, %s", hero->getObjectName(), pos.toString());
#endif
auto paths = ai->nullkiller->pathfinder->getPathInfo(pos);
auto paths = ai->nullkiller->pathfinder->getPathInfo(pos, ai->nullkiller->settings->isObjectGraphAllowed());
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Gather army found %d paths", paths.size());
@ -231,7 +231,7 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const CGTownInstance * upgrader)
logAi->trace("Checking ways to upgrade army in town %s, %s", upgrader->getObjectName(), pos.toString());
#endif
auto paths = ai->nullkiller->pathfinder->getPathInfo(pos);
auto paths = ai->nullkiller->pathfinder->getPathInfo(pos, ai->nullkiller->settings->isObjectGraphAllowed());
auto goals = CaptureObjectsBehavior::getVisitGoals(paths);
std::vector<std::shared_ptr<ExecuteHeroChain>> waysToVisitObj;

View File

@ -81,6 +81,7 @@ set(Nullkiller_HEADERS
Pathfinding/Rules/AIPreviousNodeRule.h
Pathfinding/ObjectGraph.h
AIUtility.h
pforeach.h
Analyzers/ArmyManager.h
Analyzers/HeroManager.h
Engine/Settings.h

View File

@ -412,7 +412,6 @@ struct DelayedWork
class HeroChainCalculationTask
{
private:
AISharedStorage & nodes;
AINodeStorage & storage;
std::vector<AIPathNode *> existingChains;
std::vector<ExchangeCandidate> newChains;
@ -424,8 +423,8 @@ private:
public:
HeroChainCalculationTask(
AINodeStorage & storage, AISharedStorage & nodes, const std::vector<int3> & tiles, uint64_t chainMask, int heroChainTurn)
:existingChains(), newChains(), delayedWork(), nodes(nodes), storage(storage), chainMask(chainMask), heroChainTurn(heroChainTurn), heroChain(), tiles(tiles)
AINodeStorage & storage, const std::vector<int3> & tiles, uint64_t chainMask, int heroChainTurn)
:existingChains(), newChains(), delayedWork(), storage(storage), chainMask(chainMask), heroChainTurn(heroChainTurn), heroChain(), tiles(tiles)
{
existingChains.reserve(AIPathfinding::NUM_CHAINS);
newChains.reserve(AIPathfinding::NUM_CHAINS);
@ -621,7 +620,6 @@ void HeroChainCalculationTask::cleanupInefectiveChains(std::vector<ExchangeCandi
{
vstd::erase_if(result, [&](const ExchangeCandidate & chainInfo) -> bool
{
auto pos = chainInfo.coord;
auto isNotEffective = storage.hasBetterChain(chainInfo.carrierParent, chainInfo)
|| storage.hasBetterChain(chainInfo.carrierParent, chainInfo, result);

View File

@ -168,6 +168,37 @@ private:
}
});
auto obj = ai->cb->getTopObj(pos);
if(obj && obj->ID == Obj::BOAT)
{
ai->pathfinder->calculatePathInfo(pathCache, pos);
for(AIPath & path : pathCache)
{
auto from = path.targetHero->visitablePos();
auto fromObj = actorObjectMap[path.targetHero];
auto fromTile = cb->getTile(from);
auto danger = ai->pathfinder->getStorage()->evaluateDanger(pos, path.targetHero, true);
auto updated = target->tryAddConnection(
from,
pos,
path.movementCost(),
danger);
if(NKAI_GRAPH_TRACE_LEVEL >= 2 && updated)
{
logAi->trace(
"Connected %s[%s] -> %s[%s] through [%s], cost %2f",
fromObj ? fromObj->getObjectName() : "J", from.toString(),
"Boat", pos.toString(),
pos.toString(),
path.movementCost());
}
}
}
return;
}
@ -199,7 +230,9 @@ private:
if(!cb->getTile(pos)->isWater())
continue;
if(obj1 && (obj1->ID != Obj::BOAT || obj1->ID != Obj::SHIPYARD))
auto startingObjIsBoatOrShipyard = obj1 && (obj1->ID == Obj::BOAT || obj1->ID == Obj::SHIPYARD);
if(!startingObjIsBoatOrShipyard)
continue;
}
@ -287,7 +320,7 @@ private:
assert(objectActor->visitablePos() == visitablePos);
actorObjectMap[objectActor] = obj;
actors[objectActor] = obj->ID == Obj::TOWN || obj->ID == Obj::SHIPYARD ? HeroRole::MAIN : HeroRole::SCOUT;
actors[objectActor] = obj->ID == Obj::TOWN || obj->ID == Obj::SHIPYARD || obj->ID == Obj::BOAT ? HeroRole::MAIN : HeroRole::SCOUT;
target->addObject(obj);
}
@ -717,9 +750,6 @@ void GraphPaths::quickAddChainInfoWithBlocker(std::vector<AIPath> & paths, int3
auto currentNode = currentTile->second[current.nodeType];
if(!currentNode.previous.valid())
break;
allowBattle = allowBattle || currentNode.nodeType == GrapthPathNodeType::BATTLE;
vstd::amax(danger, currentNode.danger);
vstd::amax(cost, currentNode.cost);
@ -777,7 +807,7 @@ void GraphPaths::quickAddChainInfoWithBlocker(std::vector<AIPath> & paths, int3
}
if(!path.nodes.empty())
break;
continue;
for(auto graphTile = tilesToPass.rbegin(); graphTile != tilesToPass.rend(); graphTile++)
{