The Battle for Wesnoth  1.15.13+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 "events.hpp"
28 #include "formula/string_utils.hpp"
29 #include "game_end_exceptions.hpp"
30 #include "game_events/pump.hpp"
31 #include "gettext.hpp"
35 #include "hotkey/hotkey_item.hpp"
36 #include "log.hpp"
37 #include "map/label.hpp"
38 #include "map/map.hpp"
39 #include "playturn.hpp"
40 #include "preferences/game.hpp"
41 #include "random_deterministic.hpp"
42 #include "replay_helper.hpp"
43 #include "resources.hpp"
44 #include "savegame.hpp"
46 #include "sound.hpp"
47 #include "soundsource.hpp"
48 #include "statistics.hpp"
49 #include "synced_context.hpp"
50 #include "units/unit.hpp"
52 #include "whiteboard/manager.hpp"
53 
54 #include <boost/dynamic_bitset.hpp>
55 
56 static lg::log_domain log_aitesting("ai/testing");
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 
67 playsingle_controller::playsingle_controller(const config& level, saved_game& state_of_game, bool skip_replay)
68  : play_controller(level, state_of_game, 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  // upgrade hotkey handler to the sp (whiteboard enabled) version
80  hotkey_handler_ = std::make_unique<hotkey_handler>(*this, saved_game_);
81 
82  // game may need to start in linger mode
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  } else if(get_end_level_data().is_victory) {
94  return "VICTORY";
95  } else {
96  return "DEFEAT";
97  }
98 }
99 
101 {
102  LOG_NG << "Initializing GUI... " << (SDL_GetTicks() - ticks()) << "\n";
104 
105  // Scroll to the starting position of the first team. If there is a
106  // human team, use that team; otherwise use team 1. If the map defines
107  // a starting position for the selected team, scroll to that tile. Note
108  // this often does not matter since many scenario start with messages,
109  // which will usually scroll to the speaker. Also note that the map
110  // does not necessarily define the starting positions. While usually
111  // best to use the map, the scenarion may explicitly set the positions,
112  // overriding those found in the map (if any).
113  if(map_start_.valid()) {
114  gui_->scroll_to_tile(map_start_, game_display::WARP, false);
115  LOG_NG << "Found good stored ui location " << map_start_ << "\n";
116  } else {
117  int scroll_team = gamestate().first_human_team_ + 1;
118  if(scroll_team == 0) {
119  scroll_team = 1;
120  }
121 
122  map_location loc(get_map().starting_position(scroll_team));
123  if((loc.x >= 0) && (loc.y >= 0)) {
124  gui_->scroll_to_tile(loc, game_display::WARP);
125  LOG_NG << "Found bad stored ui location " << map_start_ << " using side starting location " << loc << "\n";
126  } else {
127  LOG_NG << "Found bad stored ui location\n";
128  }
129  }
130 
131  update_locker lock_display(gui_->video(), is_skipping_replay());
133 }
134 
136 {
137  // At the beginning of the scenario, save a snapshot as replay_start
138  if(saved_game_.replay_start().empty()) {
140  }
141 
142  start_game();
143 
145  // This won't cause errors later but we should notify the user about it in case he didn't knew it.
147  // TODO: find a better title
148  _("Game Error"),
149  _("This multiplayer game uses an alternative random mode, if you don't know what this message means, then "
150  "most likely someone is cheating or someone reloaded a corrupt game."));
151  }
152 
153  return;
154 }
155 
157 {
158  LOG_NG << "starting main loop\n" << (SDL_GetTicks() - ticks()) << "\n";
159 
161  if(get_teams().empty()) {
162  ERR_NG << "Playing game with 0 teams." << std::endl;
163  }
164 
165  while(true) {
166  try {
167  play_turn();
168  if(is_regular_game_end()) {
170  return;
171  }
172  } catch(const reset_gamestate_exception& ex) {
173  //
174  // TODO:
175  //
176  // The MP replay feature still doesn't work properly (causes OOS)
177  // because:
178  //
179  // 1) The undo stack is not reset along with the gamestate (fixed).
180  // 2) The server_request_number_ is not reset along with the
181  // gamestate (fixed).
182  // 3) chat and other unsynced actions are inserted in the middle of
183  // the replay bringing the replay_pos in unorder (fixed).
184  // 4) untracked changes in side controllers are lost when resetting
185  // gamestate (fixed).
186  // 5) The game should have a stricter check for whether the loaded
187  // game is actually a parent of this game.
188  // 6) If an action was undone after a game was saved it can cause
189  // OOS if the undone action is in the snapshot of the saved
190  // game (luckily this is never the case for autosaves).
191  //
192  boost::dynamic_bitset<> local_players;
193  local_players.resize(get_teams().size(), true);
194  // Preserve side controllers, because we won't get the side controoller updates again when replaying.
195  for(std::size_t i = 0; i < local_players.size(); ++i) {
196  local_players[i] = get_teams()[i].is_local();
197  }
198 
199  if(ex.start_replay) {
200  // MP "Back to turn"
202  } else {
203  // SP replay
205  }
206 
207  reset_gamestate(*ex.level, (*ex.level)["replay_pos"]);
208 
209  for(std::size_t i = 0; i < local_players.size(); ++i) {
210  resources::gameboard->teams()[i].set_local(local_players[i]);
211  }
212 
214 
215  if(replay_controller_ == nullptr) {
216  replay_controller_ = std::make_unique<replay_controller>(*this, false, ex.level, [this]() { on_replay_end(false); });
217  }
218 
219  if(ex.start_replay) {
220  replay_controller_->play_replay();
221  }
222  }
223  } // end for loop
224 }
225 
227 {
228  LOG_NG << "in playsingle_controller::play_scenario()...\n";
229 
230  // Start music.
231  for(const config& m : level.child_range("music")) {
232  sound::play_music_config(m, true);
233  }
234 
236 
238  // Combine all the [story] tags into a single config. Handle this here since
239  // storyscreen::controller doesn't have a default constructor.
240  config cfg;
241  for(const auto& iter : level.child_range("story")) {
242  cfg.append_children(iter);
243  }
244 
245  if(!cfg.empty()) {
247  }
248  }
249 
250  gui_->labels().read(level);
251 
252  // Read sound sources
253  assert(soundsources_manager_ != nullptr);
254  for(const config& s : level.child_range("sound_source")) {
255  try {
257  soundsources_manager_->add(spec);
258  } catch(const bad_lexical_cast&) {
259  ERR_NG << "Error when parsing sound_source config: bad lexical cast." << std::endl;
260  ERR_NG << "sound_source config was: " << s.debug() << std::endl;
261  ERR_NG << "Skipping this sound source..." << std::endl;
262  }
263  }
264 
265  LOG_NG << "entering try... " << (SDL_GetTicks() - ticks()) << "\n";
266 
267  try {
269  // clears level config;
271 
272  if(!is_regular_game_end() && !linger_) {
274  }
275 
277  exit(0);
278  }
279  const bool is_victory = get_end_level_data().is_victory;
280 
281  if(gamestate().gamedata_.phase() <= game_data::PRESTART) {
282  gui_->video().clear_screen();
283  }
284 
286 
287  const end_level_data& end_level = get_end_level_data();
288 
289  if(get_teams().empty()) {
290  // store persistent teams
292 
293  // this is probably only a story scenario, i.e. has its endlevel in the prestart event
294  return LEVEL_RESULT::VICTORY;
295  }
296 
297  if(linger_) {
298  LOG_NG << "resuming from loaded linger state...\n";
299  // as carryover information is stored in the snapshot, we have to re-store it after loading a linger state
301  if(!is_observer()) {
303  }
304 
305  return LEVEL_RESULT::VICTORY;
306  }
307 
308  pump().fire(is_victory ? "local_victory" : "local_defeat");
309 
310  { // Block for set_scontext_synced_base
312  pump().fire(end_level.proceed_to_next_level ? "victory" : "defeat");
313  pump().fire("scenario_end");
314  }
315 
316  if(end_level.proceed_to_next_level) {
318  }
319 
320  if(is_observer()) {
321  gui2::show_transient_message(_("Game Over"), _("The game is over."));
322  return LEVEL_RESULT::OBSERVER_END;
323  }
324 
325  // If we're a player, and the result is victory/defeat, then send
326  // a message to notify the server of the reason for the game ending.
328  "info", config {
329  "type", "termination",
330  "condition", "game over",
331  "result", is_victory ? "victory" : "defeat",
332  },
333  });
334 
335  // Play victory music once all victory events
336  // are finished, if we aren't observers and the
337  // carryover dialog isn't disabled.
338  //
339  // Some scenario authors may use 'continue'
340  // result for something that is not story-wise
341  // a victory, so let them use [music] tags
342  // instead should they want special music.
343  const std::string& end_music = select_music(is_victory);
344  if((!is_victory || end_level.transient.carryover_report) && !end_music.empty()) {
346  sound::play_music_once(end_music);
347  }
348 
350 
351  LEVEL_RESULT res = LEVEL_RESULT::string_to_enum(end_level.test_result);
352  if(res == LEVEL_RESULT::TEST_NOT_SET) {
353  return is_victory ? LEVEL_RESULT::VICTORY : LEVEL_RESULT::DEFEAT;
354  } else {
355  return res;
356  }
357  } catch(const savegame::load_game_exception&) {
358  // Loading a new game is effectively a quit.
359  saved_game_.clear();
360  throw;
361  } catch(const wesnothd_error& e) {
362  scoped_savegame_snapshot snapshot(*this);
364  if(e.message == "") {
366  _("A network disconnection has occurred, and the game cannot continue. Do you want to save the game?"),
368  } else {
370  _("This game has been ended.\nReason: ") + e.message + _("\nDo you want to save the game?"),
372  }
373 
374  if(dynamic_cast<const ingame_wesnothd_error*>(&e)) {
375  return LEVEL_RESULT::QUIT;
376  } else {
377  throw;
378  }
379  }
380 }
381 
383 {
384  while(!should_return_to_play_side()) {
386  SDL_Delay(10);
387  }
388 }
389 
391 {
392  if(!skip_next_turn_) {
394  }
395 
396  if(replay_controller_.get() != nullptr) {
397  init_side_done_now_ = false;
398 
399  REPLAY_RETURN res = replay_controller_->play_side_impl();
400  if(res == REPLAY_FOUND_END_TURN) {
402  }
403 
405  replay_controller_.reset();
406  }
407  } else if((current_team().is_local_human() && current_team().is_proxy_human())) {
408  LOG_NG << "is human...\n";
409  // If a side is dead end the turn, but play at least side=1's
410  // turn in case all sides are dead
411  if(gamestate().board_.side_units(current_side()) == 0 && !(get_units().empty() && current_side() == 1)) {
413  }
414 
416 
417  if(end_turn_ == END_TURN_NONE) {
418  play_human_turn();
419  }
420 
423  }
424 
425  LOG_NG << "human finished turn...\n";
426  } else if(current_team().is_local_ai() || (current_team().is_local_human() && current_team().is_droid())) {
427  play_ai_turn();
428  } else if(current_team().is_network()) {
430  } else if(current_team().is_local_human() && current_team().is_idle()) {
431  end_turn_enable(false);
434 
435  if(end_turn_ == END_TURN_NONE) {
436  play_idle_loop();
437  }
438  } else {
439  // we should have skipped over empty controllers before so this shouldn't be possible
440  ERR_NG << "Found invalid side controller " << current_team().controller().to_string() << " ("
441  << current_team().proxy_controller().to_string() << ") for side " << current_team().side() << "\n";
442  }
443 }
444 
446 {
447  log_scope("player turn");
448  assert(!linger_);
450  return;
451  }
452 
454  scoped_savegame_snapshot snapshot(*this);
457  }
458 
459  if(preferences::turn_bell()) {
461  }
462 }
463 
465 {
467  blindfold b(*gui_, true); // apply a blindfold for the duration of this dialog
468  gui_->redraw_everything();
469  gui_->recalculate_minimap();
470  std::string message = _("It is now $name|’s turn");
471  utils::string_map symbols;
472  symbols["name"] = gamestate().board_.get_team(current_side()).side_name();
473  message = utils::interpolate_variables_into_string(message, &symbols);
474  gui2::show_transient_message("", message);
475  }
476 }
477 
479 {
481  return;
482  }
483 
484  try {
486  } catch(const return_to_play_side_exception&) {
487  }
488 }
489 
491 {
493 
495  execute_gotos();
496  }
497 
498  end_turn_enable(true);
499 
500  while(!should_return_to_play_side()) {
503  }
504 }
505 
507 {
508  LOG_NG << "beginning end-of-scenario linger\n";
509  linger_ = true;
510 
511  // If we need to set the status depending on the completion state
512  // the key to it is here.
513  gui_->set_game_mode(game_display::LINGER);
514 
515  // Make all of the able-to-move units' orbs consistently red
517 
518  // change the end-turn button text to its alternate label
519  gui_->get_theme().refresh_title2("button-endturn", "title2");
520  gui_->invalidate_theme();
521  gui_->redraw_everything();
522 
523  try {
524  // Same logic as single-player human turn, but
525  // *not* the same as multiplayer human turn.
526  end_turn_enable(true);
528  while(end_turn_ == END_TURN_NONE) {
529  play_slice();
530  }
531  } catch(const savegame::load_game_exception&) {
532  // Loading a new game is effectively a quit.
533  saved_game_.clear();
534  throw;
535  }
536 
537  // revert the end-turn button text to its normal label
538  gui_->get_theme().refresh_title2("button-endturn", "title");
539  gui_->invalidate_theme();
540  gui_->redraw_everything();
541  gui_->set_game_mode(game_display::RUNNING);
542 
543  LOG_NG << "ending end-of-scenario linger\n";
544 }
545 
547 {
548  gui_->enable_menu("endturn", enable);
550 }
551 
553 {
554  // Clear moves from the GUI.
555  gui_->set_route(nullptr);
556  gui_->unhighlight_reach();
557 }
558 
560 {
561  LOG_NG << "is ai...\n";
562 
563  end_turn_enable(false);
564  gui_->recalculate_minimap();
565 
566  const cursor::setter cursor_setter(cursor::WAIT);
567 
568  // Correct an oddball case where a human could have left delayed shroud
569  // updates on before giving control to the AI. (The AI does not bother
570  // with the undo stack, so it cannot delay shroud updates.)
571  team& cur_team = current_team();
572  if(!cur_team.auto_shroud_updates()) {
573  // We just took control, so the undo stack is empty. We still need
574  // to record this change for the replay though.
576  }
577 
578  undo_stack().clear();
580 
581  try {
582  try {
585  }
586  } catch(const return_to_play_side_exception&) {
587  } catch(const fallback_ai_to_human_exception&) {
589  player_type_changed_ = true;
590  ai_fallback_ = true;
591  }
592  } catch(...) {
594  throw;
595  }
596 
599  }
600 
602  gui_->recalculate_minimap();
603  gui_->invalidate_unit();
604  gui_->invalidate_game_status();
605  gui_->invalidate_all();
606 }
607 
608 /**
609  * Will handle sending a networked notification in descendent classes.
610  */
612 {
613  gui_->get_chat_manager().add_chat_message(std::time(nullptr), "Wesnoth", 0,
614  "This side is in an idle state. To proceed with the game, the host must assign it to another controller.",
616 }
617 
618 /**
619  * Will handle networked turns in descendent classes.
620  */
622 {
623  // There should be no networked sides in single-player.
624  ERR_NG << "Networked team encountered by playsingle_controller." << std::endl;
625 }
626 
627 void playsingle_controller::handle_generic_event(const std::string& name)
628 {
629  if(name == "ai_user_interact") {
630  play_slice(false);
631  }
632 }
633 
635 {
636  if(linger_) {
638  } else if(!is_browsing() && menu_handler_.end_turn(current_side())) {
640  }
641 }
642 
644 {
645  skip_next_turn_ = true;
647 }
648 
650 {
651  if(!get_teams().empty()) {
652  const team& t = get_teams()[gui_->viewing_team()];
653 
655  show_objectives();
656  }
657  }
658 }
659 
661 {
662  // mouse_handler expects at least one team for linger mode to work.
663  assert(is_regular_game_end());
664  if(get_end_level_data().transient.linger_mode && !get_teams().empty()) {
665  linger();
666  }
667 }
668 
670 {
671  // We cannot add [end_turn] to the recorder while executing another action.
673 
674  if(end_turn_ == END_TURN_REQUIRED && current_team().is_local()) {
675  // TODO: we should also send this immediately.
676  resources::recorder->end_turn(gamestate_->next_player_number_);
678  }
679 
680  assert(end_turn_ == END_TURN_SYNCED);
681  skip_next_turn_ = false;
682 
683  if(ai_fallback_) {
684  current_team().make_ai();
685  ai_fallback_ = false;
686  }
687 }
688 
690 {
691  if(replay_controller_ && replay_controller_->is_controlling_view()) {
692  replay_controller_->update_viewing_player();
693  } else if(int side_num = play_controller::find_last_visible_team()) {
694  // Update viewing team in case it has changed during the loop.
695  if(side_num != gui_->viewing_side()) {
696  update_gui_to_player(side_num - 1);
697  }
698  }
699 }
700 
702 {
703  if(replay_controller_ && replay_controller_->allow_reset_replay()) {
704  replay_controller_->stop_replay();
705  throw reset_gamestate_exception(replay_controller_->get_reset_state(), {}, false);
706  } else {
707  ERR_NG << "received invalid reset replay\n";
708  }
709 }
710 
712 {
713  replay_controller_ = std::make_unique<replay_controller>(
714  *this,
716  std::make_shared<config>(saved_game_.get_replay_starting_point()),
717  std::bind(&playsingle_controller::on_replay_end, this, is_unit_test)
718  );
719 
720  if(is_unit_test) {
721  replay_controller_->play_replay();
722  }
723 }
724 
726 {
728  return true;
729  } else if(end_turn_ == END_TURN_NONE || replay_controller_.get() != 0 || current_team().is_network()) {
730  return false;
731  } else {
732  return true;
733  }
734 }
735 
737 {
738  if(is_networked_mp()) {
740  } else if(is_unit_test) {
741  replay_controller_->return_to_play_side();
742  if(!is_regular_game_end()) {
744  e.proceed_to_next_level = false;
745  e.is_victory = false;
747  }
748  }
749 }
bool disable_auto_moves()
Definition: general.cpp:933
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:85
An error occurred during when trying to communicate with the wesnothd server.
static lg::log_domain log_aitesting("ai/testing")
int autosavemax()
Definition: game.cpp:799
std::unique_ptr< soundsource::manager > soundsources_manager_
bool turn_bell()
Definition: general.cpp:629
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:84
void heal_all_survivors()
Definition: game_board.cpp:92
std::map< std::string, t_string > string_map
int find_last_visible_team() const
returns 0 if no such team was found.
std::unique_ptr< game_display > gui_
const unit_map & get_units() const
events::mouse_handler mouse_handler_
static manager & get_singleton()
Definition: manager.hpp:143
std::unique_ptr< plugins_context > plugins_context_
bool is_network() const
Definition: team.hpp:270
config & replay_start()
Definition: saved_game.hpp:122
bool is_skipping_replay() const
const std::string & side_name() const
Definition: team.hpp:316
Exception used to escape form the ai or ui code to playsingle_controller::play_side.
virtual void play_side_impl() override
Class for autosaves.
Definition: savegame.hpp:279
game_events::wml_event_pump & pump()
const int INFINITE_AUTO_SAVES
Definition: game.hpp:206
std::unique_ptr< hotkey_handler > hotkey_handler_
int first_human_team_
Definition: game_state.hpp:74
child_itors child_range(config_key_type key)
Definition: config.cpp:356
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:249
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].
void clear()
Definition: saved_game.cpp:791
void enable_replay(bool is_unit_test=false)
virtual void play_slice(bool is_delay_enabled=true)
const gamemap & get_map() const
Class for "normal" midgame saves.
Definition: savegame.hpp:252
config & set_snapshot(config snapshot)
Definition: saved_game.cpp:557
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:235
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:384
static std::string _(const char *str)
Definition: gettext.hpp:92
persist_manager persist_
void reset_current_scenario()
Reset the stats of the current scenario to the beginning.
Definition: statistics.cpp:796
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.
playsingle_controller(const config &level, saved_game &state_of_game, bool skip_replay)
#define b
void make_human()
Definition: team.hpp:281
std::unique_ptr< game_state > gamestate_
REPLAY_RETURN
Definition: replay.hpp:155
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
virtual bool should_return_to_play_side() const override
team & get_team(int i)
Definition: game_board.hpp:96
std::size_t size(const std::string &str)
Length in characters of a UTF-8 string.
Definition: unicode.cpp:86
std::string test_result
result to use if this is a unit test
bool disable_autosave
bool has_human_sides() const
Definition: game_state.hpp:75
config to_config() const
Builds the snapshot config from members and their respective configs.
bool valid() const
Definition: location.hpp:88
game_board * gameboard
Definition: resources.cpp:20
bool is_regular_game_end() const
std::vector< team > & get_teams()
std::shared_ptr< config > stats_
virtual void init_gui()
void read_stats(const config &cfg)
Definition: statistics.cpp:772
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:693
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:37
void on_replay_end(bool is_unit_test)
bool auto_shroud_updates() const
Definition: team.hpp:346
void make_ai()
Definition: team.hpp:282
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:83
transient_end_level transient
virtual bool is_networked_mp() const
const config & get_replay_starting_point()
Definition: saved_game.cpp:586
std::size_t i
Definition: function.cpp:940
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)
Define the game&#39;s event mechanism.
#define log_scope(description)
Definition: log.hpp:206
bool empty() const
Definition: map.hpp:445
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()
const end_level_data & get_end_level_data() const
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:851
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:54
PROXY_CONTROLLER proxy_controller() const
Definition: team.hpp:290
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:609
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:29
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:575
int side() const
Definition: team.hpp:196
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:59
static lg::log_domain log_engine("engine")
bool turn_dialog()
Definition: game.cpp:424
Thrown when a lexical_cast fails.
bool empty() const
Definition: config.cpp:916
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:263