コード例 #1
0
    def utility_score(self, bot) -> float:

        car = bot.info.my_car
        ball = bot.info.ball

        my_hit_time = predict.time_till_reach_ball(car, ball)
        ball_soon = predict.ball_predict(bot, min(my_hit_time, 1.0))

        close_to_ball_01 = clip01(1.0 - norm(car.pos - ball_soon.pos) / 3500) ** 0.5  # FIXME Not great

        reachable_ball = predict.ball_predict(bot, predict.time_till_reach_ball(bot.info.my_car, ball))
        xy_ball_to_goal = xy(bot.info.opp_goal.pos - reachable_ball.pos)
        xy_car_to_ball = xy(reachable_ball.pos - bot.info.my_car.pos)
        in_position_01 = ease_out(clip01(dot(xy_ball_to_goal, xy_car_to_ball)), 0.5)

        # Chase ball right after kickoff. High right after kickoff
        kickoff_bias01 = max(0, 1 - bot.info.time_since_last_kickoff * 0.3) * float(bot.info.my_car.objective == Objective.UNKNOWN)

        obj_bonus = {
            Objective.UNKNOWN: 1,
            Objective.GO_FOR_IT: 1,
            Objective.FOLLOW_UP: 0,
            Objective.ROTATING: 0,
            Objective.SOLO: 1,
        }[bot.info.my_car.objective]

        return clip01(close_to_ball_01 * in_position_01 + kickoff_bias01) * obj_bonus
コード例 #2
0
    def find_landing_orientation(car: Car) -> Mat33:

        # FIXME: This uses a cheap approximation of the walls to find landing orientation

        obj = DummyObject(car)
        prev_pos = obj.pos
        for i in range(100):
            predict.fall(obj, 0.1)

            # Checking for intersections
            for plane in Field.SIDE_WALLS_AND_GROUND:
                if intersects_plane(prev_pos, obj.pos, plane):
                    # Bingo!
                    fall_dir = normalize(obj.pos - prev_pos)
                    left = -cross(fall_dir, plane.normal)
                    forward = -cross(plane.normal, left)

                    return Mat33.from_columns(forward, left, plane.normal)

            prev_pos = obj.pos

        # No wall/ground intersections found in fall
        # Default to looking in direction of velocity, but upright

        forward = normalize(xy(
            car.vel)) if norm(xy(car.vel)) > 20 else car.forward
        up = Vec3(z=1)
        left = cross(up, forward)

        return Mat33.from_columns(forward, left, up)
コード例 #3
0
    def get_goto_point(self, bot, src, point):
        point = xy(point)
        desired_dir = self.get_center_dir()

        desired_dir_inv = -1 * desired_dir
        car_pos = xy(src)
        point_to_car = car_pos - point

        ang_to_desired_dir = angle_between(desired_dir_inv, point_to_car)

        ANG_ROUTE_ACCEPTED = math.pi / 4.3
        can_go_straight = abs(ang_to_desired_dir) < self.span_size() / 2.0
        can_with_route = abs(
            ang_to_desired_dir) < self.span_size() / 2.0 + ANG_ROUTE_ACCEPTED
        point = point + desired_dir_inv * 50
        if can_go_straight:
            return point, 1.0
        elif can_with_route:
            ang_to_right = abs(angle_between(point_to_car,
                                             -1 * self.right_dir))
            ang_to_left = abs(angle_between(point_to_car, -1 * self.left_dir))
            closest_dir = self.right_dir if ang_to_right < ang_to_left else self.left_dir

            goto = curve_from_arrival_dir(car_pos, point, closest_dir)

            goto.x = clip(goto.x, -Field.WIDTH / 2, Field.WIDTH / 2)
            goto.y = clip(goto.y, -Field.LENGTH / 2, Field.LENGTH / 2)

            draw.line(car_pos, goto, draw.color(150, 150, 150))
            draw.line(point, goto, draw.color(150, 150, 150))
            draw.bezier([car_pos, goto, point], draw.grey())

            return goto, 0.5
        else:
            return None, 1
コード例 #4
0
    def find_landing_orientation(car: Car, num_points: int) -> Mat33:
        """
        dummy = DummyObject(car)
        trajectory = [Vec3(dummy.pos)]

        for i in range(0, num_points):
            fall(dummy, 0.0333)  # Apply physics and let car fall through the air
            trajectory.append(Vec3(dummy.pos))
            up = dummy.pitch_surface_normal()
            if norm(up) > 0.0 and i > 10:
                up = normalize(up)
                forward = normalize(dummy.vel - dot(dummy.vel, up) * up)
                left = cross(up, forward)

                return Mat33.from_columns(forward, left, up)

        return Mat33(car.rot)
        """

        forward = normalize(xy(
            car.vel)) if norm(xy(car.vel)) > 20 else car.forward
        up = Vec3(z=1)
        left = cross(up, forward)

        return Mat33.from_columns(forward, left, up)
