// -*-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>usingnamespace rcsc;
// #define DEBUG_PRINT/*-------------------------------------------------------------------*//*!
*//*
问题:
无,因为我看源代码是从后面忘前面看的,所以想提出来的问题都被姚文进和张智洋提出来了,就给子昂哥省事了哈哈!
理解:
这个函数是Bhv_CustomBeforeKickOff的执行函数,只要的作用是在踢球之前规定一些必须判断的规则,以后需要踢球之前必须通过该函数进行判断,如果符合这个这些规则才可以踢球。
By ChenYanTing
*/boolBhv_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( newNeck_TurnToRelative( 0.0 ) );
returnfalse;
}
if ( wm.gameMode().type() == GameMode::AfterGoal_
&& wm.self().vel().r() > 0.05 )
{
agent->doTurn( 180.0 );
agent->setNeckAction( newNeck_TurnToRelative( 0.0 ) );
returntrue;
}
// check center circle
SideID kickoff_side = NEUTRAL;
if ( wm.gameMode().type() == GameMode::AfterGoal_ )
{
// after our goalif ( wm.gameMode().side() != wm.ourSide() )
{
kickoff_side = wm.ourSide();
}
else
{
kickoff_side = ( wm.ourSide() == LEFT
? RIGHT
: LEFT );
}
}
else// before_kick_off
{
// check half_time countif ( 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 );
#endifint 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
}
elseif ( 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 );
#endifif ( 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
}
// movedouble tmpr = ( M_move_point - wm.self().pos() ).r();
if ( tmpr > 1.0 )
{
agent->doMove( M_move_point.x, M_move_point.y );
agent->setNeckAction( newNeck_TurnToRelative( 0.0 ) );
returntrue;
}
// field scanreturnBhv_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
*/boolBhv_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");
returnfalse;
}
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
}
elseif (agent->world().self().body().abs() > 170.0)
{
power_or_dir = 180.0;
}
elseif (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
}
elseif (agent->world().self().body().abs() > 170.0)
{
power_or_dir = -rcsc::ServerParam::i().maxBackTacklePower();
if (power_or_dir >= -1.0)
{
returnfalse;
}
}
elseif (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)
{
returnfalse;
}
}
if (std::fabs(power_or_dir) < 1.0)
{
returnfalse;
}
}
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());
returntrue;
}
else
{
// within goal widthdouble 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());
returntrue;
}
}
else
{
double tackle_power = (
power_sign >= 0.0 ?
rcsc::ServerParam::i().maxTacklePower() :
-rcsc::ServerParam::i().maxBackTacklePower() );
if (std::fabs(tackle_power) < 1.0)
{
returnfalse;
}
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());
returntrue;
}
}
}
returnfalse;
}
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>usingnamespace 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
*/boolBhv_GoToStaticBall::execute( PlayerAgent * agent ){
constdouble 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 reachreturnfalse;
}
// 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 pointif ( 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 ballelse
{
// body dir is not rightif ( ( wm.ball().angleFromSelf() - wm.self().body() ).abs() > 1.5 )
{
dlog.addText( Logger::TEAM,
__FILE__": turn to ball" );
Body_TurnToBall().execute( agent );
}
// dash to ballelse
{
dlog.addText( Logger::TEAM,
__FILE__": dash to ball" );
agent->doDash( dash_power );
}
}
agent->setNeckAction( newNeck_ScanField() );
returntrue;
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>usingnamespace rcsc;
/*-------------------------------------------------------------------*//*!
*//*
问题:
无
理解:
这个函数是Bhv_GoalieBasicMove的执行函数,主要是调用子函数,实现一系列移动需要进行的动作。
By ChenYanTing
*/boolBhv_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 );
//////////////////////////////////////////////////////////////////// tackleif ( Bhv_BasicTackle( 0.8, 90.0 ).execute( agent ) )
{
dlog.addText( Logger::TEAM,
__FILE__": tackle" );
returntrue;
}
///////////////////////////////////////////////////////////////----------------------------------------------------------if ( doPrepareDeepCross( agent, move_point ) )
{
// face to opponent side to wait the opponent last cross passreturntrue;
}
//----------------------------------------------------------// check distance to the move target point// if already there, try to stopif ( doStopAtMovePoint( agent, move_point ) )
{
// execute stop actionreturntrue;
}
//----------------------------------------------------------// check whether ball is in very dangerous stateif ( doMoveForDangerousState( agent, move_point ) )
{
// execute emergency actionreturntrue;
}
//----------------------------------------------------------// check & correct X differenceif ( doCorrectX( agent, move_point ) )
{
// execute x-pos adjustment actionreturntrue;
}
//----------------------------------------------------------if ( doCorrectBodyDir( agent, move_point, true ) ) // consider opp
{
// exeucte turnreturntrue;
}
//----------------------------------------------------------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.returntrue;
}
//----------------------------------------------------------// change my body angle to desired angleif ( doCorrectBodyDir( agent, move_point, false ) ) // not consider opp
{
returntrue;
}
dlog.addText( Logger::TEAM,
__FILE__": only look ball" );
agent->debugClient().addMessage( "OnlyTurnNeck" );
agent->doTurn( 0.0 );
agent->setNeckAction( newNeck_GoalieTurnNeck() );
returntrue;
}
/*-------------------------------------------------------------------*//*!
*//*
问题:
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_xconstdouble base_move_x = -49.8;
constdouble 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 dangerousif ( 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" );
returnVector2D( danger_move_x, ServerParam::i().goalHalfWidth() + 0.001 );
}
}
elseif ( 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" );
returnVector2D( danger_move_x, - ServerParam::i().goalHalfWidth() - 0.001 );
}
}
//---------------------------------------------------------//// ball is close to goal lineif ( 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;
}
//---------------------------------------------------------//
{
constdouble x_back = 7.0; // tune this!!int ball_pred_cycle = 5; // tune this!!constdouble 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;
}
returnVector2D( base_move_x, move_y );
}
}
/*-------------------------------------------------------------------*//*!
*//*
问题:
1.my_inc = mytype.staminaIncMax() * wm.self().recovery(),这个计算出来的是什么?
理解:
这个函数是Bhv_GoalieBasicMove的getBasicDashPower函数,主要是根据球的x坐标,进行危险度划分,然后再结合自身的体力值等因素来得到最合适的DashPower并且返回。
By ChenYanTing
*/doubleBhv_GoalieBasicMove::getBasicDashPower( PlayerAgent * agent,
const Vector2D & move_point ){
const WorldModel & wm = agent->world();
const PlayerType & mytype = wm.self().playerType();
constdouble 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;
}
elseif ( 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
*/boolBhv_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" );
returnfalse;
}
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" );
returnfalse;
}
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 pointdouble 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 );
returntrue;
}
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( newNeck_GoalieTurnNeck() );
returntrue;
}
/*-------------------------------------------------------------------*//*!
*//*
问题:
无
理解:
这个函数是Bhv_GoalieBasicMove的doStopAtMovePoint函数,主要作用是结合自己的位置、速度还有目标点的位置,来判断自己是否应该终止跑向目标点的行动。
By ChenYanTing
*/boolBhv_GoalieBasicMove::doStopAtMovePoint( PlayerAgent * agent,
const Vector2D & move_point ){
//----------------------------------------------------------// already exist at target point// but inertia movement is big// stop dashconst 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 areaif ( 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 areaif ( my_final.dist( move_point ) < dist_thr )
{
agent->debugClient().addMessage( "InertiaStay" );
dlog.addText( Logger::TEAM,
__FILE__": doStopAtMovePoint. inertia stay" );
returnfalse;
}
// 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( newNeck_GoalieTurnNeck() );
returntrue;
}
returnfalse;
}
/*-------------------------------------------------------------------*//*!
*//*
问题:
无
理解:
这个函数是Bhv_GoalieBasicMove的doMoveForDangerousState函数,主要作用是结合自身的位置、球的位置、敌人距离球的距离等因素,来判断自己是否应该前往危险区域。
By ChenYanTing
*/boolBhv_GoalieBasicMove::doMoveForDangerousState( PlayerAgent * agent,
const Vector2D & move_point ){
const WorldModel& wm = agent->world();
constdouble 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 ballif ( ! 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 ) )
{
returntrue;
}
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() );
returntrue;
}
}
returnfalse;
}
/*-------------------------------------------------------------------*//*!
*//*
问题:
无
理解:
这个函数是Bhv_GoalieBasicMove的doCorrectX函数,主要作用是j考虑球与地方球员的危险程度,来校准当前守门员的x值。
By ChenYanTing
*/boolBhv_GoalieBasicMove::doCorrectX( PlayerAgent * agent,
const Vector2D & move_point ){
const WorldModel & wm = agent->world();
constdouble 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" );
returnfalse;
}
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( newNeck_TurnToBall() );
returntrue;
}
doGoToPointLookBall( agent,
move_point,
wm.ball().angleFromSelf(),
x_buf,
dash_power );
returntrue;
}
returnfalse;
}
/*-------------------------------------------------------------------*//*!
*//*
问题:
无
理解:
这个函数是Bhv_GoalieBasicMove的doCorrectX函数,主要作用是根据自身与球的角度差、地方球员的威胁程度等因素来调节守门员的身体朝向。
By ChenYanTing
*/boolBhv_GoalieBasicMove::doCorrectBodyDir( PlayerAgent * agent,
const Vector2D & move_point,
constbool consider_opp ){
// adjust only body directionconst 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 );
constdouble angle_diff = ( wm.self().body() - target_angle ).abs();
dlog.addText( Logger::TEAM,
__FILE__": doCorrectBodyDir" );
if ( angle_diff < 5.0 )
{
returnfalse;
}
#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" );
returnfalse;
}
}
#elseif ( 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" );
returnfalse;
}
#endifdouble 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( newNeck_GoalieTurnNeck() );
returntrue;
}
returnfalse;
}
/*-------------------------------------------------------------------*//*!
*//*
问题:
无
理解:
这个函数是Bhv_GoalieBasicMove的doGoToMovePoint函数,主要作用是根据身体的朝向、目标点与自身的位置等因素来执行移动到目标点的动作。
By ChenYanTing
*/boolBhv_GoalieBasicMove::doGoToMovePoint( PlayerAgent * agent,
const Vector2D & move_point ){
// move to target point// check Y coordinate differenceconst WorldModel & wm = agent->world();
double dist_thr = wm.ball().distFromSelf() * 0.08;
if ( dist_thr < 0.5 ) dist_thr = 0.5;
constdouble 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 );
returnfalse;
}
//----------------------------------------------------------//// dash to body directiondouble dash_power = getBasicDashPower( agent, move_point );
// body direction is OKif ( std::fabs( wm.self().body().abs() - 90.0 ) < 7.0 )
{
// calc dash power only to reach the target pointdouble 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( newNeck_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 );
}
returntrue;
}
/*-------------------------------------------------------------------*//*!
*//*
问题:
无
理解:
这个函数是Bhv_GoalieBasicMove的doGoToPointLookBall函数,只是在doGoToPoint函数的基础上加了一个Look的动作
By ChenYanTing
*/voidBhv_GoalieBasicMove::doGoToPointLookBall( PlayerAgent * agent,
const Vector2D & target_point,
const AngleDeg & body_angle,
constdouble & dist_thr,
constdouble & dash_power,
constdouble & 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( newNeck_TurnToBall() );
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?