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
00048 #include "BasicPlayer.h"
00049 #include "Parse.h"
00050
00051
00052
00057 SoccerCommand BasicPlayer::alignNeckWithBody( )
00058 {
00059 return SoccerCommand( CMD_TURNNECK, WM->getAgentBodyAngleRelToNeck( ) );
00060 }
00061
00080 SoccerCommand BasicPlayer::turnBodyToPoint( VecPosition pos, int iCycles )
00081 {
00082 VecPosition posGlobal = WM->predictAgentPos(iCycles, 0);
00083 AngDeg angTurn = (pos - posGlobal).getDirection();
00084 angTurn -= WM->getAgentGlobalBodyAngle();
00085 angTurn = VecPosition::normalizeAngle( angTurn );
00086 angTurn = WM->getAngleForTurn( angTurn, WM->getAgentSpeed(),
00087 WM->getAgentObjectType() );
00088
00089 return SoccerCommand( CMD_TURN, angTurn );
00090 }
00091
00104 SoccerCommand BasicPlayer::turnBackToPoint( VecPosition pos, int iCycles )
00105 {
00106 VecPosition posGlobal = WM->predictAgentPos(iCycles, 0);
00107 AngDeg angTurn = (pos - posGlobal).getDirection();
00108 angTurn -= (WM->getAgentGlobalBodyAngle() + 180);
00109 angTurn = VecPosition::normalizeAngle( angTurn );
00110 angTurn = WM->getAngleForTurn( angTurn, WM->getAgentSpeed(),
00111 WM->getAgentObjectType() );
00112
00113 return SoccerCommand( CMD_TURN, angTurn );
00114 }
00115
00137 SoccerCommand BasicPlayer::turnNeckToPoint(VecPosition pos, SoccerCommand soc)
00138 {
00139 VecPosition posMe, velMe;
00140 AngDeg angBody, angNeck, angActual;
00141 Stamina sta;
00142
00143
00144
00145
00146 WM->predictAgentStateAfterCommand(soc,&posMe,&velMe,&angBody,&angNeck,&sta);
00147 AngDeg angDesGlobNeck = (pos - posMe).getDirection();
00148 AngDeg angNeckRelToBody= VecPosition::normalizeAngle(angDesGlobNeck-angBody);
00149
00150
00151
00152
00153
00154
00155 AngDeg angBodyRelToNeck = VecPosition::normalizeAngle(angBody-angNeck);
00156 if( angNeckRelToBody < SS->getMinNeckAng() )
00157 angActual = SS->getMinNeckAng() + angBodyRelToNeck;
00158 else if( angNeckRelToBody > SS->getMaxNeckAng() )
00159 angActual = SS->getMaxNeckAng() + angBodyRelToNeck;
00160 else
00161 angActual = angNeckRelToBody + angBodyRelToNeck;
00162 return SoccerCommand( CMD_TURNNECK, angActual );
00163 }
00164
00176 SoccerCommand BasicPlayer::searchBall()
00177 {
00178 static Time timeLastSearch;
00179 static SoccerCommand soc;
00180 static int iSign = 1;
00181 VecPosition posBall =WM->getBallPos();
00182 VecPosition posAgent=WM->getAgentGlobalPosition();
00183 AngDeg angBall =(posBall-WM->getAgentGlobalPosition()).getDirection();
00184 AngDeg angBody =WM->getAgentGlobalBodyAngle();
00185
00186 if( WM->getCurrentTime().getTime() == timeLastSearch.getTime() )
00187 return soc;
00188
00189 if( WM->getCurrentTime() - timeLastSearch > 3 )
00190 iSign = ( isAngInInterval( angBall, angBody,
00191 VecPosition::normalizeAngle(angBody+180) ) )
00192 ? 1
00193 : -1 ;
00194
00195
00196
00197
00198 soc = turnBodyToPoint( posAgent + VecPosition(1.0,
00199 VecPosition::normalizeAngle(angBody+60*iSign), POLAR ) );
00200 Log.log( 556, "search ball: turn to %f s %d t(%d %d) %f", angBall, iSign,
00201 WM->getCurrentTime().getTime(), timeLastSearch.getTime(),
00202 soc.dAngle );
00203 timeLastSearch = WM->getCurrentTime();
00204 return soc;
00205 }
00206
00207
00223 SoccerCommand BasicPlayer::dashToPoint( VecPosition pos, int iCycles )
00224 {
00225 double dDashPower = WM->getPowerForDash(
00226 pos - WM->getAgentGlobalPosition(),
00227 WM->getAgentGlobalBodyAngle(),
00228 WM->getAgentGlobalVelocity(),
00229 WM->getAgentEffort(),
00230 iCycles );
00231 return SoccerCommand( CMD_DASH, dDashPower );
00232 }
00233
00246 SoccerCommand BasicPlayer::freezeBall( )
00247 {
00248
00249
00250
00251 VecPosition posAgentPred = WM->predictAgentPos( 1, 0 );
00252
00253 double dPower = WM->getKickPowerForSpeed( WM->getBallSpeed() );
00254 if( dPower > SS->getMaxPower() )
00255 {
00256 Log.log( 552, "%d: freeze ball has to much power", WM->getCurrentCycle() );
00257 dPower = (double)SS->getMaxPower();
00258 }
00259 double dAngle = WM->getBallDirection() + 180 - WM->getAgentGlobalBodyAngle();
00260 dAngle = VecPosition::normalizeAngle( dAngle );
00261 SoccerCommand soc( CMD_KICK, dPower, dAngle );
00262 VecPosition posBall, velBall;
00263 WM->predictBallInfoAfterCommand( soc, &posBall, &velBall );
00264 if( posBall.getDistanceTo( posAgentPred ) < 0.8 * SS->getMaximalKickDist() )
00265 return soc;
00266 Log.log( 101, "freeze ball will end up oustide -> accelerate" );
00267 posBall = WM->getBallPos();
00268
00269 VecPosition posTo = posAgentPred +
00270 VecPosition( min( 0.7 * SS->getMaximalKickDist(),
00271 posBall.getDistanceTo( posAgentPred ) - 0.1 ),
00272 (posBall-posAgentPred).getDirection(),
00273 POLAR );
00274 VecPosition velDes( posTo - posBall );
00275 return accelerateBallToVelocity( velDes );
00276 }
00277
00298 SoccerCommand BasicPlayer::kickBallCloseToBody( AngDeg ang, double dKickRatio )
00299 {
00300 AngDeg angBody = WM->getAgentGlobalBodyAngle();
00301 VecPosition posAgent = WM->predictAgentPos( 1, 0 );
00302 double dDist = SS->getPlayerSize() +
00303 SS->getBallSize() +
00304 SS->getKickableMargin()*dKickRatio;
00305 AngDeg angGlobal = VecPosition::normalizeAngle( angBody + ang );
00306 VecPosition posDesBall = posAgent + VecPosition( dDist, angGlobal, POLAR );
00307 if( fabs( posDesBall.getY() ) > PITCH_WIDTH/2.0 ||
00308 fabs( posDesBall.getX() ) > PITCH_LENGTH/2.0 )
00309 {
00310 Line lineBody = Line::makeLineFromPositionAndAngle( posAgent, angGlobal );
00311 Line lineSide(0,0,0);
00312 if( fabs( posDesBall.getY() ) > PITCH_WIDTH/2.0 )
00313 lineSide = Line::makeLineFromPositionAndAngle(
00314 VecPosition( 0, sign(posDesBall.getY() )* PITCH_WIDTH/2.0 ), 0 );
00315 else
00316 lineSide = Line::makeLineFromPositionAndAngle(
00317 VecPosition( 0, sign(posDesBall.getX() )* PITCH_LENGTH/2.0 ), 90 );
00318 VecPosition posIntersect = lineSide.getIntersection( lineBody );
00319 posDesBall = posAgent +
00320 VecPosition( posIntersect.getDistanceTo( posAgent ) - 0.2,
00321 angGlobal, POLAR );
00322 }
00323
00324 VecPosition vecDesired = posDesBall - WM->getBallPos();
00325 VecPosition vecShoot = vecDesired - WM->getGlobalVelocity( OBJECT_BALL );
00326 double dPower = WM->getKickPowerForSpeed( vecShoot.getMagnitude() );
00327 AngDeg angActual = vecShoot.getDirection() - angBody;
00328 angActual = VecPosition::normalizeAngle( angActual );
00329
00330 if( dPower > SS->getMaxPower() && WM->getBallSpeed() > 0.1 )
00331 {
00332 Log.log( 500, "kickBallCloseToBody: cannot compensate ball speed, freeze");
00333 Log.log( 101, "kickBallCloseToBody: cannot compensate ball speed, freeze");
00334 return freezeBall();
00335 }
00336 else if( dPower > SS->getMaxPower() )
00337 {
00338 if( WM->isDeadBallUs() )
00339 {
00340 if( WM->getRelativeAngle( OBJECT_BALL ) > 25 )
00341 {
00342 Log.log( 101, "dead ball situation, turn to ball" );
00343 return turnBodyToObject( OBJECT_BALL );
00344 }
00345 }
00346 else
00347 {
00348 Log.log( 101, "kickBallCloseToBody: ball has no speed, but far away" );
00349 dPower = 100;
00350 }
00351 }
00352 else
00353 Log.log( 101, "(kick %f %f), vecDesired (%f,%f) %f posDes(%f,%f)",
00354 dPower, angActual,vecDesired.getX(), vecDesired.getY(),ang,
00355 posDesBall.getX(), posDesBall.getY() );
00356 return SoccerCommand( CMD_KICK, dPower, angActual );
00357 }
00358
00377 SoccerCommand BasicPlayer::accelerateBallToVelocity( VecPosition velDes )
00378 {
00379 AngDeg angBody = WM->getAgentGlobalBodyAngle();
00380 VecPosition velBall = WM->getGlobalVelocity( OBJECT_BALL );
00381 VecPosition accDes = velDes - velBall;
00382 double dPower;
00383 double angActual;
00384
00385
00386 if( accDes.getMagnitude() < SS->getBallAccelMax() )
00387 {
00388 dPower = WM->getKickPowerForSpeed ( accDes.getMagnitude() );
00389 angActual = VecPosition::normalizeAngle( accDes.getDirection() - angBody );
00390 if( dPower <= SS->getMaxPower() )
00391 return SoccerCommand( CMD_KICK, dPower, angActual );
00392 }
00393
00394
00395 dPower = SS->getMaxPower();
00396 double dSpeed = WM->getActualKickPowerRate() * dPower;
00397 double tmp = velBall.rotate(-velDes.getDirection()).getY();
00398 angActual = velDes.getDirection() - asinDeg( tmp / dSpeed );
00399 angActual = VecPosition::normalizeAngle( angActual - angBody );
00400
00401 return SoccerCommand( CMD_KICK, dPower, angActual );
00402 }
00403
00412 SoccerCommand BasicPlayer::catchBall()
00413 {
00414
00415 return SoccerCommand( CMD_CATCH, WM->getRelativeAngle( OBJECT_BALL, true ));
00416 }
00417
00418
00424 SoccerCommand BasicPlayer::communicate( char *str )
00425 {
00426 return SoccerCommand( CMD_SAY, str );
00427 }
00428
00433 SoccerCommand BasicPlayer::teleportToPos( VecPosition pos )
00434 {
00435 return SoccerCommand( CMD_MOVE, pos.getX(), pos.getY() );
00436
00437 }
00438
00441 SoccerCommand BasicPlayer::listenTo( ObjectT obj )
00442 {
00443 if( !SoccerTypes::isKnownPlayer( obj ) )
00444 return SoccerCommand( CMD_ATTENTIONTO, -1.0, -1.0 );
00445
00446 return SoccerCommand( CMD_ATTENTIONTO,
00447 1.0,
00448 SoccerTypes::getIndex( obj ) + 1 );
00449 }
00450
00452 SoccerCommand BasicPlayer::tackle( )
00453 {
00454 return SoccerCommand( CMD_TACKLE, 100.0 );
00455 }
00456
00457
00458
00467 SoccerCommand BasicPlayer::turnBodyToObject( ObjectT o )
00468 {
00469 return turnBodyToPoint( WM->predictPosAfterNrCycles(o, 1) );
00470 }
00471
00487 SoccerCommand BasicPlayer::turnNeckToObject( ObjectT o, SoccerCommand soc )
00488 {
00489 return turnNeckToPoint( WM->predictPosAfterNrCycles(o, 1), soc );
00490 }
00491
00492 SoccerCommand BasicPlayer::directTowards( VecPosition posTurnTo,
00493 AngDeg angWhenToTurn, VecPosition *pos, VecPosition *vel, AngDeg *angBody )
00494 {
00495
00496
00497 VecPosition posAgent= (pos ==NULL)?WM->getAgentGlobalPosition ():*pos;
00498 VecPosition velAgent= (vel ==NULL)?WM->getAgentGlobalVelocity ():*vel;
00499 AngDeg angBodyAgent= (angBody==NULL)?WM->getAgentGlobalBodyAngle():*angBody;
00500
00501
00502 VecPosition posPred = WM->predictFinalAgentPos();
00503 AngDeg angTo = ( posTurnTo - posPred ).getDirection();
00504 AngDeg ang = VecPosition::normalizeAngle( angTo - angBodyAgent );
00505 AngDeg angNeck = 0;
00506
00507 int iTurn = 0;
00508 while( fabs( ang ) > angWhenToTurn && iTurn < 5 )
00509 {
00510 iTurn++;
00511 WM->predictStateAfterTurn(
00512 WM->getAngleForTurn( ang, velAgent.getMagnitude() ),
00513 &posAgent,
00514 &velAgent,
00515 &angBodyAgent,
00516 &angNeck );
00517 ang = VecPosition::normalizeAngle( angTo - angBodyAgent );
00518 }
00519 Log.log( 509, "direct towards: %d turns", iTurn );
00520 posAgent = (pos ==NULL)?WM->getAgentGlobalPosition ():*pos;
00521 velAgent = (vel ==NULL)?WM->getAgentGlobalVelocity ():*vel;
00522 angBodyAgent = (angBody==NULL)?WM->getAgentGlobalBodyAngle():*angBody;
00523
00524 switch( iTurn )
00525 {
00526 case 0: cerr << "direct towards: 0 turns" ;
00527 return SoccerCommand( CMD_ILLEGAL );
00528 case 1:
00529 case 2: return turnBodyToPoint( posTurnTo, 2 );
00530 default: return dashToPoint(
00531 (pos==NULL)?WM->getAgentGlobalPosition ():*pos );
00532 }
00533 }
00534
00571 SoccerCommand BasicPlayer::moveToPos( VecPosition posTo, AngDeg angWhenToTurn,
00572 double dDistBack, bool bMoveBack, int iCycles )
00573 {
00574
00575
00576
00577 VecPosition posAgent = WM->getAgentGlobalPosition();
00578 VecPosition posPred = WM->predictFinalAgentPos();
00579
00580 AngDeg angBody = WM->getAgentGlobalBodyAngle();
00581 AngDeg angTo = ( posTo - posPred ).getDirection();
00582 angTo = VecPosition::normalizeAngle( angTo - angBody );
00583 AngDeg angBackTo = VecPosition::normalizeAngle( angTo + 180 );
00584
00585 double dDist = posAgent.getDistanceTo( posTo );
00586
00587 Log.log( 509, "moveToPos (%f,%f): body %f to %f diff %f now %f when %f",
00588 posTo.getX(), posTo.getY(), angBody,
00589 ( posTo - posPred ).getDirection(), angTo,
00590 ( posTo - WM->predictAgentPos( 1, 0 )).getDirection(),
00591 angWhenToTurn );
00592 if( bMoveBack )
00593 {
00594 if( fabs( angBackTo ) < angWhenToTurn )
00595 return dashToPoint( posTo, iCycles );
00596 else
00597 return turnBackToPoint( posTo );
00598 }
00599 else if( fabs( angTo ) < angWhenToTurn ||
00600 (fabs( angBackTo ) < angWhenToTurn && dDist < dDistBack ) )
00601 return dashToPoint( posTo, iCycles );
00602 else
00603 return directTowards( posTo, angWhenToTurn );
00604
00605 }
00606
00607
00615 SoccerCommand BasicPlayer::collideWithBall( )
00616 {
00617 SoccerCommand soc( CMD_ILLEGAL );
00618 if( WM->getRelativeDistance( OBJECT_BALL ) >
00619 WM->getBallSpeed() + SS->getPlayerSpeedMax() )
00620 return soc;
00621
00622 VecPosition posBallPred = WM->predictPosAfterNrCycles( OBJECT_BALL, 1 );
00623
00624
00625 soc = turnBodyToPoint( WM->getAgentGlobalPosition() +
00626 VecPosition( 1, 0, POLAR ) );
00627 VecPosition posAgentPred = WM->predictAgentPosAfterCommand( soc );
00628 if( posAgentPred.getDistanceTo( posBallPred ) <
00629 SS->getBallSize() + SS->getPlayerSize() )
00630 {
00631 Log.log( 511, "can collide with ball by turning" );
00632 return soc;
00633 }
00634
00635 soc = dashToPoint( posBallPred, 1 );
00636 posAgentPred = WM->predictAgentPosAfterCommand( soc );
00637 if( posAgentPred.getDistanceTo( posBallPred ) <
00638 SS->getBallSize() + SS->getPlayerSize() )
00639 {
00640 Log.log( 511, "can collide with ball by dashing %f", soc.dPower );
00641 return soc;
00642 }
00643
00644 return SoccerCommand( CMD_ILLEGAL );
00645 }
00710 SoccerCommand BasicPlayer::interceptClose( )
00711 {
00712 FeatureT feature_type = FEATURE_INTERCEPT_CLOSE;
00713 if( WM->isFeatureRelevant( feature_type ) )
00714 return WM->getFeature( feature_type ).getCommand();
00715
00716 SoccerCommand soc, socDash1, socFinal, socCollide, socTurn(CMD_ILLEGAL);
00717 double dPower, dDist;
00718 AngDeg ang, ang2;
00719 VecPosition s1, s2;
00720 bool bReady = false;
00721
00722
00723 dDist = 3*SS->getPlayerSpeedMax()
00724 + (1.0 + SS->getBallDecay())*SS->getBallSpeedMax()
00725 + SS->getMaximalKickDist();
00726 if( WM->getRelativeDistance( OBJECT_BALL ) > dDist )
00727 {
00728 bReady = true;
00729 socFinal = SoccerCommand( CMD_ILLEGAL );
00730 }
00731
00732 socCollide = collideWithBall( );
00733
00734 VecPosition posAgent = WM->getAgentGlobalPosition( );
00735 VecPosition posPred = WM->predictAgentPos( 1, 0 ), posDash1;
00736 VecPosition posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 1 );
00737 VecPosition velMe = WM->getAgentGlobalVelocity( );
00738 Stamina sta = WM->getAgentStamina( );
00739 AngDeg angBody = WM->getAgentGlobalBodyAngle( ), angTurn, angNeck=0;
00740 double dDesBody = 0.0;
00741
00742
00743
00744 if( posAgent.getX() > PENALTY_X - 5.0 )
00745 dDesBody = (WM->getPosOpponentGoal()-posAgent).getDirection();
00746
00747
00748 double dDistOpp;
00749 ObjectT objOpp = WM->getClosestInSetTo( OBJECT_SET_OPPONENTS,
00750 WM->getAgentObjectType(), &dDistOpp, PS->getPlayerConfThr() );
00751 angTurn =VecPosition::normalizeAngle(dDesBody-WM->getAgentGlobalBodyAngle());
00752
00753
00754 posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 1 );
00755 VecPosition posPred1 = WM->predictAgentPos( 1, 0 );
00756 double dDist1 = posPred1.getDistanceTo( posBall );
00757 posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 2 );
00758 VecPosition posPred2 = WM->predictAgentPos( 2, 0 );
00759 double dDist2 = posPred2.getDistanceTo( posBall );
00760 posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 3 );
00761 VecPosition posPred3 = WM->predictAgentPos( 3, 0 );
00762 double dDist3 = posPred3.getDistanceTo( posBall );
00763 Log.log( 508, "dist 1: %f, 2: %f 3: %f, 0.6: %f", dDist1, dDist2, dDist3,
00764 0.7*SS->getMaximalKickDist() );
00765
00766 AngDeg angThreshold = 25;
00767 bool bOppClose = ( objOpp != OBJECT_ILLEGAL && dDistOpp < 3.0 ) ;
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778 posAgent = WM->getAgentGlobalPosition( );
00779 posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 1 );
00780 angBody = WM->getAgentGlobalBodyAngle();
00781 velMe = WM->getAgentGlobalVelocity( );
00782 sta = WM->getAgentStamina( );
00783 Line line = Line::makeLineFromPositionAndAngle(posPred1,angBody);
00784 dDist = SS->getPlayerSize()+SS->getBallSize()+SS->getKickableMargin()/6;
00785 int iSol = line.getCircleIntersectionPoints(
00786 Circle(posBall,dDist), &s1, &s2);
00787 if (iSol > 0)
00788 {
00789 if (iSol == 2)
00790 {
00791 ang = VecPosition::normalizeAngle((posBall - s1).getDirection() -angBody);
00792 ang2= VecPosition::normalizeAngle((posBall - s2).getDirection() -angBody);
00793
00794 if( s2.getX() > s1.getX() )
00795 s1 = s2;
00796 }
00797
00798
00799
00800
00801
00802
00803 dPower = WM->getPowerForDash(s1-posAgent, angBody, velMe,sta.getEffort() );
00804 posDash1 = WM->predictAgentPos( 1, (int)dPower);
00805 if ( posDash1.getDistanceTo( posBall ) < 0.95*SS->getMaximalKickDist() )
00806 {
00807 Log.log( 508, "dash 1x possible at s1" );
00808 socDash1 = SoccerCommand( CMD_DASH, dPower );
00809 }
00810 else
00811 {
00812 dPower=WM->getPowerForDash(s2-posAgent, angBody, velMe,sta.getEffort() );
00813 posDash1 = WM->predictAgentPos( 1, (int)dPower);
00814 if ( posDash1.getDistanceTo( posBall ) < 0.95*SS->getMaximalKickDist() )
00815 {
00816 Log.log( 508, "dash 1x possible at s2" );
00817 socDash1 = SoccerCommand( CMD_DASH, dPower );
00818 }
00819 }
00820 }
00821
00822
00823
00824
00825 if( socDash1.commandType == CMD_ILLEGAL )
00826 {
00827 soc = dashToPoint( posBall );
00828 WM->predictAgentStateAfterCommand(soc,&posDash1,&velMe,
00829 &angBody,&ang,&sta );
00830 if ( posDash1.getDistanceTo( posBall ) < 0.95*SS->getMaximalKickDist() )
00831 {
00832 Log.log( 508, "dash 1x possible (special)" );
00833 socDash1 = soc;
00834 }
00835 }
00836
00837 if( bReady != true )
00838 {
00839 if( bOppClose && ! socDash1.isIllegal() )
00840 {
00841 Log.log( 508, "do dash 1x, opponent close" );
00842 WM->logCircle( 508, posDash1, SS->getMaximalKickDist(), true );
00843 socFinal = socDash1;
00844 }
00845 else
00846 {
00847 soc = turnBodyToPoint( posPred1 + VecPosition(1,dDesBody, POLAR), 1 );
00848 WM->predictAgentStateAfterCommand(soc, &posPred, &velMe,
00849 &angBody, &ang, &sta);
00850 posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 1 );
00851 if( posPred.getDistanceTo( posBall ) < 0.8*SS->getMaximalKickDist() )
00852 {
00853 socTurn = soc;
00854 ang = VecPosition::normalizeAngle(dDesBody-angBody);
00855 if( fabs(ang) < angThreshold )
00856 {
00857 socFinal = soc;
00858 Log.log( 508, "turn 1x, dist %f, angle %f, opp %f",
00859 dDist1, angTurn, dDistOpp );
00860 WM->logCircle( 508, posPred1, SS->getMaximalKickDist(), true );
00861 }
00862
00863 }
00864 if( socFinal.isIllegal() )
00865 {
00866 ang = VecPosition::normalizeAngle(dDesBody-angBody);
00867 WM->predictStateAfterTurn(
00868 WM->getAngleForTurn(ang,velMe.getMagnitude()),
00869 &posPred, &velMe, &angBody, &angNeck,
00870 WM->getAgentObjectType(),
00871 &sta );
00872 posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 2 );
00873 if( posPred.getDistanceTo( posBall ) < 0.8*SS->getMaximalKickDist() )
00874 {
00875 socTurn = soc;
00876 ang = VecPosition::normalizeAngle(dDesBody-angBody);
00877 if( fabs(ang) < angThreshold )
00878 {
00879 Log.log( 508, "turn 2x, dist %f, angle %f, opp %f",
00880 dDist2, angTurn, dDistOpp );
00881 WM->logCircle( 508, posPred2, SS->getMaximalKickDist(), true );
00882 socFinal = soc;
00883 }
00884 }
00885 }
00886 if( socFinal.isIllegal() && ! socCollide.isIllegal() &&
00887 fabs( angTurn ) > angThreshold )
00888 {
00889 Log.log( 508, "collide with ball on purpose" );
00890 posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 1 );
00891 WM->logCircle( 508, posBall, SS->getMaximalKickDist(), true );
00892 socFinal = socCollide;
00893 }
00894 if( socFinal.isIllegal() && fabs( angTurn ) > angThreshold )
00895 {
00896 posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 2 );
00897 soc = dashToPoint( posAgent );
00898 WM->predictAgentStateAfterCommand(soc,
00899 &posPred,&velMe,&angBody,&ang,&sta );
00900 if( posPred.getDistanceTo( posBall ) < 0.8*SS->getMaximalKickDist() )
00901 {
00902 Log.log( 508, "dash 1x (stop), turn 1x, dist %f, angle %f, opp %f",
00903 dDist2, angTurn, dDistOpp );
00904 WM->logCircle( 508, posPred, SS->getMaximalKickDist(), true );
00905 socFinal = soc;
00906 }
00907 }
00908 if( socFinal.isIllegal() && ! socTurn.isIllegal() )
00909 {
00910 Log.log( 508, "can do turn" );
00911 WM->logCircle( 508, posPred1, SS->getMaximalKickDist(), true );
00912 socFinal = socTurn;
00913 }
00914 if( socFinal.isIllegal() && ! socDash1.isIllegal() )
00915 {
00916 Log.log( 508, "do dash 1x" );
00917 WM->logCircle( 508, posDash1, SS->getMaximalKickDist(), true );
00918 socFinal = socDash1;
00919 }
00920 }
00921
00922 }
00923
00924
00925 else if( fabs( angTurn ) > angThreshold && !bOppClose &&
00926 dDist1 < 0.7*SS->getMaximalKickDist() )
00927 {
00928 soc = turnBodyToPoint( posPred1 + VecPosition(1,dDesBody, POLAR), 1 );
00929 Log.log( 508, "turn 1x, dist %f, angle %f, opp %f",
00930 dDist1, angTurn, dDistOpp );
00931 WM->logCircle( 508, posPred1, SS->getMaximalKickDist(), true );
00932 socFinal = soc;
00933 }
00934 else if(
00935 !bOppClose &&
00936 dDist2 < 0.7*SS->getMaximalKickDist() )
00937 {
00938 soc = turnBodyToPoint( posPred2 + VecPosition(1,dDesBody, POLAR), 2 );
00939 Log.log( 508, "turn 2x, dist %f, angle %f, opp %f",
00940 dDist2, angTurn, dDistOpp );
00941 WM->logCircle( 508, posPred2, SS->getMaximalKickDist(), true );
00942 socFinal = soc;
00943 }
00944
00945
00946 else if( socCollide.commandType != CMD_ILLEGAL &&
00947 fabs( angTurn ) > angThreshold )
00948 {
00949 Log.log( 508, "collide with ball on purpose" );
00950 WM->logCircle( 508, posDash1, SS->getMaximalKickDist(), true );
00951 socFinal = socCollide;
00952 }
00953 else if( socDash1.commandType != CMD_ILLEGAL )
00954 {
00955 Log.log( 508, "do dash 1x" );
00956 WM->logCircle( 508, posDash1, SS->getMaximalKickDist(), true );
00957 socFinal = socDash1;
00958 }
00959
00960
00961
00962 WM->setFeature( feature_type,
00963 Feature( WM->getTimeLastSeeMessage(),
00964 WM->getTimeLastSenseMessage(),
00965 WM->getTimeLastHearMessage(),
00966 OBJECT_ILLEGAL,
00967 -1,
00968 socFinal ) );
00969 return socFinal;
00970 }
00971
01008 SoccerCommand BasicPlayer::interceptCloseGoalie( )
01009 {
01010 SoccerCommand soc;
01011 double dPower, dDist;
01012 AngDeg ang;
01013 VecPosition posClosestToBall;
01014
01015
01016 VecPosition posPred = WM->predictAgentPos( 1, 0 );
01017 VecPosition posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 1 );
01018 VecPosition velMe = WM->getAgentGlobalVelocity( );
01019 Stamina sta = WM->getAgentStamina( );
01020 AngDeg angBody = WM->getAgentGlobalBodyAngle( );
01021 Line lineGoalie=Line::makeLineFromPositionAndAngle(posPred,angBody);
01022
01023
01024
01025 dDist =SS->getBallSpeedMax()+SS->getPlayerSpeedMax()+SS->getCatchableAreaL();
01026 if( WM->getRelativeDistance( OBJECT_BALL ) < dDist )
01027 {
01028 posClosestToBall = lineGoalie.getPointOnLineClosestTo( posBall );
01029 dPower = WM->getPowerForDash(
01030 posClosestToBall-posPred,
01031 angBody,
01032 velMe,
01033 sta.getEffort() );
01034 posPred = WM->predictAgentPos( 1, (int)dPower);
01035 if ( posPred.getDistanceTo( posBall ) < SS->getCatchableAreaL() )
01036 return SoccerCommand( CMD_DASH, dPower );
01037 }
01038
01039
01040
01041
01042
01043 dDist = SS->getBallSpeedMax()*(1.0+SS->getBallDecay())
01044 + 2*SS->getPlayerSpeedMax()
01045 + SS->getCatchableAreaL();
01046 if( WM->getRelativeDistance( OBJECT_BALL ) < dDist )
01047 {
01048
01049
01050
01051
01052
01053
01054 posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 2 );
01055 soc = dashToPoint( posBall );
01056 WM->predictAgentStateAfterCommand(soc,&posPred,&velMe,&angBody,&ang,&sta );
01057 dPower=WM->getPowerForDash(posBall-posPred,angBody,velMe,sta.getEffort());
01058 WM->predictStateAfterDash( dPower, &posPred, &velMe, &sta, angBody,
01059 WM->getAgentObjectType() );
01060 if( posPred.getDistanceTo(posBall) < SS->getCatchableAreaL() )
01061 return soc;
01062
01063
01064 posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 2 );
01065 posPred = WM->predictAgentPos( 2, 0 );
01066 ang = (posBall - posPred).getDirection();
01067 ang = VecPosition::normalizeAngle( ang - angBody );
01068 if (fabs( ang ) > PS->getPlayerWhenToTurnAngle() )
01069 {
01070 soc = turnBodyToPoint( posBall, 2 );
01071 WM->predictAgentStateAfterCommand(soc,&posPred,&velMe,&angBody,&ang,&sta
01072 );
01073 dPower=WM->getPowerForDash(posBall-posPred, angBody,
01074 velMe, sta.getEffort());
01075 WM->predictStateAfterDash( dPower, &posPred, &velMe, &sta, angBody);
01076 if( posPred.getDistanceTo(posBall) < SS->getCatchableAreaL() )
01077 return soc;
01078 }
01079 }
01080
01081
01082 return SoccerCommand( CMD_ILLEGAL );
01083 }
01084
01120 SoccerCommand BasicPlayer::kickTo( VecPosition posTarget, double dEndSpeed )
01121 {
01122 VecPosition posBall = WM->getBallPos();
01123 VecPosition velBall = WM->getGlobalVelocity(OBJECT_BALL);
01124 VecPosition posTraj = posTarget - posBall;
01125 VecPosition posAgent = WM->getAgentGlobalPosition();
01126 VecPosition velDes = VecPosition(
01127 WM->getKickSpeedToTravel( posTraj.getMagnitude(), dEndSpeed ),
01128 posTraj.getDirection(),
01129 POLAR );
01130 double dPower;
01131 AngDeg angActual;
01132
01133 if( WM->predictAgentPos(1, 0 ).getDistanceTo( posBall + velDes ) <
01134 SS->getBallSize() + SS->getPlayerSize() )
01135 {
01136 Line line = Line::makeLineFromTwoPoints( posBall, posBall + velDes );
01137 VecPosition posBodyProj = line.getPointOnLineClosestTo( posAgent );
01138 double dDist = posBall.getDistanceTo( posBodyProj );
01139 if( velDes.getMagnitude() < dDist )
01140 dDist -= SS->getBallSize() + SS->getPlayerSize();
01141 else
01142 dDist += SS->getBallSize() + SS->getPlayerSize();
01143 Log.log( 101, "kick results in collision, change velDes from (%f,%f)",
01144 velDes.getX(), velDes.getY() );
01145 velDes.setVecPosition( dDist, velDes.getDirection(), POLAR );
01146 }
01147
01148 Log.log( 101, "ball (%f,%f), agent (%f,%f), to (%f,%f) ang %f %f" ,
01149 WM->getBallPos().getX(), WM->getBallPos().getY(),
01150 WM->getAgentGlobalPosition().getX(),
01151 WM->getAgentGlobalPosition().getY(),
01152 posTarget.getX(), posTarget.getY(),
01153 WM->getAgentGlobalBodyAngle(),
01154 WM->getAgentGlobalNeckAngle() );
01155 Log.log( 101, "relpos body (%f,%f), vel. ball:(%f,%f) dist: %f (%f,%f,%f)" ,
01156 WM->getRelativeDistance( OBJECT_BALL ),
01157 WM->getRelativeAngle( OBJECT_BALL, true ),
01158 velBall.getX(), velBall.getY(),
01159 SS->getMaximalKickDist(), SS->getPlayerSize(), SS->getBallSize(),
01160 SS->getKickableMargin() );
01161
01162
01163 double dDistOpp;
01164 ObjectT objOpp = WM->getClosestInSetTo( OBJECT_SET_OPPONENTS,
01165 OBJECT_BALL, &dDistOpp );
01166
01167 if( velDes.getMagnitude() > SS->getBallSpeedMax() )
01168 {
01169 dPower = SS->getMaxPower();
01170 double dSpeed = WM->getActualKickPowerRate() * dPower;
01171 double tmp = velBall.rotate(-velDes.getDirection()).getY();
01172 angActual = velDes.getDirection() - asinDeg( tmp / dSpeed );
01173 double dSpeedPred = (WM->getGlobalVelocity(OBJECT_BALL)+
01174 VecPosition(dSpeed,angActual, POLAR )
01175 ).getMagnitude();
01176
01177
01178 if( dSpeedPred > PS->getPlayerWhenToKick()*SS->getBallAccelMax() )
01179 {
01180 Log.log( 101, "pos (%f,%f) too far, but can acc ball good to %f k=%f,%f",
01181 velDes.getX(), velDes.getY(), dSpeedPred, dSpeed, tmp );
01182 return accelerateBallToVelocity( velDes );
01183 }
01184 else if( WM->getActualKickPowerRate() >
01185 PS->getPlayerWhenToKick() * SS->getKickPowerRate() )
01186 {
01187 Log.log( 101, "point too far, freeze ball" );
01188 return freezeBall();
01189 }
01190 else
01191 {
01192 Log.log( 101, "point too far, reposition ball (k_r = %f)",
01193 WM->getActualKickPowerRate()/(SS->getKickPowerRate()) );
01194 return kickBallCloseToBody( 0 );
01195 }
01196 }
01197 else
01198 {
01199 VecPosition accBallDes = velDes - velBall;
01200 dPower = WM->getKickPowerForSpeed(accBallDes.getMagnitude());
01201 if( dPower <= 1.05*SS->getMaxPower() ||
01202 (dDistOpp < 2.0 && dPower <= 1.30*SS->getMaxPower() ) )
01203 {
01204 Log.log( 101, "point good and can reach point %f", dPower );
01205 return accelerateBallToVelocity( velDes );
01206 }
01207 else
01208 {
01209 Log.log( 101, "point good, but reposition ball since need %f",dPower );
01210 SoccerCommand soc = kickBallCloseToBody( 0 );
01211 VecPosition posPredBall;
01212 WM->predictBallInfoAfterCommand( soc, &posPredBall );
01213 dDistOpp = posPredBall.getDistanceTo( WM->getGlobalPosition( objOpp ) );
01214 return soc;
01215 }
01216 }
01217 }
01218
01219
01251
01252
01253
01254
01255
01256
01257
01258
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 SoccerCommand BasicPlayer::turnWithBallTo( AngDeg ang, AngDeg, double )
01299 {
01300
01301
01302
01303
01304
01305
01306
01307
01308 VecPosition posAgent= WM->getAgentGlobalPosition();
01309 VecPosition posBall = WM->getBallPos();
01310 AngDeg angBody = WM->getAgentGlobalBodyAngle();
01311 double dDist;
01312 ObjectT objOpp = WM->getClosestInSetTo( OBJECT_SET_OPPONENTS,
01313 WM->getAgentObjectType(), &dDist );
01314 VecPosition posOpp = WM->getGlobalPosition( objOpp );
01315 SoccerCommand soc = turnBodyToPoint(posAgent+VecPosition(1.0,ang,POLAR));
01316
01317 if( objOpp != OBJECT_ILLEGAL && dDist < 2.5 )
01318 {
01319 AngDeg angBall = (posBall-posAgent).getDirection();
01320 AngDeg angOpp = (posOpp -posAgent).getDirection();
01321 if( fabs( VecPosition::normalizeAngle( angBall - angOpp ) ) < 90 )
01322 {
01323 ang = angOpp + 180;
01324 Log.log( 101, "turnWithBall: kick ball away from opp at ang %f", angOpp);
01325 return kickBallCloseToBody( VecPosition::normalizeAngle( ang-angBody ));
01326 }
01327 }
01328
01329 VecPosition posAgentPred = WM->predictAgentPosAfterCommand( soc );
01330 VecPosition posBallPred = WM->predictPosAfterNrCycles( OBJECT_BALL, 1 );
01331 if( posAgentPred.getDistanceTo( posBallPred ) < 0.8*SS->getMaximalKickDist()
01332 ||
01333 ( posAgentPred.getDistanceTo(posBallPred) < 0.9*SS->getMaximalKickDist()
01334 && WM->getBallSpeed() < 0.1 ))
01335 {
01336 Log.log( 101, "turnWithBall: turn since ball will be kickable in t+1" );
01337 return soc;
01338 }
01339
01340 posAgentPred = WM->predictPosAfterNrCycles( WM->getAgentObjectType(), 1, 0 );
01341
01342
01343
01344
01345
01346
01347
01348
01349 SoccerCommand socCollide = collideWithBall( );
01350 if( ! socCollide.isIllegal( ) )
01351 {
01352 Log.log( 101, "turnWithBall: collide with ball" );
01353 return socCollide;
01354 }
01355 else if( posAgentPred.getDistanceTo(posBall) < 0.8*SS->getMaximalKickDist()
01356 &&
01357 WM->getBallSpeed() > 0.1 )
01358 {
01359 Log.log( 101, "turnWithBall: freeze ball" );
01360 return freezeBall();
01361 }
01362 else
01363 {
01364 Log.log( 101, "turnWithBall: kick ball close to desired turnangle %f",ang);
01365 return kickBallCloseToBody( VecPosition::normalizeAngle( ang - angBody ) );
01366 }
01367 }
01368
01369
01370
01371
01427 SoccerCommand BasicPlayer::moveToPosAlongLine( VecPosition pos, AngDeg ang,
01428 double dDistThr, int iSign, AngDeg angThr, AngDeg angCorr )
01429 {
01430 Line l = Line::makeLineFromPositionAndAngle( pos, ang );
01431 VecPosition posBall = WM->getBallPos();
01432 VecPosition posAgent = WM->getAgentGlobalPosition();
01433 AngDeg angBody = WM->getAgentGlobalBodyAngle();
01434 VecPosition posProj = l.getPointOnLineClosestTo( posAgent );
01435 double dDist = posAgent.getDistanceTo( posProj );
01436 double dDiff = pos.getDistanceTo ( posProj );
01437
01438
01439 if( dDist > dDistThr )
01440 {
01441
01442 VecPosition posOrg(0,0);
01443 Line m = Line::makeLineFromTwoPoints( posOrg, posAgent );
01444 VecPosition posIntersect = l.getIntersection( m );
01445 int iSide;
01446 if( posAgent.getDistanceTo(posOrg) < posIntersect.getDistanceTo( posOrg ) )
01447 iSide = +1;
01448 else
01449 iSide = -1;
01450
01451
01452 ang = ang + iSign * iSide * angCorr;
01453 }
01454
01455 Log.log( 553, "y difference to defend point %f", dDiff );
01456
01457 if( fabs( VecPosition::normalizeAngle( ang - angBody ) ) > angThr )
01458 {
01459 Log.log( 553, "angle differs too much body = %f, des = %f", angBody, ang );
01460 return turnBodyToPoint( posAgent + VecPosition( 1.0, ang, POLAR ) );
01461 }
01462 else if( posBall.getDistanceTo( OBJECT_BALL ) < 60 && dDiff > 0.6 )
01463 return dashToPoint( pos );
01464 else if( posBall.getDistanceTo( OBJECT_BALL ) < 30 && dDiff > 0.3 )
01465 return dashToPoint( pos );
01466 else
01467 return SoccerCommand( CMD_ILLEGAL );
01468 }
01469
01470
01471
01472
01482 SoccerCommand BasicPlayer::intercept( bool isGoalie )
01483 {
01484 SoccerCommand soc = (isGoalie)? interceptCloseGoalie():interceptClose(),soc2;
01485 VecPosition pos = WM->getAgentGlobalPosition();
01486
01487 if( soc.commandType != CMD_ILLEGAL
01488 && isGoalie )
01489 {
01490 Log.log( 502, "intercept in two cycles" );
01491 return soc;
01492 }
01493 Log.log( 608, "start intercept, obj %d", WM->getAgentObjectType() );
01494 soc2 = WM->predictCommandToInterceptBall( WM->getAgentObjectType(), soc );
01495 if( soc2.isIllegal() )
01496 return turnBodyToPoint( pos + VecPosition( 1.0, 0, POLAR ) );
01497 return soc2;
01498 }
01499
01542 SoccerCommand BasicPlayer::dribble( AngDeg ang, DribbleT dribbleT )
01543 {
01544 double dLength;
01545 AngDeg angBody = WM->getAgentGlobalBodyAngle();
01546 VecPosition posAgent = WM->getAgentGlobalPosition();
01547 SoccerCommand soc;
01548
01549
01550 AngDeg angDiff = VecPosition::normalizeAngle( ang - angBody );
01551 if( fabs( angDiff ) > PS->getDribbleAngThr() )
01552 return turnWithBallTo( ang, PS->getTurnWithBallAngThr(),
01553 PS->getTurnWithBallFreezeThr() );
01554
01555 switch( dribbleT )
01556 {
01557 case DRIBBLE_WITHBALL:
01558 dLength = 4.0;
01559 break;
01560 case DRIBBLE_SLOW:
01561 dLength = 5.0;
01562 break;
01563 case DRIBBLE_FAST:
01564 dLength = 10.0;
01565 break;
01566 default:
01567 dLength = 0.0;
01568 break;
01569 }
01570
01571
01572 VecPosition posDribble = posAgent + VecPosition( dLength, angBody, POLAR );
01573
01574
01575
01576 if( fabs( posDribble.getY() ) > PITCH_WIDTH/2.0 - 3.0 )
01577 posDribble.setY( (PITCH_WIDTH/2.0 - 3.0)*sign(posDribble.getY()) );
01578 if( fabs( posDribble.getX() ) > PITCH_LENGTH/2.0 - 3.0 )
01579 posDribble.setX( (PITCH_LENGTH/2.0 - 3.0)*sign(posDribble.getX()) );
01580
01581 soc = kickTo( posDribble, 0.5 );
01582
01583
01584
01585 SoccerCommand soc2 = intercept( false );
01586 if( soc.dPower < 7 && WM->isCollisionAfterCommand( soc2 ) == false )
01587 {
01588 Log.log( 560, "wanted to dribble, but only small kick %f", soc.dPower );
01589 return soc2;
01590 }
01591 return soc;
01592 }
01593
01603 SoccerCommand BasicPlayer::directPass( VecPosition pos, PassT passType)
01604 {
01605 if( passType == PASS_NORMAL )
01606 return kickTo( pos, PS->getPassEndSpeed() );
01607 else if( passType == PASS_FAST )
01608 return kickTo( pos, PS->getFastPassEndSpeed() );
01609 else
01610 return SoccerCommand( CMD_ILLEGAL );
01611 }
01612
01629 SoccerCommand BasicPlayer::leadingPass( ObjectT o, double dDist, DirectionT dir)
01630 {
01631 VecPosition posShoot = WM->getGlobalPosition( o );
01632 if( dir != DIR_ILLEGAL && dir != DIR_CENTER )
01633 posShoot+=VecPosition(dDist,SoccerTypes::getAngleFromDirection(dir),POLAR);
01634 return kickTo( posShoot, PS->getPassEndSpeed() );
01635 }
01636
01667 SoccerCommand BasicPlayer::throughPass( ObjectT o, VecPosition posEnd,
01668 AngDeg *angMax )
01669 {
01670 VecPosition posShoot = getThroughPassShootingPoint( o, posEnd, angMax );
01671 double dEnd = getEndSpeedForPass( o, posShoot );
01672
01673 return kickTo( posShoot, dEnd );
01674 }
01675
01757 SoccerCommand BasicPlayer::outplayOpponent( ObjectT o, VecPosition pos,
01758 VecPosition *posTo )
01759 {
01760
01761
01762 VecPosition posAgent = WM->getAgentGlobalPosition();
01763 AngDeg angBody = WM->getAgentGlobalBodyAngle();
01764
01765 double dMaxDist = 12.0;
01766 if( posAgent.getX() > PENALTY_X - 6.0 )
01767 dMaxDist = 10.0;
01768
01769 AngDeg ang = (pos - posAgent).getDirection();
01770
01771 AngDeg angTmp = VecPosition::normalizeAngle( ang - angBody ) ;
01772 if( fabs( angTmp ) > PS->getDribbleAngThr() )
01773 return turnWithBallTo( ang, PS->getTurnWithBallAngThr(),
01774 PS->getTurnWithBallFreezeThr() );
01775 ang = WM->getAgentGlobalBodyAngle();
01776 Line l = Line::makeLineFromPositionAndAngle(posAgent,ang);
01777 VecPosition posObj = WM->getGlobalPosition( o );
01778 VecPosition posProj = l.getPointOnLineClosestTo( posObj );
01779 double dDistOpp = posProj.getDistanceTo( posObj );
01780 double dDistAgent = posProj.getDistanceTo( posAgent );
01781 VecPosition posShoot;
01782
01783
01784
01785
01786
01787 double dCalcDist;
01788 if( o != OBJECT_ILLEGAL )
01789 {
01790 dCalcDist = (dDistOpp*dDistOpp-dDistAgent*dDistAgent)/(2*dDistAgent);
01791 dCalcDist += dDistAgent;
01792 }
01793 else
01794 dCalcDist = dMaxDist;
01795
01796 Log.log( 552, "outplay opponent %d, calc: %f, opp: %f, agent: %f",
01797 SoccerTypes::getIndex( o ) + 1, dCalcDist, dDistOpp, dDistAgent );
01798 Log.log( 560, "outplay opponent %d, calc: %f, opp: %f, agent: %f",
01799 SoccerTypes::getIndex( o ) + 1, dCalcDist, dDistOpp, dDistAgent );
01800
01801 if( dCalcDist > 7.0 )
01802 {
01803 dCalcDist = min( posAgent.getDistanceTo( pos ), dCalcDist - 2.5 );
01804 dCalcDist = min( dMaxDist, dCalcDist );
01805 posShoot = posAgent + VecPosition( dCalcDist, ang, POLAR );
01806 }
01807 else if( dDistAgent < dDistOpp - 0.3 )
01808 {
01809 dCalcDist = min( posAgent.getDistanceTo( pos ), dMaxDist );
01810 posShoot = posAgent + VecPosition( dCalcDist, ang, POLAR );
01811 }
01812 else
01813 return SoccerCommand( CMD_ILLEGAL );
01814
01815 if( posShoot.getDistanceTo( WM->getAgentGlobalPosition() ) < 2.5 )
01816 {
01817 Log.log( 552, "calculated point too close" );
01818 Log.log( 560, "calculated point too close (%f,%f)", posShoot.getX(),
01819 posShoot.getY() );
01820 return SoccerCommand( CMD_ILLEGAL );
01821 }
01822 else if( WM->getNrInSetInCone( OBJECT_SET_OPPONENTS,PS->getConeWidth(),
01823 posAgent, posShoot ) != 0 )
01824 {
01825 Log.log( 552, "outplay: is opponent in cone" );
01826 Log.log( 560, "outplay: is opponent in cone (%f,%f)", posShoot.getX(),
01827 posShoot.getY() );
01828 return SoccerCommand( CMD_ILLEGAL );
01829 }
01830 else if( WM->getNrInSetInCircle( OBJECT_SET_OPPONENTS,
01831 Circle( posShoot, posShoot.getDistanceTo( posAgent ) ) ) > 1 )
01832 {
01833 Log.log( 552, "outplay: nr of opp in circle > 1" );
01834 Log.log( 560, "outplay: nr of opp in circle > 1" );
01835 return SoccerCommand( CMD_ILLEGAL );
01836 }
01837 else if( WM->getCurrentTime() - WM->getTimeGlobalAngles(o) < 3 )
01838 {
01839 double dDistOpp = posShoot.getDistanceTo( posObj ) ;
01840 if( fabs( VecPosition::normalizeAngle( (posShoot - posObj).getDirection() -
01841 WM->getGlobalBodyAngle(o) ) ) < 30 )
01842 dDistOpp -= 1.0;
01843 if( dDistOpp < posAgent.getDistanceTo( posShoot ) )
01844 {
01845 Log.log( 560, "outplay: opponent closer" );
01846 return SoccerCommand( CMD_ILLEGAL );
01847 }
01848 }
01849
01850
01851
01852 if( posTo != NULL )
01853 *posTo = posShoot;
01854 return kickTo( posShoot, 0.5 );
01855 }
01856
01886 SoccerCommand BasicPlayer::clearBall( ClearBallT type, SideT s,AngDeg *angMax )
01887 {
01888 VecPosition posBall = WM->getBallPos();
01889 VecPosition posLeft, posRight;
01890 double clearDist = PS->getClearBallDist();
01891
01892 double dPitchY = PITCH_WIDTH / 2.0;
01893 if( type == CLEAR_BALL_DEFENSIVE )
01894 {
01895 posLeft.setVecPosition ( 0, - dPitchY + clearDist );
01896 posRight.setVecPosition( 0, + dPitchY - clearDist );
01897 }
01898 else if( type == CLEAR_BALL_OFFENSIVE )
01899 {
01900 posLeft.setVecPosition ( PENALTY_X - clearDist, - dPitchY + clearDist );
01901 posRight.setVecPosition( PENALTY_X - clearDist, + dPitchY - clearDist );
01902 }
01903 else if( type == CLEAR_BALL_OFFENSIVE_SIDE )
01904 {
01905 posLeft.setVecPosition ( PENALTY_X - clearDist, - dPitchY + 8 );
01906 posRight.setVecPosition( PENALTY_X - clearDist, + dPitchY - 8 );
01907 }
01908 else if( type == CLEAR_BALL_GOAL && posBall.getY() > 0 )
01909 {
01910 posLeft.setVecPosition ( max(PENALTY_X - 2.0, posBall.getX()-10), 0.0 );
01911 posRight.setVecPosition( PITCH_LENGTH/2.0 - 5.0, 0.0 );
01912 }
01913 else if( type == CLEAR_BALL_GOAL && posBall.getY() < 0 )
01914 {
01915 posLeft.setVecPosition ( PITCH_LENGTH/2.0 - 5.0, 0.0 );
01916 posRight.setVecPosition( max(PENALTY_X - 2.0, posBall.getX()-10), 0.0 );
01917 }
01918 else
01919 return SoccerCommand( CMD_ILLEGAL );
01920
01921 if( type != CLEAR_BALL_GOAL && s == SIDE_RIGHT )
01922 {
01923 if( type == CLEAR_BALL_OFFENSIVE_SIDE )
01924 posLeft.setY( 15.0 );
01925 else
01926 posLeft.setY ( 0.0 );
01927
01928 }
01929 else if( type != CLEAR_BALL_GOAL && s == SIDE_LEFT )
01930 {
01931 if( type == CLEAR_BALL_OFFENSIVE_SIDE )
01932 posRight.setY( -15.0 );
01933 else
01934 posRight.setY( 0.0 );
01935 }
01936
01937
01938
01939 AngDeg angLeft = (posLeft - posBall).getDirection();
01940 AngDeg angRight = (posRight - posBall).getDirection();
01941 double dDist;
01942 if( type != CLEAR_BALL_GOAL )
01943 dDist = PS->getClearBallOppMaxDist();
01944 else
01945 dDist = max( posBall.getDistanceTo(posLeft ),
01946 posBall.getDistanceTo(posRight) );
01947 AngDeg ang = WM->getDirectionOfWidestAngle( posBall, angLeft, angRight,
01948 angMax, dDist );
01949
01950 Line l1 = Line::makeLineFromPositionAndAngle( posBall, ang );
01951 Line l2 = Line::makeLineFromTwoPoints( posLeft, posRight );
01952 VecPosition posShoot = l1.getIntersection( l2 );
01953 Log.log( 560, "angLeft %f, right %f, best %f point (%f,%f)",
01954 angLeft, angRight, ang, posShoot.getX(), posShoot.getY() );
01955 if( type == CLEAR_BALL_GOAL )
01956 return kickTo( posShoot, SS->getBallSpeedMax() );
01957 else if( type == CLEAR_BALL_OFFENSIVE )
01958 return kickTo( posShoot, 0.25 );
01959 else if( type == CLEAR_BALL_OFFENSIVE_SIDE )
01960 {
01961 return kickTo( posShoot, (posBall.getX()>20) ? 1.2 : 2.7);
01962 }
01963 else
01964 return kickTo( posShoot, 0.5 );
01965 }
01966
02010 SoccerCommand BasicPlayer::mark( ObjectT o, double dDist, MarkT mark )
02011 {
02012 VecPosition posMark = getMarkingPosition( o, dDist, mark );
02013 VecPosition posAgent = WM->getAgentGlobalPosition();
02014 VecPosition posBall = WM->getGlobalPosition( OBJECT_BALL );
02015
02016
02017 if( o == OBJECT_BALL )
02018 {
02019 if( posMark.getDistanceTo( posAgent ) < 1.5 )
02020 return turnBodyToObject( OBJECT_BALL );
02021 else
02022 return moveToPos( posMark, 30.0, 3.0, false );
02023 }
02024
02025 if( posAgent.getDistanceTo( posMark ) < 2.0 )
02026 {
02027 AngDeg angOpp = (WM->getGlobalPosition( o ) - posAgent).getDirection();
02028 AngDeg angBall = (posBall - posAgent).getDirection();
02029 if( isAngInInterval( angBall, angOpp,
02030 VecPosition::normalizeAngle( angOpp + 180 ) ) )
02031 angOpp += 80;
02032 else
02033 angOpp -= 80;
02034 angOpp = VecPosition::normalizeAngle( angOpp );
02035 Log.log( 513, "mark: turn body to ang %f", angOpp );
02036 return turnBodyToPoint( posAgent + VecPosition( 1.0, angOpp, POLAR ) );
02037 }
02038 Log.log( 513, "move to marking position" );
02039
02040 return moveToPos( posMark, 25, 3.0, false );
02041 }
02042
02043
02088 SoccerCommand BasicPlayer::defendGoalLine( double dDist )
02089 {
02090
02091 VecPosition posBall = WM->getBallPos();
02092 VecPosition posAgent = WM->getAgentGlobalPosition();
02093 VecPosition posGoal = WM->getPosOwnGoal( );
02094 VecPosition posCenter(sign(posGoal.getX())*(fabs(posGoal.getX())-dDist),0);
02095 Line lineGoal = Line::makeLineFromPositionAndAngle( posCenter, 90 );
02096
02097 VecPosition posGoalLeft ( posGoal.getX(), -SS->getGoalWidth()/2.0 );
02098 VecPosition posGoalRight( posGoal.getX(), SS->getGoalWidth()/2.0 );
02099 Line left = Line::makeLineFromTwoPoints( posBall, posGoalLeft );
02100 Line right = Line::makeLineFromTwoPoints( posBall, posGoalRight );
02101 posGoalLeft = left.getIntersection ( lineGoal );
02102 posGoalRight = right.getIntersection( lineGoal );
02103 double dDistLeft = posGoalLeft.getDistanceTo( posBall );
02104 double dDistRight = posGoalRight.getDistanceTo( posBall );
02105 double dDistLine = posGoalLeft.getDistanceTo( posGoalRight );
02106 VecPosition posDefend = posGoalLeft+
02107 VecPosition( 0, (dDistLeft/(dDistLeft+dDistRight))*dDistLine);
02108
02109 bool bBallInPen = WM->isInOwnPenaltyArea( posBall );
02110
02111
02112 if( fabs( posDefend.getY() ) > SS->getGoalWidth()/2.0 )
02113 posDefend.setY( sign(posDefend.getY())*SS->getGoalWidth()/2.0);
02114
02115
02116 double dDiff = ( bBallInPen == true ) ? 1.5 : 0.5;
02117 if( posDefend.getX() + dDiff < posAgent.getX() )
02118 {
02119 Log.log( 553, "move backwards to guard point" );
02120 return moveToPos( posDefend, 30, -1.0, true );
02121 }
02122 else if( posDefend.getX() - dDiff > posAgent.getX() )
02123 {
02124 Log.log( 553, "move forward to guard point" );
02125 return moveToPos( posDefend, 30, -1.0 );
02126 }
02127
02128
02129
02130 AngDeg angDes;
02131 if( fabs( posBall.getY() - posDefend.getY() ) > 0.5 )
02132 angDes = sign( posBall.getY() - posDefend.getY() )*90.0;
02133 else
02134 angDes = sign( WM->getAgentGlobalBodyAngle() )*90.0;
02135 int iSign = sign( WM->getGlobalVelocity( OBJECT_BALL ).getY() );
02136
02137
02138
02139
02140
02141 if( bBallInPen )
02142 {
02143 Log.log( 553, "move along line, with ball in penalty area x: %f ang %f",
02144 posDefend.getX(), angDes );
02145 return moveToPosAlongLine( posDefend, angDes, 3.0, iSign, 7.0, 12.0 );
02146 }
02147 else
02148 {
02149 Log.log( 553, "move along line, with ball out pen. area (%f,%f)(%f,%f) %f",
02150 WM->getAgentGlobalPosition().getX(),
02151 WM->getAgentGlobalPosition().getY(),
02152 posBall.getX(), posBall.getY(), WM->getConfidence( OBJECT_BALL) );
02153 Log.log( 553, "%s", WM->strLastSeeMessage );
02154 return moveToPosAlongLine( posDefend, angDes, 0.5, iSign, 2.0, 12.0 );
02155 }
02156 }
02157
02163 SoccerCommand BasicPlayer::interceptScoringAttempt( )
02164 {
02165 int iSide = 1;
02166 if( WM->isPenaltyUs() || WM->isPenaltyThem() )
02167 iSide = ( WM->getSide() == WM->getSidePenalty() ) ? 1 : -1;
02168
02169 SoccerCommand soc;
02170 VecPosition posAgent = WM->getAgentGlobalPosition();
02171 VecPosition posBall = WM->getBallPos();
02172 Line lineBall = Line::makeLineFromPositionAndAngle( posBall,
02173 WM->getBallDirection() );
02174 Line lineKeeper = Line::makeLineFromPositionAndAngle( posAgent, 90);
02175 bool bInterceptAtSide = false;
02176
02177
02178
02179 VecPosition posIntersect = lineBall.getIntersection( lineKeeper );
02180 if( fabs( posIntersect.getY() ) > SS->getGoalWidth()/2.0 )
02181 {
02182 VecPosition posGoalPost( -iSide*PITCH_LENGTH/2.0,
02183 sign(posBall.getY())*(SS->getGoalWidth()/2.0 + 0.5));
02184 Line l = Line::makeLineFromPositionAndAngle( posGoalPost, 0 );
02185 posIntersect = lineBall.getIntersection( l );
02186
02187
02188
02189 if( fabs(posIntersect.getX()) > fabs(posGoalPost.getX()) ||
02190 fabs(posIntersect.getX()) < fabs(posAgent.getX()) )
02191 posIntersect.setVecPosition( posAgent.getX(), posGoalPost.getY() );
02192 else
02193 bInterceptAtSide = true;
02194 }
02195
02196
02197 soc = interceptCloseGoalie();
02198 if( ! soc.isIllegal() )
02199 {
02200 Log.log( 553, "close intercept" );
02201 return soc;
02202 }
02203
02204
02205 if( PITCH_LENGTH/2.0 - fabs(posAgent.getX()) > 8.0 )
02206 {
02207 Log.log( 553, "I am far away from keeper line: %d %d %f %f",
02208 WM->getSide(), WM->getSidePenalty(), -iSide*PITCH_LENGTH/2.0 ,
02209 posAgent.getX() );
02210 return intercept( true );
02211 }
02212 else if( fabs(posBall.getX()) > fabs(posAgent.getX()) &&
02213 fabs( posBall.getY() ) < SS->getGoalWidth()/2.0 + 2.0 )
02214 {
02215 Log.log( 553, "ball heading and ball behind me" );
02216 return intercept( true );
02217 }
02218
02219
02220 if( posIntersect.getDistanceTo( posAgent ) < 0.5 )
02221 {
02222 Log.log( 553, "close to intersection point keeperline" );
02223 soc = turnBodyToObject( OBJECT_BALL );
02224 }
02225 else if( sign( (posIntersect - posAgent ).getDirection() ) ==
02226 sign( WM->getAgentGlobalBodyAngle() ) ||
02227 bInterceptAtSide == true)
02228 {
02229 Log.log( 553, "move forward to intersection point keeperline" );
02230 soc = moveToPos( posIntersect, 20, SS->getGoalWidth() );
02231 }
02232 else
02233 {
02234 Log.log( 553, "move backward to intersection point keeperline" );
02235 soc = moveToPos( posIntersect, 20, SS->getGoalWidth(), true );
02236 }
02237
02238 return soc;
02239 }
02240
02245 SoccerCommand BasicPlayer::holdBall( )
02246 {
02247 double dDist;
02248 VecPosition posAgent = WM->getAgentGlobalPosition();
02249 ObjectT objOpp = WM->getClosestInSetTo( OBJECT_SET_OPPONENTS,
02250 OBJECT_BALL, &dDist );
02251 VecPosition posOpp = WM->getGlobalPosition ( objOpp );
02252 AngDeg angOpp = WM->getGlobalBodyAngle( objOpp );
02253 AngDeg ang = 0.0;
02254
02255 if( objOpp != OBJECT_ILLEGAL && dDist < 5 )
02256 {
02257
02258
02259 ang = ( posAgent - posOpp ).getDirection();
02260 int iSign = -sign(VecPosition::normalizeAngle( angOpp - ang ));
02261 ang += iSign*45 - WM->getAgentGlobalBodyAngle();
02262 ang = VecPosition::normalizeAngle( ang );
02263 Log.log( 512, "hold ball: opp close shoot to ang %f", ang );
02264 }
02265 else
02266 Log.log( 512, "hold ball: in direction body: %f", ang );
02267
02268 if( WM->getBallPos().getDistanceTo( posAgent + VecPosition( 0.7, ang, POLAR ) )
02269 < 0.3 )
02270 {
02271 SoccerCommand soc = turnBodyToPoint( WM->getPosOpponentGoal() );
02272 VecPosition posBallPred = WM->predictPosAfterNrCycles( OBJECT_BALL, 1 );
02273 VecPosition posPred = WM->predictAgentPosAfterCommand( soc );
02274 if( posPred.getDistanceTo( posBallPred ) < 0.85 * SS->getMaximalKickDist() )
02275 {
02276 Log.log( 512, "hold ball: turn body to goal, ball remains still" );
02277 return soc;
02278 }
02279 }
02280
02281 return kickBallCloseToBody( ang, 0.7 ) ;
02282 }
02283
02284
02285
02297 VecPosition BasicPlayer::getThroughPassShootingPoint( ObjectT objTeam,
02298 VecPosition posEnd, AngDeg *angMax )
02299 {
02300 VecPosition posTeam = WM->getGlobalPosition( objTeam );
02301 return getShootPositionOnLine( posTeam, posEnd, angMax );
02302 }
02303
02319 VecPosition BasicPlayer::getInterceptionPointBall( int *iMinCyclesBall,
02320 bool isGoalie )
02321 {
02322 static Time timeLastMinCycles(-1,0);
02323 static Time timeLastIntercepted(-1,0);
02324 VecPosition posPred = WM->getAgentGlobalPosition();
02325 VecPosition velMe = WM->getAgentGlobalVelocity();
02326 double dSpeed, dDistExtra;
02327 VecPosition posMe, posBall;
02328 AngDeg ang, angBody, angNeck;
02329 Stamina sta;
02330 double dMaxDist, dBestX = -100;
02331 int iCyclesBall, iCyclesOpp, iFirstBall = -100;
02332
02333
02334 if( (WM->getCurrentTime() - timeLastIntercepted) > 2 )
02335 timeLastMinCycles.updateTime( -1 );
02336 timeLastIntercepted = WM->getCurrentTime();
02337 *iMinCyclesBall = 100;
02338
02339 if( isGoalie )
02340 return getActiveInterceptionPointBall( iMinCyclesBall, isGoalie );
02341
02342 dMaxDist = (isGoalie) ? SS->getCatchableAreaL() : SS->getMaximalKickDist();
02343
02344
02345 dSpeed = WM->getAgentSpeed();
02346 dDistExtra = Geometry::getSumInfGeomSeries( dSpeed, SS->getPlayerDecay() );
02347 posPred += VecPosition( dDistExtra, velMe.getDirection(), POLAR );
02348
02349 ObjectT objOpp = WM->getFastestInSetTo(OBJECT_SET_OPPONENTS,
02350 OBJECT_BALL, &iCyclesOpp);
02351 Log.log( 501, "closest opponent can get to ball in %d cycles", iCyclesOpp );
02352 if( WM->isBeforeGoal( WM->getAgentGlobalPosition() ) )
02353 iCyclesOpp = 20;
02354 int i = 2;
02355
02356
02357 while( i <= PS->getPlayerWhenToIntercept() && i <= iCyclesOpp + 2 )
02358 {
02359 posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, i );
02360
02361
02362 if( posPred.getDistanceTo(posBall)/SS->getPlayerSpeedMax() > i + dMaxDist
02363 ||
02364 WM->isInField( posBall ) == false )
02365 {
02366 i++;
02367 continue;
02368 }
02369
02370
02371
02372 posMe = WM->getAgentGlobalPosition();
02373 velMe = WM->getAgentGlobalVelocity();
02374 angBody = WM->getAgentGlobalBodyAngle();
02375 angNeck = WM->getAgentGlobalNeckAngle();
02376 ang = (posBall - posPred).getDirection();
02377 ang = VecPosition::normalizeAngle( ang - angBody );
02378 sta = WM->getAgentStamina();
02379 int turn = 0;
02380
02381
02382 while (fabs(ang) > PS->getPlayerWhenToTurnAngle() && turn<5)
02383 {
02384 turn++;
02385 WM->predictStateAfterTurn( WM->getAngleForTurn(ang,velMe.getMagnitude()),
02386 &posMe, &velMe, &angBody, &angNeck,WM->getAgentObjectType(),
02387 &sta );
02388 ang = (posBall - posPred).getDirection();
02389 ang = VecPosition::normalizeAngle( ang - angBody );
02390 }
02391
02392 if( turn > 1 )
02393 Log.log( 501, "nr of turns needed: %d", turn );
02394 int iTurnTmp = turn;
02395
02396 for( ; turn < i; turn++ )
02397 WM->predictStateAfterDash(SS->getMaxPower(),&posMe,&velMe,&sta,angBody);
02398
02399
02400 if (posMe.getDistanceTo( posBall ) < dMaxDist ||
02401 (posMe.getDistanceTo( posPred ) > posBall.getDistanceTo( posPred ) -
02402 dMaxDist) )
02403 {
02404 Log.log( 501, "can intercept in %d cycles %d turns, ball %f best %f",
02405 i, iTurnTmp, posBall.getX(), dBestX );
02406
02407 if( *iMinCyclesBall == 100 )
02408 {
02409 *iMinCyclesBall = i;
02410 iFirstBall = i;
02411 }
02412
02413 iCyclesBall = i;
02414 if( WM->getCurrentTime() + iCyclesBall == timeLastMinCycles )
02415 {
02416 Log.log( 501, "choose old interception point %d", iCyclesBall );
02417 return posBall;
02418 }
02419 if( objOpp == OBJECT_ILLEGAL || isGoalie == true )
02420 {
02421
02422 if( *iMinCyclesBall == 100 )
02423 {
02424 *iMinCyclesBall = iCyclesBall;
02425 i = PS->getPlayerWhenToIntercept() + 1;
02426 }
02427 }
02428 else if( WM->isBeforeGoal( WM->getAgentGlobalPosition() ) )
02429 {
02430 if( fabs(posBall.getY()) < fabs(dBestX ) &&
02431 iCyclesBall < iFirstBall + 3 &&
02432 (iCyclesOpp - iCyclesBall) >= 2 )
02433 {
02434 dBestX = fabs(posBall.getY());
02435 *iMinCyclesBall = iCyclesBall;
02436 Log.log( 501, "update best cycles in goalarea to %d, opp %d",
02437 *iMinCyclesBall, (iCyclesOpp - iCyclesBall) );
02438 }
02439
02440 }
02441 else if( posBall.getX() >= dBestX &&
02442 fabs( posBall.getY() ) < 32.0 &&
02443 fabs( posBall.getX() ) < 50.0 &&
02444 ( posBall.getX() > - PITCH_LENGTH/4.0 ||
02445 iCyclesBall < iFirstBall + 3 ) &&
02446 (iCyclesOpp - iCyclesBall) >= 1 )
02447 {
02448 dBestX = posBall.getX();
02449 *iMinCyclesBall = iCyclesBall;
02450 Log.log( 501, "update best cycles to %d, opp diff %d", *iMinCyclesBall,
02451 iCyclesOpp - iCyclesBall );
02452 }
02453 }
02454 i++;
02455 }
02456
02457 if( i == 2 || ( i == iCyclesOpp + 3 && *iMinCyclesBall > iCyclesOpp ))
02458 {
02459 Log.log( 501, "move to interception point closest opp." );
02460 *iMinCyclesBall = iCyclesOpp;
02461 }
02462
02463 posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, *iMinCyclesBall );
02464 Log.log( 501, "choose: %d", *iMinCyclesBall );
02465 timeLastMinCycles = WM->getCurrentTime() + *iMinCyclesBall;
02466
02467 return posBall;
02468 }
02469
02470
02475 VecPosition BasicPlayer::getActiveInterceptionPointBall( int *iCyclesBall,
02476 bool isGoalie )
02477 {
02478 VecPosition posPred = WM->getAgentGlobalPosition();
02479 VecPosition velMe = WM->getAgentGlobalVelocity();
02480 double dSpeed, dDistExtra;
02481 VecPosition posMe, posBall;
02482 AngDeg ang, angBody, angNeck;
02483 Stamina sta;
02484 double dMaxDist;
02485
02486 if( isGoalie &&
02487 !WM->isInOwnPenaltyArea(WM->predictPosAfterNrCycles( OBJECT_BALL, 45)))
02488 {
02489 *iCyclesBall = -1;
02490 return posBall;
02491 }
02492
02493 dMaxDist = (isGoalie) ? SS->getCatchableAreaL() : SS->getMaximalKickDist();
02494
02495
02496 dSpeed = WM->getAgentSpeed();
02497 dDistExtra = Geometry::getSumInfGeomSeries( dSpeed, SS->getPlayerDecay() );
02498 posPred += VecPosition( dDistExtra, velMe.getDirection(), POLAR );
02499
02500
02501 for ( int i = 0; i <= PS->getPlayerWhenToIntercept(); i++ )
02502 {
02503
02504
02505 velMe = WM->getAgentGlobalVelocity();
02506 angBody = WM->getAgentGlobalBodyAngle();
02507 angNeck = WM->getAgentGlobalNeckAngle();
02508 posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, i + 1 );
02509 posMe = WM->getAgentGlobalPosition();
02510 ang = (posBall - posPred).getDirection();
02511 ang = VecPosition::normalizeAngle( ang - angBody );
02512 sta = WM->getAgentStamina();
02513 int turn = 0;
02514
02515
02516 while (fabs(ang) > PS->getPlayerWhenToTurnAngle() && turn<5)
02517 {
02518 turn++;
02519 WM->predictStateAfterTurn( WM->getAngleForTurn(ang,velMe.getMagnitude()),
02520 &posMe, &velMe, &angBody, &angNeck,WM->getAgentObjectType(),
02521 &sta );
02522 ang = (posBall - posPred).getDirection();
02523 ang = VecPosition::normalizeAngle( ang - angBody );
02524 }
02525
02526 if( turn > 1 )
02527 {
02528 Log.log( 502, "nr of turns needed: %d", turn );
02529 }
02530
02531
02532 for( ; turn < i; turn++ )
02533 WM->predictStateAfterDash(SS->getMaxPower(),&posMe,&velMe,&sta,angBody);
02534
02535
02536 if (posMe.getDistanceTo( posBall ) < dMaxDist ||
02537 (posMe.getDistanceTo( posPred ) > posBall.getDistanceTo( posPred ) +
02538 dMaxDist) )
02539 {
02540 WM->logCircle( 501, posBall, 2, true );
02541 WM->logCircle( 501, posBall, 1, true );
02542 *iCyclesBall = i;
02543 Log.log( 501, "intercept ball in %d cycles", *iCyclesBall );
02544 return posBall;
02545 }
02546 }
02547
02548 *iCyclesBall = -1;
02549 return posBall;
02550 }
02551
02552 VecPosition BasicPlayer::getDribblePoint( DribbleT dribble, double *dDist )
02553 {
02554 AngDeg angBody = WM->getAgentGlobalBodyAngle() ;
02555 VecPosition posAgent = WM->getAgentGlobalPosition() ;
02556 VecPosition pos;
02557 double dLength;
02558
02559 switch( dribble )
02560 {
02561 case DRIBBLE_WITHBALL:
02562 dLength = 5.0;
02563 *dDist = 4;
02564 break;
02565 case DRIBBLE_SLOW:
02566 dLength = 8.0;
02567 *dDist = 3.8;
02568 break;
02569 case DRIBBLE_FAST:
02570 dLength = 14.0;
02571 *dDist = 12;
02572 break;
02573 default:
02574 dLength = 0.0;
02575 break;
02576 }
02577
02578
02579 pos = posAgent + VecPosition( dLength, angBody, POLAR );
02580
02581
02582
02583 if( ( fabs( pos.getY() ) > PITCH_WIDTH/2.0 - 3.0 && fabs(angBody) > 3) ||
02584 ( fabs( pos.getX() ) > PITCH_LENGTH/2.0 - 3.0 ) )
02585 pos = WM->getOuterPositionInField( WM->getAgentGlobalPosition(),
02586 WM->getAgentGlobalBodyAngle(), 2.0, false );
02587
02588 return pos;
02589 }
02590
02602 VecPosition BasicPlayer::getShootPositionOnLine( VecPosition p1,
02603 VecPosition p2, AngDeg *angLargest )
02604 {
02605 VecPosition posBall = WM->getBallPos();
02606 Line line = Line::makeLineFromTwoPoints( p1, p2 );
02607 double dRadius = min( PS->getClearBallOppMaxDist(),
02608 posBall.getDistanceTo( p2 ) );
02609 AngDeg angMin = (p1 - posBall ).getDirection();
02610 AngDeg angMax = (p2 - posBall ).getDirection();
02611
02612 AngDeg angShoot = WM->getDirectionOfWidestAngle(
02613 posBall, min(angMin, angMax),
02614 max(angMin,angMax), angLargest, dRadius );
02615 Line line2 = Line::makeLineFromPositionAndAngle( posBall,
02616 angShoot );
02617 return line.getIntersection( line2 );
02618 }
02619
02633 double BasicPlayer::getEndSpeedForPass( ObjectT o, VecPosition posPass )
02634 {
02635
02636
02637 VecPosition posBall = WM->getBallPos();
02638 double dDist = posBall.getDistanceTo( posPass );
02639 double dLength = WM->predictNrCyclesToPoint( o, posPass );
02640 double dFirst = WM->getFirstSpeedFromDist( dDist, dLength );
02641 if( dFirst > SS->getBallSpeedMax() )
02642 dFirst = SS->getBallSpeedMax();
02643 double dEnd = WM->getEndSpeedFromFirstSpeed( dFirst, dLength );
02644 if( dEnd > PS->getPassEndSpeed() )
02645 dEnd = PS->getPassEndSpeed();
02646 else if( dEnd < 0.6 )
02647 dEnd = 0.6;
02648 else if( dLength > 10.0 )
02649 dEnd = 0.6;
02650
02651 return dEnd;
02652 }
02653
02677 VecPosition BasicPlayer::getMarkingPosition( ObjectT o, double dDist,
02678 MarkT mark)
02679 {
02680 VecPosition pos = WM->getGlobalPosition( o );
02681
02682 if( pos.getX() > - PITCH_LENGTH/2.0 + 4.0 )
02683 pos -= VecPosition( 1.0, 0.0 );
02684
02685 return WM->getMarkingPosition( pos, dDist, mark );
02686
02687 }
02688
02689
02690
02691
02692
02693
02694
02695
02696
02697
02698
02699
02700
02701
02702
02703
02704
02705
02706
02707
02708
02709
02710
02711
02712
02713
02714
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724
02725
02726
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745