CBattleInfoCallbackTest.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897
  1. /*
  2. * CBattleInfoCallbackTest.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 "../../lib/battle/CBattleInfoCallback.h"
  12. #include "../../lib/battle/CUnitState.h"
  13. #include <vstd/RNG.h>
  14. #include "mock/mock_BonusBearer.h"
  15. #include "mock/mock_battle_IBattleState.h"
  16. #include "mock/mock_battle_Unit.h"
  17. #if SCRIPTING_ENABLED
  18. #include "mock/mock_scripting_Pool.h"
  19. #endif
  20. using namespace battle;
  21. using namespace testing;
  22. class UnitFake : public UnitMock
  23. {
  24. private:
  25. std::shared_ptr<CUnitState> state;
  26. public:
  27. UnitFake()
  28. {
  29. state.reset(new CUnitStateDetached(this, this));
  30. }
  31. void addNewBonus(const std::shared_ptr<Bonus> & b)
  32. {
  33. bonusFake.addNewBonus(b);
  34. }
  35. void addCreatureAbility(BonusType bonusType)
  36. {
  37. addNewBonus(
  38. std::make_shared<Bonus>(
  39. BonusDuration::PERMANENT,
  40. bonusType,
  41. BonusSource::CREATURE_ABILITY,
  42. 0,
  43. CreatureID(0)));
  44. }
  45. void makeAlive()
  46. {
  47. EXPECT_CALL(*this, alive()).WillRepeatedly(Return(true));
  48. }
  49. void setupPoisition(BattleHex pos)
  50. {
  51. EXPECT_CALL(*this, getPosition()).WillRepeatedly(Return(pos));
  52. }
  53. void makeDoubleWide()
  54. {
  55. EXPECT_CALL(*this, doubleWide()).WillRepeatedly(Return(true));
  56. }
  57. void makeWarMachine()
  58. {
  59. addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::SIEGE_WEAPON, BonusSource::CREATURE_ABILITY, 1, BonusSourceID()));
  60. }
  61. bool isHypnotized() const override
  62. {
  63. return hasBonusOfType(BonusType::HYPNOTIZED);
  64. }
  65. bool isInvincible() const override
  66. {
  67. return hasBonusOfType(BonusType::INVINCIBLE);
  68. }
  69. void redirectBonusesToFake()
  70. {
  71. ON_CALL(*this, getAllBonuses(_, _)).WillByDefault(Invoke(&bonusFake, &BonusBearerMock::getAllBonuses));
  72. ON_CALL(*this, getTreeVersion()).WillByDefault(Invoke(&bonusFake, &BonusBearerMock::getTreeVersion));
  73. }
  74. void expectAnyBonusSystemCall()
  75. {
  76. EXPECT_CALL(*this, getAllBonuses(_, _)).Times(AtLeast(0));
  77. EXPECT_CALL(*this, getTreeVersion()).Times(AtLeast(0));
  78. }
  79. void setDefaultExpectations()
  80. {
  81. EXPECT_CALL(*this, unitSlot()).WillRepeatedly(Return(SlotID(0)));
  82. EXPECT_CALL(*this, creatureIndex()).WillRepeatedly(Return(0));
  83. }
  84. void setDefaultState()
  85. {
  86. EXPECT_CALL(*this, isClone()).WillRepeatedly(Return(false));
  87. EXPECT_CALL(*this, isCaster()).WillRepeatedly(Return(false));
  88. EXPECT_CALL(*this, acquireState()).WillRepeatedly(Return(state));
  89. }
  90. private:
  91. BonusBearerMock bonusFake;
  92. };
  93. class UnitsFake
  94. {
  95. public:
  96. std::vector<std::shared_ptr<UnitFake>> allUnits;
  97. UnitFake & add(BattleSide side)
  98. {
  99. auto * unit = new UnitFake();
  100. EXPECT_CALL(*unit, unitSide()).WillRepeatedly(Return(side));
  101. unit->setDefaultExpectations();
  102. allUnits.emplace_back(unit);
  103. return *allUnits.back().get();
  104. }
  105. Units getUnitsIf(UnitFilter predicate) const
  106. {
  107. Units ret;
  108. for(auto & unit : allUnits)
  109. {
  110. if(predicate(unit.get()))
  111. ret.push_back(unit.get());
  112. }
  113. return ret;
  114. }
  115. void setDefaultBonusExpectations()
  116. {
  117. for(auto & unit : allUnits)
  118. {
  119. unit->redirectBonusesToFake();
  120. unit->expectAnyBonusSystemCall();
  121. }
  122. }
  123. };
  124. class CBattleInfoCallbackTest : public Test
  125. {
  126. public:
  127. class TestSubject : public CBattleInfoCallback
  128. {
  129. public:
  130. const IBattleInfo * battle;
  131. #if SCRIPTING_ENABLED
  132. scripting::Pool * pool;
  133. TestSubject(scripting::Pool * p)
  134. : CBattleInfoCallback(),
  135. pool(p)
  136. #else
  137. TestSubject()
  138. : CBattleInfoCallback()
  139. #endif
  140. {
  141. }
  142. const IBattleInfo * getBattle() const override
  143. {
  144. return battle;
  145. }
  146. std::optional<PlayerColor> getPlayerID() const override
  147. {
  148. return std::nullopt;
  149. }
  150. #if SCRIPTING_ENABLED
  151. scripting::Pool * getContextPool() const override
  152. {
  153. return pool;
  154. }
  155. #endif
  156. };
  157. #if SCRIPTING_ENABLED
  158. StrictMock<scripting::PoolMock> pool;
  159. #endif
  160. TestSubject subject;
  161. BattleStateMock battleMock;
  162. UnitsFake unitsFake;
  163. CBattleInfoCallbackTest()
  164. #if SCRIPTING_ENABLED
  165. : pool(),
  166. subject(&pool)
  167. #endif
  168. {
  169. }
  170. void startBattle()
  171. {
  172. subject.battle = &battleMock;
  173. }
  174. void redirectUnitsToFake()
  175. {
  176. ON_CALL(battleMock, getUnitsIf(_)).WillByDefault(Invoke(&unitsFake, &UnitsFake::getUnitsIf));
  177. }
  178. };
  179. class AttackableHexesTest : public CBattleInfoCallbackTest
  180. {
  181. public:
  182. UnitFake & addRegularMelee(BattleHex hex, BattleSide side)
  183. {
  184. auto & unit = unitsFake.add(side);
  185. unit.makeAlive();
  186. unit.setDefaultState();
  187. unit.setupPoisition(hex);
  188. unit.redirectBonusesToFake();
  189. return unit;
  190. }
  191. UnitFake & addCerberi(BattleHex hex, BattleSide side)
  192. {
  193. auto & unit = addRegularMelee(hex, side);
  194. unit.addCreatureAbility(BonusType::THREE_HEADED_ATTACK);
  195. unit.makeDoubleWide();
  196. return unit;
  197. }
  198. UnitFake & addDragon(BattleHex hex, BattleSide side)
  199. {
  200. auto & unit = addRegularMelee(hex, side);
  201. unit.addCreatureAbility(BonusType::TWO_HEX_ATTACK_BREATH);
  202. unit.makeDoubleWide();
  203. return unit;
  204. }
  205. Units getAttackedUnits(UnitFake & attacker, UnitFake & defender, BattleHex defenderHex)
  206. {
  207. startBattle();
  208. redirectUnitsToFake();
  209. return subject.getAttackedBattleUnits(
  210. &attacker, &defender,
  211. defenderHex, false,
  212. attacker.getPosition(),
  213. defender.getPosition());
  214. }
  215. };
  216. ///// getAttackableHexes tests
  217. TEST_F(AttackableHexesTest, getAttackableHexes_SingleWideAttacker_SingleWideDefender)
  218. {
  219. UnitFake & attacker = addRegularMelee(60, BattleSide::ATTACKER);
  220. UnitFake & defender = addRegularMelee(90, BattleSide::DEFENDER);
  221. static const BattleHexArray expectedDef =
  222. {
  223. 72,
  224. 73,
  225. 89,
  226. 91,
  227. 106,
  228. 107
  229. };
  230. auto attackable = defender.getAttackableHexes(&attacker);
  231. attackable.sort([](const auto & l, const auto & r) { return l < r; });
  232. EXPECT_EQ(expectedDef, attackable);
  233. }
  234. TEST_F(AttackableHexesTest, getAttackableHexes_SingleWideAttacker_DoubleWideDefender)
  235. {
  236. UnitFake & attacker = addRegularMelee(60, BattleSide::ATTACKER);
  237. UnitFake & defender = addDragon(90, BattleSide::DEFENDER);
  238. static const BattleHexArray expectedDef =
  239. {
  240. 72,
  241. 73,
  242. 74,
  243. 89,
  244. 92,
  245. 106,
  246. 107,
  247. 108
  248. };
  249. auto attackable = defender.getAttackableHexes(&attacker);
  250. attackable.sort([](const auto & l, const auto & r) { return l < r; });
  251. EXPECT_EQ(expectedDef, attackable);
  252. }
  253. TEST_F(AttackableHexesTest, getAttackableHexes_DoubleWideAttacker_SingleWideDefender)
  254. {
  255. UnitFake & attacker = addDragon(60, BattleSide::ATTACKER);
  256. UnitFake & defender = addRegularMelee(90, BattleSide::DEFENDER);
  257. static const BattleHexArray expectedDef =
  258. {
  259. 72,
  260. 73,
  261. 74,
  262. 89,
  263. 92,
  264. 106,
  265. 107,
  266. 108
  267. };
  268. auto attackable = defender.getAttackableHexes(&attacker);
  269. attackable.sort([](const auto & l, const auto & r) { return l < r; });
  270. EXPECT_EQ(expectedDef, attackable);
  271. }
  272. TEST_F(AttackableHexesTest, getAttackableHexes_DoubleWideAttacker_DoubleWideDefender)
  273. {
  274. UnitFake & attacker = addDragon(60, BattleSide::ATTACKER);
  275. UnitFake & defender = addDragon(90, BattleSide::DEFENDER);
  276. static const BattleHexArray expectedDef =
  277. {
  278. 72,
  279. 73,
  280. 74,
  281. 75,
  282. 89,
  283. 93,
  284. 106,
  285. 107,
  286. 108,
  287. 109
  288. };
  289. auto attackable = defender.getAttackableHexes(&attacker);
  290. attackable.sort([](const auto & l, const auto & r) { return l < r; });
  291. EXPECT_EQ(expectedDef, attackable);
  292. }
  293. //// CERBERI 3-HEADED ATTACKS
  294. TEST_F(AttackableHexesTest, CerberiAttackerRight)
  295. {
  296. // #
  297. // X A D
  298. // #
  299. UnitFake & attacker = addCerberi(35, BattleSide::ATTACKER);
  300. UnitFake & defender = addRegularMelee(attacker.getPosition().cloneInDirection(BattleHex::RIGHT), BattleSide::DEFENDER);
  301. UnitFake & right = addRegularMelee(attacker.getPosition().cloneInDirection(BattleHex::BOTTOM_RIGHT), BattleSide::DEFENDER);
  302. UnitFake & left = addRegularMelee(attacker.getPosition().cloneInDirection(BattleHex::TOP_RIGHT), BattleSide::DEFENDER);
  303. auto attacked = getAttackedUnits(attacker, defender, defender.getPosition());
  304. EXPECT_TRUE(vstd::contains(attacked, &right));
  305. EXPECT_TRUE(vstd::contains(attacked, &left));
  306. }
  307. TEST_F(AttackableHexesTest, CerberiAttackerTopRight)
  308. {
  309. // # D
  310. // X A #
  311. //
  312. UnitFake & attacker = addCerberi(35, BattleSide::ATTACKER);
  313. UnitFake & defender = addRegularMelee(attacker.getPosition().cloneInDirection(BattleHex::TOP_RIGHT), BattleSide::DEFENDER);
  314. UnitFake & right = addRegularMelee(attacker.getPosition().cloneInDirection(BattleHex::RIGHT), BattleSide::DEFENDER);
  315. UnitFake & left = addRegularMelee(attacker.getPosition().cloneInDirection(BattleHex::TOP_LEFT), BattleSide::DEFENDER);
  316. auto attacked = getAttackedUnits(attacker, defender, defender.getPosition());
  317. EXPECT_TRUE(vstd::contains(attacked, &right));
  318. EXPECT_TRUE(vstd::contains(attacked, &left));
  319. }
  320. TEST_F(AttackableHexesTest, CerberiAttackerTopMiddle)
  321. {
  322. // # D #
  323. // X A
  324. //
  325. UnitFake & attacker = addCerberi(35, BattleSide::ATTACKER);
  326. UnitFake & defender = addRegularMelee(attacker.getPosition().cloneInDirection(BattleHex::TOP_LEFT), BattleSide::DEFENDER);
  327. UnitFake & right = addRegularMelee(attacker.getPosition().cloneInDirection(BattleHex::TOP_RIGHT), BattleSide::DEFENDER);
  328. UnitFake & left = addRegularMelee(attacker.occupiedHex().cloneInDirection(BattleHex::TOP_LEFT), BattleSide::DEFENDER);
  329. auto attacked = getAttackedUnits(attacker, defender, defender.getPosition());
  330. EXPECT_TRUE(vstd::contains(attacked, &right));
  331. EXPECT_TRUE(vstd::contains(attacked, &left));
  332. }
  333. TEST_F(AttackableHexesTest, CerberiAttackerTopLeft)
  334. {
  335. // D #
  336. // # X A
  337. //
  338. UnitFake & attacker = addCerberi(40, BattleSide::ATTACKER);
  339. UnitFake & defender = addRegularMelee(attacker.occupiedHex().cloneInDirection(BattleHex::TOP_LEFT), BattleSide::DEFENDER);
  340. UnitFake & right = addRegularMelee(attacker.occupiedHex().cloneInDirection(BattleHex::TOP_RIGHT), BattleSide::DEFENDER);
  341. UnitFake & left = addRegularMelee(attacker.occupiedHex().cloneInDirection(BattleHex::LEFT), BattleSide::DEFENDER);
  342. auto attacked = getAttackedUnits(attacker, defender, defender.getPosition());
  343. EXPECT_TRUE(vstd::contains(attacked, &right));
  344. EXPECT_TRUE(vstd::contains(attacked, &left));
  345. }
  346. TEST_F(AttackableHexesTest, CerberiAttackerLeft)
  347. {
  348. // #
  349. // D X A
  350. // #
  351. UnitFake & attacker = addCerberi(40, BattleSide::ATTACKER);
  352. UnitFake & defender = addRegularMelee(attacker.occupiedHex().cloneInDirection(BattleHex::LEFT), BattleSide::DEFENDER);
  353. UnitFake & right = addRegularMelee(attacker.occupiedHex().cloneInDirection(BattleHex::TOP_LEFT), BattleSide::DEFENDER);
  354. UnitFake & left = addRegularMelee(attacker.occupiedHex().cloneInDirection(BattleHex::BOTTOM_LEFT), BattleSide::DEFENDER);
  355. auto attacked = getAttackedUnits(attacker, defender, defender.getPosition());
  356. EXPECT_TRUE(vstd::contains(attacked, &right));
  357. EXPECT_TRUE(vstd::contains(attacked, &left));
  358. }
  359. //// DRAGON BREATH AS ATTACKER
  360. TEST_F(AttackableHexesTest, DragonRightRegular_RightHorithontalBreath)
  361. {
  362. // X A D #
  363. UnitFake & attacker = addDragon(35, BattleSide::ATTACKER);
  364. UnitFake & defender = addRegularMelee(36, BattleSide::DEFENDER);
  365. UnitFake & next = addRegularMelee(37, BattleSide::DEFENDER);
  366. auto attacked = getAttackedUnits(attacker, defender, defender.getPosition());
  367. EXPECT_TRUE(vstd::contains(attacked, &next));
  368. }
  369. TEST_F(AttackableHexesTest, DragonDragonBottomRightHead_BottomRightBreathFromHead)
  370. {
  371. // X A
  372. // D X target D
  373. // #
  374. UnitFake & attacker = addDragon(35, BattleSide::ATTACKER);
  375. UnitFake & defender = addDragon(attacker.getPosition().cloneInDirection(BattleHex::BOTTOM_RIGHT), BattleSide::DEFENDER);
  376. UnitFake & next = addRegularMelee(defender.getPosition().cloneInDirection(BattleHex::BOTTOM_RIGHT), BattleSide::DEFENDER);
  377. auto attacked = getAttackedUnits(attacker, defender, defender.getPosition());
  378. EXPECT_TRUE(vstd::contains(attacked, &next));
  379. }
  380. TEST_F(AttackableHexesTest, DragonDragonVerticalDownHead_VerticalDownBreathFromHead)
  381. {
  382. // X A
  383. // D X target D
  384. // #
  385. UnitFake & attacker = addDragon(35, BattleSide::ATTACKER);
  386. UnitFake & defender = addDragon(attacker.getPosition().cloneInDirection(BattleHex::BOTTOM_LEFT), BattleSide::DEFENDER);
  387. UnitFake & next = addRegularMelee(defender.occupiedHex().cloneInDirection(BattleHex::BOTTOM_RIGHT), BattleSide::DEFENDER);
  388. auto attacked = getAttackedUnits(attacker, defender, defender.getPosition());
  389. EXPECT_TRUE(vstd::contains(attacked, &next));
  390. }
  391. TEST_F(AttackableHexesTest, DragonDragonVerticalDownHead_VerticalRightBreathFromHead)
  392. {
  393. // X A
  394. // D X target X
  395. // #
  396. UnitFake & attacker = addDragon(35, BattleSide::ATTACKER);
  397. UnitFake & defender = addDragon(attacker.getPosition().cloneInDirection(BattleHex::BOTTOM_LEFT), BattleSide::DEFENDER);
  398. UnitFake & next = addRegularMelee(defender.occupiedHex().cloneInDirection(BattleHex::BOTTOM_RIGHT), BattleSide::DEFENDER);
  399. auto attacked = getAttackedUnits(attacker, defender, defender.occupiedHex());
  400. EXPECT_TRUE(vstd::contains(attacked, &next));
  401. }
  402. TEST_F(AttackableHexesTest, DragonDragonVerticalDownBack_VerticalDownBreath)
  403. {
  404. // X A
  405. // D X target X
  406. // #
  407. UnitFake & attacker = addDragon(37, BattleSide::ATTACKER);
  408. UnitFake & defender = addDragon(attacker.occupiedHex().cloneInDirection(BattleHex::BOTTOM_LEFT), BattleSide::DEFENDER);
  409. UnitFake & next = addRegularMelee(defender.getPosition().cloneInDirection(BattleHex::BOTTOM_RIGHT), BattleSide::DEFENDER);
  410. auto attacked = getAttackedUnits(attacker, defender, defender.occupiedHex());
  411. EXPECT_TRUE(vstd::contains(attacked, &next));
  412. }
  413. TEST_F(AttackableHexesTest, DragonDragonHeadBottomRight_BottomRightBreathFromHead)
  414. {
  415. // X A
  416. // D X target D
  417. // #
  418. UnitFake & attacker = addDragon(37, BattleSide::ATTACKER);
  419. UnitFake & defender = addDragon(attacker.occupiedHex().cloneInDirection(BattleHex::BOTTOM_LEFT), BattleSide::DEFENDER);
  420. UnitFake & next = addRegularMelee(defender.getPosition().cloneInDirection(BattleHex::BOTTOM_RIGHT), BattleSide::DEFENDER);
  421. auto attacked = getAttackedUnits(attacker, defender, defender.getPosition());
  422. EXPECT_TRUE(vstd::contains(attacked, &next));
  423. }
  424. TEST_F(AttackableHexesTest, DragonLeftBottomDragonBackToBack_LeftBottomBreathFromBackHex)
  425. {
  426. // X A
  427. // D X target X
  428. // #
  429. UnitFake & attacker = addDragon(8, BattleSide::ATTACKER);
  430. UnitFake & defender = addDragon(attacker.occupiedHex().cloneInDirection(BattleHex::BOTTOM_LEFT).cloneInDirection(BattleHex::LEFT), BattleSide::DEFENDER);
  431. UnitFake & next = addRegularMelee(defender.getPosition().cloneInDirection(BattleHex::BOTTOM_RIGHT), BattleSide::DEFENDER);
  432. auto attacked = getAttackedUnits(attacker, defender, defender.occupiedHex());
  433. EXPECT_TRUE(vstd::contains(attacked, &next));
  434. }
  435. //// DRAGON BREATH AS DEFENDER
  436. TEST_F(AttackableHexesTest, DragonDragonVerticalDownHeadReverse_VerticalDownBreathFromHead)
  437. {
  438. // A X
  439. // X D target D
  440. // #
  441. UnitFake & attacker = addDragon(36, BattleSide::DEFENDER);
  442. UnitFake & defender = addDragon(attacker.getPosition().cloneInDirection(BattleHex::BOTTOM_RIGHT), BattleSide::ATTACKER);
  443. UnitFake & next = addRegularMelee(defender.occupiedHex().cloneInDirection(BattleHex::BOTTOM_LEFT), BattleSide::ATTACKER);
  444. auto attacked = getAttackedUnits(attacker, defender, defender.getPosition());
  445. EXPECT_TRUE(vstd::contains(attacked, &next));
  446. }
  447. TEST_F(AttackableHexesTest, DragonVerticalDownDragonBackReverse_VerticalDownBreath)
  448. {
  449. // A X
  450. // X D target X
  451. // #
  452. UnitFake & attacker = addDragon(36, BattleSide::DEFENDER);
  453. UnitFake & defender = addDragon(attacker.occupiedHex().cloneInDirection(BattleHex::BOTTOM_RIGHT), BattleSide::ATTACKER);
  454. UnitFake & next = addRegularMelee(defender.getPosition().cloneInDirection(BattleHex::BOTTOM_LEFT), BattleSide::ATTACKER);
  455. auto attacked = getAttackedUnits(attacker, defender, defender.occupiedHex());
  456. EXPECT_TRUE(vstd::contains(attacked, &next));
  457. }
  458. TEST_F(AttackableHexesTest, DragonRightBottomDragonHeadReverse_RightBottomBreathFromHeadHex)
  459. {
  460. // A X
  461. // X D target D
  462. UnitFake & attacker = addDragon(36, BattleSide::DEFENDER);
  463. UnitFake & defender = addDragon(attacker.occupiedHex().cloneInDirection(BattleHex::BOTTOM_RIGHT), BattleSide::ATTACKER);
  464. UnitFake & next = addRegularMelee(defender.getPosition().cloneInDirection(BattleHex::BOTTOM_LEFT), BattleSide::ATTACKER);
  465. auto attacked = getAttackedUnits(attacker, defender, defender.getPosition());
  466. EXPECT_TRUE(vstd::contains(attacked, &next));
  467. }
  468. TEST_F(AttackableHexesTest, DefenderPositionOverride_BreathCountsHypoteticDefenderPosition)
  469. {
  470. // # N
  471. // X D target D
  472. // A X
  473. UnitFake & attacker = addDragon(35, BattleSide::DEFENDER);
  474. UnitFake & defender = addDragon(8, BattleSide::ATTACKER);
  475. UnitFake & next = addDragon(1, BattleSide::ATTACKER);
  476. startBattle();
  477. redirectUnitsToFake();
  478. auto attacked = subject.getAttackedBattleUnits(
  479. &attacker,
  480. &defender,
  481. 19,
  482. false,
  483. attacker.getPosition(),
  484. 19);
  485. EXPECT_TRUE(vstd::contains(attacked, &next));
  486. }
  487. class BattleFinishedTest : public CBattleInfoCallbackTest
  488. {
  489. public:
  490. void expectBattleNotFinished()
  491. {
  492. auto ret = subject.battleIsFinished();
  493. EXPECT_FALSE(ret);
  494. }
  495. void expectBattleDraw()
  496. {
  497. auto ret = subject.battleIsFinished();
  498. EXPECT_TRUE(ret);
  499. EXPECT_EQ(*ret, BattleSide::NONE);
  500. }
  501. void expectBattleWinner(BattleSide side)
  502. {
  503. auto ret = subject.battleIsFinished();
  504. EXPECT_TRUE(ret);
  505. EXPECT_EQ(*ret, side);
  506. }
  507. void expectBattleLooser(BattleSide side)
  508. {
  509. auto ret = subject.battleIsFinished();
  510. EXPECT_TRUE(ret);
  511. EXPECT_NE(*ret, side);
  512. }
  513. void setDefaultExpectations()
  514. {
  515. redirectUnitsToFake();
  516. unitsFake.setDefaultBonusExpectations();
  517. EXPECT_CALL(battleMock, getUnitsIf(_)).Times(1);
  518. }
  519. };
  520. TEST_F(BattleFinishedTest, DISABLED_NoBattleIsDraw)
  521. {
  522. expectBattleDraw();
  523. }
  524. TEST_F(BattleFinishedTest, EmptyBattleIsDraw)
  525. {
  526. setDefaultExpectations();
  527. startBattle();
  528. expectBattleDraw();
  529. }
  530. TEST_F(BattleFinishedTest, LastAliveUnitWins)
  531. {
  532. UnitFake & unit = unitsFake.add(BattleSide::DEFENDER);
  533. unit.makeAlive();
  534. unit.setDefaultState();
  535. setDefaultExpectations();
  536. startBattle();
  537. expectBattleWinner(BattleSide::DEFENDER);
  538. }
  539. TEST_F(BattleFinishedTest, TwoUnitsContinueFight)
  540. {
  541. UnitFake & unit1 = unitsFake.add(BattleSide::ATTACKER);
  542. unit1.makeAlive();
  543. UnitFake & unit2 = unitsFake.add(BattleSide::DEFENDER);
  544. unit2.makeAlive();
  545. setDefaultExpectations();
  546. startBattle();
  547. expectBattleNotFinished();
  548. }
  549. TEST_F(BattleFinishedTest, LastWarMachineNotWins)
  550. {
  551. UnitFake & unit = unitsFake.add(BattleSide::ATTACKER);
  552. unit.makeAlive();
  553. unit.makeWarMachine();
  554. unit.setDefaultState();
  555. setDefaultExpectations();
  556. startBattle();
  557. expectBattleLooser(BattleSide::ATTACKER);
  558. }
  559. TEST_F(BattleFinishedTest, LastWarMachineLoose)
  560. {
  561. try
  562. {
  563. UnitFake & unit1 = unitsFake.add(BattleSide::ATTACKER);
  564. unit1.makeAlive();
  565. unit1.setDefaultState();
  566. UnitFake & unit2 = unitsFake.add(BattleSide::DEFENDER);
  567. unit2.makeAlive();
  568. unit2.makeWarMachine();
  569. unit2.setDefaultState();
  570. setDefaultExpectations();
  571. startBattle();
  572. expectBattleWinner(BattleSide::ATTACKER);
  573. }
  574. catch(const std::exception & e)
  575. {
  576. logGlobal->error(e.what());
  577. }
  578. }
  579. class BattleMatchOwnerTest : public CBattleInfoCallbackTest
  580. {
  581. public:
  582. void setDefaultExpectations()
  583. {
  584. redirectUnitsToFake();
  585. unitsFake.setDefaultBonusExpectations();
  586. EXPECT_CALL(battleMock, getSidePlayer(Eq(BattleSide::ATTACKER))).WillRepeatedly(Return(PlayerColor(0)));
  587. EXPECT_CALL(battleMock, getSidePlayer(Eq(BattleSide::DEFENDER))).WillRepeatedly(Return(PlayerColor(1)));
  588. }
  589. };
  590. TEST_F(BattleMatchOwnerTest, normalToSelf)
  591. {
  592. UnitFake & unit1 = unitsFake.add(BattleSide::ATTACKER);
  593. EXPECT_CALL(unit1, unitId()).WillRepeatedly(Return(42));
  594. setDefaultExpectations();
  595. startBattle();
  596. EXPECT_TRUE(subject.battleMatchOwner(&unit1, &unit1, true));
  597. EXPECT_TRUE(subject.battleMatchOwner(&unit1, &unit1, boost::logic::indeterminate));
  598. EXPECT_FALSE(subject.battleMatchOwner(&unit1, &unit1, false));
  599. }
  600. TEST_F(BattleMatchOwnerTest, hypnotizedToSelf)
  601. {
  602. UnitFake & unit1 = unitsFake.add(BattleSide::ATTACKER);
  603. EXPECT_CALL(unit1, unitId()).WillRepeatedly(Return(42));
  604. unit1.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, BonusSourceID()));
  605. setDefaultExpectations();
  606. startBattle();
  607. EXPECT_TRUE(subject.battleMatchOwner(&unit1, &unit1, true));
  608. EXPECT_TRUE(subject.battleMatchOwner(&unit1, &unit1, boost::logic::indeterminate));
  609. EXPECT_FALSE(subject.battleMatchOwner(&unit1, &unit1, false));
  610. }
  611. TEST_F(BattleMatchOwnerTest, normalToNormalAlly)
  612. {
  613. UnitFake & unit1 = unitsFake.add(BattleSide::ATTACKER);
  614. EXPECT_CALL(unit1, unitId()).WillRepeatedly(Return(42));
  615. UnitFake & unit2 = unitsFake.add(BattleSide::ATTACKER);
  616. EXPECT_CALL(unit2, unitId()).WillRepeatedly(Return(4242));
  617. setDefaultExpectations();
  618. startBattle();
  619. EXPECT_TRUE(subject.battleMatchOwner(&unit1, &unit2, true));
  620. EXPECT_TRUE(subject.battleMatchOwner(&unit1, &unit2, boost::logic::indeterminate));
  621. EXPECT_FALSE(subject.battleMatchOwner(&unit1, &unit2, false));
  622. }
  623. TEST_F(BattleMatchOwnerTest, hypnotizedToNormalAlly)
  624. {
  625. UnitFake & unit1 = unitsFake.add(BattleSide::ATTACKER);
  626. EXPECT_CALL(unit1, unitId()).WillRepeatedly(Return(42));
  627. unit1.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, BonusSourceID()));
  628. UnitFake & unit2 = unitsFake.add(BattleSide::ATTACKER);
  629. EXPECT_CALL(unit2, unitId()).WillRepeatedly(Return(4242));
  630. setDefaultExpectations();
  631. startBattle();
  632. EXPECT_FALSE(subject.battleMatchOwner(&unit1, &unit2, true));
  633. EXPECT_TRUE(subject.battleMatchOwner(&unit1, &unit2, boost::logic::indeterminate));
  634. EXPECT_TRUE(subject.battleMatchOwner(&unit1, &unit2, false));
  635. }
  636. TEST_F(BattleMatchOwnerTest, normalToHypnotizedAlly)
  637. {
  638. UnitFake & unit1 = unitsFake.add(BattleSide::ATTACKER);
  639. EXPECT_CALL(unit1, unitId()).WillRepeatedly(Return(42));
  640. UnitFake & unit2 = unitsFake.add(BattleSide::ATTACKER);
  641. EXPECT_CALL(unit2, unitId()).WillRepeatedly(Return(4242));
  642. unit2.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, BonusSourceID()));
  643. setDefaultExpectations();
  644. startBattle();
  645. EXPECT_TRUE(subject.battleMatchOwner(&unit1, &unit2, true));
  646. EXPECT_TRUE(subject.battleMatchOwner(&unit1, &unit2, boost::logic::indeterminate));
  647. EXPECT_FALSE(subject.battleMatchOwner(&unit1, &unit2, false));
  648. }
  649. TEST_F(BattleMatchOwnerTest, hypnotizedToHypnotizedAlly)
  650. {
  651. UnitFake & unit1 = unitsFake.add(BattleSide::ATTACKER);
  652. EXPECT_CALL(unit1, unitId()).WillRepeatedly(Return(42));
  653. unit1.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, BonusSourceID()));
  654. UnitFake & unit2 = unitsFake.add(BattleSide::ATTACKER);
  655. EXPECT_CALL(unit2, unitId()).WillRepeatedly(Return(4242));
  656. unit2.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, BonusSourceID()));
  657. setDefaultExpectations();
  658. startBattle();
  659. EXPECT_FALSE(subject.battleMatchOwner(&unit1, &unit2, true));
  660. EXPECT_TRUE(subject.battleMatchOwner(&unit1, &unit2, boost::logic::indeterminate));
  661. EXPECT_TRUE(subject.battleMatchOwner(&unit1, &unit2, false));
  662. }
  663. TEST_F(BattleMatchOwnerTest, normalToNormalEnemy)
  664. {
  665. UnitFake & unit1 = unitsFake.add(BattleSide::ATTACKER);
  666. EXPECT_CALL(unit1, unitId()).WillRepeatedly(Return(42));
  667. UnitFake & unit2 = unitsFake.add(BattleSide::DEFENDER);
  668. EXPECT_CALL(unit2, unitId()).WillRepeatedly(Return(4242));
  669. setDefaultExpectations();
  670. startBattle();
  671. EXPECT_FALSE(subject.battleMatchOwner(&unit1, &unit2, true));
  672. EXPECT_TRUE(subject.battleMatchOwner(&unit1, &unit2, boost::logic::indeterminate));
  673. EXPECT_TRUE(subject.battleMatchOwner(&unit1, &unit2, false));
  674. }
  675. TEST_F(BattleMatchOwnerTest, hypnotizedToNormalEnemy)
  676. {
  677. UnitFake & unit1 = unitsFake.add(BattleSide::ATTACKER);
  678. EXPECT_CALL(unit1, unitId()).WillRepeatedly(Return(42));
  679. unit1.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, BonusSourceID()));
  680. UnitFake & unit2 = unitsFake.add(BattleSide::DEFENDER);
  681. EXPECT_CALL(unit2, unitId()).WillRepeatedly(Return(4242));
  682. setDefaultExpectations();
  683. startBattle();
  684. EXPECT_TRUE(subject.battleMatchOwner(&unit1, &unit2, true));
  685. EXPECT_TRUE(subject.battleMatchOwner(&unit1, &unit2, boost::logic::indeterminate));
  686. EXPECT_FALSE(subject.battleMatchOwner(&unit1, &unit2, false));
  687. }
  688. TEST_F(BattleMatchOwnerTest, normalToHypnotizedEnemy)
  689. {
  690. UnitFake & unit1 = unitsFake.add(BattleSide::ATTACKER);
  691. EXPECT_CALL(unit1, unitId()).WillRepeatedly(Return(42));
  692. UnitFake & unit2 = unitsFake.add(BattleSide::DEFENDER);
  693. EXPECT_CALL(unit2, unitId()).WillRepeatedly(Return(4242));
  694. unit2.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, BonusSourceID()));
  695. setDefaultExpectations();
  696. startBattle();
  697. EXPECT_FALSE(subject.battleMatchOwner(&unit1, &unit2, true));
  698. EXPECT_TRUE(subject.battleMatchOwner(&unit1, &unit2, boost::logic::indeterminate));
  699. EXPECT_TRUE(subject.battleMatchOwner(&unit1, &unit2, false));
  700. }
  701. TEST_F(BattleMatchOwnerTest, hypnotizedToHypnotizedEnemy)
  702. {
  703. UnitFake & unit1 = unitsFake.add(BattleSide::ATTACKER);
  704. EXPECT_CALL(unit1, unitId()).WillRepeatedly(Return(42));
  705. unit1.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, BonusSourceID()));
  706. UnitFake & unit2 = unitsFake.add(BattleSide::DEFENDER);
  707. EXPECT_CALL(unit2, unitId()).WillRepeatedly(Return(4242));
  708. unit2.addNewBonus(std::make_shared<Bonus>(BonusDuration::PERMANENT, BonusType::HYPNOTIZED, BonusSource::CREATURE_ABILITY, 0, BonusSourceID()));
  709. setDefaultExpectations();
  710. startBattle();
  711. EXPECT_TRUE(subject.battleMatchOwner(&unit1, &unit2, true));
  712. EXPECT_TRUE(subject.battleMatchOwner(&unit1, &unit2, boost::logic::indeterminate));
  713. EXPECT_FALSE(subject.battleMatchOwner(&unit1, &unit2, false));
  714. }