The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
carryover.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2016 by David White <[email protected]>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #include "carryover.hpp"
16 
17 #include "global.hpp"
18 
19 #include "config.hpp"
20 #include "team.hpp"
21 #include "units/unit.hpp"
22 #include <cassert>
23 
25  : add_(!side["carryover_add"].empty() ? side["carryover_add"].to_bool() : side["add"].to_bool())
26  , current_player_(side["current_player"])
27  , gold_(!side["carryover_gold"].empty() ? side["carryover_gold"].to_int() : side["gold"].to_int())
28  // if we load it from a snapshot we need to read the recruits from "recruits" and not from "previous_recruits".
29  , previous_recruits_(side.has_attribute("recruit") ? utils::set_split(side["recruit"]) :utils::set_split(side["previous_recruits"]))
30  , recall_list_()
31  , save_id_(side["save_id"])
32  , variables_(side.child_or_empty("variables"))
33 {
34  for(const config& u : side.child_range("unit")) {
35  recall_list_.push_back(u);
36  config& u_back = recall_list_.back();
37  u_back.remove_attributes("side", "goto_x", "goto_y", "x", "y");
38  }
39 }
40 
41 carryover::carryover(const team& t, const int gold, const bool add)
42  : add_ (add)
43  , current_player_(t.current_player())
44  , gold_(gold)
45  , previous_recruits_(t.recruits())
46  , recall_list_()
47  , save_id_(t.save_id())
48  , variables_(t.variables())
49 {
50  for(const unit_const_ptr & u : t.recall_list()) {
51  recall_list_.push_back(config());
52  u->write(recall_list_.back());
53  }
54 }
55 
56 static const int default_gold_qty = 100;
57 
59 
60  int cfg_gold = side_cfg["gold"].to_int();
61 
62  if(side_cfg["gold"].empty()) {
63  cfg_gold = default_gold_qty;
64  side_cfg["gold"] = cfg_gold;
65  }
66 
67  if(add_ && gold_ > 0){
68  side_cfg["gold"] = cfg_gold + gold_;
69  }
70  else if(gold_ > cfg_gold){
71  side_cfg["gold"] = gold_;
72  }
73  side_cfg.child_or_add("variables").swap(variables_);
74  variables_.clear();
75  gold_ = 0;
76 }
77 
79  std::string can_recruit_str = utils::join(previous_recruits_, ",");
80  previous_recruits_.clear();
81  side_cfg["previous_recruits"] = can_recruit_str;
82 }
83 
85  for(const config & u_cfg : recall_list_) {
86  side_cfg.add_child("unit", u_cfg);
87  }
88  recall_list_.clear();
89 }
90 
92  // Join the previous recruits into a string.
93  std::string can_recruit_str = utils::join(previous_recruits_);
94  if ( erase )
95  // Clear the previous recruits.
96  previous_recruits_.clear();
97 
98  return can_recruit_str;
99 }
100 
102  std::string side = "";
103  side.append("Side " + save_id_ + ": gold " + std::to_string(gold_) + " recruits " + get_recruits(false) + " units ");
104  for(const config & u_cfg : recall_list_) {
105  side.append(u_cfg["name"].str() + ", ");
106  }
107  return side;
108 }
109 
111  config& side = cfg.add_child("side");
112  side["save_id"] = save_id_;
113  side["gold"] = gold_;
114  side["add"] = add_;
115  side["current_player"] = current_player_;
116  side["previous_recruits"] = get_recruits(false);
117  side.add_child("variables", variables_);
118  for(const config & u_cfg : recall_list_) {
119  side.add_child("unit", u_cfg);
120  }
121 }
122 
123 carryover_info::carryover_info(const config& cfg, bool from_snpashot)
124  : carryover_sides_()
125  , variables_(cfg.child_or_empty("variables"))
126  , rng_(cfg)
127  , wml_menu_items_()
128  , next_scenario_(cfg["next_scenario"])
129  , next_underlying_unit_id_(cfg["next_underlying_unit_id"].to_int(0))
130 {
131  for(const config& side : cfg.child_range("side"))
132  {
133  if(side["lost"].to_bool(false) || !side["persistent"].to_bool(true))
134  {
135  //this shouldnt happen outside a snpshot.
136  assert(from_snpashot);
137  continue;
138  }
139  this->carryover_sides_.push_back(carryover(side));
140  }
141  for(const config& item : cfg.child_range("menu_item"))
142  {
143  wml_menu_items_.push_back(new config(item));
144  }
145 }
146 
147 std::vector<carryover>& carryover_info::get_all_sides() {
148  return carryover_sides_;
149 }
150 
152  carryover_sides_.push_back(carryover(cfg));
153 }
154 
157  it != carryover_sides_.end(); ++it) {
158 
159  if (it->get_save_id() == id) {
160  carryover_sides_.erase(it);
161  break;
162  }
163  }
164 }
165 
167 {
170  {
171  return value == v2.get_save_id();
172  }
173 
175 };
176 
178  if(side_cfg["save_id"].empty()){
179  side_cfg["save_id"] = side_cfg["id"];
180  }
181  std::vector<carryover>::iterator iside = std::find_if(
182  carryover_sides_.begin(),
183  carryover_sides_.end(),
184  save_id_equals(side_cfg["save_id"])
185  );
186  if(iside != carryover_sides_.end())
187  {
188  iside->transfer_all_gold_to(side_cfg);
189  iside->transfer_all_recalls_to(side_cfg);
190  iside->transfer_all_recruits_to(side_cfg);
191  carryover_sides_.erase(iside);
192  return;
193  }
194  else
195  {
196  //if no carryover was found for this side, check if starting gold is defined
197  if(!side_cfg.has_attribute("gold") || side_cfg["gold"].empty()){
198  side_cfg["gold"] = default_gold_qty;
199  }
200  }
201 }
202 
204 {
205  if(!level.has_attribute("next_underlying_unit_id"))
206  {
207  level["next_underlying_unit_id"] = next_underlying_unit_id_;
208  }
209 
210  //if the game has been loaded from a snapshot, the existing variables will be the current ones
211  if(!level.has_child("variables")) {
212  level.add_child("variables", variables_);
213  }
214 
215  config::attribute_value & seed_value = level["random_seed"];
216  if ( seed_value.empty() ) {
217  seed_value = rng_.get_random_seed_str();
218  level["random_calls"] = rng_.get_random_calls();
219  }
220 
221  if(!level.has_child("menu_item")){
222  for(config& item : wml_menu_items_)
223  {
224  level.add_child("menu_item").swap(item);
225  }
226  }
227 
228  next_scenario_ = "";
229  variables_ = config();
230  wml_menu_items_.clear();
231 
232 }
233 
235 {
236  config cfg;
237  cfg["next_underlying_unit_id"] = next_underlying_unit_id_;
238  cfg["next_scenario"] = next_scenario_;
239 
240  for(carryover& c : carryover_sides_) {
241  c.to_config(cfg);
242  }
243 
244  cfg["random_seed"] = rng_.get_random_seed_str();
245  cfg["random_calls"] = rng_.get_random_calls();
246 
247  cfg.add_child("variables", variables_);
248  for(const config& item : wml_menu_items_)
249  {
250  cfg.add_child("menu_item", item);
251  }
252  return cfg;
253 }
254 
256  for(carryover& side : carryover_sides_) {
257  if(side.get_save_id() == save_id){
258  return &side;
259  }
260  }
261  return nullptr;
262 }
263 
264 
266 {
267  for(const carryover & old_side : old_carryover.carryover_sides_)
268  {
269  std::vector<carryover>::iterator iside = std::find_if(
270  carryover_sides_.begin(),
271  carryover_sides_.end(),
272  save_id_equals(old_side.get_save_id())
273  );
274  //add the side if don't already have it.
275  if(iside == carryover_sides_.end())
276  {
277  this->carryover_sides_.push_back(old_side);
278  }
279  }
280 }
281 
child_itors child_range(const std::string &key)
Definition: config.cpp:613
void add_side(const config &cfg)
Definition: carryover.cpp:151
GLint level
Definition: glew.h:1220
const GLfloat * c
Definition: glew.h:12741
std::vector< carryover > & get_all_sides()
Definition: carryover.cpp:147
boost::ptr_vector< config > wml_menu_items_
Definition: carryover.hpp:93
const config to_config()
Definition: carryover.cpp:234
config & child_or_add(const std::string &key)
Returns a reference to the first child with the given key.
Definition: config.cpp:734
void transfer_all_recalls_to(config &side_cfg)
Definition: carryover.cpp:84
GLfloat GLfloat GLfloat v2
Definition: glew.h:1824
GLuint const GLfloat * val
Definition: glew.h:2614
std::string save_id_
Definition: carryover.hpp:47
void merge_old_carryover(const carryover_info &old_carryover)
Definition: carryover.cpp:265
carryover * get_side(std::string save_id)
Definition: carryover.cpp:255
config variables_
Definition: carryover.hpp:91
void clear()
Definition: config.cpp:1055
-file sdl_utils.hpp
void transfer_to(config &level)
Definition: carryover.cpp:203
bool empty() const
Definition: config.cpp:1105
bool empty() const
Tests for an attribute that either was never set or was set to "".
Definition: config.cpp:375
GLdouble GLdouble t
Definition: glew.h:1366
Definitions for the interface to Wesnoth Markup Language (WML).
std::string get_random_seed_str() const
Definition: mt_rng.cpp:99
Variant for storing WML attributes.
Definition: config.hpp:223
const std::string & get_save_id() const
Definition: carryover.hpp:32
std::set< std::string > previous_recruits_
Definition: carryover.hpp:42
int next_underlying_unit_id_
Definition: carryover.hpp:95
unsigned int get_random_calls() const
Definition: mt_rng.hpp:59
void transfer_all_to(config &side_cfg)
Definition: carryover.cpp:177
bool has_child(const std::string &key) const
Determine whether a config has a child or not.
Definition: config.cpp:651
This class stores all the data for a single 'side' (in game nomenclature).
Definition: team.hpp:50
void swap(config &cfg)
Definition: config.cpp:1518
GLuint id
Definition: glew.h:1647
std::vector< config > recall_list_
Definition: carryover.hpp:46
GLsizei const GLfloat * value
Definition: glew.h:1817
config variables_
Definition: carryover.hpp:48
void erase(const std::string &key)
config & add_child(const std::string &key)
Definition: config.cpp:743
void transfer_all_gold_to(config &side_cfg)
Definition: carryover.cpp:58
std::vector< carryover > carryover_sides_
Definition: carryover.hpp:90
std::string join(T const &v, const std::string &s=",")
Generates a new string joining container items in a list.
std::string current_player_
Definition: carryover.hpp:40
std::string next_scenario_
the scenario coming next (for campaigns)
Definition: carryover.hpp:94
const std::string to_string()
Definition: carryover.cpp:101
bool add_
Definition: carryover.hpp:39
std::string get_recruits(bool erase=false)
Definition: carryover.cpp:91
void transfer_all_recruits_to(config &side_cfg)
Definition: carryover.cpp:78
save_id_equals(std::string val)
Definition: carryover.cpp:168
bool operator()(carryover &v2)
Definition: carryover.cpp:169
std::set< std::string > set_split(std::string const &val, const char c= ',', const int flags=REMOVE_EMPTY|STRIP_SPACES)
Splits a (comma-)separated string into a set of pieces.
std::string value
Definition: carryover.cpp:174
bool has_attribute(const std::string &key) const
Definition: config.cpp:514
void remove_side(const std::string &id)
Definition: carryover.cpp:155
recall_list_manager & recall_list()
Definition: team.hpp:220
rand_rng::mt_rng rng_
Definition: carryover.hpp:92
void to_config(config &cfg)
Definition: carryover.cpp:110
static const int default_gold_qty
Definition: carryover.cpp:56
void remove_attributes(T...keys)
Definition: config.hpp:571
std::string::const_iterator iterator
Definition: tokenizer.hpp:21
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:83
GLsizei const GLcharARB ** string
Definition: glew.h:4503