The Battle for Wesnoth  1.15.7+dev
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 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 /**
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"
47 #include "soundsource.hpp"
48 #include "statistics.hpp"
49 #include "units/unit.hpp"
51 #include "whiteboard/manager.hpp"
52 #include "hotkey/hotkey_item.hpp"
53 #include <boost/dynamic_bitset.hpp>
54 
55 static lg::log_domain log_aitesting("ai/testing");
56 #define LOG_AIT LOG_STREAM(info, log_aitesting)
57 //If necessary, this define can be replaced with `#define LOG_AIT std::cout` to restore previous behavior
58 
59 static lg::log_domain log_engine("engine");
60 #define ERR_NG LOG_STREAM(err, log_engine)
61 #define LOG_NG LOG_STREAM(info, log_engine)
62 
63 static lg::log_domain log_enginerefac("enginerefac");
64 #define LOG_RG LOG_STREAM(info, log_enginerefac)
65 
67  saved_game& state_of_game, const ter_data_cache & tdata, bool skip_replay)
68  : play_controller(level, state_of_game, tdata, skip_replay)
69  , cursor_setter_(cursor::NORMAL)
70  , textbox_info_()
71  , replay_sender_(*resources::recorder)
72  , network_reader_([this](config& cfg) {return receive_from_wesnothd(cfg);})
75  , skip_next_turn_(false)
76  , ai_fallback_(false)
78 {
79  hotkey_handler_.reset(new hotkey_handler(*this, saved_game_)); //upgrade hotkey handler to the sp (whiteboard enabled) version
80 
81 
82  // game may need to start in linger mode
83  linger_ = this->is_regular_game_end();
84 
85  plugins_context_->set_accessor_string("level_result", std::bind(&playsingle_controller::describe_result, this));
86  plugins_context_->set_accessor_int("turn", std::bind(&play_controller::turn, this));
87 }
88 
90 {
91  if(!is_regular_game_end()) {
92  return "NONE";
93  }
94  else if(get_end_level_data_const().is_victory){
95  return "VICTORY";
96  }
97  else {
98  return "DEFEAT";
99  }
100 }
101 
103 {
104  LOG_NG << "Initializing GUI... " << (SDL_GetTicks() - ticks()) << "\n";
106 
107  // Scroll to the starting position of the first team. If there is a
108  // human team, use that team; otherwise use team 1. If the map defines
109  // a starting position for the selected team, scroll to that tile. Note
110  // this often does not matter since many scenario start with messages,
111  // which will usually scroll to the speaker. Also note that the map
112  // does not necessarily define the starting positions. While usually
113  // best to use the map, the scenarion may explicitly set the positions,
114  // overriding those found in the map (if any).
115  if(map_start_.valid())
116  {
117  gui_->scroll_to_tile(map_start_, game_display::WARP, false);
118  LOG_NG << "Found good stored ui location " << map_start_ << "\n";
119  }
120  else
121  {
122  int scroll_team = gamestate().first_human_team_ + 1;
123  if (scroll_team == 0) {
124  scroll_team = 1;
125  }
126  map_location loc(gamestate().board_.map().starting_position(scroll_team));
127  if ((loc.x >= 0) && (loc.y >= 0)) {
128  gui_->scroll_to_tile(loc, game_display::WARP);
129  LOG_NG << "Found bad stored ui location " << map_start_ << " using side starting location " << loc << "\n";
130  }
131  else {
132  LOG_NG << "Found bad stored ui location\n";
133  }
134  }
135 
136  update_locker lock_display(gui_->video(), is_skipping_replay());
138 }
139 
140 
142 {
143  // At the beginning of the scenario, save a snapshot as replay_start
146  }
147  start_game();
149  // This won't cause errors later but we should notify the user about it in case he didn't knew it.
151  // TODO: find a better title
152  _("Game Error"),
153  _("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.")
154  );
155  }
156  return;
157 }
158 
160 {
161  LOG_NG << "starting main loop\n" << (SDL_GetTicks() - ticks()) << "\n";
162 
164  if(gamestate().board_.teams().empty())
165  {
166  ERR_NG << "Playing game with 0 teams." << std::endl;
167  }
168  while(true) {
169  try {
170  play_turn();
171  if (is_regular_game_end()) {
173  return;
174  }
175  }
176  catch(const reset_gamestate_exception& ex) {
177  //
178  // TODO:
179  //
180  // The MP replay feature still doesn't work properly (causes OOS)
181  // because:
182  //
183  // 1) The undo stack is not reset along with the gamestate (fixed).
184  // 2) The server_request_number_ is not reset along with the
185  // gamestate (fixed).
186  // 3) chat and other unsynced actions are inserted in the middle of
187  // the replay bringing the replay_pos in unorder (fixed).
188  // 4) untracked changes in side controllers are lost when resetting
189  // gamestate (fixed).
190  // 5) The game should have a stricter check for whether the loaded
191  // game is actually a parent of this game.
192  // 6) If an action was undone after a game was saved it can cause
193  // OOS if the undone action is in the snapshot of the saved
194  // game (luckily this is never the case for autosaves).
195  //
196  boost::dynamic_bitset<> local_players;
197  local_players.resize(gamestate().board_.teams().size(), true);
198  //Preserve side controllers, because we won't get the side controoller updates again when replaying.
199  for(std::size_t i = 0; i < local_players.size(); ++i) {
200  local_players[i] = gamestate().board_.teams()[i].is_local();
201  }
202  if(ex.start_replay) {
203  // MP "Back to turn"
205  } else {
206  // SP replay
208  }
209  reset_gamestate(*ex.level, (*ex.level)["replay_pos"]);
210  for(std::size_t i = 0; i < local_players.size(); ++i) {
211  resources::gameboard->teams()[i].set_local(local_players[i]);
212  }
214  if (replay_controller_ == nullptr) {
215  replay_controller_.reset(new replay_controller(*this, false, ex.level, [this](){ on_replay_end(false); } ));
216  }
217  if(ex.start_replay) {
218  replay_controller_->play_replay();
219  }
220  }
221  } //end for loop
222 }
223 
225 {
226  LOG_NG << "in playsingle_controller::play_scenario()...\n";
227 
228  // Start music.
229  for(const config &m : level.child_range("music")) {
230  sound::play_music_config(m, true);
231  }
233 
234  if(!this->is_skipping_replay() && !this->is_skipping_story()) {
235  // Combine all the [story] tags into a single config. Handle this here since
236  // storyscreen::controller doesn't have a default constructor.
237  config cfg;
238  for(const auto& iter : level.child_range("story")) {
239  cfg.append_children(iter);
240  }
241 
242  if(!cfg.empty()) {
244  }
245  }
246  gui_->labels().read(level);
247 
248  // Read sound sources
249  assert(soundsources_manager_ != nullptr);
250  for (const config &s : level.child_range("sound_source")) {
251  try {
253  soundsources_manager_->add(spec);
254  } catch (const bad_lexical_cast &) {
255  ERR_NG << "Error when parsing sound_source config: bad lexical cast." << std::endl;
256  ERR_NG << "sound_source config was: " << s.debug() << std::endl;
257  ERR_NG << "Skipping this sound source..." << std::endl;
258  }
259  }
260  LOG_NG << "entering try... " << (SDL_GetTicks() - ticks()) << "\n";
261  try {
263  // clears level config;
265 
266  if (!is_regular_game_end() && !linger_) {
268  }
270  exit(0);
271  }
272  const bool is_victory = get_end_level_data_const().is_victory;
273 
274  if(gamestate().gamedata_.phase() <= game_data::PRESTART) {
275  gui_->video().clear_screen();
276  }
277 
279 
280  const end_level_data& end_level = get_end_level_data_const();
281 
282  if (gamestate().board_.teams().empty())
283  {
284  //store persistent teams
286 
287  return LEVEL_RESULT::VICTORY; // this is probably only a story scenario, i.e. has its endlevel in the prestart event
288  }
289  if(linger_) {
290  LOG_NG << "resuming from loaded linger state...\n";
291  //as carryover information is stored in the snapshot, we have to re-store it after loading a linger state
293  if(!is_observer()) {
295  }
296  return LEVEL_RESULT::VICTORY;
297  }
298  pump().fire(is_victory ? "local_victory" : "local_defeat");
299  { // Block for set_scontext_synced_base
301  pump().fire(end_level.proceed_to_next_level ? "victory" : "defeat");
302  pump().fire("scenario_end");
303  }
304  if(end_level.proceed_to_next_level) {
306  }
307  if(is_observer()) {
308  gui2::show_transient_message(_("Game Over"), _("The game is over."));
309  return LEVEL_RESULT::OBSERVER_END;
310  }
311  // If we're a player, and the result is victory/defeat, then send
312  // a message to notify the server of the reason for the game ending.
314  "info", config {
315  "type", "termination",
316  "condition", "game over",
317  "result", is_victory ? "victory" : "defeat",
318  },
319  });
320  // Play victory music once all victory events
321  // are finished, if we aren't observers and the
322  // carryover dialog isn't disabled.
323  //
324  // Some scenario authors may use 'continue'
325  // result for something that is not story-wise
326  // a victory, so let them use [music] tags
327  // instead should they want special music.
328  const std::string& end_music = select_music(is_victory);
329  if((!is_victory || end_level.transient.carryover_report) && !end_music.empty()) {
331  sound::play_music_once(end_music);
332  }
334  LEVEL_RESULT res = LEVEL_RESULT::string_to_enum(end_level.test_result);
335  if(res == LEVEL_RESULT::TEST_NOT_SET) {
336  return is_victory ? LEVEL_RESULT::VICTORY : LEVEL_RESULT::DEFEAT;
337  } else {
338  return res;
339  }
340  } catch(const savegame::load_game_exception &) {
341  // Loading a new game is effectively a quit.
342  saved_game_.clear();
343  throw;
344  } catch(const wesnothd_error& e) {
345  scoped_savegame_snapshot snapshot(*this);
347  if(e.message == "") {
348  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);
349  } else {
350  save.save_game_interactive(_("This game has been ended.\nReason: ")+e.message+_("\nDo you want to save the game?"), savegame::savegame::YES_NO);
351  }
352  if(dynamic_cast<const ingame_wesnothd_error*>(&e)) {
353  return LEVEL_RESULT::QUIT;
354  } else {
355  throw;
356  }
357  }
358 }
359 
361 {
362  while(!should_return_to_play_side()) {
364  SDL_Delay(10);
365  }
366 }
367 
369 {
370  if (!skip_next_turn_) {
372  }
373  if(replay_controller_.get() != nullptr) {
374  init_side_done_now_ = false;
375  REPLAY_RETURN res = replay_controller_->play_side_impl();
376  if(res == REPLAY_FOUND_END_TURN) {
378  }
379  if (player_type_changed_) {
380  replay_controller_.reset();
381  }
382  } else if((current_team().is_local_human() && current_team().is_proxy_human())) {
383  LOG_NG << "is human...\n";
384  // If a side is dead end the turn, but play at least side=1's
385  // turn in case all sides are dead
386  if (gamestate().board_.side_units(current_side()) == 0 && !(gamestate().board_.units().empty() && current_side() == 1)) {
388  }
389 
391  if (end_turn_ == END_TURN_NONE) {
392  play_human_turn();
393  }
396  }
397  LOG_NG << "human finished turn...\n";
398 
399  } else if(current_team().is_local_ai() || (current_team().is_local_human() && current_team().is_droid())) {
400  play_ai_turn();
401  } else if(current_team().is_network()) {
403  } else if(current_team().is_local_human() && current_team().is_idle()) {
404  end_turn_enable(false);
407  if (end_turn_ == END_TURN_NONE) {
408  play_idle_loop();
409  }
410  }
411  else {
412  // we should have skipped over empty controllers before so this shouldn't be possible
413  ERR_NG << "Found invalid side controller " << current_team().controller().to_string() << " (" << current_team().proxy_controller().to_string() << ") for side " << current_team().side() << "\n";
414  }
415 }
416 
418 {
419  log_scope("player turn");
420  assert(!linger_);
422  return;
423  }
424 
426  scoped_savegame_snapshot snapshot(*this);
429  }
430 
431  if(preferences::turn_bell()) {
433  }
434 }
435 
438  blindfold b(*gui_, true); //apply a blindfold for the duration of this dialog
439  gui_->redraw_everything();
440  gui_->recalculate_minimap();
441  std::string message = _("It is now $name|’s turn");
442  utils::string_map symbols;
443  symbols["name"] = gamestate().board_.get_team(current_side()).side_name();
444  message = utils::interpolate_variables_into_string(message, &symbols);
445  gui2::show_transient_message("", message);
446  }
447 }
448 
450 {
452  {
453  return;
454  }
455  try
456  {
458  }
459  catch (const return_to_play_side_exception&)
460  {
461  }
462 }
463 
466 
468  execute_gotos();
469  }
470 
471  end_turn_enable(true);
472  while(!should_return_to_play_side()) {
475  }
476 
477 }
478 
480 {
481  LOG_NG << "beginning end-of-scenario linger\n";
482  linger_ = true;
483 
484  // If we need to set the status depending on the completion state
485  // the key to it is here.
486  gui_->set_game_mode(game_display::LINGER);
487 
488  // Make all of the able-to-move units' orbs consistently red
490 
491  // change the end-turn button text to its alternate label
492  gui_->get_theme().refresh_title2("button-endturn", "title2");
493  gui_->invalidate_theme();
494  gui_->redraw_everything();
495 
496  try {
497  // Same logic as single-player human turn, but
498  // *not* the same as multiplayer human turn.
499  end_turn_enable(true);
501  while(end_turn_ == END_TURN_NONE) {
502  play_slice();
503  }
504  } catch(const savegame::load_game_exception &) {
505  // Loading a new game is effectively a quit.
506  saved_game_.clear();
507  throw;
508  }
509 
510  // revert the end-turn button text to its normal label
511  gui_->get_theme().refresh_title2("button-endturn", "title");
512  gui_->invalidate_theme();
513  gui_->redraw_everything();
514  gui_->set_game_mode(game_display::RUNNING);
515 
516  LOG_NG << "ending end-of-scenario linger\n";
517 }
518 
520 {
521  gui_->enable_menu("endturn", enable);
523 }
524 
525 
527 {
528  // Clear moves from the GUI.
529  gui_->set_route(nullptr);
530  gui_->unhighlight_reach();
531 }
532 
534 {
535  LOG_NG << "is ai...\n";
536 
537  end_turn_enable(false);
538  gui_->recalculate_minimap();
539 
540  const cursor::setter cursor_setter(cursor::WAIT);
541 
542  // Correct an oddball case where a human could have left delayed shroud
543  // updates on before giving control to the AI. (The AI does not bother
544  // with the undo stack, so it cannot delay shroud updates.)
545  team & cur_team = current_team();
546  if ( !cur_team.auto_shroud_updates() ) {
547  // We just took control, so the undo stack is empty. We still need
548  // to record this change for the replay though.
550  }
551  undo_stack().clear();
552 
554  try {
555  try {
558  }
559  }
560  catch (const return_to_play_side_exception&) {
561  }
562  catch (const fallback_ai_to_human_exception&) {
564  player_type_changed_ = true;
565  ai_fallback_ = true;
566  }
567  }
568  catch(...) {
570  throw;
571  }
574  }
576  gui_->recalculate_minimap();
577  gui_->invalidate_unit();
578  gui_->invalidate_game_status();
579  gui_->invalidate_all();
580 }
581 
582 
583 /**
584  * Will handle sending a networked notification in descendent classes.
585  */
587 {
588  gui_->get_chat_manager().add_chat_message(std::time(nullptr), "Wesnoth", 0,
589  "This side is in an idle state. To proceed with the game, the host must assign it to another controller.",
591 }
592 
593 /**
594  * Will handle networked turns in descendent classes.
595  */
597 {
598  // There should be no networked sides in single-player.
599  ERR_NG << "Networked team encountered by playsingle_controller." << std::endl;
600 }
601 
602 
604  if (name == "ai_user_interact"){
605  play_slice(false);
606  }
607 }
608 
609 
610 
612  if (linger_)
614  else if (!is_browsing() && menu_handler_.end_turn(current_side())){
616  }
617 }
618 
620  skip_next_turn_ = true;
622 }
623 
625 {
626  if (!gamestate().board_.teams().empty()) {
627  const team &t = gamestate().board_.teams()[gui_->viewing_team()];
628 
629  if (!is_regular_game_end() && !is_browsing() && t.objectives_changed()) {
630  show_objectives();
631  }
632  }
633 }
634 
635 
637 {
638  // mouse_handler expects at least one team for linger mode to work.
639  assert(is_regular_game_end());
640  if (get_end_level_data_const().transient.linger_mode && !gamestate().board_.teams().empty()) {
641  linger();
642  }
643 }
644 
646 {
647  //We cannot add [end_turn] to the recorder while executing another action.
649  if(end_turn_ == END_TURN_REQUIRED && current_team().is_local())
650  {
651  //TODO: we should also send this immediately.
652  resources::recorder->end_turn(gamestate_->next_player_number_);
654  }
655 
656  assert(end_turn_ == END_TURN_SYNCED);
657  skip_next_turn_ = false;
658 
659  if(ai_fallback_) {
660  current_team().make_ai();
661  ai_fallback_ = false;
662  }
663 }
664 
666 {
667  if(replay_controller_ && replay_controller_->is_controlling_view()) {
668  replay_controller_->update_viewing_player();
669  }
670  //Update viewing team in case it has changed during the loop.
671  else if(int side_num = play_controller::find_last_visible_team()) {
672  if(side_num != this->gui_->viewing_side()) {
673  update_gui_to_player(side_num - 1);
674  }
675  }
676 }
677 
679 {
680  if(replay_controller_ && replay_controller_->allow_reset_replay()) {
681  replay_controller_->stop_replay();
682  throw reset_gamestate_exception(replay_controller_->get_reset_state(), {}, false);
683  }
684  else {
685  ERR_NG << "received invalid reset replay\n";
686  }
687 }
688 
690 {
691  replay_controller_.reset(new replay_controller(*this, gamestate().has_human_sides(), std::shared_ptr<config>( new config(saved_game_.get_replay_starting_point())), std::bind(&playsingle_controller::on_replay_end, this, is_unit_test)));
692  if(is_unit_test) {
693  replay_controller_->play_replay();
694  }
695 }
696 
698 {
700  return true;
701  }
702  else if (end_turn_ == END_TURN_NONE || replay_controller_.get() != 0 || current_team().is_network()) {
703  return false;
704  }
705  else {
706  return true;
707  }
708 }
709 
711 {
712  if(is_networked_mp()) {
714  }
715  else if(is_unit_test) {
716  replay_controller_->return_to_play_side();
717  if(!is_regular_game_end()) {
719  e.proceed_to_next_level = false;
720  e.is_victory = false;
722  }
723  }
724 }
bool disable_auto_moves()
Definition: general.cpp:918
void empty_playlist()
Definition: sound.cpp:611
void end_turn(int next_player_number)
Definition: replay.cpp:301
void clear()
Clears the stack of undoable (and redoable) actions.
Definition: undo.cpp:220
void set_all_units_user_end_turn()
Definition: game_board.cpp:80
An error occurred during when trying to coommunicate with the wesnothd server.
static lg::log_domain log_aitesting("ai/testing")
int autosavemax()
Definition: game.cpp:822
std::unique_ptr< soundsource::manager > soundsources_manager_
bool turn_bell()
Definition: general.cpp:614
static void display(const std::string &scenario_name, const config &story)
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 &#39;$&#39; in the string &#39;str&#39; with the equivalent ...
virtual const std::vector< team > & teams() const override
Definition: game_board.hpp:92
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
int find_last_visible_team() const
returns 0 if no such team was found.
std::unique_ptr< game_display > gui_
events::mouse_handler mouse_handler_
static manager & get_singleton()
Definition: manager.hpp:151
std::unique_ptr< plugins_context > plugins_context_
bool is_network() const
Definition: team.hpp:262
config & replay_start()
Definition: saved_game.hpp:111
bool is_skipping_replay() const
const std::string & side_name() const
Definition: team.hpp:308
virtual void play_side_impl() override
Class for autosaves.
Definition: savegame.hpp:289
game_events::wml_event_pump & pump()
const int INFINITE_AUTO_SAVES
Definition: game.hpp:189
std::unique_ptr< hotkey_handler > hotkey_handler_
int first_human_team_
Definition: game_state.hpp:72
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.
bool objectives_changed() const
Definition: team.hpp:241
PROCESS_DATA_RESULT sync_network()
Definition: playturn.cpp:61
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].
playsingle_controller(const config &level, saved_game &state_of_game, const ter_data_cache &tdata, bool skip_replay)
void clear()
Definition: saved_game.cpp:793
void enable_replay(bool is_unit_test=false)
virtual void play_slice(bool is_delay_enabled=true)
Class for "normal" midgame saves.
Definition: savegame.hpp:262
config & set_snapshot(config snapshot)
Definition: saved_game.cpp:559
void play_music_once(const std::string &file)
Definition: sound.cpp:602
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:373
const end_level_data & get_end_level_data_const() const
persist_manager persist_
void reset_current_scenario()
Reset the stats of the current scenario to the beginning.
Definition: statistics.cpp:794
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:273
std::unique_ptr< game_state > gamestate_
REPLAY_RETURN
Definition: replay.hpp:153
-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 &#39;side&#39; (in game nomenclature).
Definition: team.hpp:44
bool end_turn(int side_num)
virtual void check_objectives() override
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:100
virtual bool should_return_to_play_side() const override
team & get_team(int i)
Definition: game_board.hpp:104
std::string test_result
result to use if this is a unit test
bool disable_autosave
config to_config() const
Builds the snapshot config from members and their respective configs.
bool valid() const
Definition: location.hpp:93
game_board * gameboard
Definition: resources.cpp:20
bool is_regular_game_end() const
std::shared_ptr< config > stats_
virtual void init_gui()
void read_stats(const config &cfg)
Definition: statistics.cpp:770
std::string describe_result() const
Managing the AIs lifecycle - headers TODO: Refactor history handling and internal commands...
#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:736
static lg::log_domain log_enginerefac("enginerefac")
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:296
virtual void play_network_turn()
Will handle networked turns in descendent classes.
static void log_game_start()
Definition: testing.cpp:90
LEVEL_RESULT play_scenario(const config &level)
bool is_browsing() const override
bool is_observer() const
void update_gui_to_player(const int team_index, const bool observe=false)
Changes the UI for this client to the passed side index.
Encapsulates the map of the game.
Definition: location.hpp:42
void on_replay_end(bool is_unit_test)
bool auto_shroud_updates() const
Definition: team.hpp:338
void make_ai()
Definition: team.hpp:274
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:93
transient_end_level transient
virtual bool is_networked_mp() const
const config & get_replay_starting_point()
Definition: saved_game.cpp:588
std::size_t i
Definition: function.cpp:933
const std::string & select_music(bool victory) const
map_location map_start_
void execute_gotos(mouse_handler &mousehandler, int side_num)
#define ERR_NG
static map_location::DIRECTION s
std::unique_ptr< replay_controller > replay_controller_
void reset_gamestate(const config &level, int replay_pos)
std::string name
Definition: sdl_ttf.cpp:70
Define the game&#39;s event mechanism.
#define log_scope(description)
Definition: log.hpp:208
bool empty() const
Definition: map.hpp:446
bool proceed_to_next_level
whether to proceed to the next scenario, equals is_victory in sp.
t_string get_scenario_name() const
Additional information on the game outcome which can be provided by WML.
actions::undo_list & undo_stack()
static void save(LexState *ls, int c)
Definition: llex.cpp:57
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
virtual bool receive_from_wesnothd(config &) const
void update_viewing_player() override
compression::format save_compression_format()
Definition: game.cpp:874
void play_bell(const std::string &files)
Definition: sound.cpp:1035
game_state & gamestate()
double t
Definition: astarsearch.cpp:64
playturn_network_adapter network_reader_
void play_music_config(const config &music_node, bool allow_interrupt_current_track, int i)
Definition: sound.cpp:704
game_classification & classification()
Definition: saved_game.hpp:55
PROXY_CONTROLLER proxy_controller() const
Definition: team.hpp:282
game_board board_
Definition: game_state.hpp:46
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:593
int current_side() const
Returns the number of the side whose turn it is.
bool is_skipping_story() const
replay_network_sender replay_sender_
std::string message
Definition: exceptions.hpp:31
std::shared_ptr< config > level
#define e
std::size_t turn() const
void commit_music_changes()
Definition: sound.cpp:822
void remove_snapshot()
Definition: saved_game.cpp:577
int side() const
Definition: team.hpp:188
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:68
static lg::log_domain log_engine("engine")
bool turn_dialog()
Definition: game.cpp:442
Thrown when a lexical_cast fails.
bool empty() const
Definition: config.cpp:884
virtual void send_to_wesnothd(const config &, const std::string &="unknown") const
virtual void handle_generic_event(const std::string &name) override
An [end_turn] was added to the replay.
void show_objectives() const
bool init_side_done_now_
Whether we did init sides in this session (false = we did init sides before we reloaded the game)...
CONTROLLER controller() const
Definition: team.hpp:255
std::shared_ptr< terrain_type_data > ter_data_cache