2525#include " gameData/MilitaryConsts.h"
2626#include " gameData/SettingTypeConv.h"
2727#include < rttr/test/testHelpers.hpp>
28+ #include < boost/test/data/monomorphic.hpp>
29+ #include < boost/test/data/test_case.hpp>
2830#include < boost/test/unit_test.hpp>
2931#include < iostream>
3032
@@ -111,8 +113,10 @@ struct AttackFixtureBase : public WorldWithGCExecution<T_numPlayers, T_width, T_
111113 BOOST_TEST_REQUIRE (world.GetPointRoad (start, road.front ()) == PointRoad::Normal);
112114 }
113115
114- void AddSoldiersWithRank (MapPoint bldPos, unsigned numSoldiers, unsigned rank, unsigned numArmoredSoldiers = 0 )
116+ void AddSoldiersWithRankAndArmor (MapPoint bldPos, unsigned numSoldiers, Job soldierType,
117+ unsigned numArmoredSoldiers = 0 )
115118 {
119+ auto const rank = getSoldierRank (soldierType);
116120 BOOST_TEST_REQUIRE (rank <= world.GetGGS ().GetMaxMilitaryRank ());
117121 auto * bld = world.template GetSpecObj <nobMilitary>(bldPos);
118122 BOOST_TEST_REQUIRE (bld);
@@ -126,19 +130,19 @@ struct AttackFixtureBase : public WorldWithGCExecution<T_numPlayers, T_width, T_
126130 {
127131 world.GetPlayer (bld->GetPlayer ()).IncreaseInventoryJob (figureToAmoredSoldierEnum (&soldier), 1 );
128132 soldier.SetArmor (true );
133+ numArmoredSoldiers--;
129134 }
130135 // Let him "walk" to goal -> Already reached -> Added and all internal states set correctly
131136 soldier.WalkToGoal ();
132137 BOOST_TEST_REQUIRE (soldier.HasNoGoal ());
133- numArmoredSoldiers--;
134138 }
135139 BOOST_TEST_REQUIRE (bld->GetNumTroops () == oldNumSoldiers + numSoldiers);
136140 }
137141
138142 void AddSoldiers (MapPoint bldPos, unsigned numWeak, unsigned numStrong)
139143 {
140- AddSoldiersWithRank (bldPos, numWeak, 0 );
141- AddSoldiersWithRank (bldPos, numStrong, 4 );
144+ AddSoldiersWithRankAndArmor (bldPos, numWeak, Job::Private );
145+ AddSoldiersWithRankAndArmor (bldPos, numStrong, Job::General );
142146 }
143147};
144148
@@ -392,8 +396,8 @@ BOOST_FIXTURE_TEST_CASE(ConquerBld, AttackFixture<>)
392396 initGameRNG ();
393397
394398 AddSoldiers (milBld0Pos, 1 , 5 );
395- AddSoldiersWithRank (milBld1Pos, 1 , 0 );
396- AddSoldiersWithRank (milBld1Pos, 1 , 1 );
399+ AddSoldiersWithRankAndArmor (milBld1Pos, 1 , Job::Private );
400+ AddSoldiersWithRankAndArmor (milBld1Pos, 1 , Job::PrivateFirstClass );
397401 BuildRoadForBlds (milBld0Pos, hqPos[0 ]);
398402
399403 // Finish recruiting, carrier outhousing etc.
@@ -462,39 +466,54 @@ BOOST_FIXTURE_TEST_CASE(ArmoredSoldierLosesArmorInFight, AttackFixture<>)
462466{
463467 initGameRNG ();
464468
465- AddSoldiersWithRank (milBld0Pos, 3 , 0 , 2 );
466- AddSoldiersWithRank (milBld1Pos, 1 , 0 , 1 );
467- BuildRoadForBlds (milBld0Pos, hqPos[0 ]);
469+ AddSoldiersWithRankAndArmor (milBld0Pos, 3 , Job::General, 2 );
470+ AddSoldiersWithRankAndArmor (milBld1Pos, 1 , Job::Private, 1 );
468471
469472 // Finish recruiting, carrier outhousing etc.
470473 RTTR_SKIP_GFS (400 );
471- // Start attack ->1 (weak one first)
472- this ->Attack (milBld1Pos, 1 , false );
473- this ->Attack (milBld1Pos, 2 , false );
474+
474475 BOOST_TEST_REQUIRE (milBld0->GetNumTroops () == 3u );
475476 BOOST_TEST_REQUIRE (milBld1->GetNumTroops () == 1u );
476- // Run till attackers reach bld. 1 Soldier will leave for them.
477- // 1 stays inside till an attacker is at door
478- // 20 GFs/node + 30 GFs for leaving
479- const unsigned distance = world.CalcDistance (milBld0Pos, milBld1Pos);
480- RTTR_EXEC_TILL (distance * 20 + 30 , milBld1->GetNumTroops () == 1 );
481- BOOST_TEST_REQUIRE (milBld1->GetNumTroops () + milBld1->GetLeavingFigures ().size () == 1u );
477+
478+ // Start attack ->1 (strong one first)
479+ this ->Attack (milBld1Pos, 1 , true );
480+ RTTR_EXEC_TILL (30 , milBld0->GetNumTroops () == 2 );
481+
482+ auto armoredSoldiers = [](nobMilitary* bld) {
483+ const auto troops = bld->GetTroops ();
484+ return std::count_if (std::begin (troops), std::end (troops),
485+ [](const auto & soldier) { return soldier.HasArmor (); });
486+ };
487+
488+ auto notArmoredSoldiers = [](nobMilitary* bld) {
489+ const auto troops = bld->GetTroops ();
490+ return std::count_if (std::begin (troops), std::end (troops),
491+ [](const auto & soldier) { return !soldier.HasArmor (); });
492+ };
493+
494+ BOOST_TEST_REQUIRE (armoredSoldiers (milBld0) == 1u );
495+ BOOST_TEST_REQUIRE (notArmoredSoldiers (milBld0) == 1u );
496+
497+ // Start attack ->1 (weak one first)
498+ this ->Attack (milBld1Pos, 1 , false );
499+ RTTR_EXEC_TILL (30 , milBld0->GetNumTroops () == 1 );
500+ BOOST_TEST_REQUIRE (armoredSoldiers (milBld0) == 1u );
501+ BOOST_TEST_REQUIRE (notArmoredSoldiers (milBld0) == 0u );
502+
482503 const Inventory& attackedPlInventory = world.GetPlayer (1 ).GetInventory ();
483504 const unsigned oldWeakSoldierCt = attackedPlInventory.people [Job::Private];
484505 const unsigned oldWeakSoldierWithArmorCt =
485506 attackedPlInventory.armoredSoldiers [jobEnumToAmoredSoldierEnum (Job::Private)];
486507
487- // Once an attacker reaches the flag, the bld will send a defender
488- BOOST_TEST_REQUIRE (!milBld1->GetDefender ());
489- RTTR_EXEC_TILL (300 , milBld1->GetNumTroops () == 0 );
490- // Defender deployed, attacker at flag
491- BOOST_TEST_REQUIRE (milBld1->GetDefender ());
492- {
493- const auto figures = world.GetFigures (milBld1->GetFlagPos ());
494- BOOST_TEST_REQUIRE (figures.size () == 1u );
495- const auto & attacker = dynamic_cast <const nofAttacker&>(*figures.begin ());
496- BOOST_TEST_REQUIRE (static_cast <const nofAttacker&>(attacker).GetPlayer () == curPlayer);
497- }
508+ // Run till attackers reach flag of bld. The bld will send a defender.
509+ // 20 GFs/node + 60 GFs for leaving
510+ const unsigned distance = world.CalcDistance (milBld0Pos, milBld1Pos);
511+ RTTR_EXEC_TILL (distance * 20 + 60 , milBld1->GetDefender () != nullptr );
512+
513+ const auto figures = world.GetFigures (milBld1->GetFlagPos ());
514+ BOOST_TEST_REQUIRE (figures.size () == 1u );
515+ const auto & attacker = dynamic_cast <const nofAttacker&>(*figures.begin ());
516+ BOOST_TEST_REQUIRE (static_cast <const nofAttacker&>(attacker).GetPlayer () == curPlayer);
498517
499518 // Lets fight until defender has no armor anymore
500519 // He should not lose a hitpoint but the armor
@@ -511,7 +530,7 @@ BOOST_FIXTURE_TEST_CASE(ConquerBldCoinAddonEnable, AttackFixture<>)
511530
512531 initGameRNG ();
513532 AddSoldiers (milBld0Pos, 1 , 5 );
514- AddSoldiersWithRank (milBld1Pos, 1 , 0 );
533+ AddSoldiersWithRankAndArmor (milBld1Pos, 1 , Job::Private );
515534 // Finish recruiting, carrier outhousing etc.
516535 RTTR_SKIP_GFS (400 );
517536
@@ -535,7 +554,7 @@ BOOST_FIXTURE_TEST_CASE(ConquerBldCoinAddonDisable, AttackFixture<>)
535554
536555 initGameRNG ();
537556 AddSoldiers (milBld0Pos, 1 , 5 );
538- AddSoldiersWithRank (milBld1Pos, 1 , 0 );
557+ AddSoldiersWithRankAndArmor (milBld1Pos, 1 , Job::Private );
539558 // Finish recruiting, carrier outhousing etc.
540559 RTTR_SKIP_GFS (400 );
541560
@@ -553,52 +572,43 @@ BOOST_FIXTURE_TEST_CASE(ConquerBldCoinAddonDisable, AttackFixture<>)
553572 BOOST_TEST_REQUIRE (milBld1->IsGoldDisabled ());
554573}
555574
556- BOOST_FIXTURE_TEST_CASE (ConquerBldArmorAddonEnable, AttackFixture<>)
575+ enum Case
557576{
558- this ->ggs .setSelection (AddonId::ARMOR_CAPTURED_BLD, 1 ); // addon is active on second run
559-
560- initGameRNG ();
561- AddSoldiers (milBld0Pos, 1 , 5 );
562- AddSoldiersWithRank (milBld1Pos, 1 , 0 );
563- // Finish recruiting, carrier outhousing etc.
564- RTTR_SKIP_GFS (400 );
565-
566- // ensure that armor are disabled
567- milBld1->SetArmorAllowed (false );
568- BOOST_TEST_REQUIRE (!milBld1->IsArmorAllowed ());
569-
570- // Start attack -> 1
571- this ->Attack (milBld1Pos, 6 , false );
572- BOOST_TEST_REQUIRE (milBld0->GetNumTroops () == 1u );
573-
574- RTTR_EXEC_TILL (2000 , milBld1->GetPlayer () == curPlayer);
575-
576- // check if armor were enabled after building was captured
577- BOOST_TEST_REQUIRE (milBld1->IsArmorAllowed ());
578- }
577+ EnableAfterDisable,
578+ DisableAfterEnable,
579+ KeepEnabled,
580+ KeepDisabled
581+ };
579582
580- BOOST_FIXTURE_TEST_CASE (ConquerBldArmorAddonDisable, AttackFixture<>)
583+ BOOST_DATA_TEST_CASE_F (AttackFixture<>, ConquerBldArmorAddon,
584+ boost::unit_test::data::make (std::array{Case::EnableAfterDisable, Case::DisableAfterEnable,
585+ Case::KeepEnabled, Case::KeepDisabled}))
581586{
582- this ->ggs .setSelection (AddonId::ARMOR_CAPTURED_BLD, 2 ); // addon is active on second run
587+ if (sample == Case::EnableAfterDisable)
588+ this ->ggs .setSelection (AddonId::ARMOR_CAPTURED_BLD, 1 );
589+ else if (sample == Case::DisableAfterEnable)
590+ this ->ggs .setSelection (AddonId::ARMOR_CAPTURED_BLD, 2 );
591+ else
592+ this ->ggs .setSelection (AddonId::ARMOR_CAPTURED_BLD, 0 );
583593
584594 initGameRNG ();
585595 AddSoldiers (milBld0Pos, 1 , 5 );
586- AddSoldiersWithRank (milBld1Pos, 1 , 0 );
587- // Finish recruiting, carrier outhousing etc.
588- RTTR_SKIP_GFS (400 );
596+ AddSoldiersWithRankAndArmor (milBld1Pos, 1 , Job::Private);
589597
590- // ensure that armor are enabled
591- milBld1->SetArmorAllowed (true );
592- BOOST_TEST_REQUIRE (milBld1->IsArmorAllowed ());
598+ // ensure that armor are enabled/disabled
599+ bool armorAllowedBeforeAttack = (sample == Case::KeepEnabled || sample == Case::DisableAfterEnable);
600+ milBld1->SetArmorAllowed (armorAllowedBeforeAttack);
601+ BOOST_TEST_REQUIRE (milBld1->IsArmorAllowed () == armorAllowedBeforeAttack);
593602
594603 // Start attack -> 1
595- this ->Attack (milBld1Pos, 6 , false );
604+ this ->Attack (milBld1Pos, 5 , false );
596605 BOOST_TEST_REQUIRE (milBld0->GetNumTroops () == 1u );
597606
598607 RTTR_EXEC_TILL (2000 , milBld1->GetPlayer () == curPlayer);
599608
600- // check if armor were disabled after building was captured
601- BOOST_TEST_REQUIRE (!milBld1->IsArmorAllowed ());
609+ // check if armor were enabled/disabled after building was captured
610+ bool armorAlloweAfterCaptured = (sample == Case::KeepEnabled || sample == Case::EnableAfterDisable);
611+ BOOST_TEST_REQUIRE (milBld1->IsArmorAllowed () == armorAlloweAfterCaptured);
602612}
603613
604614using AttackFixture4P = AttackFixture<4 , 32 , 34 >;
@@ -616,7 +626,7 @@ BOOST_FIXTURE_TEST_CASE(ConquerWithMultipleWalkingIn, AttackFixture4P)
616626 this ->ChangeMilitary (milSettings);
617627
618628 AddSoldiers (milBld0Pos, 0 , 6 );
619- AddSoldiersWithRank (milBld1Pos, 1 , 0 );
629+ AddSoldiersWithRankAndArmor (milBld1Pos, 1 , Job::Private );
620630 MapPoint milBld1FlagPos = world.GetNeighbour (milBld1Pos, Direction::SouthEast);
621631
622632 // Scenario 1: Attack with one soldier.
@@ -643,7 +653,7 @@ BOOST_FIXTURE_TEST_CASE(ConquerWithMultipleWalkingIn, AttackFixture4P)
643653 // Door opened
644654 BOOST_TEST_REQUIRE (milBld1->IsDoorOpen ());
645655 // New soldiers walked in
646- AddSoldiersWithRank (milBld1Pos, 4 , 0 );
656+ AddSoldiersWithRankAndArmor (milBld1Pos, 4 , Job::Private );
647657 // Let attacker walk in (try it at least)
648658 RTTR_EXEC_TILL (20 , attacker.GetPos () == milBld1Pos);
649659 RTTR_EXEC_TILL (20 , attacker.GetPos () == milBld1FlagPos);
@@ -678,7 +688,7 @@ BOOST_FIXTURE_TEST_CASE(ConquerWithMultipleWalkingIn, AttackFixture4P)
678688 MapPoint bldPos = hqPos[curPlayer] + MapPoint (3 , 0 );
679689 auto * alliedBld = static_cast <nobMilitary*>(
680690 BuildingFactory::CreateBuilding (world, BuildingType::Guardhouse, bldPos, curPlayer, Nation::Africans));
681- AddSoldiersWithRank (bldPos, 2 , 0 );
691+ AddSoldiersWithRankAndArmor (bldPos, 2 , Job::Private );
682692 this ->Attack (milBld1Pos, 1 , false );
683693 BOOST_TEST_REQUIRE (alliedBld->GetLeavingFigures ().size () == 1u );
684694 auto & alliedAttacker = dynamic_cast <nofAttacker&>(alliedBld->GetLeavingFigures ().front ());
@@ -687,7 +697,7 @@ BOOST_FIXTURE_TEST_CASE(ConquerWithMultipleWalkingIn, AttackFixture4P)
687697 bldPos = hqPos[curPlayer] + MapPoint (3 , 0 );
688698 auto * hostileBld = static_cast <nobMilitary*>(
689699 BuildingFactory::CreateBuilding (world, BuildingType::Guardhouse, bldPos, curPlayer, Nation::Africans));
690- AddSoldiersWithRank (bldPos, 2 , 0 );
700+ AddSoldiersWithRankAndArmor (bldPos, 2 , Job::Private );
691701 this ->Attack (milBld1Pos, 1 , false );
692702 BOOST_TEST_REQUIRE (hostileBld->GetLeavingFigures ().size () == 1u );
693703 auto & hostileAttacker = dynamic_cast <nofAttacker&>(hostileBld->GetLeavingFigures ().front ());
@@ -764,7 +774,7 @@ BOOST_FIXTURE_TEST_CASE(ConquerWithCarriersWalkingIn, AttackFixture<2>)
764774 // 1. Carrier with coin walking in the building
765775 // 2. Carrier with coin walking out of the building
766776 AddSoldiers (milBld0Pos, 0 , 6 );
767- AddSoldiersWithRank (milBld1Pos, 1 , 0 );
777+ AddSoldiersWithRankAndArmor (milBld1Pos, 1 , Job::Private );
768778 MapPoint milBld1FlagPos = world.GetNeighbour (milBld1Pos, Direction::SouthEast);
769779
770780 curPlayer = 1 ;
@@ -893,10 +903,10 @@ BOOST_FIXTURE_TEST_CASE(DestroyRoadsOnConquer, DestroyRoadsOnConquerFixture)
893903 BuildingFactory::CreateBuilding (world, BuildingType::Barracks, rightBldPos, 1 , Nation::Babylonians);
894904 BOOST_TEST_REQUIRE (rightBld);
895905
896- AddSoldiersWithRank (leftBldPos, 1 , 0 );
897- AddSoldiersWithRank (rightBldPos, 1 , 0 );
898- AddSoldiersWithRank (milBld1Pos, 1 , 0 );
899- AddSoldiersWithRank (milBld0Pos, 6 , 4 );
906+ AddSoldiersWithRankAndArmor (leftBldPos, 1 , Job::Private );
907+ AddSoldiersWithRankAndArmor (rightBldPos, 1 , Job::Private );
908+ AddSoldiersWithRankAndArmor (milBld1Pos, 1 , Job::Private );
909+ AddSoldiersWithRankAndArmor (milBld0Pos, 6 , Job::General );
900910
901911 curPlayer = 1 ;
902912 // Build 2 roads to attack building to test that destroying them does not cause a bug
@@ -942,8 +952,8 @@ struct FreeFightFixture : AttackFixture<2>
942952 : attackerBld(*milBld0), attackedBld(*milBld1), attackedBldPos(milBld1Pos),
943953 fightSpot (attackedBldPos - MapPoint(3 , 0 ))
944954 {
945- AddSoldiersWithRank (milBld0Pos, 6 , 0 );
946- AddSoldiersWithRank (milBld1Pos, 6 , 0 );
955+ AddSoldiersWithRankAndArmor (milBld0Pos, 6 , Job::Private );
956+ AddSoldiersWithRankAndArmor (milBld1Pos, 6 , Job::Private );
947957 this ->Attack (attackedBldPos, 1 , true );
948958 auto & attacker = dynamic_cast <nofAttacker&>(attackerBld.GetLeavingFigures ().front ());
949959 attacker_ = &attacker;
0 commit comments