/*!

 */
void
TackleGenerator::generate( const WorldModel & wm )
{
    static GameTime s_update_time( 0, 0 );

    if ( s_update_time == wm.time() )
    {
        // dlog.addText( Logger::CLEAR,
        //               __FILE__": already updated" );
        return;
    }
    s_update_time = wm.time();

    clear();

    if ( wm.self().isKickable() )
    {
        // dlog.addText( Logger::CLEAR,
        //               __FILE__": kickable" );
        return;
    }

    if ( wm.self().tackleProbability() < 0.001
         && wm.self().foulProbability() < 0.001 )
    {
        // dlog.addText( Logger::CLEAR,
        //               __FILE__": never tacklable" );
        return;
    }

    if ( wm.time().stopped() > 0 )
    {
        // dlog.addText( Logger::CLEAR,
        //               __FILE__": time stopped" );
        return;
    }

    if ( wm.gameMode().type() != GameMode::PlayOn
         && ! wm.gameMode().isPenaltyKickMode() )
    {
        // dlog.addText( Logger::CLEAR,
        //               __FILE__": illegal playmode " );
        return;
    }


#ifdef DEBUG_PROFILE
    MSecTimer timer;
#endif

    calculate( wm );

#ifdef DEBUG_PROFILE
    dlog.addText( Logger::CLEAR,
                  __FILE__": PROFILE. elapsed=%.3f [ms]",
                  timer.elapsedReal() );
#endif

}
Пример #2
0
/*!

 */
void
CrossGenerator::updateReceivers( const WorldModel & wm )
{
    static const double shootable_dist2 = std::pow( 16.0, 2 ); // Magic Number
    static const double min_cross_dist2
        = std::pow( ServerParam::i().defaultKickableArea() * 2.2, 2 );
    static const double max_cross_dist2
        = std::pow( inertia_n_step_distance( ServerParam::i().ballSpeedMax(),
                                             9,
                                             ServerParam::i().ballDecay() ),
                    2 );

    const Vector2D goal = ServerParam::i().theirTeamGoalPos();

    const bool is_self_passer = ( M_passer->unum() == wm.self().unum() );

    for ( AbstractPlayerCont::const_iterator
              p = wm.ourPlayers().begin(),
              end = wm.ourPlayers().end();
          p != end;
          ++p )
    {
        if ( *p == M_passer ) continue;

        if ( is_self_passer )
        {
            if ( (*p)->isGhost() ) continue;
            if ( (*p)->posCount() >= 4 ) continue;
            if ( (*p)->pos().x > wm.offsideLineX() ) continue;
        }
        else
        {
            // ignore other players
            if ( (*p)->unum() != wm.self().unum() )
            {
                continue;
            }
        }

        if ( (*p)->pos().dist2( goal ) > shootable_dist2 ) continue;

        double d2 = (*p)->pos().dist2( M_first_point );
        if ( d2 < min_cross_dist2 ) continue;
        if ( max_cross_dist2 < d2 ) continue;

        M_receiver_candidates.push_back( *p );

#ifdef DEBUG_UPDATE_OPPONENT
        dlog.addText( Logger::CROSS,
                      "Cross receiver %d pos(%.1f %.1f)",
                      (*p)->unum(),
                      (*p)->pos().x, (*p)->pos().y );
#endif
    }
}
Пример #3
0
/*!

 */
