📄 player.cpp
字号:
/*Copyright (c) 2000-2003, Jelle Kok, University of AmsterdamAll rights reserved.Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met:1. Redistributions of source code must retain the above copyright notice, thislist of conditions and the following disclaimer.2. Redistributions in binary form must reproduce the above copyright notice,this list of conditions and the following disclaimer in the documentationand/or other materials provided with the distribution.3. Neither the name of the University of Amsterdam nor the names of itscontributors may be used to endorse or promote products derived from thissoftware without specific prior written permission.THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLEFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIALDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ORSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVERCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USEOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*//*! \file Player.cpp<pre><b>File:</b> Player.cpp<b>Project:</b> Robocup Soccer Simulation Team: UvA Trilearn<b>Authors:</b> Jelle Kok<b>Created:</b> 03/03/2001<b>Last Revision:</b> $ID$<b>Contents:</b> This file contains the definitions for the Player class, which is a superclass from BasicPlayer and contains the decision procedure to select the skills from the BasicPlayer.<hr size=2><h2><b>Changes</b></h2><b>Date</b> <b>Author</b> <b>Comment</b>03/03/2001 Jelle Kok Initial version created</pre>*/#include "Player.h"#include "Parse.h"#ifndef WIN32 #include <sys/poll.h> // needed for 'poll'#endifextern Logger LogDraw;/*!This is the constructor the Player class and calls the constructor of the superclass BasicPlayer. \param act ActHandler to which the actions can be sent \param wm WorldModel which information is used to determine action \param ss ServerSettings that contain parameters used by the server \param ps PlayerSettings that contain parameters important for the client \param strTeamName team name of this player \param dVersion version this basicplayer corresponds to \param iReconnect integer that defines player number (-1 when new player) */Player::Player( ActHandler* act, WorldModel *wm, ServerSettings *ss, PlayerSettings *ps, Formations *fs, char* strTeamName, double dVersion, int iReconnect ){ char str[MAX_MSG]; ACT = act; WM = wm; SS = ss; PS = ps; formations = fs; bContLoop = true; m_iPenaltyNr = -1; WM->setTeamName( strTeamName ); m_timeLastSay = -5; m_objMarkOpp = OBJECT_ILLEGAL; m_actionPrev = ACT_ILLEGAL; // wait longer as role number increases, to make sure players appear at the // field in the correct order#ifdef WIN32 Sleep( formations->getPlayerInFormation()*500 );#else poll( 0, 0, formations->getPlayerInFormation()*500 );#endif // create initialisation string if( iReconnect != -1 ) sprintf( str, "(reconnect %s %d)", strTeamName, iReconnect ); else if( formations->getPlayerType() == PT_GOALKEEPER ) sprintf( str, "(init %s (version %f) (goalie))", strTeamName, dVersion ); else sprintf( str, "(init %s (version %f))", strTeamName, dVersion ); ACT->sendMessage( str ); }/*! This is the main loop of the agent. This method calls the update methods of the world model after it is indicated that new information has arrived. After this, the correct main loop of the player type is called, which puts the best soccer command in the queue of the ActHandler. */void Player::mainLoop( ){ char str[MAX_MSG]; Timing timer; // wait for new information from the server // cannot say bContLoop=WM->wait... since bContLoop can be changed elsewhere if( WM->waitForNewInformation() == false ) bContLoop = false; // and set the clang version sprintf( str, "(clang (ver 8 8))" ); ACT->sendMessage( str ); while( bContLoop ) // as long as server alive { Log.logWithTime( 3, " start update_all" );// Log.setHeader( WM->getCurrentCycle(), WM->getPlayerNumber() ); Log.setHeader( WM->getCurrentCycle() ); LogDraw.setHeader( WM->getCurrentCycle() ); if( WM->updateAll( ) == true ) { timer.restartTime(); SoccerCommand soc; if( ( WM->isPenaltyUs( ) || WM->isPenaltyThem() ) ) performPenalty(); else if( WM->getPlayMode() == PM_FROZEN ) ACT->putCommandInQueue( turnBodyToObject( OBJECT_BALL ) ); else { switch( formations->getPlayerType( ) ) // determine right loop { case PT_GOALKEEPER: soc = goalieMainLoop( ); break; case PT_DEFENDER_SWEEPER: case PT_DEFENDER_CENTRAL: case PT_DEFENDER_WING: soc = defenderMainLoop( ); break; case PT_MIDFIELDER_CENTER: case PT_MIDFIELDER_WING: soc = midfielderMainLoop( ); break; case PT_ATTACKER: case PT_ATTACKER_WING: soc = attackerMainLoop( ); break; case PT_ILLEGAL: default: break; } if( shallISaySomething(soc) == true ) // shall I communicate { m_timeLastSay = WM->getCurrentTime(); char strMsg[MAX_SAY_MSG]; if( WM->getPlayerNumber() == 6 && WM->getBallPos().getX() < - PENALTY_X + 4.0 ) sayOppAttackerStatus( strMsg ); else sayBallStatus( strMsg ); if( strlen( strMsg ) != 0 ) Log.log( 600, "send communication string: %s", strMsg ); WM->setCommunicationString( strMsg ); } } Log.logWithTime( 3, " determined action; waiting for new info" ); // directly after see message, will nog get better info, so send commands if( WM->getTimeLastSeeMessage() == WM->getCurrentTime() || (SS->getSynchMode() == true && WM->getRecvThink() == true )) { Log.logWithTime( 3, " send messages directly" ); ACT->sendCommands( ); Log.logWithTime( 3, " sent messages directly" ); if( SS->getSynchMode() == true ) { WM->processRecvThink( false ); ACT->sendMessageDirect( "(done)" ); } } } else Log.logWithTime( 3, " HOLE no action determined; waiting for new info"); if( WM->getCurrentCycle()%(SS->getHalfTime()*SS->getSimulatorStep()) != 0 ) { if( LogDraw.isInLogLevel( 600 ) ) { WM->logDrawInfo( 600 ); } if( LogDraw.isInLogLevel( 601 ) ) WM->logDrawBallInfo( 601 ); if( LogDraw.isInLogLevel( 700 ) ) WM->logCoordInfo( 700 ); } Log.logWithTime( 604, "time for action: %f", timer.getElapsedTime()*1000 ); // wait for new information from the server cannot say // bContLoop=WM->wait... since bContLoop can be changed elsewhere if( WM->waitForNewInformation() == false ) bContLoop = false; } // shutdow, print hole and number of players seen statistics printf("Shutting down player %d\n", WM->getPlayerNumber() ); printf(" Number of holes: %d (%f)\n", WM->iNrHoles, ((double)WM->iNrHoles/WM->getCurrentCycle())*100 ); printf(" Teammates seen: %d (%f)\n", WM->iNrTeammatesSeen, ((double)WM->iNrTeammatesSeen/WM->getCurrentCycle())); printf(" Opponents seen: %d (%f)\n", WM->iNrOpponentsSeen, ((double)WM->iNrOpponentsSeen/WM->getCurrentCycle()));}/*! This is the main decision loop for the goalkeeper. */SoccerCommand Player::goalieMainLoop( ){ return deMeer5_goalie();}/*! This is the main decision loop for a defender. */SoccerCommand Player::defenderMainLoop( ){ return deMeer5() ;}/*! This is the main decision loop for a midfielder. */SoccerCommand Player::midfielderMainLoop( ){ return deMeer5() ;}/*! This is the main decision loop for an agent. */SoccerCommand Player::attackerMainLoop( ){ return deMeer5() ;}/*! This method returns the position to move in case of a dead ball situation. A dead ball situation occurs when the team can have a free kick, kick in, etc. The agent will move to the position behind the ball and when he is there will move to the ball again. */VecPosition Player::getDeadBallPosition( ){ VecPosition pos, posBall = WM->getBallPos(); VecPosition posAgent = WM->getAgentGlobalPosition(); double dDist; // determine point to move to if( WM->isKickInUs() ) pos = posBall + VecPosition( -1.5, sign( posBall.getY() )*1.5 ); else if( WM->isCornerKickUs( ) ) pos = posBall + VecPosition( 1.5, sign( posBall.getY() ) * 1.5 ); else if( WM->isFreeKickUs() || WM->isOffsideThem() || WM->isGoalKickUs() || WM->isFreeKickFaultThem() || WM->isBackPassThem() ) pos = posBall + VecPosition( -1.5, 0.0 ); else return VecPosition( UnknownDoubleValue, UnknownDoubleValue ); AngDeg angBall = (posBall-posAgent).getDirection() ; ObjectT obj = WM->getClosestInSetTo( OBJECT_SET_PLAYERS, WM->getAgentObjectType(), &dDist); VecPosition posPlayer = WM->getGlobalPosition( obj ); // change point when heading towards other player or towards the ball if( fabs( angBall - (posPlayer-posAgent).getDirection() ) < 20 && dDist < 6 ) pos -= VecPosition( 5, 0 ); if( fabs( angBall - (pos-posAgent).getDirection()) < 20 ) { angBall = VecPosition::normalizeAngle( angBall - 90 ); pos = posBall + VecPosition( 1, angBall , POLAR ); } return pos;}/*!This method listens for input from the keyboard and when it receives this input it converts this input to the associated action. See showStringCommands for the possible options. This method is used together with the SenseHandler class that sends an alarm to indicate that a new command can be sent. This conflicts with the method in this method that listens for the user input (fgets) on Linux systems (on Solaris this isn't a problem). The only known method is to use the flag SA_RESTART with this alarm function, but that does not seem to work under Linux. If each time the alarm is sent, this gets function unblocks, it will cause major performance problems. This function should not be called when a whole match is played! */void Player::handleStdin( ){ char buf[MAX_MSG]; while( bContLoop ) {#ifdef WIN32 cin.getline( buf, MAX_MSG );#else fgets( buf, MAX_MSG, stdin ); // does unblock with signal !!!!!#endif printf( "after fgets: %s\n", buf ); executeStringCommand( buf ); }}/*!This method prints the possible commands that can be entered by the user. The whole name can be entered to perform the corresponding command, but normally only the first character is sufficient. This is indicated by putting brackets around the part of the command that is not needed. \param out output stream to which the possible commands are printed */void Player::showStringCommands( ostream& out ){ out << "Basic commands:" << endl << " a(ctions)" << endl << " c(atch) direction" << endl << " cs(lientsettings" << endl << " d(ash) power [ times ]" << endl << " de(bug) nr_cycles" << endl << " g(oto) x y" << endl << " h(elp)" << endl << " i(ntercept) x y" << endl << " k(ick) power angle" << endl << " ka x y endspeed " << endl << " m(ove) x y" << endl << " n(eck) angle" << endl << " o(pponents in cone) width dist" << endl << " p(redict cycles to) x y" << endl << " q(uit)" << endl << " s(ay) message" << endl << " ss(erversettings)" << endl << " t(urn) angle" << endl << " v(iewmode) narrow | normal | wide low | high" << endl << " w(orldmodel)" << endl;}/*!This method executes the command that is entered by the user. For the possible command look at the method showStringCommands. \param str string that is entered by the user \return true when command could be executed, false otherwise */bool Player::executeStringCommand( char *str){ SoccerCommand socCommand; int i; double x, y; switch( str[0] ) { case 'a': // actions WM->showQueuedCommands(); break; case 'c': // catch dir or cs if( strlen(str) > 1 && str[1] == 's' ) { PS->show( cout, ":" ); break; } socCommand.makeCommand( CMD_CATCH, Parse::parseFirstInt( &str ) ); break; case 'd': // dash socCommand.commandType = CMD_DASH; socCommand.dPower = Parse::parseFirstDouble( &str ); socCommand.iTimes = Parse::parseFirstInt ( &str ); if( socCommand.iTimes == 0 ) socCommand.iTimes = 1; break; case 'h': // help showStringCommands( cout ); return true; case 'k': // kick or ka (kick advanced) socCommand.commandType = CMD_KICK; if( str[1] == 'a' ) // advanced kick { double x = Parse::parseFirstDouble( &str ); double y = Parse::parseFirstDouble( &str ); double e = Parse::parseFirstDouble( &str ); socCommand = kickTo( VecPosition( x, y), e ); } else { socCommand.dPower = Parse::parseFirstDouble( &str ); socCommand.dAngle = Parse::parseFirstDouble( &str ); } break; case 'm': // move socCommand.commandType = CMD_MOVE; socCommand.dX = Parse::parseFirstDouble( &str ); socCommand.dY = Parse::parseFirstDouble( &str ); socCommand.dAngle = Parse::parseFirstDouble( &str ); break; case 'n': // turn_neck
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -