The Battle for Wesnoth  1.15.3+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 "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 "units/unit.hpp"
26 #include "units/abilities.hpp"
27 #include "resources.hpp"
28 
29 #include <algorithm>
30 #include <iterator>
31 #include "utils/functional.hpp"
32 #include "actions/attack.hpp"
33 
34 static lg::log_domain log_engine("engine");
35 #define LOG_NG LOG_STREAM(info, log_engine)
36 
37 tod_manager::tod_manager(const config& scenario_cfg):
38  currentTime_(0),
39  times_(),
40  areas_(),
41  liminal_bonus_(25),
42  turn_(scenario_cfg["turn_at"].to_int(1)),
43  num_turns_(scenario_cfg["turns"].to_int(-1)),
44  has_turn_event_fired_(!scenario_cfg["it_is_a_new_turn"].to_bool(true)),
45  has_tod_bonus_changed_ (false),
46  has_cfg_liminal_bonus_ (false)
47 {
48  // ? : operator doesn't work in this case.
49  if (scenario_cfg["current_time"].to_int(-17403) == -17403)
50  random_tod_ = scenario_cfg["random_start_time"];
51  else
52  random_tod_ = false;
53 
54  time_of_day::parse_times(scenario_cfg,times_);
56  if (scenario_cfg.has_attribute("liminal_bonus")) {
57  liminal_bonus_ = scenario_cfg["liminal_bonus"].to_int(liminal_bonus_);
59  }
60  //We need to call parse_times before fix_time_index because otherwise the first parameter will always be 0.
61  currentTime_ = fix_time_index(times_.size(), scenario_cfg["current_time"].to_int(0));
62 
63 }
64 
66 {
67  //process the random_start_time string, which can be boolean yes/no true/false or a
68  //comma-separated string of integers >= 1 referring to the times_ array indices
69  std::vector<std::string> output_strings = utils::split(random_tod_.str());
70  std::vector<int> output;
71 
72  try
73  {
74  std::transform(output_strings.begin(), output_strings.end(), std::back_inserter(output),
75  [](const std::string& str)
76  {
77  return std::stoi(str);
78  });
79  }
80  catch (const std::invalid_argument&)
81  {
82  // This happens if the random_start_time string is a boolean.
83  // Simply ignore the exception.
84  }
85 
86  // Remove non-positive times
87  output.erase(
88  std::remove_if(
89  output.begin(),
90  output.end(),
91  [](int time){ return time <= 0; }),
92  output.end());
93 
94  if(!output.empty())
95  {
96  int chosen = output[r.next_random() % output.size()];
97  currentTime_ = fix_time_index(times_.size(), chosen);
98  r.next_random();
99  }
100  else if (random_tod_.to_bool(false))
101  {
103  }
104  random_tod_ = false;
105 }
107 {
108  config cfg;
109  cfg["turn_at"] = turn_;
110  cfg["turns"] = num_turns_;
111  cfg["current_time"] = currentTime_;
112  cfg["random_start_time"] = random_tod_;
113  cfg["it_is_a_new_turn"] = !has_turn_event_fired_;
115  cfg["liminal_bonus"] = liminal_bonus_;
116 
117  for(const time_of_day& tod : times_) {
118  tod.write(cfg.add_child("time"));
119  }
120 
121  for(const area_time_of_day& a_tod : areas_) {
122  config& area = cfg.add_child("time_area");
123 
124  // If no ranges, then use hexes to generate ranges
125  if(a_tod.xsrc.empty() && a_tod.ysrc.empty()) {
126  write_location_range(a_tod.hexes, area);
127  } else {
128  area["x"] = a_tod.xsrc;
129  area["y"] = a_tod.ysrc;
130  }
131 
132  for(const time_of_day& tod : a_tod.times) {
133  // Don't write the stub default ToD if it happens to be present.
134  if(tod.id != "nulltod") {
135  tod.write(area.add_child("time"));
136  }
137  }
138 
139  area["current_time"] = a_tod.currentTime;
140 
141  if(!a_tod.id.empty()) {
142  area["id"] = a_tod.id;
143  }
144  }
145 
146  return cfg;
147 }
148 
149 static const time_of_day& dummytime()
150 {
151  static time_of_day* pdummy = new time_of_day();
152  return *pdummy;
153 }
154 
156 {
158 }
159 
161 {
162  assert(index < static_cast<int>(areas_.size()) );
163  return areas_[index].currentTime;
164 }
165 
167 {
168  if ( loc != map_location::null_location() ) {
169  for ( std::vector<area_time_of_day>::const_reverse_iterator
170  i = areas_.rbegin(), i_end = areas_.rend(); i != i_end; ++i )
171  {
172  if (i->hexes.find(loc) != i->hexes.end())
173  return i->currentTime;
174  }
175  }
176 
177  return currentTime_;
178 }
179 
180 const std::vector<time_of_day>& tod_manager::times(const map_location& loc) const
181 {
182  if ( loc != map_location::null_location() ) {
183  for ( std::vector<area_time_of_day>::const_reverse_iterator
184  i = areas_.rbegin(), i_end = areas_.rend(); i != i_end; ++i )
185  {
186  if (i->hexes.find(loc) != i->hexes.end() && !i->times.empty())
187  return i->times;
188  }
189  }
190 
191  return times_;
192 }
193 
194 const time_of_day& tod_manager::get_time_of_day(const map_location& loc, int n_turn) const
195 {
196  if(n_turn == 0)
197  n_turn = turn_;
198 
199  if ( loc != map_location::null_location() )
200  {
201  for ( std::vector<area_time_of_day>::const_reverse_iterator
202  i = areas_.rbegin(), i_end = areas_.rend(); i != i_end; ++i )
203  {
204  if (i->hexes.find(loc) != i->hexes.end() && !i->times.empty())
205  return get_time_of_day_turn(i->times, n_turn, i->currentTime);
206  }
207  }
208 
209  return get_time_of_day_turn(times_, n_turn, currentTime_);
210 }
211 
212 const time_of_day tod_manager::get_illuminated_time_of_day(const unit_map & units, const gamemap & map, const map_location& loc, int for_turn) const
213 {
214  // get ToD ignoring illumination
215  time_of_day tod = get_time_of_day(loc, for_turn);
216 
217  if ( map.on_board_with_border(loc) )
218  {
219  // Now add terrain illumination.
220  const int terrain_light = map.get_terrain_info(loc).light_bonus(tod.lawful_bonus);
221 
222  std::vector<int> mod_list;
223  std::vector<int> max_list;
224  std::vector<int> min_list;
225  int most_add = 0;
226  int most_sub = 0;
227 
228  // Find the "illuminates" effects from units that can affect loc.
229  std::array<map_location, 7> locs;
230  locs[0] = loc;
231  get_adjacent_tiles(loc, locs.data() + 1); // start at [1]
232  for ( std::size_t i = 0; i < locs.size(); ++i ) {
233  const unit_map::const_iterator itor = units.find(locs[i]);
234  if (itor != units.end() && !itor->incapacitated())
235  {
236  unit_ability_list illum = itor->get_abilities("illuminates");
237  if(!illum.empty()) {
238  unit_abilities::effect illum_effect(illum, terrain_light, false);
239  const int unit_mod = illum_effect.get_composite_value();
240 
241  // Record this value.
242  mod_list.push_back(unit_mod);
243  max_list.push_back(illum.highest("max_value").first);
244  min_list.push_back(illum.lowest("min_value").first);
245  if ( unit_mod > most_add )
246  most_add = unit_mod;
247  else if ( unit_mod < most_sub )
248  most_sub = unit_mod;
249  }
250  }
251  }
252  const bool net_darker = most_add < -most_sub;
253 
254  // Apply each unit's effect, tracking the best result.
255  int best_result = terrain_light;
256  const int base_light = terrain_light + (net_darker ? most_add : most_sub);
257  for ( std::size_t i = 0; i != mod_list.size(); ++i ) {
258  int result = bounded_add( base_light, mod_list[i], max_list[i], min_list[i] );
259 
260  if ( net_darker && result < best_result )
261  best_result = result;
262  else if ( !net_darker && result > best_result )
263  best_result = result;
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 
274 
276 {
277  return !random_start_time.empty()
278  && utils::string_bool(random_start_time, true);
279 }
280 
282 {
283  std::vector<time_of_day> new_scedule;
284  time_of_day::parse_times(time_cfg, new_scedule);
285  replace_schedule(new_scedule);
286 }
287 
288 void tod_manager::replace_schedule(const std::vector<time_of_day>& schedule)
289 {
290  if(times_.empty() || schedule.empty() || times_[currentTime_].lawful_bonus != schedule.front().lawful_bonus) {
291  has_tod_bonus_changed_ = true;
292  }
293 
294  times_ = schedule;
295  currentTime_ = 0;
296 }
297 
298 void tod_manager::replace_area_locations(int area_index, const std::set<map_location>& locs)
299 {
300  assert(area_index < static_cast<int>(areas_.size()));
301  areas_[area_index].hexes = locs;
302  has_tod_bonus_changed_ = true;
303 }
304 
305 void tod_manager::replace_local_schedule(const std::vector<time_of_day>& schedule, int area_index)
306 {
307  assert(area_index < static_cast<int>(areas_.size()));
308  area_time_of_day& area = areas_[area_index];
309 
310  if(area.times.empty() || schedule.empty())
311  {
312  //If one of those is empty then their 'prievious' time of day might depend on other areas_,
313  //its better to just assume the illimination has changes than to do the explicit computation.
314  has_tod_bonus_changed_ = true;
315  }
316  else if(area.times[area.currentTime].lawful_bonus != schedule.front().lawful_bonus)
317  {
318  // the current illimination on these tiles has changes.
319  has_tod_bonus_changed_ = true;
320  }
321  area.times = schedule;
322  area.currentTime = 0;
323 }
324 
325 void tod_manager::set_area_id(int area_index, const std::string& id)
326 {
327  assert(area_index < static_cast<int>(areas_.size()));
328  areas_[area_index].id = id;
329 }
330 
331 std::vector<std::string> tod_manager::get_area_ids() const
332 {
333  std::vector<std::string> areas;
334  for (const area_time_of_day& area : areas_) {
335  areas.push_back(area.id);
336  }
337  return areas;
338 }
339 
340 const std::set<map_location>& tod_manager::get_area_by_id(const std::string& id) const
341 {
342  for (const area_time_of_day& area : areas_) {
343  if (area.id == id) {
344  return area.hexes;
345  }
346  }
347  static const std::set<map_location> res;
348  return res;
349 }
350 
351 const std::set<map_location>& tod_manager::get_area_by_index(int index) const
352 {
353  return areas_[index].hexes;
354 }
355 
356 void tod_manager::add_time_area(const gamemap & map, const config& cfg)
357 {
358  areas_.emplace_back();
359  area_time_of_day &area = areas_.back();
360  area.id = cfg["id"].str();
361  area.xsrc = cfg["x"].str();
362  area.ysrc = cfg["y"].str();
363  area.currentTime = cfg["current_time"].to_int(0);
364  const std::vector<map_location>& locs (map.parse_location_range(area.xsrc, area.ysrc, true));
365  area.hexes.insert(locs.begin(), locs.end());
366  time_of_day::parse_times(cfg, area.times);
367  has_tod_bonus_changed_ = true;
368 }
369 
370 void tod_manager::add_time_area(const std::string& id, const std::set<map_location>& locs,
371  const config& time_cfg)
372 {
373  areas_.emplace_back();
374  area_time_of_day& area = areas_.back();
375  area.id = id;
376  area.hexes = locs;
377  area.currentTime = time_cfg["current_time"].to_int(0);
378  time_of_day::parse_times(time_cfg, area.times);
379  has_tod_bonus_changed_ = true;
380 }
381 
382 void tod_manager::remove_time_area(const std::string& area_id)
383 {
384  if(area_id.empty()) {
385  areas_.clear();
386  } else {
387  // search for all time areas that match the id.
389  while(i != areas_.end()) {
390  if((*i).id == area_id) {
391  i = areas_.erase(i);
392  } else {
393  ++i;
394  }
395  }
396  }
397  has_tod_bonus_changed_ = true;
398 }
399 
400 void tod_manager::remove_time_area(int area_index)
401 {
402  assert(area_index < static_cast<int>(areas_.size()));
403  areas_.erase(areas_.begin() + area_index);
404  has_tod_bonus_changed_ = true;
405 }
406 
407 const time_of_day& tod_manager::get_time_of_day_turn(const std::vector<time_of_day>& times, int nturn, const int current_time) const
408 {
409  if(times.empty()) {
410  return dummytime();
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 }
421 {
422  num_turns_ = std::max<int>(num, -1);
423 }
424 
426 {
427  if(resources::controller->current_team().is_local()) {
428  //the currently active side informs the mp server about the turn change.
429  //NOTE: The current implementation does not guarnateee that the server gets informed
430  // about those changes in 100% of cases. But that is ok because the information is only
431  // used to display the turn limit in the lobby (as opposed to things that cause OOS).
433  "change_turns_wml", config {
434  "current", turn_,
435  "max", num_turns_,
436  },
437  });
438  }
439 }
440 void tod_manager::modify_turns_by_wml(const std::string& mod)
441 {
442  modify_turns(mod);
444 }
446 {
447  set_number_of_turns(num);
449 }
450 
451 void tod_manager::set_turn(const int num, game_data* vars, const bool increase_limit_if_needed)
452 {
453  has_tod_bonus_changed_ = false;
454  const int new_turn = std::max<int>(num, 1);
455  LOG_NG << "changing current turn number from " << turn_ << " to " << new_turn << '\n';
456  // Correct ToD
457  set_new_current_times(new_turn);
458 
459  if(increase_limit_if_needed && (new_turn > num_turns_) && num_turns_ != -1) {
460  set_number_of_turns(new_turn);
461  }
462  turn_ = new_turn;
463  if (vars) {
464  vars->get_variable("turn_number") = new_turn;
465  }
466 }
467 
468 void tod_manager::set_turn_by_wml(const int num, game_data* vars, const bool increase_limit_if_needed)
469 {
470  set_turn(num, vars, increase_limit_if_needed);
472 }
473 
474 void tod_manager::set_new_current_times(const int new_current_turn_number)
475 {
476  set_current_time(calculate_time_index_at_turn(times_.size(), new_current_turn_number, currentTime_));
477  for (area_time_of_day& area : areas_) {
479  area.times.size(),
480  new_current_turn_number,
481  area.currentTime),
482  area);
483  }
484 }
485 
487  int number_of_times,
488  int time)
489 {
490  if (number_of_times == 0) return 0;
491  return modulo(time, number_of_times);
492 }
493 
495  int number_of_times,
496  int for_turn_number,
497  int current_time) const
498 {
499  if (number_of_times == 0) return 0;
500  return modulo(current_time + for_turn_number - turn_, number_of_times);
501 }
502 
504 {
505  time = fix_time_index(times_.size(), time);
506  if (!times_.empty() && times_[time].lawful_bonus != times_[currentTime_].lawful_bonus) {
507  has_tod_bonus_changed_ = true;
508  }
509  currentTime_ = time;
510 }
511 
512 void tod_manager::set_current_time(int time, int area_index)
513 {
514  assert(area_index < static_cast<int>(areas_.size()));
515  set_current_time(time, areas_[area_index]);
516 }
517 
518 void tod_manager::set_current_time(int time, const std::string& area_id)
519 {
520  for (area_time_of_day& area : areas_) {
521  if (area.id == area_id) {
522  set_current_time(time, area);
523  }
524  }
525 }
526 
528 {
529  time = fix_time_index(area.times.size(), time);
530  if (area.times[time].lawful_bonus != area.times[area.currentTime].lawful_bonus) {
531  has_tod_bonus_changed_ = true;
532  }
533  area.currentTime = time;
534 }
535 
537 {
538  set_turn(turn_ + 1, vars, false);
539  has_turn_event_fired_ = false;
540  return is_time_left();
541 }
542 
543 
545 {
546  return num_turns_ == -1 || turn_ <= num_turns_;
547 }
548 
549 int tod_manager::calculate_best_liminal_bonus(const std::vector<time_of_day>& schedule) const
550 {
551  int fearless_chaotic = 0;
552  int fearless_lawful = 0;
553  std::set<int> bonuses;
554  for (const auto& tod : schedule) {
555  fearless_chaotic += generic_combat_modifier(tod.lawful_bonus, unit_type::ALIGNMENT::CHAOTIC, true, 0);
556  fearless_lawful += generic_combat_modifier(tod.lawful_bonus, unit_type::ALIGNMENT::LAWFUL, true, 0);
557  bonuses.insert(std::abs(tod.lawful_bonus));
558  }
559  int target = std::max(fearless_chaotic, fearless_lawful);
560  int delta = target;
561  int result = 0;
562  for (int bonus : bonuses) {
563  int liminal_effect = 0;
564  for (const auto& tod : schedule) {
565  liminal_effect += generic_combat_modifier(tod.lawful_bonus, unit_type::ALIGNMENT::LIMINAL, false, bonus);
566  }
567  if (std::abs(target - liminal_effect) < delta) {
568  result = bonus;
569  delta = std::abs(target - liminal_effect);
570  }
571  }
572  return result;
573 }
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:97
unit_iterator end()
Definition: map.hpp:429
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:213
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:91
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:65
int lawful_bonus
The % bonus lawful units receive.
Definition: time_of_day.hpp:84
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:97
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:1591
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.
std::vector< std::string > split(const std::string &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
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:57
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:132
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:416
static std::ostream & output()
Definition: log.cpp:51
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:382
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:36
tod_manager(const config &scenario_cfg=config())
Definition: tod_manager.cpp:37
config to_config() const
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:42
std::pair< int, map_location > lowest(const std::string &key, int def=0) const
Definition: unit.hpp:79
unit_iterator find(std::size_t id)
Definition: map.cpp:311
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:48
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:35
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:476
static bool is_start_ToD(const std::string &)
void replace_area_locations(int index, const std::set< map_location > &locs)
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:85
Container associating units to locations.
Definition: map.hpp:99
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:68
bool random_start_time()
Definition: game.cpp:553
int bonus_modified
Definition: time_of_day.hpp:85
std::string::const_iterator iterator
Definition: tokenizer.hpp:24
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:75
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