AINodeStorage.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /*
  2. * AIhelper.h, 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 "AINodeStorage.h"
  12. AINodeStorage::AINodeStorage(const int3 & Sizes)
  13. : sizes(Sizes)
  14. {
  15. nodes.resize(boost::extents[sizes.x][sizes.y][sizes.z][EPathfindingLayer::NUM_LAYERS][NUM_CHAINS]);
  16. }
  17. AINodeStorage::~AINodeStorage()
  18. {
  19. }
  20. AIPathNode * AINodeStorage::getAINode(CPathNodeInfo & nodeInfo) const
  21. {
  22. return static_cast<AIPathNode *>(nodeInfo.node);
  23. }
  24. AIPathNode * AINodeStorage::getAINode(CGPathNode * node) const
  25. {
  26. return static_cast<AIPathNode *>(node);
  27. }
  28. bool AINodeStorage::isBattleNode(CGPathNode * node) const
  29. {
  30. return getAINode(node)->chainMask & BATTLE_CHAIN > 0;
  31. }
  32. AIPathNode * AINodeStorage::getNode(const int3 & coord, const EPathfindingLayer layer, int chainNumber)
  33. {
  34. return &nodes[coord.x][coord.y][coord.z][layer][chainNumber];
  35. }
  36. CGPathNode * AINodeStorage::getInitialNode()
  37. {
  38. auto hpos = hero->getPosition(false);
  39. auto initialNode = getNode(hpos, hero->boat ? EPathfindingLayer::SAIL : EPathfindingLayer::LAND, 0);
  40. initialNode->turns = 0;
  41. initialNode->moveRemains = hero->movement;
  42. initialNode->danger = 0;
  43. return initialNode;
  44. }
  45. void AINodeStorage::resetTile(const int3 & coord, EPathfindingLayer layer, CGPathNode::EAccessibility accessibility)
  46. {
  47. for(int i = 0; i < NUM_CHAINS; i++)
  48. {
  49. AIPathNode & heroNode = nodes[coord.x][coord.y][coord.z][layer][i];
  50. heroNode.chainMask = i;
  51. heroNode.update(coord, layer, accessibility);
  52. }
  53. }
  54. void AINodeStorage::commit(CDestinationNodeInfo & destination, CPathNodeInfo & source)
  55. {
  56. auto dstNode = getAINode(destination);
  57. auto srcNode = getAINode(source);
  58. dstNode->moveRemains = destination.movementLeft;
  59. dstNode->turns = destination.turn;
  60. dstNode->danger = srcNode->danger;
  61. dstNode->action = destination.action;
  62. dstNode->theNodeBefore = srcNode->theNodeBefore;
  63. }
  64. std::vector<CGPathNode *> AINodeStorage::calculateNeighbours(
  65. CPathNodeInfo & source,
  66. CPathfinderConfig * pathfinderConfig,
  67. CPathfinderHelper * pathfinderHelper)
  68. {
  69. std::vector<CGPathNode *> neighbours;
  70. auto srcNode = getAINode(source);
  71. auto accessibleNeighbourTiles = pathfinderHelper->getNeighbourTiles(source);
  72. for(auto & neighbour : accessibleNeighbourTiles)
  73. {
  74. for(EPathfindingLayer i = EPathfindingLayer::LAND; i <= EPathfindingLayer::AIR; i.advance(1))
  75. {
  76. auto nextNode = getNode(neighbour, i, srcNode->chainMask);
  77. if(nextNode->accessible == CGPathNode::NOT_SET)
  78. continue;
  79. neighbours.push_back(nextNode);
  80. }
  81. }
  82. return neighbours;
  83. }
  84. std::vector<CGPathNode *> AINodeStorage::calculateTeleportations(
  85. CPathNodeInfo & source,
  86. CPathfinderConfig * pathfinderConfig,
  87. CPathfinderHelper * pathfinderHelper)
  88. {
  89. std::vector<CGPathNode *> neighbours;
  90. auto accessibleExits = pathfinderHelper->getTeleportExits(source);
  91. auto srcNode = getAINode(source);
  92. for(auto & neighbour : accessibleExits)
  93. {
  94. auto node = getNode(neighbour, source.node->layer, srcNode->chainMask);
  95. neighbours.push_back(node);
  96. }
  97. return neighbours;
  98. }
  99. bool AINodeStorage::hasBetterChain(CPathNodeInfo & source, CDestinationNodeInfo & destination) const
  100. {
  101. auto pos = destination.coord;
  102. auto chains = nodes[pos.x][pos.y][pos.z][EPathfindingLayer::LAND];
  103. auto destinationNode = getAINode(destination);
  104. for(const AIPathNode & node : chains)
  105. {
  106. auto sameNode = node.chainMask == destinationNode->chainMask;
  107. if(sameNode || node.action == CGPathNode::ENodeAction::UNKNOWN)
  108. {
  109. continue;
  110. }
  111. if(node.danger <= destinationNode->danger && destinationNode->chainMask == 1 && node.chainMask == 0)
  112. {
  113. if(node.turns < destinationNode->turns
  114. || node.turns == destinationNode->turns && node.moveRemains >= destinationNode->moveRemains)
  115. {
  116. logAi->trace(
  117. "Block ineficient move %s:->%s, mask=%i, mp diff: %i",
  118. source.coord.toString(),
  119. destination.coord.toString(),
  120. destinationNode->chainMask,
  121. node.moveRemains - destinationNode->moveRemains);
  122. return true;
  123. }
  124. }
  125. }
  126. return false;
  127. }
  128. std::vector<AIPath> AINodeStorage::getChainInfo(int3 pos)
  129. {
  130. std::vector<AIPath> paths;
  131. auto chains = nodes[pos.x][pos.y][pos.z][EPathfindingLayer::LAND];
  132. for(const AIPathNode & node : chains)
  133. {
  134. if(node.action == CGPathNode::ENodeAction::UNKNOWN)
  135. {
  136. continue;
  137. }
  138. AIPath path;
  139. const AIPathNode * current = &node;
  140. while(current != nullptr)
  141. {
  142. AIPathNodeInfo pathNode;
  143. pathNode.movementPointsLeft = current->moveRemains;
  144. pathNode.movementPointsUsed = (int)(current->turns * hero->maxMovePoints(true) + hero->movement) - (int)current->moveRemains;
  145. pathNode.turns = current->turns;
  146. pathNode.danger = current->danger;
  147. pathNode.coord = current->coord;
  148. path.nodes.push_back(pathNode);
  149. current = getAINode(current->theNodeBefore);
  150. }
  151. paths.push_back(path);
  152. }
  153. return paths;
  154. }
  155. AIPath::AIPath()
  156. : nodes({})
  157. {
  158. }
  159. int3 AIPath::firstTileToGet() const
  160. {
  161. if(nodes.size())
  162. {
  163. return nodes.back().coord;
  164. }
  165. return int3(-1, -1, -1);
  166. }
  167. uint64_t AIPath::getPathDanger() const
  168. {
  169. if(nodes.size())
  170. {
  171. return nodes.front().danger;
  172. }
  173. return 0;
  174. }
  175. uint32_t AIPath::movementCost() const
  176. {
  177. if(nodes.size())
  178. {
  179. return nodes.front().movementPointsUsed;
  180. }
  181. // TODO: boost:optional?
  182. return 0;
  183. }
  184. uint64_t AIPath::getTotalDanger(HeroPtr hero) const
  185. {
  186. uint64_t pathDanger = getPathDanger();
  187. uint64_t objDanger = evaluateDanger(nodes.front().coord, hero.get()); // bank danger is not checked by pathfinder
  188. uint64_t danger = pathDanger > objDanger ? pathDanger : objDanger;
  189. return danger;
  190. }