00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00049 #include "Player.h"
00050 #include "Parse.h"
00051 #ifndef WIN32
00052   #include <sys/poll.h> 
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   
00086   
00087 #ifdef WIN32
00088   Sleep( formations->getPlayerInFormation()*500 );
00089 #else
00090   poll( 0, 0, formations->getPlayerInFormation()*500 );
00091 #endif
00092 
00093   
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   
00114   
00115   if(  WM->waitForNewInformation() == false )
00116     bContLoop =  false;
00117 
00118   
00119   sprintf( str, "(clang (ver 8 8))" );
00120   ACT->sendMessage( str );
00121 
00122   while( bContLoop )                                 
00123   {
00124     Log.logWithTime( 3, "  start update_all" );
00125 
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( ) )        
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 )           
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       
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     
00203     
00204     if(  WM->waitForNewInformation() == false )
00205         bContLoop =  false;
00206   }
00207 
00208   
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   
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   
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 ); 
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':                                 
00352       WM->showQueuedCommands();
00353       break;
00354     case 'c':                                 
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':                                 
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':                                
00369       showStringCommands( cout );
00370       return true;
00371     case 'k':                                
00372       socCommand.commandType = CMD_KICK;
00373       if( str[1] == 'a' ) 
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':                               
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':                              
00393       socCommand.commandType = CMD_TURNNECK;
00394       socCommand.dAngle      = Parse::parseFirstDouble( &str );
00395       break;
00396     case 'o':                              
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':                              
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':                             
00415       bContLoop = false;
00416       return true;
00417     case 's':                             
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':                             
00429       socCommand.commandType = CMD_TURN;
00430       socCommand.dAngle      = Parse::parseFirstDouble( &str );
00431       break;
00432     case 'v':                             
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':                            
00442       WM->show();
00443       return true;
00444     default:                             
00445       ACT->sendMessage( str );
00446       return true;
00447   }
00448   if( socCommand.commandType != CMD_ILLEGAL ) 
00449     ACT->putCommandInQueue( socCommand );     
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 
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   
00500   
00501   obj = WM->getClosestInSetTo( OBJECT_SET_TEAMMATES,OBJECT_BALL,&dDist);
00502   if( dDist < SS->getVisibleDistance() &&
00503       obj != WM->getAgentObjectType() )
00504     return false;
00505 
00506   
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 ) 
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   
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       ( 
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   
00546   
00547   sprintf( strMsg, "%c", 'a' + WM->getCurrentCycle()%10   );
00548 
00549   
00550   
00551   
00552   
00553   int iOffside = (int)WM->getOffsideX();
00554   if( iOffside < 26 ) 
00555     sprintf( strTmp, "%c", 'a' + iOffside );
00556   else               
00557     sprintf( strTmp, "%c", 'A' + max(iOffside - 26, 25) );
00558   strcat( strMsg, strTmp );
00559 
00560   
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   
00579   
00580   
00581   
00582   
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     
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   
00637   
00638   sprintf( strMsg, "%c", 'a' + (WM->getCurrentCycle()+iDiff)%10   );
00639 
00640   
00641   
00642   
00643   
00644   int iOffside = (int)( WM->getOffsideX( false ) - 1.0 );
00645   if( iOffside < 26 ) 
00646     sprintf( strTmp, "%c", 'a' + max( 0, iOffside) );
00647   else               
00648     sprintf( strTmp, "%c", 'A' + min(iOffside - 26, 25) );
00649   strcat( strMsg, strTmp );
00650 
00651   
00652   
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   
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   
00694   
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        
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     
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