Esempio n. 1
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.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.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
Esempio n. 2
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/   |
        #   > 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