action.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /*
  2. * action.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 "battle/CBattleInfoEssentials.h"
  12. #include "BAI/v13/action.h"
  13. #include "BAI/v13/hex.h"
  14. #include "BAI/v13/hexaction.h"
  15. #include "common.h"
  16. namespace MMAI::BAI::V13
  17. {
  18. // static
  19. std::unique_ptr<Hex> Action::initHex(const Schema::Action & a, const Battlefield * bf)
  20. {
  21. // Control actions (<0) should never reach here
  22. ASSERT(a >= 0 && a < N_ACTIONS, "Invalid action: " + std::to_string(a));
  23. auto i = a - EI(GlobalAction::_count);
  24. if(i < 0)
  25. return nullptr;
  26. i = i / EI(HexAction::_count);
  27. auto y = i / 15;
  28. auto x = i % 15;
  29. // create a new unique_ptr with a copy of Hex
  30. return std::make_unique<Hex>(*bf->hexes->at(y).at(x));
  31. }
  32. // static
  33. std::unique_ptr<Hex> Action::initAMoveTargetHex(const Schema::Action & a, const Battlefield * bf)
  34. {
  35. auto hex = initHex(a, bf);
  36. if(!hex)
  37. return nullptr;
  38. auto ha = initHexAction(a, bf);
  39. if(EI(ha) == -1)
  40. return nullptr;
  41. if(ha == HexAction::MOVE || ha == HexAction::SHOOT)
  42. return nullptr;
  43. // throw std::runtime_error("MOVE and SHOOT are not AMOVE actions");
  44. const auto & bh = hex->bhex;
  45. auto edir = AMOVE_TO_EDIR.at(EI(ha));
  46. auto nbh = bh.cloneInDirection(edir);
  47. ASSERT(nbh.isAvailable(), "unavailable AMOVE target hex #" + std::to_string(nbh.toInt()));
  48. auto [x, y] = Hex::CalcXY(nbh);
  49. // create a new unique_ptr with a copy of Hex
  50. return std::make_unique<Hex>(*bf->hexes->at(y).at(x));
  51. }
  52. // static
  53. HexAction Action::initHexAction(const Schema::Action & a, const Battlefield * bf)
  54. {
  55. if(a < EI(GlobalAction::_count))
  56. return static_cast<HexAction>(-1); // a is not about a hex
  57. return static_cast<HexAction>((a - EI(GlobalAction::_count)) % EI(HexAction::_count));
  58. }
  59. Action::Action(const Schema::Action action_, const Battlefield * bf, const std::string & color_)
  60. : action(action_), hex(initHex(action_, bf)), aMoveTargetHex(initAMoveTargetHex(action_, bf)), hexaction(initHexAction(action_, bf)), color(color_)
  61. {
  62. }
  63. std::string Action::name() const
  64. {
  65. if(action == Schema::V13::ACTION_RETREAT)
  66. return "Retreat";
  67. else if(action == Schema::V13::ACTION_WAIT)
  68. return "Wait";
  69. ASSERT(hex, "hex is null");
  70. auto ha = static_cast<HexAction>((action - EI(GlobalAction::_count)) % EI(HexAction::_count));
  71. auto res = std::string{};
  72. std::shared_ptr<const Stack> stack = nullptr;
  73. std::string stackstr;
  74. if(ha == HexAction::SHOOT || ha == HexAction::MOVE)
  75. {
  76. stack = hex->stack;
  77. }
  78. else if(aMoveTargetHex)
  79. {
  80. stack = aMoveTargetHex->stack;
  81. }
  82. // colored output does not look good (scrambles default VCMI log coloring)
  83. // Additionally, hardcoded red/blue colors are relevant during training only
  84. // => replace with attacker/defender colorless strings instead
  85. // if (stack) {
  86. // std::string targetcolor = "\033[31m"; // red
  87. // if (color == "red") targetcolor = "\033[34m"; // blue
  88. // stackstr = targetcolor + "#" + std::string(1, stack->getAlias()) + "\033[0m";
  89. // } else {
  90. // std::string targetcolor = "\033[7m"; // white
  91. // stackstr = targetcolor + "#?" + "\033[0m";
  92. // }
  93. if(stack)
  94. {
  95. std::string targetside = (color == "red") ? "L" : "R";
  96. stackstr = targetside + "-" + std::string(1, stack->getAlias());
  97. }
  98. else
  99. {
  100. stackstr = "?";
  101. }
  102. switch(ha)
  103. {
  104. case HexAction::MOVE:
  105. res = (stack && hex->bhex == stack->cstack->getPosition() ? "Defend on hex(" : "Move to (") + hex->name() + ")";
  106. break;
  107. case HexAction::AMOVE_TL:
  108. res = "Attack stack(" + stackstr + ") from hex(" + hex->name() + ") /top-left/";
  109. break;
  110. case HexAction::AMOVE_TR:
  111. res = "Attack stack(" + stackstr + ") from hex(" + hex->name() + ") /top-right/";
  112. break;
  113. case HexAction::AMOVE_R:
  114. res = "Attack stack(" + stackstr + ") from hex(" + hex->name() + ") /right/";
  115. break;
  116. case HexAction::AMOVE_BR:
  117. res = "Attack stack(" + stackstr + ") from hex(" + hex->name() + ") /bottom-right/";
  118. break;
  119. case HexAction::AMOVE_BL:
  120. res = "Attack stack(" + stackstr + ") from hex(" + hex->name() + ") /bottom-left/";
  121. break;
  122. case HexAction::AMOVE_L:
  123. res = "Attack stack(" + stackstr + ") from hex(" + hex->name() + ") /left/";
  124. break;
  125. case HexAction::AMOVE_2BL:
  126. res = "Attack stack(" + stackstr + ") from hex(" + hex->name() + ") /bottom-left-2/";
  127. break;
  128. case HexAction::AMOVE_2L:
  129. res = "Attack stack(" + stackstr + ") from hex(" + hex->name() + ") /left-2/";
  130. break;
  131. case HexAction::AMOVE_2TL:
  132. res = "Attack stack(" + stackstr + ") from hex(" + hex->name() + ") /top-left-2/";
  133. break;
  134. case HexAction::AMOVE_2TR:
  135. res = "Attack stack(" + stackstr + ") from hex(" + hex->name() + ") /top-right-2/";
  136. break;
  137. case HexAction::AMOVE_2R:
  138. res = "Attack stack(" + stackstr + ") from hex(" + hex->name() + ") /right-2/";
  139. break;
  140. case HexAction::AMOVE_2BR:
  141. res = "Attack stack(" + stackstr + ") from hex(" + hex->name() + ") /bottom-right-2/";
  142. break;
  143. case HexAction::SHOOT:
  144. res = "Attack stack(" + stackstr + ") " + hex->name() + " (ranged)";
  145. break;
  146. default:
  147. THROW_FORMAT("Unexpected hexaction: %d", EI(ha));
  148. }
  149. return res;
  150. }
  151. }