Esempio n. 1
0
    def get_output(self, packet: GameTickPacket) -> SimpleControllerState:
        self.info.read_packet(packet)
        self.controls = SimpleControllerState()

        next_state = self.state

        if self.state == State.RESET:

            self.timer = 0.0

            # put the car in the middle of the field
            car_state = CarState(
                physics=Physics(location=Vector3(0, 0, 20),
                                velocity=Vector3(0, 0, 0),
                                rotation=Rotator(0, 0, 0),
                                angular_velocity=Vector3(0, 0, 0)))

            theta = random.uniform(0, 6.28)
            pos = Vector3(sin(theta) * 1000.0, cos(theta) * 1000.0, 100.0)

            # put the ball somewhere out of the way
            ball_state = BallState(
                physics=Physics(location=pos,
                                velocity=Vector3(0, 0, 0),
                                rotation=Rotator(0, 0, 0),
                                angular_velocity=Vector3(0, 0, 0)))

            self.set_game_state(
                GameState(ball=ball_state, cars={self.index: car_state}))

            next_state = State.WAIT

        if self.state == State.WAIT:

            if self.timer > 0.2:
                next_state = State.INITIALIZE

        if self.state == State.INITIALIZE:

            # in this demonstration, we choose to dodge toward the ball
            c = self.info.my_car
            target = self.info.ball.pos
            self.action = AirDodge(c, 0.1, target)

            next_state = State.RUNNING

        if self.state == State.RUNNING:

            self.action.step(0.01666)
            self.controls = self.action.controls

            if self.timer > self.timeout:
                next_state = State.RESET

        self.timer += 0.01666
        self.state = next_state

        return self.controls
Esempio n. 2
0
 def set_mechanics(self):
     if self.drive is None:
         self.drive = Drive(self.info.my_car, self.info.ball.pos, 1399)
     if self.catching is None:
         self.catching = Catching(self.info.my_car, self.info.ball.pos,
                                  1399)
     if self.recovery is None:
         self.recovery = AerialTurn(self.info.my_car)
     if self.dodge is None:
         self.dodge = AirDodge(self.info.my_car, 0.25, self.info.ball.pos)
     if self.dribble is None:
         self.dribble = Dribbling(self.info.my_car, self.info.ball,
                                  self.info.their_goal)
Esempio n. 3
0
def defending(agent):
    target = defending_target(agent)
    agent.drive.target_pos = target
    agent.drive.target_speed = get_speed(agent, target)
    agent.drive.step(agent.FPS)
    agent.controls = agent.drive.controls
    powerslide(agent)
    if can_dodge(agent, target):
        agent.step = "Dodge"
        agent.dodge = AirDodge(agent.info.my_car, 0.1, target)
    if not agent.defending:
        agent.step = "Catching"
    if not agent.info.my_car.on_ground:
        agent.step = "Recovery"
Esempio n. 4
0
def shooting(agent):
    agent.drive.step(agent.FPS)
    agent.controls = agent.drive.controls
    powerslide(agent)
    target = shooting_target(agent)
    agent.drive.target_pos = target
    agent.drive.target_speed = get_speed(agent, target)
    if should_dodge(agent):
        agent.step = "Dodge"
        agent.dodge = AirDodge(agent.info.my_car, 0.1, agent.info.ball.pos)
    elif not (abs(agent.info.ball.vel[2]) < 100
              and sign(agent.team) * agent.info.ball.vel[1] < 0):
        agent.step = "Catching"
        agent.drive = Drive(agent.info.my_car, agent.info.ball.pos, 1399)