コード例 #5
0
    def find_landing_orientation(car: Car) -> Mat33:

        # FIXME: If we knew the arena's mesh we could test if we are landing on a wall or something

        forward = normalize(xy(
            car.vel)) if norm(xy(car.vel)) > 20 else car.forward
        up = Vec3(z=1)
        left = cross(up, forward)

        return Mat33.from_columns(forward, left, up)
コード例 #6
0
ファイル: carry.py プロジェクト: DanielDowns/RLBotPack
    def utility_score(self, bot) -> float:
        car = bot.info.my_car
        ball = bot.info.ball

        car_to_ball = car.pos - ball.pos

        bouncing_b = ball.pos.z > 130 or abs(ball.vel.z) > 300
        if not bouncing_b:
            return 0

        dist_01 = clip01(1 - norm(car_to_ball) / 3000)

        head_dir = lerp(Vec3(0, 0, 1), car.forward, 0.13)
        ang = angle_between(head_dir, car_to_ball)
        ang_01 = clip01(1 - ang / (math.pi / 2))
        xy_speed_delta_01 = lin_fall(norm(xy(car.vel - ball.vel)), 800)

        obj_bonus = {
            Objective.UNKNOWN: 0.8,
            Objective.GO_FOR_IT: 1.0,
            Objective.FOLLOW_UP: 0,
            Objective.ROTATING: 0,
            Objective.SOLO: 1.0,
        }[car.objective]

        return obj_bonus * clip01(xy_speed_delta_01 * ang_01 * dist_01 +
                                  self.is_dribbling * self.extra_utility_bias)
コード例 #7
0
    def find_landing_orientation(car: Car, num_points: int) -> Mat33:
        dummy = DummyObject(car)

        for i in range(0, num_points):
            fall(dummy,
                 0.0333)  # Apply physics and let car fall through the air

            if i > 5 and sdf_contains(dummy.pos):
                up = normalize(sdf_normal(dummy.pos))
                left = cross(normalize(dummy.vel), up)
                forward = cross(up, left)

                return Mat33.from_columns(forward, left, up)

        forward = normalize(xy(
            car.vel)) if norm(xy(car.vel)) > 20 else car.forward
        up = Vec3(z=1)
        left = cross(up, forward)

        return Mat33.from_columns(forward, left, up)
コード例 #8
0
ファイル: predict.py プロジェクト: RLBot/RLBotPack
def time_till_reach_ball(car, ball):
    """ Rough estimate about when we can reach the ball in 2d. """
    car_to_ball = xy(ball.pos - car.pos)
    dist = norm(car_to_ball) - Ball.RADIUS / 2
    vel_c_f = proj_onto_size(car.vel, car_to_ball)
    vel_b_f = proj_onto_size(ball.vel, car_to_ball)
    vel_c_amp = lerp(vel_c_f, norm(car.vel), 0.58)
    vel_f = vel_c_amp - vel_b_f
    dist_long_01 = clip01(dist / 10_000.0)
    time_normal = dist / max(220, vel_f)
    time_long = dist / max(norm(car.vel), 1410)
    time = lerp(time_normal, time_long, dist_long_01)
    arrive_time = time * 0.85
    # Combine slightly with old prediction to negative rapid changes
    result = lerp(arrive_time, car.last_expected_time_till_reach_ball, 0.22)
    car.last_expected_time_till_reach_ball = arrive_time
    return result
コード例 #9
0
    def exec(self, bot):

        car = bot.info.my_car
        ball = bot.info.ball

        car_to_ball = ball.pos - car.pos
        ball_to_enemy_goal = bot.info.enemy_goal - ball.pos
        own_goal_to_ball = ball.pos - bot.info.own_goal
        dist = norm(car_to_ball)

        offence = ball.pos.y * bot.info.team_sign < 0
        dot_enemy = dot(car_to_ball, ball_to_enemy_goal)
        dot_own = dot(car_to_ball, own_goal_to_ball)
        right_side_of_ball = dot_enemy > 0 if offence else dot_own > 0

        if right_side_of_ball:
            # Aim cone
            dir_to_post_1 = (bot.info.enemy_goal +
                             Vec3(3800, 0, 0)) - bot.info.ball.pos
            dir_to_post_2 = (bot.info.enemy_goal +
                             Vec3(-3800, 0, 0)) - bot.info.ball.pos
            cone = AimCone(dir_to_post_1, dir_to_post_2)
            cone.get_goto_point(bot, car.pos, bot.info.ball.pos)
            if bot.do_rendering:
                cone.draw(bot, bot.info.ball.pos)

            # Chase ball
            return bot.drive.go_towards_point(bot,
                                              xy(ball.pos),
                                              2000,
                                              True,
                                              True,
                                              can_dodge=dist > 2200)
        else:
            # Go home
            return bot.drive.go_towards_point(bot, bot.info.own_goal_field,
                                              2000, True, True)
