From 45d21c1c59a58aa557b62d3aa22ba89a975e323c Mon Sep 17 00:00:00 2001 From: Matthias Braun Date: Thu, 2 Dec 2004 00:25:27 +0000 Subject: [PATCH] changed worldmap to be stored inside the same directory as the levelsubset, fixed badguys writing out their current position instead of their startposition when saving levelfile SVN-Revision: 2235 --- data/levels/bonus1/info | 13 +-- .../bonusisland1.stwm => bonus1/worldmap.stwm} | 46 ++++----- .../icyisland.stwm => world1/worldmap.stwm} | 52 +++++----- lib/app/setup.cpp | 6 +- lib/app/setup.h | 6 +- lib/video/font.cpp | 2 + src/badguy/bouncing_snowball.cpp | 4 +- src/badguy/dispenser.cpp | 4 +- src/badguy/jumpy.cpp | 4 +- src/badguy/mrbomb.cpp | 4 +- src/badguy/mriceblock.cpp | 4 +- src/badguy/nolok_01.cpp | 4 +- src/badguy/snowball.cpp | 4 +- src/badguy/spiky.cpp | 4 +- src/gameloop.cpp | 2 +- src/level_subset.cpp | 14 +++ src/level_subset.h | 2 + src/title.cpp | 106 +++++++-------------- src/worldmap.cpp | 16 ++-- src/worldmap.h | 1 + 20 files changed, 139 insertions(+), 159 deletions(-) rename data/levels/{worldmap/bonusisland1.stwm => bonus1/worldmap.stwm} (93%) rename data/levels/{worldmap/icyisland.stwm => world1/worldmap.stwm} (85%) diff --git a/data/levels/bonus1/info b/data/levels/bonus1/info index 316eee70a..1060a140f 100644 --- a/data/levels/bonus1/info +++ b/data/levels/bonus1/info @@ -1,14 +1,5 @@ ;SuperTux-Level-Subset (supertux-level-subset - (title "Bonus World 1 levels") + (title "Bonus World 1") (description "Levels from the Bonus World 1") - (levels "abednego-level1.stl" "abednego-level2.stl" "abednego-level3.stl" - "abednego-level4.stl" "bonus-level1.stl" "bonus-level2.stl" - "bonus-level3.stl" "bonus-level4.stl" "bonus-level5.stl" - "matr1x-level1.stl" "matr1x-level2.stl" "matr1x-level3.stl" - "thompson-level1.stl" "thompson-level2.stl" "torfi-level1.stl" - "torfi-level2.stl" "torfi-level3.stl" "wansti-level1.stl" - "wansti-level2.stl" "wansti-level3.stl" "wansti-level4.stl" - "wansti-level5.stl") - (hide-from-contribs #t) - ) \ No newline at end of file +) diff --git a/data/levels/worldmap/bonusisland1.stwm b/data/levels/bonus1/worldmap.stwm similarity index 93% rename from data/levels/worldmap/bonusisland1.stwm rename to data/levels/bonus1/worldmap.stwm index 9ebecc8d8..47b682efd 100644 --- a/data/levels/worldmap/bonusisland1.stwm +++ b/data/levels/bonus1/worldmap.stwm @@ -61,71 +61,71 @@ )) (special-tiles - (level (name "bonus1/bonus-level1.stl") + (level (name "bonus-level1.stl") (x 35) (y 4)) - (level (name "bonus1/bonus-level2.stl") + (level (name "bonus-level2.stl") (x 32) (y 41)) - (level (name "bonus1/bonus-level3.stl") + (level (name "/bonus-level3.stl") (x 30) (y 39)) - (level (name "bonus1/bonus-level4.stl") + (level (name "/bonus-level4.stl") (extro-filelevel "extro-bonus.txt") (x 32) (y 46)) - (level (name "bonus1/bonus-level5.stl") + (level (name "bonus-level5.stl") (x 44) - (y 39)) - (level (name "bonus1/abednego-level1.stl") + (y 39)) + (level (name "abednego-level1.stl") (x 12) (y 33)) - (level (name "bonus1/abednego-level2.stl") + (level (name "abednego-level2.stl") (x 15) (y 35)) - (level (name "bonus1/abednego-level3.stl") + (level (name "abednego-level3.stl") (x 18) (y 36)) - (level (name "bonus1/abednego-level4.stl") + (level (name "abednego-level4.stl") (x 16) (y 40)) - (level (name "bonus1/matr1x-level1.stl") + (level (name "matr1x-level1.stl") (x 21) (y 17)) - (level (name "bonus1/matr1x-level2.stl") + (level (name "matr1x-level2.stl") (x 25) (y 18)) - (level (name "bonus1/matr1x-level3.stl") + (level (name "matr1x-level3.stl") (x 20) (y 20)) - (level (name "bonus1/thompson-level1.stl") + (level (name "thompson-level1.stl") (x 35) (y 20)) - (level (name "bonus1/thompson-level2.stl") + (level (name "thompson-level2.stl") (x 37) (y 22)) - (level (name "bonus1/torfi-level1.stl") + (level (name "torfi-level1.stl") (x 58) (y 34)) - (level (name "bonus1/torfi-level2.stl") + (level (name "torfi-level2.stl") (x 57) (y 38)) - (level (name "bonus1/torfi-level3.stl") + (level (name "torfi-level3.stl") (x 59) (y 40)) - (level (name "bonus1/wansti-level1.stl") + (level (name "wansti-level1.stl") (x 51) (y 14)) - (level (name "bonus1/wansti-level2.stl") + (level (name "wansti-level2.stl") (x 53) (y 16)) - (level (name "bonus1/wansti-level3.stl") + (level (name "wansti-level3.stl") (x 52) (y 20)) - (level (name "bonus1/wansti-level4.stl") + (level (name "wansti-level4.stl") (x 47) (y 18)) - (level (name "bonus1/wansti-level5.stl") + (level (name "wansti-level5.stl") (x 50) (y 22)) diff --git a/data/levels/worldmap/icyisland.stwm b/data/levels/world1/worldmap.stwm similarity index 85% rename from data/levels/worldmap/icyisland.stwm rename to data/levels/world1/worldmap.stwm index 6051289e2..d79b09af4 100644 --- a/data/levels/worldmap/icyisland.stwm +++ b/data/levels/world1/worldmap.stwm @@ -49,108 +49,108 @@ (level (x 4) (y 6) - (name "world1/level1.stl")) + (name "level1.stl")) (level (x 4) (y 8) - (name "world1/level2.stl")) + (name "level2.stl")) (level (x 5) (y 11) - (name "world1/level3.stl")) + (name "level3.stl")) (level (x 7) (y 11) - (name "world1/level4.stl")) + (name "level4.stl")) (level (x 7) (y 8) - (name "world1/level5.stl")) + (name "level5.stl")) (level (x 11) (y 9) - (name "world1/level6.stl")) + (name "level6.stl")) (level (x 14) (y 9) - (name "world1/level7.stl")) + (name "level7.stl")) (level (x 17) (y 6) - (name "world1/level8.stl")) + (name "level8.stl")) (level (x 14) (y 6) - (name "world1/level9.stl")) + (name "level9.stl")) (level (x 21) (y 8) - (name "world1/level10.stl")) + (name "level10.stl")) (level (x 26) (y 7) - (name "world1/level11.stl")) + (name "level11.stl")) (level (x 28) (y 9) - (name "world1/level12.stl")) + (name "level12.stl")) (level (x 31) (y 9) - (name "world1/level13.stl")) + (name "level13.stl")) (level (x 34) (y 11) - (name "world1/level14.stl")) + (name "level14.stl")) (level (x 29) (y 11) - (name "world1/level15.stl")) + (name "level15.stl")) (level (x 28) (y 13) - (name "world1/level16.stl")) + (name "level16.stl")) (level (x 29) (y 16) - (name "world1/level17.stl")) + (name "level17.stl")) (level (x 27) (y 19) - (name "world1/level18.stl")) + (name "level18.stl")) (level (x 23) (y 22) - (name "world1/level19.stl")) + (name "level19.stl")) (level (x 20) (y 25) - (name "world1/level20.stl")) + (name "level20.stl")) (level (x 18) (y 23) - (name "world1/level21.stl")) + (name "level21.stl")) (level (x 19) (y 20) - (name "world1/level22.stl")) + (name "level22.stl")) (level (x 14) (y 24) - (name "world1/level23.stl")) + (name "level23.stl")) (level (x 14) (y 20) - (name "world1/level24.stl")) + (name "level24.stl")) (level (x 10) (y 22) - (name "world1/level25.stl")) + (name "level25.stl")) (level (x 7) (y 20) (extro-filename "extro.txt") - (name "world1/level26.stl") + (name "level26.stl") (quit-worldmap #t)) ; In the future, do this to go to another world: ; (next-worldmap "forest.stwt) diff --git a/lib/app/setup.cpp b/lib/app/setup.cpp index 0a29dc4b9..d8c10af4c 100644 --- a/lib/app/setup.cpp +++ b/lib/app/setup.cpp @@ -67,7 +67,7 @@ void seticon(void); void usage(char * prog, int ret); /* Does the given file exist and is it accessible? */ -int FileSystem::faccessible(const std::string& filename) +bool FileSystem::faccessible(const std::string& filename) { struct stat filestat; if (stat(filename.c_str(), &filestat) == -1) @@ -84,7 +84,7 @@ int FileSystem::faccessible(const std::string& filename) } /* Can we write to this location? */ -int FileSystem::fwriteable(const std::string& filename) +bool FileSystem::fwriteable(const std::string& filename) { FILE* fi; fi = fopen(filename.c_str(), "wa"); @@ -97,7 +97,7 @@ int FileSystem::fwriteable(const std::string& filename) } /* Makes sure a directory is created in either the SuperTux home directory or the SuperTux base directory.*/ -int FileSystem::fcreatedir(const std::string& relative_dir) +bool FileSystem::fcreatedir(const std::string& relative_dir) { std::string path = st_dir + "/" + relative_dir + "/"; if(mkdir(path.c_str(),0755) != 0) diff --git a/lib/app/setup.h b/lib/app/setup.h index f48a4ab14..a918b4b25 100644 --- a/lib/app/setup.h +++ b/lib/app/setup.h @@ -29,9 +29,9 @@ namespace SuperTux { /// File system utility functions struct FileSystem { - static int faccessible(const std::string& filename); - static int fcreatedir(const std::string& relative_dir); - static int fwriteable(const std::string& filename); + static bool faccessible(const std::string& filename); + static bool fcreatedir(const std::string& relative_dir); + static bool fwriteable(const std::string& filename); static std::set read_directory(const std::string& pathname); static std::set dsubdirs(const std::string& rel_path, const std::string& expected_file); static std::set dfiles(const std::string& rel_path, const std::string& glob, const std::string& exception_str); diff --git a/lib/video/font.cpp b/lib/video/font.cpp index 303193b02..3ae918da2 100644 --- a/lib/video/font.cpp +++ b/lib/video/font.cpp @@ -223,6 +223,8 @@ void SuperTux::display_text_file(const std::string& file, float scroll_speed, if(!text_lisp->get("text", text)) throw std::runtime_error("file doesn't contain a text field"); + if(!text_lisp->get("background", background_file)) + throw std::runtime_error("file doesn't contain a background file"); } catch(std::exception& e) { std::cerr << "Couldn't load file '" << filename << "': " << e.what() << "\n"; diff --git a/src/badguy/bouncing_snowball.cpp b/src/badguy/bouncing_snowball.cpp index 06d70f8f0..912e52375 100644 --- a/src/badguy/bouncing_snowball.cpp +++ b/src/badguy/bouncing_snowball.cpp @@ -29,8 +29,8 @@ BouncingSnowball::write(lisp::Writer& writer) { writer.start_list("bouncingsnowball"); - writer.write_float("x", get_pos().x); - writer.write_float("y", get_pos().y); + writer.write_float("x", start_position.x); + writer.write_float("y", start_position.y); writer.end_list("bouncingsnowball"); } diff --git a/src/badguy/dispenser.cpp b/src/badguy/dispenser.cpp index 5f18cc77b..f3445b3f7 100644 --- a/src/badguy/dispenser.cpp +++ b/src/badguy/dispenser.cpp @@ -22,8 +22,8 @@ Dispenser::write(lisp::Writer& writer) { writer.start_list("dispenser"); - writer.write_float("x", get_pos().x); - writer.write_float("y", get_pos().y); + writer.write_float("x", start_position.x); + writer.write_float("y", start_position.y); writer.write_float("cycle", cycle); writer.write_string("badguy", badguy); diff --git a/src/badguy/jumpy.cpp b/src/badguy/jumpy.cpp index abc48ab6c..6739a54a7 100644 --- a/src/badguy/jumpy.cpp +++ b/src/badguy/jumpy.cpp @@ -17,8 +17,8 @@ Jumpy::write(lisp::Writer& writer) { writer.start_list("jumpy"); - writer.write_float("x", get_pos().x); - writer.write_float("y", get_pos().y); + writer.write_float("x", start_position.x); + writer.write_float("y", start_position.y); writer.end_list("jumpy"); } diff --git a/src/badguy/mrbomb.cpp b/src/badguy/mrbomb.cpp index 563cd6fdc..215284299 100644 --- a/src/badguy/mrbomb.cpp +++ b/src/badguy/mrbomb.cpp @@ -29,8 +29,8 @@ MrBomb::write(lisp::Writer& writer) { writer.start_list("mrbomb"); - writer.write_float("x", get_pos().x); - writer.write_float("y", get_pos().y); + writer.write_float("x", start_position.x); + writer.write_float("y", start_position.y); writer.end_list("mrbomb"); } diff --git a/src/badguy/mriceblock.cpp b/src/badguy/mriceblock.cpp index 9c5ad78e2..6a76d6908 100644 --- a/src/badguy/mriceblock.cpp +++ b/src/badguy/mriceblock.cpp @@ -33,8 +33,8 @@ MrIceBlock::write(lisp::Writer& writer) { writer.start_list("mriceblock"); - writer.write_float("x", get_pos().x); - writer.write_float("y", get_pos().y); + writer.write_float("x", start_position.x); + writer.write_float("y", start_position.y); writer.end_list("mriceblock"); } diff --git a/src/badguy/nolok_01.cpp b/src/badguy/nolok_01.cpp index ac3a8e170..1a5768fe6 100644 --- a/src/badguy/nolok_01.cpp +++ b/src/badguy/nolok_01.cpp @@ -33,8 +33,8 @@ Nolok_01::write(lisp::Writer& writer) { writer.start_list("nolok01"); - writer.write_float("x", get_pos().x); - writer.write_float("y", get_pos().y); + writer.write_float("x", start_position.x); + writer.write_float("y", start_position.y); writer.end_list("nolok01"); } diff --git a/src/badguy/snowball.cpp b/src/badguy/snowball.cpp index 4efd93874..75f68b450 100644 --- a/src/badguy/snowball.cpp +++ b/src/badguy/snowball.cpp @@ -28,8 +28,8 @@ SnowBall::write(lisp::Writer& writer) { writer.start_list("snowball"); - writer.write_float("x", get_pos().x); - writer.write_float("y", get_pos().y); + writer.write_float("x", start_position.x); + writer.write_float("y", start_position.y); writer.end_list("snowball"); } diff --git a/src/badguy/spiky.cpp b/src/badguy/spiky.cpp index b419740df..49d7e4c57 100644 --- a/src/badguy/spiky.cpp +++ b/src/badguy/spiky.cpp @@ -17,8 +17,8 @@ Spiky::write(lisp::Writer& writer) { writer.start_list("spiky"); - writer.write_float("x", get_pos().x); - writer.write_float("y", get_pos().y); + writer.write_float("x", start_position.x); + writer.write_float("y", start_position.y); writer.end_list("spiky"); } diff --git a/src/gameloop.cpp b/src/gameloop.cpp index de7c3b340..e793a1954 100644 --- a/src/gameloop.cpp +++ b/src/gameloop.cpp @@ -978,7 +978,7 @@ bool process_load_game_menu() WorldMapNS::WorldMap worldmap; - worldmap.set_map_filename("icyisland.stwm"); + worldmap.set_map_filename("/levels/world1/worldmap.stwm"); // Load the game or at least set the savegame_file variable worldmap.loadgame(slotfile); diff --git a/src/level_subset.cpp b/src/level_subset.cpp index 5cd4fc9d1..9d1b246b6 100644 --- a/src/level_subset.cpp +++ b/src/level_subset.cpp @@ -102,6 +102,14 @@ void LevelSubset::load(const std::string& subset) throw new std::runtime_error(msg.str()); } + // test is a worldmap exists + has_worldmap = false; + std::string worldmap = get_resource_filename( + std::string("levels/") + subset + "/worldmap.stwm"); + if(worldmap != "") { + has_worldmap = true; + } + if (levels.empty()) { // Level info file doesn't define any levels, so read the // directory to see what we can find @@ -175,6 +183,12 @@ LevelSubset::get_level_filename(unsigned int num) return levels[num]; } +std::string +LevelSubset::get_worldmap_filename() +{ + return std::string("/levels/" + name + "/worldmap.stwm"); +} + int LevelSubset::get_num_levels() const { diff --git a/src/level_subset.h b/src/level_subset.h index 7ae03e25a..c6ed9a995 100644 --- a/src/level_subset.h +++ b/src/level_subset.h @@ -46,12 +46,14 @@ public: void add_level(const std::string& name); std::string get_level_filename(unsigned int i); + std::string get_worldmap_filename(); int get_num_levels() const; std::string name; std::string title; std::string description; bool hide_from_contribs; + bool has_worldmap; private: void read_info_file(const std::string& info_file); diff --git a/src/title.cpp b/src/title.cpp index 1e5449ef3..fad1e8100 100644 --- a/src/title.cpp +++ b/src/title.cpp @@ -75,9 +75,6 @@ static GameSession* titlesession; static std::vector contrib_subsets; static LevelSubset* current_contrib_subset = 0; -static int first_level_index; - -static std::set worldmap_list; static FrameRate frame_rate(100); @@ -126,28 +123,17 @@ void generate_contrib_menu() contrib_menu->additem(MN_LABEL,_("Contrib Levels"),0,0); contrib_menu->additem(MN_HL,"",0,0); + int i = 0; - - for(std::set::iterator it = worldmap_list.begin(); - it != worldmap_list.end(); ++it) { - WorldMapNS::WorldMap worldmap; - worldmap.loadmap((*it).c_str()); - contrib_menu->additem(MN_ACTION, worldmap.get_world_title(),0,0, i); - ++i; - } - - contrib_menu->additem(MN_HL,"",0,0); - - first_level_index = i; - for (std::set::iterator it = level_subsets.begin(); it != level_subsets.end(); ++it) + for (std::set::iterator it = level_subsets.begin(); + it != level_subsets.end(); ++it) { LevelSubset* subset = new LevelSubset(); subset->load(*it); - if(subset->hide_from_contribs) - { + if(subset->hide_from_contribs) { delete subset; continue; - } + } contrib_menu->additem(MN_GOTO, subset->title, 0, contrib_subset_menu, i); contrib_subsets.push_back(subset); ++i; @@ -186,68 +172,52 @@ void check_levels_contrib_menu() if (index == -1) return; - if((unsigned)index < worldmap_list.size()) - { + LevelSubset& subset = * (contrib_subsets[index]); + + if(subset.has_worldmap) { WorldMapNS::WorldMap worldmap; - std::set::iterator it = worldmap_list.begin(); - for(int i = index; i > 0; --i) - ++it; - - std::string map_filename = *it; + worldmap.set_map_filename(subset.get_worldmap_filename()); // some fading fadeout(256); DrawingContext context; - context.draw_text(white_text, "Loading...", - Vector(screen->w/2, screen->h/2), CENTER_ALLIGN, LAYER_FOREGROUND1); - context.do_drawing(); - - worldmap.set_map_filename(map_filename); - - // hack to erase the extension - unsigned int ext_pos = it->find_last_of("."); - if(ext_pos != std::string::npos) - map_filename.erase(ext_pos, map_filename.size() - ext_pos); + context.draw_text(white_text, "Loading...", + Vector(screen->w/2, screen->h/2), CENTER_ALLIGN, LAYER_FOREGROUND1); + context.do_drawing(); // TODO: slots should be available for contrib maps - worldmap.loadgame(st_save_dir + "/" + map_filename + "-slot1.stsg"); + worldmap.loadgame(st_save_dir + "/" + subset.name + "-slot1.stsg"); worldmap.display(); // run the map Menu::set_current(main_menu); resume_demo(); - } - else if (index < (int)contrib_subsets.size() + first_level_index) - { - index -= first_level_index; - if (current_subset != index) - { - current_subset = index; - // FIXME: This shouln't be busy looping - LevelSubset& subset = * (contrib_subsets[index]); - - current_contrib_subset = ⊂ - - contrib_subset_menu->clear(); - - contrib_subset_menu->additem(MN_LABEL, subset.title, 0,0); - contrib_subset_menu->additem(MN_HL,"",0,0); - - for (int i = 0; i < subset.get_num_levels(); ++i) - { - /** get level's title */ - std::string filename = subset.get_level_filename(i); - std::string title = get_level_name(filename); - contrib_subset_menu->additem(MN_ACTION, title, 0, 0, i); - } + } else if (current_subset != index) { + current_subset = index; + // FIXME: This shouln't be busy looping + LevelSubset& subset = * (contrib_subsets[index]); - contrib_subset_menu->additem(MN_HL,"",0,0); - contrib_subset_menu->additem(MN_BACK, _("Back"), 0, 0); + current_contrib_subset = ⊂ - titlesession->get_current_sector()->activate(); - titlesession->set_current(); - } + contrib_subset_menu->clear(); + + contrib_subset_menu->additem(MN_LABEL, subset.title, 0,0); + contrib_subset_menu->additem(MN_HL,"",0,0); + + for (int i = 0; i < subset.get_num_levels(); ++i) + { + /** get level's title */ + std::string filename = subset.get_level_filename(i); + std::string title = get_level_name(filename); + contrib_subset_menu->additem(MN_ACTION, title, 0, 0, i); } + + contrib_subset_menu->additem(MN_HL,"",0,0); + contrib_subset_menu->additem(MN_BACK, _("Back"), 0, 0); + + titlesession->get_current_sector()->activate(); + titlesession->set_current(); + } } void check_contrib_subset_menu() @@ -327,9 +297,6 @@ void title(void) logo = new Surface(datadir + "/images/title/logo.png", true); img_choose_subset = new Surface(datadir + "/images/status/choose-level-subset.png", true); - /* Generating contrib maps by only using a string_list */ - worldmap_list = FileSystem::dfiles("levels/worldmap", "", "icyisland.stwm"); - titlesession->get_current_sector()->activate(); titlesession->set_current(); @@ -474,7 +441,6 @@ void title(void) /* Free surfaces: */ free_contrib_menu(); - worldmap_list.clear(); delete titlesession; delete bkg_title; delete logo; diff --git a/src/worldmap.cpp b/src/worldmap.cpp index 1c4ab3e10..53d8fc28c 100644 --- a/src/worldmap.cpp +++ b/src/worldmap.cpp @@ -368,17 +368,22 @@ WorldMap::~WorldMap() void WorldMap::load_map() { + std::string::size_type p = map_filename.find_last_of('/'); + if(p == std::string::npos) + levels_path = ""; + else + levels_path = map_filename.substr(0, p+1); + try { lisp::Parser parser; - std::string filename - = get_resource_filename("/levels/worldmap/" + map_filename); + std::string filename = get_resource_filename(map_filename); std::auto_ptr root (parser.parse(filename)); const lisp::Lisp* lisp = root->get_lisp("supertux-worldmap"); if(!lisp) throw new std::runtime_error("file isn't a supertux-worldmap file."); - lisp::ListIterator iter(lisp->get_cdr()); + lisp::ListIterator iter(lisp); while(iter.next()) { if(iter.item() == "tilemap") { if(tilemap.size() > 0) @@ -498,7 +503,7 @@ WorldMap::get_level_title(Level& level) try { lisp::Parser parser; std::auto_ptr root ( - parser.parse(get_resource_filename("levels/" + level.name))); + parser.parse(get_resource_filename(levels_path + level.name))); const lisp::Lisp* level_lisp = root->get_lisp("supertux-level"); if(!level_lisp) @@ -718,8 +723,7 @@ WorldMap::update(float delta) // do a shriking fade to the level shrink_fade(Vector((level->pos.x*32 + 16 + offset.x), (level->pos.y*32 + 16 + offset.y)), 500); - GameSession session( - get_resource_filename(std::string("levels/" + level->name)), + GameSession session(get_resource_filename(levels_path + level->name), ST_GL_LOAD_LEVEL_FILE, &level->statistics); switch (session.run()) diff --git a/src/worldmap.h b/src/worldmap.h index 80585ea22..0403e2f62 100644 --- a/src/worldmap.h +++ b/src/worldmap.h @@ -185,6 +185,7 @@ public: private: std::string map_filename; + std::string levels_path; typedef std::vector SpecialTiles; SpecialTiles special_tiles; -- 2.11.0