Esempio n. 5
0
    def prepare_kickoff(self, packet: GameTickPacket) -> None:
        bot_pos = Vector3(packet.game_cars[self.agent.index].physics.location)

        # Centre kickoff
        if abs(bot_pos.x) < 250:
            pad = self.get_closest_small_pad(bot_pos).location
            first_target: vec3 = vec3(
                pad.x, pad.y,
                pad.z) - vec3(0, 250, 0) * (1 if self.agent.team else -1)
            second_target: vec3 = vec3(0, 850,
                                       0) * (1 if self.agent.team else -1)

            self.kickoff_steps = [
                Drive(self.agent.game_info.my_car, first_target, 2400),
                AirDodge(self.agent.game_info.my_car, 0.075, vec3(0, 0, 0)),
                Drive(self.agent.game_info.my_car, second_target, 2400),
                AirDodge(self.agent.game_info.my_car, 0.075, vec3(0, 0, 0))
            ]
        # Off-centre kickoff
        elif abs(bot_pos.x) < 1000:
            target: vec3 = normalize(self.agent.game_info.my_car.pos) * 500

            self.kickoff_steps = [
                Drive(
                    self.agent.game_info.my_car,
                    vec3(self.agent.game_info.my_car.pos[0],
                         3477 * (1 if self.agent.team else -1), 0), 2400),
                AirDodge(self.agent.game_info.my_car, 0.075, vec3(0, 0, 0)),
                Drive(self.agent.game_info.my_car, target, 2400),
                AirDodge(self.agent.game_info.my_car, 0.075, vec3(0, 0, 0))
            ]
        # Diagonal kickoff
        else:
            pad = self.get_closest_small_pad(bot_pos).location
            car_to_pad: vec3 = vec3(pad.x, pad.y,
                                    pad.z) - self.agent.game_info.my_car.pos
            first_target: vec3 = self.agent.game_info.my_car.pos + 1.425 * car_to_pad
            second_target: vec3 = vec3(0, 150,
                                       0) * (1 if self.agent.team else -1)
            third_target: vec3 = normalize(
                self.agent.game_info.my_car.pos) * 850

            self.kickoff_steps = [
                Drive(self.agent.game_info.my_car, first_target, 2300),
                AirDodge(self.agent.game_info.my_car, 0.035, second_target),
                Drive(self.agent.game_info.my_car, third_target, 2400),
                AirDodge(self.agent.game_info.my_car, 0.1, vec3(0, 0, 0))
            ]
Esempio n. 6
0
    def get_output(self, packet: GameTickPacket) -> SimpleControllerState:
        # Hit the ball blindly if the bot is between the ball and its own goal. This is to clear it away.
        # Hit the ball to the side if the ball is closer to its own goal than it is.

        self.agent.game_info.read_packet(packet)

        if self.dodge is not None:
            self.dodge.step(1 / 60)
            if not self.dodge.finished:
                return self.dodge.controls
            else:
                self.dodge = None

        controller: SimpleControllerState = SimpleControllerState()

        ball: Vector3 = Vector3(packet.game_ball.physics.location)
        bot: PhysicsObject = PhysicsObject(
            packet.game_cars[self.agent.index].physics)

        target: Vector3
        if abs(ball.y) < abs(bot.location.y):
            target = ball
        else:
            offset: float = 100 if ball.x > bot.location.x else -100
            offset *= -1 if self.agent.team == 1 else 1
            target = ball + Vector3(offset, 0, 0)
            bot_to_ball: Vector3 = ball - bot.location
            if abs(bot_to_ball.normalised().x) > 0.7:
                self.dodge = AirDodge(self.agent.game_info.my_car, 0.1,
                                      vec3(ball.x, ball.y, ball.z))

        controller.steer = gosling_steering(bot.location, bot.rotation.z,
                                            target)
        controller.boost = True
        controller.throttle = 1

        return controller
