Example #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
Example #2
0
    def utility(self, bot) -> float:

        if self.temp_utility_desire_boost > 0:
            self.temp_utility_desire_boost = max(
                0, self.temp_utility_desire_boost - bot.info.dt)
        elif self.temp_utility_desire_boost < 0:
            self.temp_utility_desire_boost = min(
                0, self.temp_utility_desire_boost + bot.info.dt)

        ball_soon = predict.ball_predict(bot, 1)

        arena_length2 = bot.info.team_sign * Field.LENGTH / 2
        own_half_01 = clip01(
            remap(arena_length2, -arena_length2, 0.0, 1.1, ball_soon.pos.y))

        reachable_ball = predict.ball_predict(
            bot, predict.time_till_reach_ball(bot.info.my_car, bot.info.ball))
        self.ball_to_goal_right = bot.info.enemy_goal_right - reachable_ball.pos
        self.ball_to_goal_left = bot.info.enemy_goal_left - reachable_ball.pos
        self.aim_cone = AimCone(self.ball_to_goal_right,
                                self.ball_to_goal_left)
        car_to_ball = reachable_ball.pos - bot.info.my_car.pos
        in_position = self.aim_cone.contains_direction(car_to_ball)

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

        return clip01(own_half_01 + 0.1 * in_position +
                      self.temp_utility_desire_boost + kickoff_bias01)
Example #3
0
    def any_touch(self, bot, time: float, dodge_hit: bool = True):

        ball_soon = ball_predict(bot, time)
        car_to_ball = ball_soon.pos - bot.info.my_car.pos

        return self.towards(bot, ball_soon.pos + car_to_ball, time,
                            dodge_hit) or SimpleControllerState()
Example #4
0
    def towards(self, bot, target: Vec3, time: float, allowed_uncertainty: float = 0.3, dodge_hit: bool = True):

        ball_soon = ball_predict(bot, time)
        ball_soon_to_target_dir = normalize(target - ball_soon.pos)
        right = dot(axis_to_rotation(Vec3(z=allowed_uncertainty)), ball_soon_to_target_dir)
        left = dot(axis_to_rotation(Vec3(z=-allowed_uncertainty)), ball_soon_to_target_dir)
        aim_cone = AimCone(right, left)

        aim_cone.draw(ball_soon.pos, r=0, g=0)

        return self.with_aiming(bot, aim_cone, time, dodge_hit)
Example #5
0
    def utility(self, bot) -> float:
        team_sign = bot.info.team_sign

        length = team_sign * Field.LENGTH / 2
        ball_own_half_01 = clip01(
            remap(-length, length, -0.2, 1.2, bot.info.ball.pos.y))

        reachable_ball = predict.ball_predict(
            bot, predict.time_till_reach_ball(bot.info.my_car, bot.info.ball))
        car_to_ball = reachable_ball.pos - bot.info.my_car.pos
        in_position = self.aim_cone.contains_direction(car_to_ball,
                                                       math.pi / 8)

        return ball_own_half_01 * in_position
Example #6
0
    def utility_score(self, bot) -> float:
        team_sign = bot.info.team_sign

        length = team_sign * Field.LENGTH2
        ball_own_half_01 = clip01(remap(-length, length, -0.8, 1.8, bot.info.ball.pos.y))

        reachable_ball = predict.ball_predict(bot, predict.time_till_reach_ball(bot.info.my_car, bot.info.ball))
        car_to_ball = reachable_ball.pos - bot.info.my_car.pos
        in_position = self.aim_cone.contains_direction(car_to_ball, math.pi / 8)

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

        return ball_own_half_01 * in_position * obj_bonus
