The Battle for Wesnoth  1.13.11+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
playsingle_controller.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2006 - 2018 by Joerg Hinrichs <joerg.hinrichs@alice-dsl.de>
3  wesnoth playlevel Copyright (C) 2003 by David White <dave@whitevine.net>
4  Part of the Battle for Wesnoth Project http://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 /**
17  * @file
18  * Logic for single-player game.
19  */
20 
22 
23 #include "actions/undo.hpp"
24 #include "ai/manager.hpp"
25 #include "ai/testing.hpp"
26 #include "display_chat_manager.hpp"
27 #include "game_end_exceptions.hpp"
28 #include "game_events/pump.hpp"
29 #include "preferences/game.hpp"
30 #include "gettext.hpp"
34 #include "log.hpp"
35 #include "map/label.hpp"
36 #include "map/map.hpp"
37 #include "playturn.hpp"
38 #include "random_deterministic.hpp"
39 #include "replay_helper.hpp"
40 #include "resources.hpp"
41 #include "savegame.hpp"
42 #include "sound.hpp"
43 #include "synced_context.hpp"
44 #include "formula/string_utils.hpp"
45 #include "events.hpp"
46 #include "save_blocker.hpp"
48 #include "soundsource.hpp"
49 #include "statistics.hpp"
50 #include "units/unit.hpp"
52 #include "whiteboard/manager.hpp"
53 #include "hotkey/hotkey_item.hpp"
54 #include <boost/dynamic_bitset.hpp>
55 
56 static lg::log_domain log_aitesting("aitesting");
57 #define LOG_AIT LOG_STREAM(info, log_aitesting)
58 //If necessary, this define can be replaced with `#define LOG_AIT std::cout` to restore previous behavior
59 
60 static lg::log_domain log_engine("engine");
61 #define ERR_NG LOG_STREAM(err, log_engine)
62 #define LOG_NG LOG_STREAM(info, log_engine)
63 
64 static lg::log_domain log_enginerefac("enginerefac");
65 #define LOG_RG LOG_STREAM(info, log_enginerefac)
66 
68  saved_game& state_of_game,
69  const config& game_config, const ter_data_cache & tdata, bool skip_replay)
70  : play_controller(level, state_of_game, game_config, tdata, skip_replay)
71  , cursor_setter_(cursor::NORMAL)
72  , textbox_info_()
73  , replay_sender_(*resources::recorder)
74  , network_reader_([this](config& cfg) {return receive_from_wesnothd(cfg);})
75  , turn_data_(replay_sender_, network_reader_)
76  , end_turn_(END_TURN_NONE)
77  , skip_next_turn_(false)
78  , ai_fallback_(false)
79  , replay_()
80 {
81  hotkey_handler_.reset(new hotkey_handler(*this, saved_game_)); //upgrade hotkey handler to the sp (whiteboard enabled) version
82 
83 
84  // game may need to start in linger mode
85  linger_ = this->is_regular_game_end();
86 
88 
89  plugins_context_->set_accessor_string("level_result", std::bind(&playsingle_controller::describe_result, this));
90  plugins_context_->set_accessor_int("turn", std::bind(&play_controller::turn, this));
91 }
92 
94 {
95  if(!is_regular_game_end()) {
96  return "NONE";
97  }
98  else if(get_end_level_data_const().is_victory){
99  return "VICTORY";
100  }
101  else {
102  return "DEFEAT";
103  }
104 }
105 
107 {
108  LOG_NG << "Initializing GUI... " << (SDL_GetTicks() - ticks()) << "\n";
110 
111  // Scroll to the starting position of the first team. If there is a
112  // human team, use that team; otherwise use team 1. If the map defines
113  // a starting position for the selected team, scroll to that tile. Note
114  // this often does not matter since many scenario start with messages,
115  // which will usually scroll to the speaker. Also note that the map
116  // does not necessarily define the starting positions. While usually
117  // best to use the map, the scenarion may explicitly set the positions,
118  // overriding those found in the map (if any).
119  if(map_start_.valid())
120  {
121  gui_->scroll_to_tile(map_start_, game_display::WARP, false);
122  LOG_NG << "Found good stored ui location " << map_start_ << "\n";
123  }
124  else
125  {
126  int scroll_team = gamestate().first_human_team_ + 1;
127  if (scroll_team == 0) {
128  scroll_team = 1;
129  }
130  map_location loc(gamestate().board_.map().starting_position(scroll_team));
131  if ((loc.x >= 0) && (loc.y >= 0)) {
132  gui_->scroll_to_tile(loc, game_display::WARP);
133  LOG_NG << "Found bad stored ui location " << map_start_ << " using side starting location " << loc << "\n";
134  }
135  else {
136  LOG_NG << "Found bad stored ui location\n";
137  }
138  }
139 
140  update_locker lock_display(gui_->video(), is_skipping_replay());
142 }
143 
144 
146 {
147  // At the beginning of the scenario, save a snapshot as replay_start
150  }
151  start_game();
153  // This won't cause errors later but we should notify the user about it in case he didn't knew it.
155  // TODO: find a better title
156  _("Game Error"),
157  _("This multiplayer game uses an alternative random mode, if you don't know what this message means, then most likely someone is cheating or someone reloaded a corrupt game.")
158  );
159  }
160  return;
161 }
162 
164 {
165  LOG_NG << "starting main loop\n" << (SDL_GetTicks() - ticks()) << "\n";
166 
167 
168  // Avoid autosaving after loading, but still
169  // allow the first turn to have an autosave.
171  if(gamestate().board_.teams().empty())
172  {
173  ERR_NG << "Playing game with 0 teams." << std::endl;
174  }
175  while(true) {
176  try {
177  play_turn();
178  if (is_regular_game_end()) {
180  return;
181  }
182  gamestate_->player_number_ = 1;
183  }
184  catch(const reset_gamestate_exception& ex) {
185  //
186  // TODO:
187  //
188  // The MP replay feature still doesn't work properly (causes OOS)
189  // because:
190  //
191  // 1) The undo stack is not reset along with the gamestate (fixed).
192  // 2) The server_request_number_ is not reset along with the
193  // gamestate (fixed).
194  // 3) chat and other unsynced actions are inserted in the middle of
195  // the replay bringing the replay_pos in unorder (fixed).
196  // 4) untracked changes in side controllers are lost when resetting
197  // gamestate (fixed).
198  // 5) The game should have a stricter check for whether the loaded
199  // game is actually a parent of this game.
200  // 6) If an action was undone after a game was saved it can cause
201  // OOS if the undone action is in the snapshot of the saved
202  // game (luckily this is never the case for autosaves).
203  //
204  boost::dynamic_bitset<> local_players;
205  local_players.resize(gamestate().board_.teams().size(), true);
206  //Preserve side controllers, because we won't get the side controoller updates again when replaying.
207  for(size_t i = 0; i < local_players.size(); ++i) {
208  local_players[i] = gamestate().board_.teams()[i].is_local();
209  }
210  reset_gamestate(*ex.level, (*ex.level)["replay_pos"]);
211  for(size_t i = 0; i < local_players.size(); ++i) {
212  resources::gameboard->teams()[i].set_local(local_players[i]);
213  }
215  replay_.reset(new replay_controller(*this, false, ex.level));
216  if(ex.start_replay) {
217  replay_->play_replay();
218  }
219  }
220  } //end for loop
221 }
222 
224 {
225  LOG_NG << "in playsingle_controller::play_scenario()...\n";
226 
227  // Start music.
228  for(const config &m : level.child_range("music")) {
230  }
232 
233  if(!this->is_skipping_replay()) {
234  // Combine all the [story] tags into a single config. Handle this here since
235  // storyscreen::controller doesn't have a default constructor.
236  config cfg;
237  for(const auto& iter : level.child_range("story")) {
238  cfg.append_children(iter);
239  }
240 
241  if(!cfg.empty()) {
243  }
244  }
245  gui_->labels().read(level);
246 
247  // Read sound sources
248  assert(soundsources_manager_ != nullptr);
249  for (const config &s : level.child_range("sound_source")) {
250  try {
252  soundsources_manager_->add(spec);
253  } catch (bad_lexical_cast &) {
254  ERR_NG << "Error when parsing sound_source config: bad lexical cast." << std::endl;
255  ERR_NG << "sound_source config was: " << s.debug() << std::endl;
256  ERR_NG << "Skipping this sound source..." << std::endl;
257  }
258  }
259  LOG_NG << "entering try... " << (SDL_GetTicks() - ticks()) << "\n";
260  try {
262  // clears level config;
264 
265  if (!is_regular_game_end() && !linger_) {
267  }
269  exit(0);
270  }
271  const bool is_victory = get_end_level_data_const().is_victory;
272 
273  if(gamestate().gamedata_.phase() <= game_data::PRESTART) {
274  gui_->video().clear_screen();
275  }
276 
278 
279  const end_level_data& end_level = get_end_level_data_const();
280 
281  if (gamestate().board_.teams().empty())
282  {
283  //store persistent teams
285 
286  return LEVEL_RESULT::VICTORY; // this is probably only a story scenario, i.e. has its endlevel in the prestart event
287  }
288  if(linger_) {
289  LOG_NG << "resuming from loaded linger state...\n";
290  //as carryover information is stored in the snapshot, we have to re-store it after loading a linger state
292  if(!is_observer()) {
294  }
295  return LEVEL_RESULT::VICTORY;
296  }
297  pump().fire(is_victory ? "local_victory" : "local_defeat");
298  { // Block for set_scontext_synced_base
300  pump().fire(end_level.proceed_to_next_level ? "victory" : "defeat");
301  pump().fire("scenario_end");
302  }
303  if(end_level.proceed_to_next_level) {
305  }
306  if(is_observer()) {
307  gui2::show_transient_message(_("Game Over"), _("The game is over."));
308  return LEVEL_RESULT::OBSERVER_END;
309  }
310  // If we're a player, and the result is victory/defeat, then send
311  // a message to notify the server of the reason for the game ending.
313  "info", config {
314  "type", "termination",
315  "condition", "game over",
316  "result", is_victory ? "victory" : "defeat",
317  },
318  });
319  // Play victory music once all victory events
320  // are finished, if we aren't observers and the
321  // carryover dialog isn't disabled.
322  //
323  // Some scenario authors may use 'continue'
324  // result for something that is not story-wise
325  // a victory, so let them use [music] tags
326  // instead should they want special music.
327  const std::string& end_music = select_music(is_victory);
328  if((!is_victory || end_level.transient.carryover_report) && !end_music.empty()) {
330  sound::play_music_once(end_music);
331  }
333  return is_victory ? LEVEL_RESULT::VICTORY : LEVEL_RESULT::DEFEAT;
334  } catch(const savegame::load_game_exception &) {
335  // Loading a new game is effectively a quit.
336  saved_game_.clear();
337  throw;
338  } catch(wesnothd_error& e) {
339 
340  scoped_savegame_snapshot snapshot(*this);
342  save.save_game_interactive(_("A network disconnection has occurred, and the game cannot continue. Do you want to save the game?"), savegame::savegame::YES_NO);
343  if(dynamic_cast<ingame_wesnothd_error*>(&e)) {
344  return LEVEL_RESULT::QUIT;
345  } else {
346  throw;
347  }
348  }
349 }
350 
352 {
353  while(!should_return_to_play_side()) {
355  SDL_Delay(10);
356  }
357 }
358 
360 {
361  if (!skip_next_turn_) {
363  }
364  if(replay_.get() != nullptr) {
365  REPLAY_RETURN res = replay_->play_side_impl();
366  if(res == REPLAY_FOUND_END_TURN) {
368  }
369  if (player_type_changed_) {
370  replay_.reset();
371  }
372  } else if((current_team().is_local_human() && current_team().is_proxy_human())) {
373  LOG_NG << "is human...\n";
374  // If a side is dead end the turn, but play at least side=1's
375  // turn in case all sides are dead
376  if (gamestate().board_.side_units(current_side()) == 0 && !(gamestate().board_.units().empty() && current_side() == 1)) {
378  }
379 
381  if (end_turn_ == END_TURN_NONE) {
382  play_human_turn();
383  }
386  }
387  LOG_NG << "human finished turn...\n";
388 
389  } else if(current_team().is_local_ai() || (current_team().is_local_human() && current_team().is_droid())) {
390  play_ai_turn();
391  } else if(current_team().is_network()) {
393  } else if(current_team().is_local_human() && current_team().is_idle()) {
394  end_turn_enable(false);
397  if (end_turn_ == END_TURN_NONE) {
398  play_idle_loop();
399  }
400  }
401  else {
402  // we should have skipped over empty controllers before so this shouldn't be possible
403  ERR_NG << "Found invalid side controller " << current_team().controller().to_string() << " (" << current_team().proxy_controller().to_string() << ") for side " << current_team().side() << "\n";
404  }
405 }
406 
408 {
409  log_scope("player turn");
410  assert(!linger_);
412  return;
413  }
414 
415  if(init_side_done_now_) {
416  scoped_savegame_snapshot snapshot(*this);
419  }
420 
421  if(preferences::turn_bell()) {
423  }
424 }
425 
428  blindfold b(*gui_, true); //apply a blindfold for the duration of this dialog
429  gui_->redraw_everything();
430  gui_->recalculate_minimap();
431  std::string message = _("It is now $name|’s turn");
432  utils::string_map symbols;
433  symbols["name"] = gamestate().board_.get_team(current_side()).side_name();
434  message = utils::interpolate_variables_into_string(message, &symbols);
435  gui2::show_transient_message("", message);
436  }
437 }
438 
440 {
442  {
443  return;
444  }
445  try
446  {
448  }
449  catch (const return_to_play_side_exception&)
450  {
451  }
452 }
453 
456 
458  execute_gotos();
459  }
460 
461  end_turn_enable(true);
462  while(!should_return_to_play_side()) {
465  }
466 
467 }
468 
470 {
471  LOG_NG << "beginning end-of-scenario linger\n";
472  linger_ = true;
473 
474  // If we need to set the status depending on the completion state
475  // the key to it is here.
476  gui_->set_game_mode(game_display::LINGER);
477 
478  // change the end-turn button text to its alternate label
479  gui_->get_theme().refresh_title2("button-endturn", "title2");
480  gui_->invalidate_theme();
481  gui_->redraw_everything();
482 
483  // End all unit moves
485  try {
486  // Same logic as single-player human turn, but
487  // *not* the same as multiplayer human turn.
488  end_turn_enable(true);
490  while(end_turn_ == END_TURN_NONE) {
491  play_slice();
492  }
493  } catch(const savegame::load_game_exception &) {
494  // Loading a new game is effectively a quit.
495  saved_game_.clear();
496  throw;
497  }
498 
499  // revert the end-turn button text to its normal label
500  gui_->get_theme().refresh_title2("button-endturn", "title");
501  gui_->invalidate_theme();
502  gui_->redraw_everything();
503  gui_->set_game_mode(game_display::RUNNING);
504 
505  LOG_NG << "ending end-of-scenario linger\n";
506 }
507 
509 {
510  gui_->enable_menu("endturn", enable);
512 }
513 
514 
516 {
517  // Clear moves from the GUI.
518  gui_->set_route(nullptr);
519  gui_->unhighlight_reach();
520 }
521 
523 {
524  LOG_NG << "is ai...\n";
525 
526  end_turn_enable(false);
527  gui_->recalculate_minimap();
528 
529  const cursor::setter cursor_setter(cursor::WAIT);
530 
531  // Correct an oddball case where a human could have left delayed shroud
532  // updates on before giving control to the AI. (The AI does not bother
533  // with the undo stack, so it cannot delay shroud updates.)
534  team & cur_team = current_team();
535  if ( !cur_team.auto_shroud_updates() ) {
536  // We just took control, so the undo stack is empty. We still need
537  // to record this change for the replay though.
539  }
540  undo_stack().clear();
541 
543  try {
544  try {
547  }
548  }
549  catch (return_to_play_side_exception&) {
550  }
553  player_type_changed_ = true;
554  ai_fallback_ = true;
555  }
556  }
557  catch(...) {
559  throw;
560  }
563  }
565  gui_->recalculate_minimap();
566  gui_->invalidate_unit();
567  gui_->invalidate_game_status();
568  gui_->invalidate_all();
569 }
570 
571 
572 /**
573  * Will handle sending a networked notification in descendent classes.
574  */
576 {
577  gui_->get_chat_manager().add_chat_message(time(nullptr), "Wesnoth", 0,
578  "This side is in an idle state. To proceed with the game, the host must assign it to another controller.",
580 }
581 
582 /**
583  * Will handle networked turns in descendent classes.
584  */
586 {
587  // There should be no networked sides in single-player.
588  ERR_NG << "Networked team encountered by playsingle_controller." << std::endl;
589 }
590 
591 
593  if (name == "ai_user_interact"){
594  play_slice(false);
595  }
596 }
597 
598 
599 
601  if (linger_)
603  else if (!is_browsing() && menu_handler_.end_turn(current_side())){
605  }
606 }
607 
609  skip_next_turn_ = true;
611 }
612 
614 {
615  if (!gamestate().board_.teams().empty()) {
616  const team &t = gamestate().board_.teams()[gui_->viewing_team()];
617 
618  if (!is_regular_game_end() && !is_browsing() && t.objectives_changed()) {
619  show_objectives();
620  }
621  }
622 }
623 
624 
626 {
627  // mouse_handler expects at least one team for linger mode to work.
628  assert(is_regular_game_end());
629  if (get_end_level_data_const().transient.linger_mode && !gamestate().board_.teams().empty()) {
630  linger();
631  }
632 }
633 
635 {
636  //We cannot add [end_turn] to the recorder while executing another action.
638  if(end_turn_ == END_TURN_REQUIRED && current_team().is_local())
639  {
640  //TODO: we should also send this immediately.
643  }
644 
645  assert(end_turn_ == END_TURN_SYNCED);
646  skip_next_turn_ = false;
647 
648  if(ai_fallback_) {
649  current_team().make_ai();
650  ai_fallback_ = false;
651  }
652 }
653 
655 {
656  if(replay_ && replay_->is_controlling_view()) {
657  replay_->update_viewing_player();
658  }
659  //Update viewing team in case it has changed during the loop.
660  else if(int side_num = play_controller::find_last_visible_team()) {
661  if(side_num != this->gui_->viewing_side()) {
662  update_gui_to_player(side_num - 1);
663  }
664  }
665 }
666 
668 {
669  if(replay_ && replay_->allow_reset_replay()) {
670  replay_->stop_replay();
671  throw reset_gamestate_exception(replay_->get_reset_state(), false);
672  }
673  else {
674  ERR_NG << "received invalid reset replay\n";
675  }
676 }
677 
679 {
680  replay_.reset(new replay_controller(*this, gamestate().has_human_sides(), std::shared_ptr<config>( new config(saved_game_.replay_start())), std::bind(&playsingle_controller::on_replay_end, this, is_unit_test)));
681  if(is_unit_test) {
682  replay_->play_replay();
683  }
684 }
685 
687 {
689  return true;
690  }
691  else if (end_turn_ == END_TURN_NONE || replay_.get() != 0 || current_team().is_network()) {
692  return false;
693  }
694  else {
695  return true;
696  }
697 }
698 
700 {
701  if(is_unit_test) {
702  replay_->return_to_play_side();
703  if(!is_regular_game_end()) {
705  e.proceed_to_next_level = false;
706  e.is_victory = false;
708  }
709  }
710 }
bool disable_auto_moves()
Definition: general.cpp:1049
void empty_playlist()
Definition: sound.cpp:574
void clear()
Clears the stack of undoable (and redoable) actions.
Definition: undo.cpp:218
void set_all_units_user_end_turn()
Definition: game_board.cpp:80
void add_observer(events::observer *event_observer)
Adds observer of game events.
Definition: manager.cpp:327
An error occurred during when trying to coommunicate with the wesnothd server.
bool is_network() const
Definition: team.hpp:259
int autosavemax()
Definition: game.cpp:810
std::unique_ptr< soundsource::manager > soundsources_manager_
bool turn_bell()
Definition: general.cpp:607
virtual void send_to_wesnothd(const config &, const std::string &="unknown") const
static void display(const std::string &scenario_name, const config &story)
std::vector< char_t > string
int ticks() const
static bool run_and_store(const std::string &commandname, const config &data, bool use_undo=true, bool show=true, synced_command::error_handler_function error_handler=default_error_function)
hotkey::command_executor * get_hotkey_command_executor() override
Optionally get a command executor to handle context menu events.
std::string interpolate_variables_into_string(const std::string &str, const string_map *const symbols)
Function which will interpolate variables, starting with '$' in the string 'str' with the equivalent ...
virtual const std::vector< team > & teams() const override
Definition: game_board.hpp:92
const end_level_data & get_end_level_data_const() const
void heal_all_survivors()
Definition: game_board.cpp:86
std::map< std::string, t_string > string_map
virtual const unit_map & units() const override
Definition: game_board.hpp:114
void end_turn()
Definition: replay.cpp:300
std::unique_ptr< game_display > gui_
const std::string & select_music(bool victory) const
events::mouse_handler mouse_handler_
static manager & get_singleton()
Definition: manager.hpp:152
config & replay_start()
Definition: saved_game.hpp:105
virtual void play_side_impl() override
Class for autosaves.
Definition: savegame.hpp:268
game_events::wml_event_pump & pump()
const int INFINITE_AUTO_SAVES
Definition: game.hpp:191
int first_human_team_
Definition: game_state.hpp:69
child_itors child_range(config_key_type key)
Definition: config.cpp:362
virtual void init_gui() override
void show_transient_message(const std::string &title, const std::string &message, const std::string &image, const bool message_use_markup, const bool title_use_markup, const bool restore_background)
Shows a transient message to the user.
PROXY_CONTROLLER proxy_controller() const
Definition: team.hpp:279
PROCESS_DATA_RESULT sync_network()
Definition: playturn.cpp:61
static lg::log_domain log_aitesting("aitesting")
bool objectives_changed() const
Definition: team.hpp:239
static config get_auto_shroud(bool turned_on)
Records that the player has toggled automatic shroud updates.
Gather statistics important for AI testing and output them.
And endturn was required eigher by the player, by the ai or by [end_turn].
void clear()
Definition: saved_game.cpp:699
void enable_replay(bool is_unit_test=false)
void play_slice(bool is_delay_enabled=true)
Class for "normal" midgame saves.
Definition: savegame.hpp:241
config & set_snapshot(config snapshot)
Definition: saved_game.cpp:474
playsingle_controller(const config &level, saved_game &state_of_game, const config &game_config, const ter_data_cache &tdata, bool skip_replay)
void play_music_once(const std::string &file)
Definition: sound.cpp:565
bool is_skipping_replay() const
void append_children(const config &cfg)
Adds children from cfg.
Definition: config.cpp:241
static void log_game_end()
Definition: testing.cpp:102
Contains the exception interfaces used to signal completion of a scenario, campaign or turn...
bool save_game_interactive(const std::string &message, DIALOG_TYPE dialog_type)
Save a game interactively through the savegame dialog.
Definition: savegame.cpp:351
bool empty() const
Definition: config.cpp:830
std::unique_ptr< replay_controller > replay_
persist_manager persist_
void send_data()
Definition: playturn.cpp:80
An extension of play_controller::hotkey_handler, which has support for SP wesnoth features like white...
events::menu_handler menu_handler_
virtual void do_idle_notification()
Will handle sending a networked notification in descendent classes.
#define b
void make_human()
Definition: team.hpp:270
std::unique_ptr< game_state > gamestate_
REPLAY_RETURN
Definition: replay.hpp:152
-file pathfind.hpp
no linger overlay, show fog and shroud.
std::string turn_bell
saved_game & saved_game_
void end_turn_enable(bool enable)
This class stores all the data for a single 'side' (in game nomenclature).
Definition: team.hpp:44
virtual bool receive_from_wesnothd(config &) const
bool end_turn(int side_num)
virtual void check_objectives() override
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:89
virtual bool should_return_to_play_side() const override
team & get_team(int i)
Definition: game_board.hpp:104
bool auto_shroud_updates() const
Definition: team.hpp:334
int current_side() const
Returns the number of the side whose turn it is.
bool valid() const
Definition: location.hpp:74
bool is_regular_game_end() const
bool disable_autosave
size_t turn() const
game_board * gameboard
Definition: resources.cpp:20
virtual void init_gui()
Managing the AIs lifecycle - headers.
#define LOG_NG
replay * recorder
Definition: resources.cpp:28
void play_turn(side_number side)
Plays a turn for the specified side using its active AI.
Definition: manager.cpp:739
static lg::log_domain log_enginerefac("enginerefac")
bool is_observer() const
bool carryover_report
Should a summary of the scenario outcome be displayed?
An object which will lock the display for the duration of its lifetime.
Definition: video.hpp:279
virtual void play_network_turn()
Will handle networked turns in descendent classes.
static void log_game_start()
Definition: testing.cpp:89
LEVEL_RESULT play_scenario(const config &level)
bool is_browsing() const override
void update_gui_to_player(const int team_index, const bool observe=false)
Changes the UI for this client to the passed side index.
std::string describe_result() const
Encapsulates the map of the game.
Definition: location.hpp:42
void on_replay_end(bool is_unit_test)
void make_ai()
Definition: team.hpp:271
Sound source info class.
void set_end_level_data(const end_level_data &data)
Exception used to signal that the user has decided to abortt a game, and to load another game instead...
Definition: savegame.hpp:74
transient_end_level transient
map_location map_start_
void execute_gotos(mouse_handler &mousehandler, int side_num)
#define ERR_NG
Game configuration data as global variables.
Definition: build_info.cpp:53
static map_location::DIRECTION s
void reset_gamestate(const config &level, int replay_pos)
Define the game's event mechanism.
#define log_scope(description)
Definition: log.hpp:186
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.
actions::undo_list & undo_stack()
int side() const
Definition: team.hpp:187
static void save(LexState *ls, int c)
Definition: llex.cpp:57
bool empty() const
Definition: map.hpp:432
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
void update_viewing_player() override
CONTROLLER controller() const
Definition: team.hpp:253
compression::format save_compression_format()
Definition: game.cpp:873
void play_bell(const std::string &files)
Definition: sound.cpp:1004
game_state & gamestate()
double t
Definition: astarsearch.cpp:64
const std::string & side_name() const
Definition: team.hpp:304
void show_objectives() const
game_classification & classification()
Definition: saved_game.hpp:55
game_board board_
Definition: game_state.hpp:46
config to_config() const
Builds the snapshot config from members and their respective configs.
Various functions that implement the undoing (and redoing) of in-game commands.
Standard logging facilities (interface).
void autosave(const bool disable_autosave, const int autosave_max, const int infinite_autosaves)
Definition: savegame.cpp:579
static const char * name(const std::vector< SDL_Joystick * > &joysticks, const size_t index)
Definition: joystick.cpp:48
t_string get_scenario_name() const
std::shared_ptr< config > level
void play_music_config(const config &music_node, int i)
Definition: sound.cpp:666
#define e
void commit_music_changes()
Definition: sound.cpp:783
virtual bool is_networked_mp() const
void remove_snapshot()
Definition: saved_game.cpp:492
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:93
static lg::log_domain log_engine("engine")
bool turn_dialog()
Definition: game.cpp:420
Thrown when a lexical_cast fails.
virtual void handle_generic_event(const std::string &name) override
int find_last_visible_team() const
returns 0 if no such team was found.
An [end_turn] was added to the replay.
bool init_side_done_now_
Whether we did init sides in this session (false = we did init sides before we reloaded the game)...
std::shared_ptr< terrain_type_data > ter_data_cache