Esempio n. 7
0
def kick_off(agent):
    if agent.kickoffStart == "Diagonal_Scrub":
        if agent.step == "Drive":
            agent.drive.step(agent.FPS)
            agent.controls = agent.drive.controls
            if agent.drive.finished:
                agent.step = "Dodge1"
                # target = agent.info.ball.pos
                target = normalize(z0(agent.info.my_car.forward())) * 1000
                agent.dodge = AirDodge(agent.info.my_car, 0.075, target)
        elif agent.step == "Dodge1":
            agent.dodge.step(agent.FPS)
            agent.controls = agent.dodge.controls
            if agent.dodge.finished:
                agent.step = "Steer"
                target = agent.info.ball.pos
                agent.drive = Drive(agent.info.my_car, target, 1399)
        elif agent.step == "Steer":
            agent.drive.step(agent.FPS)
            agent.controls = agent.drive.controls
            if agent.info.my_car.on_ground:
                agent.drive.target_speed = 2400
            if distance_2d(agent.info.ball.pos, agent.info.my_car.pos) < 750:
                agent.step = "Dodge2"
                agent.dodge = AirDodge(agent.info.my_car, 0.075,
                                       agent.info.ball.pos)
        elif agent.step == "Dodge2":
            agent.dodge.step(agent.FPS)
            agent.controls = agent.dodge.controls
            if agent.dodge.finished and agent.info.my_car.on_ground:
                agent.step = "Catching"
    elif agent.kickoffStart == "Diagonal":
        if agent.step == "Drive":
            agent.drive.step(agent.FPS)
            agent.controls = agent.drive.controls
            if distance_2d(agent.info.ball.pos, agent.info.my_car.pos) < 850:
                agent.step = "Dodge"
                agent.dodge = AirDodge(agent.info.my_car, 0.075,
                                       agent.info.ball.pos)
        elif agent.step == "Dodge":
            agent.dodge.step(agent.FPS)
            agent.controls = agent.dodge.controls
            if agent.dodge.finished and agent.info.my_car.on_ground:
                agent.step = "Catching"
    elif agent.kickoffStart == "Center":
        if agent.step == "Drive":
            agent.drive.step(agent.FPS)
            agent.controls = agent.drive.controls
            if agent.drive.finished:
                agent.step = "Dodge1"
                agent.dodge = AirDodge(agent.info.my_car, 0.075,
                                       agent.info.ball.pos)
        elif agent.step == "Dodge1":
            agent.dodge.step(agent.FPS)
            agent.controls = agent.dodge.controls
            agent.controls.boost = 0
            if agent.dodge.finished and agent.info.my_car.on_ground:
                agent.step = "Steer"
                target = agent.info.ball.pos + sign(agent.team) * vec3(
                    0, 850, 0)
                agent.drive = Drive(agent.info.my_car, target, 2400)
        elif agent.step == "Steer":
            agent.drive.step(agent.FPS)
            agent.controls = agent.drive.controls
            if agent.drive.finished:
                agent.step = "Dodge2"
                agent.dodge = AirDodge(agent.info.my_car, 0.075,
                                       agent.info.ball.pos)
        elif agent.step == "Dodge2":
            agent.dodge.step(agent.FPS)
            agent.controls = agent.dodge.controls
            if agent.dodge.finished and agent.info.my_car.on_ground:
                agent.step = "Catching"
    elif agent.kickoffStart == "offCenter":
        if agent.step == "Drive":
            agent.drive.step(agent.FPS)
            agent.controls = agent.drive.controls
            if agent.info.my_car.boost < 15 or agent.drive.finished:
                agent.step = "Dodge1"
                agent.dodge = AirDodge(agent.info.my_car, 0.075,
                                       agent.info.ball.pos)
        elif agent.step == "Dodge1":
            agent.dodge.step(agent.FPS)
            agent.controls = agent.dodge.controls
            agent.controls.boost = 0
            if agent.dodge.finished and agent.info.my_car.on_ground:
                agent.step = "Steer"
                target = agent.info.ball.pos
                agent.drive = Drive(agent.info.my_car, target, 2400)
        elif agent.step == "Steer":
            agent.drive.step(agent.FPS)
            agent.controls = agent.drive.controls
            if distance_2d(agent.info.ball.pos, agent.info.my_car.pos) < 850:
                agent.step = "Dodge2"
                agent.dodge = AirDodge(agent.info.my_car, 0.075,
                                       agent.info.ball.pos)
        elif agent.step == "Dodge2":
            agent.dodge.step(agent.FPS)
            agent.controls = agent.dodge.controls
            if agent.dodge.finished and agent.info.my_car.on_ground:
                agent.step = "Catching"
Esempio n. 8
0
 def set_mechanics(self):
     if self.drive is None:
         self.drive = Drive(self.info.my_car, self.info.ball.pos, 1399)
     if self.dodge is None:
         self.dodge = AirDodge(self.info.my_car, 0.25, self.info.ball.pos)
