/*! */ void EditData::moveBallTo( const double & x, const double & y ) { Vector2D pos = round_coordinates( x, y ); M_state.ball_ = pos; if ( pos.absY() < 1.0 ) { M_state.ball_.y = 0.0; } if ( Options::instance().dataAutoSelect() && M_samples ) { SampleDataSet::IndexData d = M_samples->nearestData( pos, 1.0 ); if ( d.second ) { M_current_index = d.first; M_state.ball_ = d.second->ball_; } } updatePlayerPosition(); }
/*! */ 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 }
/*! ball_pos & my_pos is set to self localization oriented. if ( onfiled_side != our_side ), these coordinates must be reversed. */ Vector2D Bhv_PenaltyKick::getGoalieMovePos( const Vector2D & ball_pos, const Vector2D & my_pos ) { const ServerParam & SP = ServerParam::i(); const double min_x = -SP.pitchHalfLength() + SP.catchAreaLength()*0.9; if ( ball_pos.x < -49.0 ) { if ( ball_pos.absY() < SP.goalHalfWidth() ) { return Vector2D( min_x, ball_pos.y ); } else { return Vector2D( min_x, sign( ball_pos.y ) * SP.goalHalfWidth() ); } } Vector2D goal_l( -SP.pitchHalfLength(), -SP.goalHalfWidth() ); Vector2D goal_r( -SP.pitchHalfLength(), +SP.goalHalfWidth() ); AngleDeg ball2post_angle_l = ( goal_l - ball_pos ).th(); AngleDeg ball2post_angle_r = ( goal_r - ball_pos ).th(); // NOTE: post_angle_r < post_angle_l AngleDeg line_dir = AngleDeg::bisect( ball2post_angle_r, ball2post_angle_l ); Line2D line_mid( ball_pos, line_dir ); Line2D goal_line( goal_l, goal_r ); Vector2D intersection = goal_line.intersection( line_mid ); if ( intersection.isValid() ) { Line2D line_l( ball_pos, goal_l ); Line2D line_r( ball_pos, goal_r ); AngleDeg alpha = AngleDeg::atan2_deg( SP.goalHalfWidth(), SP.penaltyAreaLength() - 2.5 ); double dist_from_goal = ( ( line_l.dist( intersection ) + line_r.dist( intersection ) ) * 0.5 ) / alpha.sin(); dlog.addText( Logger::TEAM, __FILE__": goalie move. intersection=(%.1f, %.1f) dist_from_goal=%.1f", intersection.x, intersection.y, dist_from_goal ); if ( dist_from_goal <= SP.goalHalfWidth() ) { dist_from_goal = SP.goalHalfWidth(); dlog.addText( Logger::TEAM, __FILE__": goalie move. outer of goal. dist_from_goal=%.1f", dist_from_goal ); } if ( ( ball_pos - intersection ).r() + 1.5 < dist_from_goal ) { dist_from_goal = ( ball_pos - intersection ).r() + 1.5; dlog.addText( Logger::TEAM, __FILE__": goalie move. near than ball. dist_from_goal=%.1f", dist_from_goal ); } AngleDeg position_error = line_dir - ( intersection - my_pos ).th(); const double danger_angle = 21.0; dlog.addText( Logger::TEAM, __FILE__": goalie move position_error_angle=%.1f", position_error.degree() ); if ( position_error.abs() > danger_angle ) { dist_from_goal *= ( ( 1.0 - ((position_error.abs() - danger_angle) / (180.0 - danger_angle)) ) * 0.5 ); dlog.addText( Logger::TEAM, __FILE__": goalie move. error is big. dist_from_goal=%.1f", dist_from_goal ); } Vector2D result = intersection; Vector2D add_vec = ball_pos - intersection; add_vec.setLength( dist_from_goal ); dlog.addText( Logger::TEAM, __FILE__": goalie move. intersection=(%.1f, %.1f) add_vec=(%.1f, %.1f)%.2f", intersection.x, intersection.y, add_vec.x, add_vec.y, add_vec.r() ); result += add_vec; if ( result.x < min_x ) { result.x = min_x; } return result; } else { dlog.addText( Logger::TEAM, __FILE__": goalie move. shot line has no intersection with goal line" ); if ( ball_pos.x > 0.0 ) { return Vector2D(min_x , goal_l.y); } else if ( ball_pos.x < 0.0 ) { return Vector2D(min_x , goal_r.y); } else { return Vector2D(min_x , 0.0); } } }
/*! */ bool Bhv_BasicOffensiveKick::execute( PlayerAgent * agent ) { dlog.addText( Logger::TEAM, __FILE__": Bhv_BasicOffensiveKick" ); const WorldModel & wm = agent->world(); const PlayerPtrCont & opps = wm.opponentsFromSelf(); const PlayerObject * nearest_opp = ( opps.empty() ? static_cast< PlayerObject * >( 0 ) : opps.front() ); const double nearest_opp_dist = ( nearest_opp ? nearest_opp->distFromSelf() : 1000.0 ); const Vector2D nearest_opp_pos = ( nearest_opp ? nearest_opp->pos() : Vector2D( -1000.0, 0.0 ) ); Vector2D pass_point; if ( Body_Pass::get_best_pass( wm, &pass_point, NULL, NULL ) ) { if ( pass_point.x > wm.self().pos().x - 1.0 ) { bool safety = true; const PlayerPtrCont::const_iterator opps_end = opps.end(); for ( PlayerPtrCont::const_iterator it = opps.begin(); it != opps_end; ++it ) { if ( (*it)->pos().dist( pass_point ) < 4.0 ) { safety = false; } } if ( safety ) { dlog.addText( Logger::TEAM, __FILE__": (execute) do best pass" ); agent->debugClient().addMessage( "OffKickPass(1)" ); Body_Pass().execute( agent ); agent->setNeckAction( new Neck_TurnToLowConfTeammate() ); return true; } } } if ( nearest_opp_dist < 7.0 ) { if ( Body_Pass().execute( agent ) ) { dlog.addText( Logger::TEAM, __FILE__": (execute) do best pass" ); agent->debugClient().addMessage( "OffKickPass(2)" ); agent->setNeckAction( new Neck_TurnToLowConfTeammate() ); return true; } } // dribble to my body dir if ( nearest_opp_dist < 5.0 && nearest_opp_dist > ( ServerParam::i().tackleDist() + ServerParam::i().defaultPlayerSpeedMax() * 1.5 ) && wm.self().body().abs() < 70.0 ) { const Vector2D body_dir_drib_target = wm.self().pos() + Vector2D::polar2vector(5.0, wm.self().body()); int max_dir_count = 0; wm.dirRangeCount( wm.self().body(), 20.0, &max_dir_count, NULL, NULL ); if ( body_dir_drib_target.x < ServerParam::i().pitchHalfLength() - 1.0 && body_dir_drib_target.absY() < ServerParam::i().pitchHalfWidth() - 1.0 && max_dir_count < 3 ) { // check opponents // 10m, +-30 degree const Sector2D sector( wm.self().pos(), 0.5, 10.0, wm.self().body() - 30.0, wm.self().body() + 30.0 ); // opponent check with goalie if ( ! wm.existOpponentIn( sector, 10, true ) ) { dlog.addText( Logger::TEAM, __FILE__": (execute) dribble to my body dir" ); agent->debugClient().addMessage( "OffKickDrib(1)" ); Body_Dribble( body_dir_drib_target, 1.0, ServerParam::i().maxDashPower(), 2 ).execute( agent ); agent->setNeckAction( new Neck_TurnToLowConfTeammate() ); return true; } } } Vector2D drib_target( 50.0, wm.self().pos().absY() ); if ( drib_target.y < 20.0 ) drib_target.y = 20.0; if ( drib_target.y > 29.0 ) drib_target.y = 27.0; if ( wm.self().pos().y < 0.0 ) drib_target.y *= -1.0; const AngleDeg drib_angle = ( drib_target - wm.self().pos() ).th(); // opponent is behind of me if ( nearest_opp_pos.x < wm.self().pos().x + 1.0 ) { // check opponents // 15m, +-30 degree const Sector2D sector( wm.self().pos(), 0.5, 15.0, drib_angle - 30.0, drib_angle + 30.0 ); // opponent check with goalie if ( ! wm.existOpponentIn( sector, 10, true ) ) { const int max_dash_step = wm.self().playerType() .cyclesToReachDistance( wm.self().pos().dist( drib_target ) ); if ( wm.self().pos().x > 35.0 ) { drib_target.y *= ( 10.0 / drib_target.absY() ); } dlog.addText( Logger::TEAM, __FILE__": (execute) fast dribble to (%.1f, %.1f) max_step=%d", drib_target.x, drib_target.y, max_dash_step ); agent->debugClient().addMessage( "OffKickDrib(2)" ); Body_Dribble( drib_target, 1.0, ServerParam::i().maxDashPower(), std::min( 5, max_dash_step ) ).execute( agent ); } else { dlog.addText( Logger::TEAM, __FILE__": (execute) slow dribble to (%.1f, %.1f)", drib_target.x, drib_target.y ); agent->debugClient().addMessage( "OffKickDrib(3)" ); Body_Dribble( drib_target, 1.0, ServerParam::i().maxDashPower(), 2 ).execute( agent ); } agent->setNeckAction( new Neck_TurnToLowConfTeammate() ); return true; } // opp is far from me if ( nearest_opp_dist > 5.0 ) { dlog.addText( Logger::TEAM, __FILE__": opp far. dribble(%.1f, %.1f)", drib_target.x, drib_target.y ); agent->debugClient().addMessage( "OffKickDrib(4)" ); Body_Dribble( drib_target, 1.0, ServerParam::i().maxDashPower() * 0.4, 1 ).execute( agent ); agent->setNeckAction( new Neck_TurnToLowConfTeammate() ); return true; } // opp is near // can pass if ( Body_Pass().execute( agent ) ) { dlog.addText( Logger::TEAM, __FILE__": (execute) pass", __LINE__ ); agent->debugClient().addMessage( "OffKickPass(3)" ); agent->setNeckAction( new Neck_TurnToLowConfTeammate() ); return true; } // opp is far from me if ( nearest_opp_dist > 3.0 ) { dlog.addText( Logger::TEAM, __FILE__": (execute) opp far. dribble(%f, %f)", drib_target.x, drib_target.y ); agent->debugClient().addMessage( "OffKickDrib(5)" ); Body_Dribble( drib_target, 1.0, ServerParam::i().maxDashPower() * 0.2, 1 ).execute( agent ); agent->setNeckAction( new Neck_TurnToLowConfTeammate() ); return true; } if ( nearest_opp_dist > 2.5 ) { dlog.addText( Logger::TEAM, __FILE__": hold" ); agent->debugClient().addMessage( "OffKickHold" ); Body_HoldBall().execute( agent ); agent->setNeckAction( new Neck_TurnToLowConfTeammate() ); return true; } { dlog.addText( Logger::TEAM, __FILE__": clear" ); agent->debugClient().addMessage( "OffKickAdvance" ); Body_AdvanceBall().execute( agent ); agent->setNeckAction( new Neck_ScanField() ); } return true; }
/*! 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; }
/*! */ bool Bhv_GoalieChaseBall::is_ball_chase_situation( const PlayerAgent * agent ) { const WorldModel & wm = agent->world(); if ( wm.gameMode().type() != GameMode::PlayOn ) { return false; } const ServerParam & SP = ServerParam::i(); int self_min = wm.interceptTable()->selfReachCycle(); int opp_min = wm.interceptTable()->opponentReachCycle(); //////////////////////////////////////////////////////////////////////// // ball is in very dangerous area const Vector2D ball_next_pos = wm.ball().pos() + wm.ball().vel(); if ( ball_next_pos.x < -SP.pitchHalfLength() + 8.0 && ball_next_pos.absY() < SP.goalHalfWidth() + 3.0 ) { // exist kickable teammate // avoid back pass if ( wm.existKickableTeammate() ) { dlog.addText( Logger::TEAM, __FILE__": danger area. exist kickable teammate?" ); return false; } else if ( wm.ball().distFromSelf() < 3.0 && self_min <= 3 ) { dlog.addText( Logger::TEAM, __FILE__": danger area. ball is very near." ); return true; } else if ( self_min > opp_min + 3 && opp_min < 7 ) { dlog.addText( Logger::TEAM, __FILE__": danger area. opponent may get tha ball faster than me" ); return false; } else { dlog.addText( Logger::TEAM, __FILE__": danger area. chase ball" ); return true; } } //////////////////////////////////////////////////////////////////////// // check shoot moving if ( is_ball_shoot_moving( agent ) && self_min < opp_min ) { dlog.addText( Logger::TEAM, __FILE__": shoot moving. chase ball" ); return true; } //////////////////////////////////////////////////////////////////////// // get active interception catch point const Vector2D my_int_pos = wm.ball().inertiaPoint( wm.interceptTable()->selfReachCycle() ); double pen_thr = wm.ball().distFromSelf() * 0.1 + 1.0; if ( pen_thr < 1.0 ) pen_thr = 1.0; if ( my_int_pos.absY() > SP.penaltyAreaHalfWidth() - pen_thr || my_int_pos.x > SP.ourPenaltyAreaLineX() - pen_thr ) { dlog.addText( Logger::TEAM, __FILE__": intercept point is out of penalty" ); return false; } //////////////////////////////////////////////////////////////////////// // Now, I can chase the ball // check the ball possessor if ( wm.existKickableTeammate() && ! wm.existKickableOpponent() ) { dlog.addText( Logger::TEAM, __FILE__": exist kickable player" ); return false; } if ( opp_min <= self_min - 2 ) { dlog.addText( Logger::TEAM, __FILE__": opponent reach the ball faster than me" ); return false; } const double my_dist_to_catch = wm.self().pos().dist( my_int_pos ); double opp_min_dist = 10000.0; wm.getOpponentNearestTo( my_int_pos, 30, &opp_min_dist ); if ( opp_min_dist < my_dist_to_catch - 2.0 ) { dlog.addText( Logger::TEAM, __FILE__": opponent is nearer than me. my_dist=%.2f opp_dist=%.2f", my_dist_to_catch, opp_min_dist ); return false; } dlog.addText( Logger::TEAM, __FILE__": exist interception point. try chase." ); return true; }
/*! */ void CrossGenerator::createCross( const WorldModel & wm, const AbstractPlayerObject * receiver ) { static const int MIN_RECEIVE_STEP = 2; static const int MAX_RECEIVE_STEP = 12; // Magic Number static const double MIN_RECEIVE_BALL_SPEED = ServerParam::i().defaultPlayerSpeedMax(); // = std::max( ServerParam::i().defaultPlayerSpeedMax(), // ServerParam::i().ballSpeedMax() // * std::pow( ServerParam::i().ballDecay(), MAX_RECEIVE_STEP ) ); // static const MAX_RECEIVE_BALL_SPEED // = ServerParam::i().ballSpeedMax() // * std::pow( ServerParam::i().ballDecay(), MIN_RECEIVE_STEP ); static const double ANGLE_STEP = 3.0; static const double DIST_STEP = 0.9; const ServerParam & SP = ServerParam::i(); const double min_first_ball_speed = SP.ballSpeedMax() * 0.67; // Magic Number const double max_first_ball_speed = ( wm.gameMode().type() == GameMode::PlayOn ? SP.ballSpeedMax() : wm.self().isKickable() ? wm.self().kickRate() * SP.maxPower() : SP.kickPowerRate() * SP.maxPower() ); const PlayerType * ptype = receiver->playerTypePtr(); const Vector2D receiver_pos = receiver->inertiaFinalPoint(); const double receiver_dist = M_first_point.dist( receiver_pos ); const AngleDeg receiver_angle_from_ball = ( receiver_pos - M_first_point ).th(); #ifdef USE_ONLY_MAX_ANGLE_WIDTH double max_angle_diff = -1.0; CooperativeAction::Ptr best_action; #endif // // angle loop // for ( int a = -2; a < 3; ++a ) { const AngleDeg cross_angle = receiver_angle_from_ball + ( ANGLE_STEP * a ); // // distance loop // for ( int d = 0; d < 5; ++d ) { const double sub_dist = DIST_STEP * d; const double ball_move_dist = receiver_dist - sub_dist; const Vector2D receive_point = M_first_point + Vector2D::from_polar( ball_move_dist, cross_angle ); #ifdef DEBUG_PRINT dlog.addText( Logger::CROSS, "==== receiver=%d receivePos=(%.2f %.2f) loop=%d angle=%.1f", receiver->unum(), receive_point.x, receive_point.y, a, cross_angle.degree() ); #endif if ( receive_point.x > SP.pitchHalfLength() - 0.5 || receive_point.absY() > SP.pitchHalfWidth() - 3.0 ) { #ifdef DEBUG_PRINT dlog.addText( Logger::CROSS, "%d: xxx unum=%d (%.2f %.2f) outOfBounds", M_total_count, receiver->unum(), receive_point.x, receive_point.y ); debug_paint_failed( M_total_count, receive_point ); #endif continue; } const int receiver_step = ptype->cyclesToReachDistance( sub_dist ) + 1; // // step loop // for ( int step = std::max( MIN_RECEIVE_STEP, receiver_step ); step <= MAX_RECEIVE_STEP; ++step ) { ++M_total_count; double first_ball_speed = calc_first_term_geom_series( ball_move_dist, SP.ballDecay(), step ); if ( first_ball_speed < min_first_ball_speed ) { #ifdef DEBUG_PRINT_FAILED_COURSE dlog.addText( Logger::CROSS, "%d: xxx unum=%d (%.1f %.1f) step=%d firstSpeed=%.3f < min=%.3f", M_total_count, receiver->unum(), receive_point.x, receive_point.y, step, first_ball_speed, min_first_ball_speed ); //debug_paint_failed( M_total_count, receive_point ); #endif break; } if ( max_first_ball_speed < first_ball_speed ) { #ifdef DEBUG_PRINT_FAILED_COURSE dlog.addText( Logger::CROSS, "%d: xxx unum=%d (%.1f %.1f) step=%d firstSpeed=%.3f > max=%.3f", M_total_count, receiver->unum(), receive_point.x, receive_point.y, step, first_ball_speed, max_first_ball_speed ); //debug_paint_failed( M_total_count, receive_point ); #endif continue; } double receive_ball_speed = first_ball_speed * std::pow( SP.ballDecay(), step ); if ( receive_ball_speed < MIN_RECEIVE_BALL_SPEED ) { #ifdef DEBUG_PRINT_FAILED_COURSE dlog.addText( Logger::CROSS, "%d: xxx unum=%d (%.1f %.1f) step=%d recvSpeed=%.3f < min=%.3f", M_total_count, receiver->unum(), receive_point.x, receive_point.y, step, receive_ball_speed, min_first_ball_speed ); //debug_paint_failed( M_total_count, receive_point ); #endif break; } int kick_count = FieldAnalyzer::predict_kick_count( wm, M_passer, first_ball_speed, cross_angle ); if ( ! checkOpponent( M_first_point, receiver, receive_point, first_ball_speed, cross_angle, step + kick_count - 1 ) ) // 1 step penalty for observation delay { break; } #ifdef USE_ONLY_MAX_ANGLE_WIDTH double min_angle_diff = getMinimumAngleWidth( ball_move_dist, cross_angle ); if ( min_angle_diff > max_angle_diff ) { CooperativeAction::Ptr ptr( new Pass( M_passer->unum(), receiver->unum(), receive_point, first_ball_speed, step + kick_count, kick_count, false, "cross" ) ); ptr->setIndex( M_total_count ); max_angle_diff = min_angle_diff; best_action = ptr; } #else CooperativeAction::Ptr ptr( new Pass( M_passer->unum(), receiver->unum(), receive_point, first_ball_speed, step + kick_count, kick_count, false, "cross" ) ); ptr->setIndex( M_total_count ); M_courses.push_back( ptr ); #endif // M_courses.push_back( ptr ); #ifdef DEBUG_PRINT_SUCCESS_COURSE dlog.addText( Logger::CROSS, "%d: ok Cross step=%d pos=(%.1f %.1f) speed=%.3f->%.3f nKick=%d", M_total_count, step, kick_count, receive_point.x, receive_point.y, first_ball_speed, receive_ball_speed, kick_count ); char num[8]; snprintf( num, 8, "%d", M_total_count ); dlog.addMessage( Logger::CROSS, receive_point, num ); dlog.addRect( Logger::CROSS, receive_point.x - 0.1, receive_point.y - 0.1, 0.2, 0.2, "#00ff00" ); #endif break; } } } #ifdef USE_ONLY_MAX_ANGLE_WIDTH if ( best_action ) { M_courses.push_back( best_action ); } #endif }
/*! */ double TackleGenerator::evaluate( const WorldModel & wm, const TackleResult & result ) { const ServerParam & SP = ServerParam::i(); const Vector2D ball_end_point = inertia_final_point( wm.ball().pos(), result.ball_vel_, SP.ballDecay() ); const Segment2D ball_line( wm.ball().pos(), ball_end_point ); const double ball_speed = result.ball_speed_; const AngleDeg ball_move_angle = result.ball_move_angle_; #ifdef DEBUG_PRINT dlog.addText( Logger::CLEAR, "(evaluate) angle=%.1f speed=%.2f move_angle=%.1f end_point=(%.2f %.2f)", result.tackle_angle_.degree(), ball_speed, ball_move_angle.degree(), ball_end_point.x, ball_end_point.y ); #endif // // moving to their goal // if ( ball_end_point.x > SP.pitchHalfLength() && wm.ball().pos().dist2( SP.theirTeamGoalPos() ) < std::pow( 20.0, 2 ) ) { const Line2D goal_line( Vector2D( SP.pitchHalfLength(), 10.0 ), Vector2D( SP.pitchHalfLength(), -10.0 ) ); const Vector2D intersect = ball_line.intersection( goal_line ); if ( intersect.isValid() && intersect.absY() < SP.goalHalfWidth() ) { double shoot_score = 1000000.0; double speed_rate = 1.0 - std::exp( - std::pow( ball_speed, 2 ) / ( 2.0 * std::pow( SP.ballSpeedMax()*0.5, 2 ) ) ); double y_rate = std::exp( - std::pow( intersect.absY(), 2 ) / ( 2.0 * std::pow( SP.goalWidth(), 2 ) ) ); shoot_score *= speed_rate; shoot_score *= y_rate; #ifdef DEBUG_PRINT dlog.addText( Logger::CLEAR, "__ shoot %f (speed_rate=%f y_rate=%f)", shoot_score, speed_rate, y_rate ); #endif return shoot_score; } } // // moving to our goal // if ( ball_end_point.x < -SP.pitchHalfLength() ) { const Line2D goal_line( Vector2D( -SP.pitchHalfLength(), 10.0 ), Vector2D( -SP.pitchHalfLength(), -10.0 ) ); const Vector2D intersect = ball_line.intersection( goal_line ); if ( intersect.isValid() && intersect.absY() < SP.goalHalfWidth() + 1.0 ) { double shoot_score = 0.0; double y_penalty = ( -10000.0 * std::exp( - std::pow( intersect.absY() - SP.goalHalfWidth(), 2 ) / ( 2.0 * std::pow( SP.goalHalfWidth(), 2 ) ) ) ); double speed_bonus = ( +10000.0 * std::exp( - std::pow( ball_speed, 2 ) / ( 2.0 * std::pow( SP.ballSpeedMax()*0.5, 2 ) ) ) ); shoot_score = y_penalty + speed_bonus; #ifdef DEBUG_PRINT dlog.addText( Logger::CLEAR, "__ in our goal %f (y_pealty=%f speed_bonus=%f)", shoot_score, y_penalty, speed_bonus ); #endif return shoot_score; } } // // normal evaluation // int opponent_reach_step = predictOpponentsReachStep( wm, wm.ball().pos(), result.ball_vel_, ball_move_angle ); Vector2D final_point = inertia_n_step_point( wm.ball().pos(), result.ball_vel_, opponent_reach_step, SP.ballDecay() ); { Segment2D final_segment( wm.ball().pos(), final_point ); Rect2D pitch = Rect2D::from_center( 0.0, 0.0, SP.pitchLength(), SP.pitchWidth() ); Vector2D intersection; int n = pitch.intersection( final_segment, &intersection, NULL ); if ( n > 0 ) { final_point = intersection; } } #if 1 AngleDeg our_goal_angle = ( SP.ourTeamGoalPos() - wm.ball().pos() ).th(); double our_goal_angle_diff = ( our_goal_angle - ball_move_angle ).abs(); double our_goal_angle_rate = 1.0 - std::exp( - std::pow( our_goal_angle_diff, 2 ) / ( 2.0 * std::pow( 40.0, 2 ) ) ); double y_rate = ( final_point.absY() > SP.pitchHalfWidth() - 0.1 ? 1.0 : std::exp( - std::pow( final_point.absY() - SP.pitchHalfWidth(), 2 ) / ( 2.0 * std::pow( SP.pitchHalfWidth() * 0.7, 2 ) ) ) ); double opp_rate = 1.0 - std::exp( - std::pow( (double)opponent_reach_step, 2 ) / ( 2.0 * std::pow( 30.0, 2 ) ) ); double score = 10000.0 * our_goal_angle_rate * y_rate * opp_rate; #ifdef DEBUG_PRINT dlog.addText( Logger::CLEAR, "__ goal_angle_rate=%f", our_goal_angle_rate, y_rate, score ); dlog.addText( Logger::CLEAR, "__ y_rate=%f", our_goal_angle_rate, y_rate, score ); dlog.addText( Logger::CLEAR, "__ opp_rate=%f", opp_rate ); dlog.addText( Logger::CLEAR, ">>> score=%f", score ); #endif return score; #else double x_val = ( final_point.x > SP.pitchHalfLength() ? 1.0 : std::exp( - std::pow( final_point.x - SP.pitchHalfLength(), 2 ) / ( 2.0 * std::pow( SP.pitchLength() * 0.4, 2 ) ) ) ); double y_val = ( final_point.absY() > SP.pitchHalfWidth() ? 1.0 : std::exp( - std::pow( final_point.absY() - SP.pitchHalfWidth(), 2 ) / ( 2.0 * std::pow( SP.pitchHalfWidth() * 0.7, 2 ) ) ) ); double opp_goal_dist = SP.theirTeamGoalPos().dist( final_point ); double opp_goal_dist_val = std::exp( - std::pow( opp_goal_dist, 2 ) / ( 2.0 * std::pow( 20.0, 2 ) ) ); double our_goal_dist = SP.ourTeamGoalPos().dist( final_point ); double our_goal_dist_rate = 1.0 - std::exp( - std::pow( our_goal_dist, 2 ) / ( 2.0 * std::pow( 20.0, 2 ) ) ); double opp_rate = 1.0 - std::exp( - std::pow( (double)opponent_reach_step, 2 ) / ( 2.0 * std::pow( 30.0, 2 ) ) ); double score = 0.0; score += 1000.0 * x_val; #ifdef DEBUG_PRINT dlog.addText( Logger::CLEAR, "__ x_val %f (%f)", 10000.0 * x_val, score ); #endif score += 1000.0 * y_val; #ifdef DEBUG_PRINT dlog.addText( Logger::CLEAR, "__ y_val %f (%f)", 1000.0 * y_val, score ); #endif score += 1000.0 * opp_goal_dist_val; #ifdef DEBUG_PRINT dlog.addText( Logger::CLEAR, "__ opp_goal_dist_val %f (%f)", 1000.0 * opp_goal_dist_val, score ); #endif score *= our_goal_dist_rate; #ifdef DEBUG_PRINT dlog.addText( Logger::CLEAR, "__ our_goal_dist=%.2f rate=%f (%f)", our_goal_dist, our_goal_dist_rate, score ); #endif score *= opp_rate; #ifdef DEBUG_PRINT dlog.addText( Logger::CLEAR, "__ opponent_reach_step=%d rate=%f (%f)", opponent_reach_step, opp_rate, score ); #endif return score; #endif }
/*! */ Strategy::BallArea Strategy::get_ball_area( const Vector2D & ball_pos ) { dlog.addLine( Logger::TEAM, 52.5, -17.0, -52.5, -17.0, "#999999" ); dlog.addLine( Logger::TEAM, 52.5, 17.0, -52.5, 17.0, "#999999" ); dlog.addLine( Logger::TEAM, 36.0, -34.0, 36.0, 34.0, "#999999" ); dlog.addLine( Logger::TEAM, -1.0, -34.0, -1.0, 34.0, "#999999" ); dlog.addLine( Logger::TEAM, -30.0, -17.0, -30.0, 17.0, "#999999" ); dlog.addLine( Logger::TEAM, //-36.5, -34.0, -36.5, 34.0, -35.5, -34.0, -35.5, 34.0, "#999999" ); if ( ball_pos.x > 36.0 ) { if ( ball_pos.absY() > 17.0 ) { dlog.addText( Logger::TEAM, __FILE__": get_ball_area: Cross" ); dlog.addRect( Logger::TEAM, 36.0, -34.0, 52.5 - 36.0, 34.0 - 17.0, "#00ff00" ); dlog.addRect( Logger::TEAM, 36.0, 17.0, 52.5 - 36.0, 34.0 - 17.0, "#00ff00" ); return BA_Cross; } else { dlog.addText( Logger::TEAM, __FILE__": get_ball_area: ShootChance" ); dlog.addRect( Logger::TEAM, 36.0, -17.0, 52.5 - 36.0, 34.0, "#00ff00" ); return BA_ShootChance; } } else if ( ball_pos.x > -1.0 ) { if ( ball_pos.absY() > 17.0 ) { dlog.addText( Logger::TEAM, __FILE__": get_ball_area: DribbleAttack" ); dlog.addRect( Logger::TEAM, -1.0, -34.0, 36.0 + 1.0, 34.0 - 17.0, "#00ff00" ); dlog.addRect( Logger::TEAM, -1.0, 17.0, 36.0 + 1.0, 34.0 - 17.0, "#00ff00" ); return BA_DribbleAttack; } else { dlog.addText( Logger::TEAM, __FILE__": get_ball_area: OffMidField" ); dlog.addRect( Logger::TEAM, -1.0, -17.0, 36.0 + 1.0, 34.0, "#00ff00" ); return BA_OffMidField; } } else if ( ball_pos.x > -30.0 ) { if ( ball_pos.absY() > 17.0 ) { dlog.addText( Logger::TEAM, __FILE__": get_ball_area: DribbleBlock" ); dlog.addRect( Logger::TEAM, -30.0, -34.0, -1.0 + 30.0, 34.0 - 17.0, "#00ff00" ); dlog.addRect( Logger::TEAM, -30.0, 17.0, -1.0 + 30.0, 34.0 - 17.0, "#00ff00" ); return BA_DribbleBlock; } else { dlog.addText( Logger::TEAM, __FILE__": get_ball_area: DefMidField" ); dlog.addRect( Logger::TEAM, -30.0, -17.0, -1.0 + 30.0, 34.0, "#00ff00" ); return BA_DefMidField; } } // 2009-06-17 akiyama: -36.5 -> -35.5 //else if ( ball_pos.x > -36.5 ) else if ( ball_pos.x > -35.5 ) { if ( ball_pos.absY() > 17.0 ) { dlog.addText( Logger::TEAM, __FILE__": get_ball_area: CrossBlock" ); dlog.addRect( Logger::TEAM, //-36.5, -34.0, 36.5 - 30.0, 34.0 - 17.0, -35.5, -34.0, 35.5 - 30.0, 34.0 - 17.0, "#00ff00" ); dlog.addRect( Logger::TEAM, -35.5, 17.0, 35.5 - 30.0, 34.0 - 17.0, "#00ff00" ); return BA_CrossBlock; } else { dlog.addText( Logger::TEAM, __FILE__": get_ball_area: Stopper" ); dlog.addRect( Logger::TEAM, //-36.5, -17.0, 36.5 - 30.0, 34.0, -35.5, -17.0, 35.5 - 30.0, 34.0, "#00ff00" ); // 2009-06-17 akiyama: Stopper -> DefMidField //return BA_Stopper; return BA_DefMidField; } } else { if ( ball_pos.absY() > 17.0 ) { dlog.addText( Logger::TEAM, __FILE__": get_ball_area: CrossBlock" ); dlog.addRect( Logger::TEAM, -52.5, -34.0, 52.5 - 36.5, 34.0 - 17.0, "#00ff00" ); dlog.addRect( Logger::TEAM, -52.5, 17.0, 52.5 - 36.5, 34.0 - 17.0, "#00ff00" ); return BA_CrossBlock; } else { dlog.addText( Logger::TEAM, __FILE__": get_ball_area: Danger" ); dlog.addRect( Logger::TEAM, -52.5, -17.0, 52.5 - 36.5, 34.0, "#00ff00" ); return BA_Danger; } } dlog.addText( Logger::TEAM, __FILE__": get_ball_area: unknown area" ); return BA_None; }