Example #7
0
    def run(self, bot) -> SimpleControllerState:

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

        hits_goal_prediction = predict.will_ball_hit_goal(bot)
        reach_time = clip(predict.time_till_reach_ball(car, ball), 0,
                          hits_goal_prediction.time - 0.5)
        reachable_ball = predict.ball_predict(bot, reach_time)
        self.ball_to_goal_right = bot.info.own_goal.right_post - reachable_ball.pos
        self.ball_to_goal_left = bot.info.own_goal.left_post - reachable_ball.pos
        self.aim_cone = AimCone(self.ball_to_goal_left,
                                self.ball_to_goal_right)

        self.aim_cone.draw(reachable_ball.pos, r=200, g=0, b=160)

        shoot_controls = bot.shoot.with_aiming(bot, self.aim_cone, reach_time)

        if not bot.shoot.can_shoot:
            # Go home
            return bot.drive.home(bot)
        else:
            return shoot_controls
Example #8
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)
Example #9
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
Example #10
0
    def exec(self, bot):

        if not self.announced_in_quick_chat:
            self.announced_in_quick_chat = True
            bot.send_quick_chat(QuickChats.CHAT_EVERYONE, QuickChats.Information_IGotIt)

        ct = bot.info.time
        car = bot.info.my_car
        up = car.up
        controls = SimpleControllerState()

        # Time remaining till intercept time
        T = self.intercept_time - bot.info.time
        # Expected future position
        xf = car.pos + car.vel * T + 0.5 * GRAVITY * T ** 2
        # Expected future velocity
        vf = car.vel + GRAVITY * T

        # Is set to false while jumping to avoid FeelsBackFlipMan
        rotate = True

        if self.jumping:
            if self.jump_begin_time == -1:
                jump_elapsed = 0
                self.jump_begin_time = ct
            else:
                jump_elapsed = ct - self.jump_begin_time

            # How much longer we can press jump and still gain upward force
            tau = JUMP_MAX_DUR - jump_elapsed

            # Add jump pulse
            if jump_elapsed == 0:
                vf += up * JUMP_SPEED
                xf += up * JUMP_SPEED * T
                rotate = False

            # Acceleration from holding jump
            vf += up * JUMP_SPEED * tau
            xf += up * JUMP_SPEED * tau * (T - 0.5 * tau)

            if self.do_second_jump:
                # Impulse from the second jump
                vf += up * JUMP_SPEED
                xf += up * JUMP_SPEED * (T - tau)

            if jump_elapsed < JUMP_MAX_DUR:
                controls.jump = True
            else:
                controls.jump = False
                if self.do_second_jump:
                    if self.jump_pause_counter < 4:
                        # Do a 4-tick pause between jumps
                        self.jump_pause_counter += 1
                    else:
                        # Time to start second jump
                        # we do this by resetting our jump counter and pretend and our aerial started in the air
                        self.jump_begin_time = -1
                        self.jumping = True
                        self.do_second_jump = False
                else:
                    # We are done jumping
                    self.jumping = False
        else:
            controls.jump = False

        delta_pos = self.hit_pos - xf
        direction = normalize(delta_pos)
        car_to_hit_pos = self.hit_pos - car.pos

        dodging = self.dodge_begin_time != -1
        if dodging:
            controls.jump = True

        # We are not pressing jump, so let's align the car
        if rotate and not dodging:

            if self.do_dodge and norm(car_to_hit_pos) < Ball.RADIUS + 80:
                # Start dodge

                self.dodge_begin_time = ct

                hit_local = dot(car_to_hit_pos, car.rot)
                hit_local.z = 0

                dodge_direction = normalize(hit_local)

                controls.roll = 0
                controls.pitch = -dodge_direction.x
                controls.yaw = sign(car.rot.get(2, 2)) * direction.y
                controls.jump = True

            else:
                # Adjust orientation
                if norm(delta_pos) > 50:
                    pd = bot.fly.align(bot, looking_in_dir(delta_pos))
                else:
                    if self.target_rot is not None:
                        pd = bot.fly.align(bot, self.target_rot)
                    else:
                        pd = bot.fly.align(bot, looking_in_dir(self.hit_pos - car.pos))

                controls.roll = pd.roll
                controls.pitch = pd.pitch
                controls.yaw = pd.yaw

        if not dodging and angle_between(car.forward, direction) < 0.3:
            if norm(delta_pos) > 40:
                controls.boost = 1
                controls.throttle = 0
            else:
                controls.boost = 0
                controls.throttle = clip01(0.5 * THROTTLE_AIR_ACCEL * T ** 2)
        else:
            controls.boost = 0
            controls.throttle = 0

        prediction = predict.ball_predict(bot, T)
        self.done = T < 0
        if norm(self.hit_pos - prediction.pos) > 50:
            # Jump shot failed
            self.done = True
            bot.send_quick_chat(QuickChats.CHAT_EVERYONE, QuickChats.Apologies_Cursing)

        if bot.do_rendering:
            car_to_hit_dir = normalize(self.hit_pos - car.pos)
            color = bot.renderer.pink()
            rendering.draw_cross(bot, self.hit_pos, color, arm_length=100)
            rendering.draw_circle(bot, lerp(car.pos, self.hit_pos, 0.25), car_to_hit_dir, 40, 12, color)
            rendering.draw_circle(bot, lerp(car.pos, self.hit_pos, 0.5), car_to_hit_dir, 40, 12, color)
            rendering.draw_circle(bot, lerp(car.pos, self.hit_pos, 0.75), car_to_hit_dir, 40, 12, color)
            bot.renderer.draw_line_3d(car.pos, self.hit_pos, color)

        return controls
