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