📄 memaction.c
字号:
int ActionInfo::GetInterceptionMinCyc(){ if (IntMinCycTime != CurrentTime) return -1; else return IntMinCyc;}/*****************************************************************************************/void ActionInfo::SetIntMinCyc(int newval){ if (IntMinCycTime != CurrentTime) { IntMinCycTime = CurrentTime; IntMinCyc = newval; } else if (IntMinCyc > newval) IntMinCyc = newval;}/*****************************************************************************************/void ActionInfo::SetInterceptionLookahead(int newval){ if (newval > 0 || newval == LA_Default || newval == LA_BestSoFar) { if (IntMinCycTime == CurrentTime) DebugInt(cout << "Changing lookahead mid way through computations. Could be bad" <<endl); InterceptLookahead = newval; } else { my_error("Trying to set InterceptLookahead to an invlaid value"); } }/*****************************************************************************************//*****************************************************************************************//*****************************************************************************************//* Passive interception stuff */int ActionInfo::GetClosestPointToBallPath(Vector* pPt, float* pNumCycles, Vector PlayerPos, Vector BallPos, Vector BallVel){ if (fabs(BallVel.x) < FLOAT_EPS && fabs(BallVel.y) < FLOAT_EPS) *pPt = BallPos; else { *pPt = GetClosestPointToRay(PlayerPos, BallPos, BallVel); /* adjust point for sidelines */ Rectangle field(Vector(0,0), Vector(SP_pitch_length, SP_pitch_width)); *pPt = AdjustPtToRectOnLine(*pPt, field, LineFromRay(BallPos, BallVel)); } /* compute the number of cycles to get here */ *pNumCycles = 0; /* now get the number of cycles */ Vector traj = *pPt - BallPos; DebugInt(cout << "Pt: " << *pPt << "\tBallVel: " << BallVel << "\tBallPos: " << BallPos << "\ttraj: " << traj << endl); /* first decide if the ball is actually coming towards us */ if (signf(traj.x) != signf(BallVel.x) || signf(traj.y) != signf(BallVel.y)) { DebugInt(printf(" GCPTBP: Ball is goign wrong way for closest intercept!\n")); return 0; } float trajDist = traj.mod(); float velMod = BallVel.mod(); float temp = trajDist / velMod * (SP_ball_decay - 1) + 1; if (temp < 0.0) { /* ball will never make it to closest point */ /* SMURF - shoudl adjust for actual closest!!!! */ DebugInt(printf("GCPTBP: Ball will never make it to closest point, adjusting\n")); *pPt = BallPos + traj * SumInfGeomSeries(velMod, SP_ball_decay) / traj.mod(); *pNumCycles = SP_half_time; //just a big number return 1; } else *pNumCycles = log(temp) / log(SP_ball_decay); return 1;}/*****************************************************************************************/void ActionInfo::VerifyBPIInfo(){ if (BPItime == CurrentTime) return; BPItime = CurrentTime; Vector BallVel; if (!MyConf()) { my_error("Can't intercept if I don't know where I am"); BPIvalid = FALSE; return; } if (!BallPositionValid()) { my_error("Can't get to ball path if I don't know where it is"); BPIvalid = FALSE; return; } if (BallKickable()) { BPIvalid = TRUE; BPIable = TRUE; BPIdist = 0; BPIpoint = MyPos(); BPIballcyc = 0; return; } if (BallVelocityValid()) BallVel = BallAbsoluteVelocity(); else { BPIvalid = TRUE; BPIable = TRUE; BPIdist = BallDistance(); BPIpoint = BallAbsolutePosition(); BPIballcyc = 0; return; } DebugInt(printf("\nTime: %d\n", CurrentTime.t)); DebugInt(printf("At BallIntercept_passive\n")); int passRet; passRet = GetClosestPointToBallPath(&BPIpoint, &BPIballcyc, MyPos(), BallAbsolutePosition(), BallVel); DebugInt(printf("Passive Method: ret: %d\tx: %f\ty:%f\tcyc: %f\n", passRet, BPIpoint.x, BPIpoint.y, BPIballcyc)); if (passRet) { BPIvalid = TRUE; BPIable = TRUE; BPIdist = (BPIpoint - MyPos()).mod(); } else { BPIvalid = TRUE; BPIable = FALSE; } return; }/*****************************************************************************************/Vector ActionInfo::BallPathInterceptPoint(){ VerifyBPIInfo(); if (!BPIvalid) my_error("Calling BallPathInterceptionPoint when info not valid?"); return BPIpoint;}/*****************************************************************************************/Bool ActionInfo::BallPathInterceptAmIThere(float buffer){ VerifyBPIInfo(); if (!BPIvalid) my_error("Calling BallPathInterceptionAmIThere when info not valid"); return (MyPos() - BPIpoint).mod() <= buffer ? TRUE : FALSE;}/*****************************************************************************************/float ActionInfo::BallPathInterceptDistance(){ VerifyBPIInfo(); if (!BPIable) my_error("Calling BallPathInterceptionDistance when I can't get get there"); return BPIdist;}/*****************************************************************************************/int ActionInfo::BallPathInterceptCyclesForBall(){ VerifyBPIInfo(); if (!BPIable) my_error("Calling BallPathInterceptionCyclesForBall when I can't get get there"); return (int)ceil(BPIballcyc);}/*****************************************************************************************/Bool ActionInfo::BallPathInterceptCanIGetThere(float max_pow){ VerifyBPIInfo(); if (!BPIable) return FALSE; AngleDeg targAng = AngleTo(BPIpoint); Vector myEnd; if (fabs(GetNormalizeAngleDeg(MyAng() - targAng)) > CP_max_go_to_point_angle_err) { myEnd = MyPredictedPosition((int)ceil(BPIballcyc), max_pow); } else { myEnd = MyPredictedPositionWithTurn(targAng - MyAng(), (int)ceil(BPIballcyc), max_pow); } return ( (myEnd - MyPos()).mod() >= (BPIpoint - MyPos()).mod() ) ? TRUE : FALSE;}/*****************************************************************************************//*****************************************************************************************//*****************************************************************************************//* if we have a velocity that we want the ball to be moving at when it gets to a certain point, then this fucntion will convert to the velocity that we need to kick the ball at to have that effect */float ActionInfo::VelAtPt2VelAtFoot(Vector pt, float targ_vel_at_pt){ if (targ_vel_at_pt < FLOAT_EPS) { return SolveForSumInfGeomSeries(SP_ball_decay, (pt - MyPos()).mod() ); } else { float ball_steps = SolveForSumGeomSeries(targ_vel_at_pt, 1/SP_ball_decay, (pt - MyPos()).mod() ); return targ_vel_at_pt * pow(1/SP_ball_decay, ball_steps); } }/*****************************************************************************************//* looks at closeest opponent or teamless player *//* We only look at the closest teamless player- we really should be pessimistic and look at all of them, but it will require some changes in MemPosition */KickMode ActionInfo::BestKickModeAbs(AngleDeg abs_ang){ Unum closest = ClosestOpponent(); if (NumTeamlessPlayers() > 0) { Vector teamless_pos = ClosestTeamlessPlayerPosition(); if (closest == Unum_Unknown || DistanceTo(teamless_pos) < OpponentDistance(closest)) closest = Unum_Teamless; } if (closest == Unum_Unknown) return KM_HardestKick; int cyc_to_steal = EstimatedCyclesToSteal(closest); float targ_ang = abs_ang + signf(GetNormalizeAngleDeg(BallAngle()-abs_ang)) * (90 + CP_static_kick_ang); float ang_diff = GetNormalizeAngleDeg(BallAngle() - targ_ang); NormalizeAngleDeg(&ang_diff); if (cyc_to_steal > fabs(ang_diff)/CP_time_for_full_rotation + CP_cycles_to_kick) return KM_HardestKick; if (OpponentWithBall() != Unum_Unknown) return KM_QuickestRelease; if (cyc_to_steal < CP_cycles_to_kick) return KM_Quickly; return KM_Moderate;}/*****************************************************************************************//* returns estimated cycles for opponent to get the ball into his kickable area *//* can handle Unum_Teamless to look at closest teamless player *//* we should be able to look at any teamless player, but it woudl require some changes to MemPosition */int ActionInfo::EstimatedCyclesToSteal(Unum opp, Vector ball_pos){ Vector pos; if (opp == Unum_Teamless) { if (NumTeamlessPlayers() < 1) my_error("EstimatedCyclesToSteal: can't estimate teamless if there aren't any"); pos = ClosestTeamlessPlayerPosition(); } else { if (!OpponentPositionValid(opp)) my_error("EstimateCyclesToSteal: can't estimate if I don;t know where opponent is"); pos = OpponentAbsolutePosition(opp); } if (!BallKickable()) my_error("EstiamteCyccleToSteal: shouldn;t use this if the ball is not kickable"); if (BallKickableForOpponent(opp)) return 0; int cyc; Line oppLine = LineFromTwoPoints(pos, ball_pos); Vector oppTraj = ball_pos - pos; Vector pt = oppLine.ProjectPoint(MyPos()); float oppDist = oppTraj.mod(); oppDist -= SP_kickable_area; cyc = (int)ceil(oppDist / SP_player_speed_max); if (opp != Unum_Teamless && OpponentFaceValid(opp)) if (fabs(OpponentAbsoluteFace(opp) - oppTraj.dir()) > CP_max_go_to_point_angle_err) cyc++; //SMURF: should we be more conservative about what a collision is? float dodge_dist = pt.dist(MyPos()); if (dodge_dist < 2 * SP_player_size && pt.dist(ball_pos) > SP_kickable_margin) { /* need to take into account a dodge */ cyc += 2; //have to turn twice if (dodge_dist > 2 * SP_player_size - SP_player_speed_max) cyc += 1; // one dash will dodge us else cyc += 2; // it takes two dashes to dodge us } return cyc;}/*****************************************************************************************//*****************************************************************************************//*****************************************************************************************/Bool ActionInfo::KickInProgress(){ /* need to have kicked last cycle. Updates kick_in_progress_time */ if ( kick_in_progress && kick_in_progress_time == LastActionOpTime ){ kick_in_progress_time = CurrentTime; return TRUE; } return FALSE;}/*****************************************************************************************/void ActionInfo::StartKick(AngleDeg target_angle, KickMode mode, float target_vel, TurnDir rot){ kick_in_progress = TRUE; start_kick_time = kick_in_progress_time = CurrentTime; kick_in_progress_abs_angle = GetNormalizeAngleDeg(target_angle + MyAng()); kick_in_progress_mode = mode; kick_in_progress_target_vel = target_vel; kick_in_progress_rotation = rot;}/*****************************************************************************************/void ActionInfo::StartShot(AngleDeg target_angle, KickMode mode, TurnDir rot){ StartKick(target_angle,mode,2*SP_ball_speed_max, rot);}/*****************************************************************************************/void ActionInfo::StartPass(Unum target, float target_vel_at_dest, TurnDir rot){ if ( target == Unum_Unknown || !TeammatePositionValid(target) ) my_error("can't start this pass"); team_passer = MyNumber; team_receiver = target; team_pass_time = CurrentTime; float target_vel = VelAtPt2VelAtFoot(TeammateAbsolutePosition(target),target_vel_at_dest); StartKick(TeammateAngle(target),KM_Moderate,target_vel,rot);}#ifndef RELEASE_VERSION/*****************************************************************************************//*****************************************************************************************//*****************************************************************************************//* No reasoning about players being tired yet: if so, need to add dash_pow to the interception calls *//* These functions are very computationally intensive */Unum ActionInfo::FastestTeammateToBall(){ if ( !BallPositionValid() ) my_error("Need to know ball position to know fastest to it\n"); Unum closest = ClosestTeammateToBall(); if ( !BallMoving() && !TeammateTired(closest) ) return closest; if ( CurrentTime == Stored_Fastest_Teammate_Time ) return Stored_Fastest_Teammate; ResetInterceptionMinCyc(); SetInterceptionLookahead(LA_BestSoFar); Unum FastestPlayer = Unum_Unknown; int cycles, min_cycles = CP_max_int_lookahead+1; for (int i=1; i<=SP_team_size; i++){ if ( TeammatePositionValid(i) && TeammateInterceptionAble(i) == TRUE && (cycles=TeammateInterceptionNumberCycles(i)) < min_cycles && (i != FP_goalie_number || !CP_goalie) ){ min_cycles = cycles; FastestPlayer = i; } } Stored_Fastest_Teammate = FastestPlayer; Stored_Fastest_Teammate_Time = CurrentTime; return FastestPlayer;}/*****************************************************************************************/Unum ActionInfo::FastestOpponentToBall(){ if ( !BallPositionValid() ) my_error("Need to know ball position to know fastest to it\n"); if ( !BallMoving() ) return ClosestOpponentToBall(); ResetInterceptionMinCyc(); SetInterceptionLookahead(LA_BestSoFar); Unum FastestPlayer = Unum_Unknown; int cycles, min_cycles = CP_max_int_lookahead+1; for (int i=1; i<=SP_team_size; i++){ if ( OpponentPositionValid(i) && OpponentInterceptionAble(i) == TRUE && (cycles=OpponentInterceptionNumberCycles(i)) < min_cycles ){ min_cycles = cycles; FastestPlayer = i; } } return FastestPlayer;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -