00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "global.hpp"
00019 #include "config.hpp"
00020 #include "statistics.hpp"
00021 #include "util.hpp"
00022 #include "log.hpp"
00023 #include "serialization/binary_or_text.hpp"
00024 #include "unit.hpp"
00025
00026 #define ERR_NG lg::err(lg::engine)
00027
00028 namespace {
00029
00030
00031
00032 bool mid_scenario = false;
00033
00034 typedef statistics::stats stats;
00035
00036 int stats_disabled = 0;
00037
00038 struct scenario_stats
00039 {
00040 explicit scenario_stats(const std::string& name) : scenario_name(name)
00041 {}
00042
00043 explicit scenario_stats(const config& cfg);
00044
00045 config write() const;
00046 void write(config_writer &out) const;
00047
00048 std::vector<stats> team_stats;
00049 std::string scenario_name;
00050 };
00051
00052 scenario_stats::scenario_stats(const config& cfg)
00053 {
00054 scenario_name = cfg["scenario"];
00055 const config::child_list& teams = cfg.get_children("team");
00056 for(config::child_list::const_iterator i = teams.begin(); i != teams.end(); ++i) {
00057 team_stats.push_back(stats(**i));
00058 }
00059 }
00060
00061 config scenario_stats::write() const
00062 {
00063 config res;
00064 res["scenario"] = scenario_name;
00065 for(std::vector<stats>::const_iterator i = team_stats.begin(); i != team_stats.end(); ++i) {
00066 res.add_child("team",i->write());
00067 }
00068
00069 return res;
00070 }
00071
00072 void scenario_stats::write(config_writer &out) const
00073 {
00074 out.write_key_val("scenario", scenario_name);
00075 for(std::vector<stats>::const_iterator i = team_stats.begin(); i != team_stats.end(); ++i) {
00076 out.open_child("team");
00077 i->write(out);
00078 out.close_child("team");
00079 }
00080 }
00081
00082 std::vector<scenario_stats> master_stats;
00083
00084 }
00085
00086 static stats& get_stats(int team)
00087 {
00088 if(master_stats.empty()) {
00089 master_stats.push_back(scenario_stats(""));
00090 }
00091
00092 std::vector<stats>& team_stats = master_stats.back().team_stats;
00093 const size_t index = size_t(team-1);
00094 if(index >= team_stats.size()) {
00095 team_stats.resize(index+1);
00096 }
00097
00098 return team_stats[index];
00099 }
00100
00101 static config write_str_int_map(const stats::str_int_map& m)
00102 {
00103 config res;
00104 for(stats::str_int_map::const_iterator i = m.begin(); i != m.end(); ++i) {
00105 char buf[50];
00106 snprintf(buf,sizeof(buf),"%d",i->second);
00107 res[i->first] = buf;
00108 }
00109
00110 return res;
00111 }
00112
00113 static void write_str_int_map(config_writer &out, const stats::str_int_map& m)
00114 {
00115 for(stats::str_int_map::const_iterator i = m.begin(); i != m.end(); ++i) {
00116 char buf[50];
00117 snprintf(buf,sizeof(buf),"%d",i->second);
00118 out.write_key_val(i->first, buf);
00119 }
00120 }
00121
00122 static stats::str_int_map read_str_int_map(const config& cfg)
00123 {
00124 stats::str_int_map m;
00125 for(string_map::const_iterator i = cfg.values.begin(); i != cfg.values.end(); ++i) {
00126 m[i->first] = atoi(i->second.c_str());
00127 }
00128
00129 return m;
00130 }
00131
00132 static config write_battle_result_map(const stats::battle_result_map& m)
00133 {
00134 config res;
00135 for(stats::battle_result_map::const_iterator i = m.begin(); i != m.end(); ++i) {
00136 config& new_cfg = res.add_child("sequence");
00137 new_cfg = write_str_int_map(i->second);
00138
00139 char buf[50];
00140 snprintf(buf,sizeof(buf),"%d",i->first);
00141 new_cfg["_num"] = buf;
00142 }
00143
00144 return res;
00145 }
00146
00147 static void write_battle_result_map(config_writer &out, const stats::battle_result_map& m)
00148 {
00149 for(stats::battle_result_map::const_iterator i = m.begin(); i != m.end(); ++i) {
00150 out.open_child("sequence");
00151 write_str_int_map(out, i->second);
00152
00153 char buf[50];
00154 snprintf(buf,sizeof(buf),"%d",i->first);
00155 out.write_key_val("_num", buf);
00156 out.close_child("sequence");
00157 }
00158 }
00159
00160 static stats::battle_result_map read_battle_result_map(const config& cfg)
00161 {
00162 stats::battle_result_map m;
00163 const config::child_list c = cfg.get_children("sequence");
00164 for(config::child_list::const_iterator i = c.begin(); i != c.end(); ++i) {
00165 config item = **i;
00166 const int key = atoi(item["_num"].c_str());
00167 item.values.erase("_num");
00168 m[key] = read_str_int_map(item);
00169 }
00170
00171 return m;
00172 }
00173
00174 static void merge_str_int_map(stats::str_int_map& a, const stats::str_int_map& b)
00175 {
00176 for(stats::str_int_map::const_iterator i = b.begin(); i != b.end(); ++i) {
00177 a[i->first] += i->second;
00178 }
00179 }
00180
00181 static void merge_battle_result_maps(stats::battle_result_map& a, const stats::battle_result_map& b)
00182 {
00183 for(stats::battle_result_map::const_iterator i = b.begin(); i != b.end(); ++i) {
00184 merge_str_int_map(a[i->first],i->second);
00185 }
00186 }
00187
00188 static void merge_stats(stats& a, const stats& b)
00189 {
00190 merge_str_int_map(a.recruits,b.recruits);
00191 merge_str_int_map(a.recalls,b.recalls);
00192 merge_str_int_map(a.advanced_to,b.advanced_to);
00193 merge_str_int_map(a.deaths,b.deaths);
00194 merge_str_int_map(a.killed,b.killed);
00195
00196 merge_battle_result_maps(a.attacks,b.attacks);
00197 merge_battle_result_maps(a.defends,b.defends);
00198
00199 a.recruit_cost += b.recruit_cost;
00200 a.recall_cost += b.recall_cost;
00201
00202 a.damage_inflicted += b.damage_inflicted;
00203 a.damage_taken += b.damage_taken;
00204 a.expected_damage_inflicted += b.expected_damage_inflicted;
00205 a.expected_damage_taken += b.expected_damage_taken;
00206 a.turn_damage_inflicted += b.turn_damage_inflicted;
00207 a.turn_damage_taken += b.turn_damage_taken;
00208 a.turn_expected_damage_inflicted += b.turn_expected_damage_inflicted;
00209 a.turn_expected_damage_taken += b.turn_expected_damage_taken;
00210
00211 a.new_expected_damage_inflicted += b.new_expected_damage_inflicted;
00212 a.new_expected_damage_taken += b.new_expected_damage_taken;
00213 a.new_turn_expected_damage_inflicted += b.new_turn_expected_damage_inflicted;
00214 a.new_turn_expected_damage_taken += b.new_turn_expected_damage_taken;
00215 }
00216
00217 namespace statistics
00218 {
00219
00220 stats::stats() : recruit_cost(0), recall_cost(0),
00221 damage_inflicted(0), damage_taken(0),
00222 turn_damage_inflicted(0), turn_damage_taken(0),
00223 expected_damage_inflicted(0), expected_damage_taken(0),
00224 turn_expected_damage_inflicted(0), turn_expected_damage_taken(0),
00225 new_expected_damage_inflicted(0), new_expected_damage_taken(0),
00226 new_turn_expected_damage_inflicted(0), new_turn_expected_damage_taken(0)
00227 {}
00228
00229 stats::stats(const config& cfg)
00230 {
00231 read(cfg);
00232 }
00233
00234 config stats::write() const
00235 {
00236 config res;
00237 res.add_child("recruits",write_str_int_map(recruits));
00238 res.add_child("recalls",write_str_int_map(recalls));
00239 res.add_child("advances",write_str_int_map(advanced_to));
00240 res.add_child("deaths",write_str_int_map(deaths));
00241 res.add_child("killed",write_str_int_map(killed));
00242 res.add_child("attacks",write_battle_result_map(attacks));
00243 res.add_child("defends",write_battle_result_map(defends));
00244
00245 std::stringstream ss;
00246 ss << recruit_cost;
00247 res["recruit_cost"] = ss.str();
00248 ss.str(std::string());
00249 ss << recall_cost;
00250 res["recall_cost"] = ss.str();
00251
00252 ss.str(std::string());
00253 ss << damage_inflicted;
00254 res["damage_inflicted"] = ss.str();
00255 ss.str(std::string());
00256 ss << damage_taken;
00257 res["damage_taken"] = ss.str();
00258 ss.str(std::string());
00259 ss << expected_damage_inflicted;
00260 res["expected_damage_inflicted"] = ss.str();
00261 ss.str(std::string());
00262 ss << expected_damage_taken;
00263 res["expected_damage_taken"] = ss.str();
00264 ss.str(std::string());
00265 ss << turn_damage_inflicted;
00266
00267 res["turn_damage_inflicted"] = ss.str();
00268 ss.str(std::string());
00269 ss << turn_damage_taken;
00270 res["turn_damage_taken"] = ss.str();
00271 ss.str(std::string());
00272 ss << turn_expected_damage_inflicted;
00273 res["turn_expected_damage_inflicted"] = ss.str();
00274 ss.str(std::string());
00275 ss << turn_expected_damage_taken;
00276 res["turn_expected_damage_taken"] = ss.str();
00277
00278 ss.str(std::string());
00279 ss << new_expected_damage_inflicted;
00280 res["new_expected_damage_inflicted"] = ss.str();
00281 ss.str(std::string());
00282 ss << new_expected_damage_taken;
00283 res["new_expected_damage_taken"] = ss.str();
00284 ss.str(std::string());
00285 ss << new_turn_expected_damage_inflicted;
00286 res["new_turn_expected_damage_inflicted"] = ss.str();
00287 ss.str(std::string());
00288 ss << new_turn_expected_damage_taken;
00289 res["new_turn_expected_damage_taken"] = ss.str();
00290
00291 return res;
00292 }
00293
00294 void stats::write(config_writer &out) const
00295 {
00296 out.open_child("recruits");
00297 write_str_int_map(out, recruits);
00298 out.close_child("recruits");
00299 out.open_child("recalls");
00300 write_str_int_map(out, recalls);
00301 out.close_child("recalls");
00302 out.open_child("advances");
00303 write_str_int_map(out, advanced_to);
00304 out.close_child("advances");
00305 out.open_child("deaths");
00306 write_str_int_map(out, deaths);
00307 out.close_child("deaths");
00308 out.open_child("killed");
00309 write_str_int_map(out, killed);
00310 out.close_child("killed");
00311 out.open_child("attacks");
00312 write_battle_result_map(out, attacks);
00313 out.close_child("attacks");
00314 out.open_child("defends");
00315 write_battle_result_map(out, defends);
00316 out.close_child("defends");
00317
00318 std::stringstream ss;
00319 ss << recruit_cost;
00320 out.write_key_val("recruit_cost", ss.str());
00321 ss.str(std::string());
00322 ss << recall_cost;
00323 out.write_key_val("recall_cost", ss.str());
00324
00325 ss.str(std::string());
00326 ss << damage_inflicted;
00327 out.write_key_val("damage_inflicted", ss.str());
00328 ss.str(std::string());
00329 ss << damage_taken;
00330 out.write_key_val("damage_taken", ss.str());
00331 ss.str(std::string());
00332 ss << expected_damage_inflicted;
00333 out.write_key_val("expected_damage_inflicted", ss.str());
00334 ss.str(std::string());
00335 ss << expected_damage_taken;
00336 out.write_key_val("expected_damage_taken", ss.str());
00337 ss.str(std::string());
00338 ss << turn_damage_inflicted;
00339
00340 out.write_key_val("turn_damage_inflicted", ss.str());
00341 ss.str(std::string());
00342 ss << turn_damage_taken;
00343 out.write_key_val("turn_damage_taken", ss.str());
00344 ss.str(std::string());
00345 ss << turn_expected_damage_inflicted;
00346 out.write_key_val("turn_expected_damage_inflicted", ss.str());
00347 ss.str(std::string());
00348 ss << turn_expected_damage_taken;
00349 out.write_key_val("turn_expected_damage_taken", ss.str());
00350
00351 ss.str(std::string());
00352 ss << new_expected_damage_inflicted;
00353 out.write_key_val("new_expected_damage_inflicted", ss.str());
00354 ss.str(std::string());
00355 ss << new_expected_damage_taken;
00356 out.write_key_val("new_expected_damage_taken", ss.str());
00357 ss.str(std::string());
00358 ss << new_turn_expected_damage_inflicted;
00359 out.write_key_val("new_turn_expected_damage_inflicted", ss.str());
00360 ss.str(std::string());
00361 ss << new_turn_expected_damage_taken;
00362 out.write_key_val("new_turn_expected_damage_taken", ss.str());
00363
00364 }
00365
00366 void stats::read(const config& cfg)
00367 {
00368 if(cfg.child("recruits")) {
00369 recruits = read_str_int_map(*cfg.child("recruits"));
00370 }
00371 if(cfg.child("recalls")) {
00372 recalls = read_str_int_map(*cfg.child("recalls"));
00373 }
00374 if(cfg.child("advances")) {
00375 advanced_to = read_str_int_map(*cfg.child("advances"));
00376 }
00377 if(cfg.child("deaths")) {
00378 deaths = read_str_int_map(*cfg.child("deaths"));
00379 }
00380 if(cfg.child("killed")) {
00381 killed = read_str_int_map(*cfg.child("killed"));
00382 }
00383 if(cfg.child("recalls")) {
00384 recalls = read_str_int_map(*cfg.child("recalls"));
00385 }
00386 if(cfg.child("attacks")) {
00387 attacks = read_battle_result_map(*cfg.child("attacks"));
00388 }
00389 if(cfg.child("defends")) {
00390 defends = read_battle_result_map(*cfg.child("defends"));
00391 }
00392
00393 recruit_cost = lexical_cast<long long>(cfg["recruit_cost"]);
00394 recall_cost = lexical_cast<long long>(cfg["recall_cost"]);
00395
00396 damage_inflicted = lexical_cast<long long>(cfg["damage_inflicted"]);
00397 damage_taken = lexical_cast<long long>(cfg["damage_taken"]);
00398 expected_damage_inflicted = lexical_cast<long long>(cfg["expected_damage_inflicted"]);
00399 expected_damage_taken = lexical_cast<long long>(cfg["expected_damage_taken"]);
00400
00401 turn_damage_inflicted = lexical_cast<long long>(cfg["turn_damage_inflicted"]);
00402 turn_damage_taken = lexical_cast<long long>(cfg["turn_damage_taken"]);
00403 turn_expected_damage_inflicted = lexical_cast<long long>(cfg["turn_expected_damage_inflicted"]);
00404 turn_expected_damage_taken = lexical_cast<long long>(cfg["turn_expected_damage_taken"]);
00405
00406 new_expected_damage_inflicted = lexical_cast_default<long long>(cfg["new_expected_damage_inflicted"],expected_damage_inflicted);
00407 new_expected_damage_taken = lexical_cast_default<long long>(cfg["new_expected_damage_taken"],expected_damage_taken);
00408 new_turn_expected_damage_inflicted = lexical_cast_default<long long>(cfg["new_turn_expected_damage_inflicted"],turn_expected_damage_inflicted);
00409 new_turn_expected_damage_taken = lexical_cast_default<long long>(cfg["new_turn_expected_damage_taken"],turn_expected_damage_taken);
00410 }
00411
00412 disabler::disabler() { stats_disabled++; }
00413 disabler::~disabler() { stats_disabled--; }
00414
00415 scenario_context::scenario_context(const std::string& name)
00416 {
00417 if(!mid_scenario || master_stats.empty()) {
00418 master_stats.push_back(scenario_stats(name));
00419 }
00420
00421 mid_scenario = true;
00422 }
00423
00424 scenario_context::~scenario_context()
00425 {
00426 mid_scenario = false;
00427 }
00428
00429 attack_context::attack_context(const unit& a, const unit& d, int a_cth, int d_cth)
00430 : attacker_type(a.type_id()), defender_type(d.type_id()),
00431 attacker_side(a.side()), defender_side(d.side()),
00432 chance_to_hit_defender(a_cth), chance_to_hit_attacker(d_cth)
00433 {
00434 }
00435
00436 attack_context::~attack_context()
00437 {
00438 if(stats_disabled > 0)
00439 return;
00440
00441 std::string attacker_key = "s" + attacker_res;
00442 std::string defender_key = "s" + defender_res;
00443
00444 attacker_stats().attacks[chance_to_hit_defender][attacker_key]++;
00445 defender_stats().defends[chance_to_hit_attacker][defender_key]++;
00446 }
00447
00448 stats& attack_context::attacker_stats()
00449 {
00450 return get_stats(attacker_side);
00451 }
00452
00453 stats& attack_context::defender_stats()
00454 {
00455 return get_stats(defender_side);
00456 }
00457
00458 void attack_context::attack_excepted_damage(double attacker_inflict_, double defender_inflict_)
00459 {
00460 const long long attacker_inflict = static_cast<long long>(attacker_inflict_ * stats::desimal_shift);
00461 const long long defender_inflict = static_cast<long long>(defender_inflict_ * stats::desimal_shift);
00462 attacker_stats().new_expected_damage_inflicted += attacker_inflict;
00463 attacker_stats().new_expected_damage_taken += defender_inflict;
00464 defender_stats().new_expected_damage_inflicted += defender_inflict;
00465 defender_stats().new_expected_damage_taken += attacker_inflict;
00466 attacker_stats().new_turn_expected_damage_inflicted += attacker_inflict;
00467 attacker_stats().new_turn_expected_damage_taken += defender_inflict;
00468 defender_stats().new_turn_expected_damage_inflicted += defender_inflict;
00469 defender_stats().new_turn_expected_damage_taken += attacker_inflict;
00470 }
00471
00472
00473 void attack_context::attack_result(attack_context::ATTACK_RESULT res, long long damage, long long drain)
00474 {
00475 if(stats_disabled > 0)
00476 return;
00477
00478 push_back(attacker_res,(res == MISSES ? '0' : '1'));
00479
00480 if(res != MISSES) {
00481
00482 attacker_stats().damage_taken -= drain;
00483 defender_stats().damage_inflicted -= drain;
00484 attacker_stats().turn_damage_taken -= drain;
00485 defender_stats().turn_damage_inflicted -= drain;
00486
00487 attacker_stats().damage_inflicted += damage;
00488 defender_stats().damage_taken += damage;
00489 attacker_stats().turn_damage_inflicted += damage;
00490 defender_stats().turn_damage_taken += damage;
00491 }
00492 const int exp_damage = damage * chance_to_hit_defender * 10;
00493 const int exp_drain = drain * chance_to_hit_defender * 10;
00494
00495 attacker_stats().expected_damage_taken -= exp_drain;
00496 defender_stats().expected_damage_inflicted -= exp_drain;
00497 attacker_stats().turn_expected_damage_taken -= exp_drain;
00498 defender_stats().turn_expected_damage_inflicted -= exp_drain;
00499
00500
00501 attacker_stats().expected_damage_inflicted += exp_damage;
00502 defender_stats().expected_damage_taken += exp_damage;
00503 attacker_stats().turn_expected_damage_inflicted += exp_damage;
00504 defender_stats().turn_expected_damage_taken += exp_damage;
00505
00506 if(res == KILLS) {
00507 attacker_stats().killed[defender_type]++;
00508 defender_stats().deaths[defender_type]++;
00509 }
00510 }
00511
00512 void attack_context::defend_result(attack_context::ATTACK_RESULT res, long long damage, long long drain)
00513 {
00514 if(stats_disabled > 0)
00515 return;
00516
00517 push_back(defender_res,(res == MISSES ? '0' : '1'));
00518
00519
00520 if(res != MISSES) {
00521
00522 defender_stats().damage_taken -= drain;
00523 attacker_stats().damage_inflicted -= drain;
00524 defender_stats().turn_damage_taken -= drain;
00525 attacker_stats().turn_damage_inflicted -= drain;
00526
00527 attacker_stats().damage_taken += damage;
00528 defender_stats().damage_inflicted += damage;
00529 attacker_stats().turn_damage_taken += damage;
00530 defender_stats().turn_damage_inflicted += damage;
00531 }
00532 const long long exp_damage = damage * chance_to_hit_attacker * 10;
00533 const long long exp_drain = drain * chance_to_hit_attacker * 10;
00534
00535 defender_stats().expected_damage_taken -= exp_drain;
00536 attacker_stats().expected_damage_inflicted -= exp_drain;
00537 defender_stats().turn_expected_damage_taken -= exp_drain;
00538 attacker_stats().turn_expected_damage_inflicted -= exp_drain;
00539
00540 attacker_stats().expected_damage_taken += exp_damage;
00541 defender_stats().expected_damage_inflicted += exp_damage;
00542 attacker_stats().turn_expected_damage_taken += exp_damage;
00543 defender_stats().turn_expected_damage_inflicted += exp_damage;
00544
00545 if(res == KILLS) {
00546 attacker_stats().deaths[attacker_type]++;
00547 defender_stats().killed[attacker_type]++;
00548 }
00549 }
00550
00551 void recruit_unit(const unit& u)
00552 {
00553 if(stats_disabled > 0)
00554 return;
00555
00556 stats& s = get_stats(u.side());
00557 s.recruits[u.type_id()]++;
00558 s.recruit_cost += u.cost();
00559 }
00560
00561 void recall_unit(const unit& u)
00562 {
00563 if(stats_disabled > 0)
00564 return;
00565
00566 stats& s = get_stats(u.side());
00567 s.recalls[u.type_id()]++;
00568 s.recall_cost += u.cost();
00569 }
00570
00571 void un_recall_unit(const unit& u)
00572 {
00573 if(stats_disabled > 0)
00574 return;
00575
00576 stats& s = get_stats(u.side());
00577 s.recalls[u.type_id()]--;
00578 s.recall_cost -= u.cost();
00579 }
00580
00581 void un_recruit_unit(const unit& u)
00582 {
00583 if(stats_disabled > 0)
00584 return;
00585
00586 stats& s = get_stats(u.side());
00587 s.recruits[u.type_id()]--;
00588 s.recruit_cost -= u.cost();
00589 }
00590
00591
00592 void advance_unit(const unit& u)
00593 {
00594 if(stats_disabled > 0)
00595 return;
00596
00597 stats& s = get_stats(u.side());
00598 s.advanced_to[u.type_id()]++;
00599 }
00600
00601 void reset_turn_stats(int side)
00602 {
00603 stats &s = get_stats(side);
00604 s.turn_damage_inflicted = 0;
00605 s.turn_damage_taken = 0;
00606 s.turn_expected_damage_inflicted = 0;
00607 s.turn_expected_damage_taken = 0;
00608 s.new_turn_expected_damage_inflicted = 0;
00609 s.new_turn_expected_damage_taken = 0;
00610 }
00611
00612 stats calculate_stats(int category, int side)
00613 {
00614 if(category == 0) {
00615 stats res;
00616 for(int i = 1; i <= int(master_stats.size()); ++i) {
00617 merge_stats(res,calculate_stats(i,side));
00618 }
00619
00620 return res;
00621 } else {
00622 const size_t index = master_stats.size() - size_t(category);
00623 const size_t side_index = size_t(side) - 1;
00624 if(index < master_stats.size() && side_index < master_stats[index].team_stats.size()) {
00625 return master_stats[index].team_stats[side_index];
00626 } else {
00627 return stats();
00628 }
00629 }
00630 }
00631
00632 config write_stats()
00633 {
00634 config res;
00635 res["mid_scenario"] = (mid_scenario ? "true" : "false");
00636
00637 for(std::vector<scenario_stats>::const_iterator i = master_stats.begin(); i != master_stats.end(); ++i) {
00638 res.add_child("scenario",i->write());
00639 }
00640
00641 return res;
00642 }
00643
00644 void write_stats(config_writer &out)
00645 {
00646 out.write_key_val("mid_scenario", mid_scenario ? "true" : "false");
00647
00648 for(std::vector<scenario_stats>::const_iterator i = master_stats.begin(); i != master_stats.end(); ++i) {
00649 out.open_child("scenario");
00650 i->write(out);
00651 out.close_child("scenario");
00652 }
00653 }
00654
00655 void read_stats(const config& cfg)
00656 {
00657 fresh_stats();
00658 mid_scenario = (utils::string_bool(cfg["mid_scenario"]));
00659
00660 const config::child_list& scenarios = cfg.get_children("scenario");
00661 for(config::child_list::const_iterator i = scenarios.begin(); i != scenarios.end(); ++i) {
00662 master_stats.push_back(scenario_stats(**i));
00663 }
00664 }
00665
00666 void fresh_stats()
00667 {
00668 master_stats.clear();
00669 mid_scenario = false;
00670 }
00671
00672 void clear_current_scenario()
00673 {
00674 if(master_stats.empty() == false) {
00675 master_stats.pop_back();
00676 mid_scenario = false;
00677 }
00678 }
00679
00680 int sum_str_int_map(const stats::str_int_map& m)
00681 {
00682 int res = 0;
00683 for(stats::str_int_map::const_iterator i = m.begin(); i != m.end(); ++i) {
00684 res += i->second;
00685 }
00686
00687 return res;
00688 }
00689
00690 }
00691