The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
create_engine.hpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2013 - 2025
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"
22#include "mp_game_settings.hpp"
24
25#include <numeric>
26#include <string>
27#include <utility>
28#include <cctype>
29
30class saved_game;
31class gamemap;
33
34namespace ng {
35
36static 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. */
60class level
61{
62public:
63 level(const config& data);
64 virtual ~level() = default;
65
66 virtual void set_metadata() = 0;
67
68 virtual bool can_launch_game() const = 0;
69 virtual bool player_count_filter(int player_count) const = 0;
70
71 virtual std::string id() const
72 {
73 return data_["id"];
74 }
75
76 virtual std::string name() const
77 {
78 return data_["name"];
79 }
80
81 virtual std::string icon() const
82 {
83 return data_["icon"];
84 }
85
86 virtual std::string description() const
87 {
88 return data_["description"];
89 }
90
91 virtual bool allow_era_choice() const
92 {
93 return data_["allow_era_choice"].to_bool(true);
94 }
95
96 void set_data(const config& data)
97 {
98 data_ = data;
99 }
100
101 const config& data() const
102 {
103 return data_;
104 }
105
107 {
108 return data_;
109 }
110
111protected:
113
114private:
115 level(const level&) = delete;
116 level& operator=(const level&) = delete;
117};
118
119class scenario : public level
120{
121public:
122 scenario(const config& data);
123
124 bool can_launch_game() const;
125
126 void set_metadata();
127
128 int num_players() const
129 {
130 return num_players_;
131 }
132
133 std::string map_size() const;
134
135 bool player_count_filter(int player_count) const
136 {
137 return num_players_ == player_count;
138 }
139
140protected:
141 void set_sides();
142
143 std::unique_ptr<gamemap> map_;
144
145 std::string map_hash_;
146
147private:
148 scenario(const scenario&) = delete;
149 scenario& operator=(const scenario&) = delete;
150
152};
153
154class user_map : public scenario
155{
156public:
157 user_map(const config& data, const std::string& name, gamemap* map);
158
159 void set_metadata();
160
161 /** For user maps, the id and name are the same. */
162 std::string id() const
163 {
164 return name_;
165 }
166
167 std::string name() const
168 {
169 return name_;
170 }
171
172 std::string description() const;
173
174private:
175 user_map(const user_map&) = delete;
176 user_map& operator=(const user_map&) = delete;
177
178 std::string name_;
179};
180
181class random_map : public scenario
182{
183public:
184 random_map(const config& data);
185
186 const config& generator_data() const
187 {
188 return generator_data_;
189 }
190
191 std::string generator_name() const
192 {
193 return generator_name_;
194 }
195
197
199 {
201 }
202
203private:
204 random_map(const random_map&) = delete;
205 random_map& operator=(const random_map&) = delete;
206
208
210 std::string generator_name_;
211};
212
213class campaign : public level
214{
215public:
216 campaign(const config& data);
217
218 bool can_launch_game() const;
219
220 void set_metadata();
221
222 void mark_if_completed();
223
224 std::string id() const
225 {
226 return id_;
227 }
228
229 bool allow_era_choice() const
230 {
231 return allow_era_choice_;
232 }
233
234 int min_players() const
235 {
236 return min_players_;
237 }
238
239 int max_players() const
240 {
241 return max_players_;
242 }
243
244 bool player_count_filter(int player_count) const
245 {
246 return min_players_ <= player_count && max_players_ >= player_count;
247 }
248
249 std::pair<utils::irdya_date, utils::irdya_date> dates() const
250 {
251 return dates_;
252 }
253
254private:
255 campaign(const campaign&) = delete;
256 campaign& operator=(const campaign&) = delete;
257
258 std::string id_;
260 std::string image_label_;
263 std::pair<utils::irdya_date, utils::irdya_date> dates_;
264};
265
267{
268public:
269 explicit create_engine(saved_game& state);
270
271 enum MP_EXTRA { ERA, MOD };
272
274 {
275 std::string id;
276 std::string name;
277 std::string description;
278 const config* cfg;
279 };
280
281 typedef std::shared_ptr<extras_metadata> extras_metadata_ptr;
282
283 typedef std::shared_ptr<level> level_ptr;
284 typedef std::shared_ptr<scenario> scenario_ptr;
285 typedef std::shared_ptr<user_map> user_map_ptr;
286 typedef std::shared_ptr<random_map> random_map_ptr;
287 typedef std::shared_ptr<campaign> campaign_ptr;
288
290
294 void prepare_for_campaign(const std::string& difficulty = "");
296 // random maps, user maps
297 void prepare_for_other();
298
299 /**
300 * select_campaign_difficulty
301 *
302 * Launches difficulty selection gui and returns selected difficulty name.
303 *
304 * The gui can be bypassed by supplying a number from 1 to the number of
305 * difficulties available, corresponding to a choice of difficulty.
306 * This is useful for specifying difficulty via command line.
307 *
308 * @param set_value Preselected difficulty number. The default -1 launches the gui.
309 * @return Selected difficulty. Returns "FAIL" if set_value is invalid,
310 * and "CANCEL" if the gui is canceled.
311 */
312 std::string select_campaign_difficulty(int set_value = -1);
314 {
316 }
317
318 void apply_level_filter(const std::string& name);
319 void apply_level_filter(int players);
320 void reset_level_filters();
321
322 const std::string& level_name_filter() const
323 {
324 return level_name_filter_;
325 }
326
328 {
330 }
331
332 std::vector<level_ptr> get_levels_by_type_unfiltered(level_type::type type) const;
333 std::vector<level_ptr> get_levels_by_type(level_type::type type) const;
334
335 std::vector<std::size_t> get_filtered_level_indices(level_type::type type) const;
336
337 level& current_level() const;
338 const extras_metadata& current_era() const;
339
340 void set_current_level_type(const level_type::type type)
341 {
342 current_level_type_ = type;
343 }
344
345 level_type::type current_level_type() const
346 {
347 return current_level_type_;
348 }
349
350 /** Wrapper to simplify the is-type-campaign-or-sp-campaign check. */
351 bool is_campaign() const
352 {
353 return current_level_type_ == level_type::type::campaign || current_level_type_ == level_type::type::sp_campaign;
354 }
355
356 void set_current_level(const std::size_t index);
357
358 void set_current_era_index(const std::size_t index, bool force = false);
359 void set_current_era_index(const std::string& id, bool force = false);
360
361 std::size_t current_era_index() const
362 {
363 return current_era_index_;
364 }
365
366 const config& curent_era_cfg() const;
367
368 const std::vector<extras_metadata_ptr>& get_const_extras_by_type(const MP_EXTRA extra_type) const;
369 std::vector<extras_metadata_ptr>& get_extras_by_type(const MP_EXTRA extra_type);
370
371 bool toggle_mod(const std::string& id, bool force = false);
372
373 bool generator_assigned() const;
374 bool generator_has_settings() const;
376
377 std::pair<level_type::type, int> find_level_by_id(const std::string& id) const;
378 int find_extra_by_id(const MP_EXTRA extra_type, const std::string& id) const;
379
381 {
382 return *dependency_manager_;
383 }
384
385 void init_active_mods();
386
387 std::vector<std::string>& active_mods();
388 std::vector<extras_metadata_ptr> active_mods_data();
389
391
393
394 /** Returns true if the current level has one or more [side] tags. */
396
397 int preset_id_by_index(int index) const { return preset_ids_.at(index); }
398
399private:
400 create_engine(const create_engine&) = delete;
402
403 void init_all_levels();
404 void init_extras(const MP_EXTRA extra_type);
405 void apply_level_filters();
406
407 level_type::type current_level_type_;
409
411 std::string current_era_id_;
412
415
417 {
418 explicit type_list() : games(), games_filtered() {}
419
420 std::vector<level_ptr> games;
421 std::vector<std::size_t> games_filtered;
422
423 void apply_filter(const int player_count, const std::string& name_filter)
424 {
425 games_filtered.clear();
426
427 for(std::size_t i = 0; i < games.size(); i++) {
428 const bool num_players_match = player_count == 1 || games[i]->player_count_filter(player_count);
429
430 if(contains_ignore_case(games[i]->name(), name_filter) && num_players_match) {
431 games_filtered.push_back(i);
432 }
433 }
434 }
435
437 {
438 games_filtered.resize(games.size());
439 std::iota(games_filtered.begin(), games_filtered.end(), 0);
440 }
441 };
442
443 std::map<level_type::type, type_list> type_map_;
444 std::vector<int> preset_ids_;
445
446 std::vector<std::string> user_map_names_;
447 std::vector<std::string> user_scenario_names_;
448
449 std::vector<extras_metadata_ptr> eras_;
450 std::vector<extras_metadata_ptr> mods_;
451
453
454 // Never nullptr
455 std::unique_ptr<depcheck::manager> dependency_manager_;
456
457 std::unique_ptr<map_generator> generator_;
458
460
461 /** Reference to the main game config. */
463};
464
465} // end namespace ng
A config object defines a single node in a WML file, with access to child nodes.
Definition config.hpp:157
A class grating read only view to a vector of config objects, viewed as one config with all children ...
Encapsulates the map of the game.
Definition map.hpp:176
campaign(const campaign &)=delete
std::pair< utils::irdya_date, utils::irdya_date > dates_
void mark_if_completed()
std::pair< utils::irdya_date, utils::irdya_date > dates() const
std::string image_label_
bool player_count_filter(int player_count) const
int max_players() const
int min_players() const
std::string id() const
std::string id_
bool can_launch_game() const
bool allow_era_choice() const
campaign & operator=(const campaign &)=delete
std::string level_name_filter_
int find_extra_by_id(const MP_EXTRA extra_type, const std::string &id) const
std::string get_selected_campaign_difficulty() const
std::string current_era_id_
std::shared_ptr< campaign > campaign_ptr
std::vector< std::size_t > get_filtered_level_indices(level_type::type type) const
bool toggle_mod(const std::string &id, bool force=false)
std::vector< int > preset_ids_
void set_current_era_index(const std::size_t index, bool force=false)
std::string select_campaign_difficulty(int set_value=-1)
select_campaign_difficulty
std::vector< level_ptr > get_levels_by_type(level_type::type type) const
std::string selected_campaign_difficulty_
bool generator_has_settings() const
std::vector< std::string > & active_mods()
std::vector< std::string > user_map_names_
bool current_level_has_side_data()
Returns true if the current level has one or more [side] tags.
bool generator_assigned() const
level_type::type current_level_type() const
std::map< level_type::type, type_list > type_map_
int preset_id_by_index(int index) const
void init_extras(const MP_EXTRA extra_type)
int player_num_filter() const
std::vector< extras_metadata_ptr > & get_extras_by_type(const MP_EXTRA extra_type)
std::shared_ptr< user_map > user_map_ptr
const std::vector< extras_metadata_ptr > & get_const_extras_by_type(const MP_EXTRA extra_type) const
void apply_level_filter(const std::string &name)
const extras_metadata & current_era() const
const std::string & level_name_filter() const
create_engine & operator=(const create_engine &)=delete
std::size_t current_era_index_
const config & curent_era_cfg() const
std::vector< extras_metadata_ptr > mods_
std::unique_ptr< depcheck::manager > dependency_manager_
const depcheck::manager & dependency_manager() const
std::vector< std::string > user_scenario_names_
std::vector< extras_metadata_ptr > active_mods_data()
std::shared_ptr< level > level_ptr
void set_current_level_type(const level_type::type type)
const game_config_view & game_config_
Reference to the main game config.
std::shared_ptr< random_map > random_map_ptr
std::unique_ptr< map_generator > generator_
std::pair< level_type::type, int > find_level_by_id(const std::string &id) const
saved_game & get_state()
bool is_campaign() const
Wrapper to simplify the is-type-campaign-or-sp-campaign check.
std::vector< extras_metadata_ptr > eras_
void prepare_for_campaign(const std::string &difficulty="")
std::vector< level_ptr > get_levels_by_type_unfiltered(level_type::type type) const
const mp_game_settings & get_parameters()
std::shared_ptr< extras_metadata > extras_metadata_ptr
void set_current_level(const std::size_t index)
std::size_t current_era_index() const
level_type::type current_level_type_
std::size_t current_level_index_
create_engine(const create_engine &)=delete
level & current_level() const
std::shared_ptr< scenario > scenario_ptr
Note to all triers: It's not guaranteed that the specified component will be selected (if the user de...
Definition depcheck.hpp:50
Base class for all level type classes.
virtual bool player_count_filter(int player_count) const =0
virtual bool can_launch_game() const =0
config & data()
void set_data(const config &data)
level(const level &)=delete
virtual std::string id() const
virtual std::string name() const
virtual ~level()=default
virtual void set_metadata()=0
const config & data() const
virtual bool allow_era_choice() const
level & operator=(const level &)=delete
virtual std::string icon() const
virtual std::string description() const
bool generate_whole_scenario() const
random_map & operator=(const random_map &)=delete
const config & generator_data() const
random_map(const random_map &)=delete
std::string generator_name() const
map_generator * create_map_generator() const
std::string generator_name_
std::string map_hash_
int num_players() const
std::unique_ptr< gamemap > map_
bool player_count_filter(int player_count) const
scenario & operator=(const scenario &)=delete
scenario(const scenario &)=delete
std::string map_size() const
bool can_launch_game() const
user_map & operator=(const user_map &)=delete
std::string id() const
For user maps, the id and name are the same.
std::string name_
std::string name() const
std::string description() const
user_map(const user_map &)=delete
Definitions for the interface to Wesnoth Markup Language (WML).
static bool contains_ignore_case(const std::string &str1, const std::string &str2)
std::vector< std::size_t > games_filtered
std::vector< level_ptr > games
void apply_filter(const int player_count, const std::string &name_filter)
#define i