The Battle for Wesnoth  1.17.21+dev
play_controller.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2006 - 2023
3  by Joerg Hinrichs <joerg.hinrichs@alice-dsl.de>
4  Copyright (C) 2003 by David White <dave@whitevine.net>
5  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY.
13 
14  See the COPYING file for more details.
15 */
16 
17 #pragma once
18 
19 #include "controller_base.hpp"
20 #include "game_end_exceptions.hpp"
21 #include "help/help.hpp"
23 #include "menu_events.hpp"
24 #include "mouse_events.hpp"
25 #include "persist_manager.hpp"
26 #include "tod_manager.hpp"
27 #include "game_state.hpp"
28 #include <optional>
29 
30 #include <set>
31 
32 class game_display;
33 class game_data;
34 class team;
35 class unit;
36 class replay;
37 class replay_controller;
38 class saved_game;
39 struct mp_game_settings;
42 
43 namespace actions {
44  class undo_list;
45 }
46 
47 namespace font {
48  struct floating_label_context;
49 }
50 
51 namespace game_events {
52  class manager;
53  class wml_event_pump;
54  class wml_menu_item;
55 } // namespace game_events
56 
57 namespace soundsource {
58  class manager;
59 } // namespace soundsource
60 
61 class statistics_t;
62 
63 namespace pathfind {
64  class manager;
65 }
66 
67 namespace tooltips {
68  class manager;
69 } // namespace tooltips
70 
71 namespace wb {
72  class manager; // whiteboard manager
73 } // namespace wb
74 
75 // Holds gamestate related objects
76 class game_state;
77 
79 {
80 public:
82  saved_game& state_of_game,
83  bool skip_replay,
84  bool start_faded = false);
85  virtual ~play_controller();
86 
87  //event handler, overridden from observer
88  //there is nothing to handle in this class actually but that might change in the future
89  virtual void handle_generic_event(const std::string& /*name*/) override {}
90 
91  bool can_undo() const;
92  bool can_redo() const;
93 
94  void undo();
95  void redo();
96 
97  void load_game();
98 
99  void save_game();
100  void save_game_auto(const std::string& filename);
101  void save_replay();
102  void save_replay_auto(const std::string& filename);
103  void save_map();
104  replay& get_replay();
105 
106  void init_side_begin();
107 
108  /**
109  * Called by turn_info::process_network_data() or init_side() to call do_init_side() if necessary.
110  */
111  void maybe_do_init_side();
112 
113  /**
114  * Called by replay handler or init_side() to do actual work for turn change.
115  */
116  void do_init_side();
117 
118  void init_side_end();
119 
120  virtual void force_end_turn() = 0;
121  virtual void check_objectives() = 0;
122 
123  virtual void on_not_observer() = 0;
124 
125  /**
126  * Asks the user whether to continue on an OOS error.
127  *
128  * @throw quit_game_exception If the user wants to abort.
129  */
130  virtual void process_oos(const std::string& msg) const;
131 
133  {
135  }
136 
138  {
139  gamestate().end_level_data_.reset();
140  }
141 
142  bool is_regular_game_end() const
143  {
144  return gamestate().end_level_data_.has_value();
145  }
146 
148 
150  {
151  return *gamestate().end_level_data_;
152  }
153 
154  std::vector<team>& get_teams()
155  {
156  return gamestate().board_.teams();
157  }
158 
159  const std::vector<team>& get_teams() const
160  {
161  return gamestate().board_.teams();
162  }
163 
164  const unit_map& get_units() const
165  {
166  return gamestate().board_.units();
167  }
168 
170  {
171  return gamestate().board_.units();
172  }
173 
174  const gamemap& get_map() const
175  {
176  return gamestate().board_.map();
177  }
178 
180  {
181  return gamestate().tod_manager_;
182  }
183 
184  bool is_observer() const
185  {
186  return gamestate().board_.is_observer();
187  }
188 
189  bool do_healing() const
190  {
191  return gamestate().do_healing_;
192  }
193 
195  {
197  }
198 
200  {
201  return *gamestate_;
202  }
203 
204  const game_state& gamestate() const
205  {
206  return *gamestate_;
207  }
208 
209  /**
210  * Checks to see if a side has won.
211  *
212  * This will also remove control of villages from sides with dead leaders.
213  */
214  void check_victory();
215 
216  std::size_t turn() const {return gamestate().tod_manager_.turn();}
217 
218  /**
219  * Returns the number of the side whose turn it is.
220  *
221  * Numbering starts at one.
222  */
223  int current_side() const { return gamestate_->player_number_; }
224 
225  /**
226  * Builds the snapshot config from members and their respective configs.
227  */
228  config to_config() const;
229 
230  bool is_skipping_replay() const { return skip_replay_; }
231  void toggle_skipping_replay();
232  void do_autosave();
233 
234  bool is_skipping_story() const { return skip_story_; }
235 
236  void do_consolesave(const std::string& filename);
237 
240 
241  std::shared_ptr<wb::manager> get_whiteboard() const;
246 
248 
249  int get_ticks() const;
250 
251  virtual soundsource::manager* get_soundsource_man() override;
252  virtual plugins_context* get_plugins_context() override;
254 
256 
257  bool is_browsing() const override;
258 
259  class hotkey_handler;
260 
261  virtual replay_controller * get_replay_controller() const { return nullptr; }
262  bool is_replay() const { return get_replay_controller() != nullptr; }
263 
265  {
266  return level_["name"].t_str();
267  }
268 
269  bool get_disallow_recall() const
270  {
271  return level_["disallow_recall"].to_bool();
272  }
273 
274  std::string get_loaded_resources() const
275  {
276  return level_["loaded_resources"].str();
277  }
278 
279  std::string theme() const
280  {
281  return gamestate_->get_game_data()->get_theme();
282  }
283 
284  virtual bool should_return_to_play_side() const
285  {
286  return is_regular_game_end();
287  }
288 
289  void maybe_throw_return_to_play_side() const;
290 
291  virtual void play_side_impl() {}
292 
293  void play_side();
294 
295  team& current_team();
296  const team& current_team() const;
297 
298  bool can_use_synced_wml_menu() const;
299  std::set<std::string> all_players() const;
300  int ticks() const { return ticks_; }
301  game_display& get_display() override;
302 
303  void update_savegame_snapshot() const;
304  /**
305  * Changes the UI for this client to the passed side index.
306  */
307  void update_gui_to_player(const int team_index, const bool observe = false);
308 
309  virtual bool is_networked_mp() const { return false; }
310  virtual void send_to_wesnothd(const config&, const std::string& = "unknown") const { }
311  virtual bool receive_from_wesnothd(config&) const { return false; }
312  /** Reevaluate [show_if] conditions and build a new objectives string. */
313  void refresh_objectives() const;
314  void show_objectives() const;
315 
317  {
321  };
322 
324 
326  bool is_during_turn() const;
327  bool is_linger_mode() const;
328 
329 protected:
331  void play_slice_catch();
332  bool have_keyboard_focus() override;
333  void process_focus_keydown_event(const SDL_Event& event) override;
334  void process_keydown_event(const SDL_Event& event) override;
335  void process_keyup_event(const SDL_Event& event) override;
336 
337  void init_managers();
338  /** preload events cannot be synced */
339  void fire_preload();
340  void fire_prestart();
341  void fire_start();
342  void start_game();
343  virtual void init_gui();
345  void finish_turn(); //this should not throw an end turn or end level exception
346  bool enemies_visible() const;
347 
348  void enter_textbox();
349  void textbox_move_vertically(bool up);
350  void tab();
351 
352 
353  bool is_team_visible(int team_num, bool observer) const;
354 public:
355  /** returns 0 if no such team was found. */
356  int find_viewing_side() const;
357 
358 private:
359  const int ticks_;
360 
361 protected:
362  //gamestate
363  std::unique_ptr<game_state> gamestate_;
366 
367  //managers
369 
370  //whiteboard manager
371  std::shared_ptr<wb::manager> whiteboard_manager_;
372 
373  //plugins context
374  std::unique_ptr<plugins_context> plugins_context_;
375 
376  //more managers
377  std::unique_ptr<font::floating_label_context> labels_manager_;
381  std::unique_ptr<hotkey_handler> hotkey_handler_;
382  std::unique_ptr<soundsource::manager> soundsources_manager_;
384 
385  //other objects
386  std::unique_ptr<game_display> gui_;
387  const std::unique_ptr<unit_experience_accelerator> xp_mod_;
388  const std::unique_ptr<statistics_t> statistics_context_;
390  const actions::undo_list& undo_stack() const { return *gamestate().undo_stack_; }
391  std::unique_ptr<replay> replay_;
392 
395  /**
396  * Whether we did init sides in this session
397  * (false = we did init sides before we reloaded the game).
398  */
401  //the displayed location when we load a game.
403  // Whether to start with the display faded to black
405 
406  const std::string& select_music(bool victory) const;
407 
408  void reset_gamestate(const config& level, int replay_pos);
409 
410 private:
411 
412  void init(const config& level);
413 
414  /**
415  * This shows a warning dialog if either [scenario]next_scenario or any [endlevel]next_scenario would lead to an "Unknown Scenario" dialog.
416  */
418 
421  std::vector<std::string> victory_music_;
422  std::vector<std::string> defeat_music_;
423 
425 
426 protected:
427  mutable bool ignore_replay_errors_;
428  /// true when the controller of the currently playing side has changed.
429  /// this can mean for example:
430  /// - The currently active side was reassigned from/to another player in a mp game
431  /// - The replay controller was disabled ('continue play' button)
432  /// - The currently active side was droided / undroided.
433  /// - A side was set to idle.
435  virtual void sync_end_turn() {}
436  virtual void check_time_over();
437  virtual void update_viewing_player() = 0;
438 };
Class to store the actions that a player can undo and redo.
Definition: undo.hpp:34
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:161
bool is_observer() const
Check if we are an observer in this game.
virtual const std::vector< team > & teams() const override
Definition: game_board.hpp:86
virtual const unit_map & units() const override
Definition: game_board.hpp:113
virtual const gamemap & map() const override
Definition: game_board.hpp:103
int server_request_number_
Definition: game_state.hpp:67
std::optional< end_level_data > end_level_data_
Definition: game_state.hpp:65
const std::unique_ptr< actions::undo_list > undo_stack_
undo_stack_ is never nullptr.
Definition: game_state.hpp:59
bool do_healing_
True if healing should be done at the beginning of the next side turn.
Definition: game_state.hpp:63
game_board board_
Definition: game_state.hpp:47
tod_manager tod_manager_
Definition: game_state.hpp:48
Encapsulates the map of the game.
Definition: map.hpp:172
unit_map & get_units()
game_classification & get_classification()
const std::string & select_music(bool victory) const
virtual void handle_generic_event(const std::string &) override
void process_keydown_event(const SDL_Event &event) override
Process keydown (always).
events::menu_handler & get_menu_handler()
void maybe_throw_return_to_play_side() const
config to_config() const
Builds the snapshot config from members and their respective configs.
virtual void on_not_observer()=0
void init(const config &level)
const std::vector< team > & get_teams() const
virtual bool receive_from_wesnothd(config &) const
int get_server_request_number() const
std::vector< team > & get_teams()
std::unique_ptr< hotkey_handler > hotkey_handler_
virtual void init_gui()
virtual replay_controller * get_replay_controller() const
bool have_keyboard_focus() override
Derived classes should override this to return false when arrow keys should not scroll the map,...
std::unique_ptr< game_state > gamestate_
void show_objectives() const
events::menu_handler menu_handler_
int find_viewing_side() const
returns 0 if no such team was found.
void fire_preload()
preload events cannot be synced
std::vector< std::string > victory_music_
void check_victory()
Checks to see if a side has won.
bool is_linger_mode() const
bool is_team_visible(int team_num, bool observer) const
actions::undo_list & undo_stack()
statistics_t & statistics()
virtual soundsource::manager * get_soundsource_man() override
Get (optionally) a soundsources manager a derived class uses.
void check_next_scenario_is_known()
This shows a warning dialog if either [scenario]next_scenario or any [endlevel]next_scenario would le...
actions::undo_list & get_undo_stack()
const unit_map & get_units() const
bool do_healing() const
void set_end_level_data(const end_level_data &data)
events::mouse_handler & get_mouse_handler_base() override
Get a reference to a mouse handler member a derived class uses.
void update_savegame_snapshot() const
void increase_server_request_number()
bool is_observer() const
void set_do_healing(bool do_healing)
const actions::undo_list & undo_stack() const
bool is_during_turn() const
bool can_use_synced_wml_menu() const
void reset_gamestate(const config &level, int replay_pos)
bool is_skipping_story() const
void do_consolesave(const std::string &filename)
void save_game_auto(const std::string &filename)
void textbox_move_vertically(bool up)
bool is_regular_game_end() const
saved_game & get_saved_game()
play_controller(const config &level, saved_game &state_of_game, bool skip_replay, bool start_faded=false)
tooltips::manager tooltips_manager_
virtual void check_objectives()=0
bool remove_from_carryover_on_defeat_
void save_replay_auto(const std::string &filename)
saved_game & saved_game_
game_state & gamestate()
hotkey::command_executor * get_hotkey_command_executor() override
Optionally get a command executor to handle context menu events.
bool enemies_visible() const
std::unique_ptr< replay > replay_
const std::unique_ptr< statistics_t > statistics_context_
const mp_game_settings & get_mp_settings()
game_display & get_display() override
Get a reference to a display member a derived class uses.
virtual void update_viewing_player()=0
virtual void sync_end_turn()
bool check_regular_game_end()
bool victory_when_enemies_defeated_
std::unique_ptr< game_display > gui_
void maybe_do_init_side()
Called by turn_info::process_network_data() or init_side() to call do_init_side() if necessary.
virtual void process_oos(const std::string &msg) const
Asks the user whether to continue on an OOS error.
bool is_browsing() const override
virtual void send_to_wesnothd(const config &, const std::string &="unknown") const
virtual void play_side_impl()
std::unique_ptr< soundsource::manager > soundsources_manager_
const end_level_data & get_end_level_data() const
void do_init_side()
Called by replay handler or init_side() to do actual work for turn change.
std::string theme() const
const tod_manager & get_tod_manager() const
int current_side() const
Returns the number of the side whose turn it is.
virtual bool is_networked_mp() const
bool is_skipping_replay() const
bool get_disallow_recall() const
const hotkey::scope_changer scope_
std::unique_ptr< font::floating_label_context > labels_manager_
std::shared_ptr< wb::manager > get_whiteboard() const
std::vector< std::string > defeat_music_
const gamemap & get_map() const
bool did_autosave_this_turn_
Whether we did init sides in this session (false = we did init sides before we reloaded the game).
bool is_replay() const
bool player_type_changed_
true when the controller of the currently playing side has changed.
std::size_t turn() const
map_location map_start_
virtual bool should_return_to_play_side() const
std::set< std::string > all_players() const
virtual void force_end_turn()=0
void update_gui_to_player(const int team_index, const bool observe=false)
Changes the UI for this client to the passed side index.
events::mouse_handler mouse_handler_
std::unique_ptr< plugins_context > plugins_context_
virtual plugins_context * get_plugins_context() override
Get (optionally) a plugins context a derived class uses.
virtual ~play_controller()
bool can_undo() const
const std::unique_ptr< unit_experience_accelerator > xp_mod_
void process_focus_keydown_event(const SDL_Event &event) override
Process keydown (only when the general map display does not have focus).
void refresh_objectives() const
Reevaluate [show_if] conditions and build a new objectives string.
bool can_redo() const
game_events::wml_event_pump & pump()
void process_keyup_event(const SDL_Event &event) override
Process keyup (always).
void finish_side_turn_events()
std::string get_loaded_resources() const
help::help_manager help_manager_
const game_state & gamestate() const
persist_manager persist_
std::shared_ptr< wb::manager > whiteboard_manager_
virtual void check_time_over()
t_string get_scenario_name() const
Implements a quit confirmation dialog.
This class stores all the data for a single 'side' (in game nomenclature).
Definition: team.hpp:76
int turn() const
Container associating units to locations.
Definition: map.hpp:99
This class represents a single unit of a specific type.
Definition: unit.hpp:134
controller_base framework: controller_base is roughly analogous to a "dialog" class in a GUI toolkit ...
Contains the exception interfaces used to signal completion of a scenario, campaign or turn.
Collection of helper functions relating to Pango formatting.
std::string observer
Domain specific events.
Definition: display.hpp:49
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:110
std::string_view data
Definition: picture.cpp:199
Additional information on the game outcome which can be provided by WML.
The help implementation caches data parsed from the game_config.
Definition: help.hpp:40
Encapsulates the map of the game.
Definition: location.hpp:38
scoped_savegame_snapshot(const play_controller &controller)