/* * Copyright 2010-2015 OpenXcom Developers. * * This file is part of OpenXcom. * * OpenXcom is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenXcom is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenXcom. If not, see . */ #include #include "AlienStrategy.h" #include "SavedGame.h" #include "WeightedOptions.h" #include "../Engine/RNG.h" #include "../Ruleset/Ruleset.h" #include "../Ruleset/RuleRegion.h" namespace OpenXcom { typedef std::map MissionsByRegion; /** * Create an AlienStrategy with no values. * Running a game like this will most likely crash. */ AlienStrategy::AlienStrategy() { // Empty by design! } /** * Free all resources used by this AlienStrategy. */ AlienStrategy::~AlienStrategy() { // Free allocated memory. for (MissionsByRegion::iterator ii = _regionMissions.begin(); ii != _regionMissions.end(); ++ii) { delete ii->second; } } /** * Get starting values from the rules. * @param rules Pointer to the game ruleset. */ void AlienStrategy::init(const Ruleset *rules) { std::vector regions = rules->getRegionsList(); for (std::vector::const_iterator rr = regions.begin(); rr != regions.end(); ++rr) { RuleRegion *region = rules->getRegion(*rr); _regionChances.set(*rr, region->getWeight()); WeightedOptions *missions = new WeightedOptions(region->getAvailableMissions()); _regionMissions.insert(std::make_pair(*rr, missions)); } } /** * Loads the data from a YAML file. * @param rules Pointer to the game ruleset. * @param node YAML node. */ void AlienStrategy::load(const Ruleset *, const YAML::Node &node) { // Free allocated memory. for (MissionsByRegion::iterator ii = _regionMissions.begin(); ii != _regionMissions.end(); ++ii) { delete ii->second; } _regionMissions.clear(); _regionChances.clear(); _regionChances.load(node["regions"]); const YAML::Node &strat = node["possibleMissions"]; for (YAML::const_iterator nn = strat.begin(); nn != strat.end(); ++nn) { std::string region = (*nn)["region"].as(); const YAML::Node &missions = (*nn)["missions"]; std::auto_ptr options(new WeightedOptions()); options->load(missions); _regionMissions.insert(std::make_pair(region, options.release())); } } /** * Saves the alien data to a YAML file. * @return YAML node. */ YAML::Node AlienStrategy::save() const { YAML::Node node; node["regions"] = _regionChances.save(); for (MissionsByRegion::const_iterator ii = _regionMissions.begin(); ii != _regionMissions.end(); ++ii) { YAML::Node subnode; subnode["region"] = ii->first; subnode["missions"] = ii->second->save(); node["possibleMissions"].push_back(subnode); } return node; } /** * Choose one of the regions for a mission. * @param rules Pointer to the ruleset. * @return The region id. */ const std::string AlienStrategy::chooseRandomRegion(const Ruleset *rules) { std::string chosen = _regionChances.choose(); if (chosen.empty()) { init(rules); chosen = _regionChances.choose(); } assert ("" != chosen); return chosen; } /** * Choose one missions available for @a region. * @param region The region id. * @return The mission id. */ const std::string AlienStrategy::chooseRandomMission(const std::string ®ion) const { MissionsByRegion::const_iterator found = _regionMissions.find(region); assert(found != _regionMissions.end()); return found->second->choose(); } /** * Remove @a mission from the list of possible missions for @a region. * @param region The region id. * @param mission The mission id. * @return If there are no more regions with missions available. */ bool AlienStrategy::removeMission(const std::string ®ion, const std::string &mission) { MissionsByRegion::iterator found = _regionMissions.find(region); assert(found != _regionMissions.end()); found->second->set(mission, 0); if (found->second->empty()) { _regionMissions.erase(found); _regionChances.set(region, 0); } return _regionMissions.empty(); } }