• Robcup2D足球学习记录【2020.01.18】


    bhv_strict_check_shoot.cpp

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

    注释的格式为:
    /*
    问题:
    1.xxxx
    2.xxxx

    理解:
    这个函数是xxxxx
    By ChenYanTing
    */

    // -*-c++-*-
    
    /*!
      file bhv_pass_kick_find_receiver.cpp
      rief search the pass receiver player and perform pass kick if possible
    */
    
    /*
     *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_pass_kick_find_receiver.h"
    
    #include "action_chain_holder.h"
    #include "action_chain_graph.h"
    #include "field_analyzer.h"
    
    #include "neck_turn_to_receiver.h"
    
    #include <rcsc/action/bhv_scan_field.h>
    #include <rcsc/action/body_hold_ball.h>
    #include <rcsc/action/body_kick_one_step.h>
    #include <rcsc/action/body_smart_kick.h>
    #include <rcsc/action/body_stop_ball.h>
    #include <rcsc/action/body_turn_to_point.h>
    #include <rcsc/action/neck_scan_field.h>
    #include <rcsc/action/neck_turn_to_point.h>
    #include <rcsc/action/neck_turn_to_player_or_scan.h>
    #include <rcsc/action/view_synch.h>
    #include <rcsc/action/kick_table.h>
    #include <rcsc/player/player_agent.h>
    #include <rcsc/player/abstract_player_object.h>
    #include <rcsc/player/soccer_intention.h>
    #include <rcsc/player/intercept_table.h>
    #include <rcsc/player/say_message_builder.h>
    #include <rcsc/common/server_param.h>
    #include <rcsc/common/logger.h>
    #include <rcsc/math_util.h>
    
    #include <vector>
    #include <algorithm>
    #include <cmath>
    
    // #define DEBUG_PRINT
    
    using namespace rcsc;
    
    
    class IntentionPassKickFindReceiver
        : public SoccerIntention {
    private:
        int M_step;
        int M_receiver_unum;
        Vector2D M_receive_point;
    
    public:
    
        IntentionPassKickFindReceiver( const int receiver_unum,
                                       const Vector2D & receive_point )
            : M_step( 0 ),
              M_receiver_unum( receiver_unum ),
              M_receive_point( receive_point )
          { }
    
        bool finished( const PlayerAgent * agent );
    
        bool execute( PlayerAgent * agent );
    
    private:
    
    };
    
    /*-------------------------------------------------------------------*/
    /*!
    
     */
    /*
     问题:
    无
     
     
     理解:
     这个函数是IntentionPassKickFindReceiver的finished函数,主要作用是根据kickable、reciever等因素在IntentionPassKickFindReceiver结束时返回一些提示
     By ChenYanTing
     */
    bool
    IntentionPassKickFindReceiver::finished( const PlayerAgent * agent )
    {
        ++M_step;
    
        dlog.addText( Logger::TEAM,
                      __FILE__": (finished) step=%d",
                      M_step );
    
        if ( M_step >= 2 )
        {
            dlog.addText( Logger::TEAM,
                          __FILE__": (finished) time over" );
            return true;
        }
    
        const WorldModel & wm = agent->world();
    
        //
        // check kickable
        //
    
        if ( ! wm.self().isKickable() )
        {
            dlog.addText( Logger::TEAM,
                          __FILE__": (finished) no kickable" );
            return true;
        }
    
        //
        // check receiver
        //
    
        const AbstractPlayerObject * receiver = wm.ourPlayer( M_receiver_unum );
    
        if ( ! receiver )
        {
            dlog.addText( Logger::TEAM,
                          __FILE__": (finished) NULL receiver" );
            return true;
        }
    
        if ( receiver->unum() == wm.self().unum() )
        {
            dlog.addText( Logger::TEAM,
                          __FILE__": (finished) receiver is self" );
            return true;
        }
    
        if ( receiver->posCount() <= 0 )
        {
            dlog.addText( Logger::TEAM,
                          __FILE__": (finished) already seen" );
            return true;
        }
    
        //
        // check opponent
        //
    
        if ( wm.existKickableOpponent() )
        {
            dlog.addText( Logger::TEAM,
                          __FILE__": (finished) exist kickable opponent" );
            return true;
        }
    
        if ( wm.interceptTable()->opponentReachCycle() <= 1 )
        {
            dlog.addText( Logger::TEAM,
                          __FILE__": (finished) opponent may be kickable" );
            return true;
        }
    
        //
        // check next kickable
        //
    
        double kickable2 = std::pow( wm.self().playerType().kickableArea()
                                     - wm.self().vel().r() * ServerParam::i().playerRand()
                                     - wm.ball().vel().r() * ServerParam::i().ballRand()
                                     - 0.15,
                                     2 );
        Vector2D self_next = wm.self().pos() + wm.self().vel();
        Vector2D ball_next = wm.ball().pos() + wm.ball().vel();
    
        if ( self_next.dist2( ball_next ) > kickable2 )
        {
            // unkickable if turn is performed.
            dlog.addText( Logger::TEAM,
                          __FILE__": (finished) unkickable at next cycle" );
            return true;
        }
    
        return false;
    }
    
    
    /*-------------------------------------------------------------------*/
    /*!
    
     */
    Bhv_PassKickFindReceiver::Bhv_PassKickFindReceiver( const ActionChainGraph & chain_graph )
        : M_chain_graph( chain_graph )
    {
    }
    
    
    /*-------------------------------------------------------------------*/
    /*!
    
     */
    */
    /*
     问题:
     1.AngleDeg类有什么用?
     2.M_receive_point是什么?为什么face_point = ( receiver_pos + M_receive_point ) * 0.5?无法理解这个计算公式
     
     
     
     理解:
     这个函数是IntentionPassKickFindReceiver的execute函数,主要作用是根据reciever的坐标还有自己身体的朝向来判断是否需要执行相应的转向接受者的动作
     By ChenYanTing
     */
    bool
    IntentionPassKickFindReceiver::execute( PlayerAgent * agent )
    {
        const WorldModel & wm = agent->world();
        const AbstractPlayerObject * receiver = wm.ourPlayer( M_receiver_unum );
    
        if ( ! receiver )
        {
            return false;
        }
    
        const Vector2D next_self_pos = agent->effector().queuedNextMyPos();
        const AngleDeg next_self_body = agent->effector().queuedNextMyBody();
        const double next_view_width = agent->effector().queuedNextViewWidth().width() * 0.5;
    
        const Vector2D receiver_pos = receiver->pos() + receiver->vel();
        const AngleDeg receiver_angle = ( receiver_pos - next_self_pos ).th();
    
        Vector2D face_point = ( receiver_pos + M_receive_point ) * 0.5;
        AngleDeg face_angle = ( face_point - next_self_pos ).th();
    
        double rate = 0.5;
        while ( ( face_angle - receiver_angle ).abs() > next_view_width - 10.0 )
        {
            rate += 0.1;
            face_point
                = receiver_pos * rate
                + M_receive_point * ( 1.0 - rate );
            face_angle = ( face_point - next_self_pos ).th();
    
            if ( rate > 0.999 )
            {
                break;
            }
        }
    
        dlog.addText( Logger::TEAM,
                      __FILE__": (intentin) facePoint=(%.1f %.1f) faceAngle=%.1f",
                      face_point.x, face_point.y,
                      face_angle.degree() );
        agent->debugClient().addMessage( "IntentionTurnToReceiver%.0f",
                                         face_angle.degree() );
        Body_TurnToPoint( face_point ).execute( agent );
        agent->setNeckAction( new Neck_TurnToPoint( face_point ) );
    
        return true;
    }
    
    
    
    /*-------------------------------------------------------------------*/
    /*-------------------------------------------------------------------*/
    /*-------------------------------------------------------------------*/
    
    
    /*-------------------------------------------------------------------*/
    /*!
    
     */
    /*
     问题:
     1.AngleDeg类有什么用?
     2.M_receive_point是什么?为什么face_point = ( receiver_pos + M_receive_point ) * 0.5?无法理解这个计算公式
     
     理解:
     这个函数是Bhv_PassKickFindReceiver的execute函数,主要作用是根据isKickable、 receiver->unum()等变量来判断是否可以传球,如果不可以则返回false,否则传球并且返回true
     By ChenYanTing
     */
    bool
    Bhv_PassKickFindReceiver::execute( PlayerAgent * agent )
    {
        dlog.addText( Logger::TEAM,
                      __FILE__": Bhv_PassKickFindReceiver" );
    
        const WorldModel & wm = agent->world();
    
        if ( ! wm.self().isKickable() )
        {
            dlog.addText( Logger::TEAM,
                          __FILE__": no kickable" );
            return false;
        }
    
        //
        // validate the pass
        //
        const CooperativeAction & pass = M_chain_graph.getFirstAction();
    
        if ( pass.category() != CooperativeAction::Pass )
        {
            dlog.addText( Logger::TEAM,
                          __FILE__": action(%d) is not a pass type.",
                          pass.category() );
            return false;
        }
    
        const AbstractPlayerObject * receiver = wm.ourPlayer( pass.targetPlayerUnum() );
    
        if ( ! receiver )
        {
            dlog.addText( Logger::TEAM,
                          __FILE__": NULL receiver." );
    
            return false;
        }
    
        dlog.addText( Logger::TEAM,
                      __FILE__": pass receiver unum=%d (%.1f %.1f)",
                      receiver->unum(),
                      receiver->pos().x, receiver->pos().y );
    
        if ( wm.self().unum() == receiver->unum() )
        {
            dlog.addText( Logger::TEAM,
                          __FILE__": receiver is my self." );
            return false;
        }
    
        if ( receiver->unum() == 1 )
        {
            std::cerr << wm.time().cycle() << __FILE__ << ": DO NOT PASS TO OUR GOALIE !!!
    
    ";
            return false;
        }
    
        // if ( receiver->isGhost() )
        // {
        //     dlog.addText( Logger::TEAM,
        //                   __FILE__": receiver is a ghost." );
        //     return false;
        // }
    
        if ( wm.gameMode().type() == GameMode::PlayOn )
        {
            doPassKick( agent, pass );
            return true;
        }
    
    #if 1
        //ht: testing avoid own_goal
        if ( wm.gameMode().type() == 7 ) //GameMode::GoalKick
        {
            Body_KickOneStep( pass.targetPoint(),
                              pass.firstBallSpeed() ).execute( agent );
    
    
            agent->setNeckAction( new Neck_TurnToReceiver( M_chain_graph ) );
            doSayPass( agent, pass );
            //std::cerr << wm.time().cycle() << __FILE__ << wm.self().unum() << ": 应该没有乌龙球了吧!!!
    
    ";
    
            return true;
        }
    #endif //1
    
        //
        // estimate kick step
        //
        int kick_step = pass.kickCount(); //kickStep( wm, pass );
    
        if ( kick_step == 1
             //&& pass.targetPoint().x > -20.0
             && receiver->seenPosCount() <= 3 )
        {
            dlog.addText( Logger::TEAM,
                          __FILE__": 1 step kick." );
            doPassKick( agent, pass );
            return true;
        }
    
        //
        // trying to turn body and/or neck to the pass receiver
        //
    
        if ( doCheckReceiver( agent, pass ) )
        {
            agent->debugClient().addCircle( wm.self().pos(), 3.0 );
            agent->debugClient().addCircle( wm.self().pos(), 5.0 );
            agent->debugClient().addCircle( wm.self().pos(), 10.0 );
    
            return true;
        }
    
        if ( ( kick_step == 1
               && receiver->seenPosCount() > 3 )
             || receiver->isGhost() )
        {
            agent->debugClient().addMessage( "Pass:FindHold2" );
            dlog.addText( Logger::TEAM,
                          __FILE__": (execute) hold ball." );
    
            Body_HoldBall( true,
                           pass.targetPoint(),
                           pass.targetPoint() ).execute( agent );
            doSayPass( agent, pass );
            agent->setNeckAction( new Neck_TurnToReceiver( M_chain_graph ) );
            return true;
        }
    
        //
        // pass kick
        //
    
        doPassKick( agent, pass );
    
        return true;
    }
    
    /*-------------------------------------------------------------------*/
    /*!
    
     */
    /*
     问题:
     1.pass.kickCount()的含义是什么?
     2.M_receive_point是什么?为什么face_point = ( receiver_pos + M_receive_point ) * 0.5?无法理解这个计算公式
     3.Body_KickOneStep和Body_SmartKick的作用是什么?在哪里可以找到?
     
     理解:
     这个函数是Bhv_PassKickFindReceiver的doPassKick函数,主要作用是执行身体转向并且执行传球动作
     By ChenYanTing
     */
    bool
    Bhv_PassKickFindReceiver::doPassKick( PlayerAgent * agent,
                                          const CooperativeAction & pass )
    {
        agent->debugClient().setTarget( pass.targetPlayerUnum() );
        agent->debugClient().setTarget( pass.targetPoint() );
        dlog.addText( Logger::TEAM,
                      __FILE__" (Bhv_PassKickFindReceiver) pass to "
                      "%d receive_pos=(%.1f %.1f) speed=%.3f",
                      pass.targetPlayerUnum(),
                      pass.targetPoint().x, pass.targetPoint().y,
                      pass.firstBallSpeed() );
    
        if ( pass.kickCount() == 1
             || agent->world().gameMode().type() != GameMode::PlayOn )
        {
            Body_KickOneStep( pass.targetPoint(),
                              pass.firstBallSpeed() ).execute( agent );
    
        }
        else
        {
            Body_SmartKick( pass.targetPoint(),
                            pass.firstBallSpeed(),
                            pass.firstBallSpeed() * 0.96,
                            3 ).execute( agent );
        }
        agent->setNeckAction( new Neck_TurnToReceiver( M_chain_graph ) );
        doSayPass( agent, pass );
    
        return true;
    }
    
    /*-------------------------------------------------------------------*/
    /*!
    
     */
    /*
     问题:
     1.这个函数的意义是什么?看不太懂
     
     理解:
     这个函数是Bhv_PassKickFindReceiver的doPassKick函数,主要作用是执行身体转向并且执行传球动作
     By ChenYanTing
     */
    int
    Bhv_PassKickFindReceiver::kickStep( const WorldModel & wm,
                                        const CooperativeAction & pass )
    {
        Vector2D max_vel
            = KickTable::calc_max_velocity( ( pass.targetPoint() - wm.ball().pos() ).th(),
                                            wm.self().kickRate(),
                                            wm.ball().vel() );
    
        // dlog.addText( Logger::TEAM,
        //               __FILE__": (kickStep) maxSpeed=%.3f passSpeed=%.3f",
        //               max_vel.r(), pass.firstBallSpeed() );
    
        if ( max_vel.r2() >= std::pow( pass.firstBallSpeed(), 2 ) )
        {
            return 1;
        }
    
        if ( pass.firstBallSpeed() > 2.5 ) // Magic Number
        {
            return 3;
        }
    
        return 2;
    }
    
    /*-------------------------------------------------------------------*/
    /*!
    
     */
    /*
     问题:
     无
     
     理解:
     这个函数是Bhv_PassKickFindReceiver的doPassKick函数,主要作用是根据目标点的坐标、自己的朝向、球的位置等等来判断是否有必要doCheckReceiver,如果没有返回false,如果有责返回true并且设置朝向面对reciever
     By ChenYanTing
     */
    bool
    Bhv_PassKickFindReceiver::doCheckReceiver( PlayerAgent * agent,
                                               const CooperativeAction & pass )
    {
        const WorldModel & wm = agent->world();
    
        double nearest_opp_dist = 65535.0;
        wm.getOpponentNearestTo( wm.ball().pos(), 10, &nearest_opp_dist );
        if ( nearest_opp_dist < 4.0 )
        {
            dlog.addText( Logger::TEAM,
                          __FILE__": (doCheckReceiver) exist near opponent. dist=%.2f",
                          nearest_opp_dist );
            return false;
        }
    
        const AbstractPlayerObject * receiver = wm.ourPlayer( pass.targetPlayerUnum() );
    
        if ( ! receiver )
        {
            return false;
        }
    
        if ( receiver->seenPosCount() == 0 )
        {
            dlog.addText( Logger::TEAM,
                          __FILE__": (doCheckReceiver) receiver already seen." );
            return false;
        }
    
        //
        // set view mode
        //
        agent->setViewAction( new View_Synch() );
    
        const double next_view_half_width = agent->effector().queuedNextViewWidth().width() * 0.5;
        const double view_min = ServerParam::i().minNeckAngle() - next_view_half_width + 10.0;
        const double view_max = ServerParam::i().maxNeckAngle() + next_view_half_width - 10.0;
    
        //
        // check if turn_neck is necessary or not
        //
        const Vector2D next_self_pos = wm.self().pos() + wm.self().vel();
        const Vector2D player_pos = receiver->pos() + receiver->vel();
        const AngleDeg player_angle = ( player_pos - next_self_pos ).th();
    
        const double angle_diff = ( player_angle - wm.self().body() ).abs();
    
        if ( angle_diff < view_min
             || view_max < angle_diff )
        {
            //
            // need turn
            //
    
            dlog.addText( Logger::TEAM,
                          __FILE__": (doCheckReceiver) need turn."
                          " angleDiff=%.1f viewRange=[%.1f %.1f]",
                          angle_diff, view_min, view_max );
    
            //
            // TODO: check turn moment?
            //
    
    
            //
            // stop the ball
            //
    
            const double next_ball_dist = next_self_pos.dist( wm.ball().pos() + wm.ball().vel() );
            const double noised_kickable_area = wm.self().playerType().kickableArea()
                - wm.ball().vel().r() * ServerParam::i().ballRand()
                - wm.self().vel().r() * ServerParam::i().playerRand()
                - 0.15;
    
            dlog.addText( Logger::TEAM,
                          __FILE__": (doCheckReceiver) next_ball_dist=%.3f"
                          " noised_kickable=%.3f(kickable=%.3f)",
                          next_ball_dist,
                          noised_kickable_area,
                          wm.self().playerType().kickableArea() );
    
            if ( next_ball_dist > noised_kickable_area )
            {
                if ( doKeepBall( agent, pass ) )
                {
                    return true;
                }
    
                if ( Body_StopBall().execute( agent ) )
                {
                    dlog.addText( Logger::TEAM,
                                  __FILE__": (doCheckReceiver) stop the ball" );
                    agent->debugClient().addMessage( "PassKickFind:StopBall" );
                    agent->debugClient().setTarget( receiver->unum() );
    
                    return true;
                }
    
                dlog.addText( Logger::TEAM,
                              __FILE__": (doCheckReceiver) Could not stop the ball???" );
            }
    
            //
            // turn to receiver
            //
    
            doTurnBodyNeckToReceiver( agent, pass );
            return true;
        }
    
        //
        // can see the receiver without turn
        //
        dlog.addText( Logger::TEAM,
                      __FILE__": (doCheckReceiver) can see receiver[%d](%.2f %.2f)"
                      " angleDiff=%.1f viewRange=[%.1f %.1f]",
                      pass.targetPlayerUnum(),
                      player_pos.x, player_pos.y,
                      angle_diff, view_min, view_max );
    
        return false;
    
        // agent->debugClient().addMessage( "Pass:FindHold1" );
        // dlog.addText( Logger::TEAM,
        //               __FILE__": (doCheckReceiver) hold ball." );
    
        // Body_HoldBall( true,
        //                pass.targetPoint(),
        //                pass.targetPoint() ).execute( agent );
        // doSayPass( agent, pass );
        // agent->setNeckAction( new Neck_TurnToReceiver() );
    
        // return true;
    }
    
    /*-------------------------------------------------------------------*/
    /*!
    
     */
    /*
     问题:
     无
     
     理解:
     这个函数是Bhv_PassKickFindReceiver的doKeepBall函数,主要作用是根据getKeepBallVel()函数获得的保持球在keepArea区域的速度,与球自身的速度,来计算踢球的加速度和角度等,最后实现doKeepBall动作
     By ChenYanTing
     */
    bool
    Bhv_PassKickFindReceiver::doKeepBall( rcsc::PlayerAgent * agent,
                                          const CooperativeAction & pass )
    {
        Vector2D ball_vel = getKeepBallVel( agent->world() );
    
        if ( ! ball_vel.isValid() )
        {
            dlog.addText( Logger::TEAM,
                          __FILE__": (doKeepBall) no candidate." );
    
            return false;
        }
    
        //
        // perform first kick
        //
    
        Vector2D kick_accel = ball_vel - agent->world().ball().vel();
        double kick_power = kick_accel.r() / agent->world().self().kickRate();
        AngleDeg kick_angle = kick_accel.th() - agent->world().self().body();
    
        if ( kick_power > ServerParam::i().maxPower() )
        {
            dlog.addText( Logger::TEAM,
                          __FILE__": (doKeepBall) over kick power" );
            return false;
        }
    
        dlog.addText( Logger::TEAM,
                      __FILE__": (doKeepBall) "
                      " ballVel=(%.2f %.2f)"
                      " kickPower=%.1f kickAngle=%.1f",
                      ball_vel.x, ball_vel.y,
                      kick_power,
                      kick_angle.degree() );
    
        agent->debugClient().addMessage( "PassKickFind:KeepBall" );
        agent->debugClient().setTarget( pass.targetPlayerUnum() );
        agent->debugClient().setTarget( agent->world().ball().pos()
                                        + ball_vel
                                        + ball_vel * ServerParam::i().ballDecay() );
    
        agent->doKick( kick_power, kick_angle );
        agent->setNeckAction( new Neck_TurnToReceiver( M_chain_graph ) );
    
        //
        // set turn intention
        //
    
        dlog.addText( Logger::TEAM,
                      __FILE__": (doKeepBall) register intention" );
        agent->setIntention( new IntentionPassKickFindReceiver( pass.targetPlayerUnum(),
                                                                pass.targetPoint() ) );
    
        return true;
    }
    
    /*-------------------------------------------------------------------*/
    /*!
    
     */
    /*
     问题:
     无
     
     理解:
     这个函数是Bhv_PassKickFindReceiver的getKeepBallVel函数,最重要的部分是for循环的内容,通过十二次遍历球员的一周,找到一个最佳位置的球的对应的速度,并且返回。
     By ChenYanTing
     */
    rcsc::Vector2D
    Bhv_PassKickFindReceiver::getKeepBallVel( const rcsc::WorldModel & wm )
    {
        static GameTime s_update_time( 0, 0 );
        static Vector2D s_best_ball_vel( 0.0, 0.0 );
    
        if ( s_update_time == wm.time() )
        {
            return s_best_ball_vel;
        }
        s_update_time = wm.time();
    
        //
        //
        //
    
        const int ANGLE_DIVS = 12;
    
        const ServerParam & SP = ServerParam::i();
        const PlayerType & ptype = wm.self().playerType();
        const double collide_dist2 = std::pow( ptype.playerSize()
                                               + SP.ballSize(),
                                               2 );
        const double keep_dist = ptype.playerSize()
            + ptype.kickableMargin() * 0.5
            + ServerParam::i().ballSize();
    
        const Vector2D next_self_pos
            = wm.self().pos() + wm.self().vel();
        const Vector2D next2_self_pos
            = next_self_pos
            + wm.self().vel() * ptype.playerDecay();
    
        //
        // create keep target point
        //
    
        int best_angle = -1;
        Vector2D best_ball_vel = Vector2D::INVALIDATED;
        int best_opponent_step = 0;
        double best_ball_speed = 1000.0;
    
    
        for ( int a = 0; a < ANGLE_DIVS; ++a )
        {
            Vector2D keep_pos
                = next2_self_pos
                + Vector2D::from_polar( keep_dist,
                                        360.0/ANGLE_DIVS * a );
            if ( keep_pos.absX() > SP.pitchHalfLength() - 0.2
                 || keep_pos.absY() > SP.pitchHalfWidth() - 0.2 )
            {
                continue;
            }
    
            Vector2D ball_move = keep_pos - wm.ball().pos();
            double ball_speed = ball_move.r() / ( 1.0 + SP.ballDecay() );
    
            Vector2D max_vel
                = KickTable::calc_max_velocity( ball_move.th(),
                                                wm.self().kickRate(),
                                                wm.ball().vel() );
            if ( max_vel.r2() < std::pow( ball_speed, 2 ) )
            {
                continue;
            }
    
            Vector2D ball_next_next = keep_pos;
    
            Vector2D ball_vel = ball_move.setLengthVector( ball_speed );
            Vector2D ball_next = wm.ball().pos() + ball_vel;
    
            if ( next_self_pos.dist2( ball_next ) < collide_dist2 )
            {
                ball_next_next = ball_next;
                ball_next_next += ball_vel * ( SP.ballDecay() * -0.1 );
            }
    
    #ifdef DEBUG_PRINT
            dlog.addText( Logger::TEAM,
                          "(getKeepBallVel) %d: ball_move th=%.1f speed=%.2f max=%.2f",
                          a,
                          ball_move.th().degree(),
                          ball_speed,
                          max_vel.r() );
            dlog.addText( Logger::TEAM,
                          "__ ball_next=(%.2f %.2f) ball_next2=(%.2f %.2f)",
                          ball_next.x, ball_next.y,
                          ball_next_next.x, ball_next_next.y );
    #endif
    
            //
            // check opponent
            //
    
            int min_step = 1000;
            for ( PlayerPtrCont::const_iterator o = wm.opponentsFromSelf().begin();
                  o != wm.opponentsFromSelf().end();
                  ++o )
            {
                if ( (*o)->distFromSelf() > 10.0 )
                {
                    break;
                }
    
                int o_step = FieldAnalyzer::predict_player_reach_cycle( *o,
                                                                        ball_next_next,
                                                                        (*o)->playerTypePtr()->kickableArea(),
                                                                        0.0, // penalty distance
                                                                        1, // body count thr
                                                                        1, // default turn step
                                                                        0, // wait cycle
                                                                        true );
    
                if ( o_step < 0 )                                          //change
                {
                    break;
                }
    
                if ( o_step < min_step )
                {
                    min_step = o_step;
                }
            }
    #ifdef DEBUG_PRINT
            dlog.addText( Logger::TEAM,
                          __FILE__": (getKeepBallVel) %d: keepPos=(%.2f %.2f)"
                          " ballNext2=(%.2f %.2f) ballVel=(%.2f %.2f) speed=%.2f o_step=%d",
                          a,
                          keep_pos.x, keep_pos.y,
                          ball_next_next.x, ball_next_next.y,
                          ball_vel.x, ball_vel.y,
                          ball_speed,
                          min_step );
    #endif
            if ( min_step > best_opponent_step )
            {
                best_angle = a;
                best_ball_vel = ball_vel;
                best_opponent_step = min_step;
                best_ball_speed = ball_speed;
            }
            else if ( min_step == best_opponent_step )
            {
                if ( best_ball_speed > ball_speed )
                {
                    best_angle = a;
                    best_ball_vel = ball_vel;
                    best_opponent_step = min_step;
                    best_ball_speed = ball_speed;
                }
            }
        }
    
        s_best_ball_vel = best_ball_vel;
        return s_best_ball_vel;
    }
    
    /*-------------------------------------------------------------------*/
    /*!
    
     */
    /*
     问题:
     无
     
     理解:
     这个函数是Bhv_PassKickFindReceiver的doTurnBodyNeckToReceiver函数,主要通过往循环遍历,找到一个最合适的身体朝向,然后将身体转向reciever
     By ChenYanTing
     */
    bool
    Bhv_PassKickFindReceiver::doTurnBodyNeckToReceiver( PlayerAgent * agent,
                                                        const CooperativeAction & pass )
    {
        const ServerParam & SP = ServerParam::i();
        const WorldModel & wm = agent->world();
    
        const AbstractPlayerObject * receiver = wm.ourPlayer( pass.targetPlayerUnum() );
    
        const double next_view_half_width = agent->effector().queuedNextViewWidth().width() * 0.5;
        const double view_min = SP.minNeckAngle() - next_view_half_width + 10.0;
        const double view_max = SP.maxNeckAngle() + next_view_half_width - 10.0;
    
        //
        // create candidate body target points
        //
    
        std::vector< Vector2D > body_points;
        body_points.reserve( 16 );
    
        const Vector2D next_self_pos = wm.self().pos() + wm.self().vel();
        const Vector2D receiver_pos = receiver->pos() + receiver->vel();
        const AngleDeg receiver_angle = ( receiver_pos - next_self_pos ).th();
    
        const double max_x = SP.pitchHalfLength() - 7.0;
        const double min_x = ( max_x - 10.0 < next_self_pos.x
                               ? max_x - 10.0
                               : next_self_pos.x );
        const double max_y = std::max( SP.pitchHalfLength() - 5.0,
                                       receiver_pos.absY() );
        const double y_step = std::max( 3.0, max_y / 5.0 );
        const double y_sign = sign( receiver_pos.y );
    
        // on the static x line (x = max_x)
        for ( double y = 0.0; y < max_y + 0.001; y += y_step )
        {
            body_points.push_back( Vector2D( max_x, y * y_sign ) );
        }
    
        // on the static y line (y == receiver_pos.y)
        for ( double x_rate = 0.9; x_rate >= 0.0; x_rate -= 0.1 )
        {
            double x = std::min( max_x,
                                 max_x * x_rate + min_x * ( 1.0 - x_rate ) );
            body_points.push_back( Vector2D( x, receiver_pos.y ) );
        }
    
        //
        // evaluate candidate points
        //
    
        const double max_turn
            = wm.self().playerType().effectiveTurn( SP.maxMoment(),
                                                    wm.self().vel().r() );
        Vector2D best_point = Vector2D::INVALIDATED;
        double min_turn = 360.0;
    
        const std::vector< Vector2D >::const_iterator p_end = body_points.end();
        for ( std::vector< Vector2D >::const_iterator p = body_points.begin();
              p != p_end;
              ++p )
        {
            AngleDeg target_body_angle = ( *p - next_self_pos ).th();
            double turn_moment_abs = ( target_body_angle - wm.self().body() ).abs();
    
    #ifdef DEBUG_PRINT
            dlog.addText( Logger::TEAM,
                          "____ body_point=(%.1f %.1f) angle=%.1f moment=%.1f",
                          p->x, p->y,
                          target_body_angle.degree(),
                          turn_moment_abs );
    #endif
    
            double angle_diff = ( receiver_angle - target_body_angle ).abs();
            if ( view_min < angle_diff
                 && angle_diff < view_max )
            {
                if ( turn_moment_abs < max_turn )
                {
                    best_point = *p;
    #ifdef DEBUG_PRINT
                    dlog.addText( Logger::TEAM,
                                  "____ oooo can turn and look" );
    #endif
                    break;
                }
    
                if ( turn_moment_abs < min_turn )
                {
                    best_point = *p;
                    min_turn = turn_moment_abs;
    #ifdef DEBUG_PRINT
                    dlog.addText( Logger::TEAM,
                                  "____ ---- update candidate point min_turn=%.1f",
                                  min_turn );
    #endif
                }
            }
    #ifdef DEBUG_PRINT
            else
            {
                dlog.addText( Logger::TEAM,
                              "____ xxxx cannot look" );
            }
    #endif
        }
    
        if ( ! best_point.isValid() )
        {
            best_point = pass.targetPoint();
    #ifdef DEBUG_PRINT
            dlog.addText( Logger::TEAM,
                          __FILE__": (doTurnBodyNeckToPoint) could not find the target point." );
    #endif
        }
    
        //
        // perform the action
        //
        agent->debugClient().addMessage( "PassKickFind:Turn" );
        agent->debugClient().setTarget( receiver->unum() );
    
        dlog.addText( Logger::TEAM,
                      __FILE__": (doTurnBodyNeckToReceiver)"
                      " receiver=%d receivePos=(%.2f %.2f)"
                      " turnTo=(%.2f %.2f)",
                      pass.targetPlayerUnum(),
                      pass.targetPoint().x, pass.targetPoint().y,
                      best_point.x, best_point.y );
        agent->debugClient().addLine( next_self_pos, best_point );
    
        Body_TurnToPoint( best_point ).execute( agent );
        doSayPass( agent, pass );
        agent->setNeckAction( new Neck_TurnToReceiver( M_chain_graph ) );
    
        return true;
    }
    
    /*-------------------------------------------------------------------*/
    /*!
    
     */
    /*
     问题:
     无
     
     理解:
     这个函数是Bhv_PassKickFindReceiver的doSayPass函数,作用是告知reciever我要传球了
     By ChenYanTing
     */
    void
    Bhv_PassKickFindReceiver::doSayPass( PlayerAgent * agent,
                                         const CooperativeAction & pass )
    {
        const int receiver_unum = pass.targetPlayerUnum();
        const Vector2D & receive_pos = pass.targetPoint();
    
        if ( agent->config().useCommunication()
             && receiver_unum != Unum_Unknown
             && ! agent->effector().queuedNextBallKickable()
             )
        {
            const AbstractPlayerObject * receiver = agent->world().ourPlayer( receiver_unum );
            if ( ! receiver )
            {
                return;
            }
    
            dlog.addText( Logger::ACTION | Logger::TEAM,
                          __FILE__": (doSayPass) set pass communication." );
    
            Vector2D target_buf( 0.0, 0.0 );
    
            agent->debugClient().addMessage( "Say:pass" );
    
            Vector2D ball_vel( 0.0, 0.0 );
            if ( ! agent->effector().queuedNextBallKickable() )
            {
                ball_vel = agent->effector().queuedNextBallVel();
            }
    
            agent->addSayMessage( new PassMessage( receiver_unum,
                                                   receive_pos + target_buf,
                                                   agent->effector().queuedNextBallPos(),
                                                   ball_vel ) );
        }
    }
    
    

    bhv_attackers_move.cpp

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

    注释的格式为:
    /*
    问题:
    1.xxxx
    2.xxxx

    理解:
    这个函数是xxxxx
    By ChenYanTing
    */

    // -*-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_attackers_move.h"
    #include "bhv_basic_tackle.h"
    #include "bhv_basic_move.h"     //以后要逐渐取代掉
    #include <rcsc/action/body_intercept2009.h>
    #include <rcsc/action/basic_actions.h>
    #include <rcsc/action/bhv_scan_field.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/action/neck_turn_to_goalie_or_scan.h>
    #include <rcsc/action/neck_turn_to_low_conf_teammate.h>
    #include "strategy.h"
    #include <rcsc/player/debug_client.h>
    #include <rcsc/player/intercept_table.h>
    #include <rcsc/player/player_agent.h>
    #include <rcsc/player/soccer_intention.h>
    #include <rcsc/player/say_message_builder.h>
    
    #include <rcsc/common/audio_memory.h>
    #include <rcsc/common/logger.h>
    #include <rcsc/common/server_param.h>
    
    //#define DEBUG2014
    
    using namespace rcsc;
    
    /*-------------------------------------------------------------------*/
    
    /*-------------------------------------------------------------------*/
    /*!
    need to change:
        经常会几个人都去抢球
        跑位不太好
        中锋抢球范围不要太大
     */
    /*
     问题:
     1.问题太多,不懂那些数字的设定,以后实战的时候再看这个函数应该好很多
     
     
     
     理解:
     这个函数是Bhv_AttackersMove的AttackersMove函数,主要作用是根据一堆我看不懂的数字来设置一堆我想不清的阙值,来实现的AttackersMove哈哈哈,我不懂这个函数
     By ChenYanTing
     */
    bool
    Bhv_AttackersMove::AttackersMove(PlayerAgent * agent)
    {
      const WorldModel & wm = agent->world();
    
    //  dlog.addText(Logger::TEAM,
    //      __FILE__": AttackerOffensiveMove. target=(%.2f %.2f)", M_home_pos.x,
      //    M_home_pos.y);
    
      //------------------------------------------------------
      // tackle
      if (Bhv_BasicTackle(0.75, 90.0).execute(agent))
      {
        return true;;
      }
    
      //------------------------------------------------------
      int self_min = wm.interceptTable()->selfReachCycle();
      int mate_min = wm.interceptTable()->teammateReachCycle();
      int opp_min = wm.interceptTable()->opponentReachCycle();
     // dlog.addText(Logger::TEAM,
     //     __FILE__": execute. intercept cycle. self=%d, mate=%d, opp=%d", self_min,
     //     mate_min, opp_min);
      //------------------------------------------------------
      if (wm.self().stamina() > ServerParam::i().staminaMax() * 0.6
          && opp_min < 3
          && opp_min < mate_min - 2
          && (opp_min < self_min - 2 || opp_min == 0
              || (opp_min == 1 && self_min > 1))
          && wm.ball().pos().dist(M_home_pos) < 10.0
          && wm.ball().distFromSelf() < 15.0)
      {
        if (Body_ForestallBlock(agent))
        {
          agent->setNeckAction(new Neck_TurnToBall());
    #ifdef DEBUG2014
          std::cerr << wm.time().cycle() << __FILE__ << wm.self().unum() << ": Body_ForestallBlock.
    ";
    #endif
          return true;
        }
      }
    
      //------------------------------------------------------
        //如果自己距离球的可达半径比队友小,那么就去得到球
      if ((mate_min >= 2 && self_min <= 4)
          || (self_min <= mate_min + 1 && mate_min >= 4))
      {
     //   dlog.addText(Logger::TEAM, __FILE__": execute. get ball");
     //   agent->debugClient().addMessage("AttGetBall");
        Vector2D face_point(52.5, wm.self().pos().y);
    
        Body_Intercept2009(true, face_point).execute(agent);
        if (self_min == 4 && opp_min >= 2)
        {
          agent->setViewAction(new View_Wide());
        }
        else if (self_min == 3 && opp_min >= 2)
        {
          agent->setViewAction(new rcsc::View_Normal());
        }
        agent->setNeckAction(new Neck_TurnToBallOrScan());
    #ifdef DEBUG2014
        std::cerr << wm.time().cycle() << __FILE__ << wm.self().unum() << ": Body_Intercept.
    ";
    #endif // DEBUG2014
    
        return true;
      }
    
      //------------------------------------------------------
    
      const Vector2D mate_trap_pos = wm.ball().inertiaPoint(mate_min);
    
      Vector2D target_point = M_home_pos;
    
      const double max_x = std::max(wm.offsideLineX(), mate_trap_pos.x);
    //  dlog.addText(Logger::TEAM, __FILE__": max x = %.1f", max_x);
    
      if (wm.self().pos().x > max_x && wm.self().pos().x < 42.0
      //&& std::fabs( wm.self().pos().y - M_home_pos.y ) < 10.0
          )
      {
        target_point.y = wm.self().pos().y;
      }
    
      if (std::fabs(mate_trap_pos.y - M_home_pos.y) < 15.0
          || mate_trap_pos.x > max_x - 5.0)
      {
        if (target_point.x > max_x - 1.5)
        {
          target_point.x = std::min(M_home_pos.x, max_x - 1.5);
        }
      }
      else
      {
        if (target_point.x > max_x - 3.0)
        {
          target_point.x = std::min(M_home_pos.x, max_x - 3.0);
        }
      }
    
    #if 1
      // 2008-04-23 akiyama
      if (mate_min >= 3 && wm.self().pos().dist2(target_point) < 5.0 * 5.0)
      {
        double opp_dist = 1000.0;
        const PlayerObject * opp = wm.getOpponentNearestTo(target_point, 10,
            &opp_dist);
        if (opp && opp_dist < 4.0 && std::fabs(opp->pos().y - target_point.y) < 2.0)
        {
    //             target_point.y += ( target_point.y > opp->pos().y
    //                                 ? +3.0
    //                                 : -3.0 );
          target_point.y = (
              target_point.y > opp->pos().y ?
                  opp->pos().y + 2.0 : opp->pos().y - 2.0 );
    //      dlog.addText(Logger::TEAM,
     //         __FILE__": adjust target point to avvoid opponent. y=%.1f",
     //         target_point.y);
        }
      }
    #endif
    #if 1
      // 2008-04-28 akiyama
      if (mate_min < 3 && std::fabs(wm.self().pos().y - M_home_pos.y) < 3.0)
      {
        target_point.y = wm.self().pos().y * 0.9 + M_home_pos.y * 0.1;
        ;
     //   dlog.addText(Logger::TEAM,
      //      __FILE__": adjust target point to prepare receive. y=%.1f",
      //      target_point.y);
      }
    #endif
    
      bool breakaway = false;
      bool intentional = false;
    
      if (wm.existKickableTeammate() || mate_min <= 5 || mate_min <= opp_min + 1)
      {
        if (wm.self().pos().x > max_x)
        {
          if (std::fabs(mate_trap_pos.y - target_point.y) < 4.0)
          {
            double abs_y = wm.ball().pos().absY();
            bool outer = (wm.self().pos().absY() > abs_y );
            if (abs_y > 25.0)
              target_point.y = (outer ? 30.0 : 20.0 );
            else if (abs_y > 20.0)
              target_point.y = (outer ? 25.0 : 15.0 );
            else if (abs_y > 15.0)
              target_point.y = (outer ? 20.0 : 10.0 );
            else if (abs_y > 10.0)
              target_point.y = (outer ? 15.0 : 5.0 );
            else if (abs_y > 5.0)
              target_point.y = (outer ? 10.0 : 0.0 );
            else
              target_point.y = (outer ? 5.0 : -5.0 );
    
            if (wm.self().pos().y < 0.0)
            {
              target_point.y *= -1.0;
            }
    
       //     agent->debugClient().addMessage("AvoidOffside");
       //     dlog.addText(Logger::TEAM,
       //         __FILE__": avoid offside possibility. new_target=(%.1f %.1f)",
       //         target_point.x, target_point.y);
          }
        }
        else if (M_forward_player
        //&& wm.audioMemory().dribbleTime() != wm.time()
            && mate_min <= 2 && opp_min >= 3
            && mate_trap_pos.x > wm.offsideLineX() - 10.0
            && wm.self().stamina() > ServerParam::i().staminaMax() * 0.8
            && 5.0 < wm.self().pos().x && wm.self().pos().x < 27.0
            && wm.self().pos().x > max_x - 7.0 && wm.self().pos().x < max_x - 1.0
            && wm.self().pos().x < mate_trap_pos.x + 10.0
            && (std::fabs(mate_trap_pos.y - wm.self().pos().y) < 8.0
                || (mate_trap_pos - wm.self().pos()).th().abs() < 110.0
            //|| ( mate_trap_pos.x > wm.offsideLineX() - 8.0
            //     && std::fabs( mate_trap_pos.y - wm.self().pos().y ) < 20.0 )
            ) && wm.self().pos().dist(mate_trap_pos) < 20.0
            && std::fabs(M_home_pos.y - wm.self().pos().y) < 15.0)
        {
          double x_diff = max_x - wm.self().pos().x;
          int dash_step = wm.self().playerType().cyclesToReachDistance(x_diff);
          if (mate_min < dash_step - 1)
          {
            target_point.x = std::min(wm.self().pos().x + 20.0, 50.0);
            target_point.y = wm.self().pos().y * 0.8 + mate_trap_pos.y * 0.2;
            if (target_point.absY() > 8.0
                && target_point.absY() > M_home_pos.absY())
            {
              target_point.y = M_home_pos.y;
            }
            intentional = true;
          }
    
     //     dlog.addText(Logger::TEAM, __FILE__": try breakaway=(%.1f %.1f)",
      //        target_point.x, target_point.y);
          breakaway = true;
        }
      }
    
      const double dash_power = (
          breakaway ?
              ServerParam::i().maxPower() : getDashPower(agent, target_point) );
    
      if (dash_power < 1.0)
      {
        agent->debugClient().addMessage("AttackGoRecover");
        agent->debugClient().setTarget(target_point);
        AngleDeg face_angle = wm.ball().angleFromSelf() + 90.0;
        if (face_angle.abs() > 90.0)
          face_angle += 180.0;
        Body_TurnToAngle(face_angle).execute(agent);
        agent->setNeckAction(new Neck_TurnToBallOrScan());
        return true;
      }
    
      ///////////////////////////////////////////////////
    
      agent->debugClient().addMessage("AttackGo%.0f", dash_power);
    
      double dist_thr = std::fabs(wm.ball().pos().x - wm.self().pos().x) * 0.2
          + 0.25;
      //double dist_thr = wm.ball().pos().dist( target_point ) * 0.1 + 0.5;
      if (dist_thr < 1.0)
        dist_thr = 1.0;
      if (target_point.x > wm.self().pos().x - 0.5
          && wm.self().pos().x < wm.offsideLineX()
          && std::fabs(target_point.x - wm.self().pos().x) > 1.0)
      {
        dist_thr = std::min(1.0, wm.ball().pos().dist(target_point) * 0.1 + 0.5);
      }
    
     // agent->debugClient().setTarget(target_point);
    //  agent->debugClient().addCircle(target_point, dist_thr);
     // dlog.addText(Logger::TEAM,
    //      __FILE__": execute. go to (%.2f, %.2f) dash_power=%.2f", target_point.x,
    //      target_point.y, dash_power);
    
      if (Body_GoToPoint(target_point, dist_thr, dash_power, 100, // cycle
          false, // back
          true, // stamina save
          25.0 // angle threshold
          ).execute(agent))
      {
        if (intentional)
        {
     //     agent->debugClient().addMessage("BreakAway");
    
      //    agent->debugClient().addMessage("Sayh");
          agent->addSayMessage(new PassRequestMessage(target_point));
    
     //     dlog.addText(Logger::TEAM, __FILE__": intention breakaway");
          agent->setArmAction(new Arm_PointToPoint(target_point));
        }
        #ifdef DEBUG2014
        std::cerr << wm.time().cycle() << __FILE__ << wm.self().unum() << ": Body_GoToPoint.
    ";
        #endif // DEBUG2014
    
      }
      else
      {
        AngleDeg body_angle(0.0);
        Body_TurnToAngle(body_angle).execute(agent);
      }
    
      if (agent->world().ball().posCount() <= 1)
      {
        agent->setNeckAction(new Neck_ScanField());
      }
      else
      {
        agent->setNeckAction(new Neck_TurnToBallOrScan());
      }
    
      return true;
    }
    
    /*-------------------------------------------------------------------*/
    /*!
        ht: 20140905
        from roleoffensivehalfmove::doGoToCrossPoint( rcsc::PlayerAgent * agent, const rcsc::Vector2D & home_pos )
        need to change
    */
    /*
     问题:
     1.Circle2D类下的intersection是指的什么?
     
     理解:
     这个函数是Bhv_AttackersMove的doGoToCrossPoint函数,主要作用是根据一堆我看不懂的数字来设置一堆我想不清的阙值,来实现的AttackersMove哈哈哈,我不懂这个函数
     By ChenYanTing
     */
    void
    Bhv_AttackersMove::doGoToCrossPoint( rcsc::PlayerAgent * agent)
    {
        rcsc::dlog.addText( rcsc::Logger::ROLE,
                            __FILE__": doGoToCrossPoint" );
    
        const rcsc::WorldModel & wm = agent->world();
        //------------------------------------------------------
        // tackle
        if ( Bhv_BasicTackle( 0.75, 90.0 ).execute( agent ) )
        {
            return;
        }
    
        //----------------------------------------------
        // intercept check
        int self_min = wm.interceptTable()->selfReachCycle();
        int mate_min = wm.interceptTable()->teammateReachCycle();
        int opp_min = wm.interceptTable()->opponentReachCycle();
    
        if ( self_min < mate_min
             || ( mate_min != 0 // ! wm.existKickableTeammate()  //try mate_min > 1
                  && self_min <= 6
                  && wm.ball().pos().dist( M_home_pos ) < 10.0 )
             //|| wm.interceptTable()->isSelfFastestPlayer()
             )
        {
            rcsc::dlog.addText( rcsc::Logger::ROLE,
                                __FILE__": doGoToCross. get ball" );
            agent->debugClient().addMessage( "CrossGetBall" );
    
            rcsc::Body_Intercept2009().execute( agent );
    
            if ( self_min == 3 && opp_min >= 3 )
            {
                agent->setViewAction( new rcsc::View_Normal() );
            }
    
            if ( wm.self().pos().x > 30.0 )
            {
                if ( ! doCheckCrossPoint( agent ) )
                {
                    agent->setNeckAction( new rcsc::Neck_TurnToGoalieOrScan() );
                }
            }
            else
            {
                agent->setNeckAction( new rcsc::Neck_TurnToBallOrScan() );
            }
            return;
        }
    
        //----------------------------------------------
        // ball owner check
        if ( ! wm.interceptTable()->isOurTeamBallPossessor() )
        {
            const rcsc::PlayerObject * opp = wm.getOpponentNearestToBall( 3 );
    
            if ( opp
                 && opp->distFromSelf() < 2.0 ) //3.0?
            {
                rcsc::dlog.addText( rcsc::Logger::ROLE,
                                    __FILE__": doGoToCross. opp has ball" );
                agent->debugClient().addMessage( "CrossOppOwn(2)" );
                Bhv_BasicMove().execute( agent );
                return;
            }
        }
    
        //----------------------------------------------
        // set target
    
        rcsc::Vector2D target_point = M_home_pos;
        rcsc::Vector2D trap_pos = ( mate_min < 100
                                    ? wm.ball().inertiaPoint( mate_min )
                                    : wm.ball().pos() );
    
        if ( mate_min <= opp_min
             && mate_min < 3
             && target_point.x < 38.0
             && wm.self().pos().x < wm.offsideLineX() - 1.0
             //&& target_point.x < wm.self().pos().x
             //&& std::fabs( target_point.x - wm.self().pos().x ) < 20.0
             && std::fabs( target_point.y - wm.self().pos().y ) < 5.0
             && std::fabs( wm.self().pos().y - trap_pos.y ) < 13.0
             )
        {
            target_point.y = wm.self().pos().y * 0.9 + M_home_pos.y * 0.1;
            rcsc::dlog.addText( rcsc::Logger::ROLE,
                                __FILE__": doGoToCross. chance keep current." );
            agent->debugClient().addMessage( "CrossCurPos" );
        }
    
        // consider near opponent
        if ( target_point.x > 36.0 )
        {
            double opp_dist = 200.0;
            const rcsc::PlayerObject * opp = wm.getOpponentNearestTo( target_point,
                                                                      10,
                                                                      &opp_dist );
            if ( opp && opp_dist < 2.0 )
            {
                rcsc::Vector2D tmp_target = target_point;
                for ( int i = 0; i < 3; ++i )
                {
                    tmp_target.x -= 1.0;
    
                    double d = 0.0;
                    opp = wm.getOpponentNearestTo( tmp_target, 10, &d );
                    if ( ! opp )
                    {
                        opp_dist = 0.0;
                        target_point = tmp_target;
                        break;
                    }
                    if ( opp
                         && opp_dist < d )
                    {
                        opp_dist = d;
                        target_point = tmp_target;
                    }
                }
                rcsc::dlog.addText( rcsc::Logger::ROLE,
                                    __FILE__": doGoToCross. avoid(%.2f, %.2f)->(%.2f, %.2f)",
                                    M_home_pos.x, M_home_pos.y,
                                    target_point.x, target_point.y );
                agent->debugClient().addMessage( "Avoid" );
            }
        }
    
        if ( target_point.dist( trap_pos ) < 6.0 )
        {
            rcsc::Circle2D target_circle( trap_pos, 6.0 );
            rcsc::Line2D target_line( target_point, rcsc::AngleDeg( 90.0 ) );
            rcsc::Vector2D sol_pos1, sol_pos2;
            
            int n_sol = target_circle.intersection( target_line, &sol_pos1, &sol_pos2 );
    
            if ( n_sol == 1 ) target_point = sol_pos1;
            if ( n_sol == 2 )
            {
                target_point = ( wm.self().pos().dist2( sol_pos1 ) < wm.self().pos().dist2( sol_pos2 )
                                 ? sol_pos1
                                 : sol_pos2 );
    
            }
    
            rcsc::dlog.addText( rcsc::Logger::ROLE,
                                __FILE__": doGoToCross. adjust ot avoid the ball owner." );
            agent->debugClient().addMessage( "Adjust" );
        }
    
        //----------------------------------------------
        // set dash power
        // check X buffer & stamina
        static bool s_recover_mode = false;
        if ( wm.self().pos().x > 35.0
             && wm.self().stamina()
             < rcsc::ServerParam::i().recoverDecThrValue() + 500.0 )
        {
            s_recover_mode = true;
            rcsc::dlog.addText( rcsc::Logger::ROLE,
                                __FILE__": doGoToCross. recover on" );
        }
    
        if ( wm.self().stamina() > rcsc::ServerParam::i().staminaMax() * 0.5 )
        {
            s_recover_mode = false;
            rcsc::dlog.addText( rcsc::Logger::ROLE,
                                __FILE__": doGoToCross. recover off" );
        }
    
        double dash_power = rcsc::ServerParam::i().maxPower();
        if ( s_recover_mode )
        {
            const double my_inc
                = wm.self().playerType().staminaIncMax()
                * wm.self().recovery();
            dash_power = std::max( 1.0, my_inc - 25.0 );
            //dash_power = wm.self().playerType().staminaIncMax() * 0.6;
        }
        else if ( wm.ball().pos().x > wm.self().pos().x )
        {
            if ( wm.existKickableTeammate()
                 && wm.ball().distFromSelf() < 10.0
                 && std::fabs( wm.self().pos().x - wm.ball().pos().x ) < 5.0
                 && wm.self().pos().x > 30.0
                 && wm.ball().pos().x > 35.0 )
            {
                dash_power *= 0.5;
            }
        }
        else if ( wm.self().pos().dist( target_point ) < 3.0 )
        {
            const double my_inc
                = wm.self().playerType().staminaIncMax()
                * wm.self().recovery();
            dash_power = std::min( rcsc::ServerParam::i().maxPower(),
                                   my_inc + 10.0 );
            //dash_power = rcsc::ServerParam::i().maxPower() * 0.8;
        }
        else if ( mate_min <= 1
                  && wm.ball().pos().x > 33.0
                  && wm.ball().pos().absY() < 7.0
                  && wm.ball().pos().x < wm.self().pos().x
                  && wm.self().pos().x < wm.offsideLineX()
                  && wm.self().pos().absY() < 9.0
                  && std::fabs( wm.ball().pos().y - wm.self().pos().y ) < 3.5
                  && std::fabs( target_point.y - wm.self().pos().y ) > 5.0 )
        {
            dash_power = wm.self().playerType()
                .getDashPowerToKeepSpeed( 0.3, wm.self().effort() );
            dash_power = std::min( rcsc::ServerParam::i().maxPower() * 0.75,
                                   dash_power );
            rcsc::dlog.addText( rcsc::Logger::ROLE,
                                __FILE__": doGoToCross. slow for cross. power=%.1f",
                                dash_power );
        }
    
    #if 1
    
    
        bool intentional = true;    //false;
    
        const Vector2D mate_trap_pos = wm.ball().inertiaPoint(mate_min);
    
        const double max_x = std::max(wm.offsideLineX(), mate_trap_pos.x);
    
        if (wm.existKickableTeammate() || mate_min <= 5 || mate_min <= opp_min + 1)
        {
        }
        else if (M_forward_player
        //&& wm.audioMemory().dribbleTime() != wm.time()
            && mate_min <= 2 && opp_min >= 3
            && mate_trap_pos.x > wm.offsideLineX() - 10.0
            && wm.self().stamina() > ServerParam::i().staminaMax() * 0.8
            && 5.0 < wm.self().pos().x && wm.self().pos().x < 27.0
            && wm.self().pos().x > max_x - 7.0 && wm.self().pos().x < max_x - 1.0
            && wm.self().pos().x < mate_trap_pos.x + 10.0
            && (std::fabs(mate_trap_pos.y - wm.self().pos().y) < 8.0
                || (mate_trap_pos - wm.self().pos()).th().abs() < 110.0
            //|| ( mate_trap_pos.x > wm.offsideLineX() - 8.0
            //     && std::fabs( mate_trap_pos.y - wm.self().pos().y ) < 20.0 )
            ) && wm.self().pos().dist(mate_trap_pos) < 20.0
            && std::fabs(M_home_pos.y - wm.self().pos().y) < 15.0)
        {
          double x_diff = max_x - wm.self().pos().x;
          int dash_step = wm.self().playerType().cyclesToReachDistance(x_diff);
          if (mate_min < dash_step - 1)
          {
            target_point.x = std::min(wm.self().pos().x + 20.0, 50.0);
            target_point.y = wm.self().pos().y * 0.8 + mate_trap_pos.y * 0.2;
            if (target_point.absY() > 8.0
                && target_point.absY() > M_home_pos.absY())
            {
    //          target_point.y = M_home_pos.y;
            }
            intentional = true;
          }
        }
    #endif // 1
    
        //----------------------------------------------
        // positioning to make the cross course!!
    
        double dist_thr = wm.ball().distFromSelf() * 0.1;
        if ( dist_thr < 0.5 ) dist_thr = 0.5;
    
        agent->debugClient().addMessage( "GoToCross%.0f", dash_power );
        agent->debugClient().setTarget( target_point );
        agent->debugClient().addCircle( target_point, dist_thr );
    
        rcsc::dlog.addText( rcsc::Logger::ROLE,
                            __FILE__": doGoToCross. to (%.2f, %.2f)",
                            target_point.x, target_point.y );
    
        if ( wm.self().pos().x > target_point.x + dist_thr
             && std::fabs( wm.self().pos().x - target_point.x ) < 3.0
             && wm.self().body().abs() < 10.0 )
        {
            agent->debugClient().addMessage( "Back" );
            double back_dash_power
                = wm.self().getSafetyDashPower( -dash_power );
            rcsc::dlog.addText( rcsc::Logger::ROLE,
                                __FILE__": doShootAreaMove. Back Move" );
            agent->doDash( back_dash_power );
        }
        else
        {
            if ( ! rcsc::Body_GoToPoint( target_point, dist_thr, dash_power,
                                         5, // cycle
                                         false, // no back dash
                                         true, // save recovery
                                         30.0 // dir thr
                                         ).execute( agent ) )
            {
                rcsc::Body_TurnToAngle( 0.0 ).execute( agent );
            }
            else
            {
                if (intentional)
                {
             //     agent->debugClient().addMessage("BreakAway");
    
              //    agent->debugClient().addMessage("Sayh");
                  agent->addSayMessage(new PassRequestMessage(target_point));
    
             //     dlog.addText(Logger::TEAM, __FILE__": intention breakaway");
                  agent->setArmAction(new Arm_PointToPoint(target_point));
                }
            }
        }
    
    
    
        if ( wm.self().pos().x > 30.0 )
        {
            agent->setNeckAction( new rcsc::Neck_TurnToGoalieOrScan() );
        }
        else
        {
            agent->setNeckAction( new rcsc::Neck_TurnToLowConfTeammate() );
        }
    }
    
    /*-------------------------------------------------------------------*/
    /*!
        ht: 20140905
        from roleoffensivehalfmove::doCheckCrossPoint( rcsc::PlayerAgent * agent )
        for doGoToCrossPoint()
    */
    /*
     问题:
     1.726行的opposite_pole是指的什么?
     
     理解:
     这个函数是Bhv_AttackersMove的doCheckCrossPoint函数,主要作用是根据一些变量来返回true或者false,但是具体这些变量是怎么得到的,我不是很清楚
     By ChenYanTing
     */
    bool
    Bhv_AttackersMove::doCheckCrossPoint( rcsc::PlayerAgent * agent )
    {
        const rcsc::WorldModel & wm = agent->world();
    
        if ( wm.self().pos().x < 35.0 )
        {
            return false;
        }
    
        const rcsc::PlayerObject * opp_goalie = wm.getOpponentGoalie();
        if ( opp_goalie && opp_goalie->posCount() > 2 )
        {
            rcsc::dlog.addText( rcsc::Logger::ROLE,
                                __FILE__": doCheckCrossTarget  goalie should be checked" );
            return false;
        }
    
        rcsc::Vector2D opposite_pole( 46.0, 7.0 );
        if ( wm.self().pos().y > 0.0 ) opposite_pole.y *= -1.0;
    
        rcsc::AngleDeg opposite_pole_angle = ( opposite_pole - wm.self().pos() ).th();
    
    
        if ( wm.dirCount( opposite_pole_angle ) <= 1 )
        {
            rcsc::dlog.addText( rcsc::Logger::ROLE,
                                __FILE__": doCheckCrossTarget enough accuracy to angle %.1f",
                                opposite_pole_angle.degree() );
            return false;
        }
    
        rcsc::AngleDeg angle_diff
            = agent->effector().queuedNextAngleFromBody( opposite_pole );
        if ( angle_diff.abs() > 100.0 )
        {
            rcsc::dlog.addText( rcsc::Logger::ROLE,
                                __FILE__": doCheckCrossPoint. want to face opposite pole,"
                                " but over view range. angle_diff=%.1f",
                                angle_diff.degree() );
            return false;
        }
    
    
        agent->setNeckAction( new rcsc::Neck_TurnToPoint( opposite_pole ) );
        agent->debugClient().addMessage( "NeckToOpposite" );
        rcsc::dlog.addText( rcsc::Logger::ROLE,
                            __FILE__": doCheckCrossPoint Neck to oppsite pole" );
        return true;
    }
    
    /*-------------------------------------------------------------------*/
    /*!
    
     */
    /*
     问题:
     1.wm.offsideLineX()指的什么?
     
     理解:
     这个函数是Bhv_AttackersMove的getDashPower函数,主要作用是根据敌人的位置、自己的位置、球的位置等等因素来判断自己的耐力值应该选择消耗多少
     By ChenYanTing
     */
    double
    Bhv_AttackersMove::getDashPower(const PlayerAgent * agent,
        const Vector2D & target_point)
    {
      const WorldModel & wm = agent->world();
      int mate_min = wm.interceptTable()->teammateReachCycle();
      int opp_min = wm.interceptTable()->opponentReachCycle();
    
      if (target_point.x > wm.self().pos().x
          && wm.self().stamina() > ServerParam::i().staminaMax() * 0.7
          && mate_min <= 8)
      {
        Vector2D receive_pos = wm.ball().inertiaPoint(mate_min);
        if (std::fabs(receive_pos.y - target_point.y) < 15.0)
        {
     //     dlog.addText(Logger::TEAM, __FILE__": getDashPower. chance. fast move");
          return ServerParam::i().maxPower();
        }
      }
    
      if (wm.self().pos().x > wm.offsideLineX()
          && (wm.existKickableTeammate() || mate_min <= opp_min + 2))
      {
        Vector2D receive_pos = wm.ball().inertiaPoint(mate_min);
        if (target_point.x < receive_pos.x + 30.0
            && wm.self().pos().dist(receive_pos) < 30.0
            && wm.self().pos().dist(target_point) < 20.0)
        {
    //      dlog.addText(Logger::TEAM, __FILE__": getDashPower. offside max power");
    
          return ServerParam::i().maxPower();
        }
      }
    
      //------------------------------------------------------
      // decide dash power
      static bool s_recover_mode = false;
      if (wm.self().stamina() < ServerParam::i().staminaMax() * 0.4)
      {
     //   dlog.addText(Logger::TEAM,
     //       __FILE__": getDashPower. change to recover mode.");
        s_recover_mode = true;
      }
      else if (wm.self().stamina() > ServerParam::i().staminaMax() * 0.7)
      {
    //    dlog.addText(Logger::TEAM,
    //        __FILE__": getDashPower. came back from recover mode");
        s_recover_mode = false;
      }
    
      const double my_inc = wm.self().playerType().staminaIncMax()
          * wm.self().recovery();
    
      // dash power
      if (s_recover_mode)
      {
        // Magic Number.
        // recommended one cycle's stamina recover value
     //   dlog.addText(Logger::TEAM, __FILE__": getDashPower. recover mode");
        return std::max(0.0, my_inc - 30.0);
      }
    
      if (!wm.opponentsFromSelf().empty()
          && wm.opponentsFromSelf().front()->distFromSelf() < 1.0)
      {
        // opponent is very close
        // full power
        dlog.addText(Logger::TEAM,
            __FILE__": getDashPower. exist near opponent. full power");
        return ServerParam::i().maxPower();
      }
    
      if (wm.ball().pos().x < wm.self().pos().x
          && wm.self().pos().x < wm.offsideLineX())
      {
        // ball is back
        // not offside
     //   dlog.addText(Logger::TEAM,
    //        __FILE__": getDashPower. ball is back and not offside.");
        if (wm.self().stamina() < ServerParam::i().staminaMax() * 0.8)
        {
          return std::min(std::max(5.0, my_inc - 30.0), ServerParam::i().maxPower());
        }
        else
        {
          return std::min(my_inc * 1.1, ServerParam::i().maxPower());
        }
      }
    
      if (wm.ball().pos().x > wm.self().pos().x + 3.0)
      {
        // ball is front
        if (opp_min <= mate_min - 3)
        {
          if (wm.self().stamina() < ServerParam::i().staminaMax() * 0.6)
          {
      //      dlog.addText(Logger::TEAM,
      //          __FILE__": getDashPower. ball is front. recover");
            return std::min(std::max(0.1, my_inc - 30.0),
                ServerParam::i().maxPower());
          }
          else if (wm.self().stamina() < ServerParam::i().staminaMax() * 0.8)
          {
     //       dlog.addText(Logger::TEAM,
     //           __FILE__": getDashPower. ball is front. keep");
            return std::min(my_inc, ServerParam::i().maxPower());
          }
          else
          {
     //       dlog.addText(Logger::TEAM,
    //            __FILE__": getDashPower. ball is front. max");
            return ServerParam::i().maxPower();
          }
        }
        else
        {
     //     dlog.addText(Logger::TEAM,
     //         __FILE__": getDashPower. ball is front full powerr");
          return ServerParam::i().maxPower();
        }
      }
    
     // dlog.addText(Logger::TEAM, __FILE__": getDashPower. normal mode.");
      if (target_point.x > wm.self().pos().x + 2.0
          && wm.self().stamina() > ServerParam::i().staminaMax() * 0.6)
      {
        return ServerParam::i().maxPower();
      }
      else if (wm.self().stamina() < ServerParam::i().staminaMax() * 0.8)
      {
        return std::min(my_inc * 0.9, ServerParam::i().maxPower());
      }
      else
      {
        return std::min(my_inc * 1.5, ServerParam::i().maxPower());
      }
    }
    
    /*
     问题:
     1.962到968行,身体朝向为什么要这样设定?
     
     理解:
     这个函数是Bhv_AttackersMove的Body_ForestallBlock函数,主要作用是负责球员在各个快之间的移动
     By ChenYanTing
     */
    bool
    Bhv_AttackersMove::Body_ForestallBlock(PlayerAgent * agent)
    {
      int S_count_no_move = 0 ;
      const rcsc::WorldModel & wm = agent->world();
      rcsc:Vector2D home_pos = Strategy::i().getPosition(wm.self().unum());
      rcsc::Vector2D block_point = home_pos;
    
      if (!block_point.isValid())
      {
        return false;
      }
    
      double dist_thr = 1.0;
    
     // agent->debugClient().addMessage("forestall");
     // agent->debugClient().setTarget(block_point);
     // agent->debugClient().addCircle(block_point, dist_thr);
    
      double dash_power = wm.self().getSafetyDashPower(
          rcsc::ServerParam::i().maxPower());
    
      if (rcsc::Body_GoToPoint(block_point, dist_thr, dash_power, 5, // cycle
          false, // no back dash
          true, // save recovery
          40.0 // dir_thr
          ).execute(agent))
      {
        S_count_no_move = 0;
        return true;
      }
    
    #if 1
      ++S_count_no_move;
    
      if (S_count_no_move >= 10)
      {
     //   rcsc::dlog.addText(rcsc::Logger::TEAM,
     //       __FILE__": forestall. long no move. attack to the ball");
     //   agent->debugClient().addMessage("ForestallAttack");
        Body_Intercept2009(true).execute(agent);
        return true;
      }
    #endif
    
      rcsc::AngleDeg body_angle = wm.ball().angleFromSelf() + 90.0;
      if (body_angle.abs() < 90.0)
      {
        body_angle += 180.0;
      }
    
      rcsc::Body_TurnToAngle(body_angle).execute(agent);
    
      return true;
    }
    
    

    学习心得与体会

    这次主要看的都是一些比较基础的cpp代码,但是发现这些基础代码并不是很好看懂,因为有很多涉及到阙值的设定,和一些数学的问题。所以我觉得这一块的内容其实可以先看个大概,具体原理可以等到跑代码的时候,根据场上球员的实际情况来理解代码!

  • 相关阅读:
    Element-ui 中设置input中字符长度并提示
    vue.js如何动态的获取locoalStorage中事先存好的值
    vue中的v-if和v-show的区别详解
    vue.js中ref和$refs的使用及示例讲解
    vue实现输入框的模糊查询的示例代码(节流函数的应用场景)
    flex 如何设置换行flex-wrap
    JS排序之localeCompare( )方法的使用说明及相关案例
    JS—如何按日期对象数组进行排序,然后按时间顺序进行降序排序?
    遇到了编译报错:no method declared with objective-c selector error
    在IT界取得成功应该知道的10件事
  • 原文地址:https://www.cnblogs.com/782687539-nanfu/p/12707601.html
Copyright © 2020-2023  润新知