/*! */ int TackleGenerator::predictOpponentsReachStep( const WorldModel & wm, const Vector2D & first_ball_pos, const Vector2D & first_ball_vel, const AngleDeg & ball_move_angle ) { int first_min_step = 50; #if 1 const ServerParam & SP = ServerParam::i(); const Vector2D ball_end_point = inertia_final_point( first_ball_pos, first_ball_vel, SP.ballDecay() ); if ( ball_end_point.absX() > SP.pitchHalfLength() || ball_end_point.absY() > SP.pitchHalfWidth() ) { Rect2D pitch = Rect2D::from_center( 0.0, 0.0, SP.pitchLength(), SP.pitchWidth() ); Ray2D ball_ray( first_ball_pos, ball_move_angle ); Vector2D sol1, sol2; int n_sol = pitch.intersection( ball_ray, &sol1, &sol2 ); if ( n_sol == 1 ) { first_min_step = SP.ballMoveStep( first_ball_vel.r(), first_ball_pos.dist( sol1 ) ); #ifdef DEBUG_PRINT dlog.addText( Logger::CLEAR, "(predictOpponent) ball will be out. step=%d reach_point=(%.2f %.2f)", first_min_step, sol1.x, sol1.y ); #endif } } #endif int min_step = first_min_step; for ( AbstractPlayerCont::const_iterator o = wm.theirPlayers().begin(), end = wm.theirPlayers().end(); o != end; ++o ) { int step = predictOpponentReachStep( *o, first_ball_pos, first_ball_vel, ball_move_angle, min_step ); if ( step < min_step ) { min_step = step; } } return ( min_step == first_min_step ? 1000 : min_step ); }
/*! */ void InterceptTable::createBallCache() { const ServerParam & SP = ServerParam::i(); const double pitch_x_max = ( SP.keepawayMode() ? SP.keepawayLength() * 0.5 : SP.pitchHalfLength() + 5.0 ); const double pitch_y_max = ( SP.keepawayMode() ? SP.keepawayWidth() * 0.5 : SP.pitchHalfWidth() + 5.0 ); const double bdecay = SP.ballDecay(); Vector2D bpos = M_world.ball().pos(); Vector2D bvel = M_world.ball().vel(); M_ball_pos_cache.push_back( bpos ); if ( M_world.self().isKickable() ) { return; } for ( std::size_t i = 1; i <= MAX_CYCLE; ++i ) { bpos += bvel; bvel *= bdecay; M_ball_pos_cache.push_back( bpos ); if ( i >= 5 && bvel.r2() < 0.01*0.01 ) { // ball stopped break; } if ( bpos.absX() > pitch_x_max || bpos.absY() > pitch_y_max ) { // out of pitch break; } } if ( M_ball_pos_cache.size() == 1 ) { M_ball_pos_cache.push_back( bpos ); } }
/*! */ void ActGen_SimpleDribble::generate( std::vector< ActionStatePair > * result, const PredictState & state, const WorldModel & current_wm, const std::vector< ActionStatePair > & path ) const { static thread_local GameTime s_last_call_time( 0, 0 ); static thread_local int s_action_count = 0; if ( current_wm.time() != s_last_call_time ) { s_action_count = 0; s_last_call_time = current_wm.time(); } if ( path.empty() ) { return; } const AbstractPlayerObject * holder = state.ballHolder(); if ( ! holder ) { return; } const int ANGLE_DIVS = 8; const double ANGLE_STEP = 360.0 / ANGLE_DIVS; const int DIST_DIVS = 3; const double DIST_STEP = 1.75; const ServerParam & SP = ServerParam::i(); const double max_x= SP.pitchHalfLength() - 1.0; const double max_y= SP.pitchHalfWidth() - 1.0; const int bonus_step = 2; const PlayerType * ptype = holder->playerTypePtr(); int generated_count = 0; for ( int a = 0; a < ANGLE_DIVS; ++a ) { const AngleDeg target_angle = ANGLE_STEP * a; if ( holder->pos().x < 16.0 && target_angle.abs() > 100.0 ) { #ifdef DEBUG_PRINT dlog.addText( Logger::ACTION_CHAIN, __FILE__": %d: (%.2f %.2f) danger angle(1) %.1f", generated_count, target_angle.degree() ); #endif continue; } if ( holder->pos().x < -36.0 && holder->pos().absY() < 20.0 && target_angle.abs() > 45.0 ) { #ifdef DEBUG_PRINT dlog.addText( Logger::ACTION_CHAIN, __FILE__": %d: (%.2f %.2f) danger angle(2) %.1f", generated_count, target_angle.degree() ); #endif continue; } const Vector2D unit_vec = Vector2D::from_polar( 1.0, target_angle ); for ( int d = 1; d <= DIST_DIVS; ++d ) { const double holder_move_dist = DIST_STEP * d; const Vector2D target_point = holder->pos() + unit_vec.setLengthVector( holder_move_dist ); if ( target_point.absX() > max_x || target_point.absY() > max_y ) { #ifdef DEBUG_PRINT dlog.addText( Logger::ACTION_CHAIN, __FILE__": %d: (%.2f %.2f) out of pitch.", generated_count, target_point.x, target_point.y ); #endif continue; } const int holder_reach_step = 1 + 1 // kick + turn + ptype->cyclesToReachDistance( holder_move_dist - ptype->kickableArea() * 0.5 ); // // check opponent // bool exist_opponent = false; for ( PlayerCont::const_iterator o = state.opponents().begin(); o != state.opponents().end(); ++o ) { double opp_move_dist = o->pos().dist( target_point ); int o_step = 1 // turn step + o->playerTypePtr()->cyclesToReachDistance( opp_move_dist - ptype->kickableArea() ); if ( o_step - bonus_step <= holder_reach_step ) { exist_opponent = true; break; } } if ( exist_opponent ) { #ifdef DEBUG_PRINT dlog.addText( Logger::ACTION_CHAIN, __FILE__": %d: (%.2f %.2f) exist opponent.", generated_count, target_point.x, target_point.y ); #endif continue; } const double ball_speed = SP.firstBallSpeed( state.ball().pos().dist( target_point ), holder_reach_step ); PredictState::ConstPtr result_state( new PredictState( state, holder_reach_step, holder->unum(), target_point ) ); CooperativeAction::Ptr action( new Dribble( holder->unum(), target_point, ball_speed, 1, 1, holder_reach_step - 2, "actgenDribble" ) ); ++s_action_count; ++generated_count; action->setIndex( s_action_count ); result->push_back( ActionStatePair( action, result_state ) ); } } #ifdef DEBUG_PRINT dlog.addText( Logger::ACTION_CHAIN, __FILE__": Dribble path=%d, holder=%d generated=%d/%d", path.size(), holder->unum(), generated_count, s_action_count ); #endif }
/*! execute action */ bool Bhv_GoalieChaseBall::execute( PlayerAgent * agent ) { dlog.addText( Logger::TEAM, __FILE__": Bhv_GoalieChaseBall" ); ////////////////////////////////////////////////////////////////// // tackle if ( Bhv_BasicTackle( 0.8, 90.0 ).execute( agent ) ) { dlog.addText( Logger::TEAM, __FILE__": tackle" ); return true; } const ServerParam & SP = ServerParam::i(); const WorldModel & wm = agent->world(); //////////////////////////////////////////////////////////////////////// // get active interception catch point Vector2D my_int_pos = wm.ball().inertiaPoint( wm.interceptTable()->selfReachCycle() ); dlog.addText( Logger::TEAM, __FILE__": execute. intercept point=(%.2f %.2f)", my_int_pos.x, my_int_pos.y ); double pen_thr = wm.ball().distFromSelf() * 0.1 + 1.0; if ( pen_thr < 1.0 ) pen_thr = 1.0; //---------------------------------------------------------- const Line2D ball_line( wm.ball().pos(), wm.ball().vel().th() ); const Line2D defend_line( Vector2D( wm.self().pos().x, -10.0 ), Vector2D( wm.self().pos().x, 10.0 ) ); if ( my_int_pos.x > - SP.pitchHalfLength() - 1.0 && my_int_pos.x < SP.ourPenaltyAreaLineX() - pen_thr && my_int_pos.absY() < SP.penaltyAreaHalfWidth() - pen_thr ) { bool save_recovery = false; if ( ball_line.dist( wm.self().pos() ) < SP.catchableArea() ) { save_recovery = true; } dlog.addText( Logger::TEAM, __FILE__": execute normal intercept" ); agent->debugClient().addMessage( "Intercept(0)" ); Body_Intercept( save_recovery ).execute( agent ); agent->setNeckAction( new Neck_TurnToBall() ); return true; } int self_goalie_min = wm.interceptTable()->selfReachCycle(); int opp_min_cyc = wm.interceptTable()->opponentReachCycle(); Vector2D intersection = ball_line.intersection( defend_line ); if ( ! intersection.isValid() || ball_line.dist( wm.self().pos() ) < SP.catchableArea() * 0.8 || intersection.absY() > SP.goalHalfWidth() + 3.0 ) { if ( ! wm.existKickableOpponent() ) { if ( self_goalie_min <= opp_min_cyc + 2 && my_int_pos.x > -SP.pitchHalfLength() - 2.0 && my_int_pos.x < SP.ourPenaltyAreaLineX() - pen_thr && my_int_pos.absY() < SP.penaltyAreaHalfWidth() - pen_thr ) { if ( Body_Intercept( false ).execute( agent ) ) { dlog.addText( Logger::TEAM, __FILE__": execute normal interception" ); agent->debugClient().addMessage( "Intercept(1)" ); agent->setNeckAction( new Neck_TurnToBall() ); return true; } } dlog.addText( Logger::TEAM, __FILE__": execute. ball vel has same slope to my body??" " myvel-ang=%f body=%f. go to ball direct", wm.ball().vel().th().degree(), wm.self().body().degree() ); // ball vel angle is same to my body angle agent->debugClient().addMessage( "GoToCatch(1)" ); doGoToCatchPoint( agent, wm.ball().pos() ); return true; } } //---------------------------------------------------------- // body is already face to intersection // only dash to intersection // check catch point if ( intersection.absX() > SP.pitchHalfLength() + SP.catchableArea() || intersection.x > SP.ourPenaltyAreaLineX() - SP.catchableArea() || intersection.absY() > SP.penaltyAreaHalfWidth() - SP.catchableArea() ) { dlog.addText( Logger::TEAM, __FILE__": execute intersection(%.2f, %.2f) over range.", intersection.x, intersection.y ); if ( Body_Intercept( false ).execute( agent ) ) { agent->debugClient().addMessage( "Intercept(2)" ); agent->setNeckAction( new Neck_TurnToBall() ); return true; } else { return Bhv_GoalieBasicMove().execute( agent ); } } //---------------------------------------------------------- // check already there const Vector2D my_inertia_final_pos = wm.self().pos() + wm.self().vel() / (1.0 - wm.self().playerType().playerDecay()); double dist_thr = 0.2 + wm.ball().distFromSelf() * 0.1; if ( dist_thr < 0.5 ) dist_thr = 0.5; // if already intersection point stop dash if ( my_inertia_final_pos.dist( intersection ) < dist_thr ) { agent->debugClient().addMessage( "StopForChase" ); Body_StopDash( false ).execute( agent ); agent->setNeckAction( new Neck_TurnToBall() ); return true; } //---------------------------------------------------------- // forward or backward dlog.addText( Logger::TEAM, __FILE__": slide move. point=(%.1f, %.1f)", intersection.x, intersection.y ); if ( wm.ball().pos().x > -35.0 ) { if ( wm.ball().pos().y * intersection.y < 0.0 ) // opposite side { intersection.y = 0.0; } else { intersection.y *= 0.5; } } agent->debugClient().addMessage( "GoToCatch(2)" ); doGoToCatchPoint( agent, intersection ); return true; }