forked from OpenXcom/OpenXcom
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAlienStrategy.cpp
More file actions
247 lines (230 loc) · 7.33 KB
/
Copy pathAlienStrategy.cpp
File metadata and controls
247 lines (230 loc) · 7.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
/*
* 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 <assert.h>
#include "AlienStrategy.h"
#include "WeightedOptions.h"
#include "../Mod/Mod.h"
#include "../Mod/RuleRegion.h"
namespace OpenXcom
{
typedef std::map<std::string, WeightedOptions*> 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 mod Pointer to the game mod.
*/
void AlienStrategy::init(const Mod *mod)
{
std::vector<std::string> regions = mod->getRegionsList();
for (std::vector<std::string>::const_iterator rr = regions.begin(); rr != regions.end(); ++rr)
{
RuleRegion *region = mod->getRegion(*rr, true);
_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 node YAML node.
*/
void AlienStrategy::load(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<std::string>();
const YAML::Node &missions = (*nn)["missions"];
WeightedOptions *options = new WeightedOptions();
options->load(missions);
_regionMissions.insert(std::make_pair(region, options));
}
_missionLocations = node["missionLocations"].as< std::map<std::string, std::vector<std::pair<std::string, int> > > >(_missionLocations);
_missionRuns = node["missionsRun"].as< std::map<std::string, int> >(_missionRuns);
}
/**
* 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);
}
node["missionLocations"] = _missionLocations;
node["missionsRun"] = _missionRuns;
return node;
}
/**
* Choose one of the regions for a mission.
* @param mod Pointer to the mod.
* @return The region id.
*/
std::string AlienStrategy::chooseRandomRegion(const Mod *mod)
{
std::string chosen = _regionChances.choose();
if (chosen.empty())
{
// no more missions to choose from: refresh.
// First, free allocated memory.
for (MissionsByRegion::iterator ii = _regionMissions.begin(); ii != _regionMissions.end(); ++ii)
{
delete ii->second;
}
_regionMissions.clear();
// re-initialize the list
init(mod);
// now let's try that again.
chosen = _regionChances.choose();
}
assert ("" != chosen);
return chosen;
}
/**
* Choose one missions available for @a region.
* @param region The region id.
* @return The mission id.
*/
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);
if (found != _regionMissions.end())
{
found->second->set(mission, 0);
if (found->second->empty())
{
_regionMissions.erase(found);
_regionChances.set(region, 0);
}
}
return _regionMissions.empty();
}
/**
* Checks the number of missions run labelled as "varName".
* @return the number of missions run under the variable name.
*/
int AlienStrategy::getMissionsRun(const std::string &varName)
{
if (_missionRuns.find(varName) != _missionRuns.end())
return _missionRuns[varName];
return 0;
}
/**
* Increments the number of missions run labelled as "varName".
* @param varName the variable name that we want to use to keep track of this.
* @param increment the value to increment by.
*/
void AlienStrategy::addMissionRun(const std::string &varName, int increment)
{
if (varName.empty())
return;
_missionRuns[varName] += increment;
}
/**
* Adds a mission location to our storage array.
* @param varName the name on the variable under which to store this info.
* @param regionName the name of the region we're using.
* @param zoneNumber the number of the zone within that region we're using.
* @param maximum the maximum size of the list we want to maintain.
*/
void AlienStrategy::addMissionLocation(const std::string &varName, const std::string ®ionName, int zoneNumber, int maximum)
{
if (maximum <= 0) return;
_missionLocations[varName].push_back(std::make_pair(regionName, zoneNumber));
if (_missionLocations[varName].size() > (size_t)(maximum))
{
_missionLocations.erase(_missionLocations.begin());
}
}
/**
* Checks that a given mission location (city or whatever) isn't stored in our list of previously attacked locations.
* @param varName the name of the variable that is storing our data.
* @param regionName the name of the region we're looking for.
* @param zoneNumber the number in the region that we want to check.
* @return if the region is valid (meaning it is not in our table).
*/
bool AlienStrategy::validMissionLocation(const std::string &varName, const std::string ®ionName, int zoneNumber)
{
if (_missionLocations.find(varName) != _missionLocations.end())
{
for (std::vector<std::pair<std::string, int> >::const_iterator i = _missionLocations[varName].begin();
i != _missionLocations[varName].end();
++i)
{
if ((*i).first == regionName && (*i).second == zoneNumber)
return false;
}
}
return true;
}
/**
* Checks that a given region appears in our strategy table.
* @param region the region we want to check for validity.
* @return if the region appears in the table or not.
*/
bool AlienStrategy::validMissionRegion(const std::string ®ion)
{
std::map<std::string, WeightedOptions*>::iterator i = _regionMissions.find(region);
return (i != _regionMissions.end());
}
}