forked from OpenXcom/OpenXcom
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathWeightedOptions.cpp
More file actions
148 lines (141 loc) · 3.75 KB
/
Copy pathWeightedOptions.cpp
File metadata and controls
148 lines (141 loc) · 3.75 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
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "WeightedOptions.h"
#include "../Engine/RNG.h"
namespace OpenXcom
{
/**
* Select a random choice from among the contents.
* This MUST be called on non-empty objects.
* Each time this is called, the returned value can be different.
* @return The key of the selected choice.
*/
const std::string WeightedOptions::choose() const
{
if (_totalWeight == 0)
{
return "";
}
size_t var = RNG::generate(0, _totalWeight);
std::map<std::string, size_t>::const_iterator ii = _choices.begin();
for (; ii != _choices.end(); ++ii)
{
if (var <= ii->second)
break;
var -= ii->second;
}
// We always have a valid iterator here.
return ii->first;
}
/**
* Select the most likely option.
* This MUST be called on non-empty objects.
* @return The key of the selected choice.
*/
const std::string WeightedOptions::top() const
{
if (_totalWeight == 0)
{
return "";
}
size_t max = 0;
std::map<std::string, size_t>::const_iterator i = _choices.begin();
for (std::map<std::string, size_t>::const_iterator ii = _choices.begin(); ii != _choices.end(); ++ii)
{
if (ii->second >= max)
{
max = ii->second;
i = ii;
}
}
// We always have a valid iterator here.
return i->first;
}
/**
* Set an option's weight.
* If @a weight is set to 0, the option is removed from the list of choices.
* If @a id already exists, the new weight replaces the old one, otherwise
* @a id is added to the list of choices, with @a weight as the weight.
* @param id The option name.
* @param weight The option's new weight.
*/
void WeightedOptions::set(const std::string &id, size_t weight)
{
std::map<std::string, size_t>::iterator option = _choices.find(id);
if (option != _choices.end())
{
_totalWeight -= option->second;
if (0 != weight)
{
option->second = weight;
_totalWeight += weight;
}
else
{
_choices.erase(option);
}
}
else if (0 != weight)
{
_choices.insert(std::make_pair(id, weight));
_totalWeight += weight;
}
}
/**
* Add the weighted options from a YAML::Node to a WeightedOptions.
* The weight option list is not replaced, only values in @a nd will be added /
* changed.
* @param nd The YAML node (containing a map) with the new values.
*/
void WeightedOptions::load(const YAML::Node &nd)
{
for (YAML::const_iterator val = nd.begin(); val != nd.end(); ++val)
{
std::string id = val->first.as<std::string>();
size_t w = val->second.as<size_t>();
set(id, w);
}
}
/**
* Send the WeightedOption contents to a YAML::Emitter.
* @return YAML node.
*/
YAML::Node WeightedOptions::save() const
{
YAML::Node node;
for (std::map<std::string, size_t>::const_iterator ii = _choices.begin(); ii != _choices.end(); ++ii)
{
node[ii->first] = ii->second;
}
return node;
}
/**
* Get the list of strings associated with these weights.
* @return the list of strings in these weights.
*/
std::vector<std::string> WeightedOptions::getNames()
{
std::vector<std::string> names;
for (std::map<std::string, size_t>::const_iterator ii = _choices.begin(); ii != _choices.end(); ++ii)
{
names.push_back((*ii).first);
}
return names;
}
}