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