RealTimeBattle.cc

Go to the documentation of this file.
00001 /*
00002 RealTimeBattle, a robot programming game for Unix
00003 Copyright (C) 1998-2000  Erik Ouchterlony and Ragnar Ouchterlony
00004 
00005 This program is free software; you can redistribute it and/or modify
00006 it under the terms of the GNU General Public License as published by
00007 the Free Software Foundation; either version 2 of the License, or
00008 (at your option) any later version.
00009 
00010 This program is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 GNU General Public License for more details.
00014 
00015 You should have received a copy of the GNU General Public License
00016 along with this program; if not, write to the Free Software Foundation,
00017 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00018 */
00019 
00020 
00021 #ifdef HAVE_CONFIG_H
00022 #include <config.h>
00023 #endif
00024 
00025 #include <stdlib.h>
00026 #include <unistd.h>
00027 #include <signal.h>
00028 
00029 #include <sys/types.h>
00030 #ifdef TIME_WITH_SYS_TIME 
00031 # include <sys/time.h>
00032 # include <time.h>
00033 #else
00034 # if HAVE_SYS_TIME_H
00035 #  include <sys/time.h>
00036 # else
00037 #  include <time.h>
00038 # endif
00039 #endif
00040 
00041 # include <sys/wait.h>
00042 
00043 
00044 #include <errno.h>
00045 #ifdef HAVE_GETOPT_H
00046 # include <getopt.h>
00047 #else
00048 # include "getopt.h"
00049 #endif
00050 
00051 #ifdef HAVE_LOCALE_H
00052 # include <locale.h>
00053 #endif
00054 
00055 #include <iostream>
00056 
00057 #ifdef FLOATINGPOINT_H
00058 #include <floatingpoint>
00059 #endif
00060 
00061 #ifndef NO_GRAPHICS
00062 #include "ControlWindow.h"
00063 #endif 
00064 
00065 #include "IntlDefs.h"
00066 #include "Options.h"
00067 #include "ArenaRealTime.h"
00068 #include "ArenaReplay.h"
00069 #include "Various.h"
00070 #include "ArenaController.h"
00071 #include "String.h"
00072 //#include "Server.h"
00073 
00074 #ifndef WAIT_ANY
00075 #define WAIT_ANY (pid_t)-1
00076 #endif
00077 
00078 class Options the_opts;
00079 //class ArenaRealTime the_arena;
00080 class ArenaController the_arena_controller;
00081 
00082 //class Server my_server;
00083 
00084 #ifndef NO_GRAPHICS
00085 class Gui the_gui;
00086 class ControlWindow* controlwindow_p;
00087 #endif
00088 
00089 bool no_graphics;
00090 
00091 
00092 
00093 void 
00094 print_help_message()
00095 {
00096   cout << endl;
00097   cout << _(" Usage: RealTimeBattle [options] ") << endl << endl;
00098   cout << _(" Options:") << endl;
00099   cout << _("    --debug_mode,                -d   debug mode") << endl;
00100   cout << _("    --debug_level [0-5],         -D   sets the initial debug level. Implies -d") << endl;
00101   cout << _("    --normal_mode,               -n   normal mode (default)") << endl;
00102   cout << _("    --competition_mode,          -c   competition mode") << endl ;
00103   cout << endl;
00104   cout << _("    --no_graphics,               -g   no graphics will be displayed") << endl ;
00105   cout << _("    --option_file [file],        -o   selects option-file (default: $HOME/.rtbrc)")  << endl;
00106   cout << endl;
00107   cout << _("    --log_file [file],           -l   make log file, if 'file' is '-'\n"
00108             "                                      the log is sent to STDOUT") << endl;
00109   cout << endl;
00110   cout << _("    --tournament_file [file],    -t   specify a tournament file to\n"
00111             "                                      autostart a tournament") << endl;
00112   cout << endl;
00113   cout << _("    --statistics_file [file],    -s   file to print the statistics to\n"
00114             "                                       when autostarting") << endl;
00115   cout << endl;
00116   cout << _("    --message_file [file],       -m   redirect messages to 'file'.\n"
00117             "                                      With '-' as 'file', STDOUT is used.\n"
00118             "                                      If both log and messages are sent\n"
00119             "                                      to STDOUT, '-m' will be ignored") << endl;
00120   cout << endl;
00121   cout << _("    --replay [file]              -r   a log file to replay.\n"
00122             "                                      if '-' is specified as file,\n"
00123             "                                      input is taken from STDIN") << endl;
00124   cout << endl;
00125   cout << _("    --help,                      -h   prints this message") << endl;
00126   cout << _("    --version,                   -v   prints the version number") << endl;
00127   cout << endl;
00128 }
00129 
00130 #ifndef NO_GRAPHICS
00131 gint
00132 update_function(gpointer data)
00133 {  
00134   gint res = 1;
00135 
00136   if( the_arena_controller.is_started() )
00137     res = (gint)the_arena.timeout_function();
00138 
00139   return res;
00140 }
00141 #else 
00142 void
00143 update_function(const long int interval_usec)
00144 {
00145   struct timeval timeout;
00146   timeout.tv_sec = 0;
00147   timeout.tv_usec = interval_usec;
00148   bool res = true;
00149 
00150   do
00151     {
00152       timeout.tv_sec = 0;
00153       timeout.tv_usec = interval_usec;
00154       select(FD_SETSIZE, NULL, NULL, NULL, &timeout);
00155       if( the_arena_controller.is_started() )
00156         res = the_arena.timeout_function();
00157     } 
00158   while( res );
00159 
00160 }
00161 #endif 
00162 
00163 void
00164 sig_handler (int signum)
00165 {
00166   int pid;
00167   int status;
00168   while (1)
00169     {
00170       pid = waitpid (WAIT_ANY, &status, WNOHANG);
00171       if (pid < 0)
00172         {
00173           if( errno != ECHILD ) 
00174             Error(true, "waitpid failed", "RealTimeBattle.cc:sig_handler");
00175           break;
00176         }
00177       if (pid == 0)
00178         break;
00179     }
00180   //  if( signum == SIGCHLD ) cerr << "Sigchld caught!" << endl;
00181   //  if( signum == SIGPIPE ) cerr << "Sigpipe caught!" << endl;
00182   signal(signum, sig_handler);
00183 }
00184 
00185 void
00186 sigfpe_handler(int signum)
00187 {
00188   signal(signum, sigfpe_handler);
00189 }
00190 
00191 void
00192 parse_command_line(int argc, char **argv)
00193 {
00194   int version_flag=false, help_flag=false, graphics_flag=true;
00195   int c;
00196 
00197   extern char* optarg;
00198   extern int optind;
00199 
00200   static struct option long_options[] =
00201   {
00202     //option, argument?, flag, value
00203     {"version", 0, &version_flag, true},
00204     {"help", 0, &help_flag, true},
00205 
00206     {"debug_mode", 0, &the_arena_controller.game_mode,
00207      ArenaBase::DEBUG_MODE},
00208     {"debug_level", 1, 0, 0},
00209     {"normal_mode", 0, &the_arena_controller.game_mode,
00210      ArenaBase::NORMAL_MODE},
00211     {"competition_mode", 0, &the_arena_controller.game_mode,
00212      ArenaBase::COMPETITION_MODE},
00213     {"option_file", 1, 0, 0},
00214     {"log_file", 1, 0, 0},
00215     {"statistics_file", 1, 0, 0},
00216     {"tournament_file", 1, 0, 0},
00217     {"message_file", 1, 0, 0},
00218     {"replay", 1, 0, 0},
00219 
00220     {"no_graphics", 0, &graphics_flag, false},
00221 
00222     {0, 0, 0, 0}
00223   };
00224 
00225   for(;;)
00226     {
00227       int option_index = 0;
00228      
00229       c = getopt_long( argc, argv, "dncD:vho:l:s:t:m:r:g",
00230                        long_options, &option_index );
00231 
00232       // Detect the end of the options.
00233       if (c == -1)
00234         break;
00235      
00236       switch (c)
00237         {
00238 
00239         case 0:
00240           // If this option sets a flag, do nothing else now.
00241           if( long_options[option_index].flag != 0 )
00242             break;
00243           
00244           switch( option_index )
00245             {
00246             case 3:
00247               the_arena_controller.debug_level = str2int( optarg );
00248               the_arena_controller.game_mode = ArenaBase::DEBUG_MODE;
00249               break;
00250             case 6: 
00251               the_arena_controller.option_filename = (String)optarg;
00252               break;
00253             case 7:
00254               the_arena_controller.log_filename = (String)optarg;
00255               break;
00256             case 8:
00257               the_arena_controller.statistics_filename = (String)optarg;
00258               break;
00259             case 9:
00260               the_arena_controller.tournament_filename = (String)optarg;
00261               the_arena_controller.auto_start_and_end = true;
00262               break;
00263             case 10:
00264               the_arena_controller.message_filename = (String)optarg;
00265               break;
00266             case 11:
00267               the_arena_controller.replay_filename = (String)optarg;
00268               break;
00269             default:
00270               Error( true, "Bad error, this shouldn't happen",
00271                      "RealTimeBattle.cc:parse_command_line" );
00272               exit( EXIT_FAILURE );
00273             }
00274           break;
00275 
00276 
00277         case 'd':
00278           the_arena_controller.game_mode = ArenaBase::DEBUG_MODE;
00279           break;
00280 
00281         case 'D':
00282           the_arena_controller.debug_level = str2int( optarg );
00283           the_arena_controller.game_mode = ArenaBase::DEBUG_MODE;
00284           break;
00285 
00286         case 'n':
00287           the_arena_controller.game_mode = ArenaBase::NORMAL_MODE;
00288           break;
00289 
00290         case 'c':
00291           the_arena_controller.game_mode = ArenaBase::COMPETITION_MODE;
00292           break;
00293 
00294         case 'v':
00295           version_flag = true;
00296           break;
00297 
00298         case 'h':
00299           help_flag = true;
00300           break;
00301 
00302         case 'o':
00303           the_arena_controller.option_filename = (String)optarg;
00304           break;
00305 
00306         case 'l':
00307           the_arena_controller.log_filename = (String)optarg;
00308           break;
00309 
00310         case 's':
00311           the_arena_controller.statistics_filename = (String)optarg;
00312           break;
00313 
00314         case 't':
00315           the_arena_controller.tournament_filename = (String)optarg;
00316           the_arena_controller.auto_start_and_end = true;
00317           break;
00318 
00319         case 'm':
00320           the_arena_controller.message_filename = (String)optarg;
00321           break;
00322 
00323         case 'r':
00324           the_arena_controller.replay_filename = (String)optarg;
00325           break;
00326 
00327         case 'g':
00328           graphics_flag = false;
00329           break;
00330 
00331         default:
00332           print_help_message();
00333           exit( EXIT_FAILURE );
00334         }
00335     }
00336 
00337   if( the_arena_controller.debug_level > max_debug_level )
00338     the_arena_controller.debug_level = 5;
00339   if( the_arena_controller.debug_level < 0 )
00340     the_arena_controller.debug_level = 0;
00341 
00342   if(optind != argc) 
00343     {
00344       print_help_message();
00345       exit( EXIT_FAILURE );
00346     }
00347 
00348   if( version_flag )
00349       cout << "RealTimeBattle " << VERSION << endl;
00350 
00351   if( help_flag )
00352     print_help_message();
00353 
00354   if( help_flag || version_flag ) exit( EXIT_SUCCESS );
00355 
00356   if( the_arena_controller.option_filename == "" )
00357     {
00358       the_opts.get_options_from_rtbrc();
00359       the_arena_controller.option_filename = ".rtbrc";
00360     }
00361   else
00362     the_opts.read_options_file( the_arena_controller.option_filename,true );
00363 
00364   the_arena_controller.auto_start_and_end
00365     = ( ( the_arena_controller.tournament_filename != "" ) ||
00366         ( the_arena_controller.replay_filename == "-" ) );
00367 
00368   no_graphics = !graphics_flag;
00369 
00370   if( the_arena_controller.auto_start_and_end == false 
00371 #ifndef NO_GRAPHICS      
00372       && no_graphics
00373 #endif      
00374       )
00375     {
00376       cerr << "No graphics and no tournament file gives me nothing to do. Leaving ..." << endl;
00377       exit( EXIT_SUCCESS );
00378     }
00379 }
00380 
00381 
00382 int 
00383 main ( int argc, char* argv[] )
00384 {
00385 
00386 #ifdef FLOATINGPOINT_H
00387   fpsetmask ( ~ (FP_X_INV | FP_X_DZ | FP_X_IMP | FP_X_OFL | FP_X_UFL | FP_X_DNML) );
00388   //fpsetmask ( ~ (FP_X_INV | FP_X_DZ | FP_X_IMP) );
00389 #endif
00390 
00391 #ifndef NO_GRAPHICS
00392 
00393         
00394 #ifdef ENABLE_NLS
00395   bindtextdomain ("RealTimeBattle", PACKAGE_LOCALE_DIR);
00396   bind_textdomain_codeset ("RealTimeBattle", "UTF-8");
00397   textdomain ("RealTimeBattle");
00398 #endif
00399 
00400   gtk_set_locale ();
00401 
00402   gtk_init (&argc, &argv);
00403 #endif 
00404 /*
00405 #ifdef HAVE_LOCALE_H
00406   setlocale( LC_MESSAGES, "" );
00407   setlocale( LC_NUMERIC, "POSIX" );
00408 #endif
00409 #ifdef RTB_LOCALEDIR
00410   bindtextdomain( "RealTimeBattle", RTB_LOCALEDIR );
00411 #else
00412   bindtextdomain( "RealTimeBattle", "/usr/local/share/locale" );
00413 #endif
00414   textdomain( "RealTimeBattle" );
00415 */
00416   parse_command_line(argc, argv);
00417 
00418   if( the_arena_controller.tournament_filename != "" )
00419     the_arena_controller.start_realtime_arena();
00420   else if( the_arena_controller.replay_filename != "" )
00421     the_arena_controller.start_replay_arena();
00422 
00423   signal(SIGCHLD, sig_handler);
00424   signal(SIGPIPE, sig_handler);
00425   signal(SIGFPE, sigfpe_handler);
00426 
00427 #ifndef NO_GRAPHICS
00428   if( !no_graphics )
00429     {
00430       the_gui.set_colours();
00431       controlwindow_p = 
00432         new ControlWindow( -1, -1,
00433                            the_opts.get_l( OPTION_CONTROL_WINDOW_POS_X ),
00434                            the_opts.get_l( OPTION_CONTROL_WINDOW_POS_Y ) );
00435     }
00436 
00437 
00438   gint timeout_tag;     
00439 
00440   double interval = 1000.0*the_opts.get_d( OPTION_UPDATE_INTERVAL ) - 10.0; 
00441   
00442   //updating too fast?
00443   if ( interval < 40 ) interval = 40;
00444 
00445 
00446   timeout_tag = gtk_timeout_add( (unsigned int) interval,
00447                                  GtkFunction(update_function), (gpointer) NULL );
00448  
00449   gtk_main();
00450 #else 
00451   
00452   update_function( (long int)(the_opts.get_d( OPTION_UPDATE_INTERVAL ) * 1000000.0) );
00453   
00454 #endif 
00455 
00456   return EXIT_SUCCESS;
00457 }

Generated on Fri Oct 15 15:47:37 2004 for Real Time Battle by  doxygen 1.3.9.1