ReachabilityInfo.cpp 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. /*
  2. * ReachabilityInfo.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 "ReachabilityInfo.h"
  12. #include "Unit.h"
  13. VCMI_LIB_NAMESPACE_BEGIN
  14. ReachabilityInfo::Parameters::Parameters(const battle::Unit * Stack, BattleHex StartPosition):
  15. perspective(static_cast<BattleSide>(Stack->unitSide())),
  16. startPosition(StartPosition),
  17. doubleWide(Stack->doubleWide()),
  18. side(Stack->unitSide()),
  19. flying(Stack->hasBonusOfType(BonusType::FLYING))
  20. {
  21. knownAccessible = battle::Unit::getHexes(startPosition, doubleWide, side);
  22. }
  23. ReachabilityInfo::ReachabilityInfo()
  24. {
  25. distances.fill(INFINITE_DIST);
  26. predecessors.fill(BattleHex::INVALID);
  27. }
  28. bool ReachabilityInfo::isReachable(BattleHex hex) const
  29. {
  30. return distances[hex] < INFINITE_DIST;
  31. }
  32. uint32_t ReachabilityInfo::distToNearestNeighbour(
  33. const BattleHexArray & targetHexes,
  34. BattleHex * chosenHex) const
  35. {
  36. uint32_t ret = 1000000;
  37. for(auto targetHex : targetHexes)
  38. {
  39. for(auto & n : BattleHexArray::neighbouringTilesCache[targetHex])
  40. {
  41. if(distances[n] < ret)
  42. {
  43. ret = distances[n];
  44. if(chosenHex)
  45. *chosenHex = n;
  46. }
  47. }
  48. }
  49. return ret;
  50. }
  51. uint32_t ReachabilityInfo::distToNearestNeighbour(
  52. const battle::Unit * attacker,
  53. const battle::Unit * defender,
  54. BattleHex * chosenHex) const
  55. {
  56. auto attackableHexes = defender->getHexes();
  57. if(attacker->doubleWide())
  58. {
  59. if(defender->doubleWide())
  60. {
  61. // It can be back to back attack o==o or head to head =oo=.
  62. // In case of back-to-back the distance between heads (unit positions) may be up to 3 tiles
  63. attackableHexes.merge(battle::Unit::getHexes(defender->occupiedHex(), true, defender->unitSide()));
  64. }
  65. else
  66. {
  67. attackableHexes.merge(battle::Unit::getHexes(defender->getPosition(), true, defender->unitSide()));
  68. }
  69. }
  70. vstd::erase_if(attackableHexes, [defender](BattleHex h) -> bool
  71. {
  72. return h.getY() != defender->getPosition().getY() || !h.isAvailable();
  73. });
  74. return distToNearestNeighbour(attackableHexes, chosenHex);
  75. }
  76. VCMI_LIB_NAMESPACE_END