00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
00073
00074 #ifndef WAIT_ANY
00075 #define WAIT_ANY (pid_t)-1
00076 #endif
00077
00078 class Options the_opts;
00079
00080 class ArenaController the_arena_controller;
00081
00082
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
00181
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
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
00233 if (c == -1)
00234 break;
00235
00236 switch (c)
00237 {
00238
00239 case 0:
00240
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
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
00406
00407
00408
00409
00410
00411
00412
00413
00414
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
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 }