ClusterBehavior.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /*
  2. * RecruitHeroBehavior.cpp, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #include "StdInc.h"
  11. #include "ClusterBehavior.h"
  12. #include "../AIGateway.h"
  13. #include "../Engine/Nullkiller.h"
  14. #include "../AIUtility.h"
  15. #include "../Markers/UnlockCluster.h"
  16. #include "../Goals/Composition.h"
  17. #include "../Behaviors/CaptureObjectsBehavior.h"
  18. namespace NKAI
  19. {
  20. using namespace Goals;
  21. std::string ClusterBehavior::toString() const
  22. {
  23. return "Unlock Clusters";
  24. }
  25. Goals::TGoalVec ClusterBehavior::decompose() const
  26. {
  27. Goals::TGoalVec tasks;
  28. auto clusters = ai->nullkiller->objectClusterizer->getLockedClusters();
  29. for(auto cluster : clusters)
  30. {
  31. vstd::concatenate(tasks, decomposeCluster(cluster));
  32. }
  33. return tasks;
  34. }
  35. Goals::TGoalVec ClusterBehavior::decomposeCluster(std::shared_ptr<ObjectCluster> cluster) const
  36. {
  37. auto center = cluster->calculateCenter();
  38. auto paths = ai->nullkiller->pathfinder->getPathInfo(center->visitablePos(), ai->nullkiller->settings->isObjectGraphAllowed());
  39. auto blockerPos = cluster->blocker->visitablePos();
  40. std::vector<AIPath> blockerPaths;
  41. blockerPaths.reserve(paths.size());
  42. TGoalVec goals;
  43. #if NKAI_TRACE_LEVEL >= 2
  44. logAi->trace(
  45. "Checking cluster %s %s, found %d paths",
  46. cluster->blocker->getObjectName(),
  47. cluster->blocker->visitablePos().toString(),
  48. paths.size());
  49. #endif
  50. for(auto path = paths.begin(); path != paths.end();)
  51. {
  52. #if NKAI_TRACE_LEVEL >= 2
  53. logAi->trace("Checking path %s", path->toString());
  54. #endif
  55. auto blocker = ai->nullkiller->objectClusterizer->getBlocker(*path);
  56. if(blocker != cluster->blocker)
  57. {
  58. path = paths.erase(path);
  59. continue;
  60. }
  61. blockerPaths.push_back(*path);
  62. AIPath & clonedPath = blockerPaths.back();
  63. clonedPath.nodes.clear();
  64. for(auto node = path->nodes.rbegin(); node != path->nodes.rend(); node++)
  65. {
  66. clonedPath.nodes.insert(clonedPath.nodes.begin(), *node);
  67. if(node->coord == blockerPos || cb->getGuardingCreaturePosition(node->coord) == blockerPos)
  68. break;
  69. }
  70. for(auto & node : clonedPath.nodes)
  71. node.parentIndex -= path->nodes.size() - clonedPath.nodes.size();
  72. #if NKAI_TRACE_LEVEL >= 2
  73. logAi->trace("Unlock path found %s", blockerPaths.back().toString());
  74. #endif
  75. path++;
  76. }
  77. #if NKAI_TRACE_LEVEL >= 2
  78. logAi->trace("Decompose unlock paths");
  79. #endif
  80. auto unlockTasks = CaptureObjectsBehavior::getVisitGoals(blockerPaths);
  81. for(int i = 0; i < paths.size(); i++)
  82. {
  83. if(unlockTasks[i]->invalid())
  84. continue;
  85. auto path = paths[i];
  86. auto elementarUnlock = sptr(UnlockCluster(cluster, path));
  87. goals.push_back(sptr(Composition().addNext(elementarUnlock).addNext(unlockTasks[i])));
  88. }
  89. return goals;
  90. }
  91. }