X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Flevel.cpp;h=6c87b816e32e4c5e96a0103e96aa6be824fe346b;hb=5c14f6f384eff76491d494b4c157abf2ff776d49;hp=cc30db43fecd38fece279594542f572814dabde3;hpb=2074a5e3f8167dec24989c008ddadda14687a3a6;p=supertux.git diff --git a/src/level.cpp b/src/level.cpp index cc30db43f..6c87b816e 100644 --- a/src/level.cpp +++ b/src/level.cpp @@ -17,283 +17,203 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // 02111-1307, USA. +#include #include -#include -#include -#include +#include +#include +#include #include #include +#include +#include #include -#include "globals.h" -#include "setup.h" -#include "camera.h" -#include "screen/screen.h" -#include "level.h" -#include "physic.h" -#include "scene.h" -#include "sector.h" -#include "tile.h" -#include "lispreader.h" -#include "resources.h" -#include "music_manager.h" -#include "gameobjs.h" -#include "lispwriter.h" -using namespace std; +#include "video/screen.hpp" +#include "lisp/parser.hpp" +#include "lisp/lisp.hpp" +#include "lisp/list_iterator.hpp" +#include "lisp/writer.hpp" +#include "level.hpp" +#include "physic.hpp" +#include "sector.hpp" +#include "tile.hpp" +#include "resources.hpp" +#include "file_system.hpp" +#include "object/gameobjs.hpp" +#include "object/camera.hpp" +#include "object/tilemap.hpp" +#include "object/coin.hpp" + +// test +#include "flip_level_transformer.hpp" -LevelSubset::LevelSubset() - : image(0), levels(0) -{ -} - -LevelSubset::~LevelSubset() -{ - delete image; -} +using namespace std; -void LevelSubset::create(const std::string& subset_name) +Level::Level() + : name("noname"), author("Mr. X"), extro_music("leveldone.ogg"), extro_length(7.0) { - Level new_lev; - LevelSubset new_subset; - new_subset.name = subset_name; - new_subset.title = "Unknown Title"; - new_subset.description = "No description so far."; - new_subset.save(); - //new_lev.save(subset_name, 1, 0); } -void LevelSubset::parse (lisp_object_t* cursor) +void +Level::load(const std::string& filepath) { - while(!lisp_nil_p(cursor)) - { - lisp_object_t* cur = lisp_car(cursor); - char *s; + try { + lisp::Parser parser; + std::auto_ptr root (parser.parse(filepath)); + + const lisp::Lisp* level = root->get_lisp("supertux-level"); + if(!level) + throw std::runtime_error("file is not a supertux-level file."); + + int version = 1; + level->get("version", version); + if(version == 1) { + load_old_format(*level); + return; + } - if (!lisp_cons_p(cur) || !lisp_symbol_p (lisp_car(cur))) - { - printf("Not good"); + lisp::ListIterator iter(level); + while(iter.next()) { + const std::string& token = iter.item(); + if(token == "version") { + iter.value()->get(version); + if(version > 2) { + std::cerr << "Warning: level format newer than application.\n"; } - else - { - if (strcmp(lisp_symbol(lisp_car(cur)), "title") == 0) - { - if(( s = lisp_string(lisp_car(lisp_cdr(cur)))) != NULL) - { - title = s; - } - } - else if (strcmp(lisp_symbol(lisp_car(cur)), "description") == 0) - { - if(( s = lisp_string(lisp_car(lisp_cdr(cur)))) != NULL) - { - description = s; - } - } + } else if(token == "name") { + iter.value()->get(name); + } else if(token == "author") { + iter.value()->get(author); + } else if(token == "extro") { + const lisp::Lisp* ext = iter.lisp(); + lisp::ListIterator ext_iter(ext); + while(ext_iter.next()) { + const std::string& ext_token = ext_iter.item(); + if(ext_token == "music") { + ext_iter.value()->get(extro_music); + } else if(ext_token == "length") { + ext_iter.value()->get(extro_length); + } } - cursor = lisp_cdr (cursor); + } else if(token == "sector") { + Sector* sector = new Sector; + sector->parse(*(iter.lisp())); + add_sector(sector); + } else { + std::cerr << "Unknown token '" << token << "' in level file.\n"; + continue; + } } + + } catch(std::exception& e) { + std::stringstream msg; + msg << "Problem when reading level '" << filepath << "': " << e.what(); + throw std::runtime_error(msg.str()); + } } -void LevelSubset::load(const char* subset) +void +Level::load_old_format(const lisp::Lisp& reader) { - FILE* fi; - char filename[1024]; - char str[1024]; - int i; - lisp_object_t* root_obj = 0; - - name = subset; - - snprintf(filename, 1024, "%s/levels/%s/info", st_dir, subset); - if(!faccessible(filename)) - snprintf(filename, 1024, "%s/levels/%s/info", datadir.c_str(), subset); - if(faccessible(filename)) - { - fi = fopen(filename, "r"); - if (fi == NULL) - { - perror(filename); - } - lisp_stream_t stream; - lisp_stream_init_file (&stream, fi); - root_obj = lisp_read (&stream); - - if (root_obj->type == LISP_TYPE_EOF || root_obj->type == LISP_TYPE_PARSE_ERROR) - { - printf("World: Parse Error in file %s", filename); - } + reader.get("name", name); + reader.get("author", author); - lisp_object_t* cur = lisp_car(root_obj); - - if (!lisp_symbol_p (cur)) - { - printf("World: Read error in %s",filename); - } - - if (strcmp(lisp_symbol(cur), "supertux-level-subset") == 0) - { - parse(lisp_cdr(root_obj)); - - } - - lisp_free(root_obj); - fclose(fi); - - snprintf(str, 1024, "%s.png", filename); - if(faccessible(str)) - { - delete image; - image = new Surface(str,IGNORE_ALPHA); - } - else - { - snprintf(filename, 1024, "%s/images/status/level-subset-info.png", datadir.c_str()); - delete image; - image = new Surface(filename,IGNORE_ALPHA); - } - } - - for(i=1; i != -1; ++i) - { - /* Get the number of levels in this subset */ - snprintf(filename, 1024, "%s/levels/%s/level%d.stl", st_dir, subset,i); - if(!faccessible(filename)) - { - snprintf(filename, 1024, "%s/levels/%s/level%d.stl", datadir.c_str(), subset,i); - if(!faccessible(filename)) - break; - } - } - levels = --i; + Sector* sector = new Sector; + sector->parse_old_format(reader); + add_sector(sector); } void -LevelSubset::save() +Level::save(const std::string& filename) { - FILE* fi; - string filename; - - /* Save data file: */ - filename = "/levels/" + name + "/"; + lisp::Writer* writer = new lisp::Writer(filename); - fcreatedir(filename.c_str()); - filename = string(st_dir) + "/levels/" + name + "/info"; - if(!fwriteable(filename.c_str())) - filename = datadir + "/levels/" + name + "/info"; - if(fwriteable(filename.c_str())) - { - fi = fopen(filename.c_str(), "w"); - if (fi == NULL) - { - perror(filename.c_str()); - } + writer->write_comment("Level made using SuperTux's built-in Level Editor"); - /* Write header: */ - fprintf(fi,";SuperTux-Level-Subset\n"); - fprintf(fi,"(supertux-level-subset\n"); + writer->start_list("supertux-level"); - /* Save title info: */ - fprintf(fi," (title \"%s\")\n", title.c_str()); + int version = 2; + writer->write_int("version", version); - /* Save the description: */ - fprintf(fi," (description \"%s\")\n", description.c_str()); + writer->write_string("name", name, true); + writer->write_string("author", author); - fprintf( fi,")"); - fclose(fi); - } -} + for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i) { + Sector* sector = *i; + writer->start_list("sector"); + sector->write(*writer); + writer->end_list("sector"); + } -std::string -LevelSubset::get_level_filename(unsigned int num) -{ - char filename[1024]; - - // Load data file: - snprintf(filename, 1024, "%s/levels/%s/level%d.stl", st_dir, - name.c_str(), num); - if(!faccessible(filename)) - snprintf(filename, 1024, "%s/levels/%s/level%d.stl", datadir.c_str(), - name.c_str(), num); + writer->end_list("supertux-level"); - return std::string(filename); + delete writer; } -//--------------------------------------------------------------------------- - -Level::Level() - : name("noname"), author("mr. x"), time_left(500) +Level::~Level() { + for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i) + delete *i; } void -Level::load(const std::string& filename) +Level::add_sector(Sector* sector) { - LispReader* level = LispReader::load(filename, "supertux-level"); - - int version = 1; - level->read_int("version", version); - if(version == 1) { - load_old_format(*level); - return; - } - - for(lisp_object_t* cur = level->get_lisp(); !lisp_nil_p(cur); - cur = lisp_cdr(cur)) { - std::string token = lisp_symbol(lisp_car(lisp_car(cur))); - lisp_object_t* data = lisp_car(lisp_cdr(lisp_car(cur))); - LispReader reader(lisp_cdr(lisp_car(cur))); - - if(token == "name") { - name = lisp_string(data); - } else if(token == "author") { - author = lisp_string(data); - } else if(token == "time") { - time_left = lisp_integer(data); - } else if(token == "sector") { - Sector* sector = new Sector; - sector->parse(reader); - add_sector(sector); - } else { - std::cerr << "Unknown token '" << token << "' in level file.\n"; - continue; - } + Sector* test = get_sector(sector->get_name()); + if(test != 0) { + throw std::runtime_error("Trying to add 2 sectors with same name"); } - - delete level; + sectors.push_back(sector); } -void -Level::load_old_format(LispReader& reader) +Sector* +Level::get_sector(const std::string& name) { - reader.read_string("name", name); - reader.read_string("author", author); - reader.read_int("time", time_left); + for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i) { + Sector* sector = *i; + if(sector->get_name() == name) + return sector; + } - Sector* sector = new Sector; - sector->parse_old_format(reader); - add_sector(sector); + return 0; } -Level::~Level() +size_t +Level::get_sector_count() { - for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i) - delete i->second; + return sectors.size(); } -void -Level::add_sector(Sector* sector) +Sector* +Level::get_sector(size_t num) { - sectors.insert(std::make_pair(sector->get_name(), sector)); + return sectors.at(num); } -Sector* -Level::get_sector(const std::string& name) +int +Level::get_total_badguys() { - Sectors::iterator i = sectors.find(name); - if(i == sectors.end()) - return 0; + int total_badguys = 0; + for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i) + total_badguys += (*i)->get_total_badguys(); + return total_badguys; +} - return i->second; +int +Level::get_total_coins() +{ + // FIXME not really correct as coins can also be inside blocks... + int total_coins = 0; + for(Sectors::iterator i = sectors.begin(); i != sectors.end(); ++i) { + Sector* sector = *i; + for(Sector::GameObjects::iterator o = sector->gameobjects.begin(); + o != sector->gameobjects.end(); ++o) { + Coin* coin = dynamic_cast (*o); + if(coin) + total_coins++; + } + } + return total_coins; }