The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
tod_manager.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2009 - 2025
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#include "utils/general.hpp"
30
31#include <algorithm>
32#include <iterator>
33
34static lg::log_domain log_engine("engine");
35#define LOG_NG LOG_STREAM(info, log_engine)
36
37tod_manager::tod_manager(const config& scenario_cfg)
38 : currentTime_(0)
39 , times_(time_of_day::parse_times(scenario_cfg))
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
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 utils::erase_if(output, [](int time) { return time <= 0; });
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
95config tod_manager::to_config(const 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
148static const time_of_day& dummytime()
149{
150 static time_of_day* pdummy = new time_of_day();
151 return *pdummy;
152}
153
158
160{
161 assert(index < static_cast<int>(areas_.size()));
162 return areas_[index].currentTime;
163}
164
166{
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 return currentTime_;
175}
176
177const std::vector<time_of_day>& tod_manager::times(const map_location& loc) const
178{
179 for(auto i = areas_.rbegin(), i_end = areas_.rend();
180 i != i_end; ++i) {
181 if(i->hexes.find(loc) != i->hexes.end() && !i->times.empty())
182 return i->times;
183 }
184
185 return times_;
186}
187
189{
190 if(n_turn == 0) {
191 n_turn = turn_;
192 }
193
195 for(auto i = areas_.rbegin(), i_end = areas_.rend();
196 i != i_end; ++i) {
197 if(i->hexes.find(loc) != i->hexes.end() && !i->times.empty())
198 return get_time_of_day_turn(i->times, n_turn, i->currentTime);
199 }
200 }
201
203}
204
205const time_of_day& tod_manager::get_area_time_of_day(int area_i, int n_turn) const
206{
207 assert(area_i < static_cast<int>(areas_.size()));
208 if(n_turn == 0) {
209 n_turn = turn_;
210 }
211 return get_time_of_day_turn(areas_[area_i].times, n_turn, areas_[area_i].currentTime);
212}
213
215 const unit_map& units, const gamemap& map, const map_location& loc, int for_turn) const
216{
217 // get ToD ignoring illumination
218 time_of_day tod = get_time_of_day(loc, for_turn);
219
220 if(map.on_board_with_border(loc)) {
221 // Now add terrain illumination.
222 const int terrain_light = map.get_terrain_info(loc).light_bonus(tod.lawful_bonus);
223
224 std::vector<int> mod_list;
225 std::vector<int> max_list;
226 std::vector<int> min_list;
227 int most_add = 0;
228 int most_sub = 0;
229
230 // Find the "illuminates" effects from units that can affect loc.
231 for(const unit& u : units) {
232 if(!u.incapacitated()) {
233 const map_location& u_loc = u.get_location();
234 std::size_t distance = distance_between(u_loc, loc);
235 active_ability_list illum = u.get_abilities("illuminates");
236 utils::erase_if(illum, [&](const active_ability& i) {
237 std::size_t radius = i.ability_cfg()["radius"] != "all_map" ? i.ability_cfg()["radius"].to_int(1) : INT_MAX;
238 return distance > radius;
239 });
240 if(!illum.empty()) {
241 unit_abilities::effect illum_effect(illum, terrain_light, nullptr, unit_abilities::EFFECT_WITHOUT_CLAMP_MIN_MAX);
242 const int unit_mod = illum_effect.get_composite_value();
243
244 // Record this value.
245 mod_list.push_back(unit_mod);
246 max_list.push_back(illum.highest("max_value").first);
247 min_list.push_back(illum.lowest("min_value").first);
248
249 if(unit_mod > most_add) {
250 most_add = unit_mod;
251 } else if(unit_mod < most_sub) {
252 most_sub = unit_mod;
253 }
254 }
255 }
256 }
257 const bool net_darker = most_add < -most_sub;
258
259 // Apply each unit's effect, tracking the best result.
260 int best_result = terrain_light;
261 const int base_light = terrain_light + (net_darker ? most_add : most_sub);
262
263 for(std::size_t i = 0; i != mod_list.size(); ++i) {
264 int result = bounded_add(base_light, mod_list[i], max_list[i], min_list[i]);
265
266 if(net_darker && result < best_result) {
267 best_result = result;
268 } else if(!net_darker && result > best_result) {
269 best_result = result;
270 }
271 }
272
273 // Update the object we will return.
274 tod.bonus_modified = best_result - tod.lawful_bonus;
275 tod.lawful_bonus = best_result;
276 }
277
278 return tod;
279}
280
281bool tod_manager::is_start_ToD(const std::string& random_start_time)
282{
283 return !random_start_time.empty() && utils::string_bool(random_start_time, true);
284}
285
287{
288 replace_schedule(time_of_day::parse_times(time_cfg), time_cfg["current_time"].to_int(0));
289}
290
291void tod_manager::replace_schedule(const std::vector<time_of_day>& schedule, int initial_time)
292{
293 initial_time = fix_time_index(schedule.size(), initial_time);
294 if(times_.empty() || schedule.empty() || times_[currentTime_].lawful_bonus != schedule[initial_time].lawful_bonus) {
296 }
297
298 times_ = schedule;
299 currentTime_ = initial_time;
300}
301
302void tod_manager::move_all_areas(int x_offset, int y_offset) {
303 for (auto& area : areas_) {
304 decltype(area.hexes) new_locs;
305 for (auto& loc : area.hexes) {
306 map_location new_loc{ loc.x - x_offset, loc.y - y_offset };
307 new_locs.insert(new_loc);
308 }
309 area.hexes = new_locs;
310 }
311}
312
313void tod_manager::replace_area_locations(int area_index, const std::set<map_location>& locs)
314{
315 assert(area_index < static_cast<int>(areas_.size()));
316 areas_[area_index].hexes = locs;
318}
319
320void tod_manager::replace_local_schedule(const std::vector<time_of_day>& schedule, int area_index, int initial_time)
321{
322 assert(area_index < static_cast<int>(areas_.size()));
323 area_time_of_day& area = areas_[area_index];
324
325 initial_time = fix_time_index(area.times.size(), initial_time);
326 if(area.times.empty() || schedule.empty()) {
327 // If one of those is empty then their 'previous' time of day might depend on other areas_,
328 // its better to just assume the illumination has changes than to do the explicit computation.
330 } else if(area.times[area.currentTime].lawful_bonus != schedule[initial_time].lawful_bonus) {
331 // the current illumination on these tiles has changes.
333 }
334
335 area.times = schedule;
336 area.currentTime = initial_time;
337}
338
339void tod_manager::set_area_id(int area_index, const std::string& id)
340{
341 assert(area_index < static_cast<int>(areas_.size()));
342 areas_[area_index].id = id;
343}
344
345const std::string& tod_manager::get_area_id(int area_index) const
346{
347 assert(area_index < static_cast<int>(areas_.size()));
348 return areas_[area_index].id;
349}
350
351std::vector<std::string> tod_manager::get_area_ids() const
352{
353 std::vector<std::string> areas;
354 for(const area_time_of_day& area : areas_) {
355 areas.push_back(area.id);
356 }
357
358 return areas;
359}
360
361const std::set<map_location>& tod_manager::get_area_by_id(const std::string& id) const
362{
363 for(const area_time_of_day& area : areas_) {
364 if(area.id == id) {
365 return area.hexes;
366 }
367 }
368
369 static const std::set<map_location> res;
370 return res;
371}
372
373const std::set<map_location>& tod_manager::get_area_by_index(int index) const
374{
375 return areas_[index].hexes;
376}
377
378std::pair<int, std::string> tod_manager::get_area_on_hex(const map_location& loc) const
379{
381 for(auto i = areas_.rbegin(), i_end = areas_.rend();
382 i != i_end; ++i) {
383 if(i->hexes.find(loc) != i->hexes.end() && !i->times.empty())
384 return {std::distance(areas_.rbegin(), i), i->id};
385 }
386 }
387
388 return {-1, ""};
389}
390
392{
393 areas_.emplace_back();
394 area_time_of_day& area = areas_.back();
395 area.id = cfg["id"].str();
396 area.xsrc = cfg["x"].str();
397 area.ysrc = cfg["y"].str();
398 const std::vector<map_location>& locs(map.parse_location_range(area.xsrc, area.ysrc, true));
399 area.hexes.insert(locs.begin(), locs.end());
401 area.currentTime = fix_time_index(area.times.size(), cfg["current_time"].to_int(0));
403}
404
405void tod_manager::add_time_area(const std::string& id, const std::set<map_location>& locs, const config& time_cfg)
406{
407 areas_.emplace_back();
408 area_time_of_day& area = areas_.back();
409 area.id = id;
410 area.hexes = locs;
411 area.times = time_of_day::parse_times(time_cfg);
412 area.currentTime = fix_time_index(area.times.size(), time_cfg["current_time"].to_int(0));
414}
415
416void tod_manager::remove_time_area(const std::string& area_id)
417{
418 if(area_id.empty()) {
419 areas_.clear();
420 } else {
421 // search for all time areas that match the id.
422 auto i = areas_.begin();
423 while(i != areas_.end()) {
424 if((*i).id == area_id) {
425 i = areas_.erase(i);
426 } else {
427 ++i;
428 }
429 }
430 }
431
433}
434
436{
437 assert(area_index < static_cast<int>(areas_.size()));
438 areas_.erase(areas_.begin() + area_index);
440}
441
443 const std::vector<time_of_day>& times, int nturn, const int current_time) const
444{
445 if(times.empty()) {
446 return dummytime();
447 }
448
449 const int time = calculate_time_index_at_turn(times.size(), nturn, current_time);
450 return times[time];
451}
452
453void tod_manager::modify_turns(const std::string& mod)
454{
455 num_turns_ = std::max<int>(utils::apply_modifier(num_turns_, mod, 0), -1);
456}
457
459{
460 num_turns_ = std::max<int>(num, -1);
461}
462
464{
465 if(resources::controller->current_team().is_local()) {
466 // The currently active side informs the mp server about the turn change.
467 // NOTE: The current implementation does not guarantee that the server gets informed
468 // about those changes in 100% of cases. But that is ok because the information is only
469 // used to display the turn limit in the lobby (as opposed to things that cause OOS).
471 "change_turns_wml", config {
472 "current", turn_,
473 "max", num_turns_,
474 },
475 });
476 }
477}
478
479void tod_manager::modify_turns_by_wml(const std::string& mod)
480{
481 modify_turns(mod);
483}
484
490
491void tod_manager::set_turn(const int num, game_data* vars, const bool increase_limit_if_needed)
492{
494 const int new_turn = std::max<int>(num, 1);
495 LOG_NG << "changing current turn number from " << turn_ << " to " << new_turn;
496
497 // Correct ToD
498 set_new_current_times(new_turn);
499
500 if(increase_limit_if_needed && (new_turn > num_turns_) && num_turns_ != -1) {
501 set_number_of_turns(new_turn);
502 }
503
504 turn_ = new_turn;
505
506 if(vars) {
507 vars->get_variable("turn_number") = new_turn;
508 }
509}
510
511void tod_manager::set_turn_by_wml(const int num, game_data* vars, const bool increase_limit_if_needed)
512{
513 set_turn(num, vars, increase_limit_if_needed);
515}
516
517void tod_manager::set_new_current_times(const int new_current_turn_number)
518{
519 set_current_time(calculate_time_index_at_turn(times_.size(), new_current_turn_number, currentTime_));
520
521 for(area_time_of_day& area : areas_) {
522 set_current_time(calculate_time_index_at_turn(area.times.size(), new_current_turn_number, area.currentTime), area);
523 }
524}
525
526int tod_manager::fix_time_index(int number_of_times, int time)
527{
528 if(number_of_times == 0) {
529 return 0;
530 }
531
532 return modulo(time, number_of_times);
533}
534
535int tod_manager::calculate_time_index_at_turn(int number_of_times, int for_turn_number, int current_time) const
536{
537 if(number_of_times == 0) {
538 return 0;
539 }
540
541 return modulo(current_time + for_turn_number - turn_, number_of_times);
542}
543
545{
546 time = fix_time_index(times_.size(), time);
547 if(!times_.empty() && times_[time].lawful_bonus != times_[currentTime_].lawful_bonus) {
549 }
550
551 currentTime_ = time;
552}
553
554void tod_manager::set_current_time(int time, int area_index)
555{
556 assert(area_index < static_cast<int>(areas_.size()));
557 set_current_time(time, areas_[area_index]);
558}
559
560void tod_manager::set_current_time(int time, const std::string& area_id)
561{
562 for(area_time_of_day& area : areas_) {
563 if(area.id == area_id) {
564 set_current_time(time, area);
565 }
566 }
567}
568
570{
571 time = fix_time_index(area.times.size(), time);
572 if(!area.times.empty() && area.times[time].lawful_bonus != area.times[area.currentTime].lawful_bonus) {
574 }
575
576 area.currentTime = time;
577}
578
580{
581 set_turn(turn_ + 1, vars, false);
582 has_turn_event_fired_ = false;
583 return is_time_left();
584}
585
587{
588 return num_turns_ == -1 || turn_ <= num_turns_;
589}
590
591int tod_manager::calculate_best_liminal_bonus(const std::vector<time_of_day>& schedule) const
592{
593 int fearless_chaotic = 0;
594 int fearless_lawful = 0;
595
596 std::set<int> bonuses;
597 for(const auto& tod : schedule) {
598 fearless_chaotic += generic_combat_modifier(tod.lawful_bonus, unit_alignments::type::chaotic, true, 0);
599 fearless_lawful += generic_combat_modifier(tod.lawful_bonus, unit_alignments::type::lawful, true, 0);
600 bonuses.insert(std::abs(tod.lawful_bonus));
601 }
602
603 int target = std::max(fearless_chaotic, fearless_lawful);
604 int delta = target;
605 int result = 0;
606
607 for(int bonus : bonuses) {
608 int liminal_effect = 0;
609 for(const auto& tod : schedule) {
610 liminal_effect += generic_combat_modifier(tod.lawful_bonus, unit_alignments::type::liminal, false, bonus);
611 }
612
613 if(std::abs(target - liminal_effect) < delta) {
614 result = bonus;
615 delta = std::abs(target - liminal_effect);
616 }
617 }
618
619 return result;
620}
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:1538
Various functions that implement attacks and attack calculations.
map_location loc
Definition move.cpp:172
#define LOG_NG
std::pair< int, map_location > lowest(const std::string &key, int def=0) const
std::pair< int, map_location > highest(const std::string &key, int def=0) const
bool empty() const
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:157
config & add_child(std::string_view key)
Definition config.cpp:436
bool has_attribute(std::string_view key) const
Definition config.cpp:157
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:396
bool on_board_with_border(const map_location &loc) const
Definition map.cpp:352
Encapsulates the map of the game.
Definition map.hpp:176
const terrain_type & get_terrain_info(const t_translation::terrain_code &terrain) const
Definition map.cpp:78
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:142
static bool is_start_ToD(const std::string &)
void update_server_information() const
const std::vector< time_of_day > & times() 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 std::string & get_area_id(int area_index) const
std::vector< std::string > get_area_ids() const
void move_all_areas(int x_offset, int y_offset)
Shift all hex locations for all time areas by the given x/y offsets.
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)
config to_config(const std::string &textdomain="") 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_
const time_of_day & get_time_of_day(int for_turn=0) const
Returns global time of day for the passed turn.
void set_number_of_turns(int num)
void set_number_of_turns_by_wml(int num)
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.
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 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())
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.
int get_current_time() const
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
Container associating units to locations.
Definition map.hpp:98
This class represents a single unit of a specific type.
Definition unit.hpp:39
const config * cfg
std::string id
Text to match against addon_info.tags()
Definition manager.cpp:199
std::size_t distance_between(const map_location &a, const map_location &b)
Function which gives the number of hexes between two tiles (i.e.
Definition location.cpp:584
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:436
static std::ostream & output()
Definition log.cpp:103
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:46
constexpr T modulo(T num, int mod, T min=0)
Definition math.hpp:60
play_controller * controller
Definition resources.cpp:21
@ EFFECT_WITHOUT_CLAMP_MIN_MAX
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.
void erase_if(Container &container, const Predicate &predicate)
Convenience wrapper for using std::remove_if on a container.
Definition general.hpp:108
int apply_modifier(const int number, const std::string &amount, const int minimum)
std::vector< std::string > split(const config_attribute_value &val)
Data typedef for active_ability_list.
Encapsulates the map of the game.
Definition location.hpp:46
static const map_location & null_location()
Definition location.hpp:103
Object which defines a time of day with associated bonuses, image, sounds etc.
static std::vector< time_of_day > parse_times(const config &cfg)
Parse config and into a vector of time of day entries.
int lawful_bonus
The % bonus lawful units receive.
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 i