LCOV - code coverage report
Current view: top level - shared - Rules.cpp (source / functions) Hit Total Coverage
Test: code-coverage.info.cleaned Lines: 242 330 73.3 %
Date: 2023-01-28 00:08:57 Functions: 21 25 84.0 %

          Line data    Source code
       1             : #include <shared.hpp>
       2             : #include <algorithm>
       3             : #include <vector>
       4             : #include <array>
       5             : #include <iostream>
       6             : 
       7             : #define RULESLENGTH 16
       8             : #define CARAVAN_STEPS_AT_LEVEL_1 4
       9             : #define CARAVAN_STEPS_AT_LEVEL_2 5
      10             : #define CARAVAN_STEPS_AT_LEVEL_3 7
      11             : #define CARAVAN_STEPS_AT_LEVEL_4 7
      12             : 
      13             : #define CARVAN_NUMBER_AT_LEVEL_1 1
      14             : #define CARVAN_NUMBER_AT_LEVEL_2 2
      15             : #define CARVAN_NUMBER_AT_LEVEL_3 2
      16             : #define CARVAN_NUMBER_AT_LEVEL_4 3
      17             : 
      18             : #define NUMBER_PAWNS_ECONOMY_LVL_1 2
      19             : 
      20             : using namespace shared;
      21             : 
      22             : typedef std::vector<std::shared_ptr<std::variant<Caravan, Barbarian, BarbarianVillage, ControlPawn, City>>> elementList;
      23             : 
      24             : /**
      25             :  * @file Rules.cpp
      26             :  * @fn Rules::Rules(unsigned ruleId)
      27             :  * @brief constructor of Rules, define the ruleId of created rule.
      28             :  */
      29           9 : Rules::Rules()
      30             : {
      31           9 : }
      32             : 
      33             : /**
      34             :  * @file Rules.cpp
      35             :  * @fn void Rules::runTheRule(RuleArgsStruct &args)
      36             :  * @brief This function aim to run the rule of the card
      37             :  * @param args : struct containing all the arguments needed to run the rule
      38             :  */
      39          11 : bool Rules::runTheRule(RuleArgsStruct &args)
      40             : {
      41          11 :     switch (args.ruleId)
      42             :     {
      43           1 :     case CardsEnum::economy:
      44           1 :         return playEconomyCard(args);
      45           7 :     case CardsEnum::science:
      46           7 :         return playScienceCard(args);
      47           1 :     case CardsEnum::military:
      48           1 :         return playMilitaryCard(args);
      49           1 :     case CardsEnum::culture:
      50           1 :         return playCultureCard(args);
      51           1 :     case CardsEnum::industry:
      52           1 :         return playIndustryCard(args);
      53           0 :     default:
      54           0 :         return false;
      55             :     }
      56             : }
      57             : 
      58             : /// ECONOMY CARD ///
      59             : /**
      60             :  * @file Rules.cpp
      61             :  * @fn void Rules::playEconomyCard(RuleArgsStruct &args)
      62             :  * @brief This function aim to run the rule of the economy card
      63             :  * @param args : struct containing all the arguments needed to run the rule
      64             :  */
      65           1 : bool Rules::playEconomyCard(RuleArgsStruct &args)
      66             : {
      67           1 :     std::vector<std::array<unsigned, 2>> caravanMovementPath = args.caravanMovementPath;
      68           1 :     std::shared_ptr<Map> map = args.gameMap;
      69           1 :     unsigned numberOfBoxUsed = args.numberOfBoxUsed;
      70             : 
      71           1 :     if (numberOfBoxUsed > args.currentPlayer->getNumberOfBox(CardsEnum::economy))
      72             :     {
      73           0 :         return false;
      74             :     }
      75             : 
      76           1 :     unsigned cardLevel = args.currentPlayer->getLevelOfCard(CardsEnum::economy);
      77             : 
      78           2 :     elementList barbarianList = checkIfBarbarianIsOnThePath(caravanMovementPath, map);
      79           1 :     if (barbarianList.size() > 0 && cardLevel != 2)
      80             :     {
      81           0 :         return false;
      82             :     }
      83             : 
      84           1 :     bool isWaterOnThePath = checkIfWaterIsOnThePath(caravanMovementPath, map);
      85           1 :     if (isWaterOnThePath && cardLevel < 3)
      86             :     {
      87           0 :         return false;
      88             :     }
      89             : 
      90           1 :     unsigned maxLevelReachable = args.currentPlayer->getDificultyOfCard(CardsEnum::economy); // TODO: check if the player can reach a higher level depending on his caracteristics
      91           4 :     for (auto &element : caravanMovementPath)
      92             :     {
      93           3 :         if ((*map)(element[0], element[1])->getFieldLevel() > (FieldLevel)maxLevelReachable)
      94             :         {
      95           0 :             return false;
      96             :         }
      97             :     }
      98             : 
      99           1 :     std::vector<std::shared_ptr<Caravan>> caravans = args.currentPlayer->getCaravans();
     100             : 
     101           1 :     switch (cardLevel)
     102             :     {
     103           1 :     case 1:
     104           1 :         if (!verifyIfPathSizeIsCorrect(caravanMovementPath.size(), CARAVAN_STEPS_AT_LEVEL_1 + numberOfBoxUsed))
     105             :         {
     106           0 :             return false;
     107             :         }
     108           1 :         addCaravanAfterCardAmelioration(caravans, args.currentPlayer, CARVAN_NUMBER_AT_LEVEL_1);
     109             : 
     110           1 :         moveCaravan(caravans, caravanMovementPath.at(0), caravanMovementPath.at(caravanMovementPath.size() - 1), map, args.currentPlayer);
     111           1 :         break;
     112           0 :     case 2:
     113           0 :         if (!verifyIfPathSizeIsCorrect(caravanMovementPath.size(), CARAVAN_STEPS_AT_LEVEL_2 + numberOfBoxUsed))
     114             :         {
     115           0 :             return false;
     116             :         }
     117           0 :         addCaravanAfterCardAmelioration(caravans, args.currentPlayer, CARVAN_NUMBER_AT_LEVEL_2);
     118           0 :         if (barbarianList.size() > 0)
     119             :         {
     120           0 :             for (int i = 0; i < (int)barbarianList.size(); i++)
     121             :             {
     122           0 :                 (std::get<Barbarian>(*barbarianList.at(i))).kill();
     123           0 :                 args.currentPlayer->addBox(CardsEnum::economy, 1);
     124             :             }
     125             :         }
     126           0 :         moveCaravan(caravans, caravanMovementPath.at(0), caravanMovementPath.at(caravanMovementPath.size() - 1), map, args.currentPlayer);
     127             :         // TODO : make caravanMovementPath a vector of vector to allow to move several caravans
     128             :         // moveCaravan(caravans, caravanMovementPath.at(0), caravanMovementPath.at(caravanMovementPath.size() - 1), map, args.currentPlayer);
     129           0 :         break;
     130           0 :     case 3:
     131           0 :         if (!verifyIfPathSizeIsCorrect(caravanMovementPath.size(), CARAVAN_STEPS_AT_LEVEL_3 + numberOfBoxUsed))
     132             :         {
     133           0 :             return false;
     134             :         }
     135           0 :         addCaravanAfterCardAmelioration(caravans, args.currentPlayer, CARVAN_NUMBER_AT_LEVEL_3);
     136           0 :         moveCaravan(caravans, caravanMovementPath.at(0), caravanMovementPath.at(caravanMovementPath.size() - 1), map, args.currentPlayer);
     137             :         // moveCaravan(caravans, caravanMovementPath.at(0), caravanMovementPath.at(caravanMovementPath.size() - 1), map, args.currentPlayer);
     138             :         // exchangeRessourceWithOtherPlayer(); //  TODO: allow to exchange ressource with other player
     139           0 :         break;
     140           0 :     case 4:
     141           0 :         if (!verifyIfPathSizeIsCorrect(caravanMovementPath.size(), CARAVAN_STEPS_AT_LEVEL_4 + numberOfBoxUsed))
     142             :         {
     143           0 :             return false;
     144             :         }
     145           0 :         addCaravanAfterCardAmelioration(caravans, args.currentPlayer, CARVAN_NUMBER_AT_LEVEL_4);
     146           0 :         moveCaravan(caravans, caravanMovementPath.at(0), caravanMovementPath.at(caravanMovementPath.size() - 1), map, args.currentPlayer);
     147             :         // moveCaravan(caravans, caravanMovementPath.at(0), caravanMovementPath.at(caravanMovementPath.size() - 1), map, args.currentPlayer);
     148             :         // moveCaravan(caravans, caravanMovementPath.at(0), caravanMovementPath.at(caravanMovementPath.size() - 1), map, args.currentPlayer);
     149             :         // playAnotherCard(); // TODO: allow to play another card
     150           0 :         break;
     151           0 :     default:
     152           0 :         return false;
     153             :     }
     154             : 
     155           1 :     roundCards(args.currentPlayer, args.ruleId);
     156           1 :     return true;
     157           1 : }
     158             : 
     159             : /**
     160             :  * @file Rules.cpp
     161             :  * @fn bool Rules::verifyIfPathSizeIsCorrect(int pathSize, int maxPathSize)
     162             :  * @brief This function aim to verify if the path size is correct
     163             :  * @param pathSize the size of the path
     164             :  * @param maxPathSize the max size of the path
     165             :  */
     166           1 : bool Rules::verifyIfPathSizeIsCorrect(int pathSize, int maxPathSize)
     167             : {
     168           1 :     if (pathSize > maxPathSize)
     169             :     {
     170           0 :         return false;
     171             :     }
     172           1 :     return true;
     173             : }
     174             : 
     175             : /**
     176             :  * @file Rules.cpp
     177             :  * @fn void Rules::addCaravanAfterCardAmelioration(std::vector<std::shared_ptr<Caravan>> &caravans, std::shared_ptr<Player> currentPlayer, int numberOfCaravans)
     178             :  * @brief This function aim to add caravan after the card amelioration
     179             :  * @param caravans the caravans of the player
     180             :  * @param currentPlayer the current player
     181             :  * @param numberOfCaravans the number of caravans related to the card level
     182             :  */
     183           1 : void Rules::addCaravanAfterCardAmelioration(std::vector<std::shared_ptr<Caravan>> &caravans, std::shared_ptr<Player> currentPlayer, int numberOfCaravans)
     184             : {
     185           2 :     while (caravans.size() < (std::size_t)numberOfCaravans)
     186             :     {
     187           1 :         std::array<unsigned, 2> pos = {0, 0};
     188           1 :         std::shared_ptr<Caravan> caravan = std::make_shared<Caravan>(pos, currentPlayer->getName());
     189           1 :         currentPlayer->addCaravan(caravan);
     190           1 :         caravans.push_back(caravan);
     191           1 :     }
     192           1 : }
     193             : 
     194             : /**
     195             :  * @file Rules.cpp
     196             :  * @fn bool Rules::moveCaravan(std::vector<std::shared_ptr<Caravan>> caravans, std::array<unsigned, 2> pos1, std::array<unsigned, 2> pos2, std::shared_ptr<Map> map, std::shared_ptr<Player> currentPlayer)
     197             :  * @brief This function aim to move the caravan
     198             :  * @param caravans the caravans of the player
     199             :  * @param pos1 the first position of the caravan
     200             :  * @param pos2 the second position of the caravan
     201             :  * @param map the map
     202             :  *
     203             :  */
     204           1 : bool Rules::moveCaravan(std::vector<std::shared_ptr<Caravan>> caravans, std::array<unsigned, 2> pos1, std::array<unsigned, 2> pos2, std::shared_ptr<Map> map, std::shared_ptr<Player> currentPlayer)
     205             : {
     206           2 :     for (auto caravan : caravans)
     207             :     {
     208           1 :         if (caravan->getPosition() == pos1 && caravan->isUsed() == true)
     209             :         {
     210           0 :             caravan->setPos(pos2);
     211           0 :             (*map)(pos1[0], pos1[1])->removeElement(std::make_shared<std::variant<Caravan, Barbarian, BarbarianVillage, ControlPawn, City>>(*caravan));
     212           0 :             (*map)(pos2[0], pos2[1])->addElement(std::make_shared<std::variant<Caravan, Barbarian, BarbarianVillage, ControlPawn, City>>(*caravan));
     213           0 :             return true;
     214             :         }
     215           1 :     }
     216             : 
     217           1 :     if (!(isThereACity(pos1, map) || isThereAControlPawn(pos1, map)))
     218             :     {
     219           0 :         return false;
     220             :     }
     221           1 :     for (auto caravan : caravans)
     222             :     {
     223           1 :         if (!(caravan->isUsed()))
     224             :         {
     225           1 :             caravan->setPos(pos2);
     226           1 :             caravan->setUsed(true);
     227           1 :             (*map)(pos2[0], pos2[1])->addElement(std::make_shared<std::variant<Caravan, Barbarian, BarbarianVillage, ControlPawn, City>>(*caravan));
     228           1 :             return true;
     229             :         }
     230           1 :     }
     231           0 :     return true;
     232             : }
     233             : 
     234             : /**
     235             :  * @file Rules.cpp
     236             :  * @fn elementList Rules::checkIfBarbarianIsOnThePath(std::vector<std::array<unsigned, 2>> caravanMovementPath, std::shared_ptr<shared::Map> map)
     237             :  * @brief This function aim to check if a barbarian is on the path of the caravan
     238             :  * @param caravanMovementPath the path of the caravan
     239             :  * @param map the map of the game
     240             :  * @return a list of barbarian
     241             :  */
     242           1 : elementList Rules::checkIfBarbarianIsOnThePath(std::vector<std::array<unsigned, 2>> caravanMovementPath, std::shared_ptr<shared::Map> map)
     243             : {
     244           1 :     elementList barbarianList;
     245             : 
     246           4 :     for (int i = 0; i < (int)caravanMovementPath.size(); i++)
     247             :     {
     248           3 :         elementList elements = (*map)(caravanMovementPath.at(i)[0], caravanMovementPath.at(i)[1])->getElements();
     249           4 :         for (auto element : elements)
     250             :         {
     251           1 :             if (std::holds_alternative<Barbarian>(*element))
     252             :             {
     253           0 :                 barbarianList.push_back(element);
     254             :             }
     255           1 :         }
     256           3 :     }
     257             : 
     258           1 :     return barbarianList;
     259           0 : }
     260             : 
     261             : /**
     262             :  * @file Rules.cpp
     263             :  * @fn bool Rules::checkIfWaterIsOnThePath(std::vector<std::array<unsigned, 2>> caravanMovementPath, std::shared_ptr<shared::Map> map)
     264             :  * @brief This function aim to check if water is on the path of the caravan
     265             :  * @param caravanMovementPath the path of the caravan
     266             :  * @param map the map of the game
     267             :  * @return true if there is water on the path, false otherwise
     268             :  */
     269           1 : bool Rules::checkIfWaterIsOnThePath(std::vector<std::array<unsigned, 2>> caravanMovementPath, std::shared_ptr<shared::Map> map)
     270             : {
     271           4 :     for (auto position : caravanMovementPath)
     272             :     {
     273           3 :         if ((*map)(position[0], position[1])->getFieldLevel() == FieldLevel::Water)
     274             :         {
     275           0 :             return true;
     276             :         }
     277             :     }
     278           1 :     return false;
     279             : }
     280             : 
     281             : /// SCIENCE CARD ///
     282             : /**
     283             :  * @file Rules.cpp
     284             :  * @fn bool Rules::playScienceCard(RuleArgsStruct &args)
     285             :  * @brief This function aim to run the rule of the science card
     286             :  * @param args : struct containing all the arguments needed to run the rule
     287             :  */
     288           7 : bool Rules::playScienceCard(RuleArgsStruct &args)
     289             : {
     290           7 :     std::shared_ptr<Player> currentPlayer = args.currentPlayer;
     291           7 :     unsigned numberOfBoxUsed = args.numberOfBoxUsed;
     292           7 :     if (numberOfBoxUsed > args.currentPlayer->getNumberOfBox(CardsEnum::science))
     293             :     {
     294           0 :         return false;
     295             :     }
     296           7 :     args.currentPlayer->deleteBox(CardsEnum::science, numberOfBoxUsed);
     297             : 
     298             :     CardsEnum cardToGetABox;
     299             :     ResourceEnum resourceToGet;
     300             :     std::array<unsigned, 2> positionToNuke;
     301           7 :     std::shared_ptr<Map> gameMap;
     302           7 :     std::vector<CardsEnum> cardsToImprove = args.cardsToImprove;
     303             : 
     304           7 :     std::vector<std::array<unsigned, 2>> neighbors;
     305           7 :     unsigned cardLevel = args.currentPlayer->getLevelOfCard(CardsEnum::science);
     306           7 :     switch (cardLevel)
     307             :     {
     308           4 :     case 1:
     309             :         // do nothing special
     310           4 :         break;
     311           1 :     case 2:
     312           1 :         cardToGetABox = args.cardToGetABox;
     313           1 :         args.currentPlayer->addBox(cardToGetABox, 1);
     314           1 :         break;
     315           1 :     case 3:
     316           1 :         resourceToGet = args.resourceToGet;
     317           1 :         if (args.currentPlayer->haveResource(resourceToGet))
     318             :         {
     319           0 :             return false;
     320             :         }
     321           1 :         args.currentPlayer->addResource(resourceToGet);
     322           1 :         break;
     323           1 :     case 4:
     324           1 :         positionToNuke = args.positionToNuke;
     325           1 :         gameMap = args.gameMap;
     326           1 :         neighbors = getNeighbors(positionToNuke[0], positionToNuke[1], gameMap);
     327           1 :         neighbors.push_back(positionToNuke);
     328           1 :         nuke(neighbors, gameMap, args.currentPlayer);
     329           1 :         break;
     330           0 :     default:
     331           0 :         return false;
     332             :     }
     333             : 
     334           7 :     unsigned dificulty = currentPlayer->getDificultyOfCard(CardsEnum::science);
     335           7 :     std::array<int, 3> cardsLevelToImprove = currentPlayer->incrementTechWheel(dificulty + numberOfBoxUsed);
     336          16 :     for (auto cardtoImprove : cardsToImprove)
     337             :     {
     338           9 :         if (cardsLevelToImprove[currentPlayer->getLevelOfCard(cardtoImprove) - 1] > 0)
     339             :         {
     340           6 :             cardsLevelToImprove[currentPlayer->getLevelOfCard(cardtoImprove) - 1]--;
     341           6 :             args.currentPlayer->upgradeCard(cardtoImprove);
     342             :         }
     343             :     }
     344             : 
     345           7 :     roundCards(args.currentPlayer, args.ruleId);
     346           7 :     return true;
     347           7 : }
     348             : 
     349           7 : void Rules::killControlPawn(std::shared_ptr<Map> gameMap, std::array<unsigned, 2> position, std::shared_ptr<Player> currentPlayer)
     350             : {
     351           7 :     elementList elements = (*gameMap)(position[0], position[1])->getElements();
     352           9 :     for (auto element : elements)
     353             :     {
     354           2 :         if (std::holds_alternative<ControlPawn>(*element))
     355             :         {
     356           2 :             if (std::get<ControlPawn>(*element).isReinforced())
     357             :             {
     358           0 :                 std::get<ControlPawn>(*element).setNotReinforced();
     359             :             }
     360             :             else
     361             :             {
     362           2 :                 (*gameMap)(position[0], position[1])->removeElement(element);
     363           2 :                 currentPlayer->removeControlPawn(std::make_shared<ControlPawn>(std::get<ControlPawn>(*element)));
     364             :             }
     365             :         }
     366           2 :     }
     367           7 : }
     368             : 
     369             : /**
     370             :  * @file Rules.cpp
     371             :  * @fn void Rules::nuke(std::vector<std::array<unsigned, 2>> neightbors, std::shared_ptr<Map> gameMap, std::shared_ptr<Player> currentPlayer)
     372             :  * @brief This function aim to nuke the position given in parameter
     373             :  * @param neightbors the positions to nuke
     374             :  * @param gameMap the map of the game
     375             :  * @param currentPlayer the current player
     376             :  */
     377           1 : void Rules::nuke(std::vector<std::array<unsigned, 2>> neightbors, std::shared_ptr<Map> gameMap, std::shared_ptr<Player> currentPlayer)
     378             : {
     379           1 :     elementList elements;
     380           8 :     for (auto neightbor : neightbors)
     381             :     {
     382           7 :         elements = (*gameMap)(neightbor[0], neightbor[1])->getElements();
     383           7 :         killControlPawn(gameMap, neightbor, currentPlayer);
     384             :     }
     385           1 : }
     386             : 
     387             : /**
     388             :  * @file Rules.cpp
     389             :  * @fn std::vector<std::array<unsigned, 2>> Rules::getNeighbors(unsigned posX, unsigned posY, std::shared_ptr<Map> gameMap)
     390             :  * @brief This function aim to get the neighbors of a position
     391             :  * @param posX the x position
     392             :  * @param posY the y position
     393             :  * @param gameMap the map of the game
     394             :  * @return the neighbors of the position
     395             :  */
     396           3 : std::vector<std::array<unsigned, 2>> Rules::getNeighbors(unsigned posX, unsigned posY, std::shared_ptr<Map> gameMap)
     397             : {
     398           3 :     std::vector<std::array<unsigned, 2>> neighbors;
     399           3 :     unsigned mapSizeX = gameMap->getMapWidth();
     400           3 :     unsigned mapSizeY = gameMap->getMapHeight();
     401           3 :     if (posY % 2)
     402             :     {
     403           2 :         if (posY > 0)
     404             :         {
     405           2 :             neighbors.push_back({posX, posY - 1});
     406             :         }
     407           2 :         if (posY > 0 && posX > 0)
     408             :         {
     409           2 :             neighbors.push_back({posX - 1, posY - 1}); // faux
     410             :         }
     411           2 :         if (posX < mapSizeX - 2)
     412             :         {
     413           2 :             neighbors.push_back({posX + 1, posY});
     414             :         }
     415           2 :         if (posY < mapSizeY - 2)
     416             :         {
     417           2 :             neighbors.push_back({posX, posY + 1});
     418             :         }
     419           2 :         if (posY < mapSizeY - 2 && posX > 0)
     420             :         {
     421           2 :             neighbors.push_back({posX - 1, posY + 1});
     422             :         }
     423           2 :         if (posX > 0)
     424             :         {
     425           2 :             neighbors.push_back({posX - 1, posY});
     426             :         }
     427             :     }
     428             :     else
     429             :     {
     430           1 :         if (posY > 0)
     431             :         {
     432           1 :             neighbors.push_back({posX, posY - 1});
     433             :         }
     434           1 :         if (posY > 0 && posX < mapSizeX - 2)
     435             :         {
     436           1 :             neighbors.push_back({posX + 1, posY - 1});
     437             :         }
     438           1 :         if (posX > 0)
     439             :         {
     440           1 :             neighbors.push_back({posX - 1, posY});
     441             :         }
     442           1 :         if (posY < mapSizeY - 2)
     443             :         {
     444           1 :             neighbors.push_back({posX, posY + 1});
     445             :         }
     446           1 :         if (posY < mapSizeY - 2 && posX < mapSizeX - 2)
     447             :         {
     448           1 :             neighbors.push_back({posX + 1, posY + 1});
     449             :         }
     450           1 :         if (posX < mapSizeX - 2)
     451             :         {
     452           1 :             neighbors.push_back({posX + 1, posY});
     453             :         }
     454             :     }
     455           3 :     return neighbors;
     456           0 : }
     457             : 
     458             : /// CULTURE CARD ///
     459             : /**
     460             :  * @file Rules.cpp
     461             :  * @fn bool Rules::playCultureCard(RuleArgsStruct &args)
     462             :  * @brief This function aim to play the culture card
     463             :  * @param args : struct containing all the arguments needed to run the rule
     464             :  */
     465           1 : bool Rules::playCultureCard(RuleArgsStruct &args)
     466             : {
     467           1 :     unsigned numberOfBoxUsed = args.numberOfBoxUsed;
     468           1 :     if (numberOfBoxUsed > args.currentPlayer->getNumberOfBox(CardsEnum::culture))
     469             :     {
     470           0 :         return false;
     471             :     }
     472             : 
     473           1 :     std::vector<std::array<unsigned, 2>> pawnsPositions = args.pawnsPositions;
     474           1 :     std::shared_ptr<Map> gameMap = args.gameMap;
     475             : 
     476           1 :     unsigned cardLevel = args.currentPlayer->getLevelOfCard(CardsEnum::culture);
     477           1 :     switch (cardLevel)
     478             :     {
     479           1 :     case 1:
     480           1 :         if (pawnsPositions.size() <= NUMBER_PAWNS_ECONOMY_LVL_1 + numberOfBoxUsed)
     481             :         {
     482           1 :             if (!placeControlPawns(pawnsPositions, gameMap, args.currentPlayer))
     483             :             {
     484           0 :                 return false;
     485             :             }
     486             :         }
     487             :         else
     488             :         {
     489           0 :             return false;
     490             :         }
     491           1 :         break;
     492           0 :     case 2:
     493             :         // TODO : move one pawn on an empty field
     494           0 :         break;
     495           0 :     case 3:
     496             :         // TODO : Place one pawn on next to an ally hexagon
     497           0 :         break;
     498           0 :     case 4:
     499             :         // TODO: replace enemy pawn (reinforced or not) by one of your pawn (non reinforced)
     500           0 :         break;
     501           0 :     default:
     502           0 :         return false;
     503             :     }
     504             : 
     505           1 :     roundCards(args.currentPlayer, args.ruleId);
     506           1 :     return true;
     507           1 : }
     508             : 
     509             : /**
     510             :  * @file Rules.cpp
     511             :  * @fn bool Rules::placeControlPawns(std::vector<std::array<unsigned, 2>> positions, std::shared_ptr<Map> gameMap, std::shared_ptr<Player> currentPlayer)
     512             :  * @brief This function aim to place the control pawns on the map
     513             :  * @param positions the positions where the control pawns will be placed
     514             :  * @param gameMap the map of the game
     515             :  * @param currentPlayer the current player that owns the control pawns
     516             :  */
     517           1 : bool Rules::placeControlPawns(std::vector<std::array<unsigned, 2>> positions, std::shared_ptr<Map> gameMap, std::shared_ptr<Player> currentPlayer) // TODO : split this function
     518             : {
     519           3 :     for (auto position : positions)
     520             :     {
     521           2 :         if ((*gameMap)(position[0], position[1])->getFieldLevel() == FieldLevel::Water)
     522             :         {
     523           0 :             return false;
     524             :         }
     525           2 :         for (auto element : (*gameMap)(position[0], position[1])->getElements())
     526             :         {
     527           0 :             if (!std::holds_alternative<Caravan>(*element))
     528             :             {
     529           0 :                 return false;
     530             :             }
     531           2 :         }
     532           2 :         if (isThereACityAround(position, gameMap))
     533             :         {
     534           2 :             std::shared_ptr<shared::ControlPawn> controlPawn = std::make_shared<shared::ControlPawn>(position, currentPlayer->getName());
     535           2 :             currentPlayer->addControlPawn(controlPawn);
     536           2 :             std::variant<shared::Caravan, shared::Barbarian, shared::BarbarianVillage, shared::ControlPawn, shared::City> element = *controlPawn;
     537           2 :             (*gameMap)(position[0], position[1])->addElement(std::make_shared<std::variant<shared::Caravan, shared::Barbarian, shared::BarbarianVillage, shared::ControlPawn, shared::City>>(element));
     538           2 :         }
     539             :     }
     540           1 :     return true;
     541             : }
     542             : 
     543             : /**
     544             :  * @file Rules.cpp
     545             :  * @fn bool Rules::isThereACityAround(std::array<unsigned, 2> position, std::shared_ptr<Map> gameMap)
     546             :  * @brief This function aim to check if there is a city around a position
     547             :  * @param position the position to check
     548             :  * @param gameMap the map of the game
     549             :  * @return true if there is a city around, false otherwise
     550             :  */
     551           2 : bool Rules::isThereACityAround(std::array<unsigned, 2> position, std::shared_ptr<Map> gameMap)
     552             : {
     553           2 :     std::vector<std::array<unsigned, 2>> neighbors = getNeighbors(position[0], position[1], gameMap);
     554          11 :     for (auto neighbor : neighbors)
     555             :     {
     556          11 :         for (auto element : (*gameMap)(neighbor[0], neighbor[1])->getElements())
     557             :         {
     558           2 :             if (std::holds_alternative<City>(*element))
     559             :             {
     560           2 :                 return true; // TODO : check if the city is owned by the player
     561             :             }
     562          13 :         }
     563             :     }
     564           0 :     return false;
     565           2 : }
     566             : 
     567           1 : bool Rules::isThereACity(std::array<unsigned, 2> position, std::shared_ptr<Map> gameMap)
     568             : {
     569           1 :     for (auto element : (*gameMap)(position[0], position[1])->getElements())
     570             :     {
     571           1 :         if (std::holds_alternative<City>(*element))
     572             :         {
     573           1 :             return true; // TODO : check if the city is owned by the player
     574             :         }
     575           2 :     }
     576           0 :     return false;
     577             : }
     578             : 
     579             : /**
     580             :  * @file Rules.cpp
     581             :  * @fn bool Rules::isThereAControlPawnAround(std::array<unsigned, 2> position, std::shared_ptr<Map> gameMap)
     582             :  * @brief This function aim to check if there is a control pawn around a position
     583             :  * @param position the position to check
     584             :  * @param gameMap the map of the game
     585             :  * @return true if there is a control pawn around, false otherwise
     586             :  */
     587           0 : bool Rules::isThereAControlPawn(std::array<unsigned, 2> position, std::shared_ptr<Map> gameMap)
     588             : {
     589           0 :     for (auto element : (*gameMap)(position[0], position[1])->getElements())
     590             :     {
     591           0 :         if (std::holds_alternative<ControlPawn>(*element))
     592             :         {
     593           0 :             return true; // TODO : check if the controlpawn is owned by the player
     594             :         }
     595           0 :     }
     596             : 
     597           0 :     return false;
     598             : }
     599             : 
     600             : /// MILITARY CARD ///
     601             : /**
     602             :  * @file Rules.cpp
     603             :  * @fn bool Rules::playMilitaryCard(RuleArgsStruct &args)
     604             :  * @brief This function aim to play the military card
     605             :  * @param args : struct containing all the arguments needed to run the rule
     606             :  */
     607           1 : bool Rules::playMilitaryCard(RuleArgsStruct &args)
     608             : {
     609           1 :     if (args.militaryCardAttack == true)
     610             :     {
     611           0 :         return attack(args);
     612             :     }
     613             :     else
     614             :     {
     615           1 :         return reinforce(args);
     616             :     }
     617             : }
     618             : 
     619             : /**
     620             :  * @file Rules.cpp
     621             :  * @fn bool Rules::attack(RuleArgsStruct &args)
     622             :  * @brief This function aim to attack an enemy pawn or a city
     623             :  * @param args : struct containing all the arguments needed to run the rule
     624             :  */
     625           0 : bool Rules::attack(RuleArgsStruct &args)
     626             : {
     627             :     // TODO : attack
     628             :     // I have problems mesuring the distance of the enemy pawn from the current player hexagons
     629           0 :     return false;
     630             : }
     631             : 
     632             : /**
     633             :  * @file Rules.cpp
     634             :  * @fn bool Rules::reinforce(RuleArgsStruct &args)
     635             :  * @brief This function aim to reinforce a pawn
     636             :  * @param args : struct containing all the arguments needed to run the rule
     637             :  */
     638           1 : bool Rules::reinforce(RuleArgsStruct &args)
     639             : {
     640           1 :     unsigned numberOfBoxUsed = args.numberOfBoxUsed;
     641           1 :     if (numberOfBoxUsed > args.currentPlayer->getNumberOfBox(CardsEnum::military))
     642             :     {
     643           0 :         return false;
     644             :     }
     645             : 
     646           1 :     std::shared_ptr<Map> gameMap = args.gameMap;
     647           1 :     std::vector<std::array<unsigned, 2>> pawnsPositions = args.pawnsPositions;
     648           1 :     unsigned cardDifficulty = args.currentPlayer->getDificultyOfCard(CardsEnum::military);
     649           1 :     if (pawnsPositions.size() > cardDifficulty + numberOfBoxUsed)
     650             :     {
     651           0 :         return false;
     652             :     }
     653           1 :     std::shared_ptr<ControlPawn> controlPawn;
     654             : 
     655           3 :     for (auto position : pawnsPositions)
     656             :     {
     657           2 :         for (auto element : (*gameMap)(position[0], position[1])->getElements())
     658             :         {
     659           2 :             if (std::holds_alternative<ControlPawn>(*element))
     660             :             {
     661           2 :                 std::get<ControlPawn>(*element).setReinforced();
     662           2 :                 break;
     663             :             }
     664           2 :         }
     665             :     }
     666             : 
     667           1 :     roundCards(args.currentPlayer, args.ruleId);
     668           1 :     return true;
     669           1 : }
     670             : 
     671             : /// INDUSTRY CARD ///
     672             : /**
     673             :  * @file Rules.cpp
     674             :  * @fn bool Rules::playIndustryCard(RuleArgsStruct &args)
     675             :  * @brief This function aim to play the industry card
     676             :  * @param args : struct containing all the arguments needed to run the rule
     677             :  */
     678           1 : bool Rules::playIndustryCard(RuleArgsStruct &args)
     679             : {
     680           1 :     if (args.industryCardBuildWonder == true)
     681             :     {
     682           0 :         return buildWonder(args);
     683             :     }
     684             :     else
     685             :     {
     686           1 :         return buildCity(args);
     687             :     }
     688             : }
     689             : 
     690             : /**
     691             :  * @file Rules.cpp
     692             :  * @fn bool Rules::buildWonder(RuleArgsStruct &args)
     693             :  * @brief This function aim to build a wonder
     694             :  * @param args : struct containing all the arguments needed to run the rule
     695             :  */
     696           0 : bool Rules::buildWonder(RuleArgsStruct &args) // TODO : remake this function
     697             : {
     698             :     // TODO : build a wonder
     699           0 :     return false;
     700             : }
     701             : 
     702             : /**
     703             :  * @file Rules.cpp
     704             :  * @fn bool Rules::buildCity(RuleArgsStruct &args)
     705             :  * @brief This function aim to build a city
     706             :  * @param args : struct containing all the arguments needed to run the rule
     707             :  */
     708           1 : bool Rules::buildCity(RuleArgsStruct &args) // TODO : Check the distance to controlled hexagon
     709             : {
     710           1 :     unsigned numberOfBoxUsed = args.numberOfBoxUsed;
     711           1 :     if (numberOfBoxUsed > args.currentPlayer->getNumberOfBox(CardsEnum::industry))
     712             :     {
     713           0 :         return false;
     714             :     }
     715             : 
     716           1 :     std::shared_ptr<Map> gameMap = args.gameMap;
     717           1 :     std::array<unsigned, 2> position = args.positionOfCity;
     718             : 
     719           1 :     unsigned cardDifficulty = args.currentPlayer->getDificultyOfCard(CardsEnum::industry);
     720           1 :     if (cardDifficulty + numberOfBoxUsed < (unsigned)(*gameMap)(position[0], position[1])->getFieldLevel())
     721             :     {
     722           0 :         return false;
     723             :     }
     724           1 :     if ((*gameMap)(position[0], position[1])->getFieldLevel() == FieldLevel::Water)
     725             :     {
     726           0 :         return false;
     727             :     }
     728             : 
     729           1 :     for (auto element : (*gameMap)(position[0], position[1])->getElements())
     730             :     {
     731           0 :         if (!(std::holds_alternative<Caravan>(*element)))
     732             :         {
     733           0 :             return false;
     734             :         }
     735           1 :     }
     736           1 :     std::shared_ptr<City> city = std::make_shared<City>(position, args.currentPlayer->getName());
     737           1 :     args.currentPlayer->addCity(city);
     738           1 :     (*gameMap)(position[0], position[1])->addElement(std::make_shared<std::variant<Caravan, Barbarian, BarbarianVillage, ControlPawn, City>>(*city));
     739             : 
     740           1 :     roundCards(args.currentPlayer, args.ruleId);
     741           1 :     return true;
     742           1 : }
     743             : 
     744          11 : void Rules::roundCards(std::shared_ptr<Player> currentPlayer, CardsEnum cardPlayed)
     745             : {
     746          11 :     unsigned initialDificulty = currentPlayer->getDificultyOfCard(cardPlayed);
     747          66 :     for (auto card : currentPlayer->getListOfPriorityCards())
     748             :     {
     749          55 :         if (card->getType() == cardPlayed)
     750             :         {
     751          11 :             card->setDificulty(1);
     752             :         }
     753          44 :         else if (card->getDificulty() < initialDificulty)
     754             :         {
     755          16 :             card->setDificulty(card->getDificulty() + 1);
     756             :         }
     757          66 :     }
     758          11 : }
     759             : 
     760           0 : bool Rules::isThereACaravan(std::array<unsigned, 2> position, std::shared_ptr<Map> gameMap)
     761             : {
     762           0 :     for (auto element : (*gameMap)(position[0], position[1])->getElements())
     763             :     {
     764           0 :         if (std::holds_alternative<Caravan>(*element))
     765             :         {
     766           0 :             return true;
     767             :         }
     768           0 :     }
     769             : 
     770           0 :     return false;
     771             : }

Generated by: LCOV version 1.14