/*
* Copyright 2010-2016 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 <http://www.gnu.org/licenses/>.
*/
#include "RuleAlienMission.h"
#include "../Savegame/WeightedOptions.h"
namespace YAML
{
template<>
struct convert<OpenXcom::MissionWave>
{
static Node encode(const OpenXcom::MissionWave& rhs)
{
Node node;
node["ufo"] = rhs.ufoType;
node["count"] = rhs.ufoCount;
node["trajectory"] = rhs.trajectory;
node["timer"] = rhs.spawnTimer;
node["objective"] = rhs.objective;
return node;
}
static bool decode(const Node& node, OpenXcom::MissionWave& rhs)
{
if (!node.IsMap())
return false;
rhs.ufoType = node["ufo"].as<std::string>();
rhs.ufoCount = node["count"].as<size_t>();
rhs.trajectory = node["trajectory"].as<std::string>();
rhs.spawnTimer = node["timer"].as<size_t>();
rhs.objective = node["objective"].as<bool>(false);
return true;
}
};
}
namespace OpenXcom
{
RuleAlienMission::RuleAlienMission(const std::string &type) : _type(type), _points(0), _objective(OBJECTIVE_SCORE), _spawnZone(-1), _retaliationOdds(-1)
{
}
/**
* Ensures the allocated memory is released.
*/
RuleAlienMission::~RuleAlienMission()
{
for (std::vector<std::pair<size_t, WeightedOptions*> >::const_iterator ii = _raceDistribution.begin(); ii != _raceDistribution.end(); ++ii)
{
delete ii->second;
}
}
/**
* Loads the mission data from a YAML node.
* @param node YAML node.
*/
void RuleAlienMission::load(const YAML::Node &node)
{
_type = node["type"].as<std::string>(_type);
_points = node["points"].as<int>(_points);
_waves = node["waves"].as< std::vector<MissionWave> >(_waves);
_objective = (MissionObjective)node["objective"].as<int>(_objective);
_spawnUfo = node["spawnUfo"].as<std::string>(_spawnUfo);
_spawnZone = node["spawnZone"].as<int>(_spawnZone);
_weights = node["missionWeights"].as< std::map<size_t, int> >(_weights);
_retaliationOdds = node["retaliationOdds"].as<int>(_retaliationOdds);
_siteType = node["siteType"].as<std::string>(_siteType);
//Only allow full replacement of mission racial distribution.
if (const YAML::Node &weights = node["raceWeights"])
{
typedef std::map<size_t, WeightedOptions*> Associative;
typedef std::vector< std::pair<size_t, WeightedOptions*> > Linear;
Associative assoc;
//Place in the associative container so we can index by month and keep entries sorted.
for (Linear::iterator ii = _raceDistribution.begin(); ii != _raceDistribution.end(); ++ii)
{
assoc.insert(*ii);
}
// Now go through the node contents and merge with existing data.
for (YAML::const_iterator nn = weights.begin(); nn != weights.end(); ++nn)
{
size_t month = nn->first.as<size_t>();
Associative::iterator existing = assoc.find(month);
if (assoc.end() == existing)
{
// New entry, load and add it.
WeightedOptions *nw = new WeightedOptions();
nw->load(nn->second);
assoc.insert(std::make_pair(month, nw));
}
else
{
// Existing entry, update it.
existing->second->load(nn->second);
}
}
// Now replace values in our actual member variable!
_raceDistribution.clear();
_raceDistribution.reserve(assoc.size());
for (Associative::iterator ii = assoc.begin(); ii != assoc.end(); ++ii)
{
if (ii->second->empty())
{
// Don't keep empty lists.
delete ii->second;
}
else
{
// Place it
_raceDistribution.push_back(*ii);
}
}
}
}
/**
* Chooses one of the available races for this mission.
* The racial distribution may vary based on the current game date.
* @param monthsPassed The number of months that have passed in the game world.
* @return The string id of the race.
*/
std::string RuleAlienMission::generateRace(const size_t monthsPassed) const
{
std::vector<std::pair<size_t, WeightedOptions*> >::const_reverse_iterator rc;
for (rc = _raceDistribution.rbegin(); rc != _raceDistribution.rend() && monthsPassed < rc->first; ++rc);
if (rc == _raceDistribution.rend())
return "";
return rc->second->choose();
}
/**
* Returns the Alien score for this mission.
* @return Amount of points.
*/
int RuleAlienMission::getPoints() const
{
return _points;
}
/**
* Returns the chances of this mission being generated based on the current game date.
* @param monthsPassed The number of months that have passed in the game world.
* @return The weight.
*/
int RuleAlienMission::getWeight(const size_t monthsPassed) const
{
if (_weights.empty())
{
return 1;
}
int weight = 0;
for (std::map<size_t, int>::const_iterator i = _weights.begin(); i != _weights.end(); ++i)
{
if (i->first > monthsPassed)
{
break;
}
weight = i->second;
}
return weight;
}
/**
* Returns the Alien score for this mission.
* @return Amount of points.
*/
int RuleAlienMission::getRetaliationOdds() const
{
return _retaliationOdds;
}
}
↑ V823 Decreased performance. Object may be created in-place in the 'assoc' container. Consider replacing methods: 'insert' -> 'emplace'.