The Battle for Wesnoth  1.15.9+dev
tod_manager.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2018 by Eugen Jiresch
3  Part of the Battle for Wesnoth Project https://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 "tod_manager.hpp"
16 
17 #include "actions/attack.hpp"
18 #include "display_context.hpp"
19 #include "game_data.hpp"
20 #include "gettext.hpp"
21 #include "log.hpp"
22 #include "map/map.hpp"
23 #include "play_controller.hpp"
24 #include "random.hpp"
25 #include "resources.hpp"
27 #include "units/abilities.hpp"
28 #include "units/alignment.hpp"
29 #include "units/unit.hpp"
30 
31 #include <algorithm>
32 #include <functional>
33 #include <iterator>
34 
35 static lg::log_domain log_engine("engine");
36 #define LOG_NG LOG_STREAM(info, log_engine)
37 
38 tod_manager::tod_manager(const config& scenario_cfg)
39  : currentTime_(0)
40  , times_()
41  , areas_()
42  , liminal_bonus_(25)
43  , turn_(scenario_cfg["turn_at"].to_int(1))
44  , num_turns_(scenario_cfg["turns"].to_int(-1))
45  , has_turn_event_fired_(!scenario_cfg["it_is_a_new_turn"].to_bool(true))
46  , has_tod_bonus_changed_(false)
47  , has_cfg_liminal_bonus_(false)
48 {
49  // ? : operator doesn't work in this case.
50  if(scenario_cfg["current_time"].to_int(-17403) == -17403) {
51  random_tod_ = scenario_cfg["random_start_time"];
52  } else {
53  random_tod_ = false;
54  }
55 
56  time_of_day::parse_times(scenario_cfg, times_);
58 
59  if(scenario_cfg.has_attribute("liminal_bonus")) {
60  liminal_bonus_ = scenario_cfg["liminal_bonus"].to_int(liminal_bonus_);
62  }
63 
64  // We need to call parse_times before fix_time_index because otherwise the first parameter will always be 0.
65  currentTime_ = fix_time_index(times_.size(), scenario_cfg["current_time"].to_int(0));
66 }
67 
69 {
70  // process the random_start_time string, which can be boolean yes/no true/false or a
71  // comma-separated string of integers >= 1 referring to the times_ array indices
72  std::vector<std::string> output_strings = utils::split(random_tod_.str());
73  std::vector<int> output;
74 
75  try {
76  std::transform(output_strings.begin(), output_strings.end(), std::back_inserter(output),
77  [](const std::string& str) { return std::stoi(str); });
78  } catch(const std::invalid_argument&) {
79  // This happens if the random_start_time string is a boolean.
80  // Simply ignore the exception.
81  }
82 
83  // Remove non-positive times
84  output.erase(std::remove_if(output.begin(), output.end(), [](int time) { return time <= 0; }), output.end());
85 
86  if(!output.empty()) {
87  int chosen = output[r.next_random() % output.size()];
88  currentTime_ = fix_time_index(times_.size(), chosen);
89  r.next_random();
90  } else if(random_tod_.to_bool(false)) {
92  }
93 
94  random_tod_ = false;
95 }
96 
98 {
99  config cfg;
100  cfg["turn_at"] = turn_;
101  cfg["turns"] = num_turns_;
102 
103  // this 'if' is for the editor.
104  if(times_.size() != 0) {
105  cfg["current_time"] = currentTime_;
106  }
107 
108  cfg["random_start_time"] = random_tod_;
109  cfg["it_is_a_new_turn"] = !has_turn_event_fired_;
110 
112  cfg["liminal_bonus"] = liminal_bonus_;
113  }
114 
115  for(const time_of_day& tod : times_) {
116  tod.write(cfg.add_child("time"));
117  }
118 
119  for(const area_time_of_day& a_tod : areas_) {
120  config& area = cfg.add_child("time_area");
121 
122  // If no ranges, then use hexes to generate ranges
123  if(a_tod.xsrc.empty() && a_tod.ysrc.empty()) {
124  write_location_range(a_tod.hexes, area);
125  } else {
126  area["x"] = a_tod.xsrc;
127  area["y"] = a_tod.ysrc;
128  }
129 
130  for(const time_of_day& tod : a_tod.times) {
131  // Don't write the stub default ToD if it happens to be present.
132  if(tod.id != "nulltod") {
133  tod.write(area.add_child("time"));
134  }
135  }
136 
137  area["current_time"] = a_tod.currentTime;
138 
139  if(!a_tod.id.empty()) {
140  area["id"] = a_tod.id;
141  }
142  }
143 
144  return cfg;
145 }
146 
147 static const time_of_day& dummytime()
148 {
149  static time_of_day* pdummy = new time_of_day();
150  return *pdummy;
151 }
152 
154 {
156 }
157 
159 {
160  assert(index < static_cast<int>(areas_.size()));
161  return areas_[index].currentTime;
162 }
163 
165 {
166  if(loc != map_location::null_location()) {
167  for(auto i = areas_.rbegin(), i_end = areas_.rend();
168  i != i_end; ++i) {
169  if(i->hexes.find(loc) != i->hexes.end()) {
170  return i->currentTime;
171  }
172  }
173  }
174 
175  return currentTime_;
176 }
177 
178 const std::vector<time_of_day>& tod_manager::times(const map_location& loc) const
179 {
180  if(loc != map_location::null_location()) {
181  for(auto i = areas_.rbegin(), i_end = areas_.rend();
182  i != i_end; ++i) {
183  if(i->hexes.find(loc) != i->hexes.end() && !i->times.empty())
184  return i->times;
185  }
186  }
187 
188  return times_;
189 }
190 
191 const time_of_day& tod_manager::get_time_of_day(const map_location& loc, int n_turn) const
192 {
193  if(n_turn == 0) {
194  n_turn = turn_;
195  }
196 
197  if(loc != map_location::null_location()) {
198  for(auto i = areas_.rbegin(), i_end = areas_.rend();
199  i != i_end; ++i) {
200  if(i->hexes.find(loc) != i->hexes.end() && !i->times.empty())
201  return get_time_of_day_turn(i->times, n_turn, i->currentTime);
202  }
203  }
204 
205  return get_time_of_day_turn(times_, n_turn, currentTime_);
206 }
207 
209  const unit_map& units, const gamemap& map, const map_location& loc, int for_turn) const
210 {
211  // get ToD ignoring illumination
212  time_of_day tod = get_time_of_day(loc, for_turn);
213 
214  if(map.on_board_with_border(loc)) {
215  // Now add terrain illumination.
216  const int terrain_light = map.get_terrain_info(loc).light_bonus(tod.lawful_bonus);
217 
218  std::vector<int> mod_list;
219  std::vector<int> max_list;
220  std::vector<int> min_list;
221  int most_add = 0;
222  int most_sub = 0;
223 
224  // Find the "illuminates" effects from units that can affect loc.
225  std::array<map_location, 7> locs;
226  locs[0] = loc;
227  get_adjacent_tiles(loc, locs.data() + 1); // start at [1]
228 
229  for(std::size_t i = 0; i < locs.size(); ++i) {
230  const auto itor = units.find(locs[i]);
231  if(itor != units.end() && !itor->incapacitated()) {
232  unit_ability_list illum = itor->get_abilities("illuminates");
233  if(!illum.empty()) {
234  unit_abilities::effect illum_effect(illum, terrain_light, false);
235  const int unit_mod = illum_effect.get_composite_value();
236 
237  // Record this value.
238  mod_list.push_back(unit_mod);
239  max_list.push_back(illum.highest("max_value").first);
240  min_list.push_back(illum.lowest("min_value").first);
241 
242  if(unit_mod > most_add) {
243  most_add = unit_mod;
244  } else if(unit_mod < most_sub) {
245  most_sub = unit_mod;
246  }
247  }
248  }
249  }
250  const bool net_darker = most_add < -most_sub;
251 
252  // Apply each unit's effect, tracking the best result.
253  int best_result = terrain_light;
254  const int base_light = terrain_light + (net_darker ? most_add : most_sub);
255 
256  for(std::size_t i = 0; i != mod_list.size(); ++i) {
257  int result = bounded_add(base_light, mod_list[i], max_list[i], min_list[i]);
258 
259  if(net_darker && result < best_result) {
260  best_result = result;
261  } else if(!net_darker && result > best_result) {
262  best_result = result;
263  }
264  }
265 
266  // Update the object we will return.
267  tod.bonus_modified = best_result - tod.lawful_bonus;
268  tod.lawful_bonus = best_result;
269  }
270 
271  return tod;
272 }
273 
275 {
276  return !random_start_time.empty() && utils::string_bool(random_start_time, true);
277 }
278 
280 {
281  std::vector<time_of_day> new_scedule;
282  time_of_day::parse_times(time_cfg, new_scedule);
283  replace_schedule(new_scedule);
284 }
285 
286 void tod_manager::replace_schedule(const std::vector<time_of_day>& schedule)
287 {
288  if(times_.empty() || schedule.empty() || times_[currentTime_].lawful_bonus != schedule.front().lawful_bonus) {
289  has_tod_bonus_changed_ = true;
290  }
291 
292  times_ = schedule;
293  currentTime_ = 0;
294 }
295 
296 void tod_manager::replace_area_locations(int area_index, const std::set<map_location>& locs)
297 {
298  assert(area_index < static_cast<int>(areas_.size()));
299  areas_[area_index].hexes = locs;
300  has_tod_bonus_changed_ = true;
301 }
302 
303 void tod_manager::replace_local_schedule(const std::vector<time_of_day>& schedule, int area_index)
304 {
305  assert(area_index < static_cast<int>(areas_.size()));
306  area_time_of_day& area = areas_[area_index];
307 
308  if(area.times.empty() || schedule.empty()) {
309  // If one of those is empty then their 'previous' time of day might depend on other areas_,
310  // its better to just assume the illumination has changes than to do the explicit computation.
311  has_tod_bonus_changed_ = true;
312  } else if(area.times[area.currentTime].lawful_bonus != schedule.front().lawful_bonus) {
313  // the current illumination on these tiles has changes.
314  has_tod_bonus_changed_ = true;
315  }
316 
317  area.times = schedule;
318  area.currentTime = 0;
319 }
320 
321 void tod_manager::set_area_id(int area_index, const std::string& id)
322 {
323  assert(area_index < static_cast<int>(areas_.size()));
324  areas_[area_index].id = id;
325 }
326 
327 std::vector<std::string> tod_manager::get_area_ids() const
328 {
329  std::vector<std::string> areas;
330  for(const area_time_of_day& area : areas_) {
331  areas.push_back(area.id);
332  }
333 
334  return areas;
335 }
336 
337 const std::set<map_location>& tod_manager::get_area_by_id(const std::string& id) const
338 {
339  for(const area_time_of_day& area : areas_) {
340  if(area.id == id) {
341  return area.hexes;
342  }
343  }
344 
345  static const std::set<map_location> res;
346  return res;
347 }
348 
349 const std::set<map_location>& tod_manager::get_area_by_index(int index) const
350 {
351  return areas_[index].hexes;
352 }
353 
354 void tod_manager::add_time_area(const gamemap& map, const config& cfg)
355 {
356  areas_.emplace_back();
357  area_time_of_day& area = areas_.back();
358  area.id = cfg["id"].str();
359  area.xsrc = cfg["x"].str();
360  area.ysrc = cfg["y"].str();
361  area.currentTime = cfg["current_time"].to_int(0);
362  const std::vector<map_location>& locs(map.parse_location_range(area.xsrc, area.ysrc, true));
363  area.hexes.insert(locs.begin(), locs.end());
364  time_of_day::parse_times(cfg, area.times);
365  has_tod_bonus_changed_ = true;
366 }
367 
368 void tod_manager::add_time_area(const std::string& id, const std::set<map_location>& locs, const config& time_cfg)
369 {
370  areas_.emplace_back();
371  area_time_of_day& area = areas_.back();
372  area.id = id;
373  area.hexes = locs;
374  area.currentTime = time_cfg["current_time"].to_int(0);
375  time_of_day::parse_times(time_cfg, area.times);
376  has_tod_bonus_changed_ = true;
377 }
378 
379 void tod_manager::remove_time_area(const std::string& area_id)
380 {
381  if(area_id.empty()) {
382  areas_.clear();
383  } else {
384  // search for all time areas that match the id.
385  auto i = areas_.begin();
386  while(i != areas_.end()) {
387  if((*i).id == area_id) {
388  i = areas_.erase(i);
389  } else {
390  ++i;
391  }
392  }
393  }
394 
395  has_tod_bonus_changed_ = true;
396 }
397 
398 void tod_manager::remove_time_area(int area_index)
399 {
400  assert(area_index < static_cast<int>(areas_.size()));
401  areas_.erase(areas_.begin() + area_index);
402  has_tod_bonus_changed_ = true;
403 }
404 
406  const std::vector<time_of_day>& times, int nturn, const int current_time) const
407 {
408  if(times.empty()) {
409  return dummytime();
410  }
411 
412  const int time = calculate_time_index_at_turn(times.size(), nturn, current_time);
413  return times[time];
414 }
415 
416 void tod_manager::modify_turns(const std::string& mod)
417 {
418  num_turns_ = std::max<int>(utils::apply_modifier(num_turns_, mod, 0), -1);
419 }
420 
422 {
423  num_turns_ = std::max<int>(num, -1);
424 }
425 
427 {
428  if(resources::controller->current_team().is_local()) {
429  // The currently active side informs the mp server about the turn change.
430  // NOTE: The current implementation does not guarantee that the server gets informed
431  // about those changes in 100% of cases. But that is ok because the information is only
432  // used to display the turn limit in the lobby (as opposed to things that cause OOS).
434  "change_turns_wml", config {
435  "current", turn_,
436  "max", num_turns_,
437  },
438  });
439  }
440 }
441 
442 void tod_manager::modify_turns_by_wml(const std::string& mod)
443 {
444  modify_turns(mod);
446 }
447 
449 {
450  set_number_of_turns(num);
452 }
453 
454 void tod_manager::set_turn(const int num, game_data* vars, const bool increase_limit_if_needed)
455 {
456  has_tod_bonus_changed_ = false;
457  const int new_turn = std::max<int>(num, 1);
458  LOG_NG << "changing current turn number from " << turn_ << " to " << new_turn << '\n';
459 
460  // Correct ToD
461  set_new_current_times(new_turn);
462 
463  if(increase_limit_if_needed && (new_turn > num_turns_) && num_turns_ != -1) {
464  set_number_of_turns(new_turn);
465  }
466 
467  turn_ = new_turn;
468 
469  if(vars) {
470  vars->get_variable("turn_number") = new_turn;
471  }
472 }
473 
474 void tod_manager::set_turn_by_wml(const int num, game_data* vars, const bool increase_limit_if_needed)
475 {
476  set_turn(num, vars, increase_limit_if_needed);
478 }
479 
480 void tod_manager::set_new_current_times(const int new_current_turn_number)
481 {
482  set_current_time(calculate_time_index_at_turn(times_.size(), new_current_turn_number, currentTime_));
483 
484  for(area_time_of_day& area : areas_) {
485  set_current_time(calculate_time_index_at_turn(area.times.size(), new_current_turn_number, area.currentTime), area);
486  }
487 }
488 
489 int tod_manager::fix_time_index(int number_of_times, int time)
490 {
491  if(number_of_times == 0) {
492  return 0;
493  }
494 
495  return modulo(time, number_of_times);
496 }
497 
498 int tod_manager::calculate_time_index_at_turn(int number_of_times, int for_turn_number, int current_time) const
499 {
500  if(number_of_times == 0) {
501  return 0;
502  }
503 
504  return modulo(current_time + for_turn_number - turn_, number_of_times);
505 }
506 
508 {
509  time = fix_time_index(times_.size(), time);
510  if(!times_.empty() && times_[time].lawful_bonus != times_[currentTime_].lawful_bonus) {
511  has_tod_bonus_changed_ = true;
512  }
513 
514  currentTime_ = time;
515 }
516 
517 void tod_manager::set_current_time(int time, int area_index)
518 {
519  assert(area_index < static_cast<int>(areas_.size()));
520  set_current_time(time, areas_[area_index]);
521 }
522 
523 void tod_manager::set_current_time(int time, const std::string& area_id)
524 {
525  for(area_time_of_day& area : areas_) {
526  if(area.id == area_id) {
527  set_current_time(time, area);
528  }
529  }
530 }
531 
533 {
534  time = fix_time_index(area.times.size(), time);
535  if(area.times[time].lawful_bonus != area.times[area.currentTime].lawful_bonus) {
536  has_tod_bonus_changed_ = true;
537  }
538 
539  area.currentTime = time;
540 }
541 
543 {
544  set_turn(turn_ + 1, vars, false);
545  has_turn_event_fired_ = false;
546  return is_time_left();
547 }
548 
550 {
551  return num_turns_ == -1 || turn_ <= num_turns_;
552 }
553 
554 int tod_manager::calculate_best_liminal_bonus(const std::vector<time_of_day>& schedule) const
555 {
556  int fearless_chaotic = 0;
557  int fearless_lawful = 0;
558 
559  std::set<int> bonuses;
560  for(const auto& tod : schedule) {
561  fearless_chaotic += generic_combat_modifier(tod.lawful_bonus, UNIT_ALIGNMENT::CHAOTIC, true, 0);
562  fearless_lawful += generic_combat_modifier(tod.lawful_bonus, UNIT_ALIGNMENT::LAWFUL, true, 0);
563  bonuses.insert(std::abs(tod.lawful_bonus));
564  }
565 
566  int target = std::max(fearless_chaotic, fearless_lawful);
567  int delta = target;
568  int result = 0;
569 
570  for(int bonus : bonuses) {
571  int liminal_effect = 0;
572  for(const auto& tod : schedule) {
573  liminal_effect += generic_combat_modifier(tod.lawful_bonus, UNIT_ALIGNMENT::LIMINAL, false, bonus);
574  }
575 
576  if(std::abs(target - liminal_effect) < delta) {
577  result = bonus;
578  delta = std::abs(target - liminal_effect);
579  }
580  }
581 
582  return result;
583 }
play_controller * controller
Definition: resources.cpp:21
void set_new_current_times(const int new_current_turn_number)
For a change of the current turn number, sets the current times of the main time and all time areas...
int calculate_time_index_at_turn(int number_of_times, int for_turn_number, int current_time) const
Computes for the main time or a time area the index of its times where we&#39;re currently at...
void replace_local_schedule(const std::vector< time_of_day > &schedule, int area_index)
bool empty() const
Definition: unit.hpp:92
unit_iterator end()
Definition: map.hpp:428
bool has_turn_event_fired_
void get_adjacent_tiles(const map_location &a, map_location *res)
Function which, given a location, will place all adjacent locations in res.
Definition: location.cpp:474
void replace_schedule(const config &time_cfg)
Replace the time of day schedule.
const time_of_day & get_previous_time_of_day() const
Various functions that implement attacks and attack calculations.
bool has_attribute(config_key_type key) const
Definition: config.cpp:208
void set_turn(const int num, game_data *vars=nullptr, const bool increase_limit_if_needed=true)
Dynamically change the current turn number.
std::string id
Definition: time_of_day.hpp:89
int get_current_time(const map_location &loc=map_location::null_location()) const
void set_area_id(int area_index, const std::string &id)
bool has_tod_bonus_changed_
void resolve_random(randomness::rng &r)
handles random_start_time, should be called before the game starts.
Definition: tod_manager.cpp:68
int lawful_bonus
The % bonus lawful units receive.
Definition: time_of_day.hpp:82
void modify_turns_by_wml(const std::string &mod)
const terrain_type & get_terrain_info(const t_translation::terrain_code &terrain) const
Definition: map.cpp:96
std::set< map_location > hexes
int generic_combat_modifier(int lawful_bonus, unit_type::ALIGNMENT alignment, bool is_fearless, int max_liminal_bonus)
Returns the amount that a unit&#39;s damage should be multiplied by due to a given lawful_bonus.
Definition: attack.cpp:1615
void write(config &cfg) const
Definition: time_of_day.cpp:54
const std::set< map_location > & get_area_by_id(const std::string &id) const
int calculate_best_liminal_bonus(const std::vector< time_of_day > &schedule) const
Computes the maximum absolute value of lawful_bonus in the schedule.
config::attribute_value & get_variable(const std::string &varname)
throws invalid_variablename_exception if varname is no valid variable name.
Definition: game_data.cpp:62
void modify_turns(const std::string &mod)
static int fix_time_index(int number_of_times, int time)
Computes for the main time or a time area the index of its times where we&#39;re currently at...
Object which defines a time of day with associated bonuses, image, sounds etc.
Definition: time_of_day.hpp:55
void set_current_time(int time)
int light_bonus(int base) const
Returns the light (lawful) bonus for this terrain when the time of day gives a base bonus...
Definition: terrain.hpp:131
std::vector< map_location > parse_location_range(const std::string &xvals, const std::string &yvals, bool with_border=false) const
Parses ranges of locations into a vector of locations, using this map&#39;s dimensions as bounds...
Definition: map.cpp:421
static std::ostream & output()
Definition: log.cpp:52
void set_number_of_turns_by_wml(int num)
std::vector< time_of_day > times
bool on_board_with_border(const map_location &loc) const
Definition: map.cpp:387
const time_of_day & get_time_of_day(int for_turn=0) const
Returns global time of day for the passed turn.
Definition: tod_manager.hpp:54
config::attribute_value random_tod_
void remove_time_area(const std::string &id)
Removes a time area from config, making it follow the scenario&#39;s normal time-of-day sequence...
std::vector< time_of_day > times_
Encapsulates the map of the game.
Definition: map.hpp:33
tod_manager(const config &scenario_cfg=config())
Definition: tod_manager.cpp:38
config to_config() const
Definition: tod_manager.cpp:97
void update_server_information() const
std::vector< std::string > get_area_ids() const
void set_turn_by_wml(const int num, game_data *vars=nullptr, const bool increase_limit_if_needed=true)
Dynamically change the current turn number.
Encapsulates the map of the game.
Definition: location.hpp:37
std::pair< int, map_location > lowest(const std::string &key, int def=0) const
Definition: unit.hpp:74
unit_iterator find(std::size_t id)
Definition: map.cpp:309
const time_of_day get_illuminated_time_of_day(const unit_map &units, const gamemap &map, const map_location &loc, int for_turn=0) const
Returns time of day object for the passed turn at a location.
std::size_t i
Definition: function.cpp:933
void write_location_range(const std::set< map_location > &locs, config &cfg)
Write a set of locations into a config using ranges, adding keys x=x1,..,xn and y=y1a-y1b,..,yna-ynb.
Definition: location.cpp:398
void set_number_of_turns(int num)
const std::vector< time_of_day > & times(const map_location &loc=map_location::null_location()) const
static void parse_times(const config &cfg, std::vector< time_of_day > &normal_times)
Parse config and add time of day entries into passed vector.
Definition: time_of_day.cpp:70
static const time_of_day & dummytime()
int get_composite_value() const
Definition: abilities.hpp:46
bool string_bool(const std::string &str, bool def)
Convert no, false, off, 0, 0.0 to false, empty to def, and others to true.
bool is_time_left() const
Function to check the end of turns.
bool to_bool(bool def=false) const
#define LOG_NG
Definition: tod_manager.cpp:36
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:71
bool has_cfg_liminal_bonus_
static lg::log_domain log_engine("engine")
config & add_child(config_key_type key)
Definition: config.cpp:471
static bool is_start_ToD(const std::string &)
void replace_area_locations(int index, const std::set< map_location > &locs)
std::vector< std::string > split(const config_attribute_value &val)
void add_time_area(const gamemap &map, const config &cfg)
Adds a new local time area from config, making it follow its own time-of-day sequence.
int apply_modifier(const int number, const std::string &amount, const int minimum)
Standard logging facilities (interface).
static const map_location & null_location()
Definition: location.hpp:80
Container associating units to locations.
Definition: map.hpp:97
uint32_t next_random()
Provides the next random draw.
Definition: random.cpp:84
const std::set< map_location > & get_area_by_index(int index) const
std::vector< area_time_of_day > areas_
int bounded_add(int base, int increment, int max_sum, int min_sum=0)
Returns base + increment, but will not increase base above max_sum, nor decrease it below min_sum...
Definition: math.hpp:47
int get_current_area_time(int index) const
const time_of_day & get_time_of_day_turn(const std::vector< time_of_day > &times, int nturn, const int current_time) const
Returns time of day object in the turn "nturn".
bool next_turn(game_data *vars)
Function to move to the next turn.
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:59
bool random_start_time()
Definition: game.cpp:523
int bonus_modified
Definition: time_of_day.hpp:83
virtual void send_to_wesnothd(const config &, const std::string &="unknown") const
std::pair< int, map_location > highest(const std::string &key, int def=0) const
Definition: unit.hpp:70
T modulo(T num, int mod, T min=0)
Definition: math.hpp:61
std::string str(const std::string &fallback="") const
this class does not give synced random results derived classes might do.
Definition: random.hpp:27