00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #include <math.h>
00028 #include <signal.h>
00029 #include <unistd.h>
00030 #include <stdlib.h>
00031 #include <iostream>
00032 #include <iomanip>
00033 #include <stdarg.h>
00034
00035 #if HAVE_DIRENT_H
00036 # include <dirent.h>
00037 # define NAMLEN(dirent) strlen((dirent)->d_name)
00038 #else
00039 # define dirent direct
00040 # define NAMLEN(dirent) (dirent)->d_namlen
00041 # if HAVE_SYS_NDIR_H
00042 # include <sys/ndir.h>
00043 # endif
00044 # if HAVE_SYS_DIR_H
00045 # include <sys/dir.h>
00046 # endif
00047 # if HAVE_NDIR_H
00048 # include <ndir.h>
00049 # endif
00050 #endif
00051
00052
00053 #include "ArenaBase.h"
00054 #include "ArenaController.h"
00055
00056
00057 #include "IntlDefs.h"
00058 #include "Extras.h"
00059 #include "Various.h"
00060 #include "String.h"
00061 #include "Shot.h"
00062 #include "Options.h"
00063 #include "Wall.h"
00064 #include "Robot.h"
00065
00066 #ifndef NO_GRAPHICS
00067 # include "ControlWindow.h"
00068 # include "MessageWindow.h"
00069 extern class ControlWindow* controlwindow_p;
00070 #endif
00071
00072 ArenaBase::ArenaBase()
00073 {
00074 state = NOT_STARTED;
00075 game_mode = NORMAL_MODE;
00076
00077 sequence_nr = 0;
00078 sequences_in_tournament = 0;
00079 game_nr = 0;
00080 games_per_sequence = 0;
00081
00082 halt_next = false;
00083 pause_after_next_game = false;
00084
00085 reset_timer();
00086
00087 object_lists[ROBOT].set_deletion_responsibility(false);
00088 all_robots_in_sequence.set_deletion_responsibility(false);
00089
00090 debug_level = 0;
00091 }
00092
00093 ArenaBase::~ArenaBase()
00094 {
00095
00096 state = EXITING;
00097 sleep(1);
00098
00099 delete_lists(true, true, true, true);
00100 }
00101
00102 void
00103 ArenaBase::set_state( const state_t st )
00104 {
00105 state = st;
00106
00107 #ifndef NO_GRAPHICS
00108 if( !no_graphics )
00109 {
00110 String infotext;
00111 switch( state )
00112 {
00113 case NO_STATE:
00114 case NOT_STARTED:
00115 infotext = "RealTimeBattle";
00116 break;
00117 case STARTING_ROBOTS:
00118 infotext = "RTB " + (String)_("*Starting robots*");
00119 break;
00120 case SHUTTING_DOWN_ROBOTS:
00121 infotext = "RTB " + (String)_("*Shutting down robots*");
00122 break;
00123 case BEFORE_GAME_START:
00124 case GAME_IN_PROGRESS:
00125 infotext = "RealTimeBattle " + (String)_("*Running*");
00126 if( pause_after_next_game )
00127 infotext = "RTB " + (String)_("*Pausing after game*");
00128 break;
00129 case PAUSING_BETWEEN_GAMES:
00130 case PAUSED:
00131 infotext = "RealTimeBattle " + (String)_("*Paused*");
00132 break;
00133 case EXITING:
00134 infotext = "RealTimeBattle " + (String)_("*Exiting*");
00135 break;
00136 case FINISHED:
00137 infotext = "RealTimeBattle " + (String)_("*Finished*");
00138 break;
00139
00140 default:
00141 Error(true, "Unknown state", "ArenaBase::set_state");
00142 }
00143
00144 controlwindow_p->set_window_title( infotext );
00145 }
00146 #endif
00147 }
00148
00149 void
00150 ArenaBase::interrupt_tournament()
00151 {
00152 if( state == GAME_IN_PROGRESS || state == PAUSED ||
00153 state == PAUSING_BETWEEN_GAMES )
00154 {
00155 the_arena_controller.auto_start_and_end = false;
00156 #ifndef NO_GRAPHICS
00157 if( !no_graphics )
00158 {
00159 controlwindow_p->remove_replay_widgets();
00160 the_gui.close_scorewindow();
00161 the_gui.close_arenawindow();
00162 the_gui.close_messagewindow();
00163 }
00164 #endif
00165
00166 delete_lists(true, true, false, true);
00167
00168 set_state( FINISHED );
00169 }
00170 }
00171
00172
00173 void
00174 ArenaBase::save_statistics_to_file(String filename)
00175 {
00176
00177
00178 ofstream file(filename.chars());
00179
00180 stat_t* statp;
00181 Robot* robotp;
00182
00183 ListIterator<Robot> li;
00184 ListIterator<stat_t> stat_li;
00185 for(all_robots_in_tournament.first(li); li.ok() ; li++ )
00186 {
00187 robotp = li();
00188 file << robotp->get_robot_name() << ": " << endl;
00189 for(robotp->get_statistics()->first(stat_li); stat_li.ok(); stat_li++)
00190 {
00191 statp = stat_li();
00192 file << "Seq: " << statp->sequence_nr
00193 << " Game: " << statp->game_nr
00194 << " Pos: " << statp->position
00195 << " Points: " << statp->points
00196 << " Time Survived: " << statp->time_survived
00197 << " Total Points: " << statp->total_points << endl;
00198 }
00199 }
00200
00201
00202 }
00203
00204 void
00205 ArenaBase::print_message( const String& messager,
00206 const String& text )
00207 {
00208 if( use_message_file )
00209 message_file << messager << ": " << text << endl;
00210 #ifndef NO_GRAPHICS
00211 else if( !no_graphics && the_gui.is_messagewindow_up() )
00212 the_gui.get_messagewindow_p()->add_message( messager, text );
00213 #endif
00214 }
00215
00216 void
00217 ArenaBase::parse_arena_line(ifstream& file, double& scale, int& succession, double& angle_factor)
00218 {
00219 char text[20];
00220 double radius, radius2, bounce_c, hardn, thickness;
00221 int vertices;
00222
00223 Vector2D vec1, vec2, vec0, center;
00224 WallLine* wall_linep;
00225 WallCircle* wall_circlep;
00226 WallInnerCircle* wall_inner_circlep;
00227 WallArc* wall_arcp;
00228
00229
00230 file >> ws;
00231 file.get(text, 20, ' ');
00232 if( strcmp(text, "scale" ) == 0 )
00233 {
00234 if( succession != 1 ) Error(true, "Error in arenafile: 'scale' not first",
00235 "ArenaBase::parse_arena_line");
00236 succession = 2;
00237 double scl;
00238 file >> scl;
00239 scale *= scl;
00240 }
00241 else if( strcmp(text, "angle_unit" ) == 0 )
00242 {
00243 char unit[20];
00244 file >> ws;
00245 file.get(unit, 20, '\n');
00246 if( strcmp(unit, "radians" ) == 0)
00247 angle_factor = 1.0;
00248 else if( strcmp(unit, "degrees" ) == 0 )
00249 angle_factor = M_PI / 180.0;
00250 else
00251 Error(true, "Error in arenafile: Unknown angle unit: " + String(unit),
00252 "ArenaBase::parse_arena_line");
00253 }
00254 else if( strcmp(text, "boundary" ) == 0 )
00255 {
00256 if( succession > 2 )
00257 Error(true, "Error in arenafile: 'boundary' after wallpieces or duplicate",
00258 "ArenaBase::parse_arena_line");
00259 succession = 3;
00260 double b1, b2;
00261 file >> b1;
00262 file >> b2;
00263 boundary[0] = Vector2D(scale*b1, scale*b2);
00264 file >> b1;
00265 file >> b2;
00266 boundary[1] = Vector2D(scale*b1, scale*b2);
00267 if( boundary[1][0] - boundary[0][0] <= 0 ||
00268 boundary[1][1] - boundary[0][1] <= 0 )
00269 Error(true, "Error in arenafile: 'boundary' negative",
00270 "ArenaBase::parse_arena_line");
00271 }
00272 else if( strcmp(text, "exclusion_point" ) == 0 )
00273 {
00274 if( succession < 3 )
00275 Error(true, "Error in arenafile: 'boundary' after wallpieces or duplicate",
00276 "ArenaBase::parse_arena_line");
00277 file >> vec1;
00278 exclusion_points.insert_last(new Vector2D(scale*vec1));
00279 }
00280 else if( strcmp(text, "inner_circle" ) == 0 )
00281 {
00282 if( succession < 3 )
00283 Error(true, "Error in arenafile: 'inner_circle' before boundary",
00284 "ArenaBase::parse_arena_line");
00285 succession = 4;
00286 file >> bounce_c;
00287 file >> hardn;
00288 file >> vec1;
00289 file >> radius;
00290
00291 wall_inner_circlep = new WallInnerCircle(scale*vec1, scale*radius, bounce_c, hardn);
00292 object_lists[WALL].insert_first( wall_inner_circlep );
00293 }
00294 else if( strcmp(text, "circle" ) == 0 )
00295 {
00296 if( succession < 3 )
00297 Error(true, "Error in arenafile: 'circle' before 'boundary'",
00298 "ArenaBase::parse_arena_line");
00299 succession = 4;
00300 file >> bounce_c;
00301 file >> hardn;
00302 file >> vec1;
00303 file >> radius;
00304 wall_circlep = new WallCircle(scale*vec1, scale*radius, bounce_c, hardn);
00305 object_lists[WALL].insert_last(wall_circlep);
00306 }
00307 else if( strcmp(text, "arc" ) == 0 )
00308 {
00309 if( succession < 3 )
00310 Error(true, "Error in arenafile: 'arc' before 'boundary'",
00311 "ArenaBase::parse_arena_line");
00312 succession = 4;
00313 double angle1, angle2;
00314 file >> bounce_c;
00315 file >> hardn;
00316 file >> center;
00317 file >> radius;
00318 file >> radius2;
00319 file >> angle1;
00320 file >> angle2;
00321
00322 wall_arcp = new WallArc(scale*center, scale*radius, scale*radius2,
00323 angle1 * angle_factor, angle2 * angle_factor,
00324 bounce_c, hardn);
00325 object_lists[WALL].insert_last(wall_arcp);
00326 }
00327 else if( strcmp(text, "line" ) == 0 )
00328 {
00329 if( succession < 3 ) Error(true, "Error in arenafile: 'line' before 'boundary'",
00330 "ArenaBase::parse_arena_line");
00331 succession = 4;
00332 file >> bounce_c;
00333 file >> hardn;
00334 file >> thickness;
00335 thickness *= 0.5;
00336 file >> vec1;
00337 file >> vec2;
00338
00339
00340 if( length(vec2-vec1) == 0.0 )
00341 Error(true, "Error in arenafile: Zero length line",
00342 "ArenaBase::parse_arena_line");
00343
00344 wall_linep = new WallLine(scale*vec1, unit(vec2-vec1), scale*length(vec2-vec1),
00345 scale*thickness, bounce_c , hardn);
00346 object_lists[WALL].insert_last( wall_linep );
00347 }
00348 else if( strcmp(text, "polygon" ) == 0 )
00349 {
00350 if( succession < 3 )
00351 Error(true, "Error in arenafile: 'polygon' before 'boundary'",
00352 "ArenaBase::parse_arena_line");
00353 succession = 4;
00354 file >> bounce_c;
00355 file >> hardn;
00356 file >> thickness;
00357 thickness *= 0.5;
00358 file >> vertices;
00359 file >> vec1;
00360 wall_circlep = new WallCircle(scale*vec1, scale*thickness, bounce_c, hardn);
00361 object_lists[WALL].insert_last( wall_circlep );
00362
00363 for(int i=1; i<vertices; i++)
00364 {
00365 vec2 = vec1;
00366 file >> vec1;
00367
00368 if( length(vec2-vec1) == 0.0 )
00369 Error(true, "Error in arenafile: Zero length line in polygon",
00370 "ArenaBase::parse_arena_line");
00371
00372 wall_linep = new WallLine(scale*vec2, unit(vec1-vec2),
00373 scale*length(vec1-vec2),
00374 scale*thickness, bounce_c , hardn);
00375 object_lists[WALL].insert_last( wall_linep );
00376 wall_circlep = new WallCircle(scale*vec1, scale*thickness, bounce_c, hardn);
00377 object_lists[WALL].insert_last( wall_circlep );
00378 }
00379 }
00380 else if( strcmp(text, "closed_polygon" ) == 0 )
00381 {
00382 if( succession < 3 )
00383 Error(true, "Error in arenafile: 'closed_polygon' before 'boundary'",
00384 "ArenaBase::parse_arena_line");
00385 succession = 4;
00386 file >> bounce_c;
00387 file >> hardn;
00388 file >> thickness;
00389 thickness *= 0.5;
00390 file >> vertices;
00391 file >> vec1;
00392 wall_circlep = new WallCircle(scale*vec1, scale*thickness, bounce_c, hardn);
00393 object_lists[WALL].insert_last( wall_circlep );
00394 vec0 = vec1;
00395
00396 for(int i=1; i<vertices; i++)
00397 {
00398 vec2 = vec1;
00399 file >> vec1;
00400
00401 if( length(vec2-vec1) == 0.0 )
00402 Error(true, "Error in arenafile: Line in closed_polygon of zero length",
00403 "ArenaBase::parse_arena_line");
00404
00405 wall_linep = new WallLine(scale*vec2, unit(vec1-vec2),
00406 scale*length(vec1-vec2),
00407 scale*thickness, bounce_c , hardn);
00408 object_lists[WALL].insert_last( wall_linep );
00409 wall_circlep = new WallCircle(scale*vec1, scale*thickness, bounce_c, hardn);
00410 object_lists[WALL].insert_last( wall_circlep );
00411 }
00412
00413 if( length(vec0-vec1) == 0.0 )
00414 Error(true, "Error in arenafile: Last line in closed_polygon of zero length",
00415 "ArenaBase::parse_arena_line");
00416
00417 wall_linep = new WallLine(scale*vec1, unit(vec0-vec1), scale*length(vec0-vec1),
00418 scale*thickness, bounce_c , hardn);
00419 object_lists[WALL].insert_last( wall_linep );
00420 }
00421
00422 else if( strcmp(text, "poly_curve" ) == 0 )
00423 {
00424 if( succession < 3 )
00425 Error(true, "Error in arenafile: 'closed_polygon' before 'boundary'",
00426 "ArenaBase::parse_arena_line");
00427 succession = 4;
00428 file >> bounce_c;
00429 file >> hardn;
00430 file >> thickness;
00431 thickness *= 0.5;
00432
00433 Vector2D current_pos, direction;
00434 file >> current_pos;
00435 wall_circlep = new WallCircle(scale*current_pos, scale*thickness, bounce_c, hardn);
00436 object_lists[WALL].insert_last( wall_circlep );
00437
00438 file >> direction;
00439
00440 direction.normalize();
00441
00442 if( lengthsqr(direction) < 0.01 )
00443 Error(true, "Error in arenafile: directions must not be zero",
00444 "ArenaBase::parse_arena_line");
00445
00446 vec0 = current_pos;
00447
00448 char c;
00449 double len, angle, start_angle, end_angle, tmp;
00450 bool finish = false;
00451 do
00452 {
00453 file >> c;
00454
00455 switch( c )
00456 {
00457 case 'L':
00458 file >> len;
00459 if( len <= 0.0 )
00460 Error(true, "Error in arenafile: Line in poly_curve must be positive",
00461 "ArenaBase::parse_arena_line");
00462
00463 wall_linep = new WallLine(scale*current_pos, direction,
00464 scale*len,
00465 scale*thickness, bounce_c , hardn);
00466 object_lists[WALL].insert_last( wall_linep );
00467
00468 current_pos += len * direction;
00469 wall_circlep = new WallCircle(scale*current_pos, scale*thickness,
00470 bounce_c, hardn);
00471 object_lists[WALL].insert_last( wall_circlep );
00472
00473 break;
00474 case 'A':
00475 file >> angle;
00476 file >> radius;
00477
00478 angle *= angle_factor;
00479 center = current_pos - rotate90( direction ) * radius * sgn( angle );
00480 start_angle = vec2angle( current_pos - center );
00481 current_pos = center + radius * angle2vec( start_angle - angle );
00482 end_angle = vec2angle( current_pos - center );
00483
00484 if( angle > 0.0 )
00485 { tmp = start_angle; start_angle = end_angle; end_angle = tmp; }
00486
00487 wall_arcp = new WallArc(scale*center, scale*(radius - thickness),
00488 scale*(radius + thickness),
00489 start_angle, end_angle,
00490 bounce_c, hardn);
00491
00492 object_lists[WALL].insert_last(wall_arcp);
00493
00494
00495 direction = rotate(direction, -angle);
00496
00497 wall_circlep = new WallCircle(scale*current_pos, scale*thickness,
00498 bounce_c, hardn);
00499 object_lists[WALL].insert_last( wall_circlep );
00500 break;
00501
00502 case 'T':
00503 file >> angle;
00504 direction = rotate( direction, -angle*M_PI/180.0 );
00505
00506 break;
00507
00508 case 'C':
00509 if( length(vec0 - current_pos ) == 0.0 )
00510 Error(true, "Error in arenafile: Last line in poly_curve of zero length",
00511 "ArenaBase::parse_arena_line");
00512
00513 wall_linep = new WallLine(scale*current_pos, unit(vec0-current_pos),
00514 scale*length(vec0-current_pos),
00515 scale*thickness, bounce_c , hardn);
00516 object_lists[WALL].insert_last( wall_linep );
00517
00518 finish = true;
00519 break;
00520 case 'Q':
00521 finish = true;
00522 break;
00523
00524 default:
00525 Error(true, "Incorrect arenafile, unknown command in poly_curve: "
00526 + (String)c, "ArenaBase::parse_arena_line");
00527 break;
00528 }
00529 }
00530 while( !finish );
00531 }
00532
00533 else if( text[0] != '\0' )
00534 Error(true, "Incorrect arenafile, unknown keyword: " + (String)text,
00535 "ArenaBase::parse_arena_line");
00536
00537 }
00538
00539
00540
00541 double
00542 ArenaBase::get_shortest_distance(const Vector2D& pos, const Vector2D& dir,
00543 const double size, object_type& closest_shape,
00544 Shape*& colliding_object, const Robot* the_robot)
00545 {
00546 double dist = infinity;
00547 double d;
00548 closest_shape = NOOBJECT;
00549
00550 ListIterator<Shape> li;
00551
00552 for( int obj_type = ROBOT; obj_type < LAST_OBJECT_TYPE; obj_type++ )
00553 {
00554 for( object_lists[obj_type].first(li); li.ok(); li++)
00555 {
00556 if( obj_type != ROBOT || (Robot*)(li()) != the_robot )
00557 {
00558 d = li()->get_distance(pos, dir, size);
00559 if( d < dist)
00560 {
00561 closest_shape = (object_type)obj_type;
00562 colliding_object = li();
00563 dist = d;
00564 }
00565 }
00566 }
00567 }
00568
00569 return dist;
00570 }
00571
00572 bool
00573 ArenaBase::space_available(const Vector2D& pos, const double margin)
00574 {
00575 ListIterator<Shape> li;
00576
00577 for( int obj_type = ROBOT; obj_type < LAST_OBJECT_TYPE; obj_type++ )
00578 {
00579 for( object_lists[obj_type].first(li); li.ok(); li++)
00580 if( li()->within_distance(pos, margin) ) return false;
00581 }
00582
00583
00584
00585 Vector2D vec;
00586 double dist;
00587 object_type obj_t;
00588 Shape* shapep;
00589
00590 ListIterator<Vector2D> li_ex;
00591
00592 for( exclusion_points.first(li_ex); li_ex.ok(); li_ex++)
00593 {
00594 vec = *(li_ex());
00595 dist = length(vec - pos);
00596 if( dist <= margin ||
00597 dist <= get_shortest_distance(pos, unit(vec - pos), 0.0,
00598 obj_t, shapep, (Robot*)NULL) )
00599 return false;
00600 }
00601
00602 return true;
00603 }
00604
00605
00606 double
00607 ArenaBase::get_shooting_penalty()
00608 {
00609 return min( the_opts.get_d(OPTION_SHOOTING_PENALTY), 0.5 / (double)robots_left );
00610 }
00611
00612
00613 void
00614 ArenaBase::update_timer(const double factor)
00615 {
00616 double last_timer = current_timer;
00617
00618 current_timer = timer.get();
00619 double timescale = 1.0;
00620 if( state == GAME_IN_PROGRESS ) timescale = the_opts.get_d(OPTION_TIMESCALE);
00621 timestep = min( (current_timer - last_timer) * timescale,
00622 the_opts.get_d(OPTION_MAX_TIMESTEP) );
00623 total_time += timestep*factor;
00624
00625 total_time = max(total_time, 0.0);
00626 }
00627
00628 void
00629 ArenaBase::reset_timer()
00630 {
00631 total_time = 0.0;
00632 current_timer = 0.0;
00633 timer.reset();
00634 update_timer();
00635 }
00636
00637
00638 void
00639 ArenaBase::move_shots(const double time_period)
00640 {
00641 Shot* shotp;
00642
00643 ListIterator<Shape> li;
00644
00645 for( object_lists[SHOT].first(li); li.ok(); li++)
00646 {
00647 shotp = (Shot*)li();
00648
00649 if( shotp->is_alive() ) shotp->move(time_period);
00650
00651 if( !shotp->is_alive() ) object_lists[SHOT].remove(li);
00652 }
00653 }
00654
00655 void
00656 ArenaBase::move_shots_no_check(const double time_period)
00657 {
00658 ListIterator<Shape> li;
00659
00660 for( object_lists[SHOT].first(li); li.ok(); li++)
00661 {
00662 ((Shot*)li())->move_no_check(time_period);
00663 }
00664 }
00665
00666 void
00667 ArenaBase::set_game_mode( const enum game_mode_t gm )
00668 {
00669 game_mode = gm;
00670 if( game_mode == DEBUG_MODE )
00671 {
00672 if( debug_level == 0 )
00673 set_debug_level( the_arena_controller.debug_level );
00674 }
00675 else
00676 {
00677 debug_level = 0;
00678 }
00679 }
00680
00681 int
00682 ArenaBase::set_debug_level( const int new_level)
00683 {
00684 if( new_level > max_debug_level || new_level < 0 || new_level == debug_level )
00685 return debug_level;
00686
00687 debug_level = new_level;
00688
00689 return debug_level;
00690 }
00691
00692 void
00693 ArenaBase::pause_game_toggle()
00694 {
00695 if( game_mode != COMPETITION_MODE )
00696 {
00697 if( state == GAME_IN_PROGRESS )
00698 set_state( PAUSED );
00699 else if( state == PAUSED )
00700 set_state( GAME_IN_PROGRESS );
00701
00702 halt_next = false;
00703 }
00704 else
00705 {
00706 pause_after_next_game = !pause_after_next_game;
00707 set_state( state );
00708 }
00709 }
00710
00711 void
00712 ArenaBase::step_paused_game()
00713 {
00714 if( game_mode == DEBUG_MODE && state == PAUSED )
00715 {
00716 halt_next = true;
00717 set_state( GAME_IN_PROGRESS );
00718 }
00719 }
00720
00721 void
00722 ArenaBase::delete_lists(const bool kill_robots, const bool del_seq_list,
00723 const bool del_tourn_list, const bool del_arena_filename_list,
00724 const bool del_robot_obj_list)
00725 {
00726
00727
00728 for( int obj_type = ROBOT; obj_type < LAST_OBJECT_TYPE; obj_type++ )
00729 if( obj_type != ROBOT || del_robot_obj_list )
00730 object_lists[obj_type].delete_list();
00731
00732 exclusion_points.delete_list();
00733
00734 if( del_seq_list )
00735 {
00736 if( kill_robots )
00737 {
00738 ListIterator<Robot> li;
00739 for( all_robots_in_sequence.first(li); li.ok(); li++)
00740 li()->kill_process_forcefully();
00741 }
00742 all_robots_in_sequence.delete_list();
00743 }
00744
00745 if( del_tourn_list ) all_robots_in_tournament.delete_list();
00746 if( del_arena_filename_list ) arena_filenames.delete_list();
00747 }
00748
00749 bool
00750 ArenaBase::find_object_by_id( const List<Shape>& obj_list,
00751 ListIterator<Shape>& li,
00752 const int obj_id )
00753 {
00754 for( obj_list.first(li); li.ok(); li++)
00755 {
00756 if( li()->get_id() == obj_id )
00757 return true;
00758 }
00759 return false;
00760 }
00761
00762 bool
00763 ArenaBase::find_object_by_id( const List<Robot>& obj_list,
00764 ListIterator<Robot>& li,
00765 const int obj_id )
00766 {
00767 for( obj_list.first(li); li.ok(); li++)
00768 {
00769 if( li()->get_id() == obj_id )
00770 return true;
00771 }
00772 return false;
00773 }