The Battle for Wesnoth  1.15.12+dev
create_engine.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2013 - 2018 by Andrius Silinskas <silinskas.andrius@gmail.com>
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #pragma once
16 
17 #include "config.hpp"
20 #include "mp_game_settings.hpp"
21 #include "utils/make_enum.hpp"
22 #include "utils/irdya_datetime.hpp"
23 
24 #include <numeric>
25 #include <string>
26 #include <utility>
27 #include <cctype>
28 
29 class saved_game;
30 class gamemap;
31 class game_config_view;
32 
33 namespace ng {
34 
35 static bool contains_ignore_case(const std::string& str1, const std::string& str2)
36 {
37  if(str2.size() > str1.size()) {
38  return false;
39  }
40 
41  for(std::size_t i = 0; i < str1.size() - str2.size() + 1; i++) {
42  bool ok = true;
43  for(std::size_t j = 0; j < str2.size(); j++) {
44  if(std::tolower(str1[i + j]) != std::tolower(str2[j])) {
45  ok = false;
46  break;
47  }
48  }
49 
50  if(ok) {
51  return true;
52  }
53  }
54 
55  return false;
56 }
57 
58 /** Base class for all level type classes. */
59 class level
60 {
61 public:
62  level(const config& data);
63  virtual ~level() = default;
64 
66  (SCENARIO, "scenario")
67  (USER_MAP, "user_map")
68  (USER_SCENARIO, "user_scenario")
69  (RANDOM_MAP, "random_map")
70  (CAMPAIGN, "campaign")
71  (SP_CAMPAIGN, "sp_campaign")
72  )
73 
74  virtual void set_metadata() = 0;
75 
76  virtual bool can_launch_game() const = 0;
77  virtual bool player_count_filter(int player_count) const = 0;
78 
79  virtual std::string id() const
80  {
81  return data_["id"];
82  }
83 
84  virtual std::string name() const
85  {
86  return data_["name"];
87  }
88 
89  virtual std::string icon() const
90  {
91  return data_["icon"];
92  }
93 
94  virtual std::string description() const
95  {
96  return data_["description"];
97  }
98 
99  virtual bool allow_era_choice() const
100  {
101  return data_["allow_era_choice"].to_bool(true);
102  }
103 
104  void set_data(const config& data)
105  {
106  data_ = data;
107  }
108 
109  const config& data() const
110  {
111  return data_;
112  }
113 
115  {
116  return data_;
117  }
118 
119 protected:
121 
122 private:
123  level(const level&) = delete;
124  level& operator=(const level&) = delete;
125 };
126 
127 class scenario : public level
128 {
129 public:
130  scenario(const config& data);
131 
132  bool can_launch_game() const;
133 
134  void set_metadata();
135 
136  int num_players() const
137  {
138  return num_players_;
139  }
140 
141  std::string map_size() const;
142 
143  bool player_count_filter(int player_count) const
144  {
145  return num_players_ == player_count;
146  }
147 
148 protected:
149  void set_sides();
150 
151  std::unique_ptr<gamemap> map_;
152 
153  std::string map_hash_;
154 
155 private:
156  scenario(const scenario&) = delete;
157  scenario& operator=(const scenario&) = delete;
158 
160 };
161 
162 class user_map : public scenario
163 {
164 public:
165  user_map(const config& data, const std::string& name, gamemap* map);
166 
167  void set_metadata();
168 
169  /** For user maps, the id and name are the same. */
170  std::string id() const
171  {
172  return name_;
173  }
174 
175  std::string name() const
176  {
177  return name_;
178  }
179 
180  std::string description() const;
181 
182 private:
183  user_map(const user_map&) = delete;
184  user_map& operator=(const user_map&) = delete;
185 
186  std::string name_;
187 };
188 
189 class random_map : public scenario
190 {
191 public:
192  random_map(const config& data);
193 
194  const config& generator_data() const
195  {
196  return generator_data_;
197  }
198 
199  std::string generator_name() const
200  {
201  return generator_name_;
202  }
203 
205 
207  {
208  return generate_whole_scenario_;
209  }
210 
211 private:
212  random_map(const random_map&) = delete;
213  random_map& operator=(const random_map&) = delete;
214 
216 
218  std::string generator_name_;
219 };
220 
221 class campaign : public level
222 {
223 public:
224  campaign(const config& data);
225 
226  bool can_launch_game() const;
227 
228  void set_metadata();
229 
230  void mark_if_completed();
231 
232  std::string id() const
233  {
234  return id_;
235  }
236 
237  bool allow_era_choice() const
238  {
239  return allow_era_choice_;
240  }
241 
242  int min_players() const
243  {
244  return min_players_;
245  }
246 
247  int max_players() const
248  {
249  return max_players_;
250  }
251 
252  bool player_count_filter(int player_count) const
253  {
254  return min_players_ <= player_count && max_players_ >= player_count;
255  }
256 
257  std::pair<irdya_date, irdya_date> dates() const
258  {
259  return dates_;
260  }
261 
262 private:
263  campaign(const campaign&) = delete;
264  campaign& operator=(const campaign&) = delete;
265 
266  std::string id_;
268  std::string image_label_;
271  std::pair<irdya_date, irdya_date> dates_;
272 };
273 
275 {
276 public:
277  explicit create_engine(saved_game& state);
278 
279  enum MP_EXTRA { ERA, MOD };
280 
282  {
283  std::string id;
284  std::string name;
285  std::string description;
286  const config* cfg;
287  };
288 
289  typedef std::shared_ptr<extras_metadata> extras_metadata_ptr;
290 
291  typedef std::shared_ptr<level> level_ptr;
292  typedef std::shared_ptr<scenario> scenario_ptr;
293  typedef std::shared_ptr<user_map> user_map_ptr;
294  typedef std::shared_ptr<random_map> random_map_ptr;
295  typedef std::shared_ptr<campaign> campaign_ptr;
296 
297  void init_generated_level_data();
298 
299  void prepare_for_new_level();
300  void prepare_for_era_and_mods();
301  void prepare_for_scenario();
302  void prepare_for_campaign(const std::string& difficulty = "");
303  void prepare_for_saved_game();
304  // random maps, user maps
305  void prepare_for_other();
306 
307  /**
308  * select_campaign_difficulty
309  *
310  * Launches difficulty selection gui and returns selected difficulty name.
311  *
312  * The gui can be bypassed by supplying a number from 1 to the number of
313  * difficulties available, corresponding to a choice of difficulty.
314  * This is useful for specifying difficulty via command line.
315  *
316  * @param set_value Preselected difficulty number. The default -1 launches the gui.
317  * @return Selected difficulty. Returns "FAIL" if set_value is invalid,
318  * and "CANCEL" if the gui is canceled.
319  */
320  std::string select_campaign_difficulty(int set_value = -1);
322  {
323  return selected_campaign_difficulty_;
324  }
325 
326  void apply_level_filter(const std::string& name);
327  void apply_level_filter(int players);
328  void reset_level_filters();
329 
330  const std::string& level_name_filter() const
331  {
332  return level_name_filter_;
333  }
334 
335  int player_num_filter() const
336  {
337  return player_count_filter_;
338  }
339 
340  std::vector<level_ptr> get_levels_by_type_unfiltered(level::TYPE type) const;
341  std::vector<level_ptr> get_levels_by_type(level::TYPE type) const;
342 
343  std::vector<std::size_t> get_filtered_level_indices(level::TYPE type) const;
344 
345  level& current_level() const;
346  const extras_metadata& current_era() const;
347 
349  {
350  current_level_type_ = type;
351  }
352 
354  {
355  return current_level_type_;
356  }
357 
358  /** Wrapper to simplify the is-type-campaign-or-sp-campaign check. */
359  bool is_campaign() const
360  {
361  return current_level_type_ == level::TYPE::CAMPAIGN || current_level_type_ == level::TYPE::SP_CAMPAIGN;
362  }
363 
364  void set_current_level(const std::size_t index);
365 
366  void set_current_era_index(const std::size_t index, bool force = false);
367 
368  std::size_t current_era_index() const
369  {
370  return current_era_index_;
371  }
372 
373  const config& curent_era_cfg() const;
374 
375  const std::vector<extras_metadata_ptr>& get_const_extras_by_type(const MP_EXTRA extra_type) const;
376  std::vector<extras_metadata_ptr>& get_extras_by_type(const MP_EXTRA extra_type);
377 
378  bool toggle_mod(int index, bool force = false);
379 
380  bool generator_assigned() const;
381  bool generator_has_settings() const;
382  void generator_user_config();
383 
384  std::pair<level::TYPE, int> find_level_by_id(const std::string& id) const;
385  int find_extra_by_id(const MP_EXTRA extra_type, const std::string& id) const;
386 
388  {
389  return *dependency_manager_;
390  }
391 
392  void init_active_mods();
393 
394  std::vector<std::string>& active_mods();
395  std::vector<extras_metadata_ptr> active_mods_data();
396 
397  const mp_game_settings& get_parameters();
398 
399  saved_game& get_state();
400 
401  /** Returns true if the current level has one or more [side] tags. */
402  bool current_level_has_side_data();
403 
404 private:
405  create_engine(const create_engine&) = delete;
406  create_engine& operator=(const create_engine&) = delete;
407 
408  void init_all_levels();
409  void init_extras(const MP_EXTRA extra_type);
410  void apply_level_filters();
411 
412  std::size_t map_level_index(std::size_t index) const;
413 
415  std::size_t current_level_index_;
416 
417  std::size_t current_era_index_;
418 
419  std::string level_name_filter_;
421 
422  struct type_list
423  {
424  explicit type_list() : games(), games_filtered() {}
425 
426  std::vector<level_ptr> games;
427  std::vector<std::size_t> games_filtered;
428 
429  void apply_filter(const int player_count, const std::string& name_filter)
430  {
431  games_filtered.clear();
432 
433  for(std::size_t i = 0; i < games.size(); i++) {
434  const bool num_players_match = player_count == 1 || games[i]->player_count_filter(player_count);
435 
436  if(contains_ignore_case(games[i]->name(), name_filter) && num_players_match) {
437  games_filtered.push_back(i);
438  }
439  }
440  }
441 
443  {
444  games_filtered.resize(games.size());
445  std::iota(games_filtered.begin(), games_filtered.end(), 0);
446  }
447  };
448 
449  std::map<level::TYPE, type_list> type_map_;
450 
451  std::vector<std::string> user_map_names_;
452  std::vector<std::string> user_scenario_names_;
453 
454  std::vector<extras_metadata_ptr> eras_;
455  std::vector<extras_metadata_ptr> mods_;
456 
458 
459  // Never nullptr
460  std::unique_ptr<depcheck::manager> dependency_manager_;
461 
462  std::unique_ptr<map_generator> generator_;
463 
465 
466  /** Reference to the main game config. */
468 };
469 
470 } // end namespace ng
TYPE
Used to specify the rendering format of images.
Definition: picture.hpp:228
level & operator=(const level &)=delete
level::TYPE current_level_type() const
std::string id() const
For user maps, the id and name are the same.
std::vector< extras_metadata_ptr > mods_
std::shared_ptr< level > level_ptr
int min_players() const
std::shared_ptr< campaign > campaign_ptr
virtual ~level()=default
std::string name() const
bool allow_era_choice() const
std::vector< std::string > user_scenario_names_
const config & generator_data() const
std::vector< level_ptr > games
int max_players() const
bool generate_whole_scenario_
bool generate_whole_scenario() const
std::shared_ptr< scenario > scenario_ptr
void set_data(const config &data)
std::pair< irdya_date, irdya_date > dates() const
config & data()
std::size_t current_era_index_
Definitions for the interface to Wesnoth Markup Language (WML).
bool is_campaign() const
Wrapper to simplify the is-type-campaign-or-sp-campaign check.
std::string id() const
virtual std::string id() const
const config & data() const
std::map< level::TYPE, type_list > type_map_
void set_current_level_type(const level::TYPE type)
std::string selected_campaign_difficulty_
std::string level_name_filter_
std::pair< irdya_date, irdya_date > dates_
saved_game & state_
int num_players() const
virtual std::string name() const
std::unique_ptr< depcheck::manager > dependency_manager_
level::TYPE current_level_type_
const std::string & level_name_filter() const
Encapsulates the map of the game.
Definition: map.hpp:170
bool player_count_filter(int player_count) const
std::shared_ptr< random_map > random_map_ptr
std::unique_ptr< gamemap > map_
std::string image_label_
std::string generator_name() const
std::shared_ptr< user_map > user_map_ptr
std::string map_hash_
virtual std::string icon() const
Note to all triers: It&#39;s not guaranteed that the specified component will be selected (if the user de...
Definition: depcheck.hpp:54
std::size_t current_level_index_
map_generator * create_map_generator(const std::string &name, const config &cfg, const config *vars)
Definition: map_create.cpp:28
std::size_t i
Definition: function.cpp:940
void apply_filter(const int player_count, const std::string &name_filter)
level(const config &data)
const game_config_view & game_config_
Reference to the main game config.
std::unique_ptr< map_generator > generator_
std::vector< std::string > user_map_names_
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:71
virtual std::string description() const
std::size_t current_era_index() const
std::shared_ptr< extras_metadata > extras_metadata_ptr
std::string name_
std::vector< extras_metadata_ptr > eras_
std::string get_selected_campaign_difficulty() const
const depcheck::manager & dependency_manager() const
Base class for all level type classes.
std::string id_
virtual bool player_count_filter(int player_count) const =0
int player_num_filter() const
static bool contains_ignore_case(const std::string &str1, const std::string &str2)
bool player_count_filter(int player_count) const
std::string generator_name_
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:59
std::vector< std::size_t > games_filtered
Defines the MAKE_ENUM macro.
MAKE_ENUM(TYPE,(SCENARIO, "scenario")(USER_MAP, "user_map")(USER_SCENARIO, "user_scenario")(RANDOM_MAP, "random_map")(CAMPAIGN, "campaign")(SP_CAMPAIGN, "sp_campaign")) virtual void set_metadata()=0
virtual bool allow_era_choice() const
virtual bool can_launch_game() const =0