/** * @brief Attack phase decision making */ std::pair<std::string, std::string> Defensive::attackPhase() { RiskMap* map = this->driver->getRiskMap(); std::string playerName = this->driver->getCurrentPlayerName(); std::set<std::string> countriesOwnedByPlayer = map->getCountriesOwnedByPlayer(playerName); std::pair<std::string, std::string> maxDifferencePair; int maxDifference = 0; for (const std::string &countryName : countriesOwnedByPlayer) { Country* country = map->getCountry(countryName); // Check if we have more armies than all of the neighbours opponents own bool moreArmiesThanNeighbours = true; for (const std::string &neighnourName : map->getNeighbours(country->getName())) { Country* neighbour = map->getCountry(neighnourName); if (neighbour->getPlayer() != playerName && neighbour->getArmies() > country->getArmies()) { moreArmiesThanNeighbours = false; break; } } // If we do, find the pair of countries with the greatest chance for success for (const std::string &neighnourName : map->getNeighbours(country->getName())) { Country* neighbour = map->getCountry(neighnourName); if (neighbour->getPlayer() != playerName) { int difference = neighbour->getArmies() - country->getArmies(); if (difference >= maxDifference) { maxDifference = difference; maxDifferencePair = std::pair<std::string, std::string>(country->getName(), neighbour->getName()); } } } } return maxDifferencePair; }
/** * @brief A signal sent to the Strategy class from the game driver to indicate * that a computer-controlled player should made their move. * * The AI strategy implementations override each of the fooPhase() methods * which return the name(s) of the country or countries to act upon. * * Empty string indicates the AI wishes to make no move, or there are none * possible. */ void Strategy::takeAction(Mode mode) { RiskMap* map = this->driver->getRiskMap(); if (mode == REINFORCEMENT) { std::string countryName = this->reinforcePhase(); if (countryName == "") { return; } Country* country = map->getCountry(countryName); Player* player = map->getPlayer(country->getPlayer()); this->driver->reinforceCountry(player, country, player->getReinforcements()); } else if (mode == ATTACK) { std::pair<std::string, std::string> countryNames = this->attackPhase(); if (countryNames.first == "" || countryNames.second == "") { return; } driver->attackCountry(map->getCountry(countryNames.first), map->getCountry(countryNames.second)); } else if (mode == FORTIFICATION) { std::pair<std::string, std::string> countryNames = this->fortifyPhase(); if (countryNames.first == "" || countryNames.second == "") { return; } // Given the two countries, fortify so that the armies are as equal as possible. Country* origin = map->getCountry(countryNames.first); Country* destination = map->getCountry(countryNames.second); int splitDifference = std::abs(origin->getArmies() - destination->getArmies()) / 2; this->driver->fortifyCountry(origin, destination, splitDifference); } }
/** * @brief Gets a list of continent names owned by a player */ string_set RiskMap::getContinentsOwnedByPlayer(const std::string& playerName) { string_set continentsOwned; for (auto &ent1: this->continents) { std::string continentName = ent1.first; string_set countriesInContent = this->getCountriesInContinent(continentName); bool totalOwnership = true; for (auto &countryName: countriesInContent) { Country* country = this->getCountry(countryName); if (country->getPlayer() != playerName) { totalOwnership = false; break; } } if (totalOwnership) { continentsOwned.insert(continentName); } } return continentsOwned; }