Example #1
0
/*!

 */
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 );
    }
}
Example #4
0
/*!

 */
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;

}
Example #7
0
/*!
  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;
}
Example #8
0
/*!

 */
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;
}
Example #9
0
/*!

 */
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;
}