📄 dribble_around.c
字号:
|| (WSinfo::me->ang.get_value_mPI_pPI()>0 && WSinfo::me->pos.x<0))) ||(amICloseToFieldYBorder && ((fabs(WSinfo::me->ang.get_value_mPI_pPI())>DEG2RAD(90) && WSinfo::me->pos.y<0) || (fabs(WSinfo::me->ang.get_value_mPI_pPI())<DEG2RAD(90) && WSinfo::me->pos.y>0))); bool keepBallOnLeftSide = (!opp && isBallOnLeftSide) // no opponent and ball is on left side || ( opp // opponent ahead and ball left && oppOnMyLine && isBallOnLeftSide) || ( opp // opponent is on right side && !oppOnLeftSide && ( isBallOnLeftSide || ballChangeSidePossible)) || ( opp // opponent is on left side && oppOnLeftSide && isBallOnLeftSide && !ballChangeSidePossible) || isFieldBorderOnLeftSide; bool haveToSwitchSides = ( isBallOnLeftSide && !keepBallOnLeftSide) ||(!isBallOnLeftSide && keepBallOnLeftSide); haveToSwitchSides = haveToSwitchSides && ballChangeSidePossible; bool switchSidesBehind = haveToSwitchSides && ( (distToOpp<4 // close to opp && oppStraightAhead) // who is directly ahead || (toBallFlAbs>DEG2RAD(90) // ball behind me anyway && !(oppStraightBehind // no opponent behind me && distToOpp<4)) // who is close ); Vector lot; Geometry2d::projection_to_line(lot, WSinfo::ball->pos, Line2d(WSinfo::me->pos,Vector(WSinfo::me->ang))); bool ballAhead = lot.distance(WSinfo::ball->pos)<1.1*ServerOptions::player_size; bool ballPosOKForAdvancing = !haveToSwitchSides && !ballAhead && toBallFlAbs<DEG2RAD(135) // not too straight behind // && WSinfo::me->pos.distance(WSinfo::ball->pos)>0.5 // TODO: is this necessary? // avoid kicking when ball is far to left/right && (WSinfo::ball->pos.distance(WSinfo::me->pos) < (0.9*WSinfo::me->kick_radius) || toBallFlAbs<DEG2RAD(75) || toBallFlAbs>DEG2RAD(105)); bool closestOppDirectlyBehindMe = opp && fabs(Tools::my_angle_to(opp->pos).get_value_mPI_pPI())>DEG2RAD(100) && !nextOppToMe.reachesPos; bool breakThruOffsideLine = WSinfo::his_team_pos_of_offside_line() - WSinfo::me->pos.x < 1.5 && dribbleTo.x > WSinfo::his_team_pos_of_offside_line(); bool closestOppInMeWrongDir = opp && fabs((opp->ang - WSinfo::me->ang).get_value_mPI_pPI())>DEG2RAD(70) && opp->pos.distance(WSinfo::me->pos) < 1.5*WSinfo::me->kick_radius; bool ignoreClosestOpp = closestOppDirectlyBehindMe ||closestOppInMeWrongDir ||breakThruOffsideLine; bool dontAdvanceChased = opp && fabs(Tools::my_angle_to(opp->pos).get_value_mPI_pPI())>DEG2RAD(100) && opp->pos.distance(WSinfo::me->pos)<1.4*WSinfo::me->kick_radius && fabs((opp->vel.ARG()-WSinfo::me->ang).get_value_mPI_pPI())<DEG2RAD(30) && opp->vel.norm() > 0.4*opp->speed_max && (opp->vel.norm()>WSinfo::me->vel.norm()); POL2("getKickAhead: Chase! Do not advance."); ANGLE deviate(keepBallOnLeftSide?DEG2RAD(10):DEG2RAD(-10)); if(ballPosOKForAdvancing && !dontAdvanceChased){ if(getKickAheadBallOK(cmd,ANGLE(0),ignoreClosestOpp)) return true; else if(getKickAheadPrepareBall(cmd,keepBallOnLeftSide,true)) return true; } if(ballAhead && !dontAdvanceChased){ if(getKickAheadBallOK(cmd,deviate,ignoreClosestOpp)){ POL("getKickAhead: BallPos not OK, deviating from 0?"); return true; } } if(getKickAheadPrepareBall(cmd,keepBallOnLeftSide,switchSidesBehind)) return true; Vector safestPos, bestPos; getTargetsInMe(safestPos, bestPos); bool chased = (Tools::my_angle_to(bestPos).get_value_mPI_pPI() < PI/7 // best dest ahead && nextOppToMe.pos.distance(bestPos)<0.4 && fabs(Tools::my_angle_to(WSinfo::ball->pos).get_value_mPI_pPI())<PI/3); // ball ahead of me if(chased){ if(getKickAheadBallOK(cmd,deviate,true)){ POL("getKickAhead: chased, deviating from 0?, ignoring closest opp"); return true; } } if(getCmdKickToDest(cmd,bestPos,true,false)){ POL("getKickAhead: Kicking to best Pos in Dir."); lastActionTaken = DA_KICK_AHEAD; MARK_POS(bestPos, blue); return true; }; if(getCmdKickToDest(cmd,safestPos,true,false)){ POL("getKickAhead: Kicking to safest Pos."); lastActionTaken = DA_KICK_AHEAD; MARK_POS(safestPos, blue); return true; }; return false;}// getKickAheadBallOK {{{2bool DribbleAround::getKickAheadBallOK(Cmd& cmd, ANGLE deviate, bool ignoreClosestOpp){ POL2("In getKickAheadBallOK(), ignoreClosestOpp="<<ignoreClosestOpp); ANGLE kick_angle = WSinfo::me->ang + deviate; Cmd tmpCmd; Vector new_my_pos,new_my_vel,new_ball_pos,new_ball_vel; Vector old_new_my_pos,old_new_my_vel; ANGLE new_my_ang; bool goingInXDir = dribbleTo.x > WSinfo::me->pos.x + 5; bool haventLookedThere = WSmemory::last_seen_in_dir(Tools::my_angle_to(dribbleTo))>3; const int maxLookAhead = (!goingInXDir || opp&&opp->age>1)?1:8; Vector afterNdash[maxLookAhead+1]; // kicking == doing nothing basic_cmd->set_dash(0); basic_cmd->get_cmd(tmpCmd); Tools::model_cmd_main(WSinfo::me->pos,WSinfo::me->vel,WSinfo::me->ang,WSinfo::ball->pos,WSinfo::ball->vel,tmpCmd.cmd_main,new_my_pos,new_my_vel,new_my_ang,new_ball_pos,new_ball_vel,false); old_new_my_pos = new_my_pos; old_new_my_vel = new_my_vel; // simulate 1st dash basic_cmd->set_dash(maxSpeed); basic_cmd->get_cmd(tmpCmd); // before doing anything else, calculate how far we can get by // maxLookAhead or less dashes for(int i = 1 ; i<=maxLookAhead; i++){ // smaller bc we already did one! Tools::model_cmd_main(old_new_my_pos,old_new_my_vel,WSinfo::me->ang,WSinfo::ball->pos,WSinfo::ball->vel,tmpCmd.cmd_main,new_my_pos,new_my_vel,new_my_ang,new_ball_pos,new_ball_vel,false); old_new_my_pos = new_my_pos; old_new_my_vel = new_my_vel; afterNdash[i] = new_my_pos; } Vector lot,tmp,dest; bool foundSafePos = false; static const double maxDistToBall = 0.7*WSinfo::me->kick_radius; WSpset pset; Vector lotOnMyDirDiff; Vector lotOnMyDir; int nThDash; bool ballLeavesKickRadius; for(nThDash=maxLookAhead;nThDash>0; nThDash--){ if(nThDash*70 + 1300 > WSinfo::me->stamina) continue; for(double furthest=0.8*WSinfo::me->kick_radius;furthest>0; furthest-=.1){ lotOnMyDirDiff.init_polar(furthest,WSinfo::me->ang); lotOnMyDir = afterNdash[nThDash] + lotOnMyDirDiff; // right to me in 2 cycles Geometry2d::projection_to_line(lot, lotOnMyDir, Line2d(WSinfo::ball->pos,Vector(kick_angle))); if(nThDash<7 && !(fabs(WSinfo::me->pos.y)>FIELD_BORDER_Y-2)) lot = lot; else lot = lotOnMyDir + 0.5*(lot - lotOnMyDir); // we know now the kick dir, figure out destination of kickCmd: bool tooFar; dest = getKickDestForBallPosInNCycles(lot,1+nThDash,tooFar); if(tooFar) continue; if(afterNdash[nThDash].distance(lot)<maxDistToBall){ foundSafePos = true; break; } } if(!foundSafePos) continue; pset = WSinfo::valid_opponents; if(ignoreClosestOpp && opp) pset.remove(opp); pset.keep_and_sort_closest_players_to_point(4,lot); if(fabs(lot.y)>FIELD_BORDER_Y-1 || fabs(lot.x)>FIELD_BORDER_X-3){ // Can catch ball outside field -- dont do this foundSafePos = false; continue; } // now calculate whether the ball will leave my kick_radius // in the course of kick+dashes new_ball_pos = dest; new_ball_vel = dest - WSinfo::ball->pos; ballLeavesKickRadius = false; for(int i=1;i<=nThDash; i++){ new_ball_vel = ServerOptions::ball_decay*new_ball_vel; new_ball_pos = new_ball_pos + new_ball_vel; if(afterNdash[i].distance(new_ball_pos)>0.8*WSinfo::me->kick_radius){ ballLeavesKickRadius = true; break; } } // advance fast even if havent looked there if ball stays controlled if(ballLeavesKickRadius && haventLookedThere){ foundSafePos = false; continue; } bool betterInterceptorFound=false; Vector his_lot; float deltaPos; Geometry2d::projection_to_line(his_lot, WSinfo::me->vel, Line2d(Vector(0,0),Vector(lot - WSinfo::me->pos))); float myDeltaPos = WSinfo::me->pos.distance(his_lot); for(int i=0;i<pset.num&&ballLeavesKickRadius;i++){ Geometry2d::projection_to_line(his_lot, pset[i]->vel, Line2d(Vector(0,0),Vector(lot - pset[i]->pos))); deltaPos = pset[i]->pos.distance(his_lot); if(pset[i]->pos.distance(lot)-WSinfo::me->pos.distance(lot)<0.5+0.15*nThDash + deltaPos-myDeltaPos){ // I loose control of the ball and my next opponent is closer to ball than I am betterInterceptorFound=true; break; } } if(betterInterceptorFound){ foundSafePos=false; continue; } break; } if(!foundSafePos){ POL2("getKickAheadBallOK: Advancing too risky, stopping it"); return false; } bool isBallOnLeftSide = (Tools::my_angle_to(WSinfo::ball->pos).get_value_mPI_pPI()>0); Vector fallBack; fallBack.init_polar(0.6,WSinfo::me->ang + (isBallOnLeftSide ? ANGLE(DEG2RAD(112)):ANGLE(DEG2RAD(-112)))); Vector inMyDir; inMyDir.init_polar(0.3,WSinfo::me->ang); bool canDash = true; bool mustKick = false; if(opp && nextOppToMe.pos.distance(dest)<nextOppToMe.kick_radius+ServerOptions::ball_size){ POL2("getKickAheadBallOK: Do not advance in Opponent, moving ball to back!"); dest = fallBack + nextMeNA.pos; canDash = false; mustKick = true; } if(opp && nextOppToMe.pos.distance(dest)<nextOppToMe.kick_radius+ServerOptions::ball_size){ POL2("getKickAheadBallOK: Do not advance in Opponent(2), moving ball to back!"); dest = fallBack + inMyDir + nextMeNA.pos; canDash = false; mustKick = true; } /* * Do NOT do this: upper level will request dash! if(opp && nextOppToMe.pos.distance(dest)<nextOppToMe.kick_radius+ServerOptions::ball_size){ POL2("getKickAheadBallOK: Do not advance in Opponent(3), last chance"); Vector safestPos, bestPos; getTargetsInMe(safestPos, bestPos); if(getCmdKickToDest(cmd,bestPos,true,false)){ POL("Kicking ball to best position"); MARK_POS(safestPos, blue); return true; } if(getCmdKickToDest(cmd,safestPos,true,false)){ POL("Kicking ball to safest position"); MARK_POS(safestPos, blue); return true; } } */ POL2("getKickAheadBallOK: Should get ball after "<<nThDash<< " dashes after kick"); MARK_POS(lotOnMyDir, green); MARK_POS(lot, green); DRAW(L2D(WSinfo::ball->pos.x,WSinfo::ball->pos.y,lot.x,lot.y,"green")); DRAW(C2D(afterNdash[nThDash].x,afterNdash[nThDash].y,WSinfo::me->kick_radius,"green")); if(getCmdKickToDest(cmd,dest,false,false)){ POL("getKickAheadBallOK: Ball moving in right direction, kicking ahead."); if(canDash) setRequest(DAREQ_DASH); else if(mustKick) setRequest(DAREQ_KICK); lastActionTaken = DA_KICK_AHEAD; MARK_POS(dest, blue); return true; }; return false;}// getKickAheadPrepareBall {{{2bool DribbleAround::getKickAheadPrepareBall(Cmd& cmd, bool keepBallOnLeftSide, bool switchSidesBehind){ POL2("In getKickAheadPrepareBall()"); ANGLE toBall = Tools::my_angle_to(WSinfo::ball->pos); double toBallFl = toBall.get_value_mPI_pPI(); double toBallFlAbs = fabs(toBallFl); bool isBallOnLeftSide = (toBallFl>0); bool haveToSwitchSides = ( isBallOnLeftSide && !keepBallOnLeftSide) ||(!isBallOnLeftSide && keepBallOnLeftSide); if(!haveToSwitchSides){ Vector dest, dest1, dest2; Vector inMyDir; inMyDir.init_polar(0.4,WSinfo::me->ang); dest1.init_polar(0.8,WSinfo::me->ang + (isBallOnLeftSide ? ANGLE(5*PI/8):ANGLE(-5*PI/8))); dest1+= nextMeNA.pos; dest2 = dest1 + inMyDir; dest = ((WSinfo::ball->pos.sqr_distance(dest1)<WSinfo::ball->pos.sqr_distance(dest2))?dest1:dest2); if(getCmdKickToDest(cmd,dest,true,false)){ POL("getKickAheadPrepareBall: Preparing ball on same side."); setRequest(DAREQ_KICK); MARK_POS(dest, blue); return true; } } // now the switch sides case // TODO: this is always true!? bool ballChangeSidePossible = true || (WSinfo::ball->pos.distance(WSinfo::me->pos)>.4) && ( (toBallFlAbs<DEG2RAD(50)) ||(toBallFlAbs>DEG2RAD(130))); if(!ballChangeSidePossible){ bool toMyLine = (switchSidesBehind && toBallFlAbs>DEG2RAD(90)) ||(!switchSidesBehind && toBallFlAbs<DEG2RAD(90)); Vector dest; if(toMyLine){ dest.init_polar((switchSidesBehind?-0.8:0.8)*WSinfo::me->kick_radius,WSinfo::me->ang); dest+=nextMeNA.pos; if(getCmdKickToDest(cmd,dest,true,false)){ POL("getKickAheadPrepareBall: Cannot change sides, preparing by kicking on my line."); setRequest(DAREQ_KICK); MARK_POS(dest, blue); return true; } } ANGLE toDest; if(isBallOnLeftSide) toDest = ANGLE(WSinfo::me->ang + ANGLE(switchSidesBehind?-5*PI/8:-3*PI/8)); else toDest = ANGLE(WSinfo::me->ang + ANGLE(switchSidesBehind? 5*PI/8: 3*PI/8)); dest.init_polar(0.6*WSinfo::me->kick_radius, toDest); dest+=nextMeNA.pos; if(getCmdKickToDest(cmd,dest,true,false)){ POL("getKickAheadPrepareBall: Cannot change sides, preparing by kicking in desired dir."); setRequest(DAREQ_KICK); MARK_POS(dest, blue); return true; } } // we have to change sides and ball change sides is possible Vector dest; ANGLE toDest; if(keepBallOnLeftSide) toDest = ANGLE(WSinfo::me->ang + ANGLE(switchSidesBehind? 5*PI/8: 3*PI/8)); else toDest = ANGLE(WSinfo::me->ang + ANGLE(switchSidesBehind?-5*PI/8:-3*PI/8)); dest.init_polar(0.6*WSinfo::me->kick_radius,toDest); dest += nextMeNA.pos; if(getCmdKickToDest(cmd,dest,true,false)){ POL("getKickAheadPrepareBall: Can change sides, doing so."); setRequest(DAREQ_KICK); MARK_POS(dest, blue); return true; } return false;}// getKickForTurn {{{2bool DribbleAround::getKickForTurn(Cmd& cmd){ ANGLE toBall = (dribbleTo-WSinfo::me->pos).ANGLE_to(WSinfo::ball->pos - WSinfo::me->pos); ANGLE toOpp = opp?(dribbleTo-WSinfo::me->pos).ANGLE_to(opp->pos - WSinfo::me->pos):ANGLE(0); float toOppFl = toOpp.get_value_mPI_pPI(); float toBallFl = toBall.get_value_mPI_pPI(); ANGLE aToDribbleTo = (dribbleTo - WSinfo::me->pos).ARG(); bool isBallOnLeftSide = toBallFl > 0; bool isOppLeft = toOppFl > 0; POL2("getKickForTurn: Opp will be left="<<isOppLeft << " toOpp="<<RAD2DEG(toOppFl)); POL2("getKickForTurn: Ball is be left="<<isBallOnLeftSide << " toBall="<<RAD2DEG(toBallFl)); float toDestFl = Tools::my_angle_to(dribbleTo).get_value_mPI_pPI(); bool turnALot = fabs(toDestFl) > DEG2RAD(80); Cmd tmpCmd; Vector new_my_pos,new_my_vel,new_ball_pos,new_ball_vel; Vector old_new_my_pos,old_new_my_vel; ANGLE new_my_ang, old_new_my_ang; // simulate kick basic_cmd->set_dash(0); basic_cmd->get_cmd(tmpCmd); Tools::model_cmd_main(WSinfo::me->pos,WSinfo::me->vel,WSinfo::me->ang,WSinfo::ball->pos,WSinfo::ball->vel,tmpCmd.cmd_main,new_my_pos,new_my_vel,new_my_ang,new_ball_pos,new_ball_vel,false); old_new_my_pos = new_my_pos; old_new_my_vel = new_my_vel;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -