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