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 : }
|