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 <sys/stat.h>
00026 #include <math.h>
00027 #include <stdio.h>
00028
00029 #include "ArenaReplay.h"
00030 #include "ArenaController.h"
00031 #include "IntlDefs.h"
00032 #include "Various.h"
00033 #include "Options.h"
00034 #include "Extras.h"
00035 #include "Shot.h"
00036 #include "MessageWindow.h"
00037 #include "ArenaWindow.h"
00038 #include "ScoreWindow.h"
00039 #include "ControlWindow.h"
00040 #include "Robot.h"
00041
00042 const int max_time_infos = 16384;
00043
00044 extern class ControlWindow* controlwindow_p;
00045
00046 ArenaReplay::ArenaReplay()
00047 {
00048 reset_timer();
00049
00050 fast_forward_factor = 1.0;
00051 state = NOT_STARTED;
00052 current_replay_time = 0.0;
00053 game_position_in_log = NULL;
00054 time_position_in_log = NULL;
00055
00056 set_game_mode( (ArenaBase::game_mode_t)the_arena_controller.game_mode );
00057 set_filenames( the_arena_controller.replay_filename,
00058 the_arena_controller.message_filename,
00059 the_arena_controller.statistics_filename,
00060 the_arena_controller.option_filename );
00061 }
00062
00063 ArenaReplay::~ArenaReplay()
00064 {
00065 if( game_position_in_log != NULL )
00066 {
00067 for( int i=0; i<sequences_in_tournament; i++ )
00068 delete [] game_position_in_log[i];
00069 delete [] game_position_in_log;
00070 }
00071
00072 if( time_position_in_log != NULL )
00073 delete [] time_position_in_log;
00074
00075 }
00076
00077 bool
00078 ArenaReplay::timeout_function()
00079 {
00080 if( ( state == GAME_IN_PROGRESS || state == BEFORE_GAME_START ) )
00081 update_timer( fast_forward_factor );
00082 else if( state == PAUSED )
00083 update_timer( 0.0 );
00084
00085 switch( state )
00086 {
00087 case NOT_STARTED:
00088 start_tournament();
00089 break;
00090 case GAME_IN_PROGRESS:
00091 {
00092 #ifndef NO_GRAPHICS
00093 int old_total = (int)current_replay_time;
00094 #endif
00095
00096 parse_this_interval();
00097
00098 #ifndef NO_GRAPHICS
00099 if((int)current_replay_time - old_total != 0 && !no_graphics)
00100 {
00101 the_gui.get_scorewindow_p()->set_window_title();
00102 if( !log_from_stdin )
00103 controlwindow_p->set_progress_time( current_replay_time );
00104 }
00105 #endif
00106 }
00107 break;
00108
00109 case BEFORE_GAME_START:
00110 parse_this_interval();
00111 #ifndef NO_GRAPHICS
00112 if( !no_graphics )
00113 {
00114 if( controlwindow_p->get_displayed() != ControlWindow::REPLAY_WIDGETS &&
00115 !log_from_stdin )
00116 controlwindow_p->display_replay_widgets();
00117 the_gui.get_arenawindow_p()->drawing_area_scale_changed();
00118 the_gui.get_arenawindow_p()->draw_everything();
00119 the_gui.get_scorewindow_p()->update_robots();
00120 char msg[64];
00121 snprintf(msg, 63, _("Game %d of sequence %d"), game_nr, sequence_nr);
00122 print_message( "RealTimeBattle", (String)msg );
00123 }
00124 #endif
00125 set_state( GAME_IN_PROGRESS );
00126 break;
00127
00128 case FINISHED:
00129 if( the_arena_controller.auto_start_and_end )
00130 {
00131 if( statistics_file_name != "" )
00132 save_statistics_to_file( statistics_file_name );
00133
00134 Quit();
00135 }
00136 break;
00137
00138 default:
00139 break;
00140 }
00141 return true;
00142 }
00143
00144 void
00145 ArenaReplay::parse_this_interval()
00146 {
00147 #ifndef NO_GRAPHICS
00148 if( state == GAME_IN_PROGRESS && !no_graphics)
00149 the_gui.get_messagewindow_p()->freeze_clist();
00150 #endif
00151 if( fast_forward_factor > 0.0 )
00152 while( !log_file.eof() && total_time >= current_replay_time )
00153 {
00154 parse_this_time_index();
00155 }
00156 else
00157 {
00158 while( !log_file.eof() && total_time <= current_replay_time &&
00159 step_forward(-1, false) )
00160 {
00161 parse_this_time_index();
00162 }
00163 }
00164 #ifndef NO_GRAPHICS
00165 if( state == GAME_IN_PROGRESS && !no_graphics)
00166 the_gui.get_messagewindow_p()->thaw_clist();
00167 #endif
00168
00169 if( log_file.eof() )
00170 {
00171 set_state( FINISHED );
00172 #ifndef NO_GRAPHICS
00173 if( !no_graphics )
00174 {
00175 controlwindow_p->remove_replay_widgets();
00176 the_gui.close_arenawindow();
00177 }
00178 #endif
00179 }
00180 }
00181
00182 void
00183 ArenaReplay::parse_this_time_index()
00184 {
00185 double last_replay_time = current_replay_time;
00186
00187 if( log_file.peek() == 'T' )
00188 parse_log_line();
00189 else
00190 {
00191
00192
00193
00194 }
00195
00196 double next_replay_time = current_replay_time;
00197
00198 while( log_file.peek() != 'T' || current_replay_time == 0.0 )
00199 {
00200 if( parse_log_line() == '?' ) return;
00201 if ( current_replay_time == 0.0 ) next_replay_time = 0.0;
00202 }
00203
00204
00205 current_replay_time = next_replay_time;
00206 move_shots_no_check( current_replay_time - last_replay_time );
00207
00208 #ifndef NO_GRAPHICS
00209 if( !no_graphics )
00210 the_gui.get_arenawindow_p()->draw_moving_objects( true );
00211 #endif
00212
00213
00214 if( robots_killed_this_round != 0 )
00215 {
00216 robots_left -= robots_killed_this_round;
00217
00218 ListIterator<Shape> li;
00219 Robot* robotp;
00220 for( object_lists[ROBOT].first(li); li.ok(); li++ )
00221 {
00222 robotp = (Robot*)li();
00223 if( robotp->is_alive() )
00224 {
00225
00226 #ifndef NO_GRAPHICS
00227 if( robots_left < 15 && !no_graphics )
00228 robotp->display_score();
00229 #endif
00230 }
00231 }
00232
00233 robots_killed_this_round = 0;
00234 }
00235 }
00236
00237 void
00238 ArenaReplay::start_tournament()
00239 {
00240 #ifndef NO_GRAPHICS
00241 if( !no_graphics )
00242 {
00243 if( the_gui.is_messagewindow_up() )
00244 MessageWindow::clear_clist( NULL, the_gui.get_messagewindow_p() );
00245 else
00246 the_gui.open_messagewindow();
00247
00248 if( !the_gui.is_scorewindow_up() ) the_gui.open_scorewindow();
00249 if( !the_gui.is_arenawindow_up() ) the_gui.open_arenawindow();
00250 }
00251 #endif
00252
00253 if( !log_from_stdin )
00254 make_statistics_from_file();
00255
00256 set_state( BEFORE_GAME_START );
00257 }
00258
00259 void
00260 ArenaReplay::end_game()
00261 {
00262 }
00263
00264 void
00265 ArenaReplay::update()
00266 {
00267 }
00268
00269 void
00270 ArenaReplay::start_game()
00271 {
00272 }
00273
00274 void
00275 ArenaReplay::start_sequence()
00276 {
00277 }
00278
00279 void
00280 ArenaReplay::end_sequence()
00281 {
00282 }
00283
00284 void
00285 ArenaReplay::end_tournament()
00286 {
00287 }
00288
00289 char
00290 ArenaReplay::parse_log_line()
00291 {
00292 char first_letter = '?';
00293
00294 log_file >> ws;
00295 log_file.get( first_letter );
00296
00297 if( log_file.eof() ) return '?';
00298
00299 switch( first_letter )
00300 {
00301 case 'R':
00302 case 'S':
00303 case 'M':
00304 case 'C':
00305 case 'D':
00306 if ( fast_forward_factor > 0.0 )
00307 parse_log_line_forward( first_letter );
00308 else
00309 parse_log_line_rewind( first_letter );
00310 break;
00311
00312 case 'T':
00313 {
00314 log_file >> current_replay_time;
00315 }
00316 break;
00317 case 'P':
00318 {
00319 int robot_id;
00320 char message[200];
00321 log_file >> robot_id;
00322 log_file.get( message, 200, '\n' );
00323 ListIterator<Shape> li;
00324 find_object_by_id( object_lists[ROBOT], li, robot_id );
00325 if( li.ok() )
00326 {
00327 Robot* robotp = (Robot*)li();
00328 print_message( robotp->get_robot_name(), (String)message );
00329 }
00330
00331
00332 }
00333 break;
00334 case 'G':
00335 {
00336 delete_lists(false, false, false, false);
00337 reset_timer();
00338 current_replay_time = 0;
00339 robots_killed_this_round = 0;
00340 robots_left = robots_per_game;
00341
00342 log_file >> sequence_nr >> game_nr;
00343
00344 if( !log_from_stdin )
00345 get_time_positions_in_game();
00346
00347 ListIterator<Robot> li;
00348 for( all_robots_in_tournament.first(li); li.ok(); li++ )
00349 li()->set_values_before_game(Vector2D(infinity,infinity), 0.0);
00350
00351 arena_scale = the_opts.get_d(OPTION_ARENA_SCALE);
00352 arena_angle_factor = 1.0;
00353 arena_succession = 1;
00354 set_state( BEFORE_GAME_START );
00355
00356 #ifndef NO_GRAPHICS
00357 controlwindow_p->change_time_limitations();
00358 #endif
00359 }
00360 break;
00361 case 'H':
00362 {
00363 if( log_from_stdin )
00364 log_file >> games_per_sequence >> robots_per_game
00365 >> sequences_in_tournament >> number_of_robots;
00366 else
00367 {
00368 char buffer[400];
00369 log_file.get( buffer, 400, '\n' );
00370 log_file >> ws;
00371 }
00372 }
00373 break;
00374 case 'L':
00375 {
00376 if( log_from_stdin )
00377 {
00378 int robot_id;
00379 char robot_colour[7];
00380 char name[200];
00381 log_file >> robot_id >> ws;
00382 log_file.get( robot_colour, 7, ' ');
00383 long int col = str2hex( (String)robot_colour );
00384 log_file.get( name, 200, '\n' );
00385 Robot* robotp = new Robot( robot_id, col, (String)name );
00386 all_robots_in_tournament.insert_last(robotp);
00387 }
00388 else
00389 {
00390 char buffer[400];
00391 log_file.get( buffer, 400, '\n' );
00392 log_file >> ws;
00393 }
00394 }
00395 break;
00396 case 'A':
00397 {
00398 parse_arena_line( log_file, arena_scale, arena_succession, arena_angle_factor );
00399 }
00400 break;
00401 case 'O':
00402 {
00403 char temp;
00404 char label[200];
00405 log_file.get( label, 200, ':');
00406 log_file.get( temp );
00407 option_return_t opt = the_opts.get_option_from_string( String( label ) );
00408 switch( opt.datatype )
00409 {
00410 case ENTRY_INT:
00411 case ENTRY_HEX:
00412 {
00413 long val;
00414 log_file >> val;
00415
00416 the_opts.get_all_long_options()[opt.option_number].value = val;
00417 }
00418 break;
00419 case ENTRY_DOUBLE:
00420 {
00421 double val;
00422 log_file >> val;
00423
00424 the_opts.get_all_double_options()[opt.option_number].value = val;
00425 }
00426 break;
00427 case ENTRY_CHAR:
00428 {
00429 char val[400];
00430 log_file.get( val, 400, '\n' );
00431
00432 the_opts.get_all_string_options()[opt.option_number].value = val;
00433 }
00434 break;
00435 case ENTRY_BOOL:
00436 break;
00437 default:
00438 Error( true, "Unknown datatype", "ArenaReplay::parse_log_line" );
00439 break;
00440 }
00441 }
00442 break;
00443
00444 case '?':
00445 default:
00446 Error( false, "Unrecognized first letter in logfile: " +
00447 String(first_letter), "ArenaReplay::parse_log_line" );
00448 char buffer[400];
00449 log_file.get( buffer, 400, '\n' );
00450 log_file >> ws;
00451 log_file.clear();
00452 break;
00453 }
00454
00455 log_file >> ws;
00456
00457 return first_letter;
00458 }
00459
00460 void
00461 ArenaReplay::parse_log_line_forward( const char first_letter )
00462 {
00463 switch( first_letter )
00464 {
00465 case 'R':
00466 {
00467 int robot_id;
00468 double x, y, robot_angle, cannon_angle, radar_angle, energy;
00469 Robot* robotp = NULL;
00470 log_file >> robot_id >> x >> y
00471 >> robot_angle >> cannon_angle >> radar_angle >> energy;
00472 ListIterator<Shape> li;
00473 if( find_object_by_id( object_lists[ROBOT], li, robot_id ) )
00474 {
00475 robotp = (Robot*)li();
00476 }
00477 else
00478 {
00479 ListIterator<Robot> li2;
00480 if( log_from_stdin &&
00481 find_object_by_id( all_robots_in_tournament, li2, robot_id ) )
00482 {
00483 object_lists[ROBOT].insert_last( li2() );
00484 robotp = li2();
00485 }
00486 else
00487 Error(true, "Robot not in list", "ArenaReplay::parse_log_line_forward");
00488 }
00489
00490 robotp->change_position( x, y, robot_angle, cannon_angle, radar_angle, energy );
00491 robotp->live();
00492 }
00493 break;
00494 case 'C':
00495 {
00496 int cookie_id;
00497 double x, y;
00498 log_file >> cookie_id >> x >> y;
00499 Cookie* cookiep = new Cookie( Vector2D(x,y), 0.0, cookie_id);
00500 object_lists[COOKIE].insert_last( cookiep );
00501 }
00502 break;
00503 case 'M':
00504 {
00505 int mine_id;
00506 double x, y;
00507 log_file >> mine_id >> x >> y;
00508 Mine* minep = new Mine( Vector2D(x,y), 0.0, mine_id);
00509 object_lists[MINE].insert_last( minep );
00510 }
00511 break;
00512 case 'S':
00513 {
00514 int shot_id;
00515 double x, y, dx, dy;
00516 log_file >> shot_id >> x >> y >> dx >> dy;
00517 Shot* shotp = new Shot( Vector2D(x,y), Vector2D(dx,dy), 0, shot_id );
00518 object_lists[SHOT].insert_last( shotp );
00519 }
00520 break;
00521
00522
00523 case 'D':
00524 {
00525 char object_type = '?';
00526 int object_id;
00527 log_file.get( object_type );
00528 log_file >> object_id;
00529 switch( object_type )
00530 {
00531 case 'R':
00532 {
00533 double points_received;
00534 int pos_this_game;
00535 log_file >> points_received >> pos_this_game;
00536 ListIterator<Shape> li;
00537 find_object_by_id( object_lists[ROBOT], li, object_id );
00538 if( !li.ok() )
00539 Error(true, "Dying robot not in list", "ArenaReplay::parse_log_line_forward");
00540 Robot* robotp = (Robot*) li();
00541 if( robotp->is_alive() )
00542 {
00543 robotp->die();
00544 robots_killed_this_round++;
00545 robotp->set_stats( points_received, pos_this_game,
00546 current_replay_time, log_from_stdin);
00547 robotp->change_energy( -robotp->get_energy() );
00548 }
00549 }
00550 break;
00551 case 'C':
00552 {
00553 ListIterator<Shape> li;
00554 find_object_by_id( object_lists[COOKIE], li, object_id );
00555 if( !li.ok() )
00556 Error(false, "Dying cookie not in list", "ArenaReplay::parse_log_line_forward");
00557 else
00558 {
00559 ((Cookie*)li())->die();
00560 object_lists[COOKIE].remove(li);
00561 }
00562 }
00563 break;
00564 case 'M':
00565 {
00566 ListIterator<Shape> li;
00567 find_object_by_id( object_lists[MINE], li, object_id );
00568 if( !li.ok() )
00569 Error(false, "Dying mine not in list", "ArenaReplay::parse_log_line_forward");
00570 else
00571 {
00572 ((Mine*)li())->die();
00573 object_lists[MINE].remove(li);
00574 }
00575 }
00576 break;
00577 case 'S':
00578 {
00579 ListIterator<Shape> li;
00580 find_object_by_id( object_lists[SHOT], li, object_id );
00581 if( !li.ok() )
00582 Error(false, "Dying shot not in list", "ArenaReplay::parse_log_line_forward");
00583 else
00584 {
00585 ((Shot*)li())->die();
00586 object_lists[SHOT].remove(li);
00587 }
00588 }
00589 break;
00590 case '?':
00591 default:
00592 Error( false, "Unknown object type is dead", "ArenaReplay::parse_log_line_forward" );
00593 break;
00594 }
00595 }
00596 break;
00597 }
00598 }
00599
00600 void
00601 ArenaReplay::parse_log_line_rewind( const char first_letter )
00602 {
00603 switch( first_letter )
00604 {
00605 case 'R':
00606 {
00607 int robot_id;
00608 double x, y, robot_angle, cannon_angle, radar_angle, energy;
00609 log_file >> robot_id >> x >> y >>
00610 robot_angle >> cannon_angle >> radar_angle >> energy;
00611 ListIterator<Shape> li;
00612 find_object_by_id( object_lists[ROBOT], li, robot_id );
00613 if( !li.ok() ) Error(true, "Robot not in list", "ArenaReplay::parse_log_line_rewind");
00614
00615 Robot* robotp = (Robot*)li();
00616
00617 robotp->change_position( x, y, robot_angle, cannon_angle, radar_angle, energy );
00618 if( !robotp->is_alive() )
00619 {
00620 robotp->live();
00621 robots_killed_this_round--;
00622 robotp->set_stats(0.0, 0, 0.0, false);
00623 }
00624 }
00625 break;
00626
00627
00628 case 'C':
00629 {
00630 int id;
00631 double x,y;
00632 log_file >> id >> x >> y;
00633 ListIterator<Shape> li;
00634 find_object_by_id( object_lists[COOKIE], li, id );
00635 if( !li.ok() )
00636 {
00637
00638
00639 }
00640 else
00641 {
00642 ((Cookie*)li())->die();
00643 object_lists[COOKIE].remove(li);
00644 }
00645 }
00646 break;
00647 case 'M':
00648 {
00649 int id;
00650 double x,y;
00651 log_file >> id >> x >> y;
00652 ListIterator<Shape> li;
00653 find_object_by_id( object_lists[MINE], li, id );
00654 if( !li.ok() )
00655 {
00656
00657
00658 }
00659 else
00660 {
00661 ((Mine*)li())->die();
00662 object_lists[MINE].remove(li);
00663 }
00664 }
00665 break;
00666 case 'S':
00667 {
00668 int id;
00669 double x,y,vx,vy;
00670 log_file >> id >> x >> y >> vx >> vy;
00671
00672 ListIterator<Shape> li;
00673 find_object_by_id( object_lists[SHOT], li, id );
00674 if( !li.ok() )
00675 {
00676
00677
00678 }
00679 else
00680 {
00681 ((Shot*)li())->die();
00682 object_lists[SHOT].remove(li);
00683 }
00684 }
00685 break;
00686
00687 case 'D':
00688 char object_type = '?';
00689 int object_id;
00690 log_file.get( object_type );
00691 log_file >> object_id;
00692 switch( object_type )
00693 {
00694 case 'R':
00695 {
00696 double pnts;
00697 int pos;
00698 log_file >> pnts >> pos;
00699
00700 }
00701 break;
00702 case 'C':
00703 {
00704 object_pos_info_t* info = find_object_in_log( COOKIE, object_id );
00705 if( info->end_time > info->start_time )
00706 object_lists[COOKIE].insert_last
00707 ( new Cookie( info->pos, 0.0, info->id ) );
00708 }
00709 break;
00710 case 'M':
00711 {
00712 object_pos_info_t* info = find_object_in_log( MINE, object_id );
00713 if( info->end_time > info->start_time )
00714 object_lists[MINE].insert_last
00715 ( new Mine( info->pos, 0.0, info->id ) );
00716 }
00717 break;
00718 case 'S':
00719 {
00720 object_pos_info_t* info = find_object_in_log( SHOT, object_id );
00721
00722 if( info->end_time > info->start_time )
00723 object_lists[SHOT].insert_last
00724 ( new Shot( info->pos + (current_replay_time - info->start_time)
00725 * info->vel, info->vel, 0, info->id ) );
00726 }
00727 break;
00728
00729 }
00730 break;
00731 }
00732 }
00733
00734 void
00735 ArenaReplay::set_filenames( String& replay_fname, String& message_fname,
00736 const String& statistics_fname,
00737 const String& option_fname )
00738 {
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781 }
00782
00783
00784 void
00785 ArenaReplay::change_speed( const bool forward, const bool fast )
00786 {
00787 if( fast_forward_factor < 0 )
00788 {
00789 fast_forward_factor = 1.0;
00790 step_forward( 0, true );
00791 }
00792
00793 if( !fast || log_from_stdin )
00794 {
00795 fast_forward_factor = 1.0;
00796 }
00797 else if( forward )
00798 {
00799 fast_forward_factor = the_opts.get_d( OPTION_FAST_FORWARD_FACTOR );
00800 }
00801 else
00802 {
00803 fast_forward_factor = -the_opts.get_d( OPTION_FAST_FORWARD_FACTOR );
00804 step_forward( 0, true );
00805 }
00806 }
00807
00808
00809
00810 void
00811 ArenaReplay::change_game( const int inc_game, const int inc_seq )
00812 {
00813 int temp_game = game_nr;
00814 int temp_seq = sequence_nr;
00815
00816 temp_game += inc_game;
00817 temp_seq += inc_seq;
00818
00819 if( inc_seq == 0 )
00820 {
00821 if( temp_game >= games_per_sequence + 1 )
00822 {
00823 temp_game -= games_per_sequence;
00824 temp_seq++;
00825 }
00826 else if( temp_game <= 0 )
00827 {
00828 temp_game += games_per_sequence;
00829 temp_seq--;
00830 }
00831 }
00832 else if( inc_seq < 0 )
00833 temp_game = games_per_sequence;
00834 else if( inc_seq > 0 )
00835 temp_game = 1;
00836
00837 if( temp_seq < 1 || temp_seq > sequences_in_tournament )
00838 return;
00839
00840
00841
00842
00843 log_file.seekg( game_position_in_log[temp_seq-1][temp_game-1] );
00844
00845
00846 }
00847
00848
00849
00850 bool
00851 ArenaReplay::step_forward( const int n_o_steps, const bool clear_time )
00852 {
00853 if( !log_from_stdin )
00854 {
00855 int index = find_streampos_for_time( current_replay_time );
00856
00857 index += n_o_steps;
00858
00859
00860
00861 if( index >= 0 && index <= max_time_infos && time_position_in_log[index].pos > 0 )
00862 {
00863 double last_replay_time = current_replay_time;
00864 current_replay_time = time_position_in_log[index].time;
00865 log_file.seekg( time_position_in_log[index].pos );
00866
00867 if( clear_time )
00868 {
00869 total_time = time_position_in_log[index].time + 0.00001;
00870 update_timer(0.0);
00871 parse_this_time_index();
00872 }
00873 if( n_o_steps != 0 )
00874 move_shots_no_check( current_replay_time - last_replay_time );
00875
00876 #ifndef NO_GRAPHICS
00877 if( !no_graphics && n_o_steps != 0 )
00878 {
00879 the_gui.get_arenawindow_p()->draw_moving_objects( true );
00880 the_gui.get_scorewindow_p()->set_window_title();
00881 if( !log_from_stdin )
00882 controlwindow_p->set_progress_time( current_replay_time );
00883 }
00884 #endif
00885
00886 return true;
00887 }
00888 else
00889 return false;
00890 }
00891 return true;
00892 }
00893
00894 void
00895 ArenaReplay::step_forward_or_backward( const bool forward )
00896 {
00897 double fff_tmp = fast_forward_factor;
00898 if( forward )
00899 step_forward( 1, true );
00900 else
00901 {
00902 fast_forward_factor = -1.0;
00903 step_forward( 0, true );
00904 step_forward( -1, true);
00905 fast_forward_factor = 1.0;
00906 step_forward( 0, true );
00907 }
00908
00909 fast_forward_factor = fff_tmp;
00910 }
00911
00912 void
00913 ArenaReplay::change_replay_time( const double time )
00914 {
00915 if( !log_from_stdin && abs(time - current_replay_time) > 0.001 )
00916 {
00917 int index = find_streampos_for_time( time );
00918
00919 index -= 1;
00920
00921
00922
00923 if( index >= 0 && index <= max_time_infos && time_position_in_log[index].pos > 0 )
00924 {
00925 current_replay_time = time_position_in_log[index].time;
00926 total_time = time_position_in_log[index].time + 0.00001;
00927 update_timer(0.0);
00928 log_file.seekg( time_position_in_log[index].pos );
00929 recreate_lists();
00930 }
00931 }
00932 }
00933
00934
00935
00936 void
00937 ArenaReplay::recreate_lists()
00938 {
00939
00940 {
00941 ListIterator<Shape> li;
00942 for( object_lists[ROBOT].first(li); li.ok(); li++ )
00943 {
00944 Robot* robotp = (Robot*) li();
00945 int id = robotp->get_id();
00946 object_pos_info_t* info;
00947 if( NULL != (info = find_object_in_log( ROBOT,id ) ) )
00948 {
00949 if( info->end_time < current_replay_time && robotp->is_alive() )
00950 {
00951 robotp->die();
00952 robotp->change_energy( -robotp->get_energy() );
00953 }
00954 else if( info->end_time > current_replay_time && !(robotp->is_alive()) )
00955 {
00956 robotp->live();
00957 }
00958 }
00959 else
00960 Error(false, "Robot in object_list is not in object_positions_in_log",
00961 "ArenaReplay::recreate_lists");
00962 }
00963 }
00964
00965
00966
00967 {
00968 for( int type = SHOT; type <= MINE; (type == SHOT ? type+=2 : type++) )
00969 {
00970 ListIterator<Shape> li;
00971 for( object_lists[type].first(li); li.ok(); li++ )
00972 switch( type )
00973 {
00974 case SHOT:
00975 ((Shot*)li())->die();
00976 object_lists[SHOT].remove(li);
00977 break;
00978 case COOKIE:
00979 ((Cookie*)li())->die();
00980 object_lists[COOKIE].remove(li);
00981 break;
00982 case MINE:
00983 ((Mine*)li())->die();
00984 object_lists[MINE].remove(li);
00985 break;
00986 }
00987 }
00988
00989 ListIterator<object_pos_info_t> li;
00990 for( object_positions_in_log.first(li); li.ok(); li++ )
00991 {
00992 object_pos_info_t* info = li();
00993 if( current_replay_time > info->start_time &&
00994 current_replay_time < info->end_time )
00995 {
00996 switch( info->obj )
00997 {
00998 case SHOT:
00999 object_lists[SHOT].insert_last
01000 ( new Shot( info->pos + (current_replay_time - info->start_time)
01001 * info->vel, info->vel, 0, info->id ) );
01002 break;
01003 case COOKIE:
01004 object_lists[COOKIE].insert_last
01005 ( new Cookie( info->pos, 0.0, info->id ) );
01006 break;
01007 case MINE:
01008 object_lists[MINE].insert_last
01009 ( new Mine( info->pos, 0.0, info->id ) );
01010 break;
01011 case ROBOT:
01012 break;
01013 default:
01014 Error(true,
01015 "Variable 'type' has a forbidden value. Should never happen",
01016 "ArenaReplay::recreate_lists");
01017 }
01018 }
01019 }
01020 }
01021 }
01022
01023
01024
01025
01026
01027 char
01028 ArenaReplay::search_forward( const String& search_letters )
01029 {
01030 if( log_from_stdin )
01031 return '?';
01032
01033 char letter;
01034 char buffer[400];
01035
01036
01037 while( !log_file.eof() )
01038 {
01039 log_file.clear();
01040
01041 log_file >> letter;
01042 if( search_letters.find( letter ) != -1 )
01043 {
01044 return letter;
01045 }
01046
01047 log_file >> ws;
01048 log_file.get( buffer, 400, '\n' );
01049 }
01050
01051 return '?';
01052 }
01053
01054
01055
01056
01057 String
01058 ArenaReplay::search_forward( const List<String>& search_strings )
01059 {
01060 if( log_from_stdin ) return "";
01061
01062 bool found = false;
01063 char buffer[400];
01064 ListIterator<String> li;
01065 int i;
01066 int read_letters;
01067 char letter[16];
01068
01069 while( !log_file.eof() )
01070 {
01071 log_file.clear();
01072
01073 read_letters = 0;
01074 for( search_strings.first(li); li.ok() && !found; li++ )
01075 {
01076 found = true;
01077 for( i=0; i < li()->get_length() && found; i++ )
01078 {
01079 if( read_letters < i+1 )
01080 {
01081 log_file >> letter[read_letters];
01082 read_letters++;
01083 }
01084 if( (*li())[i] != letter[i] ) found = false;
01085 }
01086
01087 if( found ) return *li();
01088 }
01089
01090 log_file.get( buffer, 400, '\n' );
01091 }
01092
01093 return "";
01094 }
01095
01096
01097 String
01098 ArenaReplay::search_backwards( const String& search_letters )
01099 {
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122 return "";
01123 }
01124
01125 void
01126 ArenaReplay::beginning_of_prev_line()
01127 {
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142 }
01143
01144 void
01145 ArenaReplay::beginning_of_current_line()
01146 {
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156 }
01157
01158 void
01159 ArenaReplay::make_statistics_from_file()
01160 {
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250 }
01251
01252 void
01253 ArenaReplay::get_time_positions_in_game()
01254 {
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408 }
01409
01410
01411
01412 int
01413 ArenaReplay::find_streampos_for_time(const float cur_time)
01414 {
01415
01416 for(int i=1; i<max_time_infos && time_position_in_log[i].pos > -1; i++)
01417 if( cur_time < time_position_in_log[i].time )
01418 return i-1;
01419
01420 Error(false, "Time not found", "ArenaReplay::find_streampos_for_time");
01421
01422 return -1;
01423 }
01424
01425 double
01426 ArenaReplay::get_length_of_current_game()
01427 {
01428 if( time_position_in_log != NULL )
01429 if( last_time_info != 0 )
01430 {
01431
01432 return time_position_in_log[last_time_info].time;
01433 }
01434
01435
01436 return the_opts.get_d( OPTION_TIMEOUT ) + 1.0;
01437 }
01438
01439
01440 ArenaReplay::object_pos_info_t*
01441 ArenaReplay::find_object_in_log( object_type obj, int id )
01442 {
01443 ListIterator<object_pos_info_t> li;
01444 for( object_positions_in_log.first(li); li.ok(); li++ )
01445 {
01446 if( obj == li()->obj && id == li()->id )
01447 return li();
01448 }
01449
01450 return NULL;
01451 }