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
00044 #include "BasicPlayer.h"
00045
00046
00047
00052 SoccerCommand BasicPlayer::alignNeckWithBody( )
00053 {
00054 return SoccerCommand( CMD_TURNNECK, WM->getAgentBodyAngleRelToNeck( ) );
00055 }
00056
00075 SoccerCommand BasicPlayer::turnBodyToPoint( VecPosition pos, int iCycles = 1 )
00076 {
00077 VecPosition posGlobal = WM->predictAgentPos(iCycles, 0);
00078 AngDeg angTurn = (pos - posGlobal).getDirection();
00079 angTurn -= WM->getAgentGlobalBodyAngle();
00080 angTurn = VecPosition::normalizeAngle( angTurn );
00081 angTurn = WM->getAngleForTurn( angTurn, WM->getAgentSpeed() );
00082
00083 return SoccerCommand( CMD_TURN, angTurn );
00084 }
00085
00098 SoccerCommand BasicPlayer::turnBackToPoint( VecPosition pos, int iCycles = 1 )
00099 {
00100 VecPosition posGlobal = WM->predictAgentPos(iCycles, 0);
00101 AngDeg angTurn = (pos - posGlobal).getDirection();
00102 angTurn -= (WM->getAgentGlobalBodyAngle() + 180);
00103 angTurn = VecPosition::normalizeAngle( angTurn );
00104 angTurn = WM->getAngleForTurn( angTurn, WM->getAgentSpeed() );
00105
00106 return SoccerCommand( CMD_TURN, angTurn );
00107 }
00108
00130 SoccerCommand BasicPlayer::turnNeckToPoint(VecPosition pos, SoccerCommand soc)
00131 {
00132 VecPosition posMe, velMe;
00133 AngDeg angBody, angNeck, angActual;
00134 Stamina sta;
00135
00136
00137
00138
00139 WM->predictAgentStateAfterCommand(soc,&posMe,&velMe,&angBody,&angNeck,&sta);
00140 AngDeg angDesGlobNeck = (pos - posMe).getDirection();
00141 AngDeg angNeckRelToBody = VecPosition::normalizeAngle(angDesGlobNeck-angBody);
00142
00143
00144
00145
00146
00147
00148 AngDeg angBodyRelToNeck = VecPosition::normalizeAngle(angBody-angNeck);
00149 if( angNeckRelToBody < SS->getMinNeckAng() )
00150 angActual = SS->getMinNeckAng() + angBodyRelToNeck;
00151 else if( angNeckRelToBody > SS->getMaxNeckAng() )
00152 angActual = SS->getMaxNeckAng() + angBodyRelToNeck;
00153 else
00154 angActual = angNeckRelToBody + angBodyRelToNeck;
00155 return SoccerCommand( CMD_TURNNECK, angActual );
00156 }
00157
00169 SoccerCommand BasicPlayer::searchBall()
00170 {
00171 static Time timeLastSearch;
00172 static int iSign = 1;
00173
00174
00175 AngDeg ang = 2*SoccerTypes::getHalfViewAngleValue( WM->getAgentViewAngle() );
00176 ang = WM->getAngleForTurn( ang - ang/10.0, WM->getAgentSpeed() );
00177
00178
00179
00180
00181
00182
00183 AngDeg angBody = WM->getAgentGlobalBodyAngle();
00184 AngDeg angMax = VecPosition::normalizeAngle( angBody + 180 );
00185 AngDeg angBall = (WM->getBallPos()-
00186 WM->getAgentGlobalPosition()).getDirection();
00187
00188 if( abs( WM->getCurrentTime() - timeLastSearch ) > 3 )
00189 iSign = isAngInInterval( angBall, angBody, angMax ) ? 1: -1;
00190 timeLastSearch = WM->getCurrentTime();
00191
00192 if( WM->getCurrentTime() != WM->getTimeLastSeeMessage() )
00193 return SoccerCommand( CMD_TURN, iSign * ang );
00194 return SoccerCommand( CMD_TURN, iSign * ang );
00195 }
00196
00197
00210 SoccerCommand BasicPlayer::dashToPoint( VecPosition pos )
00211 {
00212 double dDashPower = WM->getPowerForDash(
00213 pos - WM->getAgentGlobalPosition(),
00214 WM->getAgentGlobalBodyAngle(),
00215 WM->getAgentGlobalVelocity(),
00216 WM->getAgentEffort() );
00217 return SoccerCommand( CMD_DASH, dDashPower );
00218
00219 }
00220
00233 SoccerCommand BasicPlayer::freezeBall( )
00234 {
00235
00236
00237
00238
00239 double dPower = WM->getKickPowerForSpeed( WM->getBallSpeed() );
00240 if( dPower > SS->getMaxPower() )
00241 {
00242 Log.log( 552, "%d: freeze ball has to much power", WM->getCurrentCycle() );
00243 dPower = (double)SS->getMaxPower();
00244 }
00245 double dAngle = WM->getBallDirection() + 180 - WM->getAgentGlobalBodyAngle();
00246 dAngle = VecPosition::normalizeAngle( dAngle );
00247 return SoccerCommand( CMD_KICK, dPower, dAngle );
00248 }
00249
00269 SoccerCommand BasicPlayer::kickBallCloseToBody( AngDeg ang )
00270 {
00271 AngDeg angBody = WM->getAgentGlobalBodyAngle();
00272 VecPosition posAgent = WM->predictAgentPos( 1, 0 );
00273 double dDist = SS->getPlayerSize() +
00274 SS->getBallSize() +
00275 SS->getKickableMargin()/6.0;
00276 AngDeg angGlobal = VecPosition::normalizeAngle( angBody + ang );
00277 VecPosition posDesBall = posAgent + VecPosition( dDist, angGlobal, POLAR );
00278 VecPosition vecDesired = posDesBall - WM->getBallPos();
00279 VecPosition vecShoot = vecDesired - WM->getGlobalVelocity( OBJECT_BALL );
00280 double dPower = WM->getKickPowerForSpeed( vecShoot.getMagnitude() );
00281 AngDeg angActual = vecShoot.getDirection() - angBody;
00282 angActual = VecPosition::normalizeAngle( angActual );
00283
00284 if( dPower > SS->getMaxPower() )
00285 {
00286 Log.log( 500, "kickBallCloseToBody: cannot compensate for ball speed, freeze");
00287 Log.log( 101, "kickBallCloseToBody: cannot compensate for ball speed, freeze");
00288 return freezeBall();
00289 }
00290 else
00291 Log.log( 101, "(kick %f %f), vecDesired (%f,%f)", dPower, angActual,
00292 vecDesired.getX(), vecDesired.getY() );
00293 return SoccerCommand( CMD_KICK, dPower, angActual );
00294 }
00295
00314 SoccerCommand BasicPlayer::accelerateBallToVelocity( VecPosition velDes )
00315 {
00316 AngDeg angBody = WM->getAgentGlobalBodyAngle();
00317 VecPosition velBall = WM->getGlobalVelocity( OBJECT_BALL );
00318 VecPosition accDes = velDes - velBall;
00319 double dPower;
00320 double angActual;
00321
00322
00323 if( accDes.getMagnitude() < SS->getBallAccelMax() )
00324 {
00325 dPower = WM->getKickPowerForSpeed ( accDes.getMagnitude() );
00326 angActual = VecPosition::normalizeAngle( accDes.getDirection() - angBody );
00327 if( dPower <= SS->getMaxPower() )
00328 return SoccerCommand( CMD_KICK, dPower, angActual );
00329 }
00330
00331
00332 dPower = SS->getMaxPower();
00333 double dSpeed = WM->getActualKickPowerRate() * dPower;
00334 double tmp = velBall.rotate(-velDes.getDirection()).getY();
00335 angActual = velDes.getDirection() - asinDeg( tmp / dSpeed );
00336 angActual = VecPosition::normalizeAngle( angActual - angBody );
00337
00338 return SoccerCommand( CMD_KICK, dPower, angActual );
00339 }
00340
00349 SoccerCommand BasicPlayer::catchBall()
00350 {
00351
00352 return SoccerCommand( CMD_CATCH, WM->getRelativeAngle( OBJECT_BALL, true ));
00353 }
00354
00355
00361 SoccerCommand BasicPlayer::communicate( char *str )
00362 {
00363 return SoccerCommand( CMD_SAY, str );
00364 }
00365
00370 SoccerCommand BasicPlayer::teleportToPos( VecPosition pos )
00371 {
00372 return SoccerCommand( CMD_MOVE, pos.getX(), pos.getY() );
00373
00374 }
00375
00376
00377
00386 SoccerCommand BasicPlayer::turnBodyToObject( ObjectT o )
00387 {
00388 return turnBodyToPoint( WM->predictPosAfterNrCycles(o, 1) );
00389 }
00390
00406 SoccerCommand BasicPlayer::turnNeckToObject( ObjectT o, SoccerCommand soc )
00407 {
00408 return turnNeckToPoint( WM->predictPosAfterNrCycles(o, 1), soc );
00409 }
00410
00442 SoccerCommand BasicPlayer::moveToPos( VecPosition posTo, AngDeg angWhenToTurn,
00443 double dDistBack, bool bMoveBack )
00444 {
00445 VecPosition posPred = WM->predictAgentPos( 1, 0 );
00446 AngDeg angBody = WM->getAgentGlobalBodyAngle();
00447 VecPosition posAgent = WM->getAgentGlobalPosition();
00448 AngDeg angTo = ( posTo - posPred ).getDirection();
00449 angTo = VecPosition::normalizeAngle( angTo - angBody );
00450 AngDeg angBackTo = VecPosition::normalizeAngle( angTo + 180 );
00451 double dDist = posAgent.getDistanceTo( posTo );
00452
00453 if( bMoveBack )
00454 {
00455 if( fabs( angBackTo ) < angWhenToTurn )
00456 return dashToPoint( posTo );
00457 else
00458 return turnBackToPoint( posTo );
00459 }
00460 else if( fabs( angTo ) < angWhenToTurn ||
00461 (fabs( angBackTo ) < angWhenToTurn && dDist < dDistBack ) )
00462 return dashToPoint( posTo );
00463 else
00464 return turnBodyToPoint( posTo );
00465 }
00466
00531 SoccerCommand BasicPlayer::interceptClose( )
00532 {
00533 SoccerCommand soc;
00534 double dPower, dDist;
00535 AngDeg ang, ang2;
00536 VecPosition s1, s2;
00537
00538
00539 dDist = 2*SS->getPlayerSpeedMax()
00540 + (1.0 + SS->getBallDecay())*SS->getBallSpeedMax()
00541 + SS->getMaximalKickDist();
00542 if( WM->getRelativeDistance( OBJECT_BALL ) > dDist )
00543 return SoccerCommand( CMD_ILLEGAL );
00544
00545
00546 VecPosition posAgent = WM->getAgentGlobalPosition( );
00547 VecPosition posPred = WM->predictAgentPos( 1, 0 );
00548 VecPosition posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 1 );
00549 VecPosition velMe = WM->getAgentGlobalVelocity( );
00550 Stamina sta = WM->getAgentStamina( );
00551 AngDeg angBody = WM->getAgentGlobalBodyAngle( );
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562 Line line = Line::makeLineFromPositionAndAngle(posPred,angBody);
00563 dDist = SS->getPlayerSize()+SS->getBallSize()+SS->getKickableMargin()/6;
00564 int iSol = line.getCircleIntersectionPoints( Circle(posBall,dDist), &s1, &s2);
00565 if (iSol > 0)
00566 {
00567 if (iSol == 2)
00568 {
00569 ang = VecPosition::normalizeAngle((posBall - s1).getDirection() -angBody);
00570 ang2 = VecPosition::normalizeAngle((posBall - s2).getDirection() -angBody);
00571 if ( fabs(ang2) < 90)
00572 s1 = s2;
00573 }
00574
00575
00576
00577
00578
00579
00580 dPower = WM->getPowerForDash(s1-posAgent, angBody, velMe,sta.getEffort() );
00581 posPred = WM->predictAgentPos( 1, (int)dPower);
00582 if ( posPred.getDistanceTo( posBall ) < SS->getMaximalKickDist() )
00583 return SoccerCommand( CMD_DASH, dPower );
00584 }
00585
00586
00587
00588
00589
00590
00591
00592
00593 posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 2 );
00594 posPred = WM->predictAgentPos( 2, 0 );
00595 ang = (posBall - posPred).getDirection();
00596 ang = VecPosition::normalizeAngle( ang - angBody );
00597 if (fabs( ang ) > PS->getPlayerWhenToTurnAngle() )
00598 {
00599 soc = turnBodyToPoint( posBall, 2 );
00600 WM->predictAgentStateAfterCommand(soc,&posPred,&velMe,&angBody,&ang,&sta );
00601 dPower = WM->getPowerForDash(posBall-posPred,angBody,velMe,sta.getEffort());
00602 WM->predictStateAfterDash( dPower, &posPred, &velMe, &sta, angBody);
00603 if (posPred.getDistanceTo(posBall) < SS->getMaximalKickDist())
00604 return soc;
00605 }
00606
00607
00608
00609
00610
00611
00612
00613 soc = SoccerCommand( CMD_DASH, SS->getMaxPower() );
00614 WM->predictAgentStateAfterCommand(soc,&posPred,&velMe,&angBody,&ang,&sta );
00615 dPower=WM->getPowerForDash(posBall-posPred,angBody,velMe,sta.getEffort());
00616 WM->predictStateAfterDash( dPower, &posPred, &velMe, &sta, angBody );
00617 if (posPred.getDistanceTo(posBall) < SS->getMaximalKickDist())
00618 return soc;
00619
00620
00621
00622 posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 3 );
00623 soc = SoccerCommand( CMD_DASH, SS->getMaxPower() );
00624 WM->predictAgentStateAfterCommand(soc,&posPred,&velMe,&angBody,&ang,&sta );
00625 WM->predictStateAfterCommand( soc, &posPred, &velMe, &angBody, &ang,&sta );
00626 dPower=WM->getPowerForDash(posBall-posPred,angBody,velMe,sta.getEffort());
00627 WM->predictStateAfterDash( dPower, &posPred, &velMe, &sta, angBody );
00628 if (posPred.getDistanceTo(posBall) < SS->getMaximalKickDist())
00629 return soc;
00630
00631
00632 return SoccerCommand( CMD_ILLEGAL );
00633 }
00634
00671 SoccerCommand BasicPlayer::interceptCloseGoalie( )
00672 {
00673 SoccerCommand soc;
00674 double dPower, dDist;
00675 AngDeg ang;
00676 VecPosition posClosestToBall;
00677
00678
00679 VecPosition posPred = WM->predictAgentPos( 1, 0 );
00680 VecPosition posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 1 );
00681 VecPosition velMe = WM->getAgentGlobalVelocity( );
00682 Stamina sta = WM->getAgentStamina( );
00683 AngDeg angBody = WM->getAgentGlobalBodyAngle( );
00684 Line lineGoalie=Line::makeLineFromPositionAndAngle(posPred,angBody);
00685
00686
00687
00688 dDist = SS->getBallSpeedMax()+SS->getPlayerSpeedMax()+SS->getCatchableAreaL();
00689 if( WM->getRelativeDistance( OBJECT_BALL ) < dDist )
00690 {
00691 posClosestToBall = lineGoalie.getPointOnLineClosestTo( posBall );
00692 dPower = WM->getPowerForDash(
00693 posClosestToBall-posPred,
00694 angBody,
00695 velMe,
00696 sta.getEffort() );
00697 posPred = WM->predictAgentPos( 1, (int)dPower);
00698 if ( posPred.getDistanceTo( posBall ) < SS->getCatchableAreaL() )
00699 return SoccerCommand( CMD_DASH, dPower );
00700 }
00701
00702
00703
00704
00705
00706 dDist = SS->getBallSpeedMax()*(1.0+SS->getBallDecay())
00707 + 2*SS->getPlayerSpeedMax()
00708 + SS->getCatchableAreaL();
00709 if( WM->getRelativeDistance( OBJECT_BALL ) < dDist )
00710 {
00711
00712
00713
00714
00715
00716
00717 posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 2 );
00718 soc = dashToPoint( posBall );
00719 WM->predictAgentStateAfterCommand(soc,&posPred,&velMe,&angBody,&ang,&sta );
00720 dPower=WM->getPowerForDash(posBall-posPred,angBody,velMe,sta.getEffort());
00721 WM->predictStateAfterDash( dPower, &posPred, &velMe, &sta, angBody );
00722 if( posPred.getDistanceTo(posBall) < SS->getCatchableAreaL() )
00723 return soc;
00724
00725
00726 posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 2 );
00727 posPred = WM->predictAgentPos( 2, 0 );
00728 ang = (posBall - posPred).getDirection();
00729 ang = VecPosition::normalizeAngle( ang - angBody );
00730 if (fabs( ang ) > PS->getPlayerWhenToTurnAngle() )
00731 {
00732 soc = turnBodyToPoint( posBall, 2 );
00733 WM->predictAgentStateAfterCommand(soc,&posPred,&velMe,&angBody,&ang,&sta );
00734 dPower=WM->getPowerForDash(posBall-posPred,angBody,velMe,sta.getEffort());
00735 WM->predictStateAfterDash( dPower, &posPred, &velMe, &sta, angBody);
00736 if( posPred.getDistanceTo(posBall) < SS->getCatchableAreaL() )
00737 return soc;
00738 }
00739 }
00740
00741
00742 return SoccerCommand( CMD_ILLEGAL );
00743 }
00744
00775 SoccerCommand BasicPlayer::kickTo( VecPosition posTarget, double dEndSpeed )
00776 {
00777 VecPosition posBall = WM->getBallPos();
00778 VecPosition velBall = WM->getGlobalVelocity(OBJECT_BALL);
00779 VecPosition posTraj = posTarget - posBall;
00780 VecPosition velDes = VecPosition(
00781 WM->getKickSpeedToTravel( posTraj.getMagnitude(), dEndSpeed ),
00782 posTraj.getDirection(),
00783 POLAR );
00784 double dPower;
00785 AngDeg angActual;
00786
00787 Log.log( 101, "glob pos ball (%f,%f), glob pos agent (%f,%f), ang %f %f" ,
00788 WM->getBallPos().getX(), WM->getBallPos().getY(),
00789 WM->getAgentGlobalPosition().getX(),
00790 WM->getAgentGlobalPosition().getY(),
00791 WM->getAgentGlobalBodyAngle(),
00792 WM->getAgentGlobalNeckAngle() );
00793 Log.log( 101, "rel pos body (%f,%f), velocity ball: (%f,%f)" ,
00794 WM->getRelativeDistance( OBJECT_BALL ),
00795 WM->getRelativeAngle( OBJECT_BALL, true ),
00796 velBall.getX(), velBall.getY() );
00797
00798 if( velDes.getMagnitude() > SS->getBallSpeedMax() )
00799 {
00800 dPower = SS->getMaxPower();
00801 double dSpeed = WM->getActualKickPowerRate() * dPower;
00802 double tmp = velBall.rotate(-velDes.getDirection()).getY();
00803 angActual = velDes.getDirection() - asinDeg( tmp / dSpeed );
00804 double dSpeedPred = ( WM->getGlobalVelocity(OBJECT_BALL)+
00805 VecPosition(dSpeed,angActual, POLAR )).getMagnitude();
00806
00807
00808 if( dSpeedPred > PS->getPlayerWhenToKick()*SS->getBallAccelMax() )
00809 {
00810 Log.log( 101, "point too far, but can acccelerate ball good to %f k=%f,%f",
00811 dSpeedPred, dSpeed, tmp );
00812 return accelerateBallToVelocity( velDes );
00813 }
00814 else if( WM->getActualKickPowerRate() >
00815 PS->getPlayerWhenToKick() * SS->getKickPowerRate() )
00816 {
00817 Log.log( 101, "point too far, freeze ball" );
00818 return freezeBall();
00819 }
00820 else
00821 {
00822 Log.log( 101, "point too far, reposition ball (k_r = %f)",
00823 WM->getActualKickPowerRate()/(SS->getKickPowerRate()) );
00824 return kickBallCloseToBody( 0 );
00825 }
00826 }
00827 else
00828 {
00829 VecPosition accBallDes = velDes - velBall;
00830 dPower = WM->getKickPowerForSpeed(accBallDes.getMagnitude());
00831 if( dPower <= 0.95*SS->getMaxPower() )
00832 {
00833 Log.log( 101, "point good and can reach point" );
00834 return accelerateBallToVelocity( velDes );
00835 }
00836 else
00837 {
00838 Log.log( 101, "point good, but reposition ball since need %f",dPower );
00839 return kickBallCloseToBody( 0 );
00840 }
00841 }
00842 }
00843
00871 SoccerCommand BasicPlayer::turnWithBallTo( AngDeg ang, AngDeg angKickThr,
00872 double dFreezeThr )
00873 {
00874
00875
00876
00877
00879
00880
00881 VecPosition posAgent = WM->getAgentGlobalPosition();
00882 VecPosition posBall = WM->getBallPos();
00883 AngDeg angBody = WM->getAgentGlobalBodyAngle();
00884 AngDeg angDiff = (posBall-posAgent).getDirection() - ang;
00885 angDiff = VecPosition::normalizeAngle( angDiff );
00886 double dDist;
00887 ObjectT objOpp = WM->getClosestInSetTo( OBJECT_SET_OPPONENTS,
00888 WM->getAgentObjectType(), &dDist );
00889 VecPosition posOpp = WM->getGlobalPosition( objOpp );
00890
00891 if( objOpp != OBJECT_ILLEGAL && dDist < 2.5 )
00892 {
00893 if( posBall.getDistanceTo( posOpp ) < posBall.getDistanceTo( posAgent ) )
00894 {
00895 ang = (posOpp - posAgent).getDirection() + 180;
00896 return kickBallCloseToBody( VecPosition::normalizeAngle( ang - angBody ));
00897 }
00898 }
00899 else if( fabs( angDiff ) > angKickThr )
00900 {
00901 return kickBallCloseToBody( VecPosition::normalizeAngle( ang - angBody ) );
00902 }
00903
00904 if( WM->getBallSpeed() > dFreezeThr )
00905 {
00906 return freezeBall();
00907 }
00908
00909 ACT->putCommandInQueue( alignNeckWithBody() );
00910 return turnBodyToPoint( posAgent + VecPosition(1.0, ang, POLAR ) );
00911 }
00912
00962 SoccerCommand BasicPlayer::moveToPosAlongLine( VecPosition pos, AngDeg ang,
00963 double dDistThr, int iSign, AngDeg angThr, AngDeg angCorr )
00964 {
00965 Line l = Line::makeLineFromPositionAndAngle( pos, ang );
00966 VecPosition posBall = WM->getBallPos();
00967 VecPosition posAgent = WM->getAgentGlobalPosition();
00968 AngDeg angBody = WM->getAgentGlobalBodyAngle();
00969 VecPosition posProj = l.getPointOnLineClosestTo( posAgent );
00970 double dDist = posAgent.getDistanceTo( posProj );
00971 double dDiff = pos.getDistanceTo ( posProj );
00972
00973 if( dDist > dDistThr )
00974 {
00975
00976 VecPosition posOrg(0,0);
00977 Line m = Line::makeLineFromTwoPoints( posOrg, posAgent );
00978 VecPosition posIntersect = l.getIntersection( m );
00979 int iSide;
00980 if( posAgent.getDistanceTo(posOrg) < posIntersect.getDistanceTo( posOrg ) )
00981 iSide = +1;
00982 else
00983 iSide = -1;
00984
00985
00986 ang = ang + iSign * iSide * angCorr;
00987 }
00988
00989 Log.log( 553, "y difference to defend point %f", dDiff );
00990
00991 if( fabs( VecPosition::normalizeAngle( ang - angBody ) ) > angThr )
00992 {
00993 Log.log( 553, "angle differs too much body = %f, des = %f", angBody, ang );
00994 return turnBodyToPoint( posAgent + VecPosition( 1.0, ang, POLAR ) );
00995 }
00996 else if( ( posBall.getX() > -PITCH_LENGTH/4.0 && dDiff > 0.6 ) )
00997 return dashToPoint( pos );
00998 else if( ( posBall.getX() < -PITCH_LENGTH/4.0 && dDiff > 0.3 ) )
00999 return dashToPoint( pos );
01000 else
01001 return SoccerCommand( CMD_ILLEGAL );
01002 }
01003
01004
01005
01006
01016 SoccerCommand BasicPlayer::intercept( bool isGoalie )
01017 {
01018 SoccerCommand soc = (isGoalie) ? interceptCloseGoalie() : interceptClose();
01019 if( soc.commandType != CMD_ILLEGAL )
01020 {
01021 Log.log( 502, "intercept in two cycles" );
01022 return soc;
01023 }
01024
01025
01026 int iSol;
01027 VecPosition posBall = getInterceptionPointBall( &iSol, isGoalie );
01028 Log.log( 502, "intercept ball in %d cycles", iSol );
01029 return moveToPos( posBall, PS->getPlayerWhenToTurnAngle(), 3.0 );
01030 }
01031
01070 SoccerCommand BasicPlayer::dribble( AngDeg ang, DribbleT dribbleT )
01071 {
01072 double dLength;
01073
01074 AngDeg angBody = WM->getAgentGlobalBodyAngle();
01075 VecPosition posAgent = WM->getAgentGlobalPosition();
01076
01077 switch( dribbleT )
01078 {
01079 case DRIBBLE_WITHBALL:
01080 dLength = 2.0;
01081 break;
01082 case DRIBBLE_SLOW:
01083 dLength = 3.0;
01084 break;
01085 case DRIBBLE_FAST:
01086 dLength = 8.0;
01087 break;
01088 default:
01089 dLength = 0.0;
01090 break;
01091 }
01092
01093
01094 VecPosition posDribble = posAgent + VecPosition( dLength, ang, POLAR );
01095
01096
01097
01098 if( ( fabs( posDribble.getY() ) > PITCH_WIDTH/2.0 - 3.0 && fabs(ang) > 3) ||
01099 ( fabs( posDribble.getX() ) > PITCH_LENGTH/2.0 - 3.0 ) )
01100 posDribble = WM->getOuterPositionInField( posAgent, ang, 2.0, false );
01101
01102
01103 ang = VecPosition::normalizeAngle( ang - angBody );
01104 if( fabs( ang ) > 20 )
01105 return turnWithBallTo( (posDribble-posAgent).getDirection(),
01106 PS->getTurnWithBallAngThr(),
01107 PS->getTurnWithBallFreezeThr() );
01108 return kickTo( posDribble, 0.5 );
01109 }
01110
01120 SoccerCommand BasicPlayer::directPass( ObjectT o, PassT passType)
01121 {
01122 VecPosition pos = WM->getGlobalPosition( o );
01123 if( passType == PASS_NORMAL )
01124 return kickTo( pos, PS->getPassEndSpeed() );
01125 else if( passType == PASS_FAST )
01126 return kickTo( pos, PS->getFastPassEndSpeed() );
01127 else
01128 return SoccerCommand( CMD_ILLEGAL );
01129 }
01130
01147 SoccerCommand BasicPlayer::leadingPass( ObjectT o, double dDist )
01148 {
01149 VecPosition posShoot = WM->getGlobalPosition( o )
01150 + VecPosition( dDist, 0.0, POLAR );
01151 return kickTo( posShoot, PS->getPassEndSpeed() );
01152 }
01153
01180 SoccerCommand BasicPlayer::throughPass( ObjectT o, VecPosition posEnd,
01181 AngDeg *angMax )
01182 {
01183 VecPosition posObj = WM->getGlobalPosition( o );
01184 VecPosition posBegin = posObj + VecPosition( 3.0, 0.0 );
01185 VecPosition posShoot = getShootPositionOnLine( posBegin, posEnd, angMax );
01186 double dEnd = getEndSpeedForPass( o, posShoot );
01187
01188 return kickTo( posShoot, dEnd );
01189 }
01190
01271 SoccerCommand BasicPlayer::outplayOpponent( ObjectT o, VecPosition pos,
01272 VecPosition *posTo )
01273 {
01274
01275
01276 VecPosition posAgent = WM->getAgentGlobalPosition();
01277 AngDeg angBody = WM->getAgentGlobalBodyAngle();
01278 AngDeg ang = (pos - posAgent).getDirection();
01279 Line l = Line::makeLineFromPositionAndAngle(posAgent,ang);
01280 VecPosition posObj = WM->getGlobalPosition( o );
01281 VecPosition posProj = l.getPointOnLineClosestTo( posObj );
01282 double dDistOpp = posProj.getDistanceTo( posObj );
01283 double dDistAgent = posProj.getDistanceTo( posAgent );
01284 VecPosition posShoot;
01285
01286
01287
01288
01289
01290 double dCalcDist;
01291 if( o != OBJECT_ILLEGAL )
01292 {
01293 dCalcDist = (dDistOpp*dDistOpp-dDistAgent*dDistAgent)/(2*dDistAgent);
01294 dCalcDist += dDistAgent;
01295 }
01296 else
01297 dCalcDist = 20;
01298
01299
01300 Log.log( 552, "outplay opponent %d, calc: %f, opp: %f, agent: %f",
01301 SoccerTypes::getIndex( o ) + 1, dCalcDist, dDistOpp, dDistAgent );
01302 Log.log( 560, "outplay opponent %d, calc: %f, opp: %f, agent: %f",
01303 SoccerTypes::getIndex( o ) + 1, dCalcDist, dDistOpp, dDistAgent );
01304
01305 if( dCalcDist > 7.0 )
01306 {
01307 dCalcDist = min( posAgent.getDistanceTo( pos ), dCalcDist - 2.5 );
01308 dCalcDist = min( 20, dCalcDist );
01309 posShoot = posAgent + VecPosition( dCalcDist, ang, POLAR );
01310 }
01311 else if( dDistAgent < dDistOpp - 0.3 )
01312 {
01313 dCalcDist = min( posAgent.getDistanceTo( pos ), 20);
01314 posShoot = posAgent + VecPosition( dCalcDist, ang, POLAR );
01315 }
01316 else
01317 return SoccerCommand( CMD_ILLEGAL );
01318
01319 if( posShoot.getDistanceTo( WM->getAgentGlobalPosition() ) < 2.5 )
01320 {
01321 Log.log( 552, "calculated point too close" );
01322 Log.log( 560, "calculated point too close (%f,%f)", posShoot.getX(),
01323 posShoot.getY() );
01324 return SoccerCommand( CMD_ILLEGAL );
01325 }
01326 else if( WM->getNrInSetInCone( OBJECT_SET_OPPONENTS,PS->getConeWidth(),
01327 posAgent, posShoot ) != 0 )
01328 {
01329 Log.log( 552, "outplay: is opponent in cone" );
01330 Log.log( 560, "outplay: is opponent in cone (%f,%f)", posShoot.getX(),
01331 posShoot.getY() );
01332 return SoccerCommand( CMD_ILLEGAL );
01333 }
01334
01335
01336 AngDeg angTmp = VecPosition::normalizeAngle( ang - angBody ) ;
01337 if( fabs( angTmp ) > 30 )
01338 return turnWithBallTo( ang, PS->getTurnWithBallAngThr(),
01339 PS->getTurnWithBallFreezeThr() );
01340
01341 if( posTo != NULL )
01342 *posTo = posShoot;
01343 return kickTo( posShoot, 0.5 );
01344 }
01345
01375 SoccerCommand BasicPlayer::clearBall( ClearBallT type, SideT s, AngDeg *angMax )
01376 {
01377 VecPosition posBall = WM->getBallPos();
01378 VecPosition posLeft, posRight;
01379 double clearDist = PS->getClearBallDist();
01380
01381 double dPitchY = PITCH_WIDTH / 2.0;
01382 if( type == CLEAR_BALL_DEFENSIVE )
01383 {
01384 posLeft.setVecPosition ( 0, - dPitchY + clearDist );
01385 posRight.setVecPosition( 0, + dPitchY - clearDist );
01386 }
01387 else if( type == CLEAR_BALL_OFFENSIVE )
01388 {
01389 posLeft.setVecPosition ( PENALTY_X - clearDist, - dPitchY + clearDist );
01390 posRight.setVecPosition( PENALTY_X - clearDist, + dPitchY - clearDist );
01391 }
01392 else if( type == CLEAR_BALL_GOAL && posBall.getY() > 0 )
01393 {
01394 posLeft.setVecPosition ( PENALTY_X - 3.0, 0.0 );
01395 posRight.setVecPosition( PITCH_LENGTH/2.0 - 10.0, 0.0 );
01396 }
01397 else if( type == CLEAR_BALL_GOAL && posBall.getY() < 0 )
01398 {
01399 posLeft.setVecPosition ( PITCH_LENGTH/2.0 - 10.0, 0.0 );
01400 posRight.setVecPosition( PENALTY_X - clearDist, 0.0 );
01401 }
01402 else
01403 return SoccerCommand( CMD_ILLEGAL );
01404
01405 if( type != CLEAR_BALL_GOAL && s == SIDE_RIGHT )
01406 posLeft.setY ( 0.0 );
01407 else if( type != CLEAR_BALL_GOAL && s == SIDE_LEFT )
01408 posRight.setY( 0.0 );
01409
01410
01411
01412 AngDeg angLeft = (posLeft - posBall).getDirection();
01413 AngDeg angRight = (posRight - posBall).getDirection();
01414 AngDeg ang = WM->getDirectionOfWidestAngle( posBall, angLeft, angRight,
01415 angMax, PS->getClearBallOppMaxDist() );
01416
01417
01418
01419
01420
01421
01422 Line l1 = Line::makeLineFromPositionAndAngle( posBall, ang );
01423 Line l2 = Line::makeLineFromTwoPoints( posLeft, posRight );
01424 VecPosition posShoot = l1.getIntersection( l2 );
01425 Log.log( 560, "angLeft %f, right %f, best %f point (%f,%f)",
01426 angLeft, angRight, ang, posShoot.getX(), posShoot.getY() );
01427 if( type == CLEAR_BALL_GOAL )
01428 return kickTo( posShoot, SS->getBallSpeedMax() );
01429 else
01430 return kickTo( posShoot, 0.5 );
01431 }
01432
01476 SoccerCommand BasicPlayer::markOpponent( ObjectT o, double dDist, MarkT mark )
01477 {
01478 VecPosition posMark = getMarkingPosition( o, dDist, mark );
01479 return moveToPos( posMark, 30, 3, false );
01480 }
01481
01482
01521 SoccerCommand BasicPlayer::defendGoalLine( double dDist )
01522 {
01523
01524 VecPosition posBall = WM->getBallPos();
01525 VecPosition posAgent = WM->getAgentGlobalPosition();
01526 Line lineGoal = Line::makeLineFromPositionAndAngle(
01527 VecPosition( - PITCH_LENGTH/2.0 + dDist, 0 ), 90 );
01528
01529
01530
01531
01532
01533
01534
01535 VecPosition posGoalLeft ( -PITCH_LENGTH/2.0, -SS->getGoalWidth()/2.0 );
01536 VecPosition posGoalRight( -PITCH_LENGTH/2.0, SS->getGoalWidth()/2.0 );
01537 Line left = Line::makeLineFromTwoPoints( posBall, posGoalLeft );
01538 Line right = Line::makeLineFromTwoPoints( posBall, posGoalRight );
01539 posGoalLeft = left.getIntersection ( lineGoal );
01540 posGoalRight = right.getIntersection( lineGoal );
01541 double dDistLeft = posGoalLeft.getDistanceTo( posBall );
01542 double dDistRight = posGoalRight.getDistanceTo( posBall );
01543 double dDistLine = posGoalLeft.getDistanceTo( posGoalRight );
01544 VecPosition posDefend = posGoalLeft+
01545 VecPosition( 0, (dDistLeft/(dDistLeft+dDistRight))*dDistLine);
01546
01547 bool bBallInPen = WM->isInOwnPenaltyArea( posBall );
01548
01549
01550 if( fabs( posDefend.getY() ) > SS->getGoalWidth()/2.0 )
01551 posDefend.setY( sign(posDefend.getY())*SS->getGoalWidth()/2.0);
01552
01553
01554 double dDiff = ( bBallInPen == true ) ? 2.0 : 0.5;
01555 if( posDefend.getX() + dDiff < posAgent.getX() )
01556 {
01557 Log.log( 553, "move backwards to guard point" );
01558 return moveToPos( posDefend, 30, -1.0, true );
01559 }
01560 else if( posDefend.getX() - dDiff > posAgent.getX() )
01561 {
01562 Log.log( 553, "move forward to guard point" );
01563 return moveToPos( posDefend, 30, -1.0 );
01564 }
01565
01566
01567
01568 AngDeg angDes;
01569 if( fabs( posBall.getY() - posDefend.getY() ) > 0.5 )
01570 angDes = sign( posBall.getY() - posDefend.getY() )*90.0;
01571 else
01572 angDes = sign( WM->getAgentGlobalBodyAngle() )*90.0;
01573 int iSign = sign( WM->getGlobalVelocity( OBJECT_BALL ).getY() );
01574
01575
01576
01577
01578
01579 if( bBallInPen )
01580 {
01581 Log.log( 553, "move along line, with ball in penalty area" );
01582 return moveToPosAlongLine( posDefend, angDes, 3.0, iSign, 7.0, 12.0 );
01583 }
01584 else
01585 {
01586 Log.log( 553, "move along line, with ball outside penalty area (%f,%f) (%f,%f) %f",
01587 WM->getAgentGlobalPosition().getX(),
01588 WM->getAgentGlobalPosition().getY(),
01589 posBall.getX(), posBall.getY(), WM->getConfidence( OBJECT_BALL) );
01590 Log.log( 553, "%s", WM->strLastSeeMessage );
01591 return moveToPosAlongLine( posDefend, angDes, 0.5, iSign, 2.0, 12.0 );
01592 }
01593 }
01594
01595
01596
01597
01611 VecPosition BasicPlayer::getInterceptionPointBall( int *iCyclesBall,
01612 bool isGoalie )
01613 {
01614 VecPosition posPred = WM->getAgentGlobalPosition();
01615 VecPosition velMe = WM->getAgentGlobalVelocity();
01616 double dSpeed, dDistExtra;
01617 VecPosition posMe, posBall;
01618 AngDeg ang, angBody, angNeck;
01619 Stamina sta;
01620 double dMaxDist;
01621
01622 dMaxDist = (isGoalie) ? SS->getCatchableAreaL() : SS->getMaximalKickDist();
01623
01624
01625 dSpeed = WM->getAgentSpeed();
01626 dDistExtra = Geometry::getSumInfGeomSeries( dSpeed, SS->getPlayerDecay() );
01627 posPred += VecPosition( dDistExtra, velMe.getDirection(), POLAR );
01628
01629
01630 for ( int i = 0; i <= 100; i++ )
01631 {
01632
01633
01634 velMe = WM->getAgentGlobalVelocity();
01635 angBody = WM->getAgentGlobalBodyAngle();
01636 angNeck = WM->getAgentGlobalNeckAngle();
01637 posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, i + 1 );
01638 posMe = WM->getAgentGlobalPosition();
01639 ang = (posBall - posPred).getDirection();
01640 ang = VecPosition::normalizeAngle( ang - angBody );
01641 sta = WM->getAgentStamina();
01642 int turn = 0;
01643
01644
01645 while (fabs(ang) > PS->getPlayerWhenToTurnAngle() && turn<5)
01646 {
01647 turn++;
01648 WM->predictStateAfterTurn( WM->getAngleForTurn( ang,velMe.getMagnitude() ),
01649 &posMe, &velMe, &angBody, &angNeck, &sta );
01650 ang = (posBall - posPred).getDirection();
01651 ang = VecPosition::normalizeAngle( ang - angBody );
01652 }
01653
01654 if( turn > 1 )
01655 {
01656 Log.log( 502, "nr of turns needed: %d", turn );
01657 }
01658
01659
01660 for( ; turn < i; turn++ )
01661 WM->predictStateAfterDash(SS->getMaxPower(),&posMe,&velMe,&sta,angBody);
01662
01663
01664 if (posMe.getDistanceTo( posBall ) < dMaxDist ||
01665 (posMe.getDistanceTo( posPred ) > posBall.getDistanceTo( posPred ) +
01666 dMaxDist) )
01667 {
01668 *iCyclesBall = i;
01669 return posBall;
01670 }
01671 }
01672 *iCyclesBall = -1;
01673 return posBall;
01674 }
01675
01687 VecPosition BasicPlayer::getShootPositionOnLine( VecPosition p1,
01688 VecPosition p2, AngDeg *angLargest )
01689 {
01690 VecPosition posBall = WM->getBallPos();
01691 Line line = Line::makeLineFromTwoPoints( p1, p2 );
01692 double dRadius = min( PS->getClearBallOppMaxDist(),
01693 posBall.getDistanceTo( p2 ) );
01694 AngDeg angMin = (p1 - posBall ).getDirection();
01695 AngDeg angMax = (p2 - posBall ).getDirection();
01696
01697 AngDeg angShoot = WM->getDirectionOfWidestAngle(
01698 posBall, min(angMin, angMax),
01699 max(angMin,angMax), angLargest, dRadius );
01700 Line line2 = Line::makeLineFromPositionAndAngle( posBall,
01701 angShoot );
01702 return line.getIntersection( line2 );
01703 }
01704
01718 double BasicPlayer::getEndSpeedForPass( ObjectT o, VecPosition posPass )
01719 {
01720
01721
01722 VecPosition posBall = WM->getBallPos();
01723 double dDist = posBall.getDistanceTo( posPass );
01724 double dLength = WM->predictNrCyclesToPoint( o, posPass,
01725 PS->getPlayerWhenToTurnAngle() );
01726 double dFirst = WM->getFirstSpeedFromDist( dDist, dLength );
01727 if( dFirst > SS->getBallSpeedMax() )
01728 dFirst = SS->getBallSpeedMax();
01729 double dEnd = WM->getEndSpeedFromFirstSpeed( dFirst, dLength );
01730 if( dEnd > PS->getPassEndSpeed() )
01731 dEnd = PS->getPassEndSpeed();
01732 else if( dEnd < 0.5 )
01733 dEnd = 0.5;
01734 else if( dLength > 10.0 )
01735 dEnd = 0.5;
01736
01737 return dEnd;
01738 }
01739
01762 VecPosition BasicPlayer::getMarkingPosition( ObjectT o, double dDist, MarkT mark)
01763 {
01764 VecPosition posBall = WM->predictPosAfterNrCycles( OBJECT_BALL, 3 );
01765 VecPosition posGoal = WM->getPosOwnGoal( );
01766 VecPosition pos = WM->getGlobalPosition( o ) - VecPosition( 1.0, 0.0 );
01767 VecPosition posMark;
01768 AngDeg ang, angToGoal, angToBall;
01769
01770 if( mark == MARK_GOAL )
01771 {
01772 angToGoal = (posGoal-pos).getDirection( );
01773 posMark = pos + VecPosition( dDist, angToGoal, POLAR );
01774 }
01775 else if( mark == MARK_BALL )
01776 {
01777 angToBall = (posBall-pos).getDirection( );
01778 posMark = pos + VecPosition( dDist, angToBall, POLAR );
01779 }
01780 else if( mark == MARK_BISECTOR )
01781 {
01782 angToBall = (posBall - pos).getDirection( );
01783 angToGoal = (posGoal - pos).getDirection( );
01784 ang = getBisectorTwoAngles( angToBall, angToGoal );
01785 posMark = pos + VecPosition( dDist, ang ,POLAR );
01786 }
01787 return posMark;
01788 }