def rendezvous_prediction(game_info, min_time, persistent): ''' Updates the place and time we will be contacting the ball ''' prediction = game_info.ball_prediction for i in range(0, len(prediction.slices), 2): aerial = Aerial(game_info.utils_game.my_car) #if prediction.slices[i].pos.z > 150:# and prediction.slices[i].time > min_time: aerial.target = Vec3_to_vec3(prediction.slices[i].pos, game_info.team_sign) aerial.arrival_time = prediction.slices[i].time simulation = aerial.simulate() if (vec3_to_Vec3(simulation.location, game_info.team_sign) - vec3_to_Vec3(aerial.target, game_info.team_sign)).magnitude() < 30: persistent.aerial.target_location = prediction.slices[i].pos persistent.aerial.target_time = prediction.slices[i].time break #else: ''' This currently isn't defined, so we're going to skip it for now. if prediction.time - game_info.game_time > drive_time(game_info, prediction.location, game_info.me.boost): persistent.hit_ball.action.target = prediction.location persistent.hit_ball.action.arrival_time = prediction.time break ''' return persistent
def __init__(self, car: Car, ball_predictions, predicate: callable = None): self.ball: Ball = None self.is_viable = True #find the first reachable ball slice that also meets the predicate test_car = Car(car) test_aerial = Aerial(car) for ball in ball_predictions: test_aerial.target = ball.position test_aerial.arrival_time = ball.time # fake our car state :D dir_to_target = ground_direction(test_car.position, test_aerial.target) test_car.velocity = dir_to_target * max(norm(test_car.velocity), 1200) test_car.orientation = look_at(dir_to_target, vec3(0,0,1)) if test_aerial.is_viable() and (predicate is None or predicate(car, ball)): self.ball = ball break #if no slice is found, use the last one if self.ball is None: self.ball = ball_predictions[-1] self.is_viable = False self.time = self.ball.time self.ground_pos = ground(self.ball.position) self.position = self.ball.position
def __init__(self, car: Car, ball_predictions: List[Ball]): self.car: Car = car self.ball: Ball = None self.is_viable = True test_aerial = Aerial(car) for i in range(0, len(ball_predictions)): ball_slice = ball_predictions[i] test_aerial.target = ball_slice.position test_aerial.arrival_time = ball_slice.time if test_aerial.is_viable(): self.ball = ball_slice break # if no slice is found, use the last one if self.ball is None: if not ball_predictions: self.ball = Ball() self.ball.time = math.inf else: self.ball = ball_predictions[-1] self.is_viable = False self.time = self.ball.time self.position = self.ball.position
def __init__(self, aerial_strike: AerialStrike): super().__init__(aerial_strike.car) self.aerial_strike = aerial_strike self.info = self.aerial_strike.info self.aerial = Aerial(self.car) self.aerial.up = vec3(0, 0, -1) self._flight_path: List[vec3] = []
class DoubleTouch(Maneuver): """ Execute a regular AerialStrike, but when it finishes, look if we could continue aerialing for a second hit. """ def __init__(self, aerial_strike: AerialStrike): super().__init__(aerial_strike.car) self.aerial_strike = aerial_strike self.info = self.aerial_strike.info self.aerial = Aerial(self.car) self.aerial.up = vec3(0, 0, -1) self._flight_path: List[vec3] = [] def find_second_touch(self): self.info.predict_ball(duration=4.0) for i in range(0, len(self.info.ball_predictions), 5): ball = self.info.ball_predictions[i] if ball.position[2] < 500: break self.aerial.target = ball.position - direction( ball, self.aerial_strike.target) * 80 self.aerial.arrival_time = ball.time final_car = AerialStrike.simulate_flight(self.car, self.aerial, self._flight_path) if distance(final_car, self.aerial.target) < 50: return self.finished = True def step(self, dt: float): if self.aerial_strike.finished: self.aerial.step(dt) self.controls = self.aerial.controls self.finished = self.aerial.finished if self.car.on_ground: self.finished = True else: self.aerial_strike.step(dt) self.controls = self.aerial_strike.controls if self.aerial_strike.finished: if not self.car.on_ground: self.find_second_touch() else: self.finished = True def interruptible(self) -> bool: return self.aerial_strike.interruptible() def render(self, draw: DrawingTool): if self.aerial_strike.finished: draw.color(draw.pink) draw.crosshair(self.aerial.target) draw.color(draw.lime) draw.polyline(self._flight_path) else: self.aerial_strike.render(draw)
def __init__(self, car: Car, info: GameInfo, target: vec3 = None): self.aerial = Aerial(car) self.aerial.angle_threshold = 0.8 self.aerial.single_jump = not self.DOUBLE_JUMP super().__init__(car, info, target) self.arrive.allow_dodges_and_wavedashes = False self.aerialing = False self.too_early = False self._flight_path: List[vec3] = []
def copy_aerial(aerial: Aerial, car: Car): aerial_copy = Aerial(car) aerial_copy.target = vec3(aerial.target) aerial_copy.arrival_time = aerial.arrival_time aerial_copy.target_orientation = aerial.target_orientation aerial_copy.up = aerial.up aerial_copy.angle_threshold = aerial.angle_threshold aerial_copy.reorient_distance = aerial.reorient_distance aerial_copy.throttle_distance = aerial.throttle_distance return aerial_copy
def __init__(self, index: int, team: int): super().__init__() self.team = team self.id = index self.aerial_turn = AerialTurn(self) self.aerial = Aerial(self) self.hover = Hover(self)
def aerial_step(aerial: Aerial, car: Car, rotation_input=None, dt=1.0 / 60.0): return_value = aerial.step(dt) if rotation_input is not None and aerial.arrival_time - car.time <= 0.5: aerial.controls.pitch = rotation_input.pitch aerial.controls.yaw = rotation_input.yaw aerial.controls.roll = rotation_input.roll # aerial.controls.boost = rotation_input.boost return return_value
class DoubleTouch(Maneuver): """ Execute a regular AerialStrike, but when it finishes, look if we could continue aerialing for a second hit. """ def __init__(self, aerial_strike: AerialStrike): super().__init__(aerial_strike.car) self.aerial_strike = aerial_strike self.info = self.aerial_strike.info self.aerial = Aerial(self.car) def find_second_touch(self): self.info.predict_ball(time_limit=3.0) intercept = AirToAirIntercept(self.car, self.info.ball_predictions) self.aerial.target = intercept.position - direction(intercept, self.aerial_strike.target) * 80 self.aerial.up = vec3(0, 0, -1) self.aerial.arrival_time = intercept.time if not intercept.is_viable: self.finished = True def step(self, dt: float): if self.aerial_strike.finished: self.aerial.step(dt) self.controls = self.aerial.controls self.finished = self.aerial.finished else: self.aerial_strike.step(dt) self.controls = self.aerial_strike.controls if self.aerial_strike.finished: if not self.car.on_ground: self.find_second_touch() else: self.finished = True def interruptible(self) -> bool: return self.aerial_strike.interruptible() def render(self, draw: DrawingTool): if self.aerial_strike.finished: draw.color(draw.pink) draw.crosshair(self.aerial.target) else: self.aerial_strike.render(draw)
def setup(self): self.aerial = Aerial(self.agent.game.my_car) self.turn = AerialTurn(self.agent.game.my_car) myGoal = center = Vector([0, 5200 * sign(self.agent.team), 200]) enemyGoal = center = Vector([0, 5200 * -sign(self.agent.team), 200]) if self.agent.me.boostLevel > 0: for i in range(0, self.agent.ballPred.num_slices): targetVec = Vector([self.agent.ballPred.slices[i].physics.location.x, self.agent.ballPred.slices[i].physics.location.y, self.agent.ballPred.slices[i].physics.location.z]) # interferenceTimer += self.agent.deltaTime # if interferenceTimer < 1: # if findEnemyClosestToLocation(self.agent,targetVec)[1] < 150: # break if self.agent.ballPred.slices[i].physics.location.z >= 300: goalDist = distance2D(center, targetVec) #if distance2D(myGoal, targetVec) > distance2D(myGoal, self.agent.me.location): if self.agent.me.location[1] * sign(self.agent.team) > self.agent.ballPred.slices[i].physics.location.y * sign(self.agent.team): zOffset = 0 if goalDist < 1500: if targetVec[2] > 600: zOffset = 70 shotAngle = correctAngle(math.degrees(angle2(targetVec, enemyGoal)) + 90 * -sign(self.agent.team)) if abs(shotAngle) <=80: xOffset = clamp(80,-80,(shotAngle*2)*-sign(self.agent.team)) self.aerial.target = vec3(self.agent.ballPred.slices[i].physics.location.x+xOffset, self.agent.ballPred.slices[i].physics.location.y, self.agent.ballPred.slices[i].physics.location.z+zOffset) self.aerial.arrival_time = self.agent.ballPred.slices[i].game_seconds simulation = self.aerial.simulate() # # check if we can reach it by an aerial if norm(simulation.location - self.aerial.target) < 100: self.target_ball = self.agent.ballPred.slices[i] self.xOffset = xOffset self.zOffset = zOffset self.active = True break
def choose_stationary_takeoff_time(game_info, target_loc, target_time): ''' Decides when to take off for an aerial based on a given target time and place. Assumes we're sitting still to start with. ''' aerial = Aerial(game_info.utils_game.my_car) aerial.target = Vec3_to_vec3(target_loc, game_info.team_sign) current_time = game_info.game_time test_interval = [current_time, target_time] while abs(test_interval[1] - test_interval[0]) > 1 / 30: test_time = (test_interval[0] + test_interval[1]) / 2 aerial.arrival_time = test_time simulation = aerial.simulate() if vec3_to_Vec3(simulation.location - aerial.target, game_info.team_sign).magnitude() < 100: test_interval = [test_interval[0], test_time] else: test_interval = [test_time, test_interval[1]] return target_time - (test_interval[1] - current_time)
def get_ball_arrival(game_info, condition): ''' Returns the time and location at which the ball first satisfies condition. condition is a function that takes in a location and returns a Boolean. ''' aerial = Aerial(game_info.utils_game.my_car) prediction = game_info.ball_prediction for i in range(0, len(prediction.slices), 2): if condition(prediction.slices[i].pos, prediction.slices[i].vel, game_info.team_sign): return prediction.slices[i].time, prediction.slices[i].pos
def simulate_flight(car: Car, aerial: Aerial, flight_path: List[vec3] = None) -> Car: test_car = Car(car) test_aerial = Aerial(test_car) test_aerial.target = aerial.target test_aerial.arrival_time = aerial.arrival_time test_aerial.angle_threshold = aerial.angle_threshold test_aerial.up = aerial.up test_aerial.single_jump = aerial.single_jump if flight_path: flight_path.clear() while not test_aerial.finished: test_aerial.step(1 / 120) test_car.boost = 100 # TODO: fix boost depletion in RLU car sim test_car.step(test_aerial.controls, 1 / 120) if flight_path: flight_path.append(vec3(test_car.position)) return test_car
def simulate_flight(self, car: Car, write_to_flight_path=True) -> Car: test_car = Car(car) test_aerial = Aerial(test_car) test_aerial.target = self.aerial.target test_aerial.arrival_time = self.aerial.arrival_time test_aerial.angle_threshold = self.aerial.angle_threshold test_aerial.up = self.aerial.up test_aerial.single_jump = self.aerial.single_jump if write_to_flight_path: self._flight_path.clear() while not test_aerial.finished: test_aerial.step(1 / 120) test_car.boost = 100 # TODO: fix boost depletion in RLU car sim test_car.step(test_aerial.controls, 1 / 120) if write_to_flight_path: self._flight_path.append(vec3(test_car.position)) return test_car
def get_output(self, packet: GameTickPacket) -> SimpleControllerState: self.game.read_game_information(packet, self.get_rigid_body_tick(), self.get_field_info()) self.controls = SimpleControllerState() next_state = self.state if self.state == State.RESET: self.timer = 0.0 b_position = Vector3(random.uniform(-1500, 1500), random.uniform( 2500, 3500), random.uniform( 300, 500)) b_velocity = Vector3(random.uniform(-300, 300), random.uniform(-100, 100), random.uniform(1000, 1500)) ball_state = BallState(physics=Physics( location=b_position, velocity=b_velocity, rotation=Rotator(0, 0, 0), angular_velocity=Vector3(0, 0, 0) )) # this just initializes the car and ball # to different starting points each time c_position = Vector3(b_position.x, 0 * random.uniform(-1500, -1000), 25) #c_position = Vector3(200, -1000, 25) car_state = CarState(physics=Physics( location=c_position, velocity=Vector3(0, 800, 0), rotation=Rotator(0, 1.6, 0), angular_velocity=Vector3(0, 0, 0) ), boost_amount=100) self.set_game_state(GameState( ball=ball_state, cars={self.game.id: 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: self.aerial = Aerial(self.game.my_car) # self.aerial.up = normalize(vec3( # random.uniform(-1, 1), # random.uniform(-1, 1), # random.uniform(-1, 1))) self.turn = AerialTurn(self.game.my_car) # predict where the ball will be prediction = Ball(self.game.ball) self.ball_predictions = [vec3(prediction.location)] for i in range(100): prediction.step(0.016666) prediction.step(0.016666) self.ball_predictions.append(vec3(prediction.location)) # if the ball is in the air if prediction.location[2] > 500: self.aerial.target = prediction.location self.aerial.arrival_time = prediction.time simulation = self.aerial.simulate() # # check if we can reach it by an aerial if norm(simulation.location - self.aerial.target) < 100: prediction.step(0.016666) prediction.step(0.016666) self.aerial.target = prediction.location self.aerial.arrival_time = prediction.time self.target_ball = Ball(prediction) break next_state = State.RUNNING if self.state == State.RUNNING: self.log.write(f"{{\"car\":{self.game.my_car.to_json()}," f"\"ball\":{self.game.ball.to_json()}}}\n") self.aerial.step(self.game.time_delta) self.controls = self.aerial.controls if self.timer > self.timeout: next_state = State.RESET self.aerial = None self.turn = None self.timer += self.game.time_delta self.state = next_state self.renderer.begin_rendering() red = self.renderer.create_color(255, 230, 30, 30) purple = self.renderer.create_color(255, 230, 30, 230) white = self.renderer.create_color(255, 230, 230, 230) if self.aerial: r = 200 x = vec3(r, 0, 0) y = vec3(0, r, 0) z = vec3(0, 0, r) target = self.aerial.target self.renderer.draw_line_3d(target - x, target + x, purple) self.renderer.draw_line_3d(target - y, target + y, purple) self.renderer.draw_line_3d(target - z, target + z, purple) if self.ball_predictions: self.renderer.draw_polyline_3d(self.ball_predictions, purple) self.renderer.end_rendering() return self.controls
class AerialStrike(Strike): MAX_DISTANCE_ERROR = 50 DELAY_TAKEOFF = True MINIMAL_HEIGHT = 400 MAXIMAL_HEIGHT = 800 MINIMAL_HEIGHT_TIME = 1.0 MAXIMAL_HEIGHT_TIME = 2.5 DOUBLE_JUMP = False def __init__(self, car: Car, info: GameInfo, target: vec3 = None): self.aerial = Aerial(car) self.aerial.angle_threshold = 0.8 self.aerial.single_jump = not self.DOUBLE_JUMP super().__init__(car, info, target) self.arrive.allow_dodges_and_wavedashes = False self.aerialing = False self.too_early = False self._flight_path: List[vec3] = [] def intercept_predicate(self, car: Car, ball: Ball): required_time = range_map(ball.position[2], self.MINIMAL_HEIGHT, self.MAXIMAL_HEIGHT, self.MINIMAL_HEIGHT_TIME, self.MAXIMAL_HEIGHT_TIME) return self.MINIMAL_HEIGHT < ball.position[ 2] < self.MAXIMAL_HEIGHT and ball.time - car.time > required_time def configure(self, intercept: Intercept): super().configure(intercept) self.aerial.target = intercept.position - direction( intercept, self.target) * 80 self.aerial.up = normalize( ground_direction(intercept, self.car) + vec3(0, 0, 0.5)) self.aerial.arrival_time = intercept.time def simulate_flight(self, car: Car, write_to_flight_path=True) -> Car: test_car = Car(car) test_aerial = Aerial(test_car) test_aerial.target = self.aerial.target test_aerial.arrival_time = self.aerial.arrival_time test_aerial.angle_threshold = self.aerial.angle_threshold test_aerial.up = self.aerial.up test_aerial.single_jump = self.aerial.single_jump if write_to_flight_path: self._flight_path.clear() while not test_aerial.finished: test_aerial.step(1 / 120) test_car.boost = 100 # TODO: fix boost depletion in RLU car sim test_car.step(test_aerial.controls, 1 / 120) if write_to_flight_path: self._flight_path.append(vec3(test_car.position)) return test_car def interruptible(self) -> bool: return self.aerialing or super().interruptible() def step(self, dt): if self.aerialing: self.aerial.target_orientation = look_at( direction(self.car, self.target), vec3(0, 0, -1)) self.aerial.step(dt) self.controls = self.aerial.controls self.finished = self.aerial.finished else: super().step(dt) # simulate aerial from current state simulated_car = self.simulate_flight(self.car) # if the car ended up too far, we're too fast and we need to slow down if ground_distance(self.car, self.aerial.target) + 100 < ground_distance( self.car, simulated_car): # self.controls.throttle = -1 pass # if it ended up near the target, we could take off elif distance(simulated_car, self.aerial.target) < self.MAX_DISTANCE_ERROR: if angle_to(self.car, self.aerial.target) < 0.1 or norm( self.car.velocity) < 1000: if self.DELAY_TAKEOFF: # extrapolate current state a small amount of time future_car = Car(self.car) time = 0.2 future_car.time += time displacement = future_car.velocity * time if norm(future_car.velocity) > 500\ else normalize(future_car.velocity) * 500 * time future_car.position += displacement # simulate aerial fot the extrapolated car again future_simulated_car = self.simulate_flight( future_car, write_to_flight_path=False) # if the aerial is also successful, that means we should continue driving instead of taking off # this makes sure that we go for the most late possible aerials, which are the most effective if distance( future_simulated_car, self.aerial.target) > self.MAX_DISTANCE_ERROR: self.aerialing = True else: self.too_early = True else: self.aerialing = True else: # self.controls.boost = True self.controls.throttle = 1 def render(self, draw: DrawingTool): super().render(draw) draw.color(draw.lime if self.aerialing else ( draw.orange if self.too_early else draw.red)) draw.polyline(self._flight_path)
def __init__(self, aerial_strike: AerialStrike): super().__init__(aerial_strike.car) self.aerial_strike = aerial_strike self.info = self.aerial_strike.info self.aerial = Aerial(self.car)
def get_output(self, packet: GameTickPacket) -> SimpleControllerState: ############################################################################################### #Startup and frame info ############################################################################################### #Initialization info if self.is_init: self.is_init = False self.field_info = self.get_field_info() #Find teammates and opponents self.teammate_indices = [] self.opponent_indices = [] for i in range(packet.num_cars): if i == self.index: pass elif packet.game_cars[i].team == self.team: self.teammate_indices.append(i) else: self.opponent_indices.append(i) self.utils_game = utils.simulation.Game(self.index, self.team) utils.simulation.Game.set_mode("soccar") if TESTING or DEBUGGING: EvilGlobals.renderer = self.renderer self.prediction = PredictionPath( ball_prediction=self.get_ball_prediction_struct(), source="Framework", team=self.team) #Game state info self.game_info = GameState(packet=packet, rigid_body_tick=self.get_rigid_body_tick(), utils_game=self.utils_game, field_info=self.field_info, my_index=self.index, my_team=self.team, ball_prediction=self.prediction, teammate_indices=self.teammate_indices, opponent_indices=self.opponent_indices, my_old_inputs=self.old_inputs) ############################################################################################### #Planning ############################################################################################### #For now everything is a 1v1. I'll fix team code again in the future. #if self.game_info.team_mode == "1v1": self.plan, self.persistent = OnesPlanning.make_plan( self.game_info, self.plan.old_plan, self.plan.path, self.persistent) ''' else: self.plan, self.persistent = TeamPlanning.make_plan(self.game_info, self.plan.old_plan, self.plan.path, self.persistent) ''' #Check if it's a kickoff. If so, we'll run kickoff code later on. self.kickoff_position = update_kickoff_position( self.game_info, self.kickoff_position) #If we're in the first frame of an RLU mechanic, start up the object. #If we're finished with it, reset it to None ### if self.persistent.aerial_turn.initialize: self.persistent.aerial_turn.initialize = False self.persistent.aerial_turn.action = AerialTurn( self.game_info.utils_game.my_car) self.persistent.aerial_turn.action.target = rot_to_mat3( self.persistent.aerial_turn.target_orientation) elif not self.persistent.aerial_turn.check: self.persistent.aerial_turn.action = None self.persistent.aerial_turn.check = False ### if self.persistent.aerial.initialize: self.persistent.aerial.initialize = False self.persistent.aerial.action = Aerial( self.game_info.utils_game.my_car) self.persistent.aerial.action.target = Vec3_to_vec3( self.persistent.aerial.target_location, self.game_info.team_sign) self.persistent.aerial.action.arrival_time = self.persistent.aerial.target_time self.persistent.aerial.action.up = Vec3_to_vec3( self.persistent.aerial.target_up, self.game_info.team_sign) elif not self.persistent.aerial.check: self.persistent.aerial.action = None self.persistent.aerial.check = False ### ############################################################################################### #Testing ############################################################################################### if TESTING: #Copy-paste from a testing file here controller_input = SimpleControllerState() return controller_input ############################################################################################### #Run either Kickoff or Cowculate ############################################################################################### if self.plan.layers[0] == "Kickoff": if self.old_kickoff_data != None: self.kickoff_data = Kickoff(self.game_info, self.kickoff_position, self.old_kickoff_data.memory, self.persistent) else: self.kickoff_data = Kickoff(self.game_info, self.kickoff_position, None, self.persistent) output, self.persistent = self.kickoff_data.input() else: output, self.persistent = Cowculate(self.plan, self.game_info, self.prediction, self.persistent) ############################################################################################### #Update previous frame variables. ############################################################################################### self.old_kickoff_data = self.kickoff_data self.old_inputs = output #Make sure we don't get stuck turtling. Not sure how effective this is. if output.throttle == 0: output.throttle = 0.01 #Making sure that RLU output is interpreted properly as an input for RLBot framework_output = SimpleControllerState() framework_output.throttle = output.throttle framework_output.steer = output.steer framework_output.yaw = output.yaw framework_output.pitch = output.pitch framework_output.roll = output.roll framework_output.boost = output.boost framework_output.handbrake = output.handbrake framework_output.jump = output.jump return framework_output
def get_output(self, packet: GameTickPacket) -> SimpleControllerState: self.game.read_game_information(packet, self.get_rigid_body_tick(), self.get_field_info()) if self.game.ball.location[2] > 250: if self.state == "Aerial": self.aerial.step(self.game.time_delta) if self.aerial.finished: self.state = "Not Aerial" return self.aerial.controls else: self.aerial = Aerial(self.game.my_car) self.aerial.up = normalize( vec3(random.uniform(-1, 1), random.uniform(-1, 1), random.uniform(-1, 1))) # predict where the ball will be prediction = Ball(self.game.ball) for i in range(100): prediction.step(0.016666) if prediction.location[2] > 500: self.aerial.target = prediction.location self.aerial.arrival_time = prediction.time if self.aerial.is_viable(): self.aerial.target = prediction.location self.aerial.arrival_time = prediction.time self.target_ball = Ball(prediction) self.state = "Aerial" break ball_location = Vector2(packet.game_ball.physics.location.x, packet.game_ball.physics.location.y) my_car = packet.game_cars[self.index] car_location = Vector2(my_car.physics.location.x, my_car.physics.location.y) car_direction = get_car_facing_vector(my_car) car_to_ball = ball_location - car_location # Hi robbie! # The,type;of,punctuation;matters! true = shreck is love, shreck is life main(9) if not true: print("https://www.twitch.tv/TehRedox is the best twitch channel") y.yeet() self.WHOOPITYScooPTI = 0 for i in range(packet.num_cars): self.WHOOPITYScooPTI += packet.game_cars[i].score_info.goals if self.WHOOPITYScooPTI > self.CountyTHIS_ALSOdonttuch: self.CountyTHIS_ALSOdonttuch = self.WHOOPITYScooPTI self.renderer.begin_rendering(str(y)) # commented out due to performance concerns # self.renderer.draw_polyline_3d([[car_location.x+triforce(-20,20), car_location.y+triforce(-20,20), triforce(shreck(200),200)] for i in range(40)], self.renderer.cyan()) self.renderer.draw_rect_2d( 0, 0, 3840, 2160, True, self.renderer.create_color( 64, 246, 74, 138)) # first bot that supports 4k resolution! self.renderer.draw_string_2d(triforce(0, 100), triforce(0, 10), 8, 8, 'BANIME', self.renderer.lime()) self.renderer.draw_string_2d( triforce(0, 100), triforce(100, 110), 8, 8, 'SCRATCH IS \n ASSEMBLY \n (also banormies) \n https://www.twitch.tv/donutkiller_pro', self.renderer.red()) self.renderer.end_rendering() steer_correction_radians = car_direction.correction_to(car_to_ball) turn = clamp11(steer_correction_radians * -3) if self.flippityThe_CAR < 1: self.howDoIUse_this[self.howDoIUse_this[0][5]] = True self.flippityThe_CAR = 1 elif self.flippityThe_CAR < 2: self.howDoIUse_this[self.howDoIUse_this[0][5]] = False self.flippityThe_CAR = 2 elif self.flippityThe_CAR < 3: self.howDoIUse_this[self.howDoIUse_this[0][5]] = True self.flippityThe_CAR = 3 elif self.flippityThe_CAR < 666: self.howDoIUse_this[self.howDoIUse_this[0][5]] = False self.flippityThe_CAR += 6 elif self.flippityThe_CAR >= 666: self.flippityThe_CAR = 0 self.howDoIUse_this[self.howDoIUse_this[0][0]] = 1 self.howDoIUse_this[self.howDoIUse_this[0][1]] = turn self.howDoIUse_this[self.howDoIUse_this[0][6]] = ( abs(turn) < 0.2 and not my_car.is_super_sonic) self.howDoIUse_this[self.howDoIUse_this[0][7]] = ( abs(turn) > 1.5 and not my_car.is_super_sonic) return getSensible_thingToCONTROL(self.howDoIUse_this)
class AerialStrike(Strike): MAX_DISTANCE_ERROR = 50 DELAY_TAKEOFF = True MINIMAL_HEIGHT = 500 MAXIMAL_HEIGHT = 800 MINIMAL_HEIGHT_TIME = 0.8 MAXIMAL_HEIGHT_TIME = 1.5 DOUBLE_JUMP = False def __init__(self, car: Car, info: GameInfo, target: vec3 = None): self.aerial = Aerial(car) self.aerial.angle_threshold = 0.8 self.aerial.double_jump = self.DOUBLE_JUMP super().__init__(car, info, target) self.arrive.allow_dodges_and_wavedashes = False self.aerialing = False self.too_early = False self._flight_path: List[vec3] = [] def intercept_predicate(self, car: Car, ball: Ball): required_time = range_map(ball.position[2], self.MINIMAL_HEIGHT, self.MAXIMAL_HEIGHT, self.MINIMAL_HEIGHT_TIME, self.MAXIMAL_HEIGHT_TIME) return self.MINIMAL_HEIGHT < ball.position[ 2] < self.MAXIMAL_HEIGHT and ball.time - car.time > required_time def configure(self, intercept: Intercept): super().configure(intercept) self.aerial.target_position = intercept.position - direction( intercept, self.target) * 100 self.aerial.up = normalize( ground_direction(intercept, self.car) + vec3(0, 0, 0.5)) self.aerial.arrival_time = intercept.time @staticmethod def simulate_flight(car: Car, aerial: Aerial, flight_path: List[vec3] = None) -> Car: test_car = Car(car) test_aerial = Aerial(test_car) test_aerial.target_position = aerial.target_position test_aerial.arrival_time = aerial.arrival_time test_aerial.angle_threshold = aerial.angle_threshold test_aerial.up = aerial.up test_aerial.double_jump = aerial.double_jump if flight_path: flight_path.clear() while not test_aerial.finished: test_aerial.step(1 / 120) test_car.boost = 100 # TODO: fix boost depletion in RLU car sim test_car.step(test_aerial.controls, 1 / 120) if flight_path: flight_path.append(vec3(test_car.position)) return test_car def interruptible(self) -> bool: return self.aerialing or super().interruptible() def step(self, dt): time_left = self.aerial.arrival_time - self.car.time if self.aerialing: to_ball = direction(self.car, self.info.ball) # freestyling if self.car.position[2] > 200: # if time_left > 0.7: # rotation = axis_to_rotation(self.car.forward() * 0.5) # self.aerial.up = dot(rotation, self.car.up()) # else: self.aerial.up = vec3(0, 0, -1) + xy(to_ball) self.aerial.target_orientation = look_at(to_ball, vec3(0, 0, -3) + to_ball) self.aerial.step(dt) self.controls = self.aerial.controls self.finished = self.aerial.finished and time_left < -0.3 else: super().step(dt) # simulate aerial from current state simulated_car = self.simulate_flight(self.car, self.aerial, self._flight_path) speed_towards_target = dot( self.car.velocity, ground_direction(self.car, self.aerial.target_position)) speed_needed = ground_distance( self.car, self.aerial.target_position) / time_left # too fast, slow down if speed_towards_target > speed_needed and angle_to( self.car, self.aerial.target_position) < 0.1: self.controls.throttle = -1 # if it ended up near the target, we could take off elif distance( simulated_car, self.aerial.target_position) < self.MAX_DISTANCE_ERROR: if angle_to(self.car, self.aerial.target_position) < 0.1 or norm( self.car.velocity) < 1000: if self.DELAY_TAKEOFF and ground_distance( self.car, self.aerial.target_position) > 1000: # extrapolate current state a small amount of time future_car = Car(self.car) time = 0.5 future_car.time += time displacement = future_car.velocity * time if norm(future_car.velocity) > 500\ else normalize(future_car.velocity) * 500 * time future_car.position += displacement # simulate aerial fot the extrapolated car again future_simulated_car = self.simulate_flight( future_car, self.aerial) # if the aerial is also successful, that means we should continue driving instead of taking off # this makes sure that we go for the most late possible aerials, which are the most effective if distance(future_simulated_car, self.aerial. target_position) > self.MAX_DISTANCE_ERROR: self.aerialing = True else: self.too_early = True else: self.aerialing = True else: # self.controls.boost = True self.controls.throttle = 1 def render(self, draw: DrawingTool): super().render(draw) draw.color(draw.lime if self.aerialing else ( draw.orange if self.too_early else draw.red)) draw.polyline(self._flight_path)
class AerialHandler(): def __init__(self,agent): self.agent = agent self.active = False self.setup() def setup(self): self.aerial = Aerial(self.agent.game.my_car) self.turn = AerialTurn(self.agent.game.my_car) myGoal = center = Vector([0, 5200 * sign(self.agent.team), 200]) enemyGoal = center = Vector([0, 5200 * -sign(self.agent.team), 200]) if self.agent.me.boostLevel > 0: for i in range(0, self.agent.ballPred.num_slices): targetVec = Vector([self.agent.ballPred.slices[i].physics.location.x, self.agent.ballPred.slices[i].physics.location.y, self.agent.ballPred.slices[i].physics.location.z]) # interferenceTimer += self.agent.deltaTime # if interferenceTimer < 1: # if findEnemyClosestToLocation(self.agent,targetVec)[1] < 150: # break if self.agent.ballPred.slices[i].physics.location.z >= 300: goalDist = distance2D(center, targetVec) #if distance2D(myGoal, targetVec) > distance2D(myGoal, self.agent.me.location): if self.agent.me.location[1] * sign(self.agent.team) > self.agent.ballPred.slices[i].physics.location.y * sign(self.agent.team): zOffset = 0 if goalDist < 1500: if targetVec[2] > 600: zOffset = 70 shotAngle = correctAngle(math.degrees(angle2(targetVec, enemyGoal)) + 90 * -sign(self.agent.team)) if abs(shotAngle) <=80: xOffset = clamp(80,-80,(shotAngle*2)*-sign(self.agent.team)) self.aerial.target = vec3(self.agent.ballPred.slices[i].physics.location.x+xOffset, self.agent.ballPred.slices[i].physics.location.y, self.agent.ballPred.slices[i].physics.location.z+zOffset) self.aerial.arrival_time = self.agent.ballPred.slices[i].game_seconds simulation = self.aerial.simulate() # # check if we can reach it by an aerial if norm(simulation.location - self.aerial.target) < 100: self.target_ball = self.agent.ballPred.slices[i] self.xOffset = xOffset self.zOffset = zOffset self.active = True break def stillValid(self): for i in range(0, self.agent.ballPred.num_slices): if self.agent.ballPred.slices[i].physics.location.z >= 300: if abs(self.target_ball.game_seconds - self.agent.ballPred.slices[i].game_seconds) < self.agent.deltaTime*3: difference = 0 difference+= abs((self.agent.ballPred.slices[i].physics.location.x+self.xOffset) - (self.target_ball.physics.location.x+self.zOffset)) difference += abs(self.agent.ballPred.slices[i].physics.location.y - self.target_ball.physics.location.y) difference += abs((self.agent.ballPred.slices[i].physics.location.z+self.zOffset) - (self.target_ball.physics.location.z+self.zOffset)) if difference < 10: self.aerial.target = vec3(self.agent.ballPred.slices[i].physics.location.x + self.xOffset, self.agent.ballPred.slices[i].physics.location.y, self.agent.ballPred.slices[i].physics.location.z + self.zOffset) self.aerial.arrival_time = self.agent.ballPred.slices[i].game_seconds self.target_ball = self.agent.ballPred.slices[i] simulation = self.aerial.simulate() return self.active = False self.setup() def update(self): if self.agent.me.boostLevel > 0: self.setup() self.aerial.step(self.agent.deltaTime) self.controls = self.aerial.controls self.controls.jump = True if self.aerial.finished: self.active = False else: self.active = False return self.controls
def setup(self): self.aerial = Aerial(self.agent.game.my_car) self.turn = AerialTurn(self.agent.game.my_car) myGoal = center = Vector([0, 5120 * sign(self.agent.team), 200]) enemyGoal = center = Vector([0, 5120 * -sign(self.agent.team), 200]) aboveThreshold = False if self.agent.me.boostLevel > 0: for i in range(0, self.agent.ballPred.num_slices): targetVec = Vector([ self.agent.ballPred.slices[i].physics.location.x, self.agent.ballPred.slices[i].physics.location.y, self.agent.ballPred.slices[i].physics.location.z ]) if self.agent.ballPred.slices[i].physics.location.z >= 300: if not aboveThreshold: aboveThreshold = True goalDist = distance2D(center, targetVec) acceptable = False if self.agent.team == 0: if self.agent.me.location[1] < targetVec[1]: acceptable = True else: if self.agent.me.location[1] > targetVec[1]: acceptable = True if acceptable: zOffset = -10 if goalDist < 1500: if targetVec[2] > 600: zOffset = 70 shotAngle = correctAngle( math.degrees(angle2(targetVec, enemyGoal)) + 90 * -sign(self.agent.team)) if self.agent.team == 0: if targetVec[1] >= 0: if abs(targetVec[0]) > 893: if targetVec[0] > 0: closePost = Vector([ 893, 5120 * -sign(self.agent.team), 200 ]) else: closePost = Vector([ -893, 5120 * -sign(self.agent.team), 200 ]) attackAngle = correctAngle( math.degrees( angle2(targetVec, closePost)) + 90 * -sign(self.agent.team)) targetLocal = toLocal( Vector([ self.agent.ballPred.slices[i]. physics.location.x, self.agent.ballPred.slices[i]. physics.location.y, self.agent.ballPred.slices[i]. physics.location.z ]), self.agent.me) carToBallAngle = correctAngle( math.degrees( math.atan2(targetLocal[1], targetLocal[0]))) totalAngle = correctAngle( math.degrees( math.tan(attackAngle) + math.tan(carToBallAngle) / (1 - (math.tan(attackAngle) * math.tan(carToBallAngle))))) if abs(totalAngle) > 60: continue elif self.agent.team == 1: if targetVec[1] <= 0: if abs(targetVec[0]) > 893: if targetVec[0] > 0: closePost = Vector([ 893, 5120 * -sign(self.agent.team), 200 ]) else: closePost = Vector([ -893, 5120 * -sign(self.agent.team), 200 ]) attackAngle = correctAngle( math.degrees( angle2(targetVec, closePost)) + 90 * -sign(self.agent.team)) targetLocal = toLocal( Vector([ self.agent.ballPred.slices[i]. physics.location.x, self.agent.ballPred.slices[i]. physics.location.y, self.agent.ballPred.slices[i]. physics.location.z ]), self.agent.me) carToBallAngle = correctAngle( math.degrees( math.atan2(targetLocal[1], targetLocal[0]))) totalAngle = correctAngle(carToBallAngle + attackAngle) if abs(totalAngle) > 60: continue if abs(shotAngle) <= 75: xOffset = clamp(80, -80, (shotAngle * 2) * -sign(self.agent.team)) self.aerial.target = vec3( self.agent.ballPred.slices[i].physics.location. x + xOffset, self.agent.ballPred.slices[i]. physics.location.y, self.agent.ballPred. slices[i].physics.location.z + zOffset) self.aerial.arrival_time = self.agent.ballPred.slices[ i].game_seconds simulation = self.aerial.simulate() if norm(simulation.location - self.aerial.target) < 100: self.target_ball = self.agent.ballPred.slices[ i] self.xOffset = xOffset self.zOffset = zOffset self.active = True if self.agent.onSurface: if self.agent.ballPred.slices[ i].physics.location.z >= 400: targetLocal = toLocal( Vector([ self.agent.ballPred.slices[i]. physics.location.x + xOffset, self.agent.ballPred.slices[i]. physics.location.y, self.agent.ballPred.slices[i]. physics.location.z + zOffset ]), self.agent.me) carToBallAngle = correctAngle( math.degrees( math.atan2( targetLocal[1], targetLocal[0]))) if abs(carToBallAngle) < 45: if distance2D( self.agent.me.location, targetLocal) > 1500: if self.agent.ballPred.slices[ i].physics.location.z >= 900: self.agent.activeState = airLaunch( self.agent) self.active = False return self.agent.activeState.update( ) break else: if aboveThreshold: break