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