Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

Player.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright (c) 2000-2003, Jelle Kok, University of Amsterdam
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without
00006 modification, are permitted provided that the following conditions are met:
00007 
00008 1. Redistributions of source code must retain the above copyright notice, this
00009 list of conditions and the following disclaimer.
00010 
00011 2. Redistributions in binary form must reproduce the above copyright notice,
00012 this list of conditions and the following disclaimer in the documentation
00013 and/or other materials provided with the distribution.
00014 
00015 3. Neither the name of the University of Amsterdam nor the names of its
00016 contributors may be used to endorse or promote products derived from this
00017 software without specific prior written permission.
00018 
00019 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00020 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
00023 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00024 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00025 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00026 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00027 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00028 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029 */
00030 
00049 #include "Player.h"
00050 #include "Parse.h"
00051 #ifndef WIN32
00052   #include <sys/poll.h> // needed for 'poll'
00053 #endif
00054 
00055 extern Logger LogDraw;
00056 
00066 Player::Player( ActHandler* act, WorldModel *wm, ServerSettings *ss,
00067       PlayerSettings *ps,
00068       Formations *fs, char* strTeamName, double dVersion, int iReconnect )
00069 
00070 {
00071   char str[MAX_MSG];
00072 
00073   ACT           = act;
00074   WM            = wm;
00075   SS            = ss;
00076   PS            = ps;
00077   formations    = fs;
00078   bContLoop     = true;
00079   m_iPenaltyNr  = -1;
00080   WM->setTeamName( strTeamName );
00081   m_timeLastSay = -5;
00082   m_objMarkOpp  = OBJECT_ILLEGAL;
00083   m_actionPrev  = ACT_ILLEGAL;
00084 
00085   // wait longer as role number increases, to make sure players appear at the
00086   // field in the correct order
00087 #ifdef WIN32
00088   Sleep( formations->getPlayerInFormation()*500 );
00089 #else
00090   poll( 0, 0, formations->getPlayerInFormation()*500 );
00091 #endif
00092 
00093   // create initialisation string
00094   if( iReconnect != -1 )
00095     sprintf( str, "(reconnect %s %d)", strTeamName, iReconnect );
00096   else if( formations->getPlayerType() == PT_GOALKEEPER )
00097     sprintf( str, "(init %s (version %f) (goalie))", strTeamName, dVersion );
00098   else
00099     sprintf( str, "(init %s (version %f))", strTeamName, dVersion );
00100   ACT->sendMessage( str );
00101   
00102 }
00103 
00108 void Player::mainLoop( )
00109 {
00110   char str[MAX_MSG];
00111   Timing timer;
00112 
00113   // wait for new information from the server
00114   // cannot say bContLoop=WM->wait... since bContLoop can be changed elsewhere
00115   if(  WM->waitForNewInformation() == false )
00116     bContLoop =  false;
00117 
00118   // and set the clang version
00119   sprintf( str, "(clang (ver 8 8))" );
00120   ACT->sendMessage( str );
00121 
00122   while( bContLoop )                                 // as long as server alive
00123   {
00124     Log.logWithTime( 3, "  start update_all" );
00125 //    Log.setHeader( WM->getCurrentCycle(), WM->getPlayerNumber() );
00126     Log.setHeader( WM->getCurrentCycle() );
00127     LogDraw.setHeader( WM->getCurrentCycle() );
00128 
00129     if( WM->updateAll( ) == true )
00130     {
00131       timer.restartTime();
00132       SoccerCommand soc;
00133       if( ( WM->isPenaltyUs( ) || WM->isPenaltyThem() ) )
00134         performPenalty();
00135       else if( WM->getPlayMode() == PM_FROZEN )
00136         ACT->putCommandInQueue( turnBodyToObject( OBJECT_BALL )  ); 
00137       else
00138       {
00139         switch( formations->getPlayerType( ) )        // determine right loop
00140         {
00141           case PT_GOALKEEPER:       soc = goalieMainLoop( );     break;
00142           case PT_DEFENDER_SWEEPER:
00143           case PT_DEFENDER_CENTRAL:
00144           case PT_DEFENDER_WING:    soc = defenderMainLoop( );   break;
00145           case PT_MIDFIELDER_CENTER:
00146           case PT_MIDFIELDER_WING:  soc = midfielderMainLoop( ); break;
00147           case PT_ATTACKER:
00148           case PT_ATTACKER_WING:    soc = attackerMainLoop( );   break;
00149           case PT_ILLEGAL:
00150           default: break;
00151         }
00152 
00153         if( shallISaySomething(soc) == true )           // shall I communicate
00154         {
00155           m_timeLastSay = WM->getCurrentTime();
00156           char strMsg[MAX_SAY_MSG];
00157           if( WM->getPlayerNumber() == 6 &&
00158               WM->getBallPos().getX() < - PENALTY_X + 4.0  )
00159             sayOppAttackerStatus( strMsg );
00160           else
00161             sayBallStatus( strMsg );
00162           if( strlen( strMsg ) != 0 )
00163             Log.log( 600, "send communication string: %s", strMsg );
00164           WM->setCommunicationString( strMsg );
00165         }
00166       }
00167       Log.logWithTime( 3, "  determined action; waiting for new info" );
00168       // directly after see message, will nog get better info, so send commands
00169       if( WM->getTimeLastSeeMessage() == WM->getCurrentTime() ||
00170           (SS->getSynchMode() == true && WM->getRecvThink() == true ))
00171       {
00172         Log.logWithTime( 3, "  send messages directly" );
00173         ACT->sendCommands( );
00174         Log.logWithTime( 3, "  sent messages directly" );
00175         if( SS->getSynchMode() == true  )
00176         {
00177           WM->processRecvThink( false );
00178           ACT->sendMessageDirect( "(done)" );
00179         }
00180       }
00181 
00182     }
00183     else
00184       Log.logWithTime( 3, "  HOLE no action determined; waiting for new info");
00185 
00186     if( WM->getCurrentCycle()%(SS->getHalfTime()*SS->getSimulatorStep()) != 0 )
00187     {
00188       if( LogDraw.isInLogLevel( 600 ) )
00189       {
00190         WM->logDrawInfo( 600 );
00191       }
00192 
00193       if( LogDraw.isInLogLevel( 601 ) )
00194         WM->logDrawBallInfo( 601 );
00195 
00196       if( LogDraw.isInLogLevel( 700 ) )
00197         WM->logCoordInfo( 700 );
00198     }
00199  
00200     Log.logWithTime( 604, "time for action: %f", timer.getElapsedTime()*1000 );
00201            
00202     // wait for new information from the server cannot say
00203     // bContLoop=WM->wait... since bContLoop can be changed elsewhere
00204     if(  WM->waitForNewInformation() == false )
00205         bContLoop =  false;
00206   }
00207 
00208   // shutdow, print hole and number of players seen statistics
00209   printf("Shutting down player %d\n", WM->getPlayerNumber() );
00210   printf("   Number of holes: %d (%f)\n", WM->iNrHoles,
00211                          ((double)WM->iNrHoles/WM->getCurrentCycle())*100 );
00212   printf("   Teammates seen: %d (%f)\n", WM->iNrTeammatesSeen,
00213                          ((double)WM->iNrTeammatesSeen/WM->getCurrentCycle()));
00214   printf("   Opponents seen: %d (%f)\n", WM->iNrOpponentsSeen,
00215                          ((double)WM->iNrOpponentsSeen/WM->getCurrentCycle()));
00216 
00217 }
00218 
00219 
00221 SoccerCommand Player::goalieMainLoop( )
00222 {
00223   return deMeer5_goalie();
00224 }
00225 
00227 SoccerCommand Player::defenderMainLoop( )
00228 {
00229   return deMeer5() ;
00230 }
00231 
00233 SoccerCommand Player::midfielderMainLoop( )
00234 {
00235   return deMeer5() ;
00236 }
00237 
00239 SoccerCommand Player::attackerMainLoop( )
00240 {
00241   return deMeer5() ;
00242 }
00243 
00248 VecPosition Player::getDeadBallPosition(  )
00249 {
00250   VecPosition pos, posBall = WM->getBallPos();
00251   VecPosition posAgent = WM->getAgentGlobalPosition();
00252   double dDist;
00253 
00254   // determine point to move to
00255   if( WM->isKickInUs()  )
00256     pos = posBall + VecPosition( -1.5, sign( posBall.getY() )*1.5 );
00257   else if( WM->isCornerKickUs( ) )
00258     pos = posBall + VecPosition( 1.5, sign( posBall.getY() ) * 1.5 );
00259   else if( WM->isFreeKickUs() || WM->isOffsideThem() || WM->isGoalKickUs() ||
00260            WM->isFreeKickFaultThem() || WM->isBackPassThem() )
00261     pos = posBall + VecPosition( -1.5, 0.0 );
00262   else
00263     return VecPosition( UnknownDoubleValue, UnknownDoubleValue );
00264 
00265   AngDeg      angBall = (posBall-posAgent).getDirection() ;
00266   ObjectT     obj = WM->getClosestInSetTo( OBJECT_SET_PLAYERS,
00267                                            WM->getAgentObjectType(), &dDist);
00268   VecPosition posPlayer = WM->getGlobalPosition( obj );
00269 
00270   // change point when heading towards other player or towards the ball
00271   if( fabs( angBall - (posPlayer-posAgent).getDirection() ) < 20 &&
00272       dDist < 6 )
00273     pos -= VecPosition( 5, 0 );
00274   if( fabs( angBall -  (pos-posAgent).getDirection()) < 20 )
00275   {
00276     angBall = VecPosition::normalizeAngle( angBall - 90 );
00277     pos = posBall + VecPosition( 1, angBall , POLAR );
00278   }
00279   return pos;
00280 }
00281 
00293 void Player::handleStdin( )
00294 {
00295   char buf[MAX_MSG];
00296 
00297   while( bContLoop )
00298   {
00299 #ifdef WIN32
00300     cin.getline( buf, MAX_MSG );
00301 #else
00302     fgets( buf, MAX_MSG, stdin ); // does unblock with signal !!!!!
00303 #endif
00304    printf( "after fgets: %s\n", buf );
00305    executeStringCommand( buf );
00306   }
00307 }
00308 
00314 void Player::showStringCommands( ostream& out )
00315 {
00316   out << "Basic commands:"                                << endl <<
00317          " a(ctions)"                                     << endl <<
00318          " c(atch) direction"                             << endl <<
00319          " cs(lientsettings"                              << endl <<
00320          " d(ash) power [ times ]"                        << endl <<
00321          " de(bug) nr_cycles"                             << endl <<
00322          " g(oto) x y"                                    << endl <<
00323          " h(elp)"                                        << endl <<
00324          " i(ntercept) x y"                               << endl <<
00325          " k(ick) power angle"                            << endl <<
00326          " ka x y endspeed "                              << endl <<
00327          " m(ove) x y"                                    << endl <<
00328          " n(eck) angle"                                  << endl <<
00329          " o(pponents in cone) width dist"                << endl <<
00330          " p(redict cycles to) x y"                       << endl <<
00331          " q(uit)"                                        << endl <<
00332          " s(ay) message"                                 << endl <<
00333          " ss(erversettings)"                             << endl <<
00334          " t(urn) angle"                                  << endl <<
00335          " v(iewmode) narrow | normal | wide low | high"  << endl <<
00336          " w(orldmodel)"                                  << endl;
00337 }
00338 
00343 bool Player::executeStringCommand( char *str)
00344 {
00345   SoccerCommand socCommand;
00346   int           i;
00347   double        x, y;
00348 
00349   switch( str[0] )
00350   {
00351     case 'a':                                 // actions
00352       WM->showQueuedCommands();
00353       break;
00354     case 'c':                                 // catch dir or cs
00355       if( strlen(str) > 1 && str[1] == 's' )
00356       {
00357         PS->show( cout, ":" );
00358         break;
00359       }
00360       socCommand.makeCommand( CMD_CATCH, Parse::parseFirstInt( &str ) );
00361       break;
00362     case 'd':                                 // dash
00363       socCommand.commandType = CMD_DASH;
00364       socCommand.dPower      = Parse::parseFirstDouble( &str );
00365       socCommand.iTimes      = Parse::parseFirstInt   ( &str );
00366       if( socCommand.iTimes == 0 ) socCommand.iTimes = 1;
00367       break;
00368     case 'h':                                // help
00369       showStringCommands( cout );
00370       return true;
00371     case 'k':                                // kick or ka (kick advanced)
00372       socCommand.commandType = CMD_KICK;
00373       if( str[1] == 'a' ) // advanced kick
00374       {
00375         double x = Parse::parseFirstDouble( &str );
00376         double y = Parse::parseFirstDouble( &str );
00377         double e = Parse::parseFirstDouble( &str );
00378         socCommand = kickTo( VecPosition( x, y), e );
00379       }
00380       else
00381       {
00382         socCommand.dPower = Parse::parseFirstDouble( &str );
00383         socCommand.dAngle = Parse::parseFirstDouble( &str );
00384       }
00385       break;
00386     case 'm':                               // move
00387       socCommand.commandType = CMD_MOVE;
00388       socCommand.dX          = Parse::parseFirstDouble( &str );
00389       socCommand.dY          = Parse::parseFirstDouble( &str );
00390       socCommand.dAngle      = Parse::parseFirstDouble( &str );
00391       break;
00392     case 'n':                              // turn_neck
00393       socCommand.commandType = CMD_TURNNECK;
00394       socCommand.dAngle      = Parse::parseFirstDouble( &str );
00395       break;
00396     case 'o':                              // count nr opp in cone
00397       x = Parse::parseFirstDouble( &str );
00398       y = Parse::parseFirstDouble( &str );
00399       i = WM->getNrInSetInCone( OBJECT_SET_OPPONENTS, x, 
00400                                 WM->getAgentGlobalPosition(),
00401                                 WM->getAgentGlobalPosition() + 
00402                                 VecPosition( y,
00403                                              WM->getAgentGlobalNeckAngle(), 
00404                                              POLAR ) );
00405       printf( "%d opponents\n", i );
00406       return true;
00407     case 'p':                              // predict cycles to point
00408       x = Parse::parseFirstDouble( &str );
00409       y = Parse::parseFirstDouble( &str );
00410       i = WM->predictNrCyclesToPoint( WM->getAgentObjectType(),
00411                                       VecPosition( x, y ) );
00412       printf( "%d cycles\n", i );
00413       return true;
00414     case 'q':                             // quit
00415       bContLoop = false;
00416       return true;
00417     case 's':                             // ss (serversettings) or say
00418       if( strlen(str) > 1 && str[1] == 's' )
00419       {
00420         SS->show( cout, ":" );
00421         break;
00422       }
00423       socCommand.commandType = CMD_SAY;
00424       Parse::gotoFirstOccurenceOf( ' ', &str );
00425       Parse::gotoFirstNonSpace( &str );
00426       strcpy( socCommand.str, str);
00427       break;
00428     case 't':                             // turn
00429       socCommand.commandType = CMD_TURN;
00430       socCommand.dAngle      = Parse::parseFirstDouble( &str );
00431       break;
00432     case 'v':                             // change_view
00433       socCommand.commandType = CMD_CHANGEVIEW;
00434       Parse::gotoFirstOccurenceOf(' ', &str );
00435       Parse::gotoFirstNonSpace( &str );
00436       socCommand.va          = SoccerTypes::getViewAngleFromStr( str );
00437       Parse::gotoFirstOccurenceOf(' ', &str );
00438       Parse::gotoFirstNonSpace( &str );
00439       socCommand.vq          = SoccerTypes::getViewQualityFromStr( str );
00440       break;
00441     case 'w':                            // worldmodel
00442       WM->show();
00443       return true;
00444     default:                             // default: send entered string
00445       ACT->sendMessage( str );
00446       return true;
00447   }
00448   if( socCommand.commandType != CMD_ILLEGAL ) // when socCommand is set
00449     ACT->putCommandInQueue( socCommand );     // send it.
00450 
00451   return true;
00452 }
00453 
00463 #ifdef WIN32
00464 DWORD WINAPI stdin_callback( LPVOID v )
00465 #else
00466 void* stdin_callback( void * v )
00467 #endif
00468 
00469 {
00470   Log.log( 1, "Starting to listen for user input" );
00471   Player* p = (Player*)v;
00472   p->handleStdin();
00473   return NULL;
00474 }
00475 
00476 /********************** SAY **************************************************/
00477 
00480 bool Player::shallISaySomething( SoccerCommand socPri )
00481 {
00482   bool        bReturn;
00483 
00484   bReturn  = ((WM->getCurrentTime() - m_timeLastSay) >= SS->getHearDecay());
00485   bReturn  &= amIAgentToSaySomething( socPri );
00486   bReturn  &= (WM->getCurrentCycle() > 0 );
00487 
00488   return bReturn;
00489 }
00490 
00494 bool Player::amIAgentToSaySomething( SoccerCommand socPri )
00495 {
00496   double  dDist;
00497   ObjectT obj;
00498 
00499   // get the closest teammate to the ball, if we are not him, we do not
00500   // communicate since he will
00501   obj = WM->getClosestInSetTo( OBJECT_SET_TEAMMATES,OBJECT_BALL,&dDist);
00502   if( dDist < SS->getVisibleDistance() &&
00503       obj != WM->getAgentObjectType() )
00504     return false;
00505 
00506   // in the defense, player 6 keeps track of the opponent attacker
00507   if( WM->getBallPos().getX() < - PENALTY_X + 4.0 &&
00508       WM->getConfidence( OBJECT_BALL ) > 0.96 &&
00509       WM->getPlayerNumber() == 6 &&
00510       WM->getCurrentCycle() % 3 == 0 ) // once very 3 cycles is enough
00511   {
00512     Log.log( 600, "player 6 is going to communicate attacker info" );
00513     return true;
00514   }
00515 
00516   VecPosition posBallPred;
00517   WM->predictBallInfoAfterCommand( socPri, &posBallPred );
00518   VecPosition posAgentPred = WM->predictAgentPosAfterCommand( socPri );
00519   // in all other cases inform teammates of ball when you have good information
00520   if( ( WM->getTimeChangeInformation(OBJECT_BALL) == WM->getCurrentTime() &&
00521           WM->getRelativeDistance( OBJECT_BALL ) < 20.0 &&
00522           WM->getTimeLastSeen( OBJECT_BALL ) == WM->getCurrentTime() )
00523         ||
00524       (
00525        WM->getRelativeDistance( OBJECT_BALL ) < SS->getVisibleDistance() &&
00526        WM->getTimeLastSeen( OBJECT_BALL ) == WM->getCurrentTime()  
00527        )
00528       ||
00529       ( // pass ball
00530        WM->getRelativeDistance( OBJECT_BALL ) < SS->getMaximalKickDist() &&
00531        posBallPred.getDistanceTo( posAgentPred ) > SS->getMaximalKickDist() 
00532        )
00533       )
00534     return true;
00535 
00536   return false;
00537 }
00538 
00541 void Player::sayOppAttackerStatus( char* strMsg )
00542 {
00543   char    strTmp[MAX_SAY_MSG];
00544 
00545   // fill the first byte with some encoding to indicate the current cycle.
00546   // The second byte   is the last digit of the cycle added to 'a'.
00547   sprintf( strMsg, "%c", 'a' + WM->getCurrentCycle()%10   );
00548 
00549   // fill the second byte with information about the offside line.
00550   // Enter either a value between a-z or A-Z indicating. This gives 52 possible
00551   // values which correspond with meters on the field. So B means the offside
00552   // line lies at 27.0.
00553   int iOffside = (int)WM->getOffsideX();
00554   if( iOffside < 26 ) // 0..25
00555     sprintf( strTmp, "%c", 'a' + iOffside );
00556   else               // 26...
00557     sprintf( strTmp, "%c", 'A' + max(iOffside - 26, 25) );
00558   strcat( strMsg, strTmp );
00559 
00560   // find the closest opponent attacker to the penalty spot.
00561   double dDist ;
00562   ObjectT objOpp = WM->getClosestInSetTo( OBJECT_SET_OPPONENTS,
00563          VecPosition(- PITCH_LENGTH/2.0 + 11.0, 0 ), &dDist  ) ;
00564 
00565   if( objOpp == OBJECT_ILLEGAL || dDist >= 20.0 )
00566   {
00567     strncpy( strMsg, "", 0 );
00568     return;
00569   }
00570 
00571   VecPosition posOpp = WM->getGlobalPosition( objOpp );
00572   if( fabs( posOpp.getY() ) > 10 )
00573   {
00574     strncpy( strMsg, "", 0 );
00575     return;
00576   }
00577 
00578   // encode the position of this attacker in the visual message. The
00579   // player_number is the third byte, then comes the x position in 3 digits (it
00580   // is assumed this value is always negative), a space and finally the y
00581   // position in 2 digits. An example of opponent nr. 9 at position
00582   // (-40.3223,-3.332) is "j403 -33)
00583   sprintf( strTmp, "%c%d %d", 'a' + SoccerTypes::getIndex( objOpp ) ,
00584                               (int)(fabs(posOpp.getX())*10),
00585                               (int)(posOpp.getY()*10));
00586   strcat( strMsg, strTmp );
00587 
00588   return ;
00589 }
00590 
00595 void Player::sayBallStatus( char * strMsg  )
00596 {
00597   VecPosition posBall = WM->getGlobalPosition( OBJECT_BALL );
00598   VecPosition velBall = WM->getGlobalVelocity( OBJECT_BALL );
00599   int iDiff = 0;
00600   SoccerCommand soc = ACT->getPrimaryCommand();
00601 
00602   if( WM->getRelativeDistance( OBJECT_BALL ) < SS->getMaximalKickDist() )
00603   {
00604     // if kick and a pass
00605     if( soc.commandType == CMD_KICK )
00606     {
00607       WM->predictBallInfoAfterCommand( soc, &posBall, &velBall );
00608       VecPosition posAgent = WM->predictAgentPos( 1, 0 );
00609       if( posBall.getDistanceTo( posAgent ) > SS->getMaximalKickDist() + 0.2 )
00610         iDiff = 1;
00611     }
00612 
00613     if( iDiff == 0 )
00614     {
00615       posBall = WM->getGlobalPosition( OBJECT_BALL );
00616       velBall.setVecPosition( 0, 0 );
00617     }
00618   }
00619   Log.log( 600, "create comm. ball after: (%1.2f,%1.2f)(%1.2f,%1.2f) diff %d",
00620      posBall.getX(), posBall.getY(), velBall.getX(), velBall.getY(), iDiff);
00621   makeBallInfo( posBall, velBall, iDiff, strMsg );
00622 }
00623 
00631 void Player::makeBallInfo( VecPosition posBall, VecPosition velBall, int iDiff,
00632                             char * strMsg  )
00633 {
00634   char    strTmp[MAX_SAY_MSG];
00635 
00636   // fill the first byte with some encoding to indicate the next cycle.
00637   // The second byte is the last digit of the cycle added to 'a'.
00638   sprintf( strMsg, "%c", 'a' + (WM->getCurrentCycle()+iDiff)%10   );
00639 
00640   // fill the second byte with information about the offside line.
00641   // Enter either a value between a-z or A-Z indicating. This gives 52 possible
00642   // values which correspond with meters on the field. So B means the offside
00643   // line lies at 27.0.
00644   int iOffside = (int)( WM->getOffsideX( false ) - 1.0 );
00645   if( iOffside < 26 ) // 0..25
00646     sprintf( strTmp, "%c", 'a' + max( 0, iOffside) );
00647   else               // 26...
00648     sprintf( strTmp, "%c", 'A' + min(iOffside - 26, 25) );
00649   strcat( strMsg, strTmp );
00650 
00651   // First add al values to a positive interval, since then we don't need
00652   // another byte for the minus sign. then take one digit at a time
00653   double x = max(0,min( rint( posBall.getX() + 48.0), 99.0));
00654   sprintf( strTmp, "%c%c%c%c%c%c%c%c",
00655      '0' + ((int)( x                          ) % 100 ) / 10 ,
00656      '0' + ((int)( x                          ) % 100 ) % 10 ,
00657      '0' + ((int)( rint(posBall.getY() + 34.0)) % 100 ) / 10 ,
00658      '0' + ((int)( rint(posBall.getY() + 34.0)) % 100 ) % 10 ,
00659      '0' + ((int)(( velBall.getX() + 2.7) * 10 )) / 10 ,
00660      '0' + ((int)(( velBall.getX() + 2.7) * 10 )) % 10 ,
00661      '0' + ((int)(( velBall.getY() + 2.7) * 10 )) / 10 ,
00662      '0' + ((int)(( velBall.getY() + 2.7) * 10 )) % 10 );
00663   strcat( strMsg, strTmp );
00664   Log.log( 6560, "say (%d) %s\n", WM->getPlayerNumber() , strMsg );
00665 
00666   return ;
00667 }
00668 
00671 void Player::performPenalty( )
00672 {
00673   VecPosition   pos;
00674   int           iSide = ( WM->getSide() == WM->getSidePenalty() ) ? -1 : 1;
00675   VecPosition   posPenalty( iSide*(52.5 - SS->getPenDistX()), 0.0 );
00676   VecPosition   posAgent = WM->getAgentGlobalPosition();
00677   AngDeg        angBody  = WM->getAgentGlobalBodyAngle();
00678 
00679   SoccerCommand soc(CMD_ILLEGAL);
00680   static PlayModeT pmPrev = PM_ILLEGAL;
00681 
00682   // raise number of penalties by one when a penalty is taken
00683   if(
00684     ( WM->getSide() == SIDE_LEFT && 
00685       pmPrev != PM_PENALTY_SETUP_LEFT && 
00686       WM->getPlayMode() == PM_PENALTY_SETUP_LEFT )
00687     ||
00688     ( WM->getSide() == SIDE_RIGHT && 
00689       pmPrev != PM_PENALTY_SETUP_RIGHT && 
00690       WM->getPlayMode() == PM_PENALTY_SETUP_RIGHT ) )
00691    m_iPenaltyNr++;
00692 
00693   // start with player 11 and go downwards with each new penalty
00694   // if we take penalty 
00695   if( WM->isPenaltyUs() && WM->getPlayerNumber() == (11 - (m_iPenaltyNr % 11)))
00696   {
00697      if( WM->getPlayMode() == PM_PENALTY_SETUP_LEFT ||
00698          WM->getPlayMode() == PM_PENALTY_SETUP_RIGHT )
00699      {
00700        pos = posPenalty - VecPosition( iSide*2.0, 0 );
00701        if( fabs( posAgent.getX() ) > fabs( pos.getX() ) )
00702          pos = posPenalty;
00703        if( pos.getDistanceTo( posAgent ) < 0.6 )
00704        {
00705          pos = posPenalty;
00706          if(  fabs( VecPosition::normalizeAngle( 
00707                    (pos-posAgent).getDirection() - angBody ) ) > 20 )
00708            soc = turnBodyToPoint( pos );
00709        }
00710        //  pos = WM->getAgentGlobalPosition();
00711      }
00712      else if( ( WM->getPlayMode() == PM_PENALTY_READY_LEFT ||
00713                 WM->getPlayMode() == PM_PENALTY_READY_RIGHT ||
00714                 WM->getPlayMode() == PM_PENALTY_TAKEN_LEFT ||
00715                 WM->getPlayMode() == PM_PENALTY_TAKEN_RIGHT 
00716                 )
00717               && WM->isBallKickable() )
00718      {
00719        soc = kickTo(VecPosition(iSide*52.5,((drand48()<0.5)?1:-1)*5.9 ),2.7);
00720      }
00721      else
00722        pos = posPenalty;
00723   }
00724   else if( formations->getPlayerType() == PT_GOALKEEPER )
00725   {
00726     if( WM->getAgentViewAngle() != VA_NARROW )
00727       ACT->putCommandInQueue( 
00728      SoccerCommand( CMD_CHANGEVIEW, VA_NARROW, VQ_HIGH ));
00729 
00730     // is penalty them, stop it, otherwise go to outside field
00731     pos = posPenalty;
00732     if( WM->isPenaltyThem( ) )
00733     {
00734       pos = VecPosition( iSide*(52.5 - 2.0), 0.0 );
00735       if( SS->getPenAllowMultKicks() == false )
00736       {
00737   if( WM->getPlayMode() == PM_PENALTY_TAKEN_LEFT ||
00738       WM->getPlayMode() == PM_PENALTY_TAKEN_RIGHT )
00739   {
00740     if( WM->isBallCatchable( ) )
00741       soc = catchBall();
00742     else
00743       soc = intercept( true );
00744   }
00745       }
00746       else if( pos.getDistanceTo( posAgent ) < 1.0 )
00747         soc = turnBodyToPoint( VecPosition( 0,0) ) ;
00748       else
00749         soc = moveToPos( pos, 25 );
00750     }
00751     else
00752       pos.setVecPosition( iSide * ( PITCH_LENGTH/2.0 + 2 ) , 25 );
00753   }
00754   else
00755   {
00756     pos = VecPosition( 5.0,
00757                        VecPosition::normalizeAngle( 
00758                          iSide*(50 + 20*WM->getPlayerNumber())),
00759                        POLAR );
00760   }
00761 
00762 
00763   if( soc.isIllegal() && 
00764       WM->getAgentGlobalPosition().getDistanceTo( pos ) < 0.8 )
00765   {
00766     soc = turnBodyToPoint( posPenalty  );    
00767   }
00768   else if( soc.isIllegal() )
00769   {
00770     soc = moveToPos( pos, 10);
00771   }
00772   if( WM->getAgentStamina().getStamina() < 
00773       SS->getRecoverDecThr()*SS->getStaminaMax() + 500 &&
00774     soc.commandType == CMD_DASH)
00775     soc.dPower = 0;
00776   
00777   ACT->putCommandInQueue( soc );
00778   ACT->putCommandInQueue( turnNeckToObject( OBJECT_BALL, soc ) );
00779 
00780   pmPrev = WM->getPlayMode();
00781 }
00782 

Generated on Fri Nov 7 11:45:40 2003 for UvA Trilearn 2003 Base Code by doxygen1.2.12 written by Dimitri van Heesch, © 1997-2001