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