/** 以最快的方式跑到目标点 * Run to the destination point with the fastest method. * \param agent the agent itself. * \param act an atomic action caculated to go to pos for this cycle. * \param pos the destination point. * \param buffer point buffer, means the real destinantion is a cycle with the certer * of pos and radius of buffer. * \param power the intend power to use. * \param can_inverse true means can run in the inverse direction of the agent's body. * \param turn_first true means that the agent should turn first to adjust the direction. */ void Dasher::GoToPoint(Agent & agent, AtomicAction & act, Vector target, double buffer, double power, bool can_inverse, bool turn_first) { act.Clear(); const Vector & my_pre_pos = agent.Self().GetPredictedPos(1); double dist = my_pre_pos.Dist(target); if (dist < buffer){ act.mSucceed = true; return; } AngleDeg dirdiff = GetNormalizeAngleDeg((target - my_pre_pos).Dir() - agent.GetSelf().GetBodyDir()); if (fabs(dirdiff) < 90.0){ can_inverse = false; //不需要倒着跑 } bool inverse = false; if (can_inverse){ int cycle = CycleNeedToPointWithCertainPosture(agent.Self(), target, true); if (cycle < 9 && cycle < CycleNeedToPointWithCertainPosture(agent.Self(), target, false)){ inverse = true; } } GoToPointWithCertainPosture(agent, act, target, buffer, power, inverse, turn_first); }
DecisionData::DecisionData(Agent & agent): mAgent ( agent ), mWorldState ( agent.World() ), mBallState ( agent.World().Ball() ), mSelfState ( agent.Self() ), mInfoState ( agent.Info()) { }
BehaviorAttackData::BehaviorAttackData(Agent & agent): mAgent ( agent ), mWorldState ( agent.GetWorldState() ), mBallState ( agent.GetWorldState().GetBall() ), mSelfState ( agent.Self() ), mPositionInfo ( agent.Info().GetPositionInfo()), mInterceptInfo ( agent.Info().GetInterceptInfo()), mStrategy (agent.GetStrategy()), mFormation ( agent.GetFormation() ) { mFormation.Update(Formation::Offensive, "Offensive"); }
/** 以确定的姿势(指倒着跑和正跑),跑到目标点 * Run to the destination point with a certain posture, forward or backword. * \param agent the agent itself. * \param act an atomic action caculated to go to pos for this cycle. * \param pos the destination point. * \param buffer point buffer, means the real destinantion is a cycle with the center * of pos and radius of buffer. * \param power the intend power to use. * \param inverse true means run backward. * \param turn_first true means that the agent should turn first to adjust the direction. */ void Dasher::GoToPointWithCertainPosture(Agent & agent, AtomicAction & act, Vector target, double buffer, double power, const bool inverse, bool turn_first) { act.Clear(); const Vector & my_pre_pos = agent.Self().GetPredictedPos(1); double dist = my_pre_pos.Dist(target); AngleDeg dirdiff = inverse? GetNormalizeAngleDeg((my_pre_pos - target).Dir() - agent.GetSelf().GetBodyDir()): GetNormalizeAngleDeg((target - my_pre_pos).Dir() - agent.GetSelf().GetBodyDir()); //需要转身的角度 double bufang; buffer = Max(0.05, buffer); //TODO: wait test if (buffer > FLOAT_EPS){ bufang = ASin(buffer / dist / 2) * 2; bufang = Max(10.0, bufang); } else { bufang = 0.0; } if (fabs(dirdiff) > bufang){ TurnDashPlaning(agent, act, target, buffer, power, inverse, turn_first); } else { power = inverse? -fabs(power): fabs(power); power = agent.GetSelf().CorrectDashPowerForStamina(power); if (fabs(power) > FLOAT_EPS){ act.mType = CT_Dash; act.mDashPower = AdjustPowerForDash(agent.Self(), target, buffer, power); act.mDashPower = agent.GetSelf().CorrectDashPowerForStamina(act.mDashPower); if (fabs(act.mDashPower) > FLOAT_EPS){ act.mSucceed = true; } else { act.mType = CT_None; //power为零时就不要执行了,没意义 TurnDashPlaning(agent, act, target, buffer, power, inverse, turn_first);//再次考虑转身,以免漏掉一线好的转身的机会 } } } }
/** * 考虑转身或直接dash * Planing to turn or to dash. * @param agent the agent itself. * @param act an atomic action to return the caculated decision. * @param target the target position to go to. * @param buffer * @param power the intend power for dash. * @param inverse true means running backwards. * @param turn_first true means turn first manually. */ void Dasher::TurnDashPlaning(Agent & agent, AtomicAction & act, Vector target, double buffer, double power, bool inverse, bool turn_first) { act.Clear(); power = inverse? -fabs(power): fabs(power); power = agent.GetSelf().CorrectDashPowerForStamina(power); PlayerState & self = agent.Self(); const Vector & my_pre_pos = self.GetPredictedPos(1); double target_dist = my_pre_pos.Dist(target); AngleDeg target_ang = inverse? GetNormalizeAngleDeg((my_pre_pos - target).Dir() - agent.GetSelf().GetBodyDir()): GetNormalizeAngleDeg((target - my_pre_pos).Dir() - agent.GetSelf().GetBodyDir()); //需要转身的角度 //DT_none //处理转身问题,可能1dash + 1turn更好 double bufang; if(buffer > FLOAT_EPS){ bufang = ASin(buffer / target_dist / 2) * 2; bufang = Max(10.0, bufang); } else{ bufang = 0.0; } const double & effort = self.GetEffort(); const double & accrate = self.GetDashPowerRate(); const double & inertia_moment = self.GetInertiaMoment(); const double & decay = self.GetPlayerDecay(); const double & speedmax = self.GetEffectiveSpeedMax(); const Vector & vel = self.GetVel(); const double & facing = self.GetBodyDir(); double speed = vel.Mod(); double diffang = fabs(target_ang); double oneturnang = self.GetMaxTurnAngle(); if(buffer < FLOAT_EPS && target_dist > 2.6){ oneturnang += 2.6; } if(turn_first || diffang <= oneturnang || speed < 0.04){ //由于噪声的存在,在非身体方向也有速度,调也调不过来,太小时不如直接转,0.04是一般队员的误差极值 act.mType = CT_Turn; act.mTurnAngle = target_ang; act.mSucceed = true; return; } else { //计算1 dash + 1turn; //下面都是算dash到什么速度最好 double mspd1 = (180.0/ ( diffang + 10 ) - 1.0 ) / inertia_moment; //10是buf,不然容易调整后正好还转不过来 double dash2spd = Min(mspd1 / decay, speedmax) / (1 + ServerParam::instance().playerRand()); if( fabs(GetNormalizeAngleDeg(vel.Dir() - facing)) > 90.0){ speed = -speed; } double spd_inf = Max(speed - accrate * ServerParam::instance().maxDashPower(), -dash2spd); double spd_sup = Min(speed + accrate * ServerParam::instance().maxDashPower(), dash2spd); Ray cur_r(self.GetPos(), facing); Vector pt_inf = cur_r.GetPoint(spd_inf * (1.0 + decay)); Vector pt_sup = cur_r.GetPoint(spd_sup * (1.0 + decay)); Vector pt;//要取得点 bool bnegtive;//要跑的点是不是在身后 Line pdl = Line(cur_r).GetPerpendicular(target);//垂线 if(pdl.IsPointInSameSide(pt_inf, pt_sup)){ if(fabs(GetNormalizeAngleDeg(facing-target_ang)) < 90.0){ pt = pt_sup; bnegtive = (spd_sup<0); } else{ pt = pt_inf; bnegtive = (spd_inf<0); } } else{ double dist; bnegtive = !cur_r.Intersection(pdl, dist); //垂点 pt = cur_r.GetPoint(dist); } double dis = pt.Dist(target);//两个周期后离point的距离,用来compare with 2 turn double twoturnang = oneturnang + 180.0 / (1.0 + inertia_moment * fabs(speed) * decay); if(twoturnang > diffang){ const Vector & pt2 = self.GetPredictedPos(2); double dis2 = pt2.Dist(target); if(dis2 < dis || diffang > 102.6){ //一次转太大,误差也大不如直接2turn act.mType = CT_Turn; act.mTurnAngle = target_ang; act.mSucceed = true; return; } } double spd_need; if(bnegtive){ spd_need = -(pt - self.GetPos()).Mod() / (1.0 + decay); } else{ spd_need = (pt - self.GetPos()).Mod() / (1.0 + decay); } //会总是dash而dash后又转不过来...,看着就像不拿球 double turnang_after_dash = 180.0 / (1.0 + inertia_moment * fabs(spd_need) * decay) - 5.0; if(GetAngleDegDiffer((target - pt).Dir(), facing) > turnang_after_dash ){ act.mType = CT_Turn; act.mTurnAngle = target_ang; act.mSucceed = true; return; } double power = ( spd_need - speed ) / accrate / effort; power = MinMax(-ServerParam::instance().maxDashPower(), power, ServerParam::instance().maxDashPower()); //I over act.mType = CT_Dash; act.mDashPower = AdjustPowerForDash(self, pt, FLOAT_EPS, power); act.mDashPower = agent.GetSelf().CorrectDashPowerForStamina(act.mDashPower); if(fabs(act.mDashPower) > FLOAT_EPS) { act.mSucceed = true; } else { act.mType = CT_Turn; //power为零时就不要执行了,没意义 act.mTurnAngle = 0.0; act.mSucceed = true; } } }