Ejemplo n.º 1
0
    def exec(self, bot) -> SimpleControllerState:
        ct = bot.info.time - self._start_time
        controls = SimpleControllerState()
        controls.throttle = 1

        car = bot.info.my_car

        # Target is allowed to be a function that takes bot as a parameter. Check what it is
        if callable(self.target):
            target = self.target(bot)
        else:
            target = self.target

        # To boost or not to boost, that is the question
        car_to_target = target - car.pos
        vel_p = proj_onto_size(car.vel, car_to_target)
        angle = angle_between(car_to_target, car.forward)
        controls.boost = self.boost and angle < self._boost_ang_req and vel_p < self._max_speed

        # States of dodge (note reversed order)
        # Land on ground
        if ct >= self._t_finishing:
            self._almost_finished = True
            if car.on_ground:
                self.done = True
            else:
                bot.maneuver = RecoveryManeuver(bot)
                self.done = True
            return controls
        elif ct >= self._t_second_unjump:
            # Stop pressing jump and rotate and wait for flip is done
            pass
        elif ct >= self._t_aim:
            if ct >= self._t_second_jump:
                controls.jump = 1

            # Direction, yaw, pitch, roll
            if self.target is None:
                controls.roll = 0
                controls.pitch = -1
                controls.yaw = 0
            else:
                target_local = dot(car_to_target, car.rot)
                target_local.z = 0

                direction = normalize(target_local)

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

        # Stop pressing jump
        elif ct >= self._t_first_unjump:
            pass

        # First jump
        else:
            controls.jump = 1

        return controls
Ejemplo n.º 2
0
    def utility(self, bot) -> float:
        team_sign = bot.info.team_sign
        ball = bot.info.ball

        ball_to_goal = bot.info.own_goal - ball.pos
        too_close = norm(ball_to_goal) < Field.GOAL_WIDTH / 2 + Ball.RADIUS

        hits_goal_prediction = predict.will_ball_hit_goal(bot)
        hits_goal = hits_goal_prediction.happens and sign(
            ball.vel.y) == team_sign and hits_goal_prediction.time < 3

        return hits_goal or too_close
Ejemplo n.º 3
0
    def stay_at(self, bot, point: Vec3, looking_at: Vec3):

        OKAY_DIST = 100

        car = bot.info.my_car
        car_to_point = point - car.pos
        car_to_point_dir = normalize(point - car.pos)
        dist = norm(car_to_point)

        if dist > OKAY_DIST:
            return self.towards_point(bot, point, int(dist * 2))
        else:
            look_dir = normalize(looking_at - car.pos)
            facing_correctly = dot(car.forward, look_dir) > 0.9
            if facing_correctly:
                return SimpleControllerState()
            else:
                ctrls = SimpleControllerState()
                ctrls.throttle = 0.7 * sign(dot(car.forward, car_to_point_dir))
                ctrls.steer = -ctrls.throttle * sign(
                    dot(car.left, car_to_point_dir))

                return ctrls
Ejemplo n.º 4
0
    def exec(self, bot) -> SimpleControllerState:
        DODGE_DIST = 250
        MIDDLE_OFFSET = 430

        # Since ball is at (0,0) we don't we a car_to_ball variable like we do so many other places
        car = bot.info.my_car
        dist = norm(car.pos)
        vel_p = -proj_onto_size(car.vel, car.pos)

        point = Vec3(0, bot.info.team_sign * (dist / 2.6 - MIDDLE_OFFSET), 0)
        speed = 2300
        opp_dist = norm(bot.info.opponents[0].pos)
        opp_does_kick = opp_dist < dist + 600

        # Opponent is not going for kickoff, so we slow down a bit
        if not opp_does_kick:
            speed = 2210
            point = Vec3(0, bot.info.team_sign * (dist / 2.05 - MIDDLE_OFFSET),
                         0)
            point += Vec3(35 * sign(car.pos.x), 0, 0)

        # Dodge when close to (0, 0) - but only if the opponent also goes for kickoff.
        # The dodge itself should happen in about 0.3 seconds
        if dist - DODGE_DIST < vel_p * 0.3 and opp_does_kick:
            bot.drive.start_dodge(bot)

        # Make two dodges when spawning far back
        elif dist > 3640 and vel_p > 1200 and not opp_does_kick:
            bot.drive.start_dodge(bot)

        # Pickup boost when spawning back corner by driving a bit towards the middle boost pad first
        elif abs(car.pos.x) > 230 and abs(car.pos.y) > 2880:
            # The pads exact location is (0, 2816), but don't have to be exact
            point.y = bot.info.team_sign * 2790

        self.done = not bot.info.is_kickoff
        bot.renderer.draw_line_3d(car.pos, point, bot.renderer.white())

        return bot.drive.towards_point(bot,
                                       point,
                                       target_vel=speed,
                                       slide=False,
                                       boost_min=0,
                                       can_dodge=False,
                                       can_keep_speed=False)
Ejemplo n.º 5
0
    def utility_score(self, bot) -> float:
        team_sign = bot.info.team_sign
        ball = bot.info.ball

        ball_to_goal = bot.info.own_goal.pos - ball.pos
        too_close = norm(ball_to_goal) < Goal.WIDTH2 + Ball.RADIUS

        hits_goal_prediction = predict.will_ball_hit_goal(bot)
        hits_goal = hits_goal_prediction.happens and sign(
            ball.vel.y) == team_sign and hits_goal_prediction.time < 3

        obj_bonus = {
            Objective.UNKNOWN: 0,
            Objective.GO_FOR_IT: 0.2,
            Objective.FOLLOW_UP: 0,
            Objective.ROTATE_BACK_OR_DEF: 0.1,
        }[bot.info.my_car.objective]

        return float(hits_goal or too_close) + obj_bonus
Ejemplo n.º 6
0
    def exec(self, bot) -> SimpleControllerState:
        ctrl = super().exec(bot)

        ct = time.time() - self._start_time

        if ct >= self._t_release_ball:
            ctrl.use_item = True

        if self._t_second_jump >= ct >= 0:
            # Rotate away from target
            car = bot.data.my_car
            target = Vec3(y=-5440 * bot.data.team_sign)
            ball_to_target = target - bot.data.ball.pos

            target_local = dot(ball_to_target, car.rot)
            target_local.z = 0

            direction = normalize(-target_local)

            ctrl.roll = 0
            ctrl.pitch = -direction.x
            ctrl.yaw = sign(car.rot.get(2, 2)) * direction.y

        return ctrl
Ejemplo n.º 7
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