コード例 #10
0
    def run(self, bot) -> SimpleControllerState:

        car = bot.info.my_car
        ball = bot.info.ball

        my_hit_time = predict.time_till_reach_ball(car, ball)
        reachable_ball = predict.ball_predict(bot, predict.time_till_reach_ball(car, ball))
        ball_to_goal_right = bot.info.opp_goal.right_post - reachable_ball.pos
        ball_to_goal_left = bot.info.opp_goal.left_post - reachable_ball.pos
        aim_cone = AimCone(ball_to_goal_right, ball_to_goal_left)
        shoot_controls = bot.shoot.with_aiming(bot, aim_cone, my_hit_time)

        hit_pos = bot.shoot.ball_when_hit.pos
        dist = norm(car.pos - hit_pos)
        closest_enemy, enemy_dist = bot.info.closest_enemy(0.5 * (hit_pos + ball.pos))

        if not bot.shoot.can_shoot and is_closer_to_goal_than(car.pos, hit_pos, bot.info.team):
            # Can't shoot but or at least on the right side: Chase

            goal_to_ball = normalize(hit_pos - bot.info.opp_goal.pos)
            offset_ball = hit_pos + goal_to_ball * Ball.RADIUS * 0.9
            enemy_hit_time = predict.time_till_reach_ball(closest_enemy, ball)
            enemy_hit_pos = predict.ball_predict(bot, enemy_hit_time).pos
            if enemy_hit_time < 1.5 * my_hit_time:
                if bot.do_rendering:
                    bot.renderer.draw_line_3d(closest_enemy.pos, enemy_hit_pos, bot.renderer.red())
                return bot.drive.home(bot)

            if bot.do_rendering:
                bot.renderer.draw_line_3d(car.pos, offset_ball, bot.renderer.yellow())

            return bot.drive.towards_point(bot, offset_ball, target_vel=2200, slide=False, boost_min=0)

        elif len(bot.info.teammates) == 0 and not bot.shoot.aim_is_ok and hit_pos.y * -bot.info.team_sign > 4250 and abs(hit_pos.x) > 900 and not dist < 420:
            # hit_pos is an enemy corner and we are not close: Avoid enemy corners in 1s and just wait

            enemy_to_ball = normalize(hit_pos - closest_enemy.pos)
            wait_point = hit_pos + enemy_to_ball * enemy_dist  # a point 50% closer to the center of the field
            wait_point = lerp(wait_point, ball.pos + Vec3(0, bot.info.team_sign * 3000, 0), 0.5)

            if bot.do_rendering:
                bot.renderer.draw_line_3d(car.pos, wait_point, bot.renderer.yellow())

            return bot.drive.towards_point(bot, wait_point, norm(car.pos - wait_point), slide=False, can_keep_speed=True, can_dodge=False)

        elif bot.shoot.can_shoot:

            # Shoot !
            if bot.do_rendering:
                aim_cone.draw(bot, bot.shoot.ball_when_hit.pos, r=0, b=0)
                if bot.shoot.using_curve:
                    rendering.draw_bezier(bot, [car.pos, bot.shoot.curve_point, hit_pos])
            return shoot_controls

        else:
            # We can't shoot at goal reliably
            # How about a shot to the corners then?
            corners = [
                Vec3(-Field.WIDTH2, -bot.info.team_sign * Field.LENGTH2, 0),
                Vec3(Field.WIDTH2, -bot.info.team_sign * Field.LENGTH2, 0),
            ]
            for corner in corners:
                ctrls = bot.shoot.towards(bot, corner, bot.info.my_car.reach_ball_time)
                if bot.shoot.can_shoot:
                    aim_cone.draw(bot, bot.shoot.ball_when_hit.pos, b=0)
                    if bot.shoot.using_curve:
                        rendering.draw_bezier(bot, [car.pos, bot.shoot.curve_point, hit_pos])
                    return ctrls

            enemy_to_ball = normalize(xy(ball.pos - closest_enemy.pos))
            ball_to_my_goal = normalize(xy(bot.info.own_goal.pos - ball.pos))
            dot_threat = dot(enemy_to_ball, ball_to_my_goal)  # 1 = enemy is in position, -1 = enemy is NOT in position

            if car.boost <= 10 and ball.pos.y * bot.info.team_sign < 0 and dot_threat < 0.15:
                collect_center = ball.pos.y * bot.info.team_sign <= 0
                collect_small = closest_enemy.pos.y * bot.info.team_sign <= 0 or enemy_dist < 900
                pads = filter_pads(bot, bot.info.big_boost_pads, big_only=not collect_small, enemy_side=False,
                                   center=collect_center)
                bot.maneuver = CollectClosestBoostManeuver(bot, pads)

            # return home-ish
            return bot.drive.stay_at(bot, lerp(bot.info.own_goal.pos, ball.pos, 0.2), ball.pos)
