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