Esempio n. 9
0
    def get_output(self, packet):
        self.info.read_packet(packet)

        #additional processing not done by RLU
        self.kickoff_pause  = packet.game_info.is_kickoff_pause
        self.round_active   = packet.game_info.is_round_active
        self.dt             = self.info.time - self.last_time
        self.last_time      = self.info.time
        self.last_touch     = packet.game_ball.latest_touch.player_name
        
        #trashtalk
        if packet.game_cars[self.index].score_info.goals == self.goals + 1:
            self.send_quick_chat(QuickChats.CHAT_EVERYONE, QuickChats.Reactions_Calculated)
            
        self.goals          = packet.game_cars[self.index].score_info.goals

        #resets controls each tick
        self.controls = SimpleControllerState()

        #choose state
        if not self.round_active:
            self.state = None
        elif not self.state == "kickoff":
            if self.kickoff_pause:
                self.kickoff_pos    = None
                self.action         = None
                self.timer          = 0.0
                self.state          = "kickoff"
        
            elif not self.info.my_car.on_ground and not isinstance(self.action, AirDodge):
                self.state          = "recovery"
                self.action         = self.action = AerialTurn(self.info.my_car)

            elif norm(self.info.my_goal.center - self.info.my_car.pos) > norm(self.info.my_goal.center - self.info.ball.pos) + self.def_extra_dist:
                self.action         = None
                self.target_speed   = 2300
                self.state          = "defence"
		
                if self.team == 0:
                    sign = -1
                else:
                    sign = 1
                
                #temporary 2v2 for Cow
                if len(self.info.teammates) > 0:
                    if self.info.ball.pos[1] > 0:
                        self.target = vec3(3000,sign*4000,0)
                    else:
                        self.target = vec3(-3000,sign*4000,0)
                else:
                    self.target = vec3(0,sign*4000,0)

            elif self.info.my_car.pos[1] > 5120 or self.info.my_car.pos[1] < -5120:
                self.target         = vec3(0,5000,0) if self.info.my_car.pos[1] > 5120 else vec3(0,-5000,0)
                self.action         = self.action = Drive(self.info.my_car,self.target,1000)
                self.state          = "goal escape"

            elif self.state == None:
                self.action         = None
                self.target         = None
                self.target_speed   = 2300
                self.state          = "offence"


        #kickoff state
        if self.state == "kickoff":
            Kickoff.kickoff(self)

            #exit kickoff state
            if self.timer >= 2.6 or self.last_touch != '':
                self.state  = None
                self.action = None

        #recovery state
        elif self.state == "recovery":
            self.action.step(self.dt)
            self.controls           = self.action.controls
            self.controls.throttle  = 1.0
            
            #exit recovery state
            if self.info.my_car.on_ground == True:
                self.state  = None
                self.action = None


        #defence state and offence state
        elif self.state == "defence" or self.state == "offence":  
            #select target
            if self.target == None:
                #large boost
                if self.info.my_car.boost <= self.low_boost and norm(self.info.my_car.pos - self.info.ball.pos) > self.max_ball_dist:
                    active_pads = []
                    for pad in self.info.boost_pads:
                        if pad.is_active:
                            active_pads.append(pad)

                    if len(active_pads) != 0:
                        closest_pad = active_pads[0]
                        for pad in active_pads:
                            if norm(pad.pos - self.info.ball.pos) < norm(closest_pad.pos - self.info.ball.pos):
                                closest_pad = pad
                        self.target = closest_pad.pos
                    else:
                        self.target = self.info.ball.pos

                #ball        
                else:
                    self.target = self.info.ball.pos

            forward_target  = dot(self.target - self.info.my_car.pos, self.info.my_car.theta)[0]
            right_target    = dot(self.target - self.info.my_car.pos, self.info.my_car.theta)[1]
            angle_to_target = math.atan2(right_target, forward_target)

            forward_goal    = dot(self.info.their_goal.center - self.info.my_car.pos, self.info.my_car.theta)[0]
            right_goal      = dot(self.info.their_goal.center - self.info.my_car.pos, self.info.my_car.theta)[1]
            angle_to_goal   = math.atan2(right_goal, forward_goal)

            #select maneuver
            if not isinstance(self.action, AirDodge):
                #shooting
                if norm(self.info.ball.pos - self.info.my_car.pos) < self.dodge_dist and (angle_to_target - (math.pi/10.0) <= angle_to_goal <= angle_to_target + (math.pi/10.0)): 
                    self.action = AirDodge(self.info.my_car,0.2,self.info.their_goal.center)
                    self.timer  = 0.0
                #dodging
                elif (-math.pi/24.0) <= angle_to_target <= (math.pi/24.0) and norm(self.info.my_car.vel) > 700 and norm(self.info.ball.pos - self.info.my_car.pos) > 1000 and not self.state == "defence":
                    self.action = AirDodge(self.info.my_car,0.2,self.target)
                    self.timer  = 0.0
                #Drive
                else:
                    self.action = Drive(self.info.my_car,self.target,self.target_speed)
                
            #exit AirDodge
            else:
                self.timer += self.dt
                if self.timer >= 0.5:
                    self.action = None
 
            #Drive
            if isinstance(self.action, Drive):
                speed = norm(self.info.my_car.vel)
                r = -6.901E-11 * speed**4 + 2.1815E-07 * speed**3 - 5.4437E-06 * speed**2 + 0.12496671 * speed + 157

                #handbrake
                self.drift = False
                if (math.pi/2.0) <= angle_to_target or angle_to_target <= (-math.pi/2.0):
                    self.drift = True

                #target speed 
                elif (norm(self.target - (self.info.my_car.pos + dot(self.info.my_car.theta,vec3(0,r,0)))) < r or norm(self.target - (self.info.my_car.pos + dot(self.info.my_car.theta,vec3(0,-r,0)))) < r) and not self.target_speed < self.min_target_s:
                    self.target_speed += -50
                    self.action = Drive(self.info.my_car,self.target,self.target_speed)
                elif self.target_speed < 1800:
                    self.target_speed += 50
                    self.action = Drive(self.info.my_car,self.target,self.target_speed)

            #maneuver tick
            if self.action != None:
                self.action.step(self.dt)
                self.controls   = self.action.controls
                self.controls.handbrake = self.drift

            #exit either state
            if (self.state == "defence" and norm(self.info.my_goal.center - self.info.my_car.pos) < norm(self.info.my_goal.center - self.info.ball.pos)) or (norm(self.target - self.info.my_car.pos) < self.target_range):
                self.state = None


        #goal escape state
        if self.state == "goal escape":
            self.action.step(self.dt)
            self.controls   = self.action.controls

            #exit goal escape state
            if not (self.info.my_car.pos[1] > 5120 or self.info.my_car.pos[1] < -5120):
                self.state  = None
                self.action = None

        if 'win32gui' in sys.modules:
            #finding the size of the Rocket League window
            def callback(hwnd, win_rect):
                if "Rocket League" in win32gui.GetWindowText(hwnd):
                    rect = win32gui.GetWindowRect(hwnd)
                    win_rect[0] = rect[0]
                    win_rect[1] = rect[1]
                    win_rect[2] = rect[2] - rect[0]
                    win_rect[3] = rect[3] - rect[1]

            self.RLwindow = [0] * 4
            win32gui.EnumWindows(callback, self.RLwindow)

        #Rendering
        Render.debug(self)
        Render.turn_circles(self)
        if not self.target == None:
            Render.target(self)
        

        return self.controls