コード例 #11
0
    def exec(self, bot) -> SimpleControllerState:

        car = bot.info.my_car
        ball = bot.info.ball

        my_hit_time = predict.time_till_reach_ball(car, ball)
        shoot_controls = bot.shoot.with_aiming(bot, self.aim_cone, my_hit_time)
        if bot.do_rendering:
            self.aim_cone.draw(bot, bot.shoot.ball_when_hit.pos, b=0)

        hit_pos = bot.shoot.ball_when_hit.pos
        dist = norm(car.pos - hit_pos)
        closest_enemy, enemy_dist = bot.info.closest_enemy(
            0.5 * (hit_pos + ball.pos))

        if not bot.shoot.can_shoot and is_closer_to_goal_than(
                car.pos, hit_pos, bot.info.team):
            # Can't shoot but or at least on the right side: Chase

            goal_to_ball = normalize(hit_pos - bot.info.enemy_goal)
            offset_ball = hit_pos + goal_to_ball * Ball.RADIUS * 0.9
            enemy_hit_time = predict.time_till_reach_ball(closest_enemy, ball)
            enemy_hit_pos = predict.ball_predict(bot, enemy_hit_time).pos
            if enemy_hit_time < 1.5 * my_hit_time:
                self.temp_utility_desire_boost -= bot.info.dt
                if bot.do_rendering:
                    bot.renderer.draw_line_3d(closest_enemy.pos, enemy_hit_pos,
                                              bot.renderer.red())
                return bot.drive.go_home(bot)

            if bot.do_rendering:
                bot.renderer.draw_line_3d(car.pos, offset_ball,
                                          bot.renderer.yellow())

            return bot.drive.go_towards_point(bot,
                                              offset_ball,
                                              target_vel=2200,
                                              slide=False,
                                              boost_min=0)

        elif not bot.shoot.aim_is_ok and hit_pos.y * -bot.info.team_sign > 4250 and abs(
                hit_pos.x) > 900 and not dist < 420:
            # hit_pos is an enemy corner and we are not close: Avoid enemy corners and just wait

            enemy_to_ball = normalize(hit_pos - closest_enemy.pos)
            wait_point = hit_pos + enemy_to_ball * enemy_dist  # a point 50% closer to the center of the field
            wait_point = lerp(wait_point,
                              ball.pos + Vec3(0, bot.info.team_sign * 3000, 0),
                              0.5)

            if bot.do_rendering:
                bot.renderer.draw_line_3d(car.pos, wait_point,
                                          bot.renderer.yellow())

            return bot.drive.go_towards_point(bot,
                                              wait_point,
                                              norm(car.pos - wait_point),
                                              slide=False,
                                              can_keep_speed=True,
                                              can_dodge=False)

        elif not bot.shoot.can_shoot:

            enemy_to_ball = normalize(xy(ball.pos - closest_enemy.pos))
            ball_to_my_goal = normalize(xy(bot.info.own_goal - ball.pos))
            dot_threat = dot(
                enemy_to_ball, ball_to_my_goal
            )  # 1 = enemy is in position, -1 = enemy is NOT in position

            if car.boost == 0 and ball.pos.y * bot.info.team_sign < 500 and dot_threat < 0.1:

                collect_center = ball.pos.y * bot.info.team_sign <= 0
                collect_small = closest_enemy.pos.y * bot.info.team_sign <= 0 or enemy_dist < 900
                pads = filter_pads(bot,
                                   bot.info.big_boost_pads,
                                   big_only=not collect_small,
                                   enemy_side=False,
                                   center=collect_center)
                bot.maneuver = CollectClosestBoostManeuver(bot, pads)
            # return home
            return bot.drive.go_home(bot)

        else:
            # Shoot !
            if bot.shoot.using_curve and bot.do_rendering:
                rendering.draw_bezier(
                    bot, [car.pos, bot.shoot.curve_point, hit_pos])
            return shoot_controls
