📄 dribble_between.c
字号:
/*Brainstormers 2D (Soccer Simulation League 2D)PUBLIC SOURCE CODE RELEASE 2005Copyright (C) 1998-2005 Neuroinformatics Group, University of Osnabrueck, GermanyThis program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 2of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.*//* * DribbleBetween skill * * @author Hannes Schulz <mail@hannes-schulz.de> * @version 0.9 * * vim:fdm=indent * */#include "dribble_between.h"#include "../policy/positioning.h"#include "ws_memory.h"#include "log_macros.h"#if 0 /* 1: debugging; 0: no debugging */#define POL(XXX) LOG_POL(0,<<"DribbleBetween: "<<XXX)#define POL2(XXX) LOG_POL(1,<<"DribbleBetween: "<<XXX)#define DRAW(XXX) LOG_POL(0,<<_2D<<XXX)#define DRAW2(XXX) LOG_POL(1,<<_2D<<XXX)#else#define POL(XXX) #define POL2(XXX) #define DRAW(XXX) #define DRAW2(XXX) #endif#define KEEPQ2D(P1,P2,W1,W2) keep_players_in_quadrangle(P1,P2,W1,W2);#define MARK_POS(P,C) DRAW(C2D((P).x,(P).y,0.3,#C));#define MIN(X,Y) ((X<Y)?X:Y)#define MAX(X,Y) ((X>Y)?X:Y)#if 0#define DRIBBLE_STATS#endifDribbleBetween::DribbleBetween(){ dribbleAround = DribbleAround::getInstance(); lastDribbleTime = 0; dribblingInsecure = false;}DribbleBetween* DribbleBetween::myInstance = NULL;DribbleBetween* DribbleBetween::getInstance() { if(myInstance == NULL){ myInstance = new DribbleBetween(); } return myInstance;}void DribbleBetween::setRelevantOpponents(){ // {{{1 static const float farAway = 5; float myDistToDribbleTo = WSinfo::me->pos.distance(dribbleTo); opps = WSinfo::valid_opponents; int oppsInMyKickRange = 0; switch(opps.num){ case 0: mode = DB_NO_OPP; return; case 1: mode = DB_ONE_OPP; return; default: break; } // find out how many players could roughly attack me in next cycle // DribbleAround can only deal with one at a time. float minDistDangerous = (3 * WSinfo::me->kick_radius); for(int i=0;i<opps.num;i++){ if(opps[i]->pos.distance(WSinfo::ball->pos)<minDistDangerous) oppsInMyKickRange++; } if(oppsInMyKickRange>1){ dribblingInsecure = true; // TODO: is this useful? //mode = DB_TOO_MANY_OPP; //return; } DRAW(C2D(dribbleTo.x,dribbleTo.y,0.2,"red")); //Vector toFarAway = dribbleTo - WSinfo::me->pos; Vector toFarAway; toFarAway.init_polar(farAway,WSinfo::me->ang); toFarAway.normalize(farAway); //Vector justBehind = WSinfo::me->pos - dribbleTo; Vector justBehind; justBehind.init_polar(-2*WSinfo::me->kick_radius,WSinfo::me->ang); justBehind.normalize(2*WSinfo::me->kick_radius); opps.keep_players_in_quadrangle(WSinfo::me->pos+justBehind,WSinfo::me->pos+toFarAway,4,6); DRAW(Quadrangle2d(WSinfo::me->pos+justBehind,WSinfo::me->pos+toFarAway,4,6)); for(int i=0;i<opps.num;i++){ DRAW(C2D(opps[i]->pos.x,opps[i]->pos.y,1.1*opps[i]->kick_radius,"blue")); } /* * TODO: use lotfusses to find out whether two opponents are on the same side of me * and remove the one further away. * for(int i = 0; i<maxNum;i++){ if(opps.num>=2){ Vector between; between.x = (opps[0]->pos.x + opps[1]->pos.x)/2; between.y = (opps[0]->pos.y + opps[1]->pos.y)/2; if(( WSinfo::me->pos.y > opps[0]->pos.y && WSinfo::me->pos.y > opps[1]->pos.y) || (WSinfo::me->pos.y < opps[0]->pos.y && WSinfo::me->pos.y < opps[1]->pos.y)){ // both are on same side: // remove the one further away opps.remove(opps[1]); } //else if(opps[0]->pos.distance(opps[1]->pos)<(WSinfo::me->pos.distance(between))){ // too close together // remove the one further away //opps.remove(opps[1]); //} }else break; } */ switch(opps.num){ case 0: mode = DB_NO_OPP;break; case 1: mode = DB_ONE_OPP;break; case 2: mode = DB_TWO_OPP;break; default: mode = DB_TOO_MANY_OPP; }} // }}}1float DribbleBetween::getValueForDribbleDir(float dribbleAngle){ static const float maxLookAhead = 9.; static const float minLookAhead = -4; Vector toDribbleTo = (dribbleTo-WSinfo::me->pos); Vector notFurtherThan(toDribbleTo.ARG()+ANGLE(dribbleAngle)); Vector atLeastThatFar(toDribbleTo.ARG()+ANGLE(dribbleAngle)); notFurtherThan.normalize(maxLookAhead); atLeastThatFar.normalize(minLookAhead); notFurtherThan += WSinfo::me->pos; atLeastThatFar += WSinfo::me->pos; // GoStraightCheck BEGIN // TODO: does this work? Is it good? /* WSpset opps = WSinfo::valid_opponents; Vector lookAhead; static const float lookAheadLength = 8; lookAhead.init_polar(lookAheadLength,notFurtherThan.ARG()); opps.keep_players_in_quadrangle(WSinfo::me->pos,WSinfo::me->pos+lookAhead,8,8); if(opps.num==0 && WSinfo::me->pos.x>-10) return -200.+(WSinfo::me->pos.x>20?(WSinfo::me->pos+lookAhead).distance(HIS_GOAL_CENTER):0); */ // GoStraightCheck END opps = WSinfo::valid_opponents; opps += WSinfo::valid_teammates_without_me; WS::Player leftBorder, rightBorder; leftBorder.pos.init_polar(.5*maxLookAhead,toDribbleTo.ARG()+ANGLE(90)); leftBorder.pos += WSinfo::me->pos; leftBorder.vel = Vector(0,0); leftBorder.number = -5; leftBorder.team = HIS_TEAM; rightBorder.pos.init_polar(.5*maxLookAhead,toDribbleTo.ARG()+ANGLE(-90)); rightBorder.pos += WSinfo::me->pos; rightBorder.vel = Vector(0,0); rightBorder.number = -6; rightBorder.team = HIS_TEAM; opps.append(&leftBorder); opps.append(&rightBorder); Vector lot; float oppDistToLot,value=1; float opponentValue; float intervalLength = maxLookAhead - minLookAhead; Vector posPlusVel; bool isBehindMe; for(int i=0;i<opps.num;i++){ posPlusVel = opps[i]->pos + opps[i]->vel; Geometry2d::projection_to_line(lot, posPlusVel, Line2d(WSinfo::me->pos,notFurtherThan-WSinfo::me->pos)); // lot must be in range [atLeastThatFar,notFurtherThan] from me, only ahead if(notFurtherThan.distance(lot)>intervalLength) continue; if(WSinfo::me->pos.distance(lot)>maxLookAhead) continue; isBehindMe = notFurtherThan.distance(lot)>maxLookAhead; opponentValue = ((opps[i]->team == HIS_TEAM) ? 1 : 0.2); if(opps[i]->number == WSinfo::ws->his_goalie_number) opponentValue = 0.1; opponentValue *= (posPlusVel.distance(WSinfo::me->pos)<4)?2:1; //opponentValue *= (isBehindMe?-.5:1); oppDistToLot = posPlusVel.distance(lot); oppDistToLot -= 8; oppDistToLot *= -1; oppDistToLot = MIN(8,oppDistToLot); oppDistToLot = MAX(-0,oppDistToLot); oppDistToLot *= opponentValue; value += (oppDistToLot*oppDistToLot); } return value;}Vector DribbleBetween::getTargetPos(){ float bestAngle=0; float value, bestValue=1E6; static const float maxDribbleAngle = DEG2RAD(70); static const int numCheckedAngles = 25; static const float angleIncrease = maxDribbleAngle/numCheckedAngles; Vector toDribbleTo = (dribbleTo-WSinfo::me->pos); Vector notOff; bool goingToCenterAllowed = WSinfo::me->pos.x>10||fabs(WSinfo::me->pos.y)<8; bool behindGoal; bool toCenter; for(float dribbleAngle = 0; dribbleAngle<maxDribbleAngle;dribbleAngle+=angleIncrease){ notOff.init_polar(14,toDribbleTo.ARG()+ANGLE(dribbleAngle)); notOff+=WSinfo::me->pos; behindGoal = fabs(notOff.y)<.8*ServerOptions::goal_width; toCenter = fabs(notOff.y) < fabs(WSinfo::me->pos.y) - 5; if((fabs(notOff.y)>FIELD_BORDER_Y-2 || fabs(notOff.x)>FIELD_BORDER_X-2) && !behindGoal){ //POL2("getTargetPos: "<<RAD2DEG(dribbleAngle)<< "?:\t Leads out of field"); } else if(!goingToCenterAllowed && toCenter){ //POL2("getTargetPos: "<<RAD2DEG(dribbleAngle)<< "?:\t Leads to center"); }else{ value = getValueForDribbleDir(dribbleAngle); //POL2("getTargetPos: "<<RAD2DEG(dribbleAngle)<< "?:\t"<< value); if(value<bestValue){ bestValue = value; bestAngle = dribbleAngle; } } notOff.init_polar(14,toDribbleTo.ARG()+ANGLE(-dribbleAngle)); notOff+=WSinfo::me->pos; behindGoal = fabs(notOff.y)<.8*ServerOptions::goal_width; toCenter = fabs(notOff.y) < fabs(WSinfo::me->pos.y) - 5; if((fabs(notOff.y)>FIELD_BORDER_Y-2 || fabs(notOff.x)>FIELD_BORDER_X-2) && !behindGoal){ //POL2("getTargetPos: "<<RAD2DEG(-dribbleAngle)<< "?:\t Leads out of field"); }else if(!goingToCenterAllowed && toCenter){ //POL2("getTargetPos: "<<RAD2DEG(-dribbleAngle)<< "?:\t Leads to center"); }else{ value = getValueForDribbleDir(-dribbleAngle); //POL2("getTargetPos: "<<RAD2DEG(-dribbleAngle)<< "?:\t"<< value); if(value<bestValue){ bestValue = value; bestAngle = -dribbleAngle; } } //if(bestValue < 2) break; // TODO: does this help? } POL("Dribble Dir has value "<<bestValue); Vector dest; dest.init_polar(20,toDribbleTo.ARG()+ANGLE(bestAngle)); dest+=WSinfo::me->pos; DRAW(L2D(WSinfo::me->pos.x,WSinfo::me->pos.y,dest.x,dest.y,"green")); if(dest.distance(WSinfo::me->pos)<2){ POL2("going for dribbleTo instead of dribbling between"); dest = dribbleTo; } if(fabs(WSinfo::me->pos.x)>FIELD_BORDER_X-4){ POL2("going for HIS_GOAL_CENTER instead of dribbling between"); dest = HIS_GOAL_CENTER; } bool amICloseToFieldBorder = (fabs(lastTarget.x)>FIELD_BORDER_X-2 || fabs(lastTarget.y)>FIELD_BORDER_Y-2) &&( fabs(WSinfo::me->pos.x) > FIELD_BORDER_X - 5 || fabs(WSinfo::me->pos.y) > FIELD_BORDER_Y - 5); bool isOldTargetInBadAngleButNewNot = fabs(Tools::my_angle_to(lastTarget).get_value_mPI_pPI())>DEG2RAD(80) && fabs(Tools::my_angle_to(dest) .get_value_mPI_pPI())<DEG2RAD(80); if(WSinfo::ws->time - lastDribbleTime > 3){ lastTarget = dest; dribbleAroundTargetValue = bestValue; dribbleAround->resetRequest(); targetTimeCounter = 0; }else if((targetTimeCounter > 4 && mode!=DB_NO_OPP) ||targetTimeCounter >5){ lastTarget = dest; dribbleAroundTargetValue = bestValue; dribbleAround->resetRequest(); targetTimeCounter = 0; }else if(WSinfo::me->pos.distance(lastTarget)<1){ lastTarget = dest; dribbleAroundTargetValue = bestValue; dribbleAround->resetRequest(); targetTimeCounter = 0; }else if(amICloseToFieldBorder){ lastTarget = dest; dribbleAroundTargetValue = bestValue; dribbleAround->resetRequest();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -