00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "global.hpp"
00019
00020 #include "race.hpp"
00021 #include "random.hpp"
00022 #include "serialization/string_utils.hpp"
00023
00024 #include <cstdlib>
00025
00026 namespace {
00027
00028 config::child_list empty_traits;
00029
00030 }
00031
00032 static void add_prefixes(const wide_string& str, size_t length, markov_prefix_map& res)
00033 {
00034 for(size_t i = 0; i <= str.size(); ++i) {
00035 const size_t start = i > length ? i - length : 0;
00036 const wide_string key(str.begin() + start, str.begin() + i);
00037 const wchar_t c = i != str.size() ? str[i] : 0;
00038 res[key].push_back(c);
00039 }
00040 }
00041
00042 static markov_prefix_map markov_prefixes(const std::vector<std::string>& items, size_t length)
00043 {
00044 markov_prefix_map res;
00045
00046 for(std::vector<std::string>::const_iterator i = items.begin(); i != items.end(); ++i) {
00047 add_prefixes(utils::string_to_wstring(*i),length,res);
00048 }
00049
00050 return res;
00051 }
00052
00053 static wide_string markov_generate_name(const markov_prefix_map& prefixes,
00054 size_t chain_size, size_t max_len, simple_rng* rng)
00055 {
00056 if(chain_size == 0)
00057 return wide_string();
00058
00059 wide_string prefix, res;
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 std::vector<int> random(max_len);
00072 size_t j = 0;
00073 for(; j < max_len; ++j) {
00074 random[j] = rng ? rng->get_random() : get_random();
00075 }
00076
00077 j = 0;
00078 while(res.size() < max_len) {
00079 const markov_prefix_map::const_iterator i = prefixes.find(prefix);
00080 if(i == prefixes.end() || i->second.empty()) {
00081 return res;
00082 }
00083
00084 const wchar_t c = i->second[random[j++]%i->second.size()];
00085 if(c == 0) {
00086 return res;
00087 }
00088
00089 res.resize(res.size()+1);
00090 res[res.size()-1] = c;
00091 prefix.resize(prefix.size()+1);
00092 prefix[prefix.size()-1] = c;
00093 while(prefix.size() > chain_size) {
00094 prefix.erase(prefix.begin());
00095 }
00096 }
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107 wide_string originalRes = res;
00108 int prefixLen;
00109 while (res.size() > 0) {
00110 prefixLen = chain_size < res.size() ? chain_size : res.size();
00111 prefix = wide_string(res.end() - prefixLen, res.end());
00112
00113 const markov_prefix_map::const_iterator i = prefixes.find(prefix);
00114 if (i == prefixes.end() || i->second.empty()) {
00115 return res;
00116 }
00117 if (std::find(i->second.begin(), i->second.end(), static_cast<wchar_t>(0))
00118 != i->second.end()) {
00119
00120 return res;
00121 }
00122
00123
00124 res.pop_back();
00125 }
00126
00127
00128
00129
00130 return originalRes;
00131 }
00132
00133 unit_race::unit_race() :
00134 id_(),
00135 plural_name_(),
00136 description_(),
00137 ntraits_(0),
00138 chain_size_(0),
00139 traits_(&empty_traits),
00140 global_traits_(true)
00141 {
00142 name_[MALE] = "";
00143 name_[FEMALE] = "";
00144 }
00145
00146 unit_race::unit_race(const config& cfg) :
00147 id_(cfg["id"]),
00148 plural_name_(cfg["plural_name"]),
00149 description_(cfg["description"]),
00150 ntraits_(atoi(cfg["num_traits"].c_str())),
00151 chain_size_(atoi(cfg["markov_chain_size"].c_str())),
00152 traits_(&cfg.get_children("trait")),
00153 global_traits_(!utils::string_bool(cfg["ignore_global_traits"]))
00154
00155 {
00156
00157
00158
00159 if(id_.empty()) {
00160
00161 id_ = (cfg["name"]);
00162 }
00163 if(plural_name_.empty()) {
00164
00165 plural_name_ = (cfg["name"]);
00166 }
00167
00168 name_[MALE] = cfg["male_name"];
00169 if(name_[MALE].empty()) {
00170 name_[MALE] = (cfg["name"]);
00171 }
00172 name_[FEMALE] = cfg["female_name"];
00173 if(name_[FEMALE].empty()) {
00174 name_[FEMALE] = (cfg["name"]);
00175 }
00176
00177 if(chain_size_ <= 0)
00178 chain_size_ = 2;
00179
00180
00181 next_[MALE] = markov_prefixes(utils::split(cfg["male_names"]), chain_size_);
00182 next_[FEMALE] = markov_prefixes(utils::split(cfg["female_names"]), chain_size_);
00183 }
00184
00185 std::string unit_race::generate_name(
00186 unit_race::GENDER gender, simple_rng* rng) const
00187 {
00188 return utils::wstring_to_string(
00189 markov_generate_name(next_[gender], chain_size_, 12, rng));
00190 }
00191
00192 bool unit_race::uses_global_traits() const
00193 {
00194 return global_traits_;
00195 }
00196
00197 const config::child_list& unit_race::additional_traits() const
00198 {
00199 return *traits_;
00200 }
00201
00202 unsigned int unit_race::num_traits() const { return ntraits_; }
00203
00204 std::string const& gender_string(unit_race::GENDER gender) {
00205 static const std::string female_string = "female";
00206 static const std::string male_string = "male";
00207 switch(gender) {
00208 case unit_race::FEMALE:
00209 return female_string;
00210 default:
00211 case unit_race::MALE:
00212 return male_string;
00213 }
00214 }
00215
00216 unit_race::GENDER string_gender(const std::string& str, unit_race::GENDER def) {
00217 if(str == gender_string(unit_race::MALE)) {
00218 return unit_race::MALE;
00219 } else if(str == gender_string(unit_race::FEMALE)) {
00220 return unit_race::FEMALE;
00221 }
00222 return def;
00223 }