コード例 #12
0
ファイル: drive.py プロジェクト: RLBot/RLBotPack
    def towards_point(self,
                      bot,
                      point: Vec3,
                      target_vel=1430,
                      slide=False,
                      boost_min=101,
                      can_keep_speed=True,
                      can_dodge=True,
                      wall_offset_allowed=125) -> SimpleControllerState:
        REQUIRED_ANG_FOR_SLIDE = 1.65
        REQUIRED_VELF_FOR_DODGE = 1100

        car = bot.info.my_car

        # Dodge is done
        if self.dodge is not None and self.dodge.done:
            self.dodge = None
            self.last_dodge_end_time = bot.info.time
        # Continue dodge
        elif self.dodge is not None:
            self.dodge.target = point
            return self.dodge.exec(bot)

        # Begin recovery
        if not car.on_ground:
            bot.maneuver = RecoveryManeuver()
            return self.controls

        # Get down from wall by choosing a point close to ground
        if not is_near_wall(point, wall_offset_allowed) and angle_between(
                car.up, Vec3(0, 0, 1)) > math.pi * 0.31:
            point = lerp(xy(car.pos), xy(point), 0.5)

        # If the car is in a goal, avoid goal posts
        self._avoid_goal_post(bot, point)

        car_to_point = point - car.pos

        # The vector from the car to the point in local coordinates:
        # point_local.x: how far in front of my car
        # point_local.y: how far to the left of my car
        # point_local.z: how far above my car
        point_local = dot(point - car.pos, car.rot)

        # Angle to point in local xy plane and other stuff
        angle = math.atan2(point_local.y, point_local.x)
        dist = norm(point_local)
        vel_f = proj_onto_size(car.vel, car.forward)
        vel_towards_point = proj_onto_size(car.vel, car_to_point)

        # Start dodge
        if can_dodge and abs(angle) <= 0.02 and vel_towards_point > REQUIRED_VELF_FOR_DODGE\
                and dist > vel_towards_point + 500 + 900 and bot.info.time > self.last_dodge_end_time + self.dodge_cooldown:
            self.dodge = DodgeManeuver(bot, point)
        # Start half-flip
        elif can_dodge and abs(angle) >= 3 and vel_towards_point < 0\
                and dist > -vel_towards_point + 500 + 900 and bot.info.time > self.last_dodge_end_time + self.dodge_cooldown:
            self.dodge = HalfFlipManeuver(bot,
                                          boost=car.boost > boost_min + 10)

        # Is point right behind? Maybe reverse instead
        if -100 < point_local.x < 0 and abs(point_local.y) < 50:
            #bot.print("Reversing?")
            pass

        # Is in turn radius deadzone?
        tr = turn_radius(abs(vel_f + 50))  # small bias
        tr_side = sign(angle)
        tr_center_local = Vec3(0, tr * tr_side, 10)
        point_is_in_turn_radius_deadzone = norm(point_local -
                                                tr_center_local) < tr
        # Draw turn radius deadzone
        if car.on_ground and False:
            tr_center_world = car.pos + dot(car.rot, tr_center_local)
            tr_center_world_2 = car.pos + dot(car.rot, -1 * tr_center_local)
            color = draw.orange()
            draw.circle(tr_center_world, car.up, tr, color)
            draw.circle(tr_center_world_2, car.up, tr, color)

        if point_is_in_turn_radius_deadzone:
            # Hard turn
            self.controls.steer = sign(angle)
            self.controls.boost = False
            self.controls.throttle = 0 if vel_f > 150 else 0.1
            if point_local.x < 110 and point_local.y < 400 and norm(
                    car.vel) < 300:
                # Brake or go backwards when the point is really close but not in front of us
                self.controls.throttle = clip(-0.25 + point_local.x / -110.0,
                                              0, -1)
                self.controls.steer = -0.5 * sign(angle)

        else:
            # Should drop speed or just keep up the speed?
            if can_keep_speed and target_vel < vel_towards_point:
                target_vel = vel_towards_point
            else:
                # Small lerp adjustment
                target_vel = lerp(vel_towards_point, target_vel, 1.1)

            # Turn and maybe slide
            self.controls.steer = clip(angle + (2.5 * angle)**3, -1.0, 1.0)
            if slide and abs(angle) > REQUIRED_ANG_FOR_SLIDE:
                self.controls.handbrake = True
                self.controls.steer = sign(angle)
            else:
                self.controls.handbrake = False

            # Overshoot target vel for quick adjustment
            target_vel = lerp(vel_towards_point, target_vel, 1.2)

            # Find appropriate throttle/boost
            if vel_towards_point < target_vel:
                self.controls.throttle = 1
                if boost_min < car.boost and vel_towards_point + 80 < target_vel and target_vel > 1400 \
                        and not self.controls.handbrake and is_heading_towards(angle, dist):
                    self.controls.boost = True
                else:
                    self.controls.boost = False

            else:
                vel_delta = target_vel - vel_towards_point
                self.controls.throttle = clip(0.2 + vel_delta / 500, 0, -1)
                self.controls.boost = False
                if self.controls.handbrake:
                    self.controls.throttle = min(0.4, self.controls.throttle)

        # Saved if something outside calls start_dodge() in the meantime
        self.last_point = point

        return self.controls