Vector2D
Bhv_ChainAction::getKeepBallVel( const WorldModel & wm )
{
    static GameTime s_update_time( 0, 0 );
    static Vector2D s_best_ball_vel( 0.0, 0.0 );

    if ( s_update_time == wm.time() )
    {
        return s_best_ball_vel;
    }
    s_update_time = wm.time();

    //
    //
    //

    const int ANGLE_DIVS = 12;

    const ServerParam & SP = ServerParam::i();
    const PlayerType & ptype = wm.self().playerType();
    const double collide_dist2 = std::pow( ptype.playerSize()
                                           + SP.ballSize(),
                                           2 );
    const double keep_dist = ptype.playerSize()
        + ptype.kickableMargin() * 0.5
        + ServerParam::i().ballSize();

    const Vector2D next_self_pos
        = wm.self().pos() + wm.self().vel();
    const Vector2D next2_self_pos
        = next_self_pos
        + wm.self().vel() * ptype.playerDecay();

    //
    // create keep target point
    //

    Vector2D best_ball_vel = Vector2D::INVALIDATED;
    int best_opponent_step = 0;
    double best_ball_speed = 1000.0;


    for ( int a = 0; a < ANGLE_DIVS; ++a )
    {
        Vector2D keep_pos
            = next2_self_pos
            + Vector2D::from_polar( keep_dist,
                                    360.0/ANGLE_DIVS * a );
        if ( keep_pos.absX() > SP.pitchHalfLength() - 0.2
             || keep_pos.absY() > SP.pitchHalfWidth() - 0.2 )
        {
            continue;
        }

        Vector2D ball_move = keep_pos - wm.ball().pos();
        double ball_speed = ball_move.r() / ( 1.0 + SP.ballDecay() );

        Vector2D max_vel
            = KickTable::calc_max_velocity( ball_move.th(),
                                            wm.self().kickRate(),
                                            wm.ball().vel() );
        if ( max_vel.r2() < std::pow( ball_speed, 2 ) )
        {
            continue;
        }

        Vector2D ball_next_next = keep_pos;

        Vector2D ball_vel = ball_move.setLengthVector( ball_speed );
        Vector2D ball_next = wm.ball().pos() + ball_vel;

        if ( next_self_pos.dist2( ball_next ) < collide_dist2 )
        {
            ball_next_next = ball_next;
            ball_next_next += ball_vel * ( SP.ballDecay() * -0.1 );
        }

#ifdef DEBUG_PRINT
        dlog.addText( Logger::TEAM,
                      __FILE__": (getKeepBallVel) %d: ball_move th=%.1f speed=%.2f max=%.2f",
                      a,
                      ball_move.th().degree(),
                      ball_speed,
                      max_vel.r() );
        dlog.addText( Logger::TEAM,
                      __FILE__": __ ball_next=(%.2f %.2f) ball_next2=(%.2f %.2f)",
                      ball_next.x, ball_next.y,
                      ball_next_next.x, ball_next_next.y );
#endif

        //
        // check opponent
        //

        int min_step = 1000;
        for ( PlayerPtrCont::const_iterator o = wm.opponentsFromSelf().begin();
              o != wm.opponentsFromSelf().end();
              ++o )
        {
            if ( (*o)->distFromSelf() > 10.0 )
            {
                break;
            }

            int o_step = FieldAnalyzer::predict_player_reach_cycle( *o,
                                                                    ball_next_next,
                                                                    (*o)->playerTypePtr()->kickableArea(),
                                                                    0.0, // penalty distance
                                                                    1, // body count thr
                                                                    1, // default turn step
                                                                    0, // wait cycle
                                                                    true );

            if ( o_step <= 0 )
            {
                break;
            }

            if ( o_step < min_step )
            {
                min_step = o_step;
            }
        }
#ifdef DEBUG_PRINT
        dlog.addText( Logger::TEAM,
                      __FILE__": (getKeepBallVel) %d: keepPos=(%.2f %.2f)"
                      " ballNext2=(%.2f %.2f) ballVel=(%.2f %.2f) speed=%.2f o_step=%d",
                      a,
                      keep_pos.x, keep_pos.y,
                      ball_next_next.x, ball_next_next.y,
                      ball_vel.x, ball_vel.y,
                      ball_speed,
                      min_step );
#endif
        if ( min_step > best_opponent_step )
        {
            best_ball_vel = ball_vel;
            best_opponent_step = min_step;
            best_ball_speed = ball_speed;
        }
        else if ( min_step == best_opponent_step )
        {
            if ( best_ball_speed > ball_speed )
            {
                best_ball_vel = ball_vel;
                best_opponent_step = min_step;
                best_ball_speed = ball_speed;
            }
        }
    }

    s_best_ball_vel = best_ball_vel;
    return s_best_ball_vel;
}
/*!

 */
void
PredictState::init( const WorldModel & wm )
{
    //
    // initialize world
    //
    M_world = &wm;

    //
    // initialize spend_time
    //
    M_spend_time = 0;

    //
    // initialize ball pos & vel
    //
    M_ball.assign( wm.ball().pos(), wm.ball().vel() );

    //
    // initialize self_unum
    //
    M_self_unum = wm.self().unum();

    //
    // initialize ball holder
    //
    const AbstractPlayerObject * h = wm.getTeammateNearestToBall( VALID_PLAYER_THRESHOLD );

    if ( h
         && wm.ball().pos().dist2( h->pos() ) < wm.ball().pos().dist2( wm.self().pos() ) )
    {
        M_ball_holder_unum = h->unum();
    }
    else
    {
        M_ball_holder_unum = wm.self().unum();
    }

    //
    // initialize all teammates
    //
    M_our_players.reserve( 11 );

    for ( int n = 1; n <= 11; ++n )
    {
        PredictPlayerObject::Ptr ptr;

        if ( n == M_self_unum )
        {
            ptr = PredictPlayerObject::Ptr( new PredictPlayerObject( wm.self() ) );
        }
        else
        {
            const AbstractPlayerObject * t = wm.ourPlayer( n );

            if ( t )
            {
                ptr = PredictPlayerObject::Ptr( new PredictPlayerObject( *t ) );

            }
            else
            {
                ptr = PredictPlayerObject::Ptr( new PredictPlayerObject() );
            }
        }

        M_our_players.push_back( ptr );

#ifndef STRICT_LINE_UPDATE
        if ( ptr->isValid()
             && M_our_offense_player_line_x < ptr->pos().x )
        {
            M_our_offense_player_line_x = ptr->pos().x;
        }
#endif
    }

    updateLines();
}
Пример #5
0
/*!

 */
