• Robcup2D足球学习记录【2020.01.30】


    bhv_custom_before_kick_off.cpp

    代码个人理解与存在的问题(已经通过注释标出)

    // -*-c++-*-
    
    /*
     *Copyright:
    
     Copyright (C) Hidehisa AKIYAMA
    
     This code is free software; you can redistribute it and/or
     modify it under the terms of the GNU Lesser General Public
     License as published by the Free Software Foundation; either
     version 3 of the License, or (at your option) any later version.
    
     This library is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     Lesser General Public License for more details.
    
     You should have received a copy of the GNU Lesser General Public
     License along with this library; if not, write to the Free Software
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    
     *EndCopyright:
     */
    
    /////////////////////////////////////////////////////////////////////
    
    #ifdef HAVE_CONFIG_H
    #include <config.h>
    #endif
    
    #include "bhv_custom_before_kick_off.h"
    
    #include <rcsc/action/bhv_scan_field.h>
    #include <rcsc/action/neck_turn_to_relative.h>
    
    #include <rcsc/player/player_agent.h>
    #include <rcsc/common/server_param.h>
    #include <rcsc/common/logger.h>
    
    using namespace rcsc;
    
    // #define DEBUG_PRINT
    
    /*-------------------------------------------------------------------*/
    /*!
    
    */
    /*
     问题:
     无,因为我看源代码是从后面忘前面看的,所以想提出来的问题都被姚文进和张智洋提出来了,就给子昂哥省事了哈哈!
     
     理解:
     这个函数是Bhv_CustomBeforeKickOff的执行函数,只要的作用是在踢球之前规定一些必须判断的规则,以后需要踢球之前必须通过该函数进行判断,如果符合这个这些规则才可以踢球。
     By ChenYanTing
     */
    bool
    Bhv_CustomBeforeKickOff::execute( PlayerAgent * agent )//踢球前的习惯的执行函数
    {
        const ServerParam & SP = ServerParam::i();
        const WorldModel & wm = agent->world();
    
        if ( wm.time().cycle() == 0
             && wm.time().stopped() < 5 )
        {
            agent->doTurn( 0.0 );
            agent->setNeckAction( new Neck_TurnToRelative( 0.0 ) );
            return false;
        }
    
        if ( wm.gameMode().type() == GameMode::AfterGoal_
             && wm.self().vel().r() > 0.05 )
        {
            agent->doTurn( 180.0 );
            agent->setNeckAction( new Neck_TurnToRelative( 0.0 ) );
            return true;
        }
    
        // check center circle
        SideID kickoff_side = NEUTRAL;
    
        if ( wm.gameMode().type() == GameMode::AfterGoal_ )
        {
            // after our goal
            if ( wm.gameMode().side() != wm.ourSide() )
            {
                kickoff_side = wm.ourSide();
            }
            else
            {
                kickoff_side = ( wm.ourSide() == LEFT
                                 ? RIGHT
                                 : LEFT );
            }
        }
        else // before_kick_off
        {
            // check half_time count
            if ( SP.halfTime() > 0 )
            {
                int half_time = SP.halfTime() * 10;
                int extra_half_time = SP.extraHalfTime() * 10;
                int normal_time = half_time * SP.nrNormalHalfs();
                int extra_time = extra_half_time * SP.nrExtraHalfs();
    #ifdef DEBUG_PRINT
                dlog.addText( Logger::ACTION,
                              __FILE__": half_time=%d nr_normal_halfs=%d normal_time=%d",
                              half_time, SP.nrNormalHalfs(),
                              normal_time );
                dlog.addText( Logger::ACTION,
                              __FILE__": extra_half_time=%d nr_extra_halfs=%d extra_time=%d",
                              extra_half_time, SP.nrExtraHalfs(),
                              extra_time );
                dlog.addText( Logger::ACTION,
                              __FILE__": total_time=%d",
                              normal_time + extra_time );
    #endif
                int time_flag = 0;
    
                if ( wm.time().cycle() <= normal_time )
                {
                    time_flag = ( wm.time().cycle() / half_time ) % 2;
    #ifdef DEBUG_PRINT
                    dlog.addText( Logger::ACTION,
                                  __FILE__": time=%d time/half_time=%d flag=%d",
                                  wm.time().cycle(),
                                  wm.time().cycle() / half_time,
                                  time_flag );
    #endif
                }
                else if ( wm.time().cycle() <= normal_time + extra_time )
                {
                    int overtime = wm.time().cycle() - normal_time;
                    time_flag = ( overtime / extra_half_time ) % 2;
    #ifdef DEBUG_PRINT
                    dlog.addText( Logger::ACTION,
                                  __FILE__": overtime=%d overttime/extra_half_time=%d flag=%d",
                                  overtime,
                                  wm.time().cycle() / extra_half_time,
                                  time_flag );
    #endif
                }
    
                kickoff_side = ( time_flag == 0
                                 ? LEFT
                                 : RIGHT );
            }
            else
            {
                kickoff_side = LEFT;
            }
        }
    
        //
        // fix move target point
        //
    #ifdef DEBUG_PRINT
        dlog.addText( Logger::ACTION,
                      __FILE__": move_pos=(%.2f %.2f)",
                      M_move_point.x, M_move_point.y );
    #endif
        if ( SP.kickoffOffside()
             && M_move_point.x >= 0.0 )
        {
            M_move_point.x = -0.001;
    #ifdef DEBUG_PRINT
            dlog.addText( Logger::ACTION,
                          __FILE__": avoid kick off offside" );
    #endif
        }
    
        if ( kickoff_side != wm.ourSide()
             && M_move_point.r() < ServerParam::i().centerCircleR() + 0.1 )
        {
            M_move_point *= ( ServerParam::i().centerCircleR() + 0.5 ) / M_move_point.r();
    #ifdef DEBUG_PRINT
            dlog.addText( Logger::ACTION,
                          __FILE__": avoid center circle. new pos=(%.2f %.2f)",
                          M_move_point.x, M_move_point.y );
    #endif
        }
    
        // move
        double tmpr = ( M_move_point - wm.self().pos() ).r();
        if ( tmpr > 1.0 )
        {
            agent->doMove( M_move_point.x, M_move_point.y );
            agent->setNeckAction( new Neck_TurnToRelative( 0.0 ) );
            return true;
        }
    
        // field scan
        return Bhv_ScanField().execute( agent );
    }
    
    

    bhv_dangerAreaTackle.cpp

    代码个人理解与存在的问题(已经通过注释标出)

    // -*-c++-*-
    
    /*
     *Copyright:
    
     Copyright (C) Hidehisa AKIYAMA
    
     This code is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation; either version 2, or (at your option)
     any later version.
    
     This code is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
    
     You should have received a copy of the GNU General Public License
     along with this code; see the file COPYING.  If not, write to
     the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
    
     *EndCopyright:
     */
    
    /////////////////////////////////////////////////////////////////////
    #ifdef HAVE_CONFIG_H
    #include <config.h>
    #endif
    
    #include "bhv_dangerAreaTackle.h"
    
    #include <rcsc/action/neck_turn_to_ball_or_scan.h>
    
    #include <rcsc/player/player_agent.h>
    #include <rcsc/player/debug_client.h>
    
    #include <rcsc/common/logger.h>
    #include <rcsc/common/server_param.h>
    
    /*-------------------------------------------------------------------*/
    /*!
     execute action
     */
    /*
     问题:
     1.agent->world().self().body().abs()与agent->world().self().body().degree()的区别在哪?是不是一个都代表角度,但是一个没有真负,另外一个却有?
     2.角度的正负是如何规定的?从x出发顺时针旋转180为正,逆时针旋转180为逆?还是说朝向对手的180度为正,朝向自己这边的180为负?
     3.agent->config().version() >= 12.0,这个有什么含义
     
     理解:
     这个函数是Bhv_DangerAreaTackle的执行函数,主要的作用为,根据身体朝向的角度、以及自己的位置与球门宽度的相对位置,还有球的坐标等因素综合判断,来进行一次合理的
     抢断。其合理性在于需要保证铲球不能踢到对方球员或者自己球门内。
     By ChenYanTing
     */
    bool
    Bhv_DangerAreaTackle::execute(rcsc::PlayerAgent * agent)
    {
      rcsc::dlog.addText(rcsc::Logger::TEAM, __FILE__": Bhv_DangerAreaTackle");
    
      if (!agent->world().existKickableOpponent()
          || agent->world().self().tackleProbability() < M_min_probability)//如果不存在可以踢球的敌人并且自己抢断的几率几乎不存在,那么返回false
      {
        rcsc::dlog.addText(rcsc::Logger::TEAM, __FILE__": failed");
        return false;
      }
    
      if (agent->world().self().pos().absY()
          > rcsc::ServerParam::i().goalHalfWidth() + 5.0)//如果自己位置的Y坐标的绝对值大于球门宽度加上0.5
      {
        double power_or_dir = 0.0;
        if (agent->config().version() >= 12.0)
        {
          if (agent->world().self().body().abs() < 10.0)
          {
            // nothing to do
          }
          else if (agent->world().self().body().abs() > 170.0)
          {
            power_or_dir = 180.0;
          }
          else if (agent->world().self().body().degree()
              * agent->world().self().pos().y < 0.0)
          {
            power_or_dir = 180.0;
          }
        }
        else
        {
          // out of goal
          power_or_dir = rcsc::ServerParam::i().maxTacklePower();
          if (agent->world().self().body().abs() < 10.0)
          {
            // nothing to do
          }
          else if (agent->world().self().body().abs() > 170.0)
          {
            power_or_dir = -rcsc::ServerParam::i().maxBackTacklePower();
            if (power_or_dir >= -1.0)
            {
              return false;
            }
          }
          else if (agent->world().self().body().degree()
              * agent->world().self().pos().y < 0.0)
          {
            power_or_dir = -rcsc::ServerParam::i().maxBackTacklePower();
            if (power_or_dir >= -1.0)
            {
              return false;
            }
          }
    
          if (std::fabs(power_or_dir) < 1.0)
          {
            return false;
          }
        }
    
        rcsc::dlog.addText(rcsc::Logger::TEAM, __FILE__": out of goal width");
        agent->debugClient().addMessage("tackle(1)");
        agent->doTackle(power_or_dir);
        agent->setNeckAction(new rcsc::Neck_TurnToBallOrScan());
        return true;
      }
      else
      {
        // within goal width
        double power_sign = 0.0;
        double abs_body = agent->world().self().body().abs();
    
        if (abs_body < 70.0)
          power_sign = 1.0;
        if (abs_body > 110.0)
          power_sign = -1.0;
        if (power_sign == 0.0)
        {
          power_sign = (agent->world().self().body().degree() > 0.0 ? 1.0 : -1.0 );
          if (agent->world().ball().pos().y < 0.0)
          {
            power_sign *= -1.0;
          }
        }
    
        if (agent->config().version() >= 12.0)
        {
          if (power_sign != 0.0)
          {
            double tackle_dir = 0.0;
            if (power_sign < 0.0)
            {
              tackle_dir = 180.0;
            }
    
            rcsc::dlog.addText(rcsc::Logger::TEAM, __FILE__": power_sign = %.0f",
                power_sign);
            agent->debugClient().addMessage("tackle(%.0f)", power_sign);
            agent->doTackle(tackle_dir);
            agent->setNeckAction(new rcsc::Neck_TurnToBallOrScan());
            return true;
          }
        }
        else
        {
          double tackle_power = (
              power_sign >= 0.0 ?
                  rcsc::ServerParam::i().maxTacklePower() :
                  -rcsc::ServerParam::i().maxBackTacklePower() );
          if (std::fabs(tackle_power) < 1.0)
          {
            return false;
          }
    
          if (power_sign != 0.0)
          {
            rcsc::dlog.addText(rcsc::Logger::TEAM, __FILE__": power_sigh =%.0f",
                power_sign);
            agent->debugClient().addMessage("tackle(%.0f)", power_sign);
            agent->doTackle(tackle_power);
            agent->setNeckAction(new rcsc::Neck_TurnToBallOrScan());
            return true;
          }
        }
      }
    
      return false;
    }
    
    

    bhv_go_to_static_ball.cpp

    代码个人理解与存在的问题(已经通过注释标出)

    // -*-c++-*-
    
    /*
     *Copyright:
    
     Copyright (C) Hidehisa AKIYAMA
    
     This code is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation; either version 3, or (at your option)
     any later version.
    
     This code is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
    
     You should have received a copy of the GNU General Public License
     along with this code; see the file COPYING.  If not, write to
     the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
    
     *EndCopyright:
     */
    
    /////////////////////////////////////////////////////////////////////
    
    #ifdef HAVE_CONFIG_H
    #include <config.h>
    #endif
    
    #include "bhv_go_to_static_ball.h"
    
    #include "bhv_set_play.h"
    
    #include <rcsc/action/basic_actions.h>
    #include <rcsc/action/body_go_to_point.h>
    #include <rcsc/action/neck_scan_field.h>
    #include <rcsc/action/neck_turn_to_ball_or_scan.h>
    
    #include <rcsc/player/player_agent.h>
    
    #include <rcsc/common/logger.h>
    #include <rcsc/common/server_param.h>
    
    using namespace rcsc;
    
    /*-------------------------------------------------------------------*/
    /*!
    
    */
    /*
     问题:
     1.M_ball_place_angle的含义是什么?这种M_开头的变量的含义都带“想”的含义吗?要怎么去理解这一类的变量呢?
     2.angle_diff = wm.ball().angleFromSelf() - M_ball_place_angle,这个angle_diff的含义是什么?为什么要拿他跟15.0进行比较?
     
     
     理解:
     这个函数是Bhv_GoToStaticBall的执行函数,主要的作用为,根据球的角度、自己的位置、身体的朝向等因素,来执行球员跑到静态球的动作。
     By ChenYanTing
     */
    bool
    Bhv_GoToStaticBall::execute( PlayerAgent * agent )
    {
        const double dir_margin = 15.0;
    
        const WorldModel & wm = agent->world();
    
        AngleDeg angle_diff = wm.ball().angleFromSelf() - M_ball_place_angle;
    
        if ( angle_diff.abs() < dir_margin
             && wm.ball().distFromSelf() < ( wm.self().playerType().playerSize()
                                             + ServerParam::i().ballSize()
                                             + 0.08 )
             )
        {
            // already reach
            return false;
        }
    
        // decide sub-target point
        Vector2D sub_target = wm.ball().pos()
                              + Vector2D::polar2vector( 2.0, M_ball_place_angle + 180.0 );
    
        double dash_power = 20.0;
        double dash_speed = -1.0;
        if ( wm.ball().distFromSelf() > 2.0 )
        {
            dash_power = Bhv_SetPlay::get_set_play_dash_power( agent );
        }
        else
        {
            dash_speed = wm.self().playerType().playerSize();
            dash_power = wm.self().playerType().getDashPowerToKeepSpeed( dash_speed, wm.self().effort() );
        }
    
        // it is necessary to go to sub target point
        if ( angle_diff.abs() > dir_margin )
        {
            dlog.addText( Logger::TEAM,
                                __FILE__": go to sub-target(%.1f, %.1f)",
                                sub_target.x, sub_target.y );
            Body_GoToPoint( sub_target,
                            0.1,
                            dash_power,
                            dash_speed ).execute( agent );
        }
        // dir diff is small. go to ball
        else
        {
            // body dir is not right
            if ( ( wm.ball().angleFromSelf() - wm.self().body() ).abs() > 1.5 )
            {
                dlog.addText( Logger::TEAM,
                                    __FILE__": turn to ball" );
                Body_TurnToBall().execute( agent );
            }
            // dash to ball
            else
            {
                dlog.addText( Logger::TEAM,
                                    __FILE__": dash to ball" );
                agent->doDash( dash_power );
            }
        }
    
        agent->setNeckAction( new Neck_ScanField() );
    
        return true;
    
    
    

    bhv_goalie_basic_move.cpp

    代码个人理解与存在的问题(已经通过注释标出)

    // -*-c++-*-
    
    /*
     *Copyright:
    
     Copyright (C) Hidehisa AKIYAMA
    
     This code is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation; either version 3, or (at your option)
     any later version.
    
     This code is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
    
     You should have received a copy of the GNU General Public License
     along with this code; see the file COPYING.  If not, write to
     the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
    
     *EndCopyright:
     */
    
    /////////////////////////////////////////////////////////////////////
    
    #ifdef HAVE_CONFIG_H
    #include <config.h>
    #endif
    
    #include "bhv_goalie_basic_move.h"
    
    #include "bhv_basic_tackle.h"
    #include "neck_goalie_turn_neck.h"
    
    #include <rcsc/action/basic_actions.h>
    #include <rcsc/action/body_go_to_point.h>
    #include <rcsc/action/body_stop_dash.h>
    #include <rcsc/action/bhv_go_to_point_look_ball.h>
    
    #include <rcsc/player/player_agent.h>
    #include <rcsc/player/intercept_table.h>
    #include <rcsc/player/debug_client.h>
    
    #include <rcsc/common/logger.h>
    #include <rcsc/common/server_param.h>
    #include <rcsc/geom/line_2d.h>
    #include <rcsc/soccer_math.h>
    
    using namespace rcsc;
    
    /*-------------------------------------------------------------------*/
    /*!
    
     */
    /*
     问题:
     无
     
     理解:
     这个函数是Bhv_GoalieBasicMove的执行函数,主要是调用子函数,实现一系列移动需要进行的动作。
     By ChenYanTing
     */
    bool
    Bhv_GoalieBasicMove::execute( PlayerAgent * agent )
    {
        const Vector2D move_point = getTargetPoint( agent );
    
        dlog.addText( Logger::TEAM,
                      __FILE__": Bhv_GoalieBasicMove. move_point(%.2f %.2f)",
                      move_point.x, move_point.y );
    
        //////////////////////////////////////////////////////////////////
        // tackle
        if ( Bhv_BasicTackle( 0.8, 90.0 ).execute( agent ) )
        {
            dlog.addText( Logger::TEAM,
                          __FILE__": tackle" );
            return true;
        }
    
        /////////////////////////////////////////////////////////////
        //----------------------------------------------------------
        if ( doPrepareDeepCross( agent, move_point ) )
        {
            // face to opponent side to wait the opponent last cross pass
            return true;
        }
        //----------------------------------------------------------
        // check distance to the move target point
        // if already there, try to stop
        if ( doStopAtMovePoint( agent, move_point ) )
        {
            // execute stop action
            return true;
        }
        //----------------------------------------------------------
        // check whether ball is in very dangerous state
        if ( doMoveForDangerousState( agent, move_point ) )
        {
            // execute emergency action
            return true;
        }
        //----------------------------------------------------------
        // check & correct X difference
        if ( doCorrectX( agent, move_point ) )
        {
            // execute x-pos adjustment action
            return true;
        }
    
        //----------------------------------------------------------
        if ( doCorrectBodyDir( agent, move_point, true ) ) // consider opp
        {
            // exeucte turn
            return true;
        }
    
        //----------------------------------------------------------
        if ( doGoToMovePoint( agent, move_point ) )
        {
            // mainly execute Y-adjustment if body direction is OK. -> only dash
            // if body direction is not good, nomal go to action is done.
            return true;
        }
    
        //----------------------------------------------------------
        // change my body angle to desired angle
        if ( doCorrectBodyDir( agent, move_point, false ) ) // not consider opp
        {
            return true;
        }
    
        dlog.addText( Logger::TEAM,
                      __FILE__": only look ball" );
        agent->debugClient().addMessage( "OnlyTurnNeck" );
    
        agent->doTurn( 0.0 );
        agent->setNeckAction( new Neck_GoalieTurnNeck() );
    
        return true;
    }
    
    /*-------------------------------------------------------------------*/
    /*!
    
     */
    /*
     问题:
     1.wm.ball().inertiaPoint( ball_reach_step ),这个球的惯性点指的是什么?之前其实也有问过一次,但是貌似被忽略啦。
     2.180行的right_pole是指的什么?
     
     理解:
     这个函数是Bhv_GoalieBasicMove的getTargetPoint函数,主要是根据球的轨迹、敌人的位置等因素,来计算出守门员应该处于的目标点并且返回该值。
     By ChenYanTing
     */
    Vector2D
    Bhv_GoalieBasicMove::getTargetPoint( PlayerAgent * agent )
    {
        //因为是守门员,所以要贴着自己的球门移动,将x设置为两类,base_move_x与danger_move_x
        const double base_move_x = -49.8;
        const double danger_move_x = -51.5;
        const WorldModel & wm = agent->world();
    
        int ball_reach_step = 0;
        if ( ! wm.existKickableTeammate()
             && ! wm.existKickableOpponent() )
        {
            ball_reach_step
                = std::min( wm.interceptTable()->teammateReachCycle(),
                            wm.interceptTable()->opponentReachCycle() );
        }
        const Vector2D base_pos = wm.ball().inertiaPoint( ball_reach_step );
    
    
        //---------------------------------------------------------//
        // angle is very dangerous
        if ( base_pos.y > ServerParam::i().goalHalfWidth() + 3.0 )
        {
            Vector2D right_pole( - ServerParam::i().pitchHalfLength(),
                                 ServerParam::i().goalHalfWidth() );
            AngleDeg angle_to_pole = ( right_pole - base_pos ).th();
    
            if ( -140.0 < angle_to_pole.degree()
                 && angle_to_pole.degree() < -90.0 )
            {
                agent->debugClient().addMessage( "RPole" );
                return Vector2D( danger_move_x, ServerParam::i().goalHalfWidth() + 0.001 );
            }
        }
        else if ( base_pos.y < -ServerParam::i().goalHalfWidth() - 3.0 )
        {
            Vector2D left_pole( - ServerParam::i().pitchHalfLength(),
                                - ServerParam::i().goalHalfWidth() );
            AngleDeg angle_to_pole = ( left_pole - base_pos ).th();
    
            if ( 90.0 < angle_to_pole.degree()
                 && angle_to_pole.degree() < 140.0 )
            {
                agent->debugClient().addMessage( "LPole" );
                return Vector2D( danger_move_x, - ServerParam::i().goalHalfWidth() - 0.001 );
            }
        }
    
        //---------------------------------------------------------//
        // ball is close to goal line
        if ( base_pos.x < -ServerParam::i().pitchHalfLength() + 8.0
             && base_pos.absY() > ServerParam::i().goalHalfWidth() + 2.0 )
        {
            Vector2D target_point( base_move_x, ServerParam::i().goalHalfWidth() - 0.1 );
            if ( base_pos.y < 0.0 )
            {
                target_point.y *= -1.0;
            }
    
            dlog.addText( Logger::TEAM,
                          __FILE__": getTarget. target is goal pole" );
            agent->debugClient().addMessage( "Pos(1)" );
    
            return target_point;
        }
    
    //---------------------------------------------------------//
        {
            const double x_back = 7.0; // tune this!!
            int ball_pred_cycle = 5; // tune this!!
            const double y_buf = 0.5; // tune this!!
            const Vector2D base_point( - ServerParam::i().pitchHalfLength() - x_back,
                                       0.0 );
            Vector2D ball_point;
            if ( wm.existKickableOpponent() )
            {
                ball_point = base_pos;
                agent->debugClient().addMessage( "Pos(2)" );
            }
            else
            {
                int opp_min = wm.interceptTable()->opponentReachCycle();
                if ( opp_min < ball_pred_cycle )
                {
                    ball_pred_cycle = opp_min;
                    dlog.addText( Logger::TEAM,
                                  __FILE__": opp may reach near future. cycle = %d",
                                  opp_min );
                }
    
                ball_point
                    = inertia_n_step_point( base_pos,
                                            wm.ball().vel(),
                                            ball_pred_cycle,
                                            ServerParam::i().ballDecay() );
                agent->debugClient().addMessage( "Pos(3)" );
            }
    
            if ( ball_point.x < base_point.x + 0.1 )
            {
                ball_point.x = base_point.x + 0.1;
            }
    
            Line2D ball_line( ball_point, base_point );
            double move_y = ball_line.getY( base_move_x );
    
            if ( move_y > ServerParam::i().goalHalfWidth() - y_buf )
            {
                move_y = ServerParam::i().goalHalfWidth() - y_buf;
            }
            if ( move_y < - ServerParam::i().goalHalfWidth() + y_buf )
            {
                move_y = - ServerParam::i().goalHalfWidth() + y_buf;
            }
    
            return Vector2D( base_move_x, move_y );
        }
    }
    
    /*-------------------------------------------------------------------*/
    /*!
    
     */
    /*
     问题:
     1.my_inc = mytype.staminaIncMax() * wm.self().recovery(),这个计算出来的是什么?
     
     理解:
     这个函数是Bhv_GoalieBasicMove的getBasicDashPower函数,主要是根据球的x坐标,进行危险度划分,然后再结合自身的体力值等因素来得到最合适的DashPower并且返回。
     By ChenYanTing
     */
    double
    Bhv_GoalieBasicMove::getBasicDashPower( PlayerAgent * agent,
                                            const Vector2D & move_point )
    {
        const WorldModel & wm = agent->world();
        const PlayerType & mytype = wm.self().playerType();
    
        const double my_inc = mytype.staminaIncMax() * wm.self().recovery();
    
        if ( std::fabs( wm.self().pos().x - move_point.x ) > 3.0 )
        {
            return ServerParam::i().maxDashPower();
        }
    
        if ( wm.ball().pos().x > -30.0 )
        {
            if ( wm.self().stamina() < ServerParam::i().staminaMax() * 0.9 )
            {
                return my_inc * 0.5;
            }
            agent->debugClient().addMessage( "P1" );
            return my_inc;
        }
        else if ( wm.ball().pos().x > ServerParam::i().ourPenaltyAreaLineX() )
        {
            if ( wm.ball().pos().absY() > 20.0 )
            {
                // penalty area
                agent->debugClient().addMessage( "P2" );
                return my_inc;
            }
            if ( wm.ball().vel().x > 1.0 )
            {
                // ball is moving to opponent side
                agent->debugClient().addMessage( "P2.5" );
                return my_inc * 0.5;
            }
    
            int opp_min = wm.interceptTable()->opponentReachCycle();
            if ( opp_min <= 3 )
            {
                agent->debugClient().addMessage( "P2.3" );
                return ServerParam::i().maxDashPower();
            }
    
            if ( wm.self().stamina() < ServerParam::i().staminaMax() * 0.7 )
            {
                agent->debugClient().addMessage( "P2.6" );
                return my_inc * 0.7;
            }
            agent->debugClient().addMessage( "P3" );
            return ServerParam::i().maxDashPower() * 0.6;
        }
        else
        {
            if ( wm.ball().pos().absY() < 15.0
                 || wm.ball().pos().y * wm.self().pos().y < 0.0 ) // opposite side
            {
                agent->debugClient().addMessage( "P4" );
                return ServerParam::i().maxDashPower();
            }
            else
            {
                agent->debugClient().addMessage( "P5" );
                return my_inc;
            }
        }
    }
    
    /*-------------------------------------------------------------------*/
    /*!
    
     */
    /*
     问题:
     无
     
     理解:
     这个函数是Bhv_GoalieBasicMove的doPrepareDeepCross函数,主要作用看不太懂。
     By ChenYanTing
     */
    bool
    Bhv_GoalieBasicMove::doPrepareDeepCross( PlayerAgent * agent,
                                             const Vector2D & move_point )
    {
        if ( move_point.absY() < ServerParam::i().goalHalfWidth() - 0.8 )
        {
            // consider only very deep cross
            dlog.addText( Logger::TEAM,
                          __FILE__": doPrepareDeepCross no deep cross" );
            return false;
        }
    
        const WorldModel & wm = agent->world();
    
        const Vector2D goal_c( - ServerParam::i().pitchHalfLength(), 0.0 );
    
        Vector2D goal_to_ball = wm.ball().pos() - goal_c;
    
        if ( goal_to_ball.th().abs() < 60.0 )
        {
            // ball is not in side cross area
            dlog.addText( Logger::TEAM,
                          __FILE__": doPrepareDeepCross.ball is not in side cross area" );
            return false;
        }
    
        Vector2D my_inertia = wm.self().inertiaFinalPoint();
        double dist_thr = wm.ball().distFromSelf() * 0.1;
        if ( dist_thr < 0.5 ) dist_thr = 0.5;
        //double dist_thr = 0.5;
    
        if ( my_inertia.dist( move_point ) > dist_thr )
        {
            // needed to go to move target point
            double dash_power = getBasicDashPower( agent, move_point );
            dlog.addText( Logger::TEAM,
                          __FILE__": doPrepareDeepCross. need to move. power=%.1f",
                          dash_power );
            agent->debugClient().addMessage( "DeepCrossMove%.0f", dash_power );
            agent->debugClient().setTarget( move_point );
            agent->debugClient().addCircle( move_point, dist_thr );
    
            doGoToPointLookBall( agent,
                                 move_point,
                                 wm.ball().angleFromSelf(),
                                 dist_thr,
                                 dash_power );
            return true;
        }
    
        AngleDeg body_angle = ( wm.ball().pos().y < 0.0
                                ? 10.0
                                : -10.0 );
        agent->debugClient().addMessage( "PrepareCross" );
        dlog.addText( Logger::TEAM,
                      __FILE__": doPrepareDeepCross  body angle = %.1f  move_point(%.1f %.1f)",
                      body_angle.degree(),
                      move_point.x, move_point.y );
        agent->debugClient().setTarget( move_point );
    
        Body_TurnToAngle( body_angle ).execute( agent );
        agent->setNeckAction( new Neck_GoalieTurnNeck() );
        return true;
    }
    
    /*-------------------------------------------------------------------*/
    /*!
    
     */
    /*
     问题:
     无
     
     理解:
     这个函数是Bhv_GoalieBasicMove的doStopAtMovePoint函数,主要作用是结合自己的位置、速度还有目标点的位置,来判断自己是否应该终止跑向目标点的行动。
     By ChenYanTing
     */
    bool
    Bhv_GoalieBasicMove::doStopAtMovePoint( PlayerAgent * agent,
                                            const Vector2D & move_point )
    {
        //----------------------------------------------------------
        // already exist at target point
        // but inertia movement is big
        // stop dash
    
        const WorldModel & wm = agent->world();
        double dist_thr = wm.ball().distFromSelf() * 0.1;
        if ( dist_thr < 0.5 ) dist_thr = 0.5;
    
        // now, in the target area
        if ( wm.self().pos().dist( move_point ) < dist_thr )
        {
            const Vector2D my_final
                = inertia_final_point( wm.self().pos(),
                                       wm.self().vel(),
                                       wm.self().playerType().playerDecay() );
            // after inertia move, can stay in the target area
            if ( my_final.dist( move_point ) < dist_thr )
            {
                agent->debugClient().addMessage( "InertiaStay" );
                dlog.addText( Logger::TEAM,
                              __FILE__": doStopAtMovePoint. inertia stay" );
                return false;
            }
    
            // try to stop at the current point
            dlog.addText( Logger::TEAM,
                          __FILE__": doStopAtMovePoint. stop dash" );
            agent->debugClient().addMessage( "Stop" );
            agent->debugClient().setTarget( move_point );
    
            Body_StopDash( true ).execute( agent ); // save recovery
            agent->setNeckAction( new Neck_GoalieTurnNeck() );
            return true;
        }
    
        return false;
    }
    
    /*-------------------------------------------------------------------*/
    /*!
    
     */
    /*
     问题:
     无
     
     理解:
     这个函数是Bhv_GoalieBasicMove的doMoveForDangerousState函数,主要作用是结合自身的位置、球的位置、敌人距离球的距离等因素,来判断自己是否应该前往危险区域。
     By ChenYanTing
     */
    bool
    Bhv_GoalieBasicMove::doMoveForDangerousState( PlayerAgent * agent,
                                                  const Vector2D & move_point )
    {
        const WorldModel& wm = agent->world();
    
        const double x_buf = 0.5;
    
        const Vector2D ball_next = wm.ball().pos() + wm.ball().vel();
    
        dlog.addText( Logger::TEAM,
                      __FILE__": doMoveForDangerousState" );
    
        if ( std::fabs( move_point.x - wm.self().pos().x ) > x_buf
             && ball_next.x < -ServerParam::i().pitchHalfLength() + 11.0
             && ball_next.absY() < ServerParam::i().goalHalfWidth() + 1.0 )
        {
            // x difference to the move point is over threshold
            // but ball is in very dangerous area (just front of our goal)
    
            // and, exist opponent close to ball
            if ( ! wm.opponentsFromBall().empty()
                 && wm.opponentsFromBall().front()->distFromBall() < 2.0 )
            {
                Vector2D block_point
                    = wm.opponentsFromBall().front()->pos();
                block_point.x -= 2.5;
                block_point.y = move_point.y;
    
                if ( wm.self().pos().x < block_point.x )
                {
                    block_point.x = wm.self().pos().x;
                }
    
                dlog.addText( Logger::TEAM,
                              __FILE__": block opponent kickaer" );
                agent->debugClient().addMessage( "BlockOpp" );
    
                if ( doGoToMovePoint( agent, block_point ) )
                {
                    return true;
                }
    
                double dist_thr = wm.ball().distFromSelf() * 0.1;
                if ( dist_thr < 0.5 ) dist_thr = 0.5;
    
                agent->debugClient().setTarget( block_point );
                agent->debugClient().addCircle( block_point, dist_thr );
    
                doGoToPointLookBall( agent,
                                     move_point,
                                     wm.ball().angleFromSelf(),
                                     dist_thr,
                                     ServerParam::i().maxDashPower() );
                return true;
            }
        }
    
        return false;
    }
    
    /*-------------------------------------------------------------------*/
    /*!
    
     */
    /*
     问题:
     无
     
     理解:
     这个函数是Bhv_GoalieBasicMove的doCorrectX函数,主要作用是j考虑球与地方球员的危险程度,来校准当前守门员的x值。
     By ChenYanTing
     */
    bool
    Bhv_GoalieBasicMove::doCorrectX( PlayerAgent * agent,
                                     const Vector2D & move_point )
    {
        const WorldModel & wm = agent->world();
    
        const double x_buf = 0.5;
    
        dlog.addText( Logger::TEAM,
                      __FILE__": doCorrectX" );
        if ( std::fabs( move_point.x - wm.self().pos().x ) < x_buf )
        {
            // x difference is already small.
            dlog.addText( Logger::TEAM,
                          __FILE__": doCorrectX. x diff is small" );
            return false;
        }
    
        int opp_min_cyc = wm.interceptTable()->opponentReachCycle();
        if ( ( ! wm.existKickableOpponent() && opp_min_cyc >= 4 )
             || wm.ball().distFromSelf() > 18.0 )
        {
            double dash_power = getBasicDashPower( agent, move_point );
    
            dlog.addText( Logger::TEAM,
                          __FILE__": doCorrectX. power=%.1f",
                          dash_power );
            agent->debugClient().addMessage( "CorrectX%.0f", dash_power );
            agent->debugClient().setTarget( move_point );
            agent->debugClient().addCircle( move_point, x_buf );
    
            if ( ! wm.existKickableOpponent()
                 && wm.ball().distFromSelf() > 30.0 )
            {
                if ( ! Body_GoToPoint( move_point, x_buf, dash_power
                                       ).execute( agent ) )
                {
                    AngleDeg body_angle = ( wm.self().body().degree() > 0.0
                                            ? 90.0
                                            : -90.0 );
                    Body_TurnToAngle( body_angle ).execute( agent );
    
                }
                agent->setNeckAction( new Neck_TurnToBall() );
                return true;
            }
    
            doGoToPointLookBall( agent,
                                 move_point,
                                 wm.ball().angleFromSelf(),
                                 x_buf,
                                 dash_power );
            return true;
        }
    
        return false;
    }
    
    /*-------------------------------------------------------------------*/
    /*!
    
     */
    /*
     问题:
     无
     
     理解:
     这个函数是Bhv_GoalieBasicMove的doCorrectX函数,主要作用是根据自身与球的角度差、地方球员的威胁程度等因素来调节守门员的身体朝向。
     By ChenYanTing
     */
    bool
    Bhv_GoalieBasicMove::doCorrectBodyDir( PlayerAgent * agent,
                                           const Vector2D & move_point,
                                           const bool consider_opp )
    {
        // adjust only body direction
    
        const WorldModel & wm = agent->world();
    
        const Vector2D ball_next = wm.ball().pos() + wm.ball().vel();
    
        const AngleDeg target_angle = ( ball_next.y < 0.0 ? -90.0 : 90.0 );
        const double angle_diff = ( wm.self().body() - target_angle ).abs();
    
        dlog.addText( Logger::TEAM,
                      __FILE__": doCorrectBodyDir" );
    
        if ( angle_diff < 5.0 )
        {
            return false;
        }
    
    #if 1
        {
            const Vector2D goal_c( - ServerParam::i().pitchHalfLength(), 0.0 );
            Vector2D goal_to_ball = wm.ball().pos() - goal_c;
            if ( goal_to_ball.th().abs() >= 60.0 )
            {
                dlog.addText( Logger::TEAM,
                              __FILE__": doCorrectBodyDir. danger area" );
                return false;
            }
        }
    #else
        if ( wm.ball().pos().x < -36.0
             && wm.ball().pos().absY() < 15.0
             && wm.self().pos().dist( move_point ) > 1.5 )
        {
            dlog.addText( Logger::TEAM,
                          __FILE__": doCorrectBodyDir. danger area" );
            return false;
        }
    #endif
    
        double opp_ball_dist
            = ( wm.opponentsFromBall().empty()
                ? 100.0
                : wm.opponentsFromBall().front()->distFromBall() );
        if ( ! consider_opp
             || opp_ball_dist > 7.0
             || wm.ball().distFromSelf() > 20.0
             || ( std::fabs( move_point.y - wm.self().pos().y ) < 1.0 // y diff
                  && ! wm.existKickableOpponent() ) )
        {
            dlog.addText( Logger::TEAM,
                          __FILE__": body face to %.1f.  angle_diff=%.1f %s",
                          target_angle.degree(), angle_diff,
                          consider_opp ? "consider_opp" : "" );
            agent->debugClient().addMessage( "CorrectBody%s",
                                             consider_opp ? "WithOpp" : "" );
            Body_TurnToAngle( target_angle ).execute( agent );
            agent->setNeckAction( new Neck_GoalieTurnNeck() );
            return true;
        }
    
        return false;
    }
    
    /*-------------------------------------------------------------------*/
    /*!
    
     */
    /*
     问题:
     无
     
     理解:
     这个函数是Bhv_GoalieBasicMove的doGoToMovePoint函数,主要作用是根据身体的朝向、目标点与自身的位置等因素来执行移动到目标点的动作。
     By ChenYanTing
     */
    bool
    Bhv_GoalieBasicMove::doGoToMovePoint( PlayerAgent * agent,
                                          const Vector2D & move_point )
    {
        // move to target point
        // check Y coordinate difference
    
        const WorldModel & wm = agent->world();
    
        double dist_thr = wm.ball().distFromSelf() * 0.08;
        if ( dist_thr < 0.5 ) dist_thr = 0.5;
    
        const double y_diff = std::fabs( move_point.y - wm.self().pos().y );
        if ( y_diff < dist_thr )
        {
            // already there
            dlog.addText( Logger::TEAM,
                          __FILE__": doGoToMovePoint. y_diff=%.2f < thr=%.2f",
                          y_diff, dist_thr );
            return false;
        }
    
        //----------------------------------------------------------//
        // dash to body direction
    
        double dash_power = getBasicDashPower( agent, move_point );
    
        // body direction is OK
        if ( std::fabs( wm.self().body().abs() - 90.0 ) < 7.0 )
        {
            // calc dash power only to reach the target point
            double required_power = y_diff / wm.self().dashRate();
            if ( dash_power > required_power )
            {
                dash_power = required_power;
            }
    
            if ( move_point.y > wm.self().pos().y )
            {
                if ( wm.self().body().degree() < 0.0 )
                {
                    dash_power *= -1.0;
                }
            }
            else
            {
                if ( wm.self().body().degree() > 0.0 )
                {
                    dash_power *= -1.0;
                }
            }
    
            dash_power = ServerParam::i().normalizeDashPower( dash_power );
    
            dlog.addText( Logger::TEAM,
                          __FILE__": doGoToMovePoint. CorrectY(1) power= %.1f",
                          dash_power );
            agent->debugClient().addMessage( "CorrectY(1)%.0f", dash_power );
            agent->debugClient().setTarget( move_point );
    
            agent->doDash( dash_power );
            agent->setNeckAction( new Neck_GoalieTurnNeck() );
        }
        else
        {
            dlog.addText( Logger::TEAM,
                          __FILE__": doGoToMovePoint. CorrectPos power= %.1f",
                          dash_power );
            agent->debugClient().addMessage( "CorrectPos%.0f", dash_power );
            agent->debugClient().setTarget( move_point );
            agent->debugClient().addCircle( move_point, dist_thr );
    
            doGoToPointLookBall( agent,
                                 move_point,
                                 wm.ball().angleFromSelf(),
                                 dist_thr,
                                 dash_power );
        }
        return true;
    }
    
    /*-------------------------------------------------------------------*/
    /*!
    
     */
    /*
     问题:
     无
     
     理解:
     这个函数是Bhv_GoalieBasicMove的doGoToPointLookBall函数,只是在doGoToPoint函数的基础上加了一个Look的动作
     By ChenYanTing
     */
    void
    Bhv_GoalieBasicMove::doGoToPointLookBall( PlayerAgent * agent,
                                              const Vector2D & target_point,
                                              const AngleDeg & body_angle,
                                              const double & dist_thr,
                                              const double & dash_power,
                                              const double & back_power_rate )
    {
        const WorldModel & wm = agent->world();
    
        if ( wm.gameMode().type() == GameMode::PlayOn
             || wm.gameMode().type() == GameMode::PenaltyTaken_ )
        {
            agent->debugClient().addMessage( "Goalie:GoToLook" );
            dlog.addText( Logger::TEAM,
                          __FILE__": doGoToPointLookBall. use GoToPointLookBall" );
            Bhv_GoToPointLookBall( target_point,
                                   dist_thr,
                                   dash_power,
                                   back_power_rate
                                   ).execute( agent );
        }
        else
        {
            agent->debugClient().addMessage( "Goalie:GoTo" );
            dlog.addText( Logger::TEAM,
                          __FILE__": doGoToPointLookBall. use GoToPoint" );
            if ( Body_GoToPoint( target_point, dist_thr, dash_power
                                 ).execute( agent ) )
            {
                dlog.addText( Logger::TEAM,
                              __FILE__": doGoToPointLookBall. go" );
            }
            else
            {
                Body_TurnToAngle( body_angle ).execute( agent );
                dlog.addText( Logger::TEAM,
                              __FILE__": doGoToPointLookBall. turn to %.1f",
                              body_angle.degree() );
            }
    
            agent->setNeckAction( new Neck_TurnToBall() );
        }
    }
    
    
  • 相关阅读:
    JQuery基础知识--方便忘记时查看
    关于jquery.validate.js的用法
    JQuery ajax提交表单及表单验证
    thinkphp rabc权限总结
    关于jquery ajax项目总结
    中国剩余定理及其拓展 CRT&EXGCD
    bzoj 4899 记忆的轮廓 题解(概率dp+决策单调性优化)
    bzoj3307 雨天的尾巴题解及改题过程(线段树合并+lca+树上差分)
    20190614考试心态爆炸记
    fhq Treap(无旋Treap)
  • 原文地址:https://www.cnblogs.com/782687539-nanfu/p/12707600.html
Copyright © 2020-2023  润新知