The Battle for Wesnoth  1.15.11+dev
play_controller.hpp
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 #pragma once
17 
18 #include "controller_base.hpp"
19 #include "game_end_exceptions.hpp"
20 #include "help/help.hpp"
22 #include "menu_events.hpp"
23 #include "mouse_events.hpp"
24 #include "persist_manager.hpp"
25 #include "tod_manager.hpp"
26 #include "game_state.hpp"
27 #include <optional>
28 
29 #include <set>
30 
31 class game_display;
32 class game_data;
33 class team;
34 class unit;
35 class replay;
36 class replay_controller;
37 class saved_game;
38 struct mp_game_settings;
41 
42 namespace actions {
43  class undo_list;
44 }
45 
46 namespace font {
47  struct floating_label_context;
48 }
49 
50 namespace game_events {
51  class manager;
52  class wml_event_pump;
53  class wml_menu_item;
54 } // namespace game_events
55 
56 namespace soundsource {
57  class manager;
58 } // namespace soundsource
59 
60 namespace statistics {
61  struct scenario_context;
62 } // namespace statistics
63 
64 namespace pathfind {
65  class manager;
66 }
67 
68 namespace tooltips {
69  struct manager;
70 } // namespace tooltips
71 
72 namespace wb {
73  class manager; // whiteboard manager
74 } // namespace wb
75 
76 // Holds gamestate related objects
77 class game_state;
78 
80 {
81 public:
82  play_controller(const config& level, saved_game& state_of_game, bool skip_replay);
83  virtual ~play_controller();
84 
85  //event handler, overridden from observer
86  //there is nothing to handle in this class actually but that might change in the future
87  virtual void handle_generic_event(const std::string& /*name*/) override {}
88 
89  bool can_undo() const;
90  bool can_redo() const;
91 
92  void undo();
93  void redo();
94 
95  void load_game();
96 
97  void save_game();
98  void save_game_auto(const std::string& filename);
99  void save_replay();
100  void save_replay_auto(const std::string& filename);
101  void save_map();
102  replay& get_replay();
103 
104  void init_side_begin();
105 
106  /**
107  * Called by turn_info::process_network_data() or init_side() to call do_init_side() if necessary.
108  */
109  void maybe_do_init_side();
110 
111  /**
112  * Called by replay handler or init_side() to do actual work for turn change.
113  */
114  void do_init_side();
115 
116  void init_side_end();
117 
118  virtual void force_end_turn() = 0;
119  virtual void check_objectives() = 0;
120 
121  virtual void on_not_observer() = 0;
122 
123  /**
124  * Asks the user whether to continue on an OOS error.
125  *
126  * @throw quit_game_exception If the user wants to abort.
127  */
128  virtual void process_oos(const std::string& msg) const;
129 
131  {
132  gamestate().end_level_data_ = data;
133  }
134 
136  {
137  gamestate().end_level_data_.reset();
138  }
139 
140  bool is_regular_game_end() const
141  {
142  return gamestate().end_level_data_.has_value();
143  }
144 
146  {
147  return *gamestate().end_level_data_;
148  }
149 
150  std::vector<team>& get_teams()
151  {
152  return gamestate().board_.teams();
153  }
154 
155  const std::vector<team>& get_teams() const
156  {
157  return gamestate().board_.teams();
158  }
159 
160  const unit_map& get_units() const
161  {
162  return gamestate().board_.units();
163  }
164 
166  {
167  return gamestate().board_.units();
168  }
169 
170  const gamemap& get_map() const
171  {
172  return gamestate().board_.map();
173  }
174 
176  {
177  return gamestate().tod_manager_;
178  }
179 
180  bool is_observer() const
181  {
182  return gamestate().board_.is_observer();
183  }
184 
185  bool do_healing() const
186  {
187  return gamestate().do_healing_;
188  }
189 
190  void set_do_healing(bool do_healing)
191  {
192  gamestate().do_healing_ = do_healing;
193  }
194 
196  {
197  return *gamestate_;
198  }
199 
200  const game_state& gamestate() const
201  {
202  return *gamestate_;
203  }
204 
205  /**
206  * Checks to see if a side has won.
207  *
208  * This will also remove control of villages from sides with dead leaders.
209  */
210  void check_victory();
211 
212  std::size_t turn() const {return gamestate().tod_manager_.turn();}
213 
214  /**
215  * Returns the number of the side whose turn it is.
216  *
217  * Numbering starts at one.
218  */
219  int current_side() const { return gamestate_->player_number_; }
220 
221  /**
222  * Builds the snapshot config from members and their respective configs.
223  */
224  config to_config() const;
225 
226  bool is_skipping_replay() const { return skip_replay_; }
227  void toggle_skipping_replay();
228  bool is_linger_mode() const { return linger_; }
229  void do_autosave();
230 
231  bool is_skipping_story() const { return skip_story_; }
232 
233  void do_consolesave(const std::string& filename);
234 
235  events::mouse_handler& get_mouse_handler_base() override;
236  events::menu_handler& get_menu_handler() { return menu_handler_; }
237 
238  std::shared_ptr<wb::manager> get_whiteboard() const;
239  const mp_game_settings& get_mp_settings();
240  game_classification& get_classification();
241  int get_server_request_number() const { return gamestate().server_request_number_; }
242  void increase_server_request_number() { ++gamestate().server_request_number_; }
243 
245 
246  int get_ticks() const;
247 
248  virtual soundsource::manager* get_soundsource_man() override;
249  virtual plugins_context* get_plugins_context() override;
250  hotkey::command_executor* get_hotkey_command_executor() override;
251 
253 
254  bool is_browsing() const override;
255  bool is_lingering() const { return linger_; }
256 
257  class hotkey_handler;
258 
259  virtual replay_controller * get_replay_controller() const { return nullptr; }
260  bool is_replay() const { return get_replay_controller() != nullptr; }
261 
263  {
264  return level_["name"].t_str();
265  }
266 
267  bool get_disallow_recall() const
268  {
269  return level_["disallow_recall"].to_bool();
270  }
271 
272  std::string get_loaded_resources() const
273  {
274  return level_["loaded_resources"].str();
275  }
276 
277  std::string theme() const
278  {
279  return gamestate_->get_game_data()->get_theme();
280  }
281 
282  virtual bool should_return_to_play_side() const
283  {
284  return is_regular_game_end();
285  }
286 
288  {
289  if(should_return_to_play_side() && !linger_ ) {
291  }
292  }
293 
294  virtual void play_side_impl() {}
295 
296  void play_side();
297 
298  team& current_team();
299  const team& current_team() const;
300 
301  bool can_use_synced_wml_menu() const;
302  std::set<std::string> all_players() const;
303  int ticks() const { return ticks_; }
304  game_display& get_display() override;
305 
306  void update_savegame_snapshot() const;
307  /**
308  * Changes the UI for this client to the passed side index.
309  */
310  void update_gui_to_player(const int team_index, const bool observe = false);
311 
312  virtual bool is_networked_mp() const { return false; }
313  virtual void send_to_wesnothd(const config&, const std::string& = "unknown") const { }
314  virtual bool receive_from_wesnothd(config&) const { return false; }
315  /** Reevaluate [show_if] conditions and build a new objectives string. */
316  void refresh_objectives() const;
317  void show_objectives() const;
318 
320  {
324  };
325 
326  saved_game& get_saved_game() { return saved_game_; }
327 
328 protected:
330  void play_slice_catch();
331  bool have_keyboard_focus() override;
332  void process_focus_keydown_event(const SDL_Event& event) override;
333  void process_keydown_event(const SDL_Event& event) override;
334  void process_keyup_event(const SDL_Event& event) override;
335 
336  void init_managers();
337  /** preload events cannot be synced */
338  void fire_preload();
339  void fire_prestart();
340  void fire_start();
341  void start_game();
342  virtual void init_gui();
343  void finish_side_turn();
344  void finish_turn(); //this should not throw an end turn or end level exception
345  bool enemies_visible() const;
346 
347  void enter_textbox();
348  void textbox_move_vertically(bool up);
349  void tab();
350 
351 
352  bool is_team_visible(int team_num, bool observer) const;
353  /** returns 0 if no such team was found. */
354  int find_last_visible_team() const;
355 
356 private:
357  const int ticks_;
358 
359 protected:
360  //gamestate
361  std::unique_ptr<game_state> gamestate_;
364 
365  //managers
366  std::unique_ptr<tooltips::manager> tooltips_manager_;
367 
368  //whiteboard manager
369  std::shared_ptr<wb::manager> whiteboard_manager_;
370 
371  //plugins context
372  std::unique_ptr<plugins_context> plugins_context_;
373 
374  //more managers
375  std::unique_ptr<font::floating_label_context> labels_manager_;
379  std::unique_ptr<hotkey_handler> hotkey_handler_;
380  std::unique_ptr<soundsource::manager> soundsources_manager_;
382 
383  //other objects
384  std::unique_ptr<game_display> gui_;
385  const std::unique_ptr<unit_experience_accelerator> xp_mod_;
386  const std::unique_ptr<const statistics::scenario_context> statistics_context_;
387  actions::undo_list& undo_stack() { return *gamestate().undo_stack_; }
388  const actions::undo_list& undo_stack() const { return *gamestate().undo_stack_; }
389  std::unique_ptr<replay> replay_;
390 
393  bool linger_;
394  /**
395  * Whether we did init sides in this session
396  * (false = we did init sides before we reloaded the game).
397  */
399  //the displayed location when we load a game.
401  const std::string& select_music(bool victory) const;
402 
403  void reset_gamestate(const config& level, int replay_pos);
404 
405 private:
406 
407  void init(const config& level);
408 
411  std::vector<std::string> victory_music_;
412  std::vector<std::string> defeat_music_;
413 
415 
416 protected:
417  mutable bool ignore_replay_errors_;
419  virtual void sync_end_turn() {}
420  virtual void check_time_over();
421  virtual void update_viewing_player() = 0;
422  void play_turn();
423 };
virtual replay_controller * get_replay_controller() const
virtual bool should_return_to_play_side() const
std::unique_ptr< soundsource::manager > soundsources_manager_
help::help_manager help_manager_
saved_game & get_saved_game()
This class represents a single unit of a specific type.
Definition: unit.hpp:120
std::unique_ptr< game_display > gui_
bool victory_when_enemies_defeated_
const unit_map & get_units() const
Collection of helper functions relating to Pango formatting.
events::mouse_handler mouse_handler_
std::unique_ptr< plugins_context > plugins_context_
bool is_skipping_replay() const
std::unique_ptr< replay > replay_
Exception used to escape form the ai or ui code to playsingle_controller::play_side.
std::unique_ptr< hotkey_handler > hotkey_handler_
void set_do_healing(bool do_healing)
const gamemap & get_map() const
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
bool do_healing() const
Contains the exception interfaces used to signal completion of a scenario, campaign or turn...
controller_base framework: controller_base is roughly analogous to a "dialog" class in a GUI toolkit ...
persist_manager persist_
std::unique_ptr< tooltips::manager > tooltips_manager_
events::menu_handler menu_handler_
bool get_disallow_recall() const
int get_server_request_number() const
std::unique_ptr< game_state > gamestate_
bool is_lingering() const
saved_game & saved_game_
std::vector< std::string > defeat_music_
This class stores all the data for a single &#39;side&#39; (in game nomenclature).
Definition: team.hpp:44
struct utils::detail::formula_initer init
const std::unique_ptr< const statistics::scenario_context > statistics_context_
bool is_linger_mode() const
Implements a quit confirmation dialog.
bool is_regular_game_end() const
Encapsulates the map of the game.
Definition: map.hpp:170
std::vector< team > & get_teams()
std::string theme() const
void pump()
Definition: events.cpp:472
bool is_observer() const
Encapsulates the map of the game.
Definition: location.hpp:37
Domain specific events.
Definition: action_wml.cpp:86
actions::undo_list & get_undo_stack()
void set_end_level_data(const end_level_data &data)
tooltips.
virtual bool is_networked_mp() const
map_location map_start_
const actions::undo_list & undo_stack() const
hotkey::scope_changer scope_
std::shared_ptr< wb::manager > whiteboard_manager_
t_string get_scenario_name() const
Additional information on the game outcome which can be provided by WML.
std::unique_ptr< font::floating_label_context > labels_manager_
actions::undo_list & undo_stack()
const end_level_data & get_end_level_data() const
virtual void handle_generic_event(const std::string &) override
std::string observer
virtual bool receive_from_wesnothd(config &) const
bool is_replay() const
Class to store the actions that a player can undo and redo.
Definition: undo.hpp:33
void maybe_throw_return_to_play_side() const
game_state & gamestate()
const std::unique_ptr< unit_experience_accelerator > xp_mod_
const tod_manager & get_tod_manager() const
events::menu_handler & get_menu_handler()
int current_side() const
Returns the number of the side whose turn it is.
bool is_skipping_story() const
const game_state & gamestate() const
Container associating units to locations.
Definition: map.hpp:97
std::string get_loaded_resources() const
std::vector< std::string > victory_music_
actions::undo_list * undo_stack
Definition: resources.cpp:32
std::size_t turn() const
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:59
const std::vector< team > & get_teams() const
virtual void send_to_wesnothd(const config &, const std::string &="unknown") const
Definition: display.hpp:48
virtual void play_side_impl()
bool init_side_done_now_
Whether we did init sides in this session (false = we did init sides before we reloaded the game)...
bool remove_from_carryover_on_defeat_
void increase_server_request_number()
unit_map & get_units()
virtual void sync_end_turn()