Beispiel #1
0
    def exec(self, bot):

        goal_to_ball = bot.info.ball.pos - bot.info.own_goal.pos
        goal_to_car = bot.info.my_car.pos - bot.info.own_goal.pos

        car_prj = proj_onto(goal_to_car, goal_to_ball)
        target = lerp(bot.info.own_goal.pos + car_prj,
                      lerp(bot.info.ball.pos, bot.info.opp_goal.pos, 0.4),
                      0.08)

        if bot.do_rendering:
            bot.renderer.draw_line_3d(bot.info.my_car.pos, target,
                                      bot.renderer.purple())

        speed = max(
            (norm(bot.info.my_car.pos - bot.info.ball.pos) - 900) * 0.6, 100)

        return bot.drive.towards_point(
            bot,
            target,
            target_vel=speed,
            slide=True,
            boost_min=0,
            can_keep_speed=norm(bot.info.my_car.pos - bot.info.ball.pos) >
            3000,
            can_dodge=True,
            wall_offset_allowed=125)
Beispiel #2
0
    def exec(self, bot) -> SimpleControllerState:
        car = bot.info.my_car
        shoot_controls = bot.shoot.with_aiming(
            bot, self.aim_cone,
            predict.time_till_reach_ball(bot.info.my_car, bot.info.ball))
        hit_pos = bot.shoot.ball_when_hit.pos

        if bot.do_rendering:
            self.aim_cone.draw(bot, hit_pos, r=0, g=170, b=255)

        if bot.shoot.can_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

        else:
            # go home-ish
            own_goal = lerp(bot.info.own_goal, bot.info.ball.pos, 0.5)
            return bot.drive.go_towards_point(bot,
                                              own_goal,
                                              target_vel=1460,
                                              slide=True,
                                              boost_min=0,
                                              can_keep_speed=True)
Beispiel #3
0
    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.1)
        ang = angle_between(head_dir, car_to_ball)
        ang_01 = clip01(1 - ang / (math.pi / 2))

        obj_bonus = {
            Objective.UNKNOWN: 0,
            Objective.GO_FOR_IT: 0.2,
            Objective.FOLLOW_UP: 0,
            Objective.ROTATE_BACK_OR_DEF: 0,
        }[car.objective]

        return clip01(0.6 * ang_01 + 0.4 * dist_01
                      #  - 0.3 * bot.analyzer.team_mate_has_ball_01
                      + self.is_dribbling * self.extra_utility_bias +
                      obj_bonus)
Beispiel #4
0
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.95
    # 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
Beispiel #5
0
    def approach_defensively(self, bot) -> SimpleControllerState:
        car = bot.data.my_car
        ball = bot.data.ball
        goal = Vec3(y=5400 * bot.data.team_sign)

        self.target = lerp(ball.pos, goal, 0.8)
        self.target_vel = norm(self.target - car.pos)

        return super().exec(bot)
Beispiel #6
0
    def run(self, bot) -> SimpleControllerState:

        car = bot.info.my_car
        ball = bot.info.ball
        half_way = lerp(bot.info.own_goal.pos, ball.pos, 0.5)
        dist_ball = norm(car.pos - ball.pos)

        return bot.drive.towards_point(
            bot,
            half_way,
            target_vel=dist_ball * 0.3,
            slide=dist_ball > 1500,
            can_dodge=False
        )
Beispiel #7
0
    def utility_score(self, bot) -> float:

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

        half_way = lerp(bot.info.own_goal.pos, ball.pos, 0.5)
        _, missing_center_guy01 = argmin(bot.info.team_cars, lambda mate: 1.0 - clip01(norm(mate.pos - half_way) / Field.LENGTH2))
        attack_in_front = any(is_closer_to_goal_than(car.pos, mate.pos, car.team) for mate in bot.info.teammates if mate.objective == Objective.GO_FOR_IT)
        ball_in_front = is_closer_to_goal_than(car.pos, ball.pos, car.team)

        obj_bonus = {
            Objective.UNKNOWN: 0,
            Objective.GO_FOR_IT: 0,
            Objective.FOLLOW_UP: 0.23,
            Objective.ROTATE_BACK_OR_DEF: 0,
        }[car.objective]

        return attack_in_front * ball_in_front * missing_center_guy01 + obj_bonus
Beispiel #8
0
    def utility(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.1)
        ang = angle_between(head_dir, car_to_ball)
        ang_01 = clip01(1 - ang / (math.pi / 2))

        return clip01(0.6 * ang_01 + 0.4 * dist_01
                      #  - 0.3 * bot.analyzer.team_mate_has_ball_01
                      + self.is_dribbling * self.extra_utility_bias)
Beispiel #9
0
    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(bot)
            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 < 50\
                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 bot.do_rendering:
            tr_center_world = car.pos + dot(car.rot, tr_center_local)
            tr_center_world_2 = car.pos + dot(car.rot, -1 * tr_center_local)
            rendering.draw_circle(bot, tr_center_world, car.up, tr, 22)
            rendering.draw_circle(bot, tr_center_world_2, car.up, tr, 22)

        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
Beispiel #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)
        shoot_controls = bot.shoot.with_aiming(bot, self.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:
                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.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:
                self.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:
                    self.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)
Beispiel #11
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.do_rendering:
            if bot.shoot.can_shoot:
                aim_cone.draw(bot, 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:
                        if bot.do_rendering:
                            rendering.draw_cross(bot, point_in_front_of_mate,
                                                 bot.renderer.green())
                        return shot_ctrls

            # Atba with bias I guess
            if bot.do_rendering:
                bot.renderer.draw_line_3d(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 and bot.do_rendering:
                rendering.draw_bezier(bot, [
                    bot.info.my_car.pos, bot.shoot.curve_point,
                    bot.shoot.ball_when_hit.pos
                ])
            return shot_ctrls
Beispiel #12
0
    def exec(self, bot) -> SimpleControllerState:

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

        shoot_controls = bot.shoot.with_aiming(
            bot, self.aim_cone, predict.time_till_reach_ball(car, ball))
        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

            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 > 4350 and abs(
                hit_pos.x) > 900 and not dist < 450:
            # 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:
            if car.boost == 0:

                collect_center = ball.pos.y * bot.info.team_sign <= 0
                collect_small = closest_enemy.pos.y * bot.info.team_sign <= 0
                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