Example #11
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
Example #12
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
Example #13
0
    def exec(self, bot):
        pred_ball = predict.ball_predict(bot, bot.info.my_car.reach_ball_time)

        # On a scale from 0 to 1, how much is this a clear?
        clear01 = clip01(
            norm(bot.info.opp_goal.pos - pred_ball.pos) / Field.LENGTH)**2

        ts = bot.info.team_sign
        right = lerp(bot.info.opp_goal.right_post,
                     Vec3(ts * Field.WIDTH2, ts * (Field.LENGTH2 + 300), 0),
                     clear01)
        left = lerp(bot.info.opp_goal.left_post,
                    Vec3(-ts * Field.WIDTH2, ts * (Field.LENGTH2 + 300), 0),
                    clear01)

        ball_to_right = right - pred_ball.pos
        ball_to_left = left - pred_ball.pos

        aim_cone = AimCone(ball_to_right, ball_to_left)
        shot_ctrls = bot.shoot.with_aiming(bot, aim_cone,
                                           bot.info.my_car.reach_ball_time)

        if bot.shoot.can_shoot:
            aim_cone.draw(bot.shoot.ball_when_hit.pos, b=0, r=0)

        if not bot.shoot.can_shoot:
            # We can't shoot on target
            if len(bot.info.teammates) != 0:
                # Consider passing
                for mate in bot.info.teammates:
                    point_in_front_of_mate = lerp(mate.pos,
                                                  bot.info.opp_goal.pos, 0.5)
                    shot_ctrls = bot.shoot.towards(
                        bot, point_in_front_of_mate,
                        bot.info.my_car.reach_ball_time)
                    if bot.shoot.can_shoot:
                        draw.cross(point_in_front_of_mate, draw.green())
                        return shot_ctrls

            # Atba with bias I guess
            draw.line(bot.info.my_car.pos, pred_ball.pos, bot.renderer.red())
            return bot.shoot.any_touch(bot, bot.info.my_car.reach_ball_time)

            # # We are out of position, start rotating back
            # own_goal = lerp(bot.info.own_goal.pos, bot.info.ball.pos, 0.5)
            # return bot.drive.towards_point(
            #     bot,
            #     own_goal,
            #     target_vel=1460,
            #     slide=False,
            #     boost_min=0,
            #     can_keep_speed=True
            # )
        else:
            # Shoot!
            if bot.shoot.using_curve:
                draw.bezier([
                    bot.info.my_car.pos, bot.shoot.curve_point,
                    bot.shoot.ball_when_hit.pos
                ])
            return shot_ctrls