コード例 #13
0
    def update(self, bot):
        ball = bot.info.ball

        # Find closest foe to ball
        self.opp_closest_to_ball, self.opp_closest_to_ball_dist = argmin(bot.info.opponents, lambda opp: norm(opp.pos - ball.pos))

        # Possession and on/off-site
        self.car_with_possession = None
        self.ally_with_possession = None
        self.opp_with_possession = None
        for car in bot.info.cars:

            # Effective position
            car.effective_pos = car.pos + xy(car.vel) * 0.8

            # On site
            car_to_ball = ball.pos - car.pos
            car_to_ball_unit = normalize(car_to_ball)
            car.onsite = dot(Vec3(y=-car.team_sign), car_to_ball_unit)

            # Reach ball time
            car.reach_ball_time = predict.time_till_reach_ball(car, ball)
            reach01 = 1 - 0.9 * lin_fall(car.reach_ball_time, 4) ** 0.5

            # Possession
            point_in_front = car.pos + car.vel * 0.5
            ball_point_dist = norm(ball.pos - point_in_front)
            dist01 = 1000 / (1000 + ball_point_dist)  # Halved after 1000 uu of dist, 1/3 at 2000
            in_front01 = (dot(car.forward, car_to_ball_unit) + 1) / 2.0
            car.possession = dist01 * in_front01 * reach01
            if self.car_with_possession is None or car.possession > self.car_with_possession.possession:
                self.car_with_possession = car
            if car.team == bot.team and (self.ally_with_possession is None or car.possession > self.ally_with_possession.possession):
                self.ally_with_possession = car
            if car.team != bot.team and (self.opp_with_possession is None or car.possession > self.opp_with_possession.possession):
                self.opp_with_possession = car

        # Objectives
        if len(bot.info.team_cars) == 1:
            # No team mates. No roles
            bot.info.my_car.objective = bot.info.my_car.last_objective = Objective.SOLO
            return

        for car in bot.info.cars:
            car.last_objective = car.objective
            car.objective = Objective.UNKNOWN

        attacker, attacker_score = argmax(bot.info.team_cars,
                                          lambda ally: ((1.0 if ally.last_objective == Objective.GO_FOR_IT else 0.73)
                                                        * ease_out(0.2 + 0.8 * ally.boost / 100, 2)  # 50 boost is 0.85, 0 boost is 0.2
                                                        * ally.possession
                                                        * ally.got_it_according_to_quick_chat_01(bot.info.time)
                                                        * (1.0 if ally.onsite else 0.5)
                                                        * (0 if ally.is_demolished else 1)))

        attacker.objective = Objective.GO_FOR_IT
        self.ideal_follow_up_pos = xy(ball.pos + bot.info.own_goal.pos) * 0.5
        follower, follower_score = argmax([ally for ally in bot.info.team_cars if ally.objective == Objective.UNKNOWN],
                                          lambda ally: (1.0 if ally.last_objective == Objective.FOLLOW_UP else 0.73)
                                                        * ease_out(0.2 * 0.8 * ally.boost / 100, 2)
                                                        * (1 + ally.onsite / 2)
                                                        * lin_fall(norm(ally.effective_pos - self.ideal_follow_up_pos), 3000)
                                                        * (0 if ally.is_demolished else 1))
        if follower is not None:
            follower.objective = Objective.FOLLOW_UP
        for car in bot.info.team_cars:
            if car.objective == Objective.UNKNOWN:
                car.objective = Objective.ROTATING
コード例 #14
0
ファイル: shots.py プロジェクト: RLBot/RLBotPack
    def with_aiming(self, bot, aim_cone: AimCone, time: float, dodge_hit: bool = True):

        #       aim: |           |           |           |
        #  ball      |   bad     |    ok     |   good    |
        # z pos:     |           |           |           |
        # -----------+-----------+-----------+-----------+
        #  too high  |   give    |   give    |   wait/   |
        #   > 1200   |    up     |    up     |  improve  |
        # -----------+ - - - - - + - - - - - + - - - - - +
        #   medium   |   give    |  improve  |  aerial   |
        #            |    up     |    aim    |           |
        # -----------+ - - - - - + - - - - - + - - - - - +
        #   soon on  |  improve  |  slow     |   small   |
        #   ground   |    aim    |  curve    |   jump    |
        # -----------+ - - - - - + - - - - - + - - - - - +
        #  on ground |  improve  |  fast     |  fast     |
        #            |   aim??   |  curve    |  straight |
        # -----------+ - - - - - + - - - - - + - - - - - +

        # FIXME if the ball is not on the ground we treat it as 'soon on ground' in all other cases

        self.controls = SimpleControllerState()
        self.aim_is_ok = False
        self.waits_for_fall = False
        self.ball_is_flying = False
        self.can_shoot = False
        self.using_curve = False
        self.curve_point = None
        car = bot.info.my_car

        ball_soon = ball_predict(bot, time)
        car_to_ball_soon = ball_soon.pos - car.pos
        dot_facing_score = dot(normalize(car_to_ball_soon), normalize(car.forward))
        dot_facing_score_2d = dot(normalize(xy(car_to_ball_soon)), normalize(xy(car.forward)))
        vel_towards_ball_soon = proj_onto_size(car.vel, car_to_ball_soon)
        is_facing = 0.1 < dot_facing_score
        is_facing_2d = 0.3 < dot_facing_score

        self.ball_when_hit = ball_soon

        if ball_soon.pos.z < 110:

            # The ball is on the ground

            if 110 < ball_soon.pos.z:  # and ball_soon.vel.z <= 0:
                # The ball is slightly in the air, lets wait just a bit more
                self.waits_for_fall = True
                ball_landing = next_ball_landing(bot, ball_soon, size=100)
                time = time + ball_landing.time
                ball_soon = ball_predict(bot, time)
                car_to_ball_soon = ball_soon.pos - car.pos

            self.ball_when_hit = ball_soon

            # The ball is on the ground, are we in position for a shot?
            if aim_cone.contains_direction(car_to_ball_soon) and is_facing:

                # Straight shot

                self.aim_is_ok = True
                self.can_shoot = True

                if norm(car_to_ball_soon) < 400 + Ball.RADIUS and aim_cone.contains_direction(car_to_ball_soon)\
                        and vel_towards_ball_soon > 300:
                    bot.drive.start_dodge(bot, towards_ball=True)

                offset_point = xy(ball_soon.pos) - 50 * aim_cone.get_center_dir()
                speed = self._determine_speed(norm(car_to_ball_soon), time)
                self.controls = bot.drive.towards_point(bot, offset_point, target_vel=speed, slide=True, boost_min=0, can_keep_speed=False)
                return self.controls

            elif aim_cone.contains_direction(car_to_ball_soon, math.pi / 5):

                # Curve shot

                self.aim_is_ok = True
                self.using_curve = True
                self.can_shoot = True

                offset_point = xy(ball_soon.pos) - 50 * aim_cone.get_center_dir()
                closest_dir = aim_cone.get_closest_dir_in_cone(car_to_ball_soon)
                self.curve_point = curve_from_arrival_dir(car.pos, offset_point, closest_dir)

                self.curve_point.x = clip(self.curve_point.x, -Field.WIDTH / 2, Field.WIDTH / 2)
                self.curve_point.y = clip(self.curve_point.y, -Field.LENGTH / 2, Field.LENGTH / 2)

                if dodge_hit and norm(car_to_ball_soon) < 400 + Ball.RADIUS and angle_between(car.forward, car_to_ball_soon) < 0.5\
                        and aim_cone.contains_direction(car_to_ball_soon) and vel_towards_ball_soon > 300:
                    bot.drive.start_dodge(bot, towards_ball=True)

                speed = self._determine_speed(norm(car_to_ball_soon), time)
                self.controls = bot.drive.towards_point(bot, self.curve_point, target_vel=speed, slide=True, boost_min=0, can_keep_speed=False)
                return self.controls

            else:

                # We are NOT in position!
                return None

        elif ball_soon.pos.z < 600 and ball_soon.vel.z <= 0:

            # Ball is on ground soon. Is it worth waiting? TODO if aim is bad, do a slow curve - or delete case?
            pass

        # ---------------------------------------
        # Ball is in the air, or going in the air

        if 200 < ball_soon.pos.z < 1400 and aim_cone.contains_direction(car_to_ball_soon) and is_facing_2d:

            # Can we hit it if we make jump shot or aerial shot?

            vel_f = proj_onto_size(car.vel, xy(car_to_ball_soon))
            aerial = ball_soon.pos.z > 750

            if vel_f > 400:  # Some forward momentum is required

                flat_dist = norm(xy(car_to_ball_soon))
                # This range should be good https://www.desmos.com/calculator/bx9imtiqi5
                good_height = 0.3 * ball_soon.pos.z < flat_dist < 4 * ball_soon.pos.z

                if good_height:

                    # Alternative ball positions
                    alternatives = [
                        (ball_predict(bot, time * 0.8), time * 0.8),
                        (ball_predict(bot, time * 0.9), time * 0.9),
                        (ball_soon, time),
                        (ball_predict(bot, time * 1.1), time * 1.1),
                        (ball_predict(bot, time * 1.2), time * 1.2)
                    ]

                    for alt_ball, alt_time in alternatives:

                        potential_small_jump_shot = JumpShotManeuver(bot, alt_ball.pos, bot.info.time + alt_time, do_second_jump=aerial)
                        jump_shot_viable = potential_small_jump_shot.is_viable(car, bot.info.time)

                        if jump_shot_viable:
                            self.can_shoot = True
                            self.aim_is_ok = True
                            bot.maneuver = potential_small_jump_shot
                            return bot.maneuver.exec(bot)

        self.ball_is_flying = True
        return self.controls
コード例 #15
0
    def with_aiming(self,
                    bot,
                    aim_cone: AimCone,
                    time: float,
                    dodge_hit: bool = True):

        #       aim: |           |           |           |
        #  ball      |   bad     |    ok     |   good    |
        # z pos:     |           |           |           |
        # -----------+-----------+-----------+-----------+
        #  too high  |   give    |   give    |   wait/   |
        #            |    up     |    up     |  improve  |
        # -----------+ - - - - - + - - - - - + - - - - - +
        #   medium   |   give    |  improve  |  aerial   |
        #            |    up     |    aim    |           |
        # -----------+ - - - - - + - - - - - + - - - - - +
        #   soon on  |  improve  |  slow     |   small   |
        #   ground   |    aim    |  curve    |   jump    |
        # -----------+ - - - - - + - - - - - + - - - - - +
        #  on ground |  improve  |  fast     |  fast     |
        #            |   aim??   |  curve    |  straight |
        # -----------+ - - - - - + - - - - - + - - - - - +

        # FIXME if the ball is not on the ground we treat it as 'soon on ground' in all other cases

        self.controls = SimpleControllerState()
        self.aim_is_ok = False
        self.waits_for_fall = False
        self.ball_is_flying = False
        self.can_shoot = False
        self.using_curve = False
        self.curve_point = None
        self.ball_when_hit = None
        car = bot.info.my_car

        ball_soon = ball_predict(bot, time)
        car_to_ball_soon = ball_soon.pos - car.pos
        dot_facing_score = dot(normalize(car_to_ball_soon),
                               normalize(car.forward))
        vel_towards_ball_soon = proj_onto_size(car.vel, car_to_ball_soon)
        is_facing = 0 < dot_facing_score

        if ball_soon.pos.z < 110 or (ball_soon.pos.z < 475 and ball_soon.vel.z
                                     <= 0) or True:  #FIXME Always true

            # The ball is on the ground or soon on the ground

            if 275 < ball_soon.pos.z < 475 and aim_cone.contains_direction(
                    car_to_ball_soon):
                # Can we hit it if we make a small jump?
                vel_f = proj_onto_size(car.vel, xy(car_to_ball_soon))
                car_expected_pos = car.pos + car.vel * time
                ball_soon_flat = xy(ball_soon.pos)
                diff = norm(car_expected_pos - ball_soon_flat)
                ball_in_front = dot(ball_soon.pos - car_expected_pos,
                                    car.vel) > 0

                if bot.do_rendering:
                    bot.renderer.draw_line_3d(car.pos, car_expected_pos,
                                              bot.renderer.lime())
                    bot.renderer.draw_rect_3d(car_expected_pos, 12, 12, True,
                                              bot.renderer.lime())

                if vel_f > 400:
                    if diff < 150 and ball_in_front:
                        bot.maneuver = SmallJumpManeuver(
                            bot, lambda b: b.info.ball.pos)

            if 110 < ball_soon.pos.z:  # and ball_soon.vel.z <= 0:
                # The ball is slightly in the air, lets wait just a bit more
                self.waits_for_fall = True
                ball_landing = next_ball_landing(bot, ball_soon, size=100)
                time = time + ball_landing.time
                ball_soon = ball_predict(bot, time)
                car_to_ball_soon = ball_soon.pos - car.pos

            self.ball_when_hit = ball_soon

            # The ball is on the ground, are we in position for a shot?
            if aim_cone.contains_direction(car_to_ball_soon) and is_facing:

                # Straight shot

                self.aim_is_ok = True
                self.can_shoot = True

                if norm(car_to_ball_soon) < 240 + Ball.RADIUS and aim_cone.contains_direction(car_to_ball_soon)\
                        and vel_towards_ball_soon > 300:
                    bot.drive.start_dodge(bot)

                offset_point = xy(
                    ball_soon.pos) - 50 * aim_cone.get_center_dir()
                speed = self.determine_speed(norm(car_to_ball_soon), time)
                self.controls = bot.drive.go_towards_point(
                    bot,
                    offset_point,
                    target_vel=speed,
                    slide=True,
                    boost_min=0,
                    can_keep_speed=False)
                return self.controls

            elif aim_cone.contains_direction(car_to_ball_soon, math.pi / 5):

                # Curve shot

                self.aim_is_ok = True
                self.using_curve = True
                self.can_shoot = True

                offset_point = xy(
                    ball_soon.pos) - 50 * aim_cone.get_center_dir()
                closest_dir = aim_cone.get_closest_dir_in_cone(
                    car_to_ball_soon)
                self.curve_point = curve_from_arrival_dir(
                    car.pos, offset_point, closest_dir)

                self.curve_point.x = clip(self.curve_point.x, -Field.WIDTH / 2,
                                          Field.WIDTH / 2)
                self.curve_point.y = clip(self.curve_point.y,
                                          -Field.LENGTH / 2, Field.LENGTH / 2)

                if dodge_hit and norm(car_to_ball_soon) < 240 + Ball.RADIUS and angle_between(car.forward, car_to_ball_soon) < 0.5\
                        and aim_cone.contains_direction(car_to_ball_soon) and vel_towards_ball_soon > 300:
                    bot.drive.start_dodge(bot)

                speed = self.determine_speed(norm(car_to_ball_soon), time)
                self.controls = bot.drive.go_towards_point(
                    bot,
                    self.curve_point,
                    target_vel=speed,
                    slide=True,
                    boost_min=0,
                    can_keep_speed=False)
                return self.controls

            else:

                # We are NOT in position!
                self.aim_is_ok = False

                pass

        else:

            if aim_cone.contains_direction(car_to_ball_soon):
                self.waits_for_fall = True
                self.aim_is_ok = True
                #self.can_shoot = False
                pass  # Allow small aerial (wait if ball is too high)

            elif aim_cone.contains_direction(car_to_ball_soon, math.pi / 4):
                self.ball_is_flying = True
                pass  # Aim is ok, but ball is in the air