void
ShootGenerator::createShoot( const WorldModel & wm,
                             const Vector2D & target_point )
{
    const AngleDeg ball_move_angle = ( target_point - M_first_ball_pos ).th();

    const PlayerObject * goalie = wm.getOpponentGoalie();
    if ( goalie
         && 5 < goalie->posCount()
         && goalie->posCount() < 30
         && wm.dirCount( ball_move_angle ) > 3 )
    {
#ifdef DEBUG_PRINT
        dlog.addText( Logger::SHOOT,
                      "%d: __ xxx goalie_count=%d, low dir accuracy",
                      M_total_count,
                      goalie->posCount() );
#endif
        return;
    }

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

    const double ball_speed_max = ( wm.gameMode().type() == GameMode::PlayOn
                                    || wm.gameMode().isPenaltyKickMode()
                                    ? SP.ballSpeedMax()
                                    : wm.self().kickRate() * SP.maxPower() );

    const double ball_move_dist = M_first_ball_pos.dist( target_point );

    const Vector2D max_one_step_vel
        = ( wm.self().isKickable()
            ? KickTable::calc_max_velocity( ball_move_angle,
                                            wm.self().kickRate(),
                                            wm.ball().vel() )
            : ( target_point - M_first_ball_pos ).setLengthVector( 0.1 ) );
    const double max_one_step_speed = max_one_step_vel.r();

    double first_ball_speed
        = std::max( ( ball_move_dist + 5.0 ) * ( 1.0 - SP.ballDecay() ),
                    std::max( max_one_step_speed,
                              1.5 ) );

    bool over_max = false;
#ifdef DEBUG_PRINT_FAILED_COURSE
    bool success = false;
#endif
    while ( ! over_max )
    {
        if ( first_ball_speed > ball_speed_max - 0.001 )
        {
            over_max = true;
            first_ball_speed = ball_speed_max;
        }

        if ( createShoot( wm,
                          target_point,
                          first_ball_speed,
                          ball_move_angle,
                          ball_move_dist ) )
        {
            Course & course = M_courses.back();

            if ( first_ball_speed <= max_one_step_speed + 0.001 )
            {
                course.kick_step_ = 1;
            }

#ifdef DEBUG_PRINT_SUCCESS_COURSE
            dlog.addText( Logger::SHOOT,
                          "%d: ok shoot target=(%.2f %.2f)"
                          " speed=%.3f angle=%.1f",
                          M_total_count,
                          target_point.x, target_point.y,
                          first_ball_speed,
                          ball_move_angle.degree() );
            dlog.addRect( Logger::SHOOT,
                          target_point.x - 0.1, target_point.y - 0.1,
                          0.2, 0.2,
                          "#00ff00" );
            char num[8];
            snprintf( num, 8, "%d", M_total_count );
            dlog.addMessage( Logger::SHOOT,
                             target_point, num, "#ffffff" );
#endif
#ifdef DEBUG_PRINT_FAILED_COURSE
            success = true;
#endif
#ifdef SEARCH_UNTIL_MAX_SPEED_AT_SAME_POINT
            if ( course.goalie_never_reach_
                 && course.opponent_never_reach_ )
            {
                return;
            }
            ++M_total_count;
#else
            return;
#endif
        }

        first_ball_speed += 0.3;
    }

#ifdef DEBUG_PRINT_FAILED_COURSE
    if ( success )
    {
        return;
    }

    dlog.addText( Logger::SHOOT,
                  "%d: xxx shoot target=(%.2f %.2f)"
                  " speed=%.3f angle=%.1f",
                  M_total_count,
                  target_point.x, target_point.y,
                  first_ball_speed,
                  ball_move_angle.degree() );
    dlog.addRect( Logger::SHOOT,
                  target_point.x - 0.1, target_point.y - 0.1,
                  0.2, 0.2,
                  "#ff0000" );
    char num[8];
    snprintf( num, 8, "%d", M_total_count );
    dlog.addMessage( Logger::SHOOT,
                     target_point, num, "#ffffff" );
#endif
}
Пример #6
0
/*!

 */
