The Battle for Wesnoth  1.15.0-dev
pump.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2018 by David White <dave@whitevine.net>
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 /**
16  * @file
17  * Handles the current state of WML-events. This includes raising and firing,
18  * as well as tracking the context for event firing.
19  */
20 
21 #include "game_events/pump.hpp"
23 #include "game_events/handlers.hpp"
24 
25 #include "display_chat_manager.hpp"
26 #include "game_config.hpp"
27 #include "gettext.hpp"
28 #include "log.hpp"
29 #include "play_controller.hpp"
30 #include "resources.hpp"
32 #include "side_filter.hpp"
33 #include "units/map.hpp"
34 #include "units/unit.hpp"
35 #include "variable.hpp"
36 #include "whiteboard/manager.hpp"
37 
38 #include <iomanip>
39 #include <iostream>
40 
41 static lg::log_domain log_engine("engine");
42 #define DBG_NG LOG_STREAM(debug, log_engine)
43 #define LOG_NG LOG_STREAM(info, log_engine)
44 #define ERR_NG LOG_STREAM(err, log_engine)
45 
46 static lg::log_domain log_wml("wml");
47 #define DBG_WML LOG_STREAM(debug, log_wml)
48 #define LOG_WML LOG_STREAM(info, log_wml)
49 #define WRN_WML LOG_STREAM(warn, log_wml)
50 #define ERR_WML LOG_STREAM(err, log_wml)
51 
52 static lg::log_domain log_event_handler("event_handler");
53 #define DBG_EH LOG_STREAM(debug, log_event_handler)
54 
55 // This file is in the game_events namespace.
56 namespace game_events
57 {
58 namespace context
59 {
60 /// State when processing a particular flight of events or commands.
61 struct state
62 {
66 
67  explicit state(bool s, bool m = true)
68  : undo_disabled(m)
69  , action_canceled(false)
70  , skip_messages(s)
71  {
72  }
73 };
74 
75 class scoped
76 {
77 public:
78  scoped(std::stack<context::state>& contexts, bool m = true);
79  ~scoped();
80 
81 private:
82  std::stack<context::state>& contexts_;
83 };
84 }
85 
86 struct pump_impl
87 {
88  std::vector<queued_event> events_queue;
89 
90  std::stringstream wml_messages_stream;
91 
92  std::stack<context::state> contexts_;
93 
94  unsigned instance_count;
95 
97 
99  : events_queue()
100  , wml_messages_stream()
101  , contexts_()
102  , instance_count(0)
103  , my_manager(&man)
104  {
105  contexts_.emplace(false);
106  }
107 };
108 
109 namespace
110 { // Types
111 class pump_manager
112 {
113 public:
114  pump_manager(pump_impl&);
115  ~pump_manager();
116 
117  /// Allows iteration through the queued events.
118  queued_event& next()
119  {
120  return queue_[pumped_count_++];
121  }
122  /// Indicates the iteration is over.
123  bool done() const
124  {
125  return pumped_count_ >= queue_.size();
126  }
127 
128  unsigned count() const
129  {
130  return impl_.instance_count;
131  }
132 
133 private:
134  pump_impl& impl_;
135  int x1_, x2_, y1_, y2_;
136 
137  /**
138  * Tracks the events to process.
139  * This isolates these events from any events that might be generated during the processing.
140  */
141  std::vector<queued_event> queue_;
142 
143  /** Tracks how many events have been processed. */
144  std::size_t pumped_count_;
145 };
146 } // end anonymous namespace (types)
147 
148 namespace
149 { // Support functions
150 
151 pump_manager::pump_manager(pump_impl& impl)
152  : impl_(impl)
153  , x1_(resources::gamedata->get_variable("x1"))
154  , x2_(resources::gamedata->get_variable("x2"))
155  , y1_(resources::gamedata->get_variable("y1"))
156  , y2_(resources::gamedata->get_variable("y2"))
157  , queue_()
158  , pumped_count_(0) // Filled later with a swap().
159 {
160  queue_.swap(impl_.events_queue);
161  ++impl_.instance_count;
162 }
163 
164 pump_manager::~pump_manager()
165 {
166  --impl_.instance_count;
167 
168  // Not sure what the correct thing to do is here. In princple,
169  // discarding all events (i.e. clearing events_queue) seems like
170  // the right thing to do in the face of an exception. However, the
171  // previous functionality preserved the queue, so for now we will
172  // restore it.
173  if(!done()) {
174  // The remaining events get inserted at the beginning of events_queue.
175  std::vector<queued_event> temp;
176  impl_.events_queue.swap(temp);
177  impl_.events_queue.insert(impl_.events_queue.end(), queue_.begin() + pumped_count_, queue_.end());
178  impl_.events_queue.insert(impl_.events_queue.end(), temp.begin(), temp.end());
179  }
180 
181  // Restore the old values of the game variables.
186 }
187 }
188 
189 /**
190  * Returns true iff the given event passes all its filters.
191  */
193 {
194  const unit_map& units = resources::gameboard->units();
195  unit_map::const_iterator unit1 = units.find(ev.loc1);
196  unit_map::const_iterator unit2 = units.find(ev.loc2);
197  vconfig filters(handler.get_config());
198 
199  for(const vconfig& condition : filters.get_children("filter_condition")) {
200  if(!conditional_passed(condition)) {
201  return false;
202  }
203  }
204 
205  for(const vconfig& f : filters.get_children("filter_side")) {
206  side_filter ssf(f, &resources::controller->gamestate());
208  return false;
209  }
210 
211  for(const vconfig& f : filters.get_children("filter")) {
212  if(!ev.loc1.matches_unit_filter(unit1, f)) {
213  return false;
214  }
215  }
216 
217  vconfig::child_list special_filters = filters.get_children("filter_attack");
218  bool special_matches = special_filters.empty();
219  if(!special_matches && unit1 != units.end()) {
220  const bool matches_unit = ev.loc1.matches_unit(unit1);
221  const config& attack = ev.data.child("first");
222  for(const vconfig& f : special_filters) {
223  if(f.empty()) {
224  special_matches = true;
225  } else if(!matches_unit) {
226  return false;
227  }
228 
229  special_matches = special_matches || matches_special_filter(attack, f);
230  }
231  }
232 
233  if(!special_matches) {
234  return false;
235  }
236 
237  for(const vconfig& f : filters.get_children("filter_second")) {
238  if(!ev.loc2.matches_unit_filter(unit2, f)) {
239  return false;
240  }
241  }
242 
243  special_filters = filters.get_children("filter_second_attack");
244  special_matches = special_filters.empty();
245  if(!special_matches && unit2 != units.end()) {
246  const bool matches_unit = ev.loc2.matches_unit(unit2);
247  const config& attack = ev.data.child("second");
248  for(const vconfig& f : special_filters) {
249  if(f.empty()) {
250  special_matches = true;
251  } else if(!matches_unit) {
252  return false;
253  }
254 
255  special_matches = special_matches || matches_special_filter(attack, f);
256  }
257  }
258 
259  if(!special_matches) {
260  return false;
261  }
262 
263  // All filters passed.
264  return true;
265 }
266 
267 /**
268  * Processes an event through a single event handler.
269  * This includes checking event filters, but not checking that the event
270  * name matches.
271  *
272  * @param[in,out] handler_p The handler to offer the event to.
273  * This may be reset during processing.
274  * @param[in] ev The event information.
275  */
277 {
278  DBG_EH << "processing event " << ev.name << " with id=" << ev.id << "\n";
279 
280  // We currently never pass a null pointer to this function, but to
281  // guard against future modifications:
282  if(!handler_p) {
283  return;
284  }
285 
286  unit_map& units = resources::gameboard->units();
287  scoped_xy_unit first_unit("unit", ev.loc1, units);
288  scoped_xy_unit second_unit("second_unit", ev.loc2, units);
289  scoped_weapon_info first_weapon("weapon", ev.data.child("first"));
290  scoped_weapon_info second_weapon("second_weapon", ev.data.child("second"));
291 
292  if(!filter_event(*handler_p, ev)) {
293  return;
294  }
295 
296  // The event hasn't been filtered out, so execute the handler.
297  context::scoped evc(impl_->contexts_);
298  assert(resources::lua_kernel != nullptr);
299  handler_p->handle_event(ev, *resources::lua_kernel);
300  // NOTE: handler_p may be null at this point!
301 
302  if(ev.name == "select") {
304  }
305 
306  if(game_display::get_singleton() != nullptr) {
308  }
309 }
310 
311 /**
312  * Helper function for show_wml_messages(), which gathers
313  * the messages from a stringstream.
314  */
315 void wml_event_pump::fill_wml_messages_map(std::map<std::string, int>& msg_map, std::stringstream& source)
316 {
317  while(true) {
318  std::string msg;
319  std::getline(source, msg);
320 
321  if(source.eof()) {
322  break;
323  }
324 
325  if(msg.empty()) {
326  continue;
327  }
328 
329  if(msg_map.find(msg) == msg_map.end()) {
330  msg_map[msg] = 1;
331  } else {
332  msg_map[msg]++;
333  }
334  }
335 
336  // Make sure the eof flag is cleared otherwise no new messages are shown
337  source.clear();
338 }
339 
340 /**
341  * Shows a summary of messages/errors generated so far by WML.
342  * Identical messages are shown once, with (between parentheses)
343  * the number of times that message was encountered.
344  * The order in which the messages are shown does not need
345  * to be the order in which these messages are encountered.
346  * Messages are also written to std::cerr if to_cerr is true.
347  */
348 void wml_event_pump::show_wml_messages(std::stringstream& source, const std::string& caption, bool to_cerr)
349 {
350  // Get all unique messages in messages,
351  // with the number of encounters for these messages
352  std::map<std::string, int> messages;
353  fill_wml_messages_map(messages, source);
354 
355  // Show the messages collected
356  for(std::map<std::string, int>::const_iterator itor = messages.begin(); itor != messages.end(); ++itor) {
357  std::stringstream msg;
358  msg << itor->first;
359  if(itor->second > 1) {
360  msg << " (" << itor->second << ")";
361  }
362 
364  std::time(nullptr), caption, 0, msg.str(), events::chat_handler::MESSAGE_PUBLIC, false);
365 
366  if(to_cerr) {
367  std::cerr << caption << ": " << msg.str() << '\n';
368  }
369  }
370 }
371 
372 /**
373  * Shows a summary of the errors encountered in WML so far,
374  * to avoid a lot of the same messages to be shown.
375  * Identical messages are shown once, with (between parentheses)
376  * the number of times that message was encountered.
377  * The order in which the messages are shown does not need
378  * to be the order in which these messages are encountered.
379  * Messages are always written to std::cerr.
380  */
382 {
383  static const std::string caption("Invalid WML found");
384 
385  show_wml_messages(lg::wml_error(), caption, true);
386 }
387 
388 /**
389  * Shows a summary of the messages generated so far by WML.
390  * Identical messages are shown once, with (between parentheses)
391  * the number of times that message was encountered.
392  * The order in which the messages are shown does not need
393  * to be the order in which these messages are encountered.
394  */
396 {
397  static const std::string caption("WML");
398 
399  show_wml_messages(impl_->wml_messages_stream, caption, false);
400 }
401 
403  lg::logger& logger, const std::string& prefix, const std::string& message, bool in_chat)
404 {
405  logger(log_wml) << message << std::endl;
406  if(in_chat) {
407  impl_->wml_messages_stream << prefix << message << std::endl;
408  }
409 }
410 
411 context::scoped::scoped(std::stack<context::state>& contexts, bool m)
412  : contexts_(contexts)
413 {
414  // The default context at least should always be on the stack
415  assert(contexts_.size() > 0);
416 
417  bool skip_messages = (contexts_.size() > 1) && contexts_.top().skip_messages;
418  contexts_.emplace(skip_messages, m);
419 }
420 
422 {
423  assert(contexts_.size() > 1);
424  bool undo_disabled = contexts_.top().undo_disabled;
425  bool action_canceled = contexts_.top().action_canceled;
426 
427  contexts_.pop();
428  contexts_.top().undo_disabled |= undo_disabled;
429  contexts_.top().action_canceled |= action_canceled;
430 }
431 
433 {
434  assert(impl_->contexts_.size() > 0);
435  return impl_->contexts_.top().undo_disabled;
436 }
437 
439 {
440  assert(impl_->contexts_.size() > 0);
441  impl_->contexts_.top().undo_disabled = b;
442 }
443 
445 {
446  assert(impl_->contexts_.size() > 0);
447  return impl_->contexts_.top().action_canceled;
448 }
449 
451 {
452  assert(impl_->contexts_.size() > 0);
453  impl_->contexts_.top().action_canceled = true;
454 }
455 
456 
458 {
459  assert(impl_->contexts_.size() > 0);
460  return impl_->contexts_.top().skip_messages;
461 }
462 
464 {
465  assert(impl_->contexts_.size() > 0);
466  impl_->contexts_.top().skip_messages = b;
467 }
468 
469 /**
470  * Helper function which determines whether a wml_message text can
471  * really be pushed into the wml_messages_stream, and does it.
472  */
473 void wml_event_pump::put_wml_message(const std::string& logger, const std::string& message, bool in_chat)
474 {
475  if(logger == "err" || logger == "error") {
476  put_wml_message(lg::err(), _("Error: "), message, in_chat);
477  } else if(logger == "warn" || logger == "wrn" || logger == "warning") {
478  put_wml_message(lg::warn(), _("Warning: "), message, in_chat);
479  } else if((logger == "debug" || logger == "dbg") && !lg::debug().dont_log(log_wml)) {
480  put_wml_message(lg::debug(), _("Debug: "), message, in_chat);
481  } else if(!lg::info().dont_log(log_wml)) {
482  put_wml_message(lg::info(), _("Info: "), message, in_chat);
483  }
484 }
485 
487  const std::string& event, const entity_location& loc1, const entity_location& loc2, const config& data)
488 {
489  raise(event, loc1, loc2, data);
490  return (*this)();
491 }
492 
493 pump_result_t wml_event_pump::fire(const std::string& event,
494  const std::string& id,
495  const entity_location& loc1,
496  const entity_location& loc2,
497  const config& data)
498 {
499  raise(event, id, loc1, loc2, data);
500  return (*this)();
501 }
502 
503 void wml_event_pump::raise(const std::string& event,
504  const std::string& id,
505  const entity_location& loc1,
506  const entity_location& loc2,
507  const config& data)
508 {
509  if(game_display::get_singleton() == nullptr)
510  return;
511 
512  DBG_EH << "raising event name=" << event << ", id=" << id << "\n";
513 
514  impl_->events_queue.emplace_back(event, id, loc1, loc2, data);
515 }
516 
518 {
519  // Quick aborts:
520  if(game_display::get_singleton() == nullptr) {
521  return pump_result_t();
522  }
523 
524  assert(resources::lua_kernel != nullptr);
525  if(impl_->events_queue.empty()) {
526  DBG_EH << "Processing queued events, but none found.\n";
527  return pump_result_t();
528  }
529 
530  if(impl_->instance_count >= game_config::max_loop) {
531  ERR_NG << "game_events pump waiting to process new events because "
532  << "recursion level would exceed maximum: " << game_config::max_loop << '\n';
533  return pump_result_t();
534  }
535 
536  if(!lg::debug().dont_log("event_handler")) {
537  std::stringstream ss;
538  for(const queued_event& ev : impl_->events_queue) {
539  ss << "name=" << ev.name << ", "
540  << "id=" << ev.id << "; ";
541  }
542  DBG_EH << "processing queued events: " << ss.str() << "\n";
543  }
544 
545  // Ensure the whiteboard doesn't attempt to build its future unit map
546  // while events are being processed.
547  wb::real_map real_unit_map;
548 
549  pump_manager pump_instance(*impl_);
550  context::scoped evc(impl_->contexts_, false);
551  // Loop through the events we need to process.
552  while(!pump_instance.done()) {
553  queued_event& ev = pump_instance.next();
554 
555  if(ev.name.empty() && ev.id.empty()) {
556  continue;
557  }
558 
559  const std::string& event_name = ev.name;
560  const std::string& event_id = ev.id;
561 
562  // Clear the unit cache, since the best clearing time is hard to figure out
563  // due to status changes by WML. Every event will flush the cache.
565 
566  { // Block for context::scoped
567  context::scoped inner_evc(impl_->contexts_, false);
569  }
570 
571  assert(impl_->my_manager);
572 
577 
578  if(event_id.empty()) {
579  // Handle events of this name.
580  impl_->my_manager->execute_on_events(event_name, [&](game_events::manager&, handler_ptr& ptr) {
581  DBG_EH << "processing event " << event_name << " with id=" << ptr->get_config()["id"] << "\n";
582 
583  // Let this handler process our event.
584  process_event(ptr, ev);
585  });
586  } else {
587  // Get the handler directly via ID
588  handler_ptr cur_handler = impl_->my_manager->get_event_handler_by_id(event_id);
589 
590  if(cur_handler) {
591  DBG_EH << "processing event " << event_name << " with id=" << cur_handler->get_config()["id"] << "\n";
592  process_event(cur_handler, ev);
593  }
594  }
595 
596  // Flush messages when finished iterating over event_handlers.
597  flush_messages();
598  }
599 
600  // Notify the whiteboard of any event.
601  // This is used to track when moves, recruits, etc. happen.
602  resources::whiteboard->on_gamestate_change();
603 
604  return std::make_tuple(undo_disabled(), action_canceled());
605 }
606 
608 {
609  // Dialogs can only be shown if the display is not locked
610  if(game_display::get_singleton() && !CVideo::get_singleton().update_locked()) {
611  show_wml_errors();
612  show_wml_messages();
613  }
614 }
615 
617  : impl_(new pump_impl(man))
618 {
619 }
620 
622 {
623 }
624 
625 } // end namespace game_events
play_controller * controller
Definition: resources.cpp:21
manager * my_manager
Definition: pump.cpp:96
int x2_
Definition: pump.cpp:135
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:423
std::vector< queued_event > queue_
Tracks the events to process.
Definition: pump.cpp:141
unit_iterator end()
Definition: map.hpp:415
entity_location loc2
Definition: pump.hpp:65
State when processing a particular flight of events or commands.
Definition: pump.cpp:61
map_location last_selected
the last location where a select event fired.
Definition: game_data.hpp:83
#define ERR_NG
Definition: pump.cpp:44
bool matches_unit_filter(const unit_map::const_iterator &un_it, const vconfig &filter) const
Determines if un_it matches filter.
wml_event_pump(manager &)
Definition: pump.cpp:616
virtual const unit_map & units() const override
Definition: game_board.hpp:114
logger & info()
Definition: log.cpp:90
std::stringstream wml_messages_stream
Definition: pump.cpp:90
const map_location & filter_loc() const
int wml_x() const
Definition: location.hpp:157
static CVideo & get_singleton()
Definition: video.hpp:43
std::string name
Definition: pump.hpp:62
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
scoped(std::stack< context::state > &contexts, bool m=true)
Definition: pump.cpp:411
bool action_canceled()
Returns whether or not wml wants to abort the currently executed user action.
Definition: pump.cpp:444
const std::size_t max_loop
The maximum number of hexes on a map and items in an array and also used as maximum in wml loops...
Definition: game_config.cpp:92
game_data * gamedata
Definition: resources.cpp:22
config::attribute_value & get_variable(const std::string &varname)
throws invalid_variablename_exception if varname is no valid variable name.
Definition: game_data.cpp:62
void add_chat_message(const std::time_t &time, const std::string &speaker, int side, const std::string &msg, events::chat_handler::MESSAGE_TYPE type, bool bell)
#define b
int x1_
Definition: pump.cpp:135
int y2_
Definition: pump.cpp:135
static lg::log_domain log_engine("engine")
static void clear_status_caches()
Clear this unit status cache for all units.
Definition: unit.cpp:699
child_list get_children(const std::string &key) const
Definition: variable.cpp:190
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:89
const config & get_config() const
Definition: handlers.hpp:67
bool matches_unit(const unit_map::const_iterator &un_it) const
Determines if un_it matches (using underlying ID) the unit that was supplied when this was constructe...
int wml_y() const
Definition: location.hpp:158
void show_wml_messages()
Shows a summary of the messages generated so far by WML.
Definition: pump.cpp:395
pump_impl(manager &man)
Definition: pump.cpp:98
game_board * gameboard
Definition: resources.cpp:20
std::vector< queued_event > events_queue
Definition: pump.cpp:88
void flush_messages()
Flushes WML messages and errors.
Definition: pump.cpp:607
bool run_event(const game_events::queued_event &)
Executes the game_events.on_event function.
void show_wml_errors()
Shows a summary of the errors encountered in WML so far, to avoid a lot of the same messages to be sh...
Definition: pump.cpp:381
logger & debug()
Definition: log.cpp:96
static lg::log_domain log_event_handler("event_handler")
Domain specific events.
Definition: action_wml.cpp:88
int y1_
Definition: pump.cpp:135
unit_iterator find(std::size_t id)
Definition: map.cpp:311
std::shared_ptr< wb::manager > whiteboard
Definition: resources.cpp:33
state(bool s, bool m=true)
Definition: pump.cpp:67
Define conditionals for the game&#39;s events mechanism, a.k.a.
std::size_t pumped_count_
Tracks how many events have been processed.
Definition: pump.cpp:144
void put_wml_message(const std::string &logger, const std::string &message, bool in_chat)
Helper function which determines whether a wml_message text can really be pushed into the wml_message...
Definition: pump.cpp:473
std::stringstream & wml_error()
Use this logger to send errors due to deprecated WML.
Definition: log.cpp:269
logger & err()
Definition: log.cpp:78
void raise(const std::string &event, const std::string &id, const entity_location &loc1=entity_location::null_entity, const entity_location &loc2=entity_location::null_entity, const config &data=config())
Definition: pump.cpp:503
bool undo_disabled()
Context: The general environment within which events are processed.
Definition: pump.cpp:432
bool matches_special_filter(const config &cfg, const vconfig &filter)
void set_action_canceled()
Sets whether or not wml wants to abort the currently executed user action.
Definition: pump.cpp:450
static map_location::DIRECTION s
pump_result_t operator()()
Definition: pump.cpp:517
pump_impl & impl_
Definition: pump.cpp:134
Define the game&#39;s event mechanism.
#define DBG_EH
Definition: pump.cpp:53
The game event manager loads the scenario configuration object, and ensures that events are handled a...
Definition: manager.hpp:43
static lg::log_domain log_wml("wml")
void process_event(handler_ptr &handler_p, const queued_event &ev)
Processes an event through a single event handler.
Definition: pump.cpp:276
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:486
entity_location loc1
Definition: pump.hpp:64
#define next(ls)
Definition: llex.cpp:32
display_chat_manager & get_chat_manager()
bool conditional_passed(const vconfig &cond)
bool match(const team &t) const
Define the handlers for the game&#39;s events mechanism.
logger & warn()
Definition: log.cpp:84
#define f
unsigned instance_count
Definition: pump.cpp:94
bool filter_event(const event_handler &handler, const queued_event &ev)
Returns true iff the given event passes all its filters.
Definition: pump.cpp:192
void set_undo_disabled(bool mutated)
[allow_undo] implementation
Definition: pump.cpp:438
A variable-expanding proxy for the config class.
Definition: variable.hpp:42
Standard logging facilities (interface).
int current_side() const
Returns the number of the side whose turn it is.
game_lua_kernel * lua_kernel
Definition: resources.cpp:25
Container associating units to locations.
Definition: map.hpp:99
void fill_wml_messages_map(std::map< std::string, int > &msg_map, std::stringstream &source)
Helper function for show_wml_messages(), which gathers the messages from a stringstream.
Definition: pump.cpp:315
std::stack< context::state > contexts_
Definition: pump.cpp:92
std::stack< context::state > & contexts_
Definition: pump.cpp:82
std::vector< vconfig > child_list
Definition: variable.hpp:78
std::shared_ptr< event_handler > handler_ptr
Definition: fwd.hpp:24
std::tuple< bool, bool > pump_result_t
Definition: fwd.hpp:28
Ensures that the real unit map is active for the duration of the struct&#39;s life.
Definition: manager.hpp:282
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:92
static game_display * get_singleton()
bool maybe_rebuild()
Rebuilds the screen if needs_rebuild(true) was previously called, and resets the flag.
bool context_skip_messages()
Returns whether or not we are skipping messages.
Definition: pump.cpp:457