game.cpp

Go to the documentation of this file.
00001 /* $Id: game.cpp 53562 2012-03-20 04:33:09Z shadowmaster $ */
00002 /*
00003    Copyright (C) 2003 - 2012 by David White <dave@whitevine.net>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
00014 */
00015 
00016 #include "global.hpp"
00017 
00018 #include "about.hpp"
00019 #include "addon/manager.hpp"
00020 #include "addon/manager_ui.hpp"
00021 #include "commandline_options.hpp"
00022 #include "game_controller.hpp"
00023 #include "game_controller_new.hpp"
00024 #include "gui/dialogs/title_screen.hpp"
00025 #ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
00026 #include "gui/widgets/debug.hpp"
00027 #endif
00028 #include "gui/widgets/window.hpp"
00029 #include "help.hpp"
00030 #include "loadscreen.hpp"
00031 #include "playcampaign.hpp"
00032 #include "preferences_display.hpp"
00033 #include "replay.hpp"
00034 #include "statistics.hpp"
00035 #include "serialization/parser.hpp"
00036 #include "serialization/validator.hpp"
00037 #include "version.hpp"
00038 
00039 #include <cerrno>
00040 #include <clocale>
00041 #include <fstream>
00042 #include <libintl.h>
00043 
00044 #include <boost/iostreams/copy.hpp>
00045 #include <boost/iostreams/filter/gzip.hpp>
00046 
00047 #ifdef HAVE_VISUAL_LEAK_DETECTOR
00048 #include "vld.h"
00049 #endif
00050 
00051 // Minimum stack cookie to prevent stack overflow on AmigaOS4
00052 #ifdef __amigaos4__
00053 const char __attribute__((used)) stackcookie[] = "\0$STACK: 16000000";
00054 #endif
00055 
00056 static lg::log_domain log_config("config");
00057 #define LOG_CONFIG LOG_STREAM(info, log_config)
00058 
00059 #define LOG_GENERAL LOG_STREAM(info, lg::general)
00060 
00061 static lg::log_domain log_preprocessor("preprocessor");
00062 #define LOG_PREPROC LOG_STREAM(info,log_preprocessor)
00063 
00064 // this is needed to allow identical functionality with clean refactoring
00065 // play_game only returns on an error, all returns within play_game can
00066 // be replaced with this
00067 static void safe_exit(int res) {
00068 
00069     LOG_GENERAL << "exiting with code " << res << "\n";
00070 #ifdef OS2 /* required to correctly shutdown SDL on OS/2 */
00071         SDL_Quit();
00072 #endif
00073     exit(res);
00074 }
00075 
00076 // maybe this should go in a util file somewhere?
00077 static void gzip_codec(const std::string & input_file, const std::string & output_file, bool encode)
00078 {
00079     try {
00080         std::ofstream ofile(output_file.c_str(), std::ios_base::out
00081                 | std::ios_base::binary);
00082         std::ifstream ifile(input_file.c_str(),
00083         std::ios_base::in | std::ios_base::binary);
00084         boost::iostreams::filtering_streambuf<boost::iostreams::input> in;
00085         if(encode)
00086             in.push(boost::iostreams::gzip_compressor());
00087         else
00088             in.push(boost::iostreams::gzip_decompressor());
00089         in.push(ifile);
00090         boost::iostreams::copy(in, ofile);
00091             ifile.close();
00092         safe_exit(remove(input_file.c_str()));
00093         }  catch(io_exception& e) {
00094         std::cerr << "IO error: " << e.what() << "\n";
00095     }
00096 }
00097 
00098 static void gzip_encode(const std::string & input_file, const std::string & output_file)
00099 {
00100     gzip_codec(input_file, output_file, true);
00101 }
00102 
00103 static void gzip_decode(const std::string & input_file, const std::string & output_file)
00104 {
00105     gzip_codec(input_file, output_file, false);
00106 }
00107 
00108 /** Process commandline-arguments */
00109 static int process_command_args(const commandline_options& cmdline_opts) {
00110 
00111     // Options that don't change behaviour based on any others should be checked alphabetically below.
00112 
00113     if(cmdline_opts.config_dir) {
00114         set_preferences_dir(*cmdline_opts.config_dir);
00115     }
00116     if(cmdline_opts.config_path) {
00117         std::cout << get_user_data_dir() << '\n';
00118         return 0;
00119     }
00120     if(cmdline_opts.data_dir) {
00121         const std::string datadir = *cmdline_opts.data_dir;
00122         std::cerr << "Overriding data directory with " << datadir << std::endl;
00123 #ifdef _WIN32
00124         // use c_str to ensure that index 1 points to valid element since c_str() returns null-terminated string
00125         if(datadir.c_str()[1] == ':') {
00126 #else
00127         if(datadir[0] == '/') {
00128 #endif
00129             game_config::path = datadir;
00130         } else {
00131             game_config::path = get_cwd() + '/' + datadir;
00132         }
00133 
00134         if(!is_directory(game_config::path)) {
00135             std::cerr << "Could not find directory '" << game_config::path << "'\n";
00136             throw config::error("directory not found");
00137         }
00138     // don't update font as we already updating it in game ctor
00139     //font_manager_.update_font_path();
00140     }
00141     if(cmdline_opts.gunzip) {
00142         const std::string input_file(*cmdline_opts.gunzip);
00143         if(!is_gzip_file(input_file)) {
00144             std::cerr << "file '" << input_file << "'isn't a .gz file\n";
00145             return 2;
00146         }
00147         const std::string output_file(
00148             input_file, 0, input_file.length() - 3);
00149         gzip_decode(input_file, output_file);
00150     }
00151     if(cmdline_opts.gzip) {
00152         const std::string input_file(*cmdline_opts.gzip);
00153         const std::string output_file(*cmdline_opts.gzip + ".gz");
00154         gzip_encode(input_file, output_file);
00155     }
00156     if(cmdline_opts.help) {
00157         std::cout << cmdline_opts;
00158         return 0;
00159     }
00160     if(cmdline_opts.log) {
00161         for(std::vector<boost::tuple<int, std::string> >::const_iterator it=cmdline_opts.log->begin(); it!=cmdline_opts.log->end(); ++it)
00162         {
00163             const std::string log_domain = it->get<1>();
00164             const int severity = it->get<0>();
00165             if (!lg::set_log_domain_severity(log_domain, severity))
00166             {
00167                 std::cerr << "unknown log domain: " << log_domain << '\n';
00168                 return 2;
00169             }
00170         }
00171     }
00172     if(cmdline_opts.logdomains) {
00173         std::cout << lg::list_logdomains(*cmdline_opts.logdomains);
00174         return 0;
00175     }
00176     if(cmdline_opts.new_syntax) {
00177         game_config::new_syntax = true;
00178     }
00179     if(cmdline_opts.path) {
00180         std::cout <<  game_config::path << "\n";
00181         return 0;
00182     }
00183     if(cmdline_opts.rng_seed) {
00184         srand(*cmdline_opts.rng_seed);
00185     }
00186     if(cmdline_opts.screenshot) {
00187         static char opt[] = "SDL_VIDEODRIVER=dummy";
00188         SDL_putenv(opt);
00189     }
00190     if(cmdline_opts.strict_validation) {
00191         strict_validation_enabled = true;
00192     }
00193     if(cmdline_opts.version) {
00194         std::cout << "Battle for Wesnoth" << " " << game_config::version << "\n";
00195         return 0;
00196     }
00197 
00198     // Options changing their behaviour dependant on some others should be checked below.
00199 
00200     if ( cmdline_opts.preprocess ) {
00201 
00202         std::string output_macros_file;
00203         preproc_map input_macros;
00204 
00205         if( cmdline_opts.preprocess_input_macros ) {
00206             std::string file = *cmdline_opts.preprocess_input_macros;
00207             if ( file_exists( file ) == false )
00208             {
00209                 std::cerr << "please specify an existing file. File "<< file <<" doesn't exist.\n";
00210                 return 1;
00211             }
00212 
00213             std::cerr << SDL_GetTicks() << " Reading cached defines from: " << file << "\n";
00214 
00215             config cfg;
00216             scoped_istream stream = istream_file( file );
00217             read( cfg, *stream );
00218 
00219             int read = 0;
00220 
00221             // use static preproc_define::read_pair(config) to make a object
00222             foreach ( const config::any_child &value, cfg.all_children_range() ) {
00223                 const preproc_map::value_type def = preproc_define::read_pair( value.cfg );
00224                 input_macros[def.first] = def.second;
00225                 ++read;
00226             }
00227             std::cerr << SDL_GetTicks() << " Read " << read << " defines.\n";
00228         }
00229 
00230         if( cmdline_opts.preprocess_output_macros ) {
00231 
00232             if ( cmdline_opts.preprocess_output_macros->empty() == false )
00233                 output_macros_file = *cmdline_opts.preprocess_output_macros;
00234         }
00235 
00236         const std::string resourceToProcess(*cmdline_opts.preprocess_path);
00237         const std::string targetDir(*cmdline_opts.preprocess_target);
00238 
00239         Uint32 startTime = SDL_GetTicks();
00240         // if the users add the SKIP_CORE define we won't preprocess data/core
00241         bool skipCore = false;
00242         bool skipTerrainGFX = false;
00243         // the 'core_defines_map' is the one got from data/core macros
00244         preproc_map defines_map( input_macros );
00245 
00246         if ( cmdline_opts.preprocess_defines ) {
00247 
00248             // add the specified defines
00249             foreach ( const std::string &define, *cmdline_opts.preprocess_defines ) {
00250                 if (define.empty()){
00251                     std::cerr << "empty define supplied\n";
00252                     continue;
00253                 }
00254 
00255                 LOG_PREPROC << "adding define: " << define << '\n';
00256                 defines_map.insert(std::make_pair(define, preproc_define(define)));
00257 
00258                 if (define == "SKIP_CORE")
00259                 {
00260                     std::cerr << "'SKIP_CORE' defined.\n";
00261                     skipCore = true;
00262                 }
00263                 else if (define == "NO_TERRAIN_GFX")
00264                 {
00265                     std::cerr << "'NO_TERRAIN_GFX' defined.\n";
00266                     skipTerrainGFX = true;
00267                 }
00268             }
00269         }
00270 
00271         // add the WESNOTH_VERSION define
00272         defines_map["WESNOTH_VERSION"] = preproc_define(game_config::wesnoth_version.str());
00273 
00274         std::cerr << "added " << defines_map.size() << " defines.\n";
00275 
00276         // preprocess core macros first if we don't skip the core
00277         if (skipCore == false) {
00278             std::cerr << "preprocessing common macros from 'data/core' ...\n";
00279 
00280             // process each folder explicitly to gain speed
00281             preprocess_resource(game_config::path + "/data/core/macros",&defines_map);
00282             if (skipTerrainGFX == false)
00283                 preprocess_resource(game_config::path + "/data/core/terrain-graphics",&defines_map);
00284 
00285             std::cerr << "acquired " << (defines_map.size() - input_macros.size())
00286                 << " 'data/core' defines.\n";
00287         }
00288         else
00289             std::cerr << "skipped 'data/core'\n";
00290 
00291         // preprocess resource
00292         std::cerr << "preprocessing specified resource: "
00293                     << resourceToProcess << " ...\n";
00294         preprocess_resource(resourceToProcess, &defines_map, true,true, targetDir);
00295         std::cerr << "acquired " << (defines_map.size() - input_macros.size())
00296                     << " total defines.\n";
00297 
00298         if ( output_macros_file.empty() == false )
00299         {
00300             std::string outputPath = targetDir + "/_MACROS_.cfg";
00301             if ( output_macros_file.empty() == false )
00302                 outputPath = output_macros_file;
00303 
00304             std::cerr << "writing '" << outputPath << "' with "
00305                         << defines_map.size() << " defines.\n";
00306 
00307             scoped_ostream out = ostream_file(outputPath);
00308             if (!out->fail())
00309             {
00310                 config_writer writer(*out,false);
00311 
00312                 for(preproc_map::iterator itor = defines_map.begin();
00313                     itor != defines_map.end(); ++itor)
00314                 {
00315                     (*itor).second.write(writer, (*itor).first);
00316                 }
00317             }
00318             else
00319                 std::cerr << "couldn't open the file.\n";
00320         }
00321 
00322         std::cerr << "preprocessing finished. Took "<< SDL_GetTicks() - startTime << " ticks.\n";
00323         return 0;
00324     }
00325 
00326     // Not the most intuitive solution, but I wanted to leave current semantics for now
00327     return -1;
00328 }
00329 
00330 /**
00331  * I would prefer to setup locale first so that early error
00332  * messages can get localized, but we need the game_controller
00333  * initialized to have get_intl_dir() to work.  Note: setlocale()
00334  * does not take GUI language setting into account.
00335  */
00336 static void init_locale() {
00337     #if defined _WIN32 || defined __APPLE__
00338         setlocale(LC_ALL, "English");
00339     #else
00340         std::setlocale(LC_ALL, "C");
00341         std::setlocale(LC_MESSAGES, "");
00342     #endif
00343     const std::string& intl_dir = get_intl_dir();
00344     bindtextdomain (PACKAGE, intl_dir.c_str());
00345     bind_textdomain_codeset (PACKAGE, "UTF-8");
00346     bindtextdomain (PACKAGE "-lib", intl_dir.c_str());
00347     bind_textdomain_codeset (PACKAGE "-lib", "UTF-8");
00348     textdomain (PACKAGE);
00349 }
00350 
00351 /**
00352  * Setups the game environment and enters
00353  * the titlescreen or game loops.
00354  */
00355 static int do_gameloop(int argc, char** argv)
00356 {
00357     srand(time(NULL));
00358 
00359     commandline_options cmdline_opts = commandline_options(argc,argv);
00360     game_config::wesnoth_program_dir = directory_name(argv[0]);
00361     int finished = process_command_args(cmdline_opts);
00362     if(finished != -1) {
00363         return finished;
00364     }
00365 
00366     //ensure recorder has an actually random seed instead of what it got during
00367     //static initialization (before any srand() call)
00368     recorder.set_seed(rand());
00369     boost::shared_ptr<game_controller_abstract> game;
00370     if (game_config::new_syntax)
00371         game = boost::shared_ptr<game_controller_abstract>(new game_controller_new(cmdline_opts));
00372     else
00373         game = boost::shared_ptr<game_controller_abstract>(new game_controller(cmdline_opts,argv[0]));
00374     const int start_ticks = SDL_GetTicks();
00375 
00376     init_locale();
00377 
00378     bool res;
00379 
00380     // do initialize fonts before reading the game config, to have game
00381     // config error messages displayed. fonts will be re-initialized later
00382     // when the language is read from the game config.
00383     res = font::load_font_config();
00384     if(res == false) {
00385         std::cerr << "could not initialize fonts\n";
00386         return 1;
00387     }
00388 
00389     res = game->init_language();
00390     if(res == false) {
00391         std::cerr << "could not initialize the language\n";
00392         return 1;
00393     }
00394 
00395     res = game->init_video();
00396     if(res == false) {
00397         std::cerr << "could not initialize display\n";
00398         return 1;
00399     }
00400 
00401     if(preferences::joystick_support_enabled()) {
00402         res = game->init_joystick();
00403         if(res == false) {
00404             std::cerr << "could not initialize joystick\n";
00405         }
00406     }
00407 
00408     const cursor::manager cursor_manager;
00409     cursor::set(cursor::WAIT);
00410 
00411     loadscreen::global_loadscreen_manager loadscreen_manager(game->disp().video());
00412 
00413     loadscreen::start_stage("init gui");
00414     gui2::init();
00415     const gui2::event::tmanager gui_event_manager;
00416 
00417     loadscreen::start_stage("load config");
00418     res = game->init_config();
00419     if(res == false) {
00420         std::cerr << "could not initialize game config\n";
00421         return 1;
00422     }
00423     loadscreen::start_stage("init fonts");
00424 
00425     res = font::load_font_config();
00426     if(res == false) {
00427         std::cerr << "could not re-initialize fonts for the current language\n";
00428         return 1;
00429     }
00430 
00431     loadscreen::start_stage("refresh addons");
00432     refresh_addon_version_info_cache();
00433 
00434 #if defined(_X11) && !defined(__APPLE__)
00435     SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
00436 #endif
00437 
00438     config tips_of_day;
00439 
00440     loadscreen::start_stage("titlescreen");
00441 
00442     LOG_CONFIG << "time elapsed: "<<  (SDL_GetTicks() - start_ticks) << " ms\n";
00443 
00444     for (;;)
00445     {
00446         // reset the TC, since a game can modify it, and it may be used
00447         // by images in add-ons or campaigns dialogs
00448         image::set_team_colors();
00449 
00450         statistics::fresh_stats();
00451 
00452         if (!game->is_loading()) {
00453             const config &cfg = game->game_config().child("titlescreen_music");
00454             if (cfg) {
00455                 sound::play_music_repeatedly(game_config::title_music);
00456                 foreach (const config &i, cfg.child_range("music")) {
00457                     sound::play_music_config(i);
00458                 }
00459                 sound::commit_music_changes();
00460             } else {
00461                 sound::empty_playlist();
00462                 sound::stop_music();
00463             }
00464         }
00465 
00466         loadscreen_manager.reset();
00467 
00468         if(game->play_test() == false) {
00469             return 0;
00470         }
00471 
00472         if(game->play_multiplayer_mode() == false) {
00473             return 0;
00474         }
00475 
00476         if(game->play_screenshot_mode() == false) {
00477             return 0;
00478         }
00479 
00480         recorder.clear();
00481 
00482         //Start directly a campaign
00483         if(game->goto_campaign() == false){
00484             if (game->jump_to_campaign_id().empty())
00485                 continue; //Go to main menu
00486             else
00487                 return 1; //we got an error starting the campaign from command line
00488         }
00489 
00490         //Start directly a multiplayer
00491         //Eventually with a specified server
00492         if(game->goto_multiplayer() == false){
00493             continue; //Go to main menu
00494         }
00495 
00496         if (game->goto_editor() == false) {
00497             return 0;
00498         }
00499 
00500         gui2::ttitle_screen::tresult res = game->is_loading()
00501                 ? gui2::ttitle_screen::LOAD_GAME
00502                 : gui2::ttitle_screen::NOTHING;
00503 
00504         const preferences::display_manager disp_manager(&game->disp());
00505 
00506         const font::floating_label_context label_manager;
00507 
00508         cursor::set(cursor::NORMAL);
00509         if(res == gui2::ttitle_screen::NOTHING) {
00510             const hotkey::basic_handler key_handler(&game->disp());
00511             gui2::ttitle_screen dlg;
00512             dlg.show(game->disp().video());
00513 
00514             res = static_cast<gui2::ttitle_screen::tresult>(dlg.get_retval());
00515         }
00516 
00517         game_controller_abstract::RELOAD_GAME_DATA should_reload = game_controller_abstract::RELOAD_DATA;
00518 
00519         if(res == gui2::ttitle_screen::QUIT_GAME) {
00520             LOG_GENERAL << "quitting game...\n";
00521             return 0;
00522         } else if(res == gui2::ttitle_screen::LOAD_GAME) {
00523             if(game->load_game() == false) {
00524                 game->clear_loaded_game();
00525                 res = gui2::ttitle_screen::NOTHING;
00526                 continue;
00527             }
00528             should_reload = game_controller_abstract::NO_RELOAD_DATA;
00529         } else if(res == gui2::ttitle_screen::TUTORIAL) {
00530             game->set_tutorial();
00531         } else if(res == gui2::ttitle_screen::NEW_CAMPAIGN) {
00532             if(game->new_campaign() == false) {
00533                 continue;
00534             }
00535         } else if(res == gui2::ttitle_screen::MULTIPLAYER) {
00536             game_config::debug = game_config::mp_debug;
00537             if(game->play_multiplayer() == false) {
00538                 continue;
00539             }
00540         } else if(res == gui2::ttitle_screen::CHANGE_LANGUAGE) {
00541             if (game->change_language()) {
00542                 tips_of_day.clear();
00543                 t_string::reset_translations();
00544                 image::flush_cache();
00545             }
00546             continue;
00547         } else if(res == gui2::ttitle_screen::EDIT_PREFERENCES) {
00548             game->show_preferences();
00549             continue;
00550         } else if(res == gui2::ttitle_screen::SHOW_ABOUT) {
00551             about::show_about(game->disp());
00552             continue;
00553         } else if(res == gui2::ttitle_screen::SHOW_HELP) {
00554             help::help_manager help_manager(&game->game_config(), NULL);
00555             help::show_help(game->disp());
00556             continue;
00557         } else if(res == gui2::ttitle_screen::GET_ADDONS) {
00558             // NOTE: we need the help_manager to get access to the Add-ons
00559             // section in the game help!
00560             help::help_manager help_manager(&game->game_config(), NULL);
00561             if(manage_addons(game->disp())) {
00562                 game->reload_changed_game_config();
00563             }
00564             continue;
00565         } else if(res == gui2::ttitle_screen::RELOAD_GAME_DATA) {
00566             loadscreen::global_loadscreen_manager loadscreen(game->disp().video());
00567             game->reload_changed_game_config();
00568             image::flush_cache();
00569             continue;
00570         } else if(res == gui2::ttitle_screen::START_MAP_EDITOR) {
00571             ///@todo editor can ask the game to quit completely
00572             if (game->start_editor() == editor::EXIT_QUIT_TO_DESKTOP) {
00573                 return 0;
00574             }
00575             continue;
00576         }
00577 
00578         if (recorder.at_end()){
00579             game->launch_game(should_reload);
00580         }
00581         else{
00582             game->play_replay();
00583         }
00584     }
00585 }
00586 
00587 
00588 #ifdef __native_client__
00589 int wesnoth_main(int argc, char** argv)
00590 #else
00591 int main(int argc, char** argv)
00592 #endif
00593 {
00594 
00595 #ifdef HAVE_VISUAL_LEAK_DETECTOR
00596     VLDEnable();
00597 #endif
00598 
00599 #if defined(_OPENMP) && !defined(_WIN32) && !defined(__APPLE__)
00600     // Wesnoth is a special case for OMP
00601     // OMP wait strategy is to have threads busy-loop for 100ms
00602     // if there is nothing to do, they then go to sleep.
00603     // this avoids the scheduler putting the thread to sleep when work
00604     // is about to be available
00605     //
00606     // However Wesnoth has a lot of very small jobs that need to be done
00607     // at each redraw => 50fps every 2ms.
00608     // All the threads are thus busy-waiting all the time, hogging the CPU
00609     // To avoid that problem, we need to set the OMP_WAIT_POLICY env var
00610     // but that var is read by OMP at library loading time (before main)
00611     // thus the relaunching of ourselves after setting the variable.
00612     if (!getenv("OMP_WAIT_POLICY")) {
00613         setenv("OMP_WAIT_POLICY", "PASSIVE", 1);
00614         execv(argv[0], argv);
00615     }
00616 #endif
00617 
00618     if(SDL_Init(SDL_INIT_TIMER) < 0) {
00619         fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
00620         return(1);
00621     }
00622 
00623     try {
00624         std::cerr << "Battle for Wesnoth v" << game_config::revision << '\n';
00625         const time_t t = time(NULL);
00626         std::cerr << "Started on " << ctime(&t) << "\n";
00627 
00628         const std::string exe_dir = get_exe_dir();
00629         if(!exe_dir.empty() && file_exists(exe_dir + "/data/_main.cfg")) {
00630             std::cerr << "Automatically found a possible data directory at "
00631                       << exe_dir << '\n';
00632             game_config::path = exe_dir;
00633         }
00634 
00635         const int res = do_gameloop(argc,argv);
00636         safe_exit(res);
00637     } catch(boost::program_options::error& e) {
00638         std::cerr << "Error in command line: " << e.what() << '\n';
00639         return 1;
00640     } catch(CVideo::error&) {
00641         std::cerr << "Could not initialize video. Exiting.\n";
00642         return 1;
00643     } catch(font::manager::error&) {
00644         std::cerr << "Could not initialize fonts. Exiting.\n";
00645         return 1;
00646     } catch(config::error& e) {
00647         std::cerr << e.message << "\n";
00648         return 1;
00649     } catch(gui::button::error&) {
00650         std::cerr << "Could not create button: Image could not be found\n";
00651         return 1;
00652     } catch(CVideo::quit&) {
00653         //just means the game should quit
00654     } catch(end_level_exception&) {
00655         std::cerr << "caught end_level_exception (quitting)\n";
00656     } catch(twml_exception& e) {
00657         std::cerr << "WML exception:\nUser message: "
00658             << e.user_message << "\nDev message: " << e.dev_message << '\n';
00659         return 1;
00660     } catch(game_logic::formula_error& e) {
00661         std::cerr << e.what()
00662             << "\n\nGame will be aborted.\n";
00663         return 1;
00664     } catch(game::error &) {
00665         // A message has already been displayed.
00666         return 1;
00667     } catch(std::bad_alloc&) {
00668         std::cerr << "Ran out of memory. Aborted.\n";
00669         return ENOMEM;
00670     }
00671 
00672     return 0;
00673 } // end main
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:02:51 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs