Пример #1
0
/*!

*/
bool
Neck_ForMark::execute( PlayerAgent * agent )
{
    dlog.addText( Logger::ACTION,
                  __FILE__": Neck_ForMark count_thr=%d",
                  M_count_thr );

    const WorldModel & wm = agent->world();

    const PlayerPtrCont & opps = wm.opponentsFromSelf();
    const PlayerObject * nearest_opp = ( opps.empty() ? static_cast< PlayerObject * >( 0 ) : opps.front() );
    const Vector2D opp = ( nearest_opp ? nearest_opp->pos() : Vector2D( -1000.0, 0.0 ) );
    if ( wm.opponentsFromSelf().front()->posCount() > 1 )
    {
        return  Neck_TurnToPoint( opp ).execute( agent );
    }
    if ( wm.ball().posCount() <= M_count_thr )
    {
        dlog.addText( Logger::ACTION,
                      __FILE__": pos_count=%d <= count_thr=%d",
                      wm.ball().posCount(), M_count_thr );
        return Neck_ScanField().execute( agent );
    }

    const ServerParam & SP = ServerParam::i();

    const Vector2D ball_next = agent->effector().queuedNextBallPos();
    const Vector2D my_next = agent->effector().queuedNextSelfPos();

    if ( wm.ball().posCount() <= 0
         && my_next.dist( ball_next ) < SP.visibleDistance() - 0.2 )
    {
        dlog.addText( Logger::ACTION,
                      __FILE__": in visible distance." );
        return Neck_ScanField().execute( agent );
    }

    const AngleDeg my_next_body = agent->effector().queuedNextSelfBody();
    const double next_view_width = agent->effector().queuedNextViewWidth().width();

    if ( ( ( ball_next - my_next ).th() - my_next_body ).abs()
         > SP.maxNeckAngle() + next_view_width * 0.5 + 2.0 )
    {
        dlog.addText( Logger::ACTION,
                      __FILE__": never face to ball" );
        return Neck_ScanField().execute( agent );
    }

    dlog.addText( Logger::ACTION,
                  __FILE__": turn neck to ball" );
    return Neck_TurnToBall().execute( agent );
}
/*!

*/
bool
Neck_TurnToBallOrScan::execute( PlayerAgent * agent )
{
    dlog.addText( Logger::ACTION,
                  __FILE__": Neck_TurnToBallOrScan count_thr=%d",
                  M_count_thr );

    const WorldModel & wm = agent->world();

    if ( wm.ball().posCount() <= M_count_thr )
    {
        dlog.addText( Logger::ACTION,
                      __FILE__": pos_count=%d <= count_thr=%d",
                      wm.ball().posCount(), M_count_thr );
        return Neck_ScanField().execute( agent );
    }

    const ServerParam & SP = ServerParam::i();

    const Vector2D ball_next = agent->effector().queuedNextBallPos();
    const Vector2D my_next = agent->effector().queuedNextSelfPos();

    if ( wm.ball().posCount() <= 0
         && my_next.dist( ball_next ) < SP.visibleDistance() - 0.2 )
    {
        dlog.addText( Logger::ACTION,
                      __FILE__": in visible distance." );
        return Neck_ScanField().execute( agent );
    }

    const AngleDeg my_next_body = agent->effector().queuedNextSelfBody();
    const double next_view_width = agent->effector().queuedNextViewWidth().width();

    if ( ( ( ball_next - my_next ).th() - my_next_body ).abs()
         > SP.maxNeckAngle() + next_view_width * 0.5 + 2.0 )
    {
        dlog.addText( Logger::ACTION,
                      __FILE__": never face to ball" );
        return Neck_ScanField().execute( agent );
    }

    dlog.addText( Logger::ACTION,
                  __FILE__": turn neck to ball" );
    return Neck_TurnToBall().execute( agent );
}
Пример #3
0
/*!

*/
bool
Neck_ScanPlayers::execute( PlayerAgent * agent )
{
#ifdef __APPLE__
    static GameTime s_last_calc_time( 0, 0 );
    static ViewWidth s_last_calc_view_width = ViewWidth::NORMAL;
    static double s_last_calc_min_neck_angle = 0.0;
    static double s_last_calc_max_neck_angle = 0.0;
    static double s_cached_target_angle = 0.0;
#else
    static thread_local GameTime s_last_calc_time( 0, 0 );
    static thread_local ViewWidth s_last_calc_view_width = ViewWidth::NORMAL;
    static thread_local double s_last_calc_min_neck_angle = 0.0;
    static thread_local double s_last_calc_max_neck_angle = 0.0;
    static thread_local double s_cached_target_angle = 0.0;
#endif

    if ( s_last_calc_time != agent->world().time()
         || s_last_calc_view_width != agent->effector().queuedNextViewWidth()
         || std::fabs( s_last_calc_min_neck_angle - M_min_neck_angle ) > 1.0e-3
         || std::fabs( s_last_calc_max_neck_angle - M_max_neck_angle ) > 1.0e-3 )
    {
        s_last_calc_time = agent->world().time();
        s_last_calc_view_width = agent->effector().queuedNextViewWidth();
        s_last_calc_min_neck_angle = M_min_neck_angle;
        s_last_calc_max_neck_angle = M_max_neck_angle;

#ifdef DEBUG_PRINT
        dlog.addText( Logger::ACTION,
                      __FILE__": (execute) call calcAngle()" );
#endif
        s_cached_target_angle = get_best_angle( agent,
                                                M_min_neck_angle,
                                                M_max_neck_angle );
    }

    if ( s_cached_target_angle == INVALID_ANGLE )
    {
        dlog.addText( Logger::ACTION,
                      __FILE__": (execute) envalid angle" );
        return Neck_ScanField().execute( agent );
    }

    AngleDeg target_angle = s_cached_target_angle;

    dlog.addText( Logger::ACTION,
                  __FILE__": (execute) target_angle=%.1f cached_value=%.1f",
                  target_angle.degree(), s_cached_target_angle );
    agent->debugClient().addMessage( "NeckScanPl" );

    agent->doTurnNeck( target_angle
                       - agent->effector().queuedNextSelfBody()
                       - agent->world().self().neck() );
    return true;
}
/*!

 */
bool
Neck_TurnToLowConfTeammate::execute( PlayerAgent * agent )
{
    const WorldModel & wm = agent->world();
    const PlayerPtrCont & teammates = wm.teammatesFromSelf();

    if ( teammates.empty() )
    {
        dlog.addText( Logger::ACTION,
                      __FILE__": no teammate" );
        return Neck_ScanField().execute( agent );
    }

    const double next_view_half_width = agent->effector().queuedNextViewWidth().width() * 0.5;
    const double next_neck_half_range = ServerParam::i().maxNeckAngle() + next_view_half_width;
    const Vector2D next_self_pos = agent->effector().queuedNextSelfPos();
    const AngleDeg next_self_body = agent->effector().queuedNextSelfBody();

    int pos_count = 1;
    Vector2D candidate_point( -52.5, 0.0 );
    int candidate_unum = 0;

    const double max_dist = 40.0;

    const PlayerPtrCont::const_iterator t_end = teammates.end();
    for ( PlayerPtrCont::const_iterator it = teammates.begin();
          it != t_end;
          ++it )
    {
        if ( (*it)->isGhost() )
        {
            continue;
        }

        if ( (*it)->distFromSelf() > max_dist )
        {
            break;
        }

        if ( (*it)->posCount() >= pos_count
             && candidate_point.x < (*it)->pos().x )
        {
            Vector2D pos = (*it)->pos() + (*it)->vel();
            AngleDeg angle = ( pos - next_self_pos ).th();

            if ( ( angle - next_self_body ).abs() < next_neck_half_range - 5.0 )
            {
                // can face
                candidate_unum = (*it)->unum();
                candidate_point = pos;
                pos_count = (*it)->posCount();
            }
        }
    }

    if ( pos_count <= 1 )
    {
        dlog.addText( Logger::ACTION,
                      __FILE__": no candidate. pos_count=%d",
                      pos_count );
        return Neck_TurnToBallOrScan().execute( agent );
    }

    dlog.addText( Logger::ACTION,
                  __FILE__": look teammate %d (%.1f, %.1f). pos_count=%d",
                  candidate_unum,
                  candidate_point.x, candidate_point.y,
                  pos_count );

    //
    // search the best angle
    //

    AngleDeg player_angle = ( candidate_point - next_self_pos ).th();
    AngleDeg left_max_angle = player_angle - ( next_view_half_width - 15.0 );
    AngleDeg right_max_angle = player_angle + ( next_view_half_width - 15.0 );

    if ( left_max_angle.isLeftOf( next_self_body + ServerParam::i().minNeckAngle() ) )
    {
        left_max_angle = next_self_body + ServerParam::i().minNeckAngle();
    }

    if ( right_max_angle.isRightOf( next_self_body + ServerParam::i().maxNeckAngle() ) )
    {
        right_max_angle = next_self_body + ServerParam::i().maxNeckAngle();
    }

    dlog.addText( Logger::ACTION,
                  __FILE__": player_angle=%.0f  left_angle=%.0f  right_angle=%.0f",
                  player_angle.degree(),
                  left_max_angle.degree(),
                  right_max_angle.degree() );

    // count players in view cone

    const double angle_range = ( right_max_angle - left_max_angle ).abs();
    const double neck_step = angle_range / 10.0;

    double best_dir = -360.0;
    double best_score = -1.0;
    double best_angle_diff = 0.0;


    if ( wm.opponentsFromSelf().size() >= 11 )
    {
        const AbstractPlayerCont::const_iterator end = wm.allPlayers().end();
        for ( double dir = 0.0; dir < angle_range + 0.001; dir += neck_step )
        {
            AngleDeg target_angle = left_max_angle + dir;
            AngleDeg left = target_angle - next_view_half_width;
            AngleDeg right = target_angle + next_view_half_width;

            double score = 0.0;
            double angle_diff = 180.0;

            for ( AbstractPlayerCont::const_iterator p = wm.allPlayers().begin();
                  p != end;
                  ++p )
            {
                if ( (*p)->isSelf() ) continue;
                //if ( (*p)->isGhost() ) continue;
                Vector2D pos = (*p)->pos() + (*p)->vel();
                if ( pos.dist( next_self_pos ) > 35.0 ) continue; // XXX magic number XXX

                AngleDeg angle = ( pos - next_self_pos ).th();
                if ( angle.isRightOf( left )
                     && angle.isLeftOf( right ) )
                {
#if 1

                    int pos_count = (*p)->seenPosCount();
                    if ( (*p)->isGhost() ) pos_count = std::min( 2, pos_count );

                    double base_val = ( pos_count + 1 ) * 2.0;
                    //double rate = std::exp( - std::pow( (*p)->distFromBall(), 2 )
                    double rate = std::exp( - std::pow( (*p)->distFromSelf(), 2 )
                                            / ( 2.0 * std::pow( 40.0, 2 ) ) ); // Magic Number: variance = 40.0
                    score += base_val * rate;


#else
                    if ( (*p)->goalie()
                         && next_self_pos.x > 33.0 )
                    {
                        score += (*p)->posCount() * 2 + 20;
                    }
                    else if ( pos.x > next_self_pos.x - 5.0 )
                    {
                        score += (*p)->posCount() * 2 + 1;
                    }
                    else
                    {
                        score += (*p)->posCount();
                    }
#endif

                    double tmp_diff = std::min( ( angle - left ).abs(),
                                                ( angle - right ).abs() );
                    if ( tmp_diff < angle_diff )
                    {
                        angle_diff = tmp_diff;
                    }
                }
            }
#ifdef DEBUG
            dlog.addText( Logger::ACTION,
                          "__ dir=%.0f  score=%.1f angle_diff=%.1f",
                          target_angle.degree(),
                          score,
                          angle_diff );
#endif
            if ( score > best_score )
            {
                best_dir = target_angle.degree();
                best_score = score;
                best_angle_diff = angle_diff;
#ifdef DEBUG
                dlog.addText( Logger::ACTION,
                              "__ update best dir (1)" );
#endif
            }
            else if ( score == best_score )
            {
                if ( best_angle_diff < angle_diff )
                {
                    best_dir = target_angle.degree();
                    best_score = score;
                    best_angle_diff = angle_diff;
#ifdef DEBUG
                    dlog.addText( Logger::ACTION,
                                  "__ update best dir (2)" );
#endif
                }
            }
        }
    }

    AngleDeg best_angle = player_angle;
    if ( best_dir != -360.0 )
    {
        dlog.addText( Logger::ACTION,
                      __FILE__": changed target angle to max player count. player_angle=%.0f -> %.0f",
                      player_angle.degree(),
                      best_dir );
        best_angle = best_dir;
    }
    else
    {
        int left_sum_count = 0;
        int right_sum_count = 0;
        wm.dirRangeCount( left_max_angle,
                          next_view_half_width * 2.0,
                          NULL, &left_sum_count, NULL );
        wm.dirRangeCount( right_max_angle,
                          next_view_half_width * 2.0,
                          NULL, &right_sum_count, NULL );
        if ( left_sum_count < right_sum_count )
        {
            best_angle = left_max_angle;
            dlog.addText( Logger::ACTION,
                          __FILE__": changed target angle to left max. player_angle=%.0f -> %.0f",
                          player_angle.degree(),
                          left_max_angle.degree() );
        }
        else if ( right_sum_count < left_sum_count )
        {
            best_angle = right_max_angle;
            dlog.addText( Logger::ACTION,
                          __FILE__": changed target angle to right max. player_angle=%.0f -> %.0f",
                          player_angle.degree(),
                          right_max_angle.degree() );
        }
    }

    AngleDeg neck_moment = best_angle;
    neck_moment -= next_self_body; // relative to body
    neck_moment -= wm.self().neck(); // relative to face
    neck_moment = ServerParam::i().normalizeNeckMoment( neck_moment.degree() );

    agent->debugClient().addMessage( "LookOur%d", candidate_unum );
    return agent->doTurnNeck( neck_moment );
}