The Battle for Wesnoth  1.13.11+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
synced_commands.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2018 by David White <dave@whitevine.net>
3  Part of the Battle for Wesnoth Project http://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 #include "synced_commands.hpp"
15 #include <cassert>
16 
17 #include "log.hpp"
18 #include "map/location.hpp"
19 #include "game_data.hpp"
20 #include "units/unit.hpp"
21 #include "team.hpp"
22 #include "play_controller.hpp"
23 #include "actions/create.hpp"
24 #include "actions/advancement.hpp"
25 #include "actions/attack.hpp"
26 #include "actions/move.hpp"
27 #include "actions/undo.hpp"
28 #include "preferences/general.hpp"
29 #include "preferences/game.hpp"
30 #include "game_events/pump.hpp"
31 #include "map/map.hpp"
32 #include "units/helper.hpp"
33 #include "recall_list_manager.hpp"
34 #include "resources.hpp"
36 #include "formula/string_utils.hpp"
37 #include "units/types.hpp"
38 #include "units/udisplay.hpp"
39 #include "whiteboard/manager.hpp"
40 #include "font/standard_colors.hpp"
41 
42 static lg::log_domain log_replay("replay");
43 #define DBG_REPLAY LOG_STREAM(debug, log_replay)
44 #define LOG_REPLAY LOG_STREAM(info, log_replay)
45 #define WRN_REPLAY LOG_STREAM(warn, log_replay)
46 #define ERR_REPLAY LOG_STREAM(err, log_replay)
47 
48 
49 /**
50  * @param[in] tag The replay tag for this action.
51  * @param[in] function The callback for this action.
52  */
53 synced_command::synced_command(const std::string & tag, handler function)
54 {
55  assert(registry().find( tag ) == registry().end());
56  registry()[tag] = function;
57 }
58 
60 {
61  //Use a pointer to ensure that this object is not destructed when the program ends.
62  static map* instance = new map();
63  return *instance;
64 }
65 
66 
67 SYNCED_COMMAND_HANDLER_FUNCTION(recruit, child, use_undo, show, error_handler)
68 {
69  int current_team_num = resources::controller->current_side();
70  team &current_team = resources::gameboard->get_team(current_team_num);
71 
73  map_location from(child.child_or_empty("from"), resources::gamedata);
74  // Validate "from".
75  if ( !from.valid() ) {
76  // This will be the case for AI recruits in replays saved
77  // before 1.11.2, so it is not more severe than a warning.
78  // EDIT: we broke compatibility with 1.11.2 anyway so we should give an error.
79  error_handler("Missing leader location for recruitment.\n", false);
80  }
81  else if ( resources::gameboard->units().find(from) == resources::gameboard->units().end() ) {
82  // Sync problem?
83  std::stringstream errbuf;
84  errbuf << "Recruiting leader not found at " << from << ".\n";
85  error_handler(errbuf.str(), false);
86  }
87 
88  // Get the unit_type ID.
89  std::string type_id = child["type"];
90  if ( type_id.empty() ) {
91  error_handler("Recruitment is missing a unit type.", true);
92  return false;
93  }
94 
95  const unit_type *u_type = unit_types.find(type_id);
96  if (!u_type) {
97  std::stringstream errbuf;
98  errbuf << "Recruiting illegal unit: '" << type_id << "'.\n";
99  error_handler(errbuf.str(), true);
100  return false;
101  }
102 
103  const std::string res = actions::find_recruit_location(current_team_num, loc, from, type_id);
104  if(!res.empty())
105  {
106  std::stringstream errbuf;
107  errbuf << "cannot recruit unit: " << res << "\n";
108  error_handler(errbuf.str(), true);
109  return false;
110  //we are already oos because the unit wasn't created, no need to keep the bookkeeping right...
111  }
112  const int beginning_gold = current_team.gold();
113 
114 
115 
116  if ( u_type->cost() > beginning_gold ) {
117  std::stringstream errbuf;
118  errbuf << "unit '" << type_id << "' is too expensive to recruit: "
119  << u_type->cost() << "/" << beginning_gold << "\n";
120  error_handler(errbuf.str(), false);
121  }
122 
123  actions::recruit_unit(*u_type, current_team_num, loc, from, show, use_undo);
124 
125  LOG_REPLAY << "recruit: team=" << current_team_num << " '" << type_id << "' at (" << loc
126  << ") cost=" << u_type->cost() << " from gold=" << beginning_gold << ' '
127  << "-> " << current_team.gold() << "\n";
128  return true;
129 }
130 
131 SYNCED_COMMAND_HANDLER_FUNCTION(recall, child, use_undo, show, error_handler)
132 {
133 
134  int current_team_num = resources::controller->current_side();
135  team &current_team = resources::gameboard->get_team(current_team_num);
136 
137  const std::string& unit_id = child["value"];
138  map_location loc(child, resources::gamedata);
139  map_location from(child.child_or_empty("from"), resources::gamedata);
140 
141  if ( !actions::recall_unit(unit_id, current_team, loc, from, map_location::NDIRECTIONS, show, use_undo) ) {
142  error_handler("illegal recall: unit_id '" + unit_id + "' could not be found within the recall list.\n", true);
143  //when recall_unit returned false nothing happened so we can safety return false;
144  return false;
145  }
146  return true;
147 }
148 
149 SYNCED_COMMAND_HANDLER_FUNCTION(attack, child, /*use_undo*/, show, error_handler)
150 {
151  const config &destination = child.child("destination");
152  const config &source = child.child("source");
153  //check_checksums(*cfg);
154 
155  if (!destination) {
156  error_handler("no destination found in attack\n", true);
157  return false;
158  }
159 
160  if (!source) {
161  error_handler("no source found in attack \n", true);
162  return false;
163  }
164 
165  //we must get locations by value instead of by references, because the iterators
166  //may become invalidated later
167  const map_location src(source, resources::gamedata);
168  const map_location dst(destination, resources::gamedata);
169 
170  int weapon_num = child["weapon"];
171  // having defender_weapon in the replay fixes a bug (OOS) where one player (or observer) chooses a different defensive weapon.
172  // Xan pointed out this was a possibility: we calculate defense weapon
173  // now based on attack_prediction code, but this uses floating point
174  // calculations, which means that in the case where results are close,
175  // rounding differences can mean that both ends choose different weapons.
176  int def_weapon_num = child["defender_weapon"].to_int(-2);
177  if (def_weapon_num == -2) {
178  // Let's not gratuitously destroy backwards compatibility.
179  LOG_REPLAY << "Old data, having to guess weapon\n";
180  def_weapon_num = -1;
181  }
182 
184  if (!u.valid()) {
185  error_handler("unfound location for source of attack\n", true);
186  return false;
187  }
188 
189  if (child.has_attribute("attacker_type")) {
190  const std::string &att_type_id = child["attacker_type"];
191  if (u->type_id() != att_type_id) {
192  WRN_REPLAY << "unexpected attacker type: " << att_type_id << "(game state gives: " << u->type_id() << ")" << std::endl;
193  }
194  }
195 
196  if (static_cast<unsigned>(weapon_num) >= u->attacks().size()) {
197  error_handler("illegal weapon type in attack\n", true);
198  return false;
199  }
200 
202 
203  if (!tgt.valid()) {
204  std::stringstream errbuf;
205  errbuf << "unfound defender for attack: " << src << " -> " << dst << '\n';
206  error_handler(errbuf.str(), true);
207  return false;
208  }
209 
210  if (child.has_attribute("defender_type")) {
211  const std::string &def_type_id = child["defender_type"];
212  if (tgt->type_id() != def_type_id) {
213  WRN_REPLAY << "unexpected defender type: " << def_type_id << "(game state gives: " << tgt->type_id() << ")" << std::endl;
214  }
215  }
216 
217  if (def_weapon_num >= static_cast<int>(tgt->attacks().size())) {
218 
219  error_handler("illegal defender weapon type in attack\n", true);
220  return false;
221  }
222 
223  DBG_REPLAY << "Attacker XP (before attack): " << u->experience() << "\n";
224 
226  attack_unit_and_advance(src, dst, weapon_num, def_weapon_num, show);
227  return true;
228 }
229 
230 SYNCED_COMMAND_HANDLER_FUNCTION(disband, child, /*use_undo*/, /*show*/, error_handler)
231 {
232 
233  int current_team_num = resources::controller->current_side();
234  team &current_team = resources::gameboard->get_team(current_team_num);
235 
236  const std::string& unit_id = child["value"];
237  size_t old_size = current_team.recall_list().size();
238 
239  // Find the unit in the recall list.
240  unit_ptr dismissed_unit = current_team.recall_list().find_if_matches_id(unit_id);
241  assert(dismissed_unit);
242  //add dismissal to the undo stack
243  resources::undo_stack->add_dismissal(dismissed_unit);
244 
245  current_team.recall_list().erase_if_matches_id(unit_id);
246 
247  if (old_size == current_team.recall_list().size()) {
248  error_handler("illegal disband\n", true);
249  return false;
250  }
251  return true;
252 }
253 
254 SYNCED_COMMAND_HANDLER_FUNCTION(move, child, use_undo, show, error_handler)
255 {
256  int current_team_num = resources::controller->current_side();
257  team &current_team = resources::gameboard->get_team(current_team_num);
258 
259  std::vector<map_location> steps;
260 
261  try {
262  read_locations(child,steps);
263  } catch (std::invalid_argument&) {
264  WRN_REPLAY << "Warning: Path data contained something which could not be parsed to a sequence of locations:" << "\n config = " << child.debug() << std::endl;
265  return false;
266  }
267 
268  if(steps.empty())
269  {
270  WRN_REPLAY << "Warning: Missing path data found in [move]" << std::endl;
271  return false;
272  }
273 
274  const map_location& src = steps.front();
275  const map_location& dst = steps.back();
276 
277  if (src == dst) {
278  WRN_REPLAY << "Warning: Move with identical source and destination. Skipping..." << std::endl;
279  return false;
280  }
281 
282  // The nominal destination should appear to be unoccupied.
284  if ( u.valid() ) {
285  WRN_REPLAY << "Warning: Move destination " << dst << " appears occupied." << std::endl;
286  // We'll still proceed with this movement, though, since
287  // an event might intervene.
288  // 'event' doesn't mean wml event but rather it means 'hidden' units form the movers point of view.
289  }
290 
291  u = resources::gameboard->units().find(src);
292  if (!u.valid()) {
293  std::stringstream errbuf;
294  errbuf << "unfound location for source of movement: "
295  << src << " -> " << dst << '\n';
296  error_handler(errbuf.str(), true);
297  return false;
298  }
299  bool skip_sighted = false;
300  bool skip_ally_sighted = false;
301  if(child["skip_sighted"] == "all")
302  {
303  skip_sighted = true;
304  }
305  else if(child["skip_sighted"] == "only_ally")
306  {
307  skip_ally_sighted = true;
308  }
309 
310  bool show_move = show;
311  if ( current_team.is_local_ai() || current_team.is_network_ai())
312  {
313  show_move = show_move && !preferences::skip_ai_moves();
314  }
315  actions::move_unit_from_replay(steps, use_undo ? resources::undo_stack : nullptr, skip_sighted, skip_ally_sighted, show_move);
316 
317  return true;
318 }
319 
320 SYNCED_COMMAND_HANDLER_FUNCTION(fire_event, child, use_undo, /*show*/, /*error_handler*/)
321 {
322  bool undoable = true;
323 
324  if(const config &last_select = child.child("last_select"))
325  {
326  //the select event cannot clear the undo stack.
328  }
329  const std::string &event_name = child["raise"];
330  if (const config &source = child.child("source")) {
331  undoable = undoable & !std::get<0>(resources::game_events->pump().fire(event_name, map_location(source, resources::gamedata)));
332  } else {
333  undoable = undoable & !std::get<0>(resources::game_events->pump().fire(event_name));
334  }
335 
336  // Not clearing the undo stack here causes OOS because we added an entry to the replay but no entry to the undo stack.
337  if(use_undo) {
338  if(!undoable) {
340  } else {
342  }
343  }
344  return true;
345 }
346 
347 SYNCED_COMMAND_HANDLER_FUNCTION(lua_ai, child, /*use_undo*/, /*show*/, /*error_handler*/)
348 {
349  const std::string &lua_code = child["code"];
350  assert(resources::lua_kernel);
351  resources::lua_kernel->run(lua_code.c_str());
352  return true;
353 }
354 
355 SYNCED_COMMAND_HANDLER_FUNCTION(auto_shroud, child, use_undo, /*show*/, /*error_handler*/)
356 {
357  assert(use_undo);
358  team &current_team = resources::controller->current_team();
359 
360  bool active = child["active"].to_bool();
361  // We cannot update shroud here like 'if(active) resources::undo_stack->commit_vision();'.
362  // because the undo.cpp code assumes exactly 1 entry in the undo stack per entry in the replay.
363  // And doing so would create a second entry in the undo stack for this 'auto_shroud' entry.
364  current_team.set_auto_shroud_updates(active);
366  return true;
367 }
368 
369 /** from resources::undo_stack->commit_vision(bool is_replay):
370  * Updates fog/shroud based on the undo stack, then updates stack as needed.
371  * Call this when "updating shroud now".
372  * This may fire events and change the game state.
373  * @param[in] is_replay Set to true when this is called during a replay.
374  *
375  * This means it is a synced command like any other.
376  */
377 
378 SYNCED_COMMAND_HANDLER_FUNCTION(update_shroud, /*child*/, use_undo, /*show*/, error_handler)
379 {
380  assert(use_undo);
381  team &current_team = resources::controller->current_team();
382  if(current_team.auto_shroud_updates()) {
383  error_handler("Team has DSU disabled but we found an explicit shroud update", false);
384  }
387  return true;
388 }
389 namespace
390 {
391  void debug_notification(const char* message)
392  {
393  utils::string_map symbols;
394  symbols["player"] = resources::controller->current_team().current_player();
395  display::announce_options announce_options;
396  announce_options.lifetime = 1000;
397  display::get_singleton()->announce(vgettext(message, symbols), font::NORMAL_COLOR, announce_options);
398  }
399 }
400 SYNCED_COMMAND_HANDLER_FUNCTION(debug_unit, child, use_undo, /*show*/, /*error_handler*/)
401 {
402  if(use_undo) {
404  }
405  debug_notification(":unit debug command was used during turn of $player");
406  map_location loc(child);
407  const std::string name = child["name"];
408  const std::string value = child["value"];
409 
411  if (i == resources::gameboard->units().end()) {
412  return false;
413  }
414  if (name == "advances" ) {
415  int int_value = std::stoi(value);
416  for (int levels=0; levels<int_value; levels++) {
417  i->set_experience(i->max_experience());
418 
419  advance_unit_at(advance_unit_params(loc).force_dialog(true));
420  i = resources::gameboard->units().find(loc);
421  if (!i.valid()) {
422  break;
423  }
424  }
425  } else if (name == "status" ) {
426  for (std::string status : utils::split(value)) {
427  bool add = true;
428  if (status.length() >= 1 && status[0] == '-') {
429  add = false;
430  status = status.substr(1);
431  }
432  if (status.empty()) {
433  continue;
434  }
435  i->set_state(status, add);
436  }
437  } else {
438  config cfg;
439  i->write(cfg);
440  cfg[name] = value;
441 
442  // Attempt to create a new unit. If there are error (such an invalid type key), exit.
443  try{
444  unit_ptr new_u(new unit(cfg, true));
445  new_u->set_location(loc);
446  // Don't remove the unit until after we've verified there are no errors in creating the new one,
447  // or else the unit would simply be removed from the map with no replacement.
449  resources::whiteboard->on_kill_unit();
451  } catch(unit_type::error& e) {
452  ERR_REPLAY << e.what() << std::endl; // TODO: more appropriate error message log
453  return false;
454  }
455  }
456  if (name == "fail") { //testcase for bug #18488
457  assert(i.valid());
458  }
461 
462  return true;
463 }
464 SYNCED_COMMAND_HANDLER_FUNCTION(debug_create_unit, child, use_undo, /*show*/, error_handler)
465 {
466  if(use_undo) {
468  }
469 
470  debug_notification("A unit was created using debug command during turn of $player");
471  map_location loc(child);
472  resources::whiteboard->on_kill_unit();
473  const unit_race::GENDER gender = string_gender(child["gender"], unit_race::NUM_GENDERS);
474  const unit_type *u_type = unit_types.find(child["type"]);
475  if (!u_type) {
476  error_handler("Invalid unit type", true);
477  return false;
478  }
479 
480  const int side_num = resources::controller
482 
483  // Create the unit.
484  unit_ptr created(new unit(*u_type, side_num, true, gender));
485  created->new_turn();
486 
487  unit_map::unit_iterator unit_it;
488 
489  // Add the unit to the board.
490  std::tie(unit_it, std::ignore) = resources::gameboard->units().replace(loc, created);
491 
493  resources::game_events->pump().fire("unit_placed", loc);
495 
496  // Village capture?
497  if ( resources::gameboard->map().is_village(loc) )
498  actions::get_village(loc, created->side());
499 
500  // Update fog/shroud.
501  // Not checking auto_shroud_updates() here since :create is not undoable. (#2196)
502  actions::shroud_clearer clearer;
503  clearer.clear_unit(loc, *created);
504  clearer.fire_events();
505  if (unit_it.valid() ) // In case sighted events messed with the unit.
506  actions::actor_sighted(*unit_it);
507 
508  return true;
509 }
510 
511 SYNCED_COMMAND_HANDLER_FUNCTION(debug_lua, child, use_undo, /*show*/, /*error_handler*/)
512 {
513  if(use_undo) {
515  }
516  debug_notification(":lua debug command was used during turn of $player");
517  resources::lua_kernel->run(child["code"].str().c_str());
519 
520  return true;
521 }
522 
523 SYNCED_COMMAND_HANDLER_FUNCTION(debug_kill, child, use_undo, /*show*/, /*error_handler*/)
524 {
525  if (use_undo) {
527  }
528  debug_notification("kill debug command was used during turn of $player");
529 
530  const map_location loc(child["x"].to_int(), child["y"].to_int(), wml_loc());
532  if (i != resources::gameboard->units().end()) {
533  const int dying_side = i->side();
534  resources::controller->pump().fire("last_breath", loc, loc);
535  if (i.valid()) {
536  unit_display::unit_die(loc, *i);
537  }
539  if (i.valid()) {
540  i->set_hitpoints(0);
541  }
542  resources::controller->pump().fire("die", loc, loc);
543  if (i.valid()) {
545  }
546  resources::whiteboard->on_kill_unit();
547  actions::recalculate_fog(dying_side);
548  }
549  return true;
550 }
551 
552 SYNCED_COMMAND_HANDLER_FUNCTION(debug_next_level, child, use_undo, /*show*/, /*error_handler*/)
553 {
554  if(use_undo) {
556  }
557 
558  debug_notification(":next_level debug command was used during turn of $player");
559 
560  std::string next_level = child["next_level"];
561  if (!next_level.empty())
562  resources::gamedata->set_next_scenario(next_level);
564  e.transient.carryover_report = false;
565  e.prescenario_save = true;
566  e.transient.linger_mode = false;
567  e.proceed_to_next_level = true;
568  e.is_victory = true;
569 
572 
573  return true;
574 }
575 
576 SYNCED_COMMAND_HANDLER_FUNCTION(debug_turn_limit, child, use_undo, /*show*/, /*error_handler*/)
577 {
578  if(use_undo) {
580  }
581 
582  debug_notification(":turn_limit debug command was used during turn of $player");
583 
584  resources::tod_manager->set_number_of_turns(child["turn_limit"].to_int(-1));
586  return true;
587 }
588 
589 SYNCED_COMMAND_HANDLER_FUNCTION(debug_turn, child, use_undo, /*show*/, /*error_handler*/)
590 {
591  if(use_undo) {
593  }
594 
595  debug_notification(":turn debug command was used during turn of $player");
596 
597  resources::tod_manager->set_turn(child["turn"].to_int(1), resources::gamedata);
598 
601 
602  return true;
603 }
604 
605 SYNCED_COMMAND_HANDLER_FUNCTION(debug_set_var, child, use_undo, /*show*/, /*error_handler*/)
606 {
607  if(use_undo) {
609  }
610 
611  debug_notification(":set_var debug command was used during turn of $player");
612 
613  try {
614  resources::gamedata->set_variable(child["name"],child["value"]);
615  }
616  catch(const invalid_variablename_exception&) {
617  // command_failed(_("Variable not found"));
618  return false;
619  }
620  return true;
621 }
622 
623 SYNCED_COMMAND_HANDLER_FUNCTION(debug_gold, child, use_undo, /*show*/, /*error_handler*/)
624 {
625  if(use_undo) {
627  }
628 
629  debug_notification(":gold debug command was used during turn of $player");
630 
631  resources::controller->current_team().spend_gold(-child["gold"].to_int(0));
633  return true;
634 }
635 
636 
637 SYNCED_COMMAND_HANDLER_FUNCTION(debug_event, child, use_undo, /*show*/, /*error_handler*/)
638 {
639  if(use_undo) {
641  }
642 
643  debug_notification(":throw debug command was used during turn of $player");
644 
645  resources::controller->pump().fire(child["eventname"]);
647 
648  return true;
649 }
650 
651 
652 SYNCED_COMMAND_HANDLER_FUNCTION(debug_fog, /*child*/, use_undo, /*show*/, /*error_handler*/)
653 {
654  if(use_undo) {
656  }
657 
658  debug_notification(":fog debug command was used during turn of $player");
659 
660  team& current_team = resources::controller->current_team();
661  current_team.set_fog(!current_team.uses_fog());
662  actions::recalculate_fog(current_team.side());
663 
666 
667  return true;
668 }
669 
670 
671 SYNCED_COMMAND_HANDLER_FUNCTION(debug_shroud, /*child*/, use_undo, /*show*/, /*error_handler*/)
672 {
673  if(use_undo) {
675  }
676 
677  debug_notification(":shroud debug command was used during turn of $player");
678 
679  team& current_team = resources::controller->current_team();
680  current_team.set_shroud(!current_team.uses_shroud());
681  actions::clear_shroud(current_team.side());
682 
685 
686  return true;
687 }
688 
void clear()
Clears the stack of undoable (and redoable) actions.
Definition: undo.cpp:218
play_controller * controller
Definition: resources.cpp:21
bool uses_shroud() const
Definition: team.hpp:314
bool is_local_ai() const
Definition: team.hpp:265
bool recall_unit(const std::string &id, team &current_team, const map_location &loc, const map_location &from, map_location::DIRECTION facing, bool show, bool use_undo)
Recalls the unit with the indicated ID for the provided team.
Definition: create.cpp:740
void read_locations(const config &cfg, std::vector< map_location > &locs)
Parse x,y keys of a config into a vector of locations.
Definition: location.cpp:446
bool fire_event(const ui_event event, std::vector< std::pair< widget *, ui_event >> &event_chain, widget *dispatcher, widget *w, F &&...params)
Helper function for fire_event.
config & child(config_key_type key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
Definition: config.cpp:417
::tod_manager * tod_manager
Definition: resources.cpp:29
void set_shroud(bool shroud)
Definition: team.hpp:322
#define ERR_REPLAY
const char * what() const NOEXCEPT
Definition: exceptions.hpp:37
std::vector< char_t > string
const std::string & current_player() const
Definition: team.hpp:232
static display * get_singleton()
Returns the display object if a display object exists.
Definition: display.hpp:87
std::map< std::string, t_string > string_map
virtual const unit_map & units() const override
Definition: game_board.hpp:114
bool invalidate(const map_location &loc)
Function to invalidate a specific tile for redrawing.
Definition: display.cpp:3020
This class represents a single unit of a specific type.
Definition: unit.hpp:100
bool clear_unit(const map_location &view_loc, team &view_team, size_t viewer_id, int sight_range, bool slowed, const movetype::terrain_costs &costs, const map_location &real_loc, const std::set< map_location > *known_units=nullptr, size_t *enemy_count=nullptr, size_t *friend_count=nullptr, move_unit_spectator *spectator=nullptr, bool instant=true)
Clears shroud (and fog) around the provided location for view_team based on sight_range, costs, and slowed.
Definition: vision.cpp:330
umap_retval_pair_t insert(unit_ptr p)
Inserts the unit pointed to by p into the map.
Definition: map.cpp:135
Various functions that implement attacks and attack calculations.
size_t size() const
Get the number of units on the list.
void set_turn(const int num, game_data *vars=nullptr, const bool increase_limit_if_needed=true)
Dynamically change the current turn number.
static map & registry()
using static function variable instead of static member variable to prevent static initialization fia...
game_events::wml_event_pump & pump()
void redraw_everything()
Invalidates entire screen, including all tiles and sidebar.
Definition: display.cpp:2412
void invalidate_unit()
Function to invalidate that unit status displayed on the sidebar.
synced_command(const std::string &tag, handler function)
unit_type_data unit_types
Definition: types.cpp:1453
std::map< std::string, handler > map
bool prescenario_save
Should a prescenario be created the next game?
#define WRN_REPLAY
-file sdl_utils.hpp
void redraw_minimap()
Schedule the minimap to be redrawn.
Definition: display.hpp:618
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.
void new_turn()
Update lighting settings.
std::vector< std::pair< const std::string *, const stats * > > levels
Stats (and name) for each scenario. The pointers are never nullptr.
Definition: statistics.hpp:114
A single unit type that the player may recruit.
Definition: types.hpp:42
game_data * gamedata
Definition: resources.cpp:22
umap_retval_pair_t replace(const map_location &l, unit_ptr p)
Works like unit_map::add; but l is emptied first, if needed.
Definition: map.cpp:225
This class stores all the data for a single 'side' (in game nomenclature).
Definition: team.hpp:44
void recruit_unit(const unit_type &u_type, int side_num, const map_location &loc, const map_location &from, bool show, bool use_undo)
Recruits a unit of the given type for the given side.
Definition: create.cpp:708
team & get_team(int i)
Definition: game_board.hpp:104
Various functions that implement advancements of units.
bool linger_mode
Should linger mode be invoked?
bool auto_shroud_updates() const
Definition: team.hpp:334
unit_ptr find_if_matches_id(const std::string &unit_id)
Find a unit by id. Null pointer if not found.
int current_side() const
Returns the number of the side whose turn it is.
#define LOG_REPLAY
void recalculate_minimap()
Schedule the minimap for recalculation.
Definition: display.hpp:612
game_board * gameboard
Definition: resources.cpp:20
void unit_die(const map_location &loc, unit &loser, const_attack_ptr attack, const_attack_ptr secondary_attack, const map_location &winner_loc, unit *winner)
Show a unit fading out.
Definition: udisplay.cpp:543
unit_race::GENDER string_gender(const std::string &str, unit_race::GENDER def)
Definition: race.cpp:141
void recalculate_fog(int side)
Function that recalculates the fog of war.
Definition: vision.cpp:705
void set_variable(const std::string &varname, const t_string &value)
does nothing if varname is no valid variable name.
Definition: game_data.cpp:84
void flush_messages()
Flushes WML messages and errors.
Definition: pump.cpp:621
void spend_gold(const int amount)
Definition: team.hpp:207
bool carryover_report
Should a summary of the scenario outcome be displayed?
void commit_vision()
Updates fog/shroud based on the undo stack, then updates stack as needed.
Definition: undo.cpp:241
#define DBG_REPLAY
void set_fog(bool fog)
Definition: team.hpp:323
game_events::manager * game_events
Definition: resources.cpp:24
SYNCED_COMMAND_HANDLER_FUNCTION(recruit, child, use_undo, show, error_handler)
void erase_if_matches_id(const std::string &unit_id)
Erase any unit with this id.
advances the unit at loc if it has enough experience, maximum 20 times.
Definition: advancement.hpp:40
const color_t NORMAL_COLOR
virtual void force_end_turn()=0
int cost() const
Definition: types.hpp:158
Encapsulates the map of the game.
Definition: location.hpp:42
Various functions related to moving units.
void run(char const *prog, int nArgs=0)
Runs a plain script.
std::shared_ptr< wb::manager > whiteboard
Definition: resources.cpp:33
Various functions related to the creation of units (recruits, recalls, and placed units)...
void set_end_level_data(const end_level_data &data)
void add_dismissal(const unit_const_ptr u)
Adds a dismissal to the undo stack.
Definition: undo.cpp:163
transient_end_level transient
size_t move_unit_from_replay(const std::vector< map_location > &steps, undo_list *undo_stack, bool continued_move, bool skip_ally_sighted, bool show_move)
Moves a unit across the board.
Definition: move.cpp:1298
void set_number_of_turns(int num)
void announce(const std::string &msg, const color_t &color=font::GOOD_COLOR, const announce_options &options=announce_options())
Announce a message prominently.
Definition: display.cpp:1786
Holds options for calls to function 'announce' (announce).
Definition: display.hpp:584
Define the game's event mechanism.
size_t i
Definition: function.cpp:933
bool proceed_to_next_level
whether to proceed to the next scenario, equals is_victory in sp.
Additional information on the game outcome which can be provided by WML.
int side() const
Definition: team.hpp:187
void advance_unit_at(const advance_unit_params &params)
pump_result_t fire(const std::string &event, const entity_location &loc1=entity_location::null_entity, const entity_location &loc2=entity_location::null_entity, const config &data=config())
Function to fire an event.
Definition: pump.cpp:491
std::string vgettext(const char *msgid, const utils::string_map &symbols)
size_t erase(const map_location &l)
Erases the unit at location l, if any.
Definition: map.cpp:298
bool clear_shroud(int side, bool reset_fog, bool fire_events)
Function that will clear shroud (and fog) based on current unit positions.
Definition: vision.cpp:754
void add_update_shroud()
Adds a shroud update to the undo stack.
Definition: undo.cpp:203
int gold() const
Definition: team.hpp:188
game_events::pump_result_t get_village(const map_location &loc, int side, bool *action_timebonus, bool fire_event)
Makes it so the village at the given location is owned by the given side.
Definition: move.cpp:139
boost::intrusive_ptr< unit > unit_ptr
Definition: ptr.hpp:29
int lifetime
Lifetime measured in frames.
Definition: display.hpp:587
bool find(E event, F functor)
Tests whether an event handler is available.
bool uses_fog() const
Definition: team.hpp:315
void unit_recruited(const map_location &loc, const map_location &leader_loc)
Definition: udisplay.cpp:698
Various functions that implement the undoing (and redoing) of in-game commands.
std::string find_recruit_location(const int side, map_location &recruit_location, map_location &recruited_from, const std::string &unit_type)
Finds a location on which to place a unit.
Definition: create.cpp:464
Standard logging facilities (interface).
bool is_network_ai() const
Definition: team.hpp:267
void add_dummy()
Adds an auto-shroud toggle to the undo stack.
Definition: undo.cpp:152
recall_list_manager & recall_list()
Definition: team.hpp:214
game_lua_kernel * lua_kernel
Definition: resources.cpp:25
static const char * name(const std::vector< SDL_Joystick * > &joysticks, const size_t index)
Definition: joystick.cpp:48
Class to encapsulate fog/shroud clearing and the resultant sighted events.
Definition: vision.hpp:57
const unit_type * find(const std::string &key, unit_type::BUILD_STATUS status=unit_type::FULL) const
Finds a unit_type by its id() and makes sure it is built to the specified level.
Definition: types.cpp:1276
void set_auto_shroud_updates(bool value)
Definition: team.hpp:335
#define e
void add_auto_shroud(bool turned_on)
Adds an auto-shroud toggle to the undo stack.
Definition: undo.cpp:144
actions::undo_list * undo_stack
Definition: resources.cpp:32
game_events::wml_event_pump & pump()
Definition: manager.cpp:185
static lg::log_domain log_replay("replay")
unit_iterator find(size_t id)
Definition: map.cpp:311
bool valid() const
Definition: map.hpp:276
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:93
unit_map::iterator find_visible_unit(const map_location &loc, const team &current_team, bool see_all=false)
Definition: game_board.cpp:168
Display units performing various actions: moving, attacking, and dying.
bool skip_ai_moves()
Definition: game.cpp:750
void attack_unit_and_advance(const map_location &attacker, const map_location &defender, int attack_with, int defend_with, bool update_display, const ai::unit_advancements_aspect &ai_advancement)
Performs an attack, and advanced the units afterwards.
Definition: attack.cpp:1556
game_events::pump_result_t actor_sighted(const unit &target, const std::vector< int > *cache)
Fires sighted events for the sides that can see target.
Definition: vision.cpp:622
static game_display * get_singleton()
void show(const std::string &window_id, const t_string &message, const point &mouse, const SDL_Rect &source_rect)
Shows a tip.
Definition: tooltip.cpp:154