Esempio n. 10
0
 def get_controls(self):
     if self.step == "Steer" or self.step == "Dodge2":
         self.step = "Catching"
     if self.step == "Catching":
         target = get_bounce(self)
         if target is None:
             self.step = "Defending"
         else:
             self.catching.target_pos = target[0]
             self.catching.target_speed = (distance_2d(
                 self.info.my_car.pos, target[0]) + 50) / target[1]
             self.catching.step(self.FPS)
             self.controls = self.catching.controls
             ball = self.info.ball
             car = self.info.my_car
             if distance_2d(ball.pos,
                            car.pos) < 150 and 65 < abs(ball.pos[2] -
                                                        car.pos[2]) < 127:
                 self.step = "Dribbling"
                 self.dribble = Dribbling(self.info.my_car, self.info.ball,
                                          self.info.their_goal)
             if self.defending:
                 self.step = "Defending"
             if not self.info.my_car.on_ground:
                 self.step = "Recovery"
             ball = self.info.ball
             if abs(ball.vel[2]) < 100 and sign(
                     self.team) * ball.vel[1] < 0 and sign(
                         self.team) * ball.pos[1] < 0:
                 self.step = "Shooting"
     elif self.step == "Dribbling":
         self.dribble.step(self.FPS)
         self.controls = self.dribble.controls
         ball = self.info.ball
         car = self.info.my_car
         bot_to_opponent = self.info.opponents[0].pos - self.info.my_car.pos
         local_bot_to_target = dot(bot_to_opponent, self.info.my_car.theta)
         angle_front_to_target = math.atan2(local_bot_to_target[1],
                                            local_bot_to_target[0])
         opponent_is_near = norm(vec2(bot_to_opponent)) < 2000
         opponent_is_in_the_way = math.radians(
             -10) < angle_front_to_target < math.radians(10)
         if not (distance_2d(ball.pos, car.pos) < 150
                 and 65 < abs(ball.pos[2] - car.pos[2]) < 127):
             self.step = "Catching"
         if self.defending:
             self.step = "Defending"
         if opponent_is_near and opponent_is_in_the_way:
             self.step = "Dodge"
             self.dodge = AirDodge(self.info.my_car, 0.25,
                                   self.info.their_goal.center)
         if not self.info.my_car.on_ground:
             self.step = "Recovery"
     elif self.step == "Defending":
         defending(self)
     elif self.step == "Dodge":
         self.dodge.step(self.FPS)
         self.controls = self.dodge.controls
         self.controls.boost = 0
         if self.dodge.finished and self.info.my_car.on_ground:
             self.step = "Catching"
     elif self.step == "Recovery":
         self.recovery.step(self.FPS)
         self.controls = self.recovery.controls
         if self.info.my_car.on_ground:
             self.step = "Catching"
     elif self.step == "Shooting":
         shooting(self)
