#include "Player.h"
SoccerCommand Player::deMeer5_Defender()
{
SoccerCommand soc(CMD_ILLEGAL);
if (WM->isBeforeKickOff())
{
// if not in kickoff formation, teleport to kick_off formation
if (formations->getFormation() != FT_INITIAL || WM->getAgentGlobalPosition().getDistanceTo(WM->getStrategicPosition()) > 2.0)
{
formations->setFormation(FT_INITIAL);
soc = teleportToPos(WM->getStrategicPosition());
}
// else turn to front
else
{
soc = turnBodyToPoint(WM->getAgentGlobalPosition() + VecPosition(1, 0), 0);
ACT->putCommandInQueue(alignNeckWithBody());
}
}
else
{
Log.log(100, " windywinter4defender");
soc = windywinter4defender();
}
ACT->putCommandInQueue(soc);
ACT->putCommandInQueue(WM->getChangeViewCommand());
return soc;
}
SoccerCommand Player::windywinter4defender()
{
SoccerCommand soc(CMD_ILLEGAL);
ObjectT ClosestTeamMate = WM->getClosestRelativeInSet(OBJECT_SET_TEAMMATES);
ObjectT ClosestOpponent = WM->getClosestRelativeInSet(OBJECT_SET_OPPONENTS);
int iTmp;
PS->setBallConfThr(0.95);
PS->setTackleHighConfThr(0.75);
// if ball pos unknown, search for it
if (WM->getConfidence(OBJECT_BALL) < PS->getBallConfThr())
{
Log.log(100, " search ball");
soc = searchBall();
ACT->putCommandInQueue(alignNeckWithBody());
WM->setChangeViewCommand(SoccerCommand(CMD_CHANGEVIEW, VA_NARROW, VQ_HIGH));
}
// if kickable (which means the ball is in kickable range and the play mode allows us to kick)
else if (WM->isBallKickable())
{
if (WM->isDeadBallUs() && WM->isInOwnPenaltyArea(WM->getBallPos()))
{
Log.log(100, " dead ball in penalty area");
AngDeg angBall = (WM->getBallPos() - WM->getAgentGlobalPosition()).getDirection();
angBall = VecPosition::normalizeAngle(angBall - 90);
VecPosition pos = WM->getBallPos() + VecPosition(2, angBall, POLAR);
soc = moveToPos(pos, PS->getPlayerWhenToTurnAngle());
ACT->putCommandInQueue(lookaround(soc));
}
// if close to opponent goal or goalie and not an indirect free kick, shoot
if ((WM->getAgentGlobalPosition().getDistanceTo(WM->getPosOpponentGoal()) < 12.0 || WM->getAgentGlobalPosition().getDistanceTo(WM->getGlobalPosition(OBJECT_OPPONENT_GOALIE)) < 3.0)
&& !WM->isIndirectFreeKickUs())
{
Log.log(100, " shoot");
Line shoot_line_1 = Line::makeLineFromTwoPoints(WM->getBallPos(), WM->getPosOpponentGoalTop());
Line shoot_line_2 = Line::makeLineFromTwoPoints(WM->getBallPos(), WM->getPosOpponentGoalBottom());
double distance_1 = shoot_line_1.getDistanceWithPoint(WM->predictPosAfterNrCycles(OBJECT_OPPONENT_GOALIE, 1));
double distance_2 = shoot_line_2.getDistanceWithPoint(WM->predictPosAfterNrCycles(OBJECT_OPPONENT_GOALIE, 1));
VecPosition posGoal;
double shoot_range = max(SS->getGoalWidth() * WM->getAgentGlobalPosition().getDistanceTo(WM->getPosOpponentGoal()) / PITCH_LENGTH, 0.3);
if (distance_1 < distance_2)
{
posGoal = WM->getPosOpponentGoalBottom() - shoot_range;
}
else
{
posGoal = WM->getPosOpponentGoalTop() + shoot_range;
}
soc = kickTo(posGoal, SS->getBallSpeedMax()); // kick maximal
ACT->putCommandInQueue(lookaround(soc));
WM->setChangeViewCommand(SoccerCommand(CMD_CHANGEVIEW, VA_NARROW, VQ_HIGH));
}
// prepare to take dead ball, look for teammates first
else if (WM->isDeadBallUs() && WM->getConfidence(ClosestTeamMate) < 0.98)
{
Log.log(100, " our dead ball, search for teammate");
soc = SoccerCommand(CMD_TURN, VecPosition::normalizeAngle(WM->getAgentGlobalBodyAngle() + 60));
ACT->putCommandInQueue(alignNeckWithBody());
WM->setChangeViewCommand(SoccerCommand(CMD_CHANGEVIEW, VA_NARROW, VQ_HIGH));
}
else if (WM->getBallPos().getX() < -10.0
&& WM->getActualKickPowerRate(WM->getClosestInSetTo(OBJECT_SET_OPPONENTS, OBJECT_BALL)) > 0.75//对于球相对于当前agent的位置,计算实际踢球力量的比率。
&& WM->getProbTackleSucceeds() > PS->getTackleHighConfThr())//agent铲球成功的概率>
{
Log.log(100, " too dangerous, tackle it");
Line body = Line::makeLineFromPositionAndAngle(WM->getAgentGlobalPosition(), WM->getAgentGlobalBodyAngle());
Line bottom = Line::makeLineFromTwoPoints(VecPosition(-PITCH_LENGTH/2, 7.01), VecPosition(-PITCH_LENGTH/2, -7.01));
if (fabs(body.getIntersection(bottom).getY())>8.0)
{
soc = tackle(WM->getAgentGlobalBodyAngle());
}
else
{
VecPosition agent_to_top = VecPosition(-PITCH_LENGTH/2, PITCH_WIDTH/2) - WM->getAgentGlobalPosition();
VecPosition agent_to_bottom = VecPosition(-PITCH_LENGTH/2, -PITCH_WIDTH/2) - WM->getAgentGlobalPosition();
VecPosition agent_body = VecPosition(1, WM->getAgentGlobalBodyAngle(), POLAR);
if (agent_body.getAngleTo(agent_to_top) < agent_body.getAngleTo(agent_to_bottom))
{
soc = tackle(agent_to_top.getDirection());
}
else
{
soc = tackle(agent_to_bottom.getDirection());
}
}
}
else
{
soc = getBestPassCmd_Defender();
if (soc.commandType == CMD_ILLEGAL)
{
soc = getSecondPassCmd_Defender(8);
}
// pass ball (for both play on and dead ball)
if (soc.commandType != CMD_ILLEGAL)
{
Log.log(100, " pass ball");
// prevent too smart kick
if (WM->isDeadBallUs() && soc.dPower < 30.0) soc.dPower = 100.0;
ACT->putCommandInQueue(lookaround(soc));
}
// if no one to pass, stamina high and not a dead ball, dribble
else if (WM->getAgentStamina().getStamina() > SS->getRecoverDecThr() * SS->getStaminaMax() + 800
&& !WM->isDeadBallUs())
{
ObjectT ClosestOpponentAhead = WM->getClosestAheadRelativeInSet(OBJECT_SET_OPPONENTS);
double disToOpp=WM->getAgentGlobalPosition().getDistanceTo(WM->getGlobalPosition(ClosestOpponentAhead));
if (ClosestOpponentAhead==OBJECT_ILLEGAL || disToOpp>5)
{
soc=dribble((WM->getPosOpponentGoal()-WM->getBallPos()).getDirection(),6);
}
else if (disToOpp>2)
{
double angOpp=VecPosition::normalizeAngle(WM->getGlobalBodyAngle(ClosestOpponentAhead));//标准化角度。(-180,180)
double outPlayAng;
if ((angOpp>=0)&&(angOpp<180)) outPlayAng=fabs(VecPosition::normalizeAngle(angOpp+45));
else outPlayAng=fabs(VecPosition::normalizeAngle(angOpp-45));
soc=dribble(outPlayAng,5);
Log.log(100,"dangerous outPlayAng is %lf ",outPlayAng);
}
else
{
Log.log(100, " no one to pass the ball, kick to opponent goal");
VecPosition posGoal(PITCH_LENGTH / 2.0, (-1 + 2 * (WM->getCurrentCycle() % 2)) * 0.4 * SS->getGoalWidth());
soc = kickTo(posGoal, SS->getBallSpeedMax());
Log.log(100,"hold ball");
}
ACT->putCommandInQueue(lookaround(soc));
}
else
{
Log.log(100, " no one to pass the ball, kick to opponent goal");
VecPosition posGoal(PITCH_LENGTH / 2.0, (-1 + 2 * (WM->getCurrentCycle() % 2)) * 0.4 * SS->getGoalWidth());
soc = kickTo(posGoal, SS->getBallSpeedMax());
ACT->putCommandInQueue(lookaround(soc));
}
WM->setChangeViewCommand(SoccerCommand(CMD_CHANGEVIEW, VA_NARROW, VQ_HIGH));
}
}
// if we get a dead ball, and it's not in our penalty area (if is, the goalie will take it sooner or later)
// if this player is closest to the ball, he will go to take the ball
else if (WM->isDeadBallUs() && !WM->isBallInOwnPenaltyArea()
&& WM->getClosestInSetTo(OBJECT_SET_TEAMMATES_NO_GOALIE, OBJECT_BALL) == WM->getAgentObjectType())
{
Log.log(100, " go to take dead ball");
// if not in position, move to position
if (WM->getRelativeDistance(OBJECT_BALL) >= SS->getPlayerSize()+0.05)
{
soc = moveToPos(getDeadBallPosition(), 5); // move to take dead ball
// if stamina low, dash slowly
if (soc.commandType == CMD_DASH && WM->getAgentStamina().getStamina() < SS->getRecoverDecThr() * SS->getStaminaMax() + 800)
{
Log.log(100, " but stamina is too low");
soc.dPower = min(30.0 * WM->getAgentStamina().getRecovery(), soc.dPower*0.3);
}
ACT->putCommandInQueue(lookaround(soc));
}
// else wait till kickable signal
else
{
soc = turnBodyToPoint(WM->getPosOpponentGoal());
ACT->putCommandInQueue(lookaround(soc));
}
WM->setChangeViewCommand(SoccerCommand(CMD_CHANGEVIEW, VA_NARROW, VQ_HIGH));
}
// if this player is 2nd closest to the ball, he will go to back up the 1st one
else if (WM->isDeadBallUs() && !WM->isBallInOwnPenaltyArea()
&& WM->getSecondClosestInSetTo(OBJECT_SET_TEAMMATES_NO_GOALIE, OBJECT_BALL) == WM->getAgentObjectType())
{
Log.log(100, " go to backup dead ball");
// if not in position, move to position
if (WM->getRelativeDistance(OBJECT_BALL) >= SS->getOffsideKickMargin())
{
soc = moveToPos(getDeadBallBackUpPosition(), 5); // move to take dead ball
// if stamina low, dash slowly
if (soc.commandType == CMD_DASH && WM->getAgentStamina().getStamina() < SS->getRecoverDecThr() * SS->getStaminaMax() + 800)
{
Log.log(100, " but stamina is too low");
soc.dPower = min(30.0 * WM->getAgentStamina().getRecovery(), soc.dPower*0.3);
}
ACT->putCommandInQueue(lookaround(soc));
}
// else wait till kickable signal
else
{
soc = turnBodyToPoint(WM->getBallPos());
ACT->putCommandInQueue(lookaround(soc));
}
WM->setChangeViewCommand(SoccerCommand(CMD_CHANGEVIEW, VA_NARROW, VQ_HIGH));
}
// if opponents get a dead ball in forward and this player can get there in time, go to set up a wall
else if (WM->isDeadBallThem() && WM->getBallPos().getX()<-15 && WM->predictNrCyclesToPoint(WM->getAgentObjectType(), WM->getBallPos()) < 18)
{//预测对象从当前位置移动到posTo所需的周期数。
Log.log(100, " set up wall of players");
VecPosition pos = getDeadBallDefencePosition();
if (WM->getAgentGlobalPosition().getDistanceTo(pos) > SS->getPlayerSize())
{
Log.log(100, " move to pos (%f,%f)", pos.getX(), pos.getY());
soc = moveToPos(pos, 20);
VecPosition pos = getDeadBallDefencePosition();
ACT->putCommandInQueue(lookaround(soc));
}
else
{
soc = turnBodyToPoint(WM->getBallPos());
ACT->putCommandInQueue(alignNeckWithBody());
}
WM->setChangeViewCommand(SoccerCommand(CMD_CHANGEVIEW, VA_NARROW, VQ_HIGH));
}
// if opponents possess ball and it's safe to tackle it, tackle
else if (WM->getBallPos().getX() < -10.0
&& WM->isBallInTheirPossesion()//拥有球·-
&& WM->getProbTackleSucceeds() > PS->getTackleHighConfThr() * min(WM->getBallPos().getDistanceTo(WM->getPosOwnGoal())/30.0, (WM->getBallPos()-WM->getGlobalPosition(WM->getLastDefender())).getX()<0 ? 0.5 : 1))
{
Log.log(100, " too dangerous, tackle it");
// tackle to closest teammate
if (ClosestTeamMate != OBJECT_ILLEGAL)
{
soc = tackle((WM->getGlobalPosition(ClosestTeamMate) - WM->getAgentGlobalPosition()).getDirection());
}
// tackle to body angle
else
{
Line body = Line::makeLineFromPositionAndAngle(WM->getAgentGlobalPosition(), WM->getAgentGlobalBodyAngle());
Line bottom = Line::makeLineFromTwoPoints(VecPosition(-PITCH_LENGTH/2, 7.01), VecPosition(-PITCH_LENGTH/2, -7.01));
if (fabs(body.getIntersection(bottom).getY())>8.0)
{
soc = tackle(WM->getAgentGlobalBodyAngle());
}
else
{
VecPosition agent_to_top = VecPosition(-PITCH_LENGTH/2, PITCH_WIDTH/2) - WM->getAgentGlobalPosition();
VecPosition agent_to_bottom = VecPosition(-PITCH_LENGTH/2, -PITCH_WIDTH/2) - WM->getAgentGlobalPosition();
VecPosition agent_body = VecPosition(1, WM->getAgentGlobalBodyAngle(), POLAR);
if (agent_body.getAngleTo(agent_to_top) < agent_body.getAngleTo(agent_to_bottom))
{
soc = tackle(agent_to_top.getDirection());
}
else
{
soc = tackle(agent_to_bottom.getDirection());
}
}
}
ACT->putCommandInQueue(turnNeckToObject(OBJECT_BALL, soc));
WM->setChangeViewCommand(SoccerCommand(CMD_CHANGEVIEW, VA_NORMAL, VQ_HIGH));
}
else
{
int cycles_opponent_to_ball, cycles_fastest_to_ball, cycles_intercept;
ObjectT obj_fastest_to_ball = WM->getFastestInSetTo(OBJECT_SET_TEAMMATES_NO_GOALIE, OBJECT_BALL, &cycles_fastest_to_ball);
WM->predictCommandToInterceptBall(WM->getAgentObjectType(), interceptClose(), &cycles_intercept);
WM->getFastestInSetTo(OBJECT_SET_OPPONENTS, OBJECT_BALL, &cycles_opponent_to_ball);
// if fastest to ball, intercept it
if ((obj_fastest_to_ball == WM->getAgentObjectType() || (cycles_intercept<=cycles_fastest_to_ball+2/* && cycles_opponent_to_ball<=cycles_fastest_to_ball+2*/))
&& !WM->isDeadBallThem() && !WM->isDeadBallUs()
&& WM->getBallPos().getDistanceTo(WM->getGlobalPosition(OBJECT_TEAMMATE_1)) > 1.085)
{
Log.log(100, " fastest to ball; can get there in %d cycles", cycles_intercept);
soc = intercept(false);
if ((WM->getCurrentTime().getTime()+WM->getCurrentTime().getTimeStopped())%2 == 1)
{
ACT->putCommandInQueue(turnNeckToObject(OBJECT_BALL, soc));
}
else
{
ACT->putCommandInQueue(lookaround(soc));
}
WM->setChangeViewCommand(SoccerCommand(CMD_CHANGEVIEW, VA_NARROW, VQ_HIGH));
}
else
{
// find most valuable player to mark, if there is one and the ball is not in safe position
pair<double, ObjectT> mark_target = getMostValuableMarkObj();
if (WM->getBallPos().getX() < 6.0
&& mark_target.second != OBJECT_ILLEGAL && mark_target.first<10000 && WM->getGlobalPosition(mark_target.second).getX() < 0
&& !WM->isDeadBallUs() && (!WM->isDeadBallThem() || WM->isDeadBallThem() && WM->getRelativeDistance(OBJECT_BALL) > SS->getOffsideKickMargin()))
{
// if the obj is fastest to ball, mark ball instead
Log.log(100, " mark %d, profit %f", SoccerTypes::getIndex(mark_target.second)+1, mark_target.first);
if (WM->getFastestInSetTo(OBJECT_SET_OPPONENTS, OBJECT_BALL, &iTmp) == mark_target.second)
{
mark_target.second = OBJECT_BALL;
}
soc = mark(mark_target.second, 3.0, MARK_GOAL);
// calculate save_stamina_rate
double save_stamina_rate = 0.9* min(1+WM->getBallPos().getX()/((PITCH_LENGTH-PENALTY_AREA_LENGTH)/2), WM->getBallPos().getDistanceTo(WM->getGlobalPosition(mark_target.second)/(PITCH_LENGTH-PENALTY_AREA_LENGTH)));
VecPosition target_to_ball = WM->getBallPos()-WM->getGlobalPosition(mark_target.second);
VecPosition target_speed = WM->getGlobalVelocity(mark_target.second);
if (target_speed.getAngleTo(target_to_ball) < 20.0) save_stamina_rate/=2;
if (save_stamina_rate > 0.9) save_stamina_rate = 0.9;
// if stamina low, dash slowly
if (soc.commandType == CMD_DASH && WM->getAgentStamina().getStamina() < save_stamina_rate * SS->getStaminaMax() )
{
soc.dPower = min(30.0 * WM->getAgentStamina().getRecovery(), soc.dPower*0.3);
Log.log(100, " but stamina is too low");
}
if (mark_target.second == OBJECT_BALL)
{
if (WM->getRelativeDistance(OBJECT_BALL) > 3.0)
{
ACT->putCommandInQueue(turnNeckToPoint(WM->getBallPos(), soc));
}
else
{
ACT->putCommandInQueue(lookaround(soc));
}
}
else if (WM->getRelativeDistance(mark_target.second) < 6.0
&& WM->getTimeGlobalAngles(mark_target.second) == WM->getCurrentTime())
{
ACT->putCommandInQueue(turnNeckToPoint(WM->getGlobalPosition(mark_target.second) + VecPosition(12, WM->getGlobalNeckAngle(mark_target.second), POLAR), soc));
}
else
{
ACT->putCommandInQueue(turnNeckToPoint(WM->getGlobalPosition(mark_target.second), soc));
}
WM->setChangeViewCommand(SoccerCommand(CMD_CHANGEVIEW, VA_NARROW, VQ_HIGH));
}
// else if not near strategic pos, go to strategic pos
else if (WM->getAgentGlobalPosition().getDistanceTo(WM->getStrategicPosition()) > SS->getPlayerSize()*4 /*+ fabs(WM->getAgentGlobalPosition().getX() - WM->getBallPos().getX()) / 10.0*/)
{
Log.log(100, " move to strategic position");
soc = moveToPos(WM->getStrategicPosition(), PS->getPlayerWhenToTurnAngle());
// calculate save_stamina_rate
double save_stamina_rate = 0.9;
if (WM->getAgentGlobalPosition().getX() < WM->getGlobalPosition(WM->getFirstOpponent()).getX())
{
save_stamina_rate = 0.3;
}
// if stamina low, dash slowly
if (soc.commandType == CMD_DASH && WM->getAgentStamina().getStamina() < save_stamina_rate * SS->getStaminaMax() )
{
soc.dPower = min(30.0 * WM->getAgentStamina().getRecovery(), soc.dPower*0.3);
Log.log(100, " but stamina is too low");
}
if ((WM->getCurrentTime().getTime()+WM->getCurrentTime().getTimeStopped())%2 == 1)
{
ACT->putCommandInQueue(turnNeckToObject(OBJECT_BALL, soc));
}
else
{
ACT->putCommandInQueue(lookaround(soc));
}
WM->setChangeViewCommand(SoccerCommand(CMD_CHANGEVIEW, VA_NARROW, VQ_HIGH));
}
// nothing to do
else
{
Log.log(100, " nothing to do but watching ball or looking around");
if (WM->isDeadBallUs())
{
if ((WM->getCurrentTime().getTime()+WM->getCurrentTime().getTimeStopped())%2 == 1)
{
ACT->putCommandInQueue(turnNeckToObject(OBJECT_BALL, soc));
}
else
{
ACT->putCommandInQueue(lookaround(soc));
}
ACT->putCommandInQueue(turnNeckToObject(OBJECT_BALL, soc));
}
else
{
soc = turnBodyToPoint(WM->getAgentGlobalPosition() + VecPosition(1, 0), 0);
ACT->putCommandInQueue(lookaround(soc));
}
WM->setChangeViewCommand(SoccerCommand(CMD_CHANGEVIEW, VA_NARROW, VQ_HIGH));
}
}
}
return soc;
}
SoccerCommand BasicPlayer::getBestPassCmd_Defender()
{
static Feature last_best_cmd;
if (last_best_cmd.getTimeSee() > WM->getCurrentTime()-2 && last_best_cmd.getCommand().commandType != CMD_ILLEGAL
&& WM->getMinEndSpeed4SafePass(last_best_cmd.getVec()) > 0
&& (WM->isOnside(last_best_cmd.getObject()) || !WM->isOnside(WM->getAgentObjectType())))//判断对象是否未越位。
{
Log.log(101, " pass to same pos as last cycle");
return kickTo(last_best_cmd.getVec(), last_best_cmd.getInfo());
}
SoccerCommand soc(CMD_ILLEGAL);
double max_pass_profit = 0.1;
VecPosition best_pass_target = VecPosition(UnknownDoubleValue, UnknownDoubleValue);
ObjectT best_pass_target_o = OBJECT_ILLEGAL;
double best_pass_speed = -1.0;
int iIndex;
for (ObjectT o = WM->iterateObjectStart(iIndex, OBJECT_SET_TEAMMATES_NO_GOALIE, PS->getPlayerHighConfThr()); o != OBJECT_ILLEGAL;
o = WM->iterateObjectNext(iIndex, OBJECT_SET_TEAMMATES_NO_GOALIE, PS->getPlayerHighConfThr()))
{
if (o != WM->getAgentObjectType() && (WM->isOnside(o) || !WM->isOnside(WM->getAgentObjectType())))
{
Log.log(101, " calculating pass to %d", SoccerTypes::getIndex(o)+1);
double confidence = WM->getConfidence(o);
for (AngDeg leading_dir = -180.0; leading_dir <= 180.0; leading_dir += 30.0)
{
if (WM->getTimeGlobalAngles(o) > WM->getCurrentTime()-4)//time储存了身体和脖子的角度
{
confidence *= cos(VecPosition::normalizeAngle(leading_dir - WM->getGlobalBodyAngle(o))/180 * PI/2)/2 + 0.5;
}
else
{
confidence *= 0.5;
}
for (double leading_dist = 0; leading_dist <= 4.0; leading_dist += 1.0)
{
VecPosition pass_target = WM->getGlobalPosition(o) + VecPosition(leading_dist, leading_dir, POLAR);
double distX = pass_target.getX() - WM->getBallPos().getX();
double posY = fabs(pass_target.getY());
if (pass_target.getX()>30)
{
posY = PITCH_WIDTH / 2.0 - posY;
}
distX = min(24.0, distX);
double profit = sin(distX/24.0*PI)*24.0 * posY/4.0;
if (profit*confidence > max_pass_profit)
{
int pass_cycles;
ObjectT fastest_opponent;
double min_pass_speed = WM->getMinEndSpeed4SafePass(pass_target, &fastest_opponent, &pass_cycles);
if (min_pass_speed > 0)
{
int cycles_o = WM->predictNrCyclesToPoint(o, pass_target);
if (cycles_o <= pass_cycles)
{
int safety_cycles = min(3, WM->predictNrCyclesToPoint(fastest_opponent, pass_target) - pass_cycles);
double max_pass_speed = WM->getEndSpeedFromFirstSpeed(WM->getBallPos().getDistanceTo(pass_target) *(1-SS->getBallDecay()) / (1- pow(SS->getBallDecay(), cycles_o+1)), cycles_o);
//profit += min_pass_speed*4;
confidence *= fabs(sin(min(1.0, safety_cycles/3.0)* PI/2));
profit *= confidence;
if (profit > max_pass_profit)
{
max_pass_profit = profit;
best_pass_target = pass_target;
best_pass_speed = (min_pass_speed+max_pass_speed)/2;
best_pass_target_o = o;
}
Log.log(102, " pos (%f,%f) profit %f", pass_target.getX(), pass_target.getY(), profit);
}
}
}
}
}
}
}
WM->iterateObjectDone(iIndex);
if (best_pass_target_o != OBJECT_ILLEGAL)
{
soc = kickTo(best_pass_target, best_pass_speed);
last_best_cmd.setTimeSee(WM->getCurrentTime());
last_best_cmd.setVec(best_pass_target);
last_best_cmd.setInfo(best_pass_speed);
last_best_cmd.setObject(best_pass_target_o);
Log.log(101, " pass to %d pos (%f,%f) profit %f", SoccerTypes::getIndex(best_pass_target_o)+1, best_pass_target.getX(), best_pass_target.getY(), max_pass_profit);
}
return soc;
}
SoccerCommand BasicPlayer::getSecondPassCmd_Defender(double minPassProfit)
{
return getSecondPassCmd_Attacker(minPassProfit);
}