LCOV - code coverage report
Current view: top level - shared - Map.cpp (source / functions) Hit Total Coverage
Test: code-coverage.info.cleaned Lines: 112 119 94.1 %
Date: 2023-01-28 00:08:57 Functions: 11 11 100.0 %

          Line data    Source code
       1             : #include <shared.hpp>
       2             : #include <math.h>
       3             : #include <ctime>
       4             : #include <variant>
       5             : #include <iostream>
       6             : 
       7             : #define NUMBER_OF_FIELDS 5
       8             : #define PERLIN_NOISE_WIDTH 10
       9             : #define PERLIN_NOISE_PARAM 0.8
      10             : 
      11             : using namespace shared;
      12             : 
      13             : typedef std::variant<Caravan, Barbarian, BarbarianVillage, ControlPawn, City> variantElement;
      14             : 
      15             : const FieldLevel wonderList[] = {FieldLevel::WonderEverest, FieldLevel::WonderGalapagos, FieldLevel::WonderKilimanjaro,
      16             :                                  FieldLevel::WonderMessa, FieldLevel::WonderPantanal, FieldLevel::WonderVolcanic};
      17             : 
      18             : std::vector<CityStateEnum> stateCityField = {
      19             :     CityStateEnum::carthage,
      20             :     CityStateEnum::kaboul,
      21             :     CityStateEnum::mohenjoDaro,
      22             :     CityStateEnum::kumasi,
      23             :     CityStateEnum::seoul,
      24             :     CityStateEnum::geneva,
      25             :     CityStateEnum::buenosAires,
      26             :     CityStateEnum::bruxelles};
      27             : 
      28             : /*!
      29             :  * @brief Map constructor
      30             :  * @param width Width of the map to instantiate
      31             :  * @param height Height of the map to instantiate
      32             :  */
      33          14 : Map::Map(unsigned width, unsigned height)
      34             : {
      35          14 :     this->height = height;
      36          14 :     this->width = width;
      37          14 : }
      38             : 
      39          12 : void Map::init()
      40             : {
      41          12 :     if (isInizialize)
      42             :     {
      43           0 :         return;
      44             :     }
      45         142 :     for (unsigned i = 0; i < this->height; i++)
      46             :     {
      47        1730 :         for (unsigned j = 0; j < this->width; j++)
      48             :         {
      49        1600 :             mapOfTheGame.push_back(std::make_shared<Hexagon>());
      50             :         }
      51             :     }
      52          12 :     isInizialize = true;
      53             : }
      54             : 
      55           2 : void Map::setMapHeight(unsigned height)
      56             : {
      57           2 :     this->height = height;
      58           2 : }
      59             : 
      60           2 : void Map::setMapWidth(unsigned width)
      61             : {
      62           2 :     this->width = width;
      63           2 : }
      64             : 
      65          18 : unsigned Map::getMapHeight()
      66             : {
      67          18 :     return this->height;
      68             : }
      69             : 
      70         117 : unsigned Map::getMapWidth()
      71             : {
      72         117 :     return this->width;
      73             : }
      74             : 
      75         500 : bool wonderCondition(std::shared_ptr<Hexagon> hex, std::vector<FieldLevel> &remWonder)
      76             : {
      77         500 :     return hex->getFieldLevel() != FieldLevel::Water &&
      78         586 :            remWonder.empty() == false &&
      79        1086 :            hex->hexResource == nullptr &&
      80         764 :            rand() % 1000 < 5;
      81             : }
      82             : 
      83             : /*!
      84             :  * @brief Function to generate a random map based on Perlin Noise
      85             :  * @param seed Seed to use for the random generation
      86             :  */
      87           3 : void Map::generateRandomMap(int seed)
      88             : {
      89             : 
      90           3 :     if (!isInizialize)
      91             :     {
      92           3 :         init();
      93             :     }
      94             : 
      95           3 :     PerlinNoise pn(seed);
      96           3 :     srand(time(NULL));
      97             : 
      98           3 :     std::vector<FieldLevel> remainingWonders(wonderList, wonderList + sizeof(wonderList) / sizeof(wonderList[0]));
      99           3 :     std::vector<bool> remainingCity(stateCityField.size(), true);
     100             : 
     101          38 :     for (unsigned i = 0; i < this->height; i++)
     102             :     {
     103         535 :         for (unsigned j = 0; j < this->width; j++)
     104             :         {
     105         500 :             double x = (double)j / ((double)this->width);
     106         500 :             double y = (double)i / ((double)this->height);
     107             : 
     108         500 :             double n = pn.noise(PERLIN_NOISE_WIDTH * x, PERLIN_NOISE_WIDTH * y, PERLIN_NOISE_PARAM);
     109         500 :             int field = (int)round(n * (NUMBER_OF_FIELDS + 1));
     110             : 
     111         500 :             std::array<unsigned, 2> position = {i, j};
     112             : 
     113         500 :             switch (field)
     114             :             {
     115           0 :             case 0:
     116           0 :                 setWater(i, j);
     117           0 :                 break;
     118           8 :             case 1:
     119           8 :                 mapOfTheGame[i * this->width + j]->setFieldType(FieldLevel::Grassland);
     120           8 :                 addResource(i, j, 2, ResourceEnum::stone);
     121           8 :                 addResource(i, j, 2, ResourceEnum::antiquity);
     122           8 :                 break;
     123         125 :             case 2:
     124         125 :                 mapOfTheGame[i * this->width + j]->setFieldType(FieldLevel::Hill);
     125         125 :                 addResource(i, j, 2, ResourceEnum::stone);
     126         125 :                 addResource(i, j, 2, ResourceEnum::antiquity);
     127         125 :                 break;
     128         253 :             case 3:
     129         253 :                 mapOfTheGame[i * this->width + j]->setFieldType(FieldLevel::Forest);
     130         253 :                 addResource(i, j, 2, ResourceEnum::stone);
     131         253 :                 addResource(i, j, 2, ResourceEnum::antiquity);
     132         253 :                 break;
     133          99 :             case 4:
     134          99 :                 mapOfTheGame[i * this->width + j]->setFieldType(FieldLevel::Desert);
     135          99 :                 addResource(i, j, 12, ResourceEnum::oil);
     136          99 :                 addResource(i, j, 6, ResourceEnum::antiquity);
     137          99 :                 break;
     138          15 :             case 5:
     139          15 :                 mapOfTheGame[i * this->width + j]->setFieldType(FieldLevel::Mountain);
     140          15 :                 addResource(i, j, 12, ResourceEnum::diamond);
     141          15 :                 addResource(i, j, 6, ResourceEnum::stone);
     142          15 :                 break;
     143           0 :             default:
     144           0 :                 mapOfTheGame[i * this->width + j]->setFieldType(FieldLevel::Water);
     145           0 :                 break;
     146             :             }
     147             : 
     148         500 :             if (i == 0 || i == this->height - 1 || j == 0 || j == this->width - 1)
     149             :             {
     150         138 :                 setWater(i, j);
     151             :             }
     152             :             // 50% chance to be water
     153         362 :             else if (rand() % 10 < 5 && (i == 1 || i == this->height - 2 || j == 1 || j == this->width - 2))
     154             :             {
     155          58 :                 setWater(i, j);
     156             :             }
     157             :             // 10% chance to be water
     158         304 :             else if (rand() % 10 < 1 && (i == 2 || i == this->height - 3 || j == 2 || j == this->width - 3))
     159             :             {
     160          11 :                 setWater(i, j);
     161             :             }
     162             : 
     163         500 :             if (wonderCondition(mapOfTheGame[i * this->width + j], remainingWonders))
     164             :             {
     165           4 :                 int wonderIndex = rand() % remainingWonders.size(); // remainingWonders is not empty here
     166           4 :                 FieldLevel wonder = remainingWonders[wonderIndex];
     167           4 :                 remainingWonders.erase(remainingWonders.begin() + wonderIndex);
     168           4 :                 mapOfTheGame[i * this->width + j]->setFieldType(wonder);
     169             :             }
     170             : 
     171         500 :             if (mapOfTheGame[i * this->width + j]->hexResource != nullptr || mapOfTheGame[i * this->width + j]->getFieldLevel() == FieldLevel::Water)
     172             :             {
     173         247 :                 continue;
     174             :             }
     175             : 
     176         264 :             if (rand() % 100 < 5)
     177             :             {
     178          11 :                 std::shared_ptr<shared::BarbarianVillage> barbareVillage = std::make_shared<shared::BarbarianVillage>();
     179          11 :                 std::shared_ptr<shared::Barbarian> barbare = std::make_shared<shared::Barbarian>();
     180          11 :                 mapOfTheGame[i * this->width + j]->addElement(std::make_shared<variantElement>(*barbare));
     181          11 :                 mapOfTheGame[i * this->width + j]->addElement(std::make_shared<variantElement>(*barbareVillage));
     182          11 :                 continue;
     183          11 :             }
     184             : 
     185         253 :             if (rand() % 100 < 3)
     186             :             {
     187           9 :                 std::vector<int> remainingIndex;
     188          81 :                 for (unsigned k = 0; k < stateCityField.size(); k++)
     189             :                 {
     190          72 :                     if (remainingCity[k])
     191             :                     {
     192          62 :                         remainingIndex.push_back(k);
     193             :                     }
     194             :                 }
     195           9 :                 if (remainingIndex.empty() == false)
     196             :                 {
     197           9 :                     int index = remainingIndex[rand() % remainingIndex.size()]; // remainingIndex is not empty
     198           9 :                     std::shared_ptr<shared::City> city = std::make_shared<shared::City>(position, "not defined"); // TODO: check if we place random cities
     199           9 :                     city->setStateCity(stateCityField[index]);
     200           9 :                     remainingCity[index] = false;
     201           9 :                     mapOfTheGame[i * this->width + j]->addElement(std::make_shared<variantElement>(*city));
     202           9 :                 }
     203           9 :             }
     204             :         }
     205             :     }
     206           3 : }
     207             : 
     208        1000 : void Map::addResource(int x, int y, int procent, ResourceEnum resource)
     209             : {
     210        1000 :     if (rand() % 100 < procent)
     211             :     {
     212          42 :         mapOfTheGame[x * this->width + y]->hexResource = std::make_shared<Resource>(resource);
     213             :     }
     214        1000 : }
     215             : 
     216         207 : void Map::setWater(int x, int y)
     217             : {
     218         207 :     mapOfTheGame[x * this->width + y]->setFieldType(FieldLevel::Water);
     219         207 :     mapOfTheGame[x * this->width + y]->clearElement();
     220         207 :     mapOfTheGame[x * this->width + y]->hexResource = nullptr;
     221         207 : }
     222             : 
     223             : /*!
     224             :  * @brief Operator to access a specific hexagon of the map
     225             :  * @param x X coordinate of the hexagon
     226             :  * @param y Y coordinate of the hexagon
     227             :  * @return Pointer to the hexagon
     228             :  */
     229        1383 : std::shared_ptr<Hexagon> Map::operator()(unsigned x, unsigned y)
     230             : {
     231        1383 :     if (x < this->width && y < this->height && mapOfTheGame.size() > 0)
     232             :     {
     233        1378 :         return mapOfTheGame[y * this->width + x];
     234             :     }
     235             :     else
     236             :     {
     237           5 :         return nullptr;
     238             :     }
     239             : }

Generated by: LCOV version 1.14