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() );
    }
}

posted @ 2020-01-30 23:31  南孚先生  阅读(349)  评论(0编辑  收藏  举报