void
ShootGenerator::generate( const WorldModel & wm, bool consider_shot_distance )
{
#ifdef __APPLE__
    static GameTime s_update_time( 0, 0 );
#else
    static thread_local GameTime s_update_time( 0, 0 );
#endif

    if ( s_update_time == wm.time() )
    {
        return;
    }
    s_update_time = wm.time();

    clear();

    if ( ! wm.self().isKickable()
         && wm.interceptTable()->selfReachCycle() > 1 )
    {
        return;
    }

    if ( wm.time().stopped() > 0
         || wm.gameMode().type() == GameMode::KickOff_
         // || wm.gameMode().type() == GameMode::KickIn_
         || wm.gameMode().type() == GameMode::IndFreeKick_ )
    {
        return;
    }

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

    if ( consider_shot_distance &&
         wm.self().pos().dist2( SP.theirTeamGoalPos() ) > std::pow( 30.0, 2 ) )
    {
#ifdef DEBUG_PRINT
      dlog.addText( Logger::SHOOT,
                    __FILE__": over shootable distance" );
#endif
      return;
    }

    M_first_ball_pos = ( wm.self().isKickable()
                         ? wm.ball().pos()
                         : wm.ball().pos() + wm.ball().vel() );

#ifdef DEBUG_PROFILE
    MSecTimer timer;
#endif

    Vector2D goal_l( SP.pitchHalfLength(), -SP.goalHalfWidth() );
    Vector2D goal_r( SP.pitchHalfLength(), +SP.goalHalfWidth() );

    goal_l.y += std::min( 1.5,
                          0.6 + goal_l.dist( M_first_ball_pos ) * 0.042 );
    goal_r.y -= std::min( 1.5,
                          0.6 + goal_r.dist( M_first_ball_pos ) * 0.042 );

    if ( wm.self().pos().x > SP.pitchHalfLength() - 1.0
         && wm.self().pos().absY() < SP.goalHalfWidth() )
    {
        goal_l.x = wm.self().pos().x + 1.5;
        goal_r.x = wm.self().pos().x + 1.5;
    }

    const int DIST_DIVS = 25;
    const double dist_step = std::fabs( goal_l.y - goal_r.y ) / ( DIST_DIVS - 1 );

#ifdef DEBUG_PRINT
    dlog.addText( Logger::SHOOT,
                  __FILE__": ===== Shoot search range=(%.1f %.1f)-(%.1f %.1f) dist_step=%.1f =====",
                  goal_l.x, goal_l.y, goal_r.x, goal_r.y, dist_step );
#endif

    for ( int i = 0; i < DIST_DIVS; ++i )
    {
        ++M_total_count;

        Vector2D target_point = goal_l;
        target_point.y += dist_step * i;

#ifdef DEBUG_PRINT
        dlog.addText( Logger::SHOOT,
                      "%d: ===== shoot target(%.2f %.2f) ===== ",
                      M_total_count,
                      target_point.x, target_point.y );
#endif
        createShoot( wm, target_point );
    }


    evaluateCourses( wm );


#ifdef DEBUG_PROFILE
    dlog.addText( Logger::SHOOT,
                  __FILE__": PROFILE %d/%d. elapsed=%.3f [ms]",
                  (int)M_courses.size(),
                  DIST_DIVS,
                  timer.elapsedReal() );
#endif

}
Пример #7
0
void
FullstateSensor::printWithWorld( const WorldModel & world ) const
{
    Vector2D tmpv;
    double tmpval;
    dlog.addText( Logger::WORLD,
                  "FS ball    (%+.3f %+.3f) (%+.3f %+.3f) %.3f",
                  ball().pos_.x, ball().pos_.y,
                  ball().vel_.x, ball().vel_.y,
                  ball().vel_.r() );
    dlog.addText( Logger::WORLD,
                  "____internal (%+.3f %+.3f) (%+.3f %+.3f) %.3f  gconf=%d rconf=%d",
                  world.ball().pos().x, world.ball().pos().y,
                  world.ball().vel().x, world.ball().vel().y,
                  world.ball().vel().r(),
                  world.ball().posCount(), world.ball().rposCount() );
    tmpv = ball().pos_ - world.ball().pos();
    dlog.addText( Logger::WORLD,
                  "__ball pos err (%+.3f %+.3f) %.3f",
                  tmpv.x, tmpv.y, tmpv.r() );
    dlog.addText( Logger::WORLD,
                  "____internal (%+.3f %+.3f)",
                  world.ball().posError().x, world.ball().posError().y );
    tmpv = ball().vel_ - world.ball().vel();
    tmpval = tmpv.r();
    dlog.addText( Logger::WORLD,
                  "__ball vel err (%+.3f %+.3f) %.3f  %s",
                  tmpv.x, tmpv.y, tmpval, (tmpval > 1.0 ? "big error" : "" ) );
    dlog.addText( Logger::WORLD,
                  "____internal (%+.3f %+.3f)",
                  world.ball().velError().x, world.ball().velError().y );

    const FullstateSensor::PlayerCont& player_cont
        = ( world.isOurLeft()
            ? leftTeam()
            : rightTeam() );
    for ( FullstateSensor::PlayerCont::const_iterator it = player_cont.begin();
          it != player_cont.end();
          ++it )
    {
        if ( it->unum_ == world.self().unum() )
        {
            dlog.addText( Logger::WORLD,
                          "FS self  (%+.3f %+.3f) (%+.3f %+.3f) b=%+.2f n=%+.2f f=%+.2f",
                          it->pos_.x, it->pos_.y,
                          it->vel_.x, it->vel_.y,
                          it->body_, it->neck_,
                          AngleDeg::normalize_angle( it->body_ + it->neck_ ) );

            dlog.addText( Logger::WORLD,
                          "____internal (%+.3f %+.3f) (%+.3f %+.3f) b=%+.2f n=%+.2f f=%+.2f",
                          world.self().pos().x, world.self().pos().y,
                          world.self().vel().x, world.self().vel().y,
                          world.self().body().degree(),
                          world.self().neck().degree(),
                          world.self().face().degree() );

            tmpv = it->pos_ - world.self().pos();
            double d = tmpv.r();
            dlog.addText( Logger::WORLD,
                          "__self pos err (%+.3f %+.3f) %.3f %s",
                          tmpv.x, tmpv.y, d, ( d > 0.3 ? "  big error" : "" ) );
            dlog.addText( Logger::WORLD,
                          "____internal (%+.3f %+.3f) %.3f",
                          world.self().posError().x,
                          world.self().posError().y,
                          world.self().posError().r() );
            tmpv = it->vel_ - world.self().vel();
            dlog.addText( Logger::WORLD,
                          "__self vel err (%+.3f %+.3f) %.3f",
                          tmpv.x, tmpv.y, tmpv.r() );
            dlog.addText( Logger::WORLD,
                          "____internal (%+.3f %+.3f) %.3f",
                          world.self().velError().x,
                          world.self().velError().y,
                          world.self().velError().r() );
            tmpv = ball().pos_ - it->pos_;
            dlog.addText( Logger::WORLD,
                          "__ball rpos (%+.3f %+.3f) %.3f",
                          tmpv.x, tmpv.y, tmpv.r() );
            dlog.addText( Logger::WORLD,
                          "____internal (%+.3f %+.3f) %.3f",
                          world.ball().rpos().x,
                          world.ball().rpos().y,
                          world.ball().rpos().r() );
            tmpv -= world.ball().rpos();
            dlog.addText( Logger::WORLD,
                          "__ball rpos err (%+.3f %+.3f) %.3f",
                          tmpv.x, tmpv.y, tmpv.r() );
            dlog.addText( Logger::WORLD,
                          "____internal (%+.3f %+.3f) %.3f",
                          world.ball().rposError().x,
                          world.ball().rposError().y,
                          world.ball().rposError().r() );
            break;
        }
    }
}
Пример #8
0
/*!

*/
void
DebugClient::toStr( const WorldModel & world,
                    const ActionEffector & effector )
{
    std::ostringstream ostr;

    ostr << "((debug (format-version 3)) (time "
         << world.time().cycle() << ")";


    // self
    /*
      SELF ::=  (s SIDE PLAYER_NUMBER POS_X POS_Y VEL_X VEL_Y
      BODY_DIRECTION FACE_DIRECTION  [(c "COMMENT")])
      where SIDE is 'l' or 'r'.
      where PLAYER_NUMBER is 1 to 11.
      where POS_X and POS_Y is absolute coordinate.
      where VEL_X and VEL_Y is absolute velocity.
      where BODY_DIRECTION is absolute player body direction (degree).
      where NECK_DIRECTION is body relative face direction (degree).
      This is equals to (absolute_face_direction - BODY_DIRECTION).
      where COMMENT is a string.
      Typically, it is used as information accuracy.
    */
    if ( world.self().posValid() )
    {
        ostr << " (s "
             << ( world.ourSide() == LEFT ? "l " : "r " )
             << world.self().unum() << ' '
             << ROUND(world.self().pos().x, 0.01) << ' '
             << ROUND(world.self().pos().y, 0.01) << ' '
             << ROUND(world.self().vel().x, 0.01) << ' '
             << ROUND(world.self().vel().y, 0.01) << ' '
             << ROUND(world.self().body().degree(), 0.1) << ' '
             << ROUND(world.self().neck().degree(), 0.1) << " (c \""
             << world.self().posCount() << ' '
            //<< '(' << ROUND(world.self().posError().x, 0.001)
            //<< ", " << ROUND(world.self().posError().y, 0.001) << ") "
             << world.self().velCount() << ' '
             << world.self().faceCount();
        if ( world.self().card() == YELLOW ) ostr << "y";
        ostr << "\"))";
    }

    // ball
    /*
      BALL_INFO ::=  (b POS_X POS_Y [VEL_X VEL_Y] [(c "COMMENT")])
    */
    if ( world.ball().posValid() )
    {
        ostr << " (b "
             << ROUND(world.ball().pos().x, 0.01) << ' '
             << ROUND(world.ball().pos().y, 0.01);
        if ( world.ball().velValid() )
        {
            ostr << ' ' << ROUND(world.ball().vel().x, 0.01)
                 << ' ' << ROUND(world.ball().vel().y, 0.01);
        }
        ostr << " (c \"g" << world.ball().posCount()
             << 'r' << world.ball().rposCount()
            //<< "(" << ROUND(world.ball().rpos().x, 0.01)
            // << ", " << ROUND(world.ball().rpos().y, 0.01) << ')'
             << 'v' << world.ball().velCount()
            //<< "(" << ROUND(world.ball().vel().x, 0.01)
            // << ", " << ROUND(world.ball().vel().y, 0.01) << ')'
             << "\"))";
    }

    // players
    /*
      PLAYER_INFO ::=  (TEAM [PLAYER_NUMBER] POS_X POS_Y
      [(bd BODY_DIRECTION)] [(c "COMMENT")])
      TEAM is one of follows.
      't' (teammate), 'o' (opponent),
      'u' (unknown), 'ut' (unknown teammate), 'ut' (unknown opponent).
      When TEAM is 't' or 'o', PLAYER_NUMBER must be specified.
      Otherwise PLAYER_NUMBER must not be specified.
      Body direction and comment is optional.
    */

    std::for_each( world.teammates().begin(),
                   world.teammates().end(),
                   PlayerPrinter( ostr, 't' ) );

    std::for_each( world.opponents().begin(),
                   world.opponents().end(),
                   PlayerPrinter( ostr, 'o' ) );

    std::for_each( world.unknownPlayers().begin(),
                   world.unknownPlayers().end(),
                   PlayerPrinter( ostr, 'u' ) );

    // say message
    if ( ! effector.getSayMessage().empty() )
    {
        ostr << " (say \"";
        for ( std::vector< const SayMessage * >::const_iterator it = effector.sayMessageCont().begin();
              it != effector.sayMessageCont().end();
              ++it )
        {
            (*it)->printDebug( ostr );
        }
        ostr << " {" << effector.getSayMessage() << "}\")";
    }

    // heard information
    if ( world.audioMemory().time() == world.time() )
    {
        ostr << " (hear ";
        world.audioMemory().printDebug( ostr );
        ostr << ')';
    }

    // target number
    if ( M_target_unum != Unum_Unknown )
    {
        ostr << " (target-teammate " << M_target_unum << ")";
    }

    // target point
    if ( M_target_point.isValid() )
    {
        ostr << " (target-point "
             << M_target_point.x << " " << M_target_point.y
             << ")";
    }

    // message
    if ( ! M_message.empty() )
    {
        ostr << " (message \"" << M_message << "\")";
    }

    // lines
    std::for_each( M_lines.begin(), M_lines.end(),
                   LinePrinter( ostr ) );
    // triangles
    std::for_each( M_triangles.begin(), M_triangles.end(),
                   TrianglePrinter( ostr ) );
    // rectangles
    std::for_each( M_rectangles.begin(), M_rectangles.end(),
                   RectPrinter( ostr ) );
    // circles
    std::for_each( M_circles.begin(), M_circles.end(),
                   CirclePrinter( ostr ) );

    ostr << ")";

    M_main_buffer.assign( ostr.str() );
}
Пример #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
}
Пример #10
0
/*!

 */
