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 <math.h>
00026 #include <signal.h>
00027 #include <unistd.h>
00028 #include <stdlib.h>
00029 #include <iostream>
00030 #include <iomanip>
00031 #include <stdarg.h>
00032 #include <sys/stat.h>
00033 #include <stdio.h>
00034
00035 using namespace std;
00036
00037
00038 #include "ArenaRealTime.h"
00039 #include "ArenaController.h"
00040 #include "ArenaWindow.h"
00041
00042
00043 #include "IntlDefs.h"
00044 #include "Extras.h"
00045 #include "Various.h"
00046 #include "String.h"
00047 #include "Shot.h"
00048 #include "Options.h"
00049 #include "Wall.h"
00050 #include "Robot.h"
00051 #ifndef NO_GRAPHICS
00052 # include "ScoreWindow.h"
00053 # include "ControlWindow.h"
00054 # include "MessageWindow.h"
00055 #endif
00056
00057 #ifndef NO_GRAPHICS
00058 extern class ControlWindow* controlwindow_p;
00059 #endif
00060
00061 ArenaRealTime::ArenaRealTime()
00062 {
00063 set_game_mode( (ArenaBase::game_mode_t)the_arena_controller.game_mode );
00064 set_filenames( the_arena_controller.log_filename,
00065 the_arena_controller.statistics_filename,
00066 the_arena_controller.tournament_filename,
00067 the_arena_controller.message_filename,
00068 the_arena_controller.option_filename );
00069
00070 robots_in_sequence = NULL;
00071 }
00072
00073 ArenaRealTime::~ArenaRealTime()
00074 {
00075 for(int i=0; i < sequences_in_tournament; i++)
00076 delete [] robots_in_sequence[i];
00077
00078 if( robots_in_sequence != NULL )
00079 delete robots_in_sequence;
00080
00081 if( use_log_file && LOG_FILE ) LOG_FILE.close();
00082 if( use_message_file && message_file ) message_file.close();
00083 }
00084
00085
00086 void
00087 ArenaRealTime::clear()
00088 {
00089 delete_lists(true, true, true, true);
00090
00091 for(int i=0; i < sequences_in_tournament; i++)
00092 delete [] robots_in_sequence[i];
00093
00094 sequence_nr = 0;
00095 sequences_in_tournament = 0;
00096
00097 set_state( NOT_STARTED );
00098 }
00099
00100 void
00101 ArenaRealTime::set_filenames( String& log_fname,
00102 const String& statistics_fname,
00103 const String& tournament_fname,
00104 String& message_fname,
00105 const String& option_fname )
00106 {
00107 bool log_stdout = false;
00108
00109 if( log_fname == "" )
00110 {
00111 use_log_file = false;
00112 }
00113 else if( log_fname == "-" || log_fname == "STDOUT" )
00114 {
00115 cout << "Attach -- Muss gefixt werden in ArenaREaltime.cc 113" << endl;
00116
00117 use_log_file = true;
00118 log_stdout = true;
00119 }
00120 else
00121 {
00122
00123 LOG_FILE.open(log_fname.chars(), ios::out);
00124
00125 use_log_file = true;
00126 if( !LOG_FILE )
00127 {
00128 Error( false, "Couldn't open log file. Contuing without log file",
00129 "ArenaRealTime::set_filenames" );
00130 use_log_file = false;
00131 }
00132 }
00133 if( message_fname == "" )
00134 {
00135 use_message_file = false;
00136 }
00137 else if( message_fname == "-" || message_fname == "STDOUT" )
00138 {
00139 if( !log_stdout )
00140 {
00141 use_message_file = true;
00142
00143 }
00144 else
00145 {
00146 use_message_file = false;
00147 }
00148 }
00149 else
00150 {
00151 use_message_file = true;
00152
00153 if( !message_file )
00154 {
00155 Error( false, "Couldn't open message file. Message file disabled",
00156 "ArenaRealTime::set_filenames" );
00157 use_message_file = false;
00158 }
00159
00160 }
00161
00162 statistics_file_name = statistics_fname;
00163
00164 tournament_file_name = tournament_fname;
00165
00166 option_file_name = option_fname;
00167 }
00168
00169 void
00170 ArenaRealTime::parse_arena_file(String& filename)
00171 {
00172 Vector2D vec1, vec2, vec0;
00173
00174 ifstream file(filename.chars());
00175 if( !file ) Error(true, "Couldn't open arena file" + filename, "ArenaBase::parse_arena_file");
00176
00177 int succession = 1;
00178 double scale = the_opts.get_d(OPTION_ARENA_SCALE);
00179 double angle_factor = 1.0;
00180 do
00181 {
00182 parse_arena_line(file, scale, succession, angle_factor);
00183
00184 } while( !file.eof() );
00185
00186 file.close();
00187
00188
00189 if( use_log_file )
00190 {
00191 char buffer[500];
00192
00193 ifstream file(filename.chars());
00194 if( !file ) Error(true, "Couldn't open arena file for log file" + filename, "ArenaBase::parse_arena_file");
00195
00196 do
00197 {
00198 file >> ws;
00199 file.get(buffer, 500, '\n');
00200 if( buffer[0] != '\0' ) print_to_logfile('A', buffer);
00201 }
00202 while( buffer[0] != '\0' );
00203
00204 }
00205
00206 }
00207
00208 void
00209 ArenaRealTime::print_to_logfile(const char first_letter ... )
00210 {
00211 if( !use_log_file ) return;
00212
00213 va_list args;
00214 va_start(args, first_letter);
00215
00216
00217 if( update_count_for_logging != 0 && first_letter == 'R' )
00218 {
00219 va_end(args);
00220 return;
00221 }
00222
00223 LOG_FILE << first_letter;
00224
00225 int prec = 2;
00226 LOG_FILE << setiosflags(ios::fixed) << setprecision(prec);
00227
00228 switch(first_letter)
00229 {
00230 case 'R':
00231 LOG_FILE << va_arg(args, int ) << " ";
00232 LOG_FILE << va_arg(args, double) << " ";
00233 LOG_FILE << va_arg(args, double) << " ";
00234 LOG_FILE << va_arg(args, double) << " ";
00235 LOG_FILE << va_arg(args, double) << " ";
00236 LOG_FILE << va_arg(args, double) << " ";
00237 LOG_FILE << va_arg(args, double);
00238 break;
00239
00240 case 'T':
00241 LOG_FILE << setprecision(prec+1) << va_arg(args, double);
00242 break;
00243
00244 case 'P':
00245 LOG_FILE << va_arg(args, int ) << " ";
00246 LOG_FILE << va_arg(args, char* );
00247 break;
00248
00249 case 'C':
00250 LOG_FILE << va_arg(args, int ) << " ";
00251 LOG_FILE << va_arg(args, double) << " ";
00252 LOG_FILE << va_arg(args, double);
00253 break;
00254
00255 case 'M':
00256 LOG_FILE << va_arg(args, int ) << " ";
00257 LOG_FILE << va_arg(args, double) << " ";
00258 LOG_FILE << va_arg(args, double);
00259 break;
00260
00261 case 'S':
00262 LOG_FILE << va_arg(args, int ) << " ";
00263 LOG_FILE << va_arg(args, double) << " ";
00264 LOG_FILE << va_arg(args, double) << " ";
00265 LOG_FILE << setprecision(prec+1) << va_arg(args, double) << " ";
00266 LOG_FILE << setprecision(prec+1) << va_arg(args, double);
00267 break;
00268
00269 case 'D':
00270 {
00271 int obj_type = va_arg(args, int );
00272 LOG_FILE << (char)obj_type << " ";
00273 LOG_FILE << va_arg(args, int) << " ";
00274 if( obj_type == 'R' )
00275 {
00276 LOG_FILE << setprecision(1)
00277 << va_arg(args, double) << " ";
00278 LOG_FILE << va_arg(args, int);
00279 }
00280 }
00281 break;
00282
00283 case 'G':
00284 LOG_FILE << va_arg(args, int ) << " ";
00285 LOG_FILE << va_arg(args, int ) << " ";
00286
00287 break;
00288
00289 case 'H':
00290 LOG_FILE << va_arg(args, int ) << " ";
00291 LOG_FILE << va_arg(args, int ) << " ";
00292 LOG_FILE << va_arg(args, int ) << " ";
00293 LOG_FILE << va_arg(args, int ) << " ";
00294
00295 break;
00296
00297 case 'L':
00298 {
00299 LOG_FILE << va_arg(args, int ) << " ";
00300 LOG_FILE << hex2str(va_arg(args, long )) << " ";
00301
00302 String name = va_arg(args, char*);
00303 if( name == "" ) name = "Anonymous";
00304 LOG_FILE << name;
00305 }
00306 break;
00307
00308 case 'A':
00309 LOG_FILE << va_arg(args, char*);
00310 break;
00311
00312 case 'O':
00313 {
00314 char option_type = (char)va_arg(args, int);
00315 LOG_FILE << va_arg(args, char*);
00316 switch( option_type )
00317 {
00318 case 'D':
00319 LOG_FILE << String( va_arg(args, double) ).chars();
00320 break;
00321 case 'L':
00322 LOG_FILE << String( va_arg(args, long) ).chars();
00323 break;
00324 case 'H':
00325 LOG_FILE << hex2str( va_arg(args, long) ).chars();
00326 break;
00327 case 'S':
00328 LOG_FILE << String( va_arg(args, char*) ).chars();
00329 break;
00330 }
00331 }
00332 break;
00333
00334 default:
00335 Error(true, "Unrecognized first letter in logfile", "ArenaRealTime::print_to_logfile");
00336 break;
00337 }
00338
00339 LOG_FILE << endl;
00340 va_end(args);
00341 }
00342
00343 Vector2D
00344 ArenaRealTime::get_random_position()
00345 {
00346 return Vector2D( boundary[0][0] + (boundary[1][0] - boundary[0][0])*
00347 (double)rand()/(double)RAND_MAX,
00348 boundary[0][1] + (boundary[1][1] - boundary[0][1])*
00349 (double)rand()/(double)RAND_MAX );
00350 }
00351
00352 void
00353 ArenaRealTime::broadcast(const message_to_robot_type msg_type ...)
00354 {
00355 va_list args;
00356 va_start(args, msg_type);
00357 String str = (String)message_to_robot[msg_type].msg + ' ';
00358 for(int i=0; i<message_to_robot[msg_type].number_of_args; i++)
00359 {
00360 switch(message_to_robot[msg_type].arg_type[i])
00361 {
00362 case NONE:
00363 Error(true, "Couldn't send message, no arg_type", "ArenaRealTime::broadcast");
00364 break;
00365 case INT:
00366 str += (String)va_arg(args, int) + ' ';
00367 break;
00368 case DOUBLE:
00369 str += String(va_arg(args, double), 6) + ' ';
00370 break;
00371 case STRING:
00372 str += (String)va_arg(args, char*) + ' ';
00373 break;
00374 case HEX:
00375 str += hex2str(va_arg(args, int)) + ' ';
00376 break;
00377 default:
00378 Error(true, "Couldn't send message, unknown arg_type", "ArenaRealTime::broadcast");
00379 }
00380 }
00381 str += '\n';
00382
00383 ListIterator<Shape> li;
00384 for( object_lists[ROBOT].first(li); li.ok(); li++ )
00385 *(((Robot*)li())->get_outstreamp()) << str;
00386 }
00387
00388 void
00389 ArenaRealTime::quit_ordered()
00390 {
00391 set_state( EXITING );
00392 }
00393
00394 bool
00395 ArenaRealTime::timeout_function()
00396 {
00397 #ifndef NO_GRAPHICS
00398 int old_total = (int)total_time;
00399 #endif
00400
00401 if( state != PAUSED )
00402 {
00403 update_timer ();
00404 }
00405
00406 switch(state)
00407 {
00408 case NOT_STARTED:
00409 if( the_arena_controller.auto_start_and_end )
00410 parse_tournament_file( tournament_file_name,
00411 (StartTournamentFunction)
00412 ArenaRealTime::start_tournament_from_tournament_file,
00413 this );
00414 break;
00415
00416 case FINISHED:
00417 if( the_arena_controller.auto_start_and_end )
00418 {
00419 if( statistics_file_name != "" )
00420 save_statistics_to_file( statistics_file_name );
00421
00422 Quit();
00423 }
00424 break;
00425
00426 case STARTING_ROBOTS:
00427 {
00428 read_robot_messages();
00429
00430 if( total_time > next_check_time ) start_sequence_follow_up();
00431 }
00432 break;
00433
00434 case SHUTTING_DOWN_ROBOTS:
00435 {
00436 ListIterator<Robot> li;
00437 for( all_robots_in_sequence.first(li); li.ok(); li++ )
00438 li()->get_messages();
00439
00440 if( total_time > next_check_time ) end_sequence_follow_up();
00441 }
00442 break;
00443
00444 case GAME_IN_PROGRESS:
00445 {
00446 update();
00447 #ifndef NO_GRAPHICS
00448 if((int)total_time > old_total && !no_graphics)
00449 the_gui.get_scorewindow_p()->set_window_title();
00450 #endif
00451 if( robots_left <= 1 || total_time > the_opts.get_d(OPTION_TIMEOUT) )
00452 {
00453 end_game();
00454 }
00455 else
00456 {
00457 if( game_mode == COMPETITION_MODE && total_time > next_check_time ) check_robots();
00458
00459
00460 if( ((double)rand()) / (double)RAND_MAX <= timestep*the_opts.get_d(OPTION_COOKIE_FREQUENCY) )
00461 add_cookie();
00462
00463 if( ((double)rand()) / (double)RAND_MAX <= timestep*the_opts.get_d(OPTION_MINE_FREQUENCY) )
00464 add_mine();
00465
00466 if( halt_next )
00467 {
00468 set_state( PAUSED );
00469 halt_next = false;
00470 }
00471 }
00472 }
00473 break;
00474
00475 case PAUSED:
00476 break;
00477
00478 case PAUSING_BETWEEN_GAMES:
00479 if( !pause_after_next_game ) start_game();
00480 break;
00481
00482 case EXITING:
00483 return false;
00484
00485 case BEFORE_GAME_START:
00486 case NO_STATE:
00487 Error(true, "Arena shouldn't be in this state here!!", "ArenaRealTime::timeout_function");
00488 }
00489
00490 return true;
00491 }
00492
00493 void
00494 ArenaRealTime::update()
00495 {
00496 print_to_logfile('T', total_time);
00497
00498 #ifndef NO_GRAPHICS
00499 if( state == GAME_IN_PROGRESS && !no_graphics)
00500 the_gui.get_messagewindow_p()->freeze_clist();
00501 #endif
00502
00503 read_robot_messages();
00504 move_shots(timestep);
00505 update_robots();
00506
00507 #ifndef NO_GRAPHICS
00508 if( state == GAME_IN_PROGRESS && !no_graphics)
00509 {
00510 the_gui.get_arenawindow_p()->draw_moving_objects( true );
00511 the_gui.get_messagewindow_p()->thaw_clist();
00512 }
00513 #endif
00514
00515 update_count_for_logging++;
00516 if( update_count_for_logging == the_opts.get_l(OPTION_LOG_EVERY_NTH_UPDATE_INTERVAL) )
00517 update_count_for_logging = 0;
00518 }
00519
00520 void
00521 ArenaRealTime::add_cookie()
00522 {
00523 double en = the_opts.get_d(OPTION_COOKIE_MIN_ENERGY) +
00524 (the_opts.get_d(OPTION_COOKIE_MAX_ENERGY) - the_opts.get_d(OPTION_COOKIE_MIN_ENERGY)) *
00525 (double)rand() / (double)RAND_MAX;
00526 bool found_space = false;
00527 double r = the_opts.get_d(OPTION_COOKIE_RADIUS);
00528 Vector2D pos;
00529
00530 for( int i=0; i<100 && !found_space; i++ )
00531 {
00532 pos = get_random_position();
00533 found_space = space_available(pos, r*2.0);
00534 }
00535
00536 if( !found_space ) return;
00537
00538 Cookie* cookiep = new Cookie(pos, en);
00539 object_lists[COOKIE].insert_last( cookiep );
00540
00541 print_to_logfile('C', cookiep->get_id(), pos[0], pos[1]);
00542 }
00543
00544 void
00545 ArenaRealTime::add_mine()
00546 {
00547 double en = the_opts.get_d(OPTION_MINE_MIN_ENERGY) +
00548 (the_opts.get_d(OPTION_MINE_MAX_ENERGY) - the_opts.get_d(OPTION_MINE_MIN_ENERGY)) *
00549 (double)rand() / (double)RAND_MAX;
00550 bool found_space = false;
00551 double r = the_opts.get_d(OPTION_MINE_RADIUS);
00552 Vector2D pos;
00553
00554 for( int i=0; i<100 && !found_space; i++)
00555 {
00556 pos = get_random_position();
00557 found_space = space_available(pos, r*2.0);
00558 }
00559
00560 if( !found_space ) return;
00561
00562 Mine* minep = new Mine(pos, en);
00563 object_lists[MINE].insert_last( minep );
00564
00565 print_to_logfile('M', minep->get_id(), pos[0], pos[1]);
00566 }
00567
00568 void
00569 ArenaRealTime::check_robots()
00570 {
00571 ListIterator<Robot> li;
00572 for( all_robots_in_sequence.first(li); li.ok(); li++ )
00573 {
00574 if( li()->is_process_running() )
00575 {
00576 li()->check_process();
00577 }
00578 }
00579
00580 next_check_time = total_time + the_opts.get_d(OPTION_CHECK_INTERVAL);
00581 }
00582
00583 void
00584 ArenaRealTime::read_robot_messages()
00585 {
00586 ListIterator<Robot> li;
00587 for( all_robots_in_sequence.first(li); li.ok(); li++ )
00588 {
00589 if( li()->is_alive() || state != GAME_IN_PROGRESS )
00590 li()->get_messages();
00591 }
00592 }
00593
00594 void
00595 ArenaRealTime::update_robots()
00596 {
00597 Robot* robotp;
00598
00599 robots_killed_this_round = 0;
00600
00601 ListIterator<Shape> li;
00602 for( object_lists[ROBOT].first(li); li.ok(); li++ )
00603 {
00604 robotp = (Robot*)li();
00605 if( robotp->is_alive() )
00606 {
00607 robotp->update_radar_and_cannon(timestep);
00608 robotp->change_velocity(timestep);
00609 robotp->move(timestep);
00610 }
00611 if( robotp->is_alive() )
00612 robotp->get_messages();
00613 }
00614
00615
00616
00617 for( object_lists[ROBOT].first(li); li.ok(); li++ )
00618 {
00619 robotp = (Robot*)li();
00620 if( !robotp->is_alive() )
00621 {
00622 object_lists[ROBOT].remove(li);
00623 robots_killed_this_round++;
00624 }
00625 else
00626 {
00627 double lvls = (double)the_opts.get_l(OPTION_ROBOT_ENERGY_LEVELS);
00628 robotp->send_message( ENERGY, rint( robotp->get_energy() / lvls ) * lvls );
00629 }
00630 }
00631
00632 robots_left -= robots_killed_this_round;
00633
00634 if( robots_killed_this_round > 0 )
00635 {
00636 for( object_lists[ROBOT].first(li); li.ok(); li++ )
00637 {
00638 robotp = (Robot*)li();
00639
00640 #ifndef NO_GRAPHICS
00641 if( robots_left < 15 && !no_graphics )
00642 robotp->display_score();
00643 #endif
00644 }
00645
00646 ListIterator<Robot> li2;
00647 for( all_robots_in_sequence.first(li2); li2.ok(); li2++ )
00648 if( li2()->is_dead_but_stats_not_set() )
00649 li2()->set_stats(robots_killed_this_round);
00650
00651 broadcast(ROBOTS_LEFT, robots_left);
00652 }
00653
00654
00655 for( object_lists[ROBOT].first(li); li.ok(); li++ )
00656 ((Robot*)li())->send_signal();
00657 }
00658
00659
00660
00661
00662 double
00663 ArenaRealTime::colour_dist(const long col1, const long int col2)
00664 {
00665 double red1 = (col1 & 0x0000ff);
00666 double green1 = (col1 & 0x00ff00) >> 8;
00667 double blue1 = (col1 & 0xff0000) >> 16;
00668
00669 double red2 = (col2 & 0x0000ff);
00670 double green2 = (col2 & 0x00ff00) >> 8;
00671 double blue2 = (col2 & 0xff0000) >> 16;
00672
00673 return ( fabs(red1 -red2 ) * log(1.0 + sqrt(red1 +red2 )) +
00674 fabs(green1-green2) * log(1.0 + sqrt(green1+green2)) +
00675 fabs(blue1 -blue2 ) * log(1.0 + sqrt(blue1 +blue2 )) ) / 2417.8;
00676
00677
00678
00679
00680
00681
00682
00683
00684 }
00685
00686 bool
00687 ArenaRealTime::is_colour_allowed(const long colour, const double min_dist, const Robot* robotp)
00688 {
00689 double d;
00690 ListIterator<Robot> li;
00691
00692 for( all_robots_in_sequence.first(li); li.ok(); li++ )
00693 {
00694 if(li() != robotp)
00695 {
00696 d = colour_dist( colour, li()->get_rgb_colour() );
00697 if( d < min_dist ) return false;
00698 }
00699 }
00700
00701 d = colour_dist( colour, the_opts.get_l( OPTION_BACKGROUND_COLOUR ) );
00702 if( d < min_dist ) return false;
00703
00704 return true;
00705 }
00706
00707 long int
00708 ArenaRealTime::find_free_colour(const long int home_colour,
00709 const long int away_colour,
00710 const Robot* robotp, const bool random_colours)
00711 {
00712 long int tmp_colour;
00713
00714 for(double min_dist = 0.1; min_dist > 0.01 ; min_dist *= 0.8)
00715 {
00716 if( !random_colours )
00717 {
00718 if( is_colour_allowed(home_colour, min_dist, robotp) ) return home_colour;
00719 if( is_colour_allowed(away_colour, min_dist, robotp) ) return away_colour;
00720 }
00721 for(int i=0; i<25; i++)
00722 {
00723 tmp_colour = rand() & 0xffffff;
00724 if( is_colour_allowed(tmp_colour, min_dist*2, robotp) ) return tmp_colour;
00725 }
00726 }
00727 Error(true, "Impossible to find colour", "ArenaRealTime::find_free_colour");
00728
00729 return 0;
00730 }
00731
00732 int
00733 ArenaRealTime::set_debug_level( const int new_level)
00734 {
00735 ArenaBase::set_debug_level(new_level);
00736
00737 if( GAME_IN_PROGRESS )
00738 {
00739 broadcast(GAME_OPTION, DEBUG_LEVEL, (double)debug_level);
00740 }
00741
00742 return debug_level;
00743 }
00744
00745 void
00746 ArenaRealTime::start_game()
00747 {
00748
00749
00750 if( pause_after_next_game )
00751 {
00752 set_state( PAUSING_BETWEEN_GAMES );
00753 return;
00754 }
00755
00756 current_arena_nr = current_arena_nr % number_of_arenas + 1;
00757
00758 String* filename = arena_filenames.get_nth(current_arena_nr);
00759
00760 print_to_logfile('G', sequence_nr, game_nr + 1);
00761
00762 parse_arena_file(*filename);
00763
00764 int charpos;
00765 if( (charpos = filename->find('/',0,true)) != -1 )
00766 current_arena_filename = get_segment(*filename, charpos+1, -1);
00767 else
00768 Error(true, "Incomplete arena file path" + *filename, "ArenaRealTime::start_game");
00769
00770 char msg[128];
00771 snprintf( msg, 127, _("Game %d of sequence %d begins on arena"),
00772 game_nr+1, sequence_nr );
00773 print_message( "RealTimeBattle", String(msg) + " " + current_arena_filename );
00774
00775
00776
00777 shot_count = 0;
00778 cookie_count = 0;
00779 mine_count = 0;
00780
00781
00782
00783
00784 Robot* robotp;
00785 bool found_space;
00786 double angle;
00787 Vector2D pos;
00788
00789 robots_left = 0;
00790
00791 set_state( BEFORE_GAME_START );
00792
00793 ListIterator<Robot> li;
00794 for( all_robots_in_sequence.first(li); li.ok(); li++ )
00795 {
00796 robotp = li();
00797 robotp->get_messages();
00798
00799 found_space = false;
00800 for( int i=0; i<100 && !found_space; i++)
00801 {
00802 pos = get_random_position();
00803 found_space = space_available(pos, the_opts.get_d(OPTION_ROBOT_RADIUS)*1.2);
00804 }
00805
00806 if( !found_space ) Error(true, "Couldn't find space for all robots", "ArenaRealTime::start_game");
00807 angle = ((double)rand())*2.0*M_PI/RAND_MAX;
00808 robotp->set_values_before_game(pos, angle);
00809 object_lists[ROBOT].insert_last(robotp);
00810 robots_left++;
00811 robotp->live();
00812 }
00813
00814
00815
00816 broadcast(GAME_STARTS);
00817 broadcast(ROBOTS_LEFT, robots_left);
00818 the_opts.broadcast_opts();
00819
00820
00821 update_count_for_logging = 0;
00822 print_to_logfile('T', 0.0);
00823
00824 ListIterator<Shape> li2;
00825 for( object_lists[ROBOT].first(li2); li2.ok(); li2++ )
00826 {
00827 robotp = (Robot*)li2();
00828 robotp->send_signal();
00829 robotp->move(0.0);
00830 }
00831
00832 set_state( GAME_IN_PROGRESS );
00833 game_nr++;
00834
00835 #ifndef NO_GRAPHICS
00836 if( !no_graphics )
00837 {
00838 the_gui.get_arenawindow_p()->clear_area();
00839 the_gui.get_arenawindow_p()->drawing_area_scale_changed();
00840 the_gui.get_scorewindow_p()->update_robots();
00841
00842 reset_timer();
00843 the_gui.get_scorewindow_p()->set_window_title();
00844 the_gui.get_arenawindow_p()->set_window_title();
00845 }
00846 #endif
00847
00848 reset_timer();
00849 next_check_time = total_time + the_opts.get_d(OPTION_CHECK_INTERVAL);
00850 }
00851
00852 void
00853 ArenaRealTime::end_game()
00854 {
00855 Robot* robotp;
00856 ListIterator<Robot> li;
00857
00858 int robots_died_by_timeout = robots_left;
00859 robots_left = 0;
00860
00861 for( all_robots_in_sequence.first(li); li.ok(); li++ )
00862 {
00863 robotp = li();
00864 if( robotp->is_alive() || robotp->is_dead_but_stats_not_set() )
00865 {
00866 robotp->die();
00867 robotp->set_stats(robots_died_by_timeout, true);
00868 }
00869 }
00870
00871 broadcast(GAME_FINISHES);
00872
00873 delete_lists(false, false, false, false);
00874
00875 if(game_nr == games_per_sequence)
00876 end_sequence();
00877 else
00878 start_game();
00879 }
00880
00881
00882 void
00883 ArenaRealTime::start_sequence()
00884 {
00885 game_nr = 0;
00886 current_arena_nr = 0;
00887
00888
00889
00890 for(int i=0; i<robots_per_game; i++)
00891 {
00892 all_robots_in_sequence.
00893 insert_last( all_robots_in_tournament.
00894 get_nth(robots_in_sequence[sequence_nr][i]));
00895 }
00896
00897
00898
00899
00900 Robot* robotp;
00901 ListIterator<Robot> li;
00902 for( all_robots_in_sequence.first(li); li.ok(); li++ )
00903 {
00904 robotp = li();
00905 if( robotp->is_networked() )
00906 {
00907 *robotp->get_outstreamp() << "@R" << endl;
00908 robotp->set_values_at_process_start_up();
00909 }
00910 else
00911 robotp->start_process();
00912 }
00913
00914
00915
00916 set_state( STARTING_ROBOTS );
00917 sequence_nr++;
00918 reset_timer();
00919 next_check_time = total_time + the_opts.get_d(OPTION_ROBOT_STARTUP_TIME);
00920 }
00921
00922 void
00923 ArenaRealTime::start_sequence_follow_up()
00924 {
00925
00926 Robot* robotp = NULL;
00927
00928 ListIterator<Robot> li;
00929 for( all_robots_in_sequence.first(li); li.ok(); li++ )
00930 {
00931 robotp = li();
00932 if( !(robotp->is_networked()) &&
00933 !(robotp->is_process_running()) )
00934 {
00935 all_robots_in_sequence.remove(li);
00936 robots_left--;
00937 }
00938 else
00939 {
00940 if( !robotp->set_and_get_has_competed() )
00941 print_to_logfile('L', robotp->get_id(), robotp->get_rgb_colour(),
00942 robotp->get_robot_name().chars());
00943
00944 if( !robotp->is_name_given() )
00945 {
00946 robotp->send_message(WARNING, NAME_NOT_GIVEN, "");
00947 char msg[128];
00948 snprintf( msg, 127, _("Robot with filename %s has not given any name"),
00949 robotp->get_robot_filename().chars() );
00950 print_message( "RealTimeBattle", String(msg) );
00951 }
00952
00953 if( !robotp->is_colour_given() )
00954 {
00955 robotp->send_message(WARNING, COLOUR_NOT_GIVEN, "");
00956 robotp->set_colour( find_free_colour( 0, 0, robotp, true ) );
00957 robotp->set_colour_given( true );
00958 }
00959 }
00960
00961 }
00962 start_game();
00963 }
00964
00965 void
00966 ArenaRealTime::end_sequence()
00967 {
00968
00969
00970 ListIterator<Robot> li;
00971 for( all_robots_in_sequence.first(li); li.ok(); li++ )
00972 {
00973 li()->end_process();
00974 }
00975
00976
00977
00978 set_state( SHUTTING_DOWN_ROBOTS);
00979 next_check_time = total_time + 1.0;
00980 }
00981
00982 void
00983 ArenaRealTime::end_sequence_follow_up()
00984 {
00985
00986
00987 Robot* robotp;
00988
00989 ListIterator<Robot> li;
00990 for( all_robots_in_sequence.first(li); li.ok(); li++ )
00991 {
00992 robotp = li();
00993 if( robotp->is_process_running() ) robotp->kill_process_forcefully();
00994 robotp->delete_pipes();
00995 all_robots_in_sequence.remove(li);
00996 }
00997
00998 if( sequence_nr == sequences_in_tournament )
00999 end_tournament();
01000 else
01001 start_sequence();
01002 }
01003
01004 void
01005 ArenaRealTime::start_tournament_from_tournament_file
01006 ( const List<start_tournament_info_t>& robotfilename_list,
01007 const List<start_tournament_info_t>& arenafilename_list,
01008 const int robots_p_game, const int games_p_sequence,
01009 const int n_o_sequences, ArenaRealTime* ar_p )
01010 {
01011 ar_p->start_tournament( robotfilename_list, arenafilename_list, robots_p_game,
01012 games_p_sequence, n_o_sequences );
01013 }
01014
01015 void
01016 ArenaRealTime::
01017 start_tournament(const List<start_tournament_info_t>& robotfilename_list,
01018 const List<start_tournament_info_t>& arenafilename_list,
01019 const int robots_p_game,
01020 const int games_p_sequence,
01021 const int n_o_sequences)
01022 {
01023 clear();
01024
01025
01026
01027 #ifndef NO_GRAPHICS
01028 if( !no_graphics )
01029 {
01030 if( the_gui.is_messagewindow_up() )
01031 MessageWindow::clear_clist( NULL, the_gui.get_messagewindow_p() );
01032 else
01033 the_gui.open_messagewindow();
01034
01035 if( !the_gui.is_scorewindow_up() ) the_gui.open_scorewindow();
01036 if( !the_gui.is_arenawindow_up() ) the_gui.open_arenawindow();
01037 }
01038 #endif
01039
01040
01041
01042 number_of_robots = 0;
01043 robot_count = 0;
01044 Robot* robotp;
01045 start_tournament_info_t* infop = NULL;
01046 String* stringp;
01047
01048 ListIterator<start_tournament_info_t> li;
01049 for( robotfilename_list.first(li); li.ok(); li++ )
01050 {
01051 infop = li();
01052 robotp = new Robot(infop->filename);
01053 all_robots_in_tournament.insert_last( robotp );
01054 number_of_robots++;
01055 }
01056
01057
01058 number_of_arenas = 0;
01059
01060 for( arenafilename_list.first(li); li.ok(); li++ )
01061 {
01062 stringp = new String(li()->filename);
01063 arena_filenames.insert_last( stringp );
01064 number_of_arenas++;
01065 }
01066
01067 robots_per_game = robots_p_game;
01068 games_per_sequence = games_p_sequence;
01069 sequences_in_tournament = n_o_sequences;
01070
01071
01072 int games_per_round = binomial(number_of_robots, robots_per_game);
01073 int complete_rounds = n_o_sequences / games_per_round;
01074 int rem_games = n_o_sequences % games_per_round;
01075
01076 robots_in_sequence = new (int*)[n_o_sequences];
01077 for(int i=0; i<n_o_sequences; i++) robots_in_sequence[i] = new int[robots_per_game];
01078
01079 int current_sequence[robots_per_game];
01080 int current_nr = 0;
01081
01082
01083
01084
01085 for(int round_nr=0; round_nr < complete_rounds; round_nr++)
01086 {
01087 int k, i, j;
01088
01089 for(i=0; i<robots_per_game; i++) current_sequence[i] = i+1;
01090 current_sequence[robots_per_game-1]--;
01091
01092
01093 for(i=0; i< games_per_round; i++)
01094 {
01095
01096 k = robots_per_game - 1;
01097 while( current_sequence[k] == number_of_robots + 1 - robots_per_game + k )
01098 k--;
01099
01100 if( k < 0 ) Error(true, "Problem generating list of participants, k < 0",
01101 "ArenaRealTime::start_tournament");
01102
01103 current_sequence[k]++;
01104 for(j=k+1; j<robots_per_game; j++) current_sequence[j] = current_sequence[j-1]+1;
01105
01106 for(j=0; j<robots_per_game; j++)
01107 robots_in_sequence[current_nr][j] = current_sequence[j];
01108
01109 current_nr++;
01110 }
01111 reorder_pointer_array((void**)robots_in_sequence, games_per_round);
01112 }
01113
01114
01115
01116 int robot_matches_played[number_of_robots];
01117 for(int i=0; i<number_of_robots; i++) robot_matches_played[i] = 0;
01118
01119 bool robot_playing_this_match[number_of_robots];
01120 int min_matches_played = 0;
01121 int number_of_robots_on_min_matches = number_of_robots;
01122 int nr;
01123
01124 for(int i=0; i< rem_games; i++)
01125 {
01126 for(int i2=0; i2<number_of_robots; i2++) robot_playing_this_match[i2] = false;
01127
01128 for(int j=0; j<robots_per_game; j++)
01129 {
01130 do
01131 nr = (int)floor(number_of_robots*((double)rand() / (double)RAND_MAX));
01132 while( robot_playing_this_match[nr] || robot_matches_played[nr] != min_matches_played );
01133
01134 robot_playing_this_match[nr] = true;
01135 robot_matches_played[nr]++;
01136 number_of_robots_on_min_matches--;
01137 if( number_of_robots_on_min_matches == 0 )
01138 {
01139 min_matches_played++;
01140 number_of_robots_on_min_matches = number_of_robots;
01141 }
01142
01143 robots_in_sequence[current_nr][j] = nr + 1;
01144 }
01145 current_nr++;
01146 }
01147
01148
01149
01150
01151 srand(timer.get_random_seed());
01152
01153
01154
01155 print_to_logfile('H', games_per_sequence, robots_per_game,
01156 sequences_in_tournament, number_of_robots);
01157
01158 the_opts.log_all_options();
01159
01160 sequence_nr = 0;
01161 start_sequence();
01162 }
01163
01164 void
01165 ArenaRealTime::end_tournament()
01166 {
01167 set_state( FINISHED );
01168
01169 #ifndef NO_GRAPHICS
01170 if( !no_graphics )
01171 {
01172
01173
01174
01175 the_gui.close_arenawindow();
01176 }
01177 #endif
01178 }