/*! */ Strategy::BallArea Strategy::get_ball_area( const WorldModel & wm ) { int ball_step = 1000; ball_step = std::min( ball_step, wm.interceptTable()->teammateReachCycle() ); ball_step = std::min( ball_step, wm.interceptTable()->opponentReachCycle() ); ball_step = std::min( ball_step, wm.interceptTable()->selfReachCycle() ); return get_ball_area( wm.ball().inertiaPoint( ball_step ) ); }
/*! */ void Strategy::updateSituation( const WorldModel & wm ) { M_current_situation = Normal_Situation; if ( wm.gameMode().type() != GameMode::PlayOn ) { if ( wm.gameMode().isPenaltyKickMode() ) { dlog.addText( Logger::TEAM, __FILE__": Situation PenaltyKick" ); M_current_situation = PenaltyKick_Situation; } else if ( wm.gameMode().isPenaltyKickMode() ) { dlog.addText( Logger::TEAM, __FILE__": Situation OurSetPlay" ); M_current_situation = OurSetPlay_Situation; } else { dlog.addText( Logger::TEAM, __FILE__": Situation OppSetPlay" ); M_current_situation = OppSetPlay_Situation; } return; } int self_min = wm.interceptTable()->selfReachCycle(); int mate_min = wm.interceptTable()->teammateReachCycle(); int opp_min = wm.interceptTable()->opponentReachCycle(); int our_min = std::min( self_min, mate_min ); if ( opp_min <= our_min - 2 ) { dlog.addText( Logger::TEAM, __FILE__": Situation Defense" ); M_current_situation = Defense_Situation; return; } if ( our_min <= opp_min - 2 ) { dlog.addText( Logger::TEAM, __FILE__": Situation Offense" ); M_current_situation = Offense_Situation; return; } dlog.addText( Logger::TEAM, __FILE__": Situation Normal" ); }
/*! */ 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 }
/*! */ double Neck_ScanPlayers::calculate_score( const WorldModel & wm, const Vector2D & next_self_pos, const AngleDeg & left_angle, const AngleDeg & right_angle ) { double score = 0.0; double view_buffer = 90.0; const int our_min = std::min( wm.interceptTable()->selfReachCycle(), wm.interceptTable()->teammateReachCycle() ); const int opp_min = wm.interceptTable()->opponentReachCycle(); const bool our_ball = ( our_min <= opp_min ); const AbstractPlayerCont::const_iterator end = wm.allPlayers().end(); for ( AbstractPlayerCont::const_iterator p = wm.allPlayers().begin(); p != end; ++p ) { if ( (*p)->isSelf() ) continue; Vector2D pos = (*p)->pos() + (*p)->vel(); AngleDeg angle = ( pos - next_self_pos ).th(); if ( ! angle.isRightOf( left_angle ) || ! angle.isLeftOf( right_angle ) ) { continue; } double pos_count = (*p)->seenPosCount(); if ( (*p)->isGhost() && (*p)->ghostCount() % 2 == 1 ) { pos_count = std::min( 2.0, pos_count ); } pos_count += 1.0; if ( our_ball ) { if ( (*p)->side() == wm.ourSide() && ( (*p)->pos().x > wm.ball().pos().x - 10.0 || (*p)->pos().x > 30.0 ) ) { pos_count *= 2.0; } } double base_val = std::pow( pos_count, 2 ); double rate = std::exp( - std::pow( (*p)->distFromSelf(), 2 ) / ( 2.0 * std::pow( 20.0, 2 ) ) ); // Magic Number score += base_val * rate; double buf = std::min( ( angle - left_angle ).abs(), ( angle - right_angle ).abs() ); #ifdef DEBUG_PRINT dlog.addText( Logger::ACTION, "__ %c_%d (%.2f %.2f) count=%d base=%f rate=%f +%f buf=%.1f", (*p)->side() == LEFT ? 'L' : (*p)->side() == RIGHT ? 'R' : 'N', (*p)->unum(), (*p)->pos().x, (*p)->pos().y, (*p)->posCount(), base_val, rate, base_val * rate, buf ); #endif if ( buf < view_buffer ) { view_buffer = buf; } } // The bigger view buffer, the bigger rate // range: [1.0:2.0] // double rate = 2.0 - std::exp( - std::pow( view_buffer, 2 ) // / ( 2.0 * std::pow( 180.0, 2 ) ) ); // Magic Number double rate = 1.0 + view_buffer / 90.0; #ifdef DEBUG_PRINT dlog.addText( Logger::ACTION, "base_score=%.1f view_buf=%.1f rate=%f -> %f", score, view_buffer, rate, score * rate ); #endif score *= rate; return score; }
/*! */ 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 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" ); } }
/*! */ 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; }