void
CrossGenerator::updatePasser( const WorldModel & wm )
{
    if ( wm.self().isKickable()
         && ! wm.self().isFrozen() )
    {
        M_passer = &wm.self();
        M_first_point = wm.ball().pos();
#ifdef DEBUG_UPDATE_PASSER
        dlog.addText( Logger::CROSS,
                      __FILE__" (updatePasser) self kickable." );
#endif
        return;
    }

    int s_min = wm.interceptTable()->selfReachCycle();
    int t_min = wm.interceptTable()->teammateReachCycle();
    int o_min = wm.interceptTable()->opponentReachCycle();

    int our_min = std::min( s_min, t_min );
    if ( o_min < std::min( our_min - 4, (int)rint( our_min * 0.9 ) ) )
    {
#ifdef DEBUG_UPDATE_PASSER
        dlog.addText( Logger::CROSS,
                      __FILE__" (updatePasser) opponent ball." );
#endif
        return;
    }

    if ( s_min <= t_min )
    {
        if ( s_min <= 2 )
        {
            M_passer = &wm.self();
            M_first_point = wm.ball().inertiaPoint( s_min );
        }
    }
    else
    {
        if ( t_min <= 2 )
        {
            M_passer = wm.interceptTable()->fastestTeammate();
            M_first_point = wm.ball().inertiaPoint( t_min );
        }
    }

    if ( ! M_passer )
    {
#ifdef DEBUG_UPDATE_PASSER
        dlog.addText( Logger::CROSS,
                      __FILE__" (updatePasser) no passer." );
#endif
        return;
    }

    if ( M_passer->unum() != wm.self().unum() )
    {
        if ( M_first_point.dist2( wm.self().pos() ) > std::pow( 20.0, 2 ) )
        {
            M_passer = static_cast< const AbstractPlayerObject * >( 0 );
#ifdef DEBUG_UPDATE_PASSER
            dlog.addText( Logger::CROSS,
                          __FILE__" (updatePasser) passer is too far." );
#endif
            return;
        }
    }

#ifdef DEBUG_UPDATE_PASSER
    dlog.addText( Logger::CROSS,
                  __FILE__" (updatePasser) passer=%d(%.1f %.1f) reachStep=%d startPos=(%.1f %.1f)",
                  M_passer->unum(),
                  M_passer->pos().x, M_passer->pos().y,
                  t_min,
                  M_first_point.x, M_first_point.y );
#endif
}
/*!

 */
