The Battle for Wesnoth  1.15.0-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 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 "ogl/utils.hpp"
38 #include "playturn.hpp"
39 #include "random_deterministic.hpp"
40 #include "replay_helper.hpp"
41 #include "resources.hpp"
42 #include "savegame.hpp"
43 #include "sound.hpp"
44 #include "synced_context.hpp"
45 #include "formula/string_utils.hpp"
46 #include "events.hpp"
47 #include "save_blocker.hpp"
49 #include "soundsource.hpp"
50 #include "statistics.hpp"
51 #include "units/unit.hpp"
53 #include "whiteboard/manager.hpp"
54 #include "hotkey/hotkey_item.hpp"
55 #include <boost/dynamic_bitset.hpp>
56 
57 static lg::log_domain log_aitesting("aitesting");
58 #define LOG_AIT LOG_STREAM(info, log_aitesting)
59 //If necessary, this define can be replaced with `#define LOG_AIT std::cout` to restore previous behavior
60 
61 static lg::log_domain log_engine("engine");
62 #define ERR_NG LOG_STREAM(err, log_engine)
63 #define LOG_NG LOG_STREAM(info, log_engine)
64 
65 static lg::log_domain log_enginerefac("enginerefac");
66 #define LOG_RG LOG_STREAM(info, log_enginerefac)
67 
69  saved_game& state_of_game,
70  const config& game_config, const ter_data_cache & tdata, bool skip_replay)
71  : play_controller(level, state_of_game, game_config, tdata, skip_replay)
72  , cursor_setter_(cursor::NORMAL)
73  , replay_sender_(*resources::recorder)
74  , network_reader_([this](config& cfg) {return receive_from_wesnothd(cfg);})
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 
87  plugins_context_->set_accessor_string("level_result", std::bind(&playsingle_controller::describe_result, this));
88  plugins_context_->set_accessor_int("turn", std::bind(&play_controller::turn, this));
89 }
90 
92 {
93  if(!is_regular_game_end()) {
94  return "NONE";
95  }
96  else if(get_end_level_data_const().is_victory){
97  return "VICTORY";
98  }
99  else {
100  return "DEFEAT";
101  }
102 }
103 
105 {
106  LOG_NG << "Initializing GUI... " << (SDL_GetTicks() - ticks()) << "\n";
108 
109  // Scroll to the starting position of the first team. If there is a
110  // human team, use that team; otherwise use team 1. If the map defines
111  // a starting position for the selected team, scroll to that tile. Note
112  // this often does not matter since many scenario start with messages,
113  // which will usually scroll to the speaker. Also note that the map
114  // does not necessarily define the starting positions. While usually
115  // best to use the map, the scenarion may explicitly set the positions,
116  // overriding those found in the map (if any).
117  if(map_start_.valid())
118  {
119  gui_->scroll_to_tile(map_start_, game_display::WARP, false);
120  LOG_NG << "Found good stored ui location " << map_start_ << "\n";
121  }
122  else
123  {
124  int scroll_team = gamestate().first_human_team_ + 1;
125  if (scroll_team == 0) {
126  scroll_team = 1;
127  }
128  map_location loc(gamestate().board_.map().starting_position(scroll_team));
129  if ((loc.x >= 0) && (loc.y >= 0)) {
130  gui_->scroll_to_tile(loc, game_display::WARP);
131  LOG_NG << "Found bad stored ui location " << map_start_ << " using side starting location " << loc << "\n";
132  }
133  else {
134  LOG_NG << "Found bad stored ui location\n";
135  }
136  }
137 
138  update_locker lock_display(gui_->video(), is_skipping_replay());
139 }
140 
141 
143 {
144  // At the beginning of the scenario, save a snapshot as replay_start
147  }
148  start_game();
150  // This won't cause errors later but we should notify the user about it in case he didn't knew it.
152  // TODO: find a better title
153  _("Game Error"),
154  _("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.")
155  );
156  }
157  return;
158 }
159 
161 {
162  LOG_NG << "starting main loop\n" << (SDL_GetTicks() - ticks()) << "\n";
163 
164 
165  // Avoid autosaving after loading, but still
166  // allow the first turn to have an autosave.
168  if(gamestate().board_.teams().empty())
169  {
170  ERR_NG << "Playing game with 0 teams." << std::endl;
171  }
172  while(true) {
173  try {
174  play_turn();
175  if (is_regular_game_end()) {
177  return;
178  }
179  }
180  catch(const reset_gamestate_exception& ex) {
181  //
182  // TODO:
183  //
184  // The MP replay feature still doesn't work properly (causes OOS)
185  // because:
186  //
187  // 1) The undo stack is not reset along with the gamestate (fixed).
188  // 2) The server_request_number_ is not reset along with the
189  // gamestate (fixed).
190  // 3) chat and other unsynced actions are inserted in the middle of
191  // the replay bringing the replay_pos in unorder (fixed).
192  // 4) untracked changes in side controllers are lost when resetting
193  // gamestate (fixed).
194  // 5) The game should have a stricter check for whether the loaded
195  // game is actually a parent of this game.
196  // 6) If an action was undone after a game was saved it can cause
197  // OOS if the undone action is in the snapshot of the saved
198  // game (luckily this is never the case for autosaves).
199  //
200  boost::dynamic_bitset<> local_players;
201  local_players.resize(gamestate().board_.teams().size(), true);
202  //Preserve side controllers, because we won't get the side controoller updates again when replaying.
203  for(std::size_t i = 0; i < local_players.size(); ++i) {
204  local_players[i] = gamestate().board_.teams()[i].is_local();
205  }
206  reset_gamestate(*ex.level, (*ex.level)["replay_pos"]);
207  for(std::size_t i = 0; i < local_players.size(); ++i) {
208  resources::gameboard->teams()[i].set_local(local_players[i]);
209  }
211  replay_.reset(new replay_controller(*this, false, ex.level));
212  if(ex.start_replay) {
213  replay_->play_replay();
214  }
215  }
216  } //end for loop
217 }
218 
220 {
221  LOG_NG << "in playsingle_controller::play_scenario()...\n";
222 
223  // Start music.
224  for(const config &m : level.child_range("music")) {
226  }
228 
229  if(!this->is_skipping_replay()) {
230  // Combine all the [story] tags into a single config. Handle this here since
231  // storyscreen::controller doesn't have a default constructor.
232  config cfg;
233  for(const auto& iter : level.child_range("story")) {
234  cfg.append_children(iter);
235  }
236 
237  if(!cfg.empty()) {
239  }
240  }
241 
242  gui_->labels().read(level);
243 
244  // Read sound sources
245  assert(soundsources_manager_ != nullptr);
246  for (const config &s : level.child_range("sound_source")) {
247  try {
249  soundsources_manager_->add(spec);
250  } catch (const bad_lexical_cast &) {
251  ERR_NG << "Error when parsing sound_source config: bad lexical cast." << std::endl;
252  ERR_NG << "sound_source config was: " << s.debug() << std::endl;
253  ERR_NG << "Skipping this sound source..." << std::endl;
254  }
255  }
256  LOG_NG << "entering try... " << (SDL_GetTicks() - ticks()) << "\n";
257  try {
259  // clears level config;
261 
262  if (!is_regular_game_end() && !linger_) {
264  }
266  exit(0);
267  }
268  const bool is_victory = get_end_level_data_const().is_victory;
269 
270  if(gamestate().gamedata_.phase() <= game_data::PRESTART) {
271 #ifdef USE_GL_RENDERING
272  gl::clear_screen();
273 #else
274  gui_->video().clear_screen();
275 #endif
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  return is_victory ? LEVEL_RESULT::VICTORY : LEVEL_RESULT::DEFEAT;
335  } catch(const savegame::load_game_exception &) {
336  // Loading a new game is effectively a quit.
337  saved_game_.clear();
338  throw;
339  } catch(const wesnothd_error& e) {
340 
341  scoped_savegame_snapshot snapshot(*this);
343  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);
344  if(dynamic_cast<const ingame_wesnothd_error*>(&e)) {
345  return LEVEL_RESULT::QUIT;
346  } else {
347  throw;
348  }
349  }
350 }
351 
353 {
354  while(!should_return_to_play_side()) {
356  SDL_Delay(10);
357  }
358 }
359 
361 {
362  if (!skip_next_turn_) {
364  }
365  if(replay_.get() != nullptr) {
366  REPLAY_RETURN res = replay_->play_side_impl();
367  if(res == REPLAY_FOUND_END_TURN) {
369  }
370  if (player_type_changed_) {
371  replay_.reset();
372  }
373  } else if((current_team().is_local_human() && current_team().is_proxy_human())) {
374  LOG_NG << "is human...\n";
375  // If a side is dead end the turn, but play at least side=1's
376  // turn in case all sides are dead
377  if (gamestate().board_.side_units(current_side()) == 0 && !(gamestate().board_.units().empty() && current_side() == 1)) {
379  }
380 
382  if (end_turn_ == END_TURN_NONE) {
383  play_human_turn();
384  }
387  }
388  LOG_NG << "human finished turn...\n";
389 
390  } else if(current_team().is_local_ai() || (current_team().is_local_human() && current_team().is_droid())) {
391  play_ai_turn();
392  } else if(current_team().is_network()) {
394  } else if(current_team().is_local_human() && current_team().is_idle()) {
395  end_turn_enable(false);
398  if (end_turn_ == END_TURN_NONE) {
399  play_idle_loop();
400  }
401  }
402  else {
403  // we should have skipped over empty controllers before so this shouldn't be possible
404  ERR_NG << "Found invalid side controller " << current_team().controller().to_string() << " (" << current_team().proxy_controller().to_string() << ") for side " << current_team().side() << "\n";
405  }
406 }
407 
409 {
410  log_scope("player turn");
411  assert(!linger_);
413  return;
414  }
415 
416  if(init_side_done_now_) {
417  scoped_savegame_snapshot snapshot(*this);
420  }
421 
422  if(preferences::turn_bell()) {
424  }
425 }
426 
429  blindfold b(*gui_, true); //apply a blindfold for the duration of this dialog
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 
481  // End all unit moves
483  try {
484  // Same logic as single-player human turn, but
485  // *not* the same as multiplayer human turn.
486  end_turn_enable(true);
488  while(end_turn_ == END_TURN_NONE) {
489  play_slice();
490  }
491  } catch(const savegame::load_game_exception &) {
492  // Loading a new game is effectively a quit.
493  saved_game_.clear();
494  throw;
495  }
496 
497  // revert the end-turn button text to its normal label
498  gui_->get_theme().refresh_title2("button-endturn", "title");
499  gui_->set_game_mode(game_display::RUNNING);
500 
501  LOG_NG << "ending end-of-scenario linger\n";
502 }
503 
504 #if 0
506 {
507  //gui_->enable_menu("endturn", enable);
508 }
509 #else
511 #endif
512 
514 {
515  // Clear moves from the GUI.
516  gui_->set_route(nullptr);
517  gui_->unhighlight_reach();
518 }
519 
521 {
522  LOG_NG << "is ai...\n";
523 
524  end_turn_enable(false);
525  gui_->recalculate_minimap();
526 
527  const cursor::setter cursor_setter(cursor::WAIT);
528 
529  // Correct an oddball case where a human could have left delayed shroud
530  // updates on before giving control to the AI. (The AI does not bother
531  // with the undo stack, so it cannot delay shroud updates.)
532  team & cur_team = current_team();
533  if ( !cur_team.auto_shroud_updates() ) {
534  // We just took control, so the undo stack is empty. We still need
535  // to record this change for the replay though.
537  }
538  undo_stack().clear();
539 
541  try {
542  try {
545  }
546  }
547  catch (const return_to_play_side_exception&) {
548  }
549  catch (const fallback_ai_to_human_exception&) {
551  player_type_changed_ = true;
552  ai_fallback_ = true;
553  }
554  }
555  catch(...) {
557  throw;
558  }
561  }
563  gui_->recalculate_minimap();
564 }
565 
566 
567 /**
568  * Will handle sending a networked notification in descendent classes.
569  */
571 {
572  gui_->get_chat_manager().add_chat_message(std::time(nullptr), "Wesnoth", 0,
573  "This side is in an idle state. To proceed with the game, the host must assign it to another controller.",
575 }
576 
577 /**
578  * Will handle networked turns in descendent classes.
579  */
581 {
582  // There should be no networked sides in single-player.
583  ERR_NG << "Networked team encountered by playsingle_controller." << std::endl;
584 }
585 
586 
587 void playsingle_controller::handle_generic_event(const std::string& name){
588  if (name == "ai_user_interact"){
589  play_slice(false);
590  }
591 }
592 
593 
594 
596  if (linger_)
598  else if (!is_browsing() && menu_handler_.end_turn(current_side())){
600  }
601 }
602 
604  skip_next_turn_ = true;
606 }
607 
609 {
610  if (!gamestate().board_.teams().empty()) {
611  const team &t = gamestate().board_.teams()[gui_->viewing_team()];
612 
613  if (!is_regular_game_end() && !is_browsing() && t.objectives_changed()) {
614  show_objectives();
615  }
616  }
617 }
618 
619 
621 {
622  // mouse_handler expects at least one team for linger mode to work.
623  assert(is_regular_game_end());
624  if (get_end_level_data_const().transient.linger_mode && !gamestate().board_.teams().empty()) {
625  linger();
626  }
627 }
628 
630 {
631  //We cannot add [end_turn] to the recorder while executing another action.
633  if(end_turn_ == END_TURN_REQUIRED && current_team().is_local())
634  {
635  //TODO: we should also send this immediately.
636  resources::recorder->end_turn(gamestate_->next_player_number_);
638  }
639 
640  assert(end_turn_ == END_TURN_SYNCED);
641  skip_next_turn_ = false;
642 
643  if(ai_fallback_) {
644  current_team().make_ai();
645  ai_fallback_ = false;
646  }
647 }
648 
650 {
651  if(replay_ && replay_->is_controlling_view()) {
652  replay_->update_viewing_player();
653  }
654  //Update viewing team in case it has changed during the loop.
655  else if(int side_num = play_controller::find_last_visible_team()) {
656  if(side_num != this->gui_->viewing_side()) {
657  update_gui_to_player(side_num - 1);
658  }
659  }
660 }
661 
663 {
664  if(replay_ && replay_->allow_reset_replay()) {
665  replay_->stop_replay();
666  throw reset_gamestate_exception(replay_->get_reset_state(), false);
667  }
668  else {
669  ERR_NG << "received invalid reset replay\n";
670  }
671 }
672 
674 {
675  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)));
676  if(is_unit_test) {
677  replay_->play_replay();
678  }
679 }
680 
682 {
684  return true;
685  }
686  else if (end_turn_ == END_TURN_NONE || replay_.get() != 0 || current_team().is_network()) {
687  return false;
688  }
689  else {
690  return true;
691  }
692 }
693 
695 {
696  if(is_unit_test) {
697  replay_->return_to_play_side();
698  if(!is_regular_game_end()) {
700  e.proceed_to_next_level = false;
701  e.is_victory = false;
703  }
704  }
705 }
bool disable_auto_moves()
Definition: general.cpp:911
void empty_playlist()
Definition: sound.cpp:574
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.
int autosavemax()
Definition: game.cpp:809
std::unique_ptr< soundsource::manager > soundsources_manager_
bool turn_bell()
Definition: general.cpp:607
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)
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:152
std::unique_ptr< plugins_context > plugins_context_
bool is_network() const
Definition: team.hpp:259
config & replay_start()
Definition: saved_game.hpp:109
bool is_skipping_replay() const
const std::string & side_name() const
Definition: team.hpp:304
virtual void play_side_impl() override
Class for autosaves.
Definition: savegame.hpp:269
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:70
child_itors child_range(config_key_type key)
Definition: config.cpp:366
virtual void init_gui() override
bool objectives_changed() const
Definition: team.hpp:239
PROCESS_DATA_RESULT sync_network()
Definition: playturn.cpp:59
static lg::log_domain log_aitesting("aitesting")
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:730
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:242
config & set_snapshot(config snapshot)
Definition: saved_game.cpp:503
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
void append_children(const config &cfg)
Adds children from cfg.
Definition: config.cpp:245
static void log_game_end()
Definition: testing.cpp:103
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:353
const end_level_data & get_end_level_data_const() const
std::unique_ptr< replay_controller > replay_
persist_manager persist_
void send_data()
Definition: playturn.cpp:78
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: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:89
virtual bool should_return_to_play_side() const override
team & get_team(int i)
Definition: game_board.hpp:104
bool disable_autosave
config to_config() const
Builds the snapshot config from members and their respective configs.
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)
Shows a transient message to the user.
bool valid() const
Definition: location.hpp:93
game_board * gameboard
Definition: resources.cpp:20
bool is_regular_game_end() const
virtual void init_gui()
std::string describe_result() const
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:746
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:256
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:334
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
virtual bool is_networked_mp() const
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
Game configuration data as global variables.
Definition: build_info.cpp:46
static map_location::DIRECTION s
void reset_gamestate(const config &level, int replay_pos)
Define the game&#39;s event mechanism.
#define log_scope(description)
Definition: log.hpp:186
bool empty() const
Definition: map.hpp:432
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:491
virtual bool receive_from_wesnothd(config &) const
void update_viewing_player() override
compression::format save_compression_format()
Definition: game.cpp:872
void play_bell(const std::string &files)
Definition: sound.cpp:1004
game_state & gamestate()
double t
Definition: astarsearch.cpp:63
playturn_network_adapter network_reader_
game_classification & classification()
Definition: saved_game.hpp:55
PROXY_CONTROLLER proxy_controller() const
Definition: team.hpp:279
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:581
int current_side() const
Returns the number of the side whose turn it is.
replay_network_sender replay_sender_
std::shared_ptr< config > level
void play_music_config(const config &music_node, int i)
Definition: sound.cpp:666
#define e
std::size_t turn() const
void commit_music_changes()
Definition: sound.cpp:783
void remove_snapshot()
Definition: saved_game.cpp:521
int side() const
Definition: team.hpp:187
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:419
Thrown when a lexical_cast fails.
bool empty() const
Definition: config.cpp:837
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:253
std::shared_ptr< terrain_type_data > ter_data_cache