diff --git a/AI/Nullkiller/AIUtility.h b/AI/Nullkiller/AIUtility.h index d5d4206e6..f1b529ad0 100644 --- a/AI/Nullkiller/AIUtility.h +++ b/AI/Nullkiller/AIUtility.h @@ -50,7 +50,6 @@ #include -using namespace tbb; using dwellingContent = std::pair>; @@ -246,48 +245,6 @@ uint64_t timeElapsed(std::chrono::time_point // todo: move to obj manager bool shouldVisit(const Nullkiller * ai, const CGHeroInstance * h, const CGObjectInstance * obj); -template -void pforeachTilePos(const int3 & mapSize, TFunc fn) -{ - for(int z = 0; z < mapSize.z; ++z) - { - parallel_for(blocked_range(0, mapSize.x), [&](const blocked_range& 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 -void pforeachTilePaths(const int3 & mapSize, const Nullkiller * ai, TFunc fn) -{ - for(int z = 0; z < mapSize.z; ++z) - { - parallel_for(blocked_range(0, mapSize.x), [&](const blocked_range & r) - { - int3 pos(0, 0, z); - std::vector 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; diff --git a/AI/Nullkiller/Analyzers/DangerHitMapAnalyzer.cpp b/AI/Nullkiller/Analyzers/DangerHitMapAnalyzer.cpp index d25494f4e..6d11d01ba 100644 --- a/AI/Nullkiller/Analyzers/DangerHitMapAnalyzer.cpp +++ b/AI/Nullkiller/Analyzers/DangerHitMapAnalyzer.cpp @@ -11,6 +11,7 @@ #include "DangerHitMapAnalyzer.h" #include "../Engine/Nullkiller.h" +#include "../pforeach.h" #include "../../../lib/CRandomGenerator.h" namespace NKAI diff --git a/AI/Nullkiller/Analyzers/ObjectClusterizer.cpp b/AI/Nullkiller/Analyzers/ObjectClusterizer.cpp index f172f0a31..f301b4d20 100644 --- a/AI/Nullkiller/Analyzers/ObjectClusterizer.cpp +++ b/AI/Nullkiller/Analyzers/ObjectClusterizer.cpp @@ -235,9 +235,9 @@ void ObjectClusterizer::clusterize() ai->memory->visitableObjs.end()); #if NKAI_TRACE_LEVEL == 0 - parallel_for(blocked_range(0, objs.size()), [&](const blocked_range & r) { + tbb::parallel_for(tbb::blocked_range(0, objs.size()), [&](const tbb::blocked_range & r) { #else - blocked_range r(0, objs.size()); + tbb::blocked_range r(0, objs.size()); #endif auto priorityEvaluator = ai->priorityEvaluators->acquire(); auto heroes = ai->cb->getHeroesInfo(); diff --git a/AI/Nullkiller/Behaviors/GatherArmyBehavior.cpp b/AI/Nullkiller/Behaviors/GatherArmyBehavior.cpp index de1fab7f4..22e3d03ba 100644 --- a/AI/Nullkiller/Behaviors/GatherArmyBehavior.cpp +++ b/AI/Nullkiller/Behaviors/GatherArmyBehavior.cpp @@ -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> waysToVisitObj; diff --git a/AI/Nullkiller/CMakeLists.txt b/AI/Nullkiller/CMakeLists.txt index 15e54c395..93f94a351 100644 --- a/AI/Nullkiller/CMakeLists.txt +++ b/AI/Nullkiller/CMakeLists.txt @@ -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 diff --git a/AI/Nullkiller/Pathfinding/AINodeStorage.cpp b/AI/Nullkiller/Pathfinding/AINodeStorage.cpp index 54a2d42e0..d061fad19 100644 --- a/AI/Nullkiller/Pathfinding/AINodeStorage.cpp +++ b/AI/Nullkiller/Pathfinding/AINodeStorage.cpp @@ -412,7 +412,6 @@ struct DelayedWork class HeroChainCalculationTask { private: - AISharedStorage & nodes; AINodeStorage & storage; std::vector existingChains; std::vector newChains; @@ -424,8 +423,8 @@ private: public: HeroChainCalculationTask( - AINodeStorage & storage, AISharedStorage & nodes, const std::vector & 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 & 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 bool { - auto pos = chainInfo.coord; auto isNotEffective = storage.hasBetterChain(chainInfo.carrierParent, chainInfo) || storage.hasBetterChain(chainInfo.carrierParent, chainInfo, result); diff --git a/AI/Nullkiller/Pathfinding/ObjectGraph.cpp b/AI/Nullkiller/Pathfinding/ObjectGraph.cpp index fb26ccc84..7f64bd1e4 100644 --- a/AI/Nullkiller/Pathfinding/ObjectGraph.cpp +++ b/AI/Nullkiller/Pathfinding/ObjectGraph.cpp @@ -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 & 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 & paths, int3 } if(!path.nodes.empty()) - break; + continue; for(auto graphTile = tilesToPass.rbegin(); graphTile != tilesToPass.rend(); graphTile++) {