Esempio n. 11
0
class hypebot(BaseAgent):
    def __init__(self, name, team, index):
        super().__init__(name, team, index)
        self.name = name
        self.team = team
        self.index = index
        self.defending = False
        self.info = None
        self.bounces = []
        self.drive = None
        self.catching = None
        self.dodge = None
        self.recovery = None
        self.dribble = None
        self.controls = SimpleControllerState()
        self.kickoff = False
        self.inFrontOfBall = False
        self.kickoffStart = None
        self.step = "Catching"
        self.time = 0
        self.FPS = 1 / 120
        self.p_s = 0.
        self.kickoffTime = 0

    def initialize_agent(self):
        self.info = GameInfo(self.index, self.team, self.get_field_info())

    def get_output(self, packet: GameTickPacket) -> SimpleControllerState:
        if packet.game_info.seconds_elapsed - self.time > 0:
            self.FPS = packet.game_info.seconds_elapsed - self.time
        self.time = packet.game_info.seconds_elapsed
        self.info.read_packet(packet)
        self.predict()
        self.set_mechanics()
        prev_kickoff = self.kickoff
        self.kickoff = packet.game_info.is_kickoff_pause
        self.defending = self.should_defending()
        if self.kickoff and not prev_kickoff:
            initKickOff(self)
        if self.kickoff or self.step == "Dodge2":
            kickOff(self)
        else:
            self.get_controls()
        self.render_string(str(self.step))
        if not packet.game_info.is_round_active:
            self.controls.steer = 0
        return self.controls

    def predict(self):
        self.bounces = []
        ball_prediction = self.get_ball_prediction_struct()
        for i in range(ball_prediction.num_slices):
            location = vec3(ball_prediction.slices[i].physics.location.x,
                            ball_prediction.slices[i].physics.location.y,
                            ball_prediction.slices[i].physics.location.z)
            prev_ang_vel = ball_prediction.slices[i -
                                                  1].physics.angular_velocity
            prev_normalized_ang_vel = normalize(
                vec3(prev_ang_vel.x, prev_ang_vel.y, prev_ang_vel.z))
            current_ang_vel = ball_prediction.slices[
                i].physics.angular_velocity
            current_normalized_ang_vel = normalize(
                vec3(current_ang_vel.x, current_ang_vel.y, current_ang_vel.z))
            if prev_normalized_ang_vel != current_normalized_ang_vel and location[
                    2] < 125:
                self.bounces.append((location, i * 1 / 60))

    def set_mechanics(self):
        if self.drive is None:
            self.drive = Drive(self.info.my_car, self.info.ball.pos, 1399)
        if self.catching is None:
            self.catching = Catching(self.info.my_car, self.info.ball.pos,
                                     1399)
        if self.recovery is None:
            self.recovery = AerialTurn(self.info.my_car)
        if self.dodge is None:
            self.dodge = AirDodge(self.info.my_car, 0.25, self.info.ball.pos)
        if self.dribble is None:
            self.dribble = Dribbling(self.info.my_car, self.info.ball,
                                     self.info.their_goal)

    def get_controls(self):
        if self.step == "Steer" or self.step == "Dodge2":
            self.step = "Catching"
        if self.step == "Catching":
            target = get_bounce(self)
            if target is None:
                self.step = "Defending"
            else:
                self.catching.target_pos = target[0]
                self.catching.target_speed = (distance_2d(
                    self.info.my_car.pos, target[0]) + 50) / target[1]
                self.catching.step(self.FPS)
                self.controls = self.catching.controls
                ball = self.info.ball
                car = self.info.my_car
                if distance_2d(ball.pos,
                               car.pos) < 150 and 65 < abs(ball.pos[2] -
                                                           car.pos[2]) < 127:
                    self.step = "Dribbling"
                    self.dribble = Dribbling(self.info.my_car, self.info.ball,
                                             self.info.their_goal)
                if self.defending:
                    self.step = "Defending"
                if not self.info.my_car.on_ground:
                    self.step = "Recovery"
                ball = self.info.ball
                if abs(ball.vel[2]) < 100 and sign(
                        self.team) * ball.vel[1] < 0 and sign(
                            self.team) * ball.pos[1] < 0:
                    self.step = "Shooting"
        elif self.step == "Dribbling":
            self.dribble.step(self.FPS)
            self.controls = self.dribble.controls
            ball = self.info.ball
            car = self.info.my_car
            bot_to_opponent = self.info.opponents[0].pos - self.info.my_car.pos
            local_bot_to_target = dot(bot_to_opponent, self.info.my_car.theta)
            angle_front_to_target = math.atan2(local_bot_to_target[1],
                                               local_bot_to_target[0])
            opponent_is_near = norm(vec2(bot_to_opponent)) < 2000
            opponent_is_in_the_way = math.radians(
                -10) < angle_front_to_target < math.radians(10)
            if not (distance_2d(ball.pos, car.pos) < 150
                    and 65 < abs(ball.pos[2] - car.pos[2]) < 127):
                self.step = "Catching"
            if self.defending:
                self.step = "Defending"
            if opponent_is_near and opponent_is_in_the_way:
                self.step = "Dodge"
                self.dodge = AirDodge(self.info.my_car, 0.25,
                                      self.info.their_goal.center)
            if not self.info.my_car.on_ground:
                self.step = "Recovery"
        elif self.step == "Defending":
            defending(self)
        elif self.step == "Dodge":
            self.dodge.step(self.FPS)
            self.controls = self.dodge.controls
            self.controls.boost = 0
            if self.dodge.finished and self.info.my_car.on_ground:
                self.step = "Catching"
        elif self.step == "Recovery":
            self.recovery.step(self.FPS)
            self.controls = self.recovery.controls
            if self.info.my_car.on_ground:
                self.step = "Catching"
        elif self.step == "Shooting":
            shooting(self)

    def render_string(self, string):
        self.renderer.begin_rendering('The State')
        if self.step == "Dodge1":
            self.renderer.draw_line_3d(self.info.my_car.pos, self.dodge.target,
                                       self.renderer.black())
        self.renderer.draw_line_3d(self.info.my_car.pos, self.bounces[0][0],
                                   self.renderer.blue())
        self.renderer.draw_string_2d(
            20, 20, 3, 3, string + " " + str(abs(self.info.ball.vel[2])) +
            " " + str(sign(self.team) * self.info.ball.vel[1]),
            self.renderer.red())
        self.renderer.end_rendering()

    def should_defending(self):
        ball = self.info.ball
        car = self.info.my_car
        our_goal = self.info.my_goal.center
        car_to_ball = ball.pos - car.pos
        in_front_of_ball = distance_2d(ball.pos, our_goal) < distance_2d(
            car.pos, our_goal)
        backline_intersect = line_backline_intersect(
            self.info.my_goal.center[1], vec2(car.pos), vec2(car_to_ball))
        return in_front_of_ball and abs(backline_intersect) < 2000