void
TackleGenerator::calculate( const WorldModel & wm )
{
    const ServerParam & SP = ServerParam::i();

    const double min_angle = SP.minMoment();
    const double max_angle = SP.maxMoment();
    const double angle_step = std::fabs( max_angle - min_angle ) / ANGLE_DIVS;

#ifdef ASSUME_OPPONENT_KICK
    const Vector2D goal_pos = SP.ourTeamGoalPos();
    const bool shootable_area = ( wm.ball().pos().dist2( goal_pos ) < std::pow( 18.0, 2 ) );
    const Vector2D shoot_accel = ( goal_pos - wm.ball().pos() ).setLengthVector( 2.0 );
#endif

    const AngleDeg ball_rel_angle = wm.ball().angleFromSelf() - wm.self().body();
    const double tackle_rate
        = SP.tacklePowerRate()
        * ( 1.0 - 0.5 * ball_rel_angle.abs() / 180.0 );

#ifdef DEBUG_PRINT
    dlog.addText( Logger::CLEAR,
                  __FILE__": min_angle=%.1f max_angle=%.1f angle_step=%.1f",
                  min_angle, max_angle, angle_step );
    dlog.addText( Logger::CLEAR,
                  __FILE__": ball_rel_angle=%.1f tackle_rate=%.1f",
                  ball_rel_angle.degree(), tackle_rate );
#endif

    for ( int a = 0; a < ANGLE_DIVS; ++a )
    {
        const AngleDeg dir = min_angle + angle_step * a;

        double eff_power= ( SP.maxBackTacklePower()
                            + ( SP.maxTacklePower() - SP.maxBackTacklePower() )
                            * ( 1.0 - ( dir.abs() / 180.0 ) ) );
        eff_power *= tackle_rate;

        AngleDeg angle = wm.self().body() + dir;
        Vector2D accel = Vector2D::from_polar( eff_power, angle );

#ifdef ASSUME_OPPONENT_KICK
        if ( shootable_area
             && wm.existKickableOpponent() )
        {
            accel += shoot_accel;
            double d = accel.r();
            if ( d > SP.ballAccelMax() )
            {
                accel *= ( SP.ballAccelMax() / d );
            }
        }
#endif

        Vector2D vel = wm.ball().vel() + accel;

        double speed = vel.r();
        if ( speed > SP.ballSpeedMax() )
        {
            vel *= ( SP.ballSpeedMax() / speed );
        }

        M_candidates.push_back( TackleResult( angle, vel ) );
#ifdef DEBUG_PRINT
        const TackleResult & result = M_candidates.back();
        dlog.addText( Logger::CLEAR,
                      "%d: angle=%.1f(dir=%.1f), result: vel(%.2f %.2f ) speed=%.2f move_angle=%.1f",
                      a,
                      result.tackle_angle_.degree(), dir.degree(),
                      result.ball_vel_.x, result.ball_vel_.y,
                      result.ball_speed_, result.ball_move_angle_.degree() );
#endif
    }


    M_best_result.clear();

    const Container::iterator end = M_candidates.end();
    for ( Container::iterator it = M_candidates.begin();
          it != end;
          ++it )
    {
        it->score_ = evaluate( wm, *it );

#ifdef DEBUG_PRINT
        Vector2D ball_end_point = inertia_final_point( wm.ball().pos(),
                                                       it->ball_vel_,
                                                       SP.ballDecay() );
        dlog.addLine( Logger::CLEAR,
                      wm.ball().pos(),
                      ball_end_point,
                      "#0000ff" );
        char buf[16];
        snprintf( buf, 16, "%.3f", it->score_ );
        dlog.addMessage( Logger::CLEAR,
                         ball_end_point, buf, "#ffffff" );
#endif

        if ( it->score_ > M_best_result.score_ )
        {
#ifdef DEBUG_PRINT
            dlog.addText( Logger::CLEAR,
                          ">>>> updated" );
#endif
            M_best_result = *it;
        }
    }


#ifdef DEBUG_PRINT
    dlog.addLine( Logger::CLEAR,
                  wm.ball().pos(),
                  inertia_final_point( wm.ball().pos(),
                                       M_best_result.ball_vel_,
                                       SP.ballDecay() ),
                  "#ff0000" );
    dlog.addText( Logger::CLEAR,
                  "==== best_angle=%.1f score=%f speed=%.3f move_angle=%.1f",
                  M_best_result.tackle_angle_.degree(),
                  M_best_result.score_,
                  M_best_result.ball_speed_,
                  M_best_result.ball_move_angle_.degree() );
#endif
}
Пример #12
0
/*!

 */
void
Strategy::updatePosition( const WorldModel & wm )
{
    static GameTime s_update_time( 0, 0 );
    if ( s_update_time == wm.time() )
    {
        return;
    }
    s_update_time = wm.time();

    Formation::Ptr f = getFormation( wm );
    if ( ! f )
    {
        std::cerr << wm.teamName() << ':' << wm.self().unum() << ": "
                  << wm.time()
                  << " ***ERROR*** could not get the current formation" << std::endl;
        return;
    }

    int ball_step = 0;
    if ( wm.gameMode().type() == GameMode::PlayOn
         || wm.gameMode().type() == GameMode::GoalKick_ )
    {
        ball_step = std::min( 1000, wm.interceptTable()->teammateReachCycle() );
        ball_step = std::min( ball_step, wm.interceptTable()->opponentReachCycle() );
        ball_step = std::min( ball_step, wm.interceptTable()->selfReachCycle() );
    }

    Vector2D ball_pos = wm.ball().inertiaPoint( ball_step );

    dlog.addText( Logger::TEAM,
                  __FILE__": HOME POSITION: ball pos=(%.1f %.1f) step=%d",
                  ball_pos.x, ball_pos.y,
                  ball_step );

    M_positions.clear();
    f->getPositions( ball_pos, M_positions );

    if ( ServerParam::i().useOffside() )
    {
        double max_x = wm.offsideLineX();
        if ( ServerParam::i().kickoffOffside()
             && ( wm.gameMode().type() == GameMode::BeforeKickOff
                  || wm.gameMode().type() == GameMode::AfterGoal_ ) )
        {
            max_x = 0.0;
        }
        else
        {
            int mate_step = wm.interceptTable()->teammateReachCycle();
            if ( mate_step < 50 )
            {
                Vector2D trap_pos = wm.ball().inertiaPoint( mate_step );
                if ( trap_pos.x > max_x ) max_x = trap_pos.x;
            }

            max_x -= 1.0;
        }

        for ( int unum = 1; unum <= 11; ++unum )
        {
            if ( M_positions[unum-1].x > max_x )
            {
                dlog.addText( Logger::TEAM,
                              "____ %d offside. home_pos_x %.2f -> %.2f",
                              unum,
                              M_positions[unum-1].x, max_x );
                M_positions[unum-1].x = max_x;
            }
        }
    }

    M_position_types.clear();
    for ( int unum = 1; unum <= 11; ++unum )
    {
        PositionType type = Position_Center;
        if ( f->isSideType( unum ) )
        {
            type = Position_Left;
        }
        else if ( f->isSymmetryType( unum ) )
        {
            type = Position_Right;
        }

        M_position_types.push_back( type );

        dlog.addText( Logger::TEAM,
                      "__ %d home pos (%.2f %.2f) type=%d",
                      unum,
                      M_positions[unum-1].x, M_positions[unum-1].y,
                      type );
        dlog.addCircle( Logger::TEAM,
                        M_positions[unum-1], 0.5,
                        "#000000" );
    }
}
Пример #13
0
/*!

 */
double
Strategy::get_normal_dash_power( const WorldModel & wm )
{
    static bool s_recover_mode = false;

    if ( wm.self().staminaModel().capacityIsEmpty() )
    {
        return std::min( ServerParam::i().maxDashPower(),
                         wm.self().stamina() + wm.self().playerType().extraStamina() );
    }

    const int self_min = wm.interceptTable()->selfReachCycle();
    const int mate_min = wm.interceptTable()->teammateReachCycle();
    const int opp_min = wm.interceptTable()->opponentReachCycle();

    // check recover
    if ( wm.self().staminaModel().capacityIsEmpty() )
    {
        s_recover_mode = false;
    }
    else if ( wm.self().stamina() < ServerParam::i().staminaMax() * 0.5 )
    {
        s_recover_mode = true;
    }
    else if ( wm.self().stamina() > ServerParam::i().staminaMax() * 0.7 )
    {
        s_recover_mode = false;
    }

    /*--------------------------------------------------------*/
    double dash_power = ServerParam::i().maxDashPower();
    const double my_inc
        = wm.self().playerType().staminaIncMax()
        * wm.self().recovery();

    if ( wm.ourDefenseLineX() > wm.self().pos().x
         && wm.ball().pos().x < wm.ourDefenseLineX() + 20.0 )
    {
        dlog.addText( Logger::TEAM,
                      __FILE__": (get_normal_dash_power) correct DF line. keep max power" );
        // keep max power
        dash_power = ServerParam::i().maxDashPower();
    }
    else if ( s_recover_mode )
    {
        dash_power = my_inc - 25.0; // preffered recover value
        if ( dash_power < 0.0 ) dash_power = 0.0;

        dlog.addText( Logger::TEAM,
                      __FILE__": (get_normal_dash_power) recovering" );
    }
    // exist kickable teammate
    else if ( wm.existKickableTeammate()
              && wm.ball().distFromSelf() < 20.0 )
    {
        dash_power = std::min( my_inc * 1.1,
                               ServerParam::i().maxDashPower() );
        dlog.addText( Logger::TEAM,
                      __FILE__": (get_normal_dash_power) exist kickable teammate. dash_power=%.1f",
                      dash_power );
    }
    // in offside area
    else if ( wm.self().pos().x > wm.offsideLineX() )
    {
        dash_power = ServerParam::i().maxDashPower();
        dlog.addText( Logger::TEAM,
                      __FILE__": in offside area. dash_power=%.1f",
                      dash_power );
    }
    else if ( wm.ball().pos().x > 25.0
              && wm.ball().pos().x > wm.self().pos().x + 10.0
              && self_min < opp_min - 6
              && mate_min < opp_min - 6 )
    {
        dash_power = bound( ServerParam::i().maxDashPower() * 0.1,
                            my_inc * 0.5,
                            ServerParam::i().maxDashPower() );
        dlog.addText( Logger::TEAM,
                      __FILE__": (get_normal_dash_power) opponent ball dash_power=%.1f",
                      dash_power );
    }
    // normal
    else
    {
        dash_power = std::min( my_inc * 1.7,
                               ServerParam::i().maxDashPower() );
        dlog.addText( Logger::TEAM,
                      __FILE__": (get_normal_dash_power) normal mode dash_power=%.1f",
                      dash_power );
    }

    return dash_power;
}