def run(self, agent: VirxERLU): print("running speedflip routine") if self.stage == 0: agent.controller.boost = True if agent.me.boost > self.old_boost: self.stage = 1 agent.print(f"Next stage: {self.stage}") else: self.old_boost = agent.me.boost elif self.stage == 1: angles = defaultPD( agent, agent.me.local_location(Vector(110 * sign(agent.me.location.x)))) if abs(angles[1]) < 0.1: self.stage = 2 agent.print(f"Next stage: {self.stage}") elif self.stage == 2: agent.push(speed_flip()) self.stage = 3 agent.print(f"Next stage: {self.stage}") elif self.stage == 3: # TODO do a second flip is the opponent is speedflipping as well if False: agent.push( flip( agent.me.local_location( Vector(120 * sign(agent.me.location.x))))) self.stage = 4 agent.print(f"Next stage: {self.stage}") elif self.stage == 4: agent.pop()
def __init__(self, vector, cancel=False): self.vector = vector.normalize() self.pitch = abs(self.vector.x) * -sign(self.vector.x) self.yaw = abs(self.vector.y) * sign(self.vector.y) self.cancel = cancel # the time the jump began self.time = -1 # keeps track of the frames the jump button has been released self.counter = 0
def run(self, agent): ball_slice = agent.ball_prediction_struct.slices[ agent.future_ball_location_slice].physics.location ball_loc = Vector(ball_slice.x, ball_slice.y) agent.line(ball_loc, ball_loc + Vector(z=185), agent.renderer.white()) ball_loc.y *= side(agent.team) if ball_loc.y < -2560 or (ball_loc.y < agent.ball.location.y * side(agent.team)): ball_loc = Vector(agent.ball.location.x, agent.ball.location.y * side(agent.team) + 640) distance = 1280 target = Vector(y=(ball_loc.y + distance) * side(agent.team)) agent.line(target, target + Vector(z=642), (255, 0, 255)) target.x = (abs(ball_loc.x) + (250 if target.y < -1280 else -( 1024 if abs(ball_loc.x) > 1024 else ball_loc.x))) * sign( ball_loc.x) self_to_target = agent.me.location.dist(target) if self_to_target < 250 and ball_loc.y < -640 and agent.me.velocity.magnitude( ) < 100 and abs( Vector(x=1).angle2D( agent.me.local_location(agent.ball.location))) > 0.1: agent.push(face_target(ball=True)) else: self.goto.target = target self.goto.vector = agent.ball.location self.goto.run(agent, manual=True) if self_to_target < 500: agent.controller.boost = False
def run(self, agent): if self.start_time is None: self.start_time = agent.time car_to_boost = self.boost.location - agent.me.location distance_remaining = car_to_boost.flatten().magnitude() agent.line(self.boost.location - Vector(z=500), self.boost.location + Vector(z=500), [0, 255, 0]) if self.target is not None: vector = (self.target - self.boost.location).normalize() side_of_vector = sign(vector.cross(Vector(z=1)).dot(car_to_boost)) car_to_boost_perp = car_to_boost.cross( Vector(z=side_of_vector)).normalize() adjustment = car_to_boost.angle(vector) * distance_remaining / 3.14 final_target = self.boost.location + (car_to_boost_perp * adjustment) car_to_target = (self.target - agent.me.location).magnitude() else: adjustment = 9999 car_to_target = 0 final_target = self.boost.location # Some adjustment to the final target to ensure it's inside the field and we don't try to dirve through any goalposts to reach it if abs(agent.me.location.y) > 5150: final_target.x = cap(final_target.x, -750, 750) local_target = agent.me.local(final_target - agent.me.location) angles = defaultPD(agent, local_target) defaultThrottle(agent, 2300) agent.controller.boost = self.boost.large if abs( angles[1]) < 0.3 else False agent.controller.handbrake = True if abs( angles[1]) > 2.3 else agent.controller.handbrake velocity = 1 + agent.me.velocity.magnitude() if not self.boost.active or agent.me.boost >= 99.0 or distance_remaining < 350: agent.pop() elif agent.me.airborne: agent.push(recovery(self.target)) elif abs(angles[1]) < 0.05 and velocity > 600 and velocity < 2150 and ( distance_remaining / velocity > 2.0 or (adjustment < 90 and car_to_target / velocity > 2.0)): agent.push(flip(local_target)) elif agent.time - self.start_time > 6 and not agent.stack[ -1].__class__.__name__ == "flip": agent.pop()
def run(self, agent, manual=False): car_to_target = self.target - agent.me.location distance_remaining = car_to_target.flatten().magnitude() agent.dbg_2d(distance_remaining) agent.line(self.target - Vector(z=500), self.target + Vector(z=500), [255, 0, 255]) if (not self.brake and distance_remaining < 350) or (self.brake and distance_remaining < (agent.me.local(agent.me.velocity).x ** 2 * -1) / (2 * brake_accel.x)): if not manual: agent.pop() if self.brake: agent.push(brake()) return if self.vector != None: # See commends for adjustment in jump_shot or aerial for explanation side_of_vector = sign(self.vector.cross(Vector(z=1)).dot(car_to_target)) car_to_target_perp = car_to_target.cross(Vector(z=side_of_vector)).normalize() adjustment = car_to_target.angle(self.vector) * distance_remaining / 3.14 final_target = self.target + (car_to_target_perp * adjustment) else: final_target = self.target # Some adjustment to the final target to ensure it's inside the field and we don't try to dirve through any goalposts to reach it if abs(agent.me.location.y) > 5150: final_target.x = cap(final_target.x, -750, 750) local_target = agent.me.local(final_target - agent.me.location) angles = defaultPD(agent, local_target, self.direction) defaultThrottle(agent, 2300, self.direction) if len(agent.friends) > 0 and agent.me.local(agent.me.velocity).x < 250 and agent.controller.throttle > 0.75 and min(agent.me.location.flat_dist(car.location) for car in agent.friends) < 251: agent.push(flip(Vector(y=250))) return if agent.me.boost < 30 or (agent.playstyle is agent.playstyles.Defensive and agent.predictions['self_from_goal'] < 4000): agent.controller.boost = False agent.controller.handbrake = True if abs(angles[1]) >= 2.3 or (agent.me.local(agent.me.velocity).x >= 1400 and abs(angles[1]) > 1.5) else agent.controller.handbrake velocity = 1+agent.me.velocity.magnitude() if abs(angles[1]) < 0.05 and velocity > 600 and velocity < 2150 and distance_remaining / velocity > 2: agent.push(flip(local_target)) elif abs(angles[1]) > 2.8 and velocity < 200 and distance_remaining / velocity > 2: agent.push(flip(local_target, True)) elif agent.me.airborne: agent.push(recovery(self.target))
def run(self, agent): agent.shooting = True raw_time_remaining = self.intercept_time - agent.time # Capping raw_time_remaining above 0 to prevent division problems time_remaining = cap(raw_time_remaining, 0.001, 10.0) car_to_ball = self.ball_location - agent.me.location # whether we are to the left or right of the shot vector side_of_shot = sign( self.shot_vector.cross(Vector(z=1)).dot(car_to_ball)) car_to_dodge_point = self.dodge_point - agent.me.location car_to_dodge_perp = car_to_dodge_point.cross( Vector(z=side_of_shot)) # perpendicular distance_remaining = car_to_dodge_point.magnitude() speed_required = distance_remaining / time_remaining acceleration_required = backsolve( self.dodge_point, agent.me, time_remaining, 0 if not self.jumping else agent.gravity.z) local_acceleration_required = agent.me.local(acceleration_required) # The adjustment causes the car to circle around the dodge point in an effort to line up with the shot vector # The adjustment slowly decreases to 0 as the bot nears the time to jump adjustment = car_to_dodge_point.angle( self.shot_vector) * distance_remaining / 2.0 # size of adjustment # factoring in how close to jump we are adjustment *= (cap(self.jump_threshold - (acceleration_required.z), 0, self.jump_threshold) / self.jump_threshold) # we don't adjust the final target if we are already jumping final_target = self.dodge_point + ( (car_to_dodge_perp.normalize() * adjustment) if not self.jumping else 0) + Vector(z=50) # Ensuring our target isn't too close to the sides of the field, where our car would get messed up by the radius of the curves # Some adjustment to the final target to ensure it's inside the field and we don't try to dirve through any goalposts to reach it if abs(agent.me.location.y) > 5150: final_target.x = cap(final_target.x, -750, 750) local_final_target = agent.me.local(final_target - agent.me.location) # drawing debug lines to show the dodge point and final target (which differs due to the adjustment) agent.line(agent.me.location, self.dodge_point, agent.renderer.white()) agent.line(self.dodge_point - Vector(z=100), self.dodge_point + Vector(z=100), agent.renderer.red()) agent.line(final_target - Vector(z=100), final_target + Vector(z=100), agent.renderer.green()) # Calling our drive utils to get us going towards the final target angles = defaultPD(agent, local_final_target, self.direction) defaultThrottle(agent, speed_required, self.direction) agent.line(agent.me.location, agent.me.location + (self.shot_vector * 200), agent.renderer.white()) agent.controller.boost = False if abs( angles[1]) > 0.3 or agent.me.airborne else agent.controller.boost agent.controller.handbrake = True if abs( angles[1] ) > 2.3 and self.direction == 1 else agent.controller.handbrake if not self.jumping: if raw_time_remaining <= 0 or ( speed_required - 2300) * time_remaining > 45 or not shot_valid(agent, self): # If we're out of time or not fast enough to be within 45 units of target at the intercept time, we pop agent.pop() agent.shooting = False agent.shot_weight = -1 agent.shot_time = -1 if agent.me.airborne: agent.push(recovery()) elif local_acceleration_required.z > self.jump_threshold and local_acceleration_required.z > local_acceleration_required.flatten( ).magnitude(): # Switch into the jump when the upward acceleration required reaches our threshold, and our lateral acceleration is negligible self.jumping = True else: if (raw_time_remaining > 0.2 and not shot_valid(agent, self, 150) ) or raw_time_remaining <= -0.9 or (not agent.me.airborne and self.counter > 0): agent.pop() agent.shooting = False agent.shot_weight = -1 agent.shot_time = -1 agent.push(recovery()) elif self.counter == 0 and local_acceleration_required.z > 0 and raw_time_remaining > 0.083: # Initial jump to get airborne + we hold the jump button for extra power as required agent.controller.jump = True elif self.counter < 3: # make sure we aren't jumping for at least 3 frames agent.controller.jump = False self.counter += 1 elif raw_time_remaining <= 0.1 and raw_time_remaining > -0.9: # dodge in the direction of the shot_vector agent.controller.jump = True if not self.dodging: vector = agent.me.local(self.shot_vector) self.p = abs(vector.x) * -sign(vector.x) self.y = abs(vector.y) * sign(vector.y) * self.direction self.dodging = True # simulating a deadzone so that the dodge is more natural agent.controller.pitch = self.p if abs(self.p) > 0.2 else 0 agent.controller.yaw = self.y if abs(self.y) > 0.3 else 0
def run(self, agent): agent.shooting = True raw_time_remaining = self.intercept_time - agent.time # Capping raw_time_remaining above 0 to prevent division problems time_remaining = cap(raw_time_remaining, 0.001, 10.0) car_to_ball = self.ball_location - agent.me.location # whether we are to the left or right of the shot vector side_of_shot = sign( self.shot_vector.cross(Vector(z=1)).dot(car_to_ball)) car_to_intercept = self.intercept - agent.me.location car_to_intercept_perp = car_to_intercept.cross( Vector(z=side_of_shot)) # perpendicular distance_remaining = car_to_intercept.flatten().magnitude() speed_required = distance_remaining / time_remaining # When still on the ground we pretend agent.gravity doesn't exist, for better or worse acceleration_required = backsolve( self.intercept, agent.me, time_remaining, 0 if self.jump_time == 0 else agent.gravity.z) local_acceleration_required = agent.me.local(acceleration_required) # The adjustment causes the car to circle around the dodge point in an effort to line up with the shot vector # The adjustment slowly decreases to 0 as the bot nears the time to jump adjustment = car_to_intercept.angle( self.shot_vector) * distance_remaining / 1.57 # size of adjustment # factoring in how close to jump we are adjustment *= cap(self.jump_threshold - (acceleration_required.z), 0, self.jump_threshold) / self.jump_threshold # we don't adjust the final target if we are already jumping final_target = self.intercept + ( (car_to_intercept_perp.normalize() * adjustment) if self.jump_time == 0 else 0) # Some extra adjustment to the final target to ensure it's inside the field and we don't try to dirve through any goalposts to reach it if abs(agent.me.location.y) > 5150: final_target.x = cap(final_target.x, -750, 750) local_final_target = agent.me.local(final_target - agent.me.location) # drawing debug lines to show the dodge point and final target (which differs due to the adjustment) agent.line(agent.me.location, self.intercept, agent.renderer.white()) agent.line(self.intercept - Vector(z=100), self.intercept + Vector(z=100), agent.renderer.red()) agent.line(final_target - Vector(z=100), final_target + Vector(z=100), agent.renderer.green()) angles = defaultPD(agent, local_final_target) if self.jump_time == 0: defaultThrottle(agent, speed_required) agent.controller.boost = False if abs( angles[1] ) > 0.3 or agent.me.airborne else agent.controller.boost agent.controller.handbrake = True if abs( angles[1]) > 2.3 else agent.controller.handbrake if acceleration_required.z > self.jump_threshold: # Switch into the jump when the upward acceleration required reaches our threshold, hopefully we have aligned already... self.jump_time = agent.time else: time_since_jump = agent.time - self.jump_time # While airborne we boost if we're within 30 degrees of our local acceleration requirement if agent.me.airborne and local_acceleration_required.magnitude( ) * time_remaining > 100: angles = defaultPD(agent, local_acceleration_required) if abs(angles[0]) + abs(angles[1]) < 0.5: agent.controller.boost = True if self.counter == 0 and (time_since_jump <= 0.2 and local_acceleration_required.z > 0): # hold the jump button up to 0.2 seconds to get the most acceleration from the first jump agent.controller.jump = True elif time_since_jump > 0.2 and self.counter < 3: # Release the jump button for 3 ticks agent.controller.jump = False self.counter += 1 elif local_acceleration_required.z > 300 and self.counter == 3: # the acceleration from the second jump is instant, so we only do it for 1 frame agent.controller.jump = True agent.controller.pitch = 0 agent.controller.yaw = 0 agent.controller.roll = 0 self.counter += 1 if raw_time_remaining < -0.25 or not shot_valid(agent, self): agent.pop() agent.shooting = False agent.shot_weight = -1 agent.shot_time = -1 agent.push(recovery())
def run(self, agent): if not agent.shooting: agent.shooting = True T = self.intercept_time - agent.time # Capping T above 0 to prevent division problems time_remaining = cap(T, 0.000001, 6) slice_n = round(T * 60) agent.dbg_2d(f"Shot slice #: {slice_n}") if T > 0.3 or self.ball_location is None: ball = agent.ball_prediction_struct.slices[ slice_n].physics.location self.ball_location = Vector(ball.x, ball.y, ball.z) self.dodge_point = self.ball_location - (self.shot_vector * agent.best_shot_value) if self.dodge_point.z > 300: agent.pop() return car_to_ball = self.ball_location - agent.me.location # whether we should go forwards or backwards angle_to_target = abs(Vector(x=1).angle2D(agent.me.local(car_to_ball))) # whether we are to the left or right of the shot vector side_of_shot = sign( self.shot_vector.cross(Vector(z=1)).dot(car_to_ball)) final_target = self.dodge_point.copy() # Some adjustment to the final target to ensure it's inside the field and we don't try to drive through any goalposts to reach it if abs(agent.me.location.y) > 5120 - (agent.me.hitbox.length / 2): final_target.x = cap(final_target.x, -750, 750) car_to_dodge_point = final_target - agent.me.location car_to_dodge_perp = car_to_dodge_point.cross( Vector(z=side_of_shot)) # perpendicular acceleration_required = backsolve( self.dodge_point, agent.me, time_remaining, Vector() if not self.jumping else agent.gravity) local_acceleration_required = agent.me.local(acceleration_required) distance_remaining = car_to_dodge_point.flatten().magnitude() # The adjustment causes the car to circle around the dodge point in an effort to line up with the shot vector # The adjustment slowly decreases to 0 as the bot nears the time to jump adjustment = car_to_dodge_point.angle2D( self.shot_vector) * distance_remaining / 2 # size of adjustment # controls how soon car will jump based on acceleration required # we set this based on the time remaining # bigger = later, which allows more time to align with shot vector # smaller = sooner jump_threshold = cap(T * 200, 250, 584) # factoring in how close to jump we are adjustment *= (cap(jump_threshold - (acceleration_required.z), 0, jump_threshold) / jump_threshold) # we don't adjust the final target if we are already jumping final_target += ((car_to_dodge_perp.normalize() * adjustment) if not self.jumping else 0) + Vector(z=50) distance_remaining = (final_target - agent.me.location).flatten().magnitude() direction = 1 if angle_to_target < 2.1 or ( agent.gravity.z > -450 and distance_remaining >= 1000) else -1 local_final_target = agent.me.local_location(final_target) # drawing debug lines to show the dodge point and final target (which differs due to the adjustment) agent.line(agent.me.location, self.dodge_point, agent.renderer.white()) agent.line(self.dodge_point - Vector(z=100), self.dodge_point + Vector(z=100), agent.renderer.green()) agent.line(final_target - Vector(z=100), final_target + Vector(z=100), agent.renderer.blue()) vf = agent.me.velocity + agent.gravity * T xf = agent.me.location + agent.me.velocity * T + 0.5 * agent.gravity * T * T ball_l = agent.me.local_location(agent.ball.location) speed_required = 2300 if ( self.ball_location.z < 92 + agent.me.hitbox.height / 2 and abs(ball_l.y) < 46 and ball_l.x > agent.me.hitbox.length ) or distance_remaining > 2560 else distance_remaining * 0.975 / time_remaining agent.dbg_2d(f"Speed required: {speed_required}") if not self.jumping: defaultPD(agent, local_final_target) defaultThrottle(agent, speed_required * direction) agent.controller.handbrake = angle_to_target > 1.54 if direction == 1 else angle_to_target < 2.2 local_dodge_point = agent.me.local_location( self.dodge_point.flatten()) # use algebra to get the required jump time min_jump_time = self.dodge_point - agent.me.location min_jump_time -= agent.me.velocity * T min_jump_time -= 0.5 * agent.gravity * T * T min_jump_time -= agent.me.up * jump_speed * T min_jump_time /= jump_acc # This leaves us with xf = dT - 0.5d^2, so we use the quadratic formula to solve it min_jump_time = max(quadratic(-0.5, T, sum(min_jump_time) / 3)) min_jump_time += 0.05 f_vf = vf + (agent.me.up * (jump_speed + jump_acc * min_jump_time)) local_vf = agent.me.local(f_vf.flatten()) velocity = agent.me.local_velocity().x if T <= 0 or not virxrlcu.jump_shot_is_viable( T + 0.3, agent.boost_accel, agent.me.location.dist( self.ball_location), self.shot_vector.tuple(), agent.me.forward.tuple(), agent.me.boost if agent.boost_amount != 'unlimited' else 100000, velocity): # If we're out of time or not fast enough to be within 45 units of target at the intercept time, we pop agent.pop() agent.shooting = False agent.shot_weight = -1 agent.shot_time = -1 if agent.me.airborne: agent.push(recovery()) elif self.dodge_point.z > 92 + agent.me.hitbox.height / 2 and ( (T <= min_jump_time and self.dodge_point.z >= 175) or (T <= 0.3 and self.dodge_point.z < 175)) and abs(local_dodge_point.y) < ( 92 if find_slope(self.shot_vector, car_to_ball) > 2 or self.dodge_point.z <= 92 + agent.me.hitbox.height / 2 else math.ceil(92 + agent.me.hitbox.width / 2)) and local_vf.x >= local_dodge_point.x: # Switch into the jump when the upward acceleration required reaches our threshold, and our lateral acceleration is negligible self.jumping = True elif agent.boost_amount != 'unlimited' and angle_to_target < 0.03 and velocity > 600 and velocity < speed_required - 150 and distance_remaining / velocity > 3: if agent.gravity.z < -450: agent.push(wave_dash()) else: agent.push(flip(local_final_target)) elif direction == -1 and velocity < 200 and distance_remaining / abs( velocity) > 2: agent.push(flip(local_final_target, True)) elif agent.me.airborne: agent.push(recovery(local_final_target)) else: if self.jump_time == -1: self.jump_time = agent.time jump_elapsed = agent.time - self.jump_time tau = jump_max_duration - jump_elapsed if jump_elapsed == 0: vf += agent.me.up * jump_speed xf += agent.me.up * jump_speed * T vf += agent.me.up * jump_acc * tau xf += agent.me.up * jump_acc * tau * (T - 0.5 * tau) delta_x = self.dodge_point - xf d_direction = delta_x.normalize() if abs(agent.me.forward.dot( d_direction)) > 0.5 and self.counter < 3: delta_v = delta_x.dot(agent.me.forward) / T if agent.me.boost > 0 and delta_v >= agent.boost_accel * min_boost_time: agent.controller.boost = True else: agent.controller.throttle = cap( delta_v / (throttle_accel * min_boost_time), -1, 1) if T <= -0.4 or (not agent.me.airborne and self.counter >= 3): agent.pop() agent.shooting = False agent.shot_weight = -1 agent.shot_time = -1 agent.push(recovery()) return else: if self.counter == 3 and agent.me.location.dist( self.dodge_point) < (92.75 + agent.me.hitbox.length) * 1.05: # Get the required pitch and yaw to flip correctly vector = agent.me.local(self.shot_vector) self.p = abs(vector.x) * -sign(vector.x) self.y = abs(vector.y) * sign(vector.y) * direction # simulating a deadzone so that the dodge is more natural self.p = cap(self.p, -1, 1) if abs(self.p) > 0.1 else 0 self.y = cap(self.y, -1, 1) if abs(self.y) > 0.1 else 0 agent.controller.pitch = self.p agent.controller.yaw = self.y # Wait 1 more frame before dodging self.counter += 1 elif self.counter == 4: # Dodge agent.controller.jump = True agent.controller.pitch = self.p agent.controller.yaw = self.y else: # Face the direction we're heading in, with the z of our target target = agent.me.local(agent.me.velocity.flatten()) target.z = agent.me.local_location(self.dodge_point).z defaultPD(agent, target) if jump_elapsed < jump_max_duration and vf.z < self.dodge_point.z: # Initial jump to get airborne + we hold the jump button for extra power as required agent.controller.jump = True elif self.counter < 3: # Make sure we aren't jumping for at least 3 frames self.counter += 1 l_vf = vf + agent.me.location agent.line(l_vf - Vector(z=100), l_vf + Vector(z=100), agent.renderer.red())
def run(self, agent, manual=False): car_to_target = self.target - agent.me.location distance_remaining = car_to_target.flatten().magnitude() angle_to_target = abs( Vector(x=1).angle2D(agent.me.local(car_to_target))) direction = 1 if angle_to_target <= 2 or ( agent.gravity.z > -450 and distance_remaining >= 1000) else -1 agent.dbg_2d(f"Angle to target: {angle_to_target}") agent.dbg_2d(f"Distance to target: {distance_remaining}") agent.line(self.target - Vector(z=500), self.target + Vector(z=500), (255, 0, 255)) if (not self.brake and distance_remaining < 350) or ( self.brake and distance_remaining * 0.95 < (agent.me.local_velocity().x**2 * -1) / (2 * brake_accel.x)): if not manual: agent.pop() if self.brake: agent.push(brake()) return final_target = self.target.copy() # Some adjustment to the final target to ensure it's inside the field and we don't try to drive through any goalposts to reach it if abs(agent.me.location.y) > 5120 - (agent.me.hitbox.length / 2): final_target.x = cap(final_target.x, -750, 750) if self.vector is not None: # See comments for adjustment in jump_shot for explanation side_of_vector = sign( self.vector.cross(Vector(z=1)).dot(car_to_target)) car_to_target_perp = car_to_target.cross( Vector(z=side_of_vector)).normalize() adjustment = car_to_target.angle2D( self.vector) * distance_remaining / 3.14 final_target += car_to_target_perp * adjustment local_target = agent.me.local_location(final_target) defaultPD(agent, local_target) target_speed = 2300 if distance_remaining > 640 else 1400 defaultThrottle(agent, target_speed * direction) # this is to break rule 1's with TM8'S ONLY # 251 is the distance between center of the 2 longest cars in the game, with a bit extra if len(agent.friends) > 0 and agent.me.local_velocity( ).x < 50 and agent.controller.throttle == 1 and min( agent.me.location.flat_dist(car.location) for car in agent.friends) < 251: if self.rule1_timer == -1: self.rule1_timer = agent.time elif agent.time - self.rule1_timer > 1.5: agent.push(flip(Vector(y=250))) return elif self.rule1_timer != -1: self.rule1_timer = -1 if distance_remaining < 320: agent.controller.boost = False agent.controller.handbrake = angle_to_target > 1.54 if direction == 1 else angle_to_target < 2.2 velocity = agent.me.local_velocity().x if agent.boost_amount != 'unlimited' and angle_to_target < 0.03 and distance_remaining > 1920 and velocity > 600 and velocity < 2150 and distance_remaining / velocity > 2: if agent.gravity.z < -450: agent.push(wave_dash()) else: agent.push(flip(local_target)) elif direction == -1 and distance_remaining > 1000 and velocity < 200: agent.push(flip(local_target, True)) elif agent.me.airborne: agent.push(recovery(self.target))
def run(self, agent): if not agent.shooting: agent.shooting = True if self.time == -1: self.time = agent.time elapsed = agent.time - self.time T = self.intercept_time - agent.time xf = agent.me.location + agent.me.velocity * T + 0.5 * agent.gravity * T * T vf = agent.me.velocity + agent.gravity * T slice_n = math.ceil(T * 60) agent.dbg_2d(f"Shot slice #: {slice_n}") if T > 0.1 or self.target is None: ball = agent.ball_prediction_struct.slices[ slice_n].physics.location self.ball = Vector(ball.x, ball.y, ball.z) self.target = self.ball - (self.shot_vector * agent.best_shot_value * 0.8) if agent.me.location.z > 2044 - agent.me.hitbox.height * 1.1: self.ceiling = True self.target -= Vector(z=92) if not self.ceiling and (self.jumping or not agent.me.airborne): agent.dbg_2d("Jumping") if not self.jumping or not agent.me.airborne: self.jumping = True self.jump_time = agent.time self.counter = 0 jump_elapsed = agent.time - self.jump_time tau = jump_max_duration - jump_elapsed if jump_elapsed == 0: vf += agent.me.up * jump_speed xf += agent.me.up * jump_speed * T vf += agent.me.up * jump_acc * tau xf += agent.me.up * jump_acc * tau * (T - 0.5 * tau) if self.fast_aerial: vf += agent.me.up * jump_speed xf += agent.me.up * jump_speed * (T - tau) if jump_elapsed < jump_max_duration: agent.controller.jump = True elif self.counter < 6: self.counter += 1 if self.counter == 3: agent.controller.jump = True self.dodging = True elif self.counter == 6: self.dodging = self.jumping = False elif jump_elapsed < jump_max_duration: agent.controller.jump = True else: self.jumping = False if self.ceiling: agent.dbg_2d(f"Ceiling shot") delta_x = self.target - xf direction = delta_x.normalize() agent.line(agent.me.location, self.target, agent.renderer.white()) c_vf = vf + agent.me.location agent.line(c_vf - Vector(z=100), c_vf + Vector(z=100), agent.renderer.blue()) agent.line(xf - Vector(z=100), xf + Vector(z=100), agent.renderer.red()) agent.line(self.target - Vector(z=100), self.target + Vector(z=100), agent.renderer.green()) if not self.dodging: target = delta_x if delta_x.magnitude() > 50 else ( self.target - agent.me.location) if self.jumping: target = target.flatten() target = agent.me.local(target) if abs(Vector(x=1).angle(target)) > 0.005: defaultPD(agent, target, upside_down=self.shot_vector.z < 0 and not self.jumping) if abs(agent.me.forward.dot(direction)) > 0.5: delta_v = delta_x.dot(agent.me.forward) / T if agent.me.boost > 0 and delta_v >= agent.boost_accel * min_boost_time: agent.controller.boost = True else: agent.controller.throttle = cap( delta_v / (throttle_accel * min_boost_time), -1, 1) if T <= 0 or (not self.jumping and not agent.me.airborne) or ( not self.jumping and T > 2 and self.fast_aerial and not virxrlcu.aerial_shot_is_viable( T + 0.3, 144, agent.boost_accel, agent.gravity.tuple(), agent.me.location.tuple(), agent.me.velocity.tuple(), agent.me.up.tuple(), agent.me.forward.tuple(), 1 if agent.me.airborne else -1, agent.me.boost if agent.boost_amount != 'unlimited' else 100000, self.ball.tuple())): agent.pop() agent.shooting = False agent.shot_weight = -1 agent.shot_time = -1 agent.push(ball_recovery()) elif (self.ceiling and self.target.dist(agent.me.location) < 92 + agent.me.hitbox.length and not agent.me.doublejumped and agent.me.location.z < agent.ball.location.z + 92 and self.target.y * side(agent.team) > -4240) or ( not self.ceiling and not self.fast_aerial and self.target.dist(agent.me.location) < 92 + agent.me.hitbox.length and not agent.me.doublejumped): agent.dbg_2d("Flipping") agent.controller.jump = True local_target = agent.me.local_location(self.target) agent.controller.pitch = abs( local_target.x) * -sign(local_target.x) agent.controller.yaw = abs(local_target.y) * sign(local_target.y)
def run(self, agent): # This routine is the same as jump_shot, but it's designed to hit the ball above 250uus (and below 551uus or so) without any boost if not agent.shooting: agent.shooting = True T = self.intercept_time - agent.time # Capping T above 0 to prevent division problems time_remaining = cap(T, 0.000001, 6) slice_n = round(T * 60) agent.dbg_2d(f"Shot slice #: {slice_n}") if T > 0.3 or self.ball_location is None: ball = agent.ball_prediction_struct.slices[ slice_n].physics.location self.ball_location = Vector(ball.x, ball.y, ball.z) self.dodge_point = self.ball_location - (self.shot_vector * agent.best_shot_value) if self.dodge_point.z > 490 or self.dodge_point.z < 380: agent.pop() return car_to_ball = self.ball_location - agent.me.location # whether we should go forwards or backwards angle_to_target = abs( Vector(x=1).angle2D(agent.me.local_location(self.dodge_point))) # whether we are to the left or right of the shot vector side_of_shot = sign( self.shot_vector.cross(Vector(z=1)).dot(car_to_ball)) final_target = self.dodge_point.copy() # Some adjustment to the final target to ensure it's inside the field and we don't try to drive through any goalposts to reach it if abs(agent.me.location.y) > 5120 - (agent.me.hitbox.length / 2): final_target.x = cap(final_target.x, -750, 750) car_to_dodge_point = final_target - agent.me.location car_to_dodge_perp = car_to_dodge_point.cross( Vector(z=side_of_shot)) # perpendicular distance_remaining = car_to_dodge_point.flatten().magnitude() acceleration_required = backsolve( self.dodge_point, agent.me, time_remaining, Vector() if not self.jumping else agent.gravity) local_acceleration_required = agent.me.local_velocity( acceleration_required) # The adjustment causes the car to circle around the dodge point in an effort to line up with the shot vector # The adjustment slowly decreases to 0 as the bot nears the time to jump adjustment = car_to_dodge_point.angle2D( self.shot_vector) * distance_remaining / 2 # size of adjustment # controls how soon car will jump based on acceleration required # we set this based on the time remaining # bigger = later, which allows more time to align with shot vector # smaller = sooner jump_threshold = cap(T * 200, 250, 584) # factoring in how close to jump we are adjustment *= (cap(jump_threshold - (acceleration_required.z), 0, jump_threshold) / jump_threshold) # we don't adjust the final target if we are already jumping final_target += ((car_to_dodge_perp.normalize() * adjustment) if not self.jumping else 0) + Vector(z=50) distance_remaining = (final_target - agent.me.location).flatten().magnitude() local_final_target = agent.me.local_location(final_target) # drawing debug lines to show the dodge point and final target (which differs due to the adjustment) agent.line(agent.me.location, self.dodge_point, agent.renderer.white()) agent.line(self.dodge_point - Vector(z=100), self.dodge_point + Vector(z=100), agent.renderer.green()) vf = agent.me.velocity + agent.gravity * T distance = agent.me.local_location( self.dodge_point).x if agent.me.airborne else distance_remaining speed_required = 2300 if distance_remaining > 2560 else distance / time_remaining agent.dbg_2d(f"Speed required: {speed_required}") if not self.jumping: velocity = agent.me.local_velocity().x local_dodge_point = agent.me.local_location( self.dodge_point.flatten()) local_vf = agent.me.local(vf.flatten()) if T <= 0 or not virxrlcu.double_jump_shot_is_viable( T + 0.3, agent.boost_accel, agent.me.location.dist( self.ball_location), self.shot_vector.tuple(), agent.me.forward.tuple(), agent.me.boost if agent.boost_amount != 'unlimited' else 100000, velocity): # If we're out of time or the ball was hit away or we just can't get enough speed, pop agent.pop() agent.shooting = False agent.shot_weight = -1 agent.shot_time = -1 if agent.me.airborne: agent.push(ball_recovery()) elif abs(local_dodge_point.y ) < 92 and local_vf.x >= local_dodge_point.x: # Switch into the jump when the upward acceleration required reaches our threshold, and our lateral acceleration is negligible, and we're close enough to the point in time where the ball will be at the given location self.jumping = True elif agent.boost_amount != 'unlimited' and angle_to_target < 0.03 and velocity > 600 and velocity < speed_required - 500 and distance_remaining / velocity > 3: if agent.gravity.z < -450: agent.push(wave_dash()) else: agent.push(flip(local_final_target)) elif agent.boost_amount != 'unlimited' and angle_to_target >= 2 and distance_remaining > 1000 and velocity < 200: agent.push(flip(local_final_target, True)) elif agent.me.airborne: agent.push(recovery(local_final_target)) else: defaultPD(agent, local_final_target) defaultThrottle(agent, speed_required) agent.controller.handbrake = angle_to_target > 1.54 else: # Mark the time we started jumping so we know when to dodge if self.jump_time == -1: self.jump_time = agent.time jump_elapsed = agent.time - self.jump_time tau = jump_max_duration - jump_elapsed xf = agent.me.location + agent.me.velocity * T + 0.5 * agent.gravity * T * T if jump_elapsed == 0: vf += agent.me.up * jump_speed xf += agent.me.up * jump_speed * T vf += agent.me.up * jump_acc * tau xf += agent.me.up * jump_acc * tau * (T - 0.5 * tau) vf += agent.me.up * jump_speed xf += agent.me.up * jump_speed * (T - tau) delta_x = self.dodge_point - xf direction = delta_x.normalize() if abs(agent.me.forward.dot(direction)) > 0.5: delta_v = delta_x.dot(agent.me.forward) / T if agent.me.boost > 0 and delta_v >= agent.boost_accel * min_boost_time: agent.controller.boost = True else: agent.controller.throttle = cap( delta_v / (throttle_accel * min_boost_time), -1, 1) if T <= -0.4 or (not agent.me.airborne and self.counter > 0): agent.pop() agent.shooting = False agent.shot_weight = -1 agent.shot_time = -1 agent.push(ball_recovery()) elif jump_elapsed < jump_max_duration and vf.z <= self.dodge_point.z: agent.controller.jump = True elif self.counter < 4: self.counter += 1 if self.counter == 3: agent.controller.jump = True elif self.counter == 4: defaultPD(agent, agent.me.local_location(self.dodge_point), upside_down=True) if self.counter < 3: defaultPD( agent, agent.me.local( (self.dodge_point - agent.me.location).flatten())) l_vf = vf + agent.me.location agent.line(l_vf - Vector(z=100), l_vf + Vector(z=100), agent.renderer.red())
def run(self): """ This is for state setting the ball to high up for aerial testing "" if not self.shooting and self.ball.location.z < 98: ball_state = BallState(Physics(location=GSVec3(0, -3000, self.ball.location.z), velocity=GSVec3(0, 0, 2000), angular_velocity=GSVec3(0, 0, 0))) game_state = GameState(ball=ball_state) self.set_game_state(game_state) if not self.shooting: self.smart_shot((self.foe_goal.left_post, self.foe_goal.right_post)) if self.is_clear(): self.push(goto(Vector(), self.foe_goal.location)) """ self.dbg_3d(self.playstyle.name) for _ in range(len(self.friends) + len(self.foes) + 1): try: msg = self.matchcomms.incoming_broadcast.get_nowait() except Empty: break if msg.get("VirxEB" ) is not None and msg['VirxEB']['team'] is self.team: msg = msg['VirxEB'] if self.playstyle is self.playstyles.Defensive: if msg.get("match_defender") and msg['index'] < self.index: self.playstyle = self.playstyles.Neutral self.clear() self.goto_nearest_boost() self.can_shoot = self.time self.print("You can defend") elif self.playstyle is self.playstyles.Offensive: if msg.get("attacking") and msg['index'] < self.index: self.playstyle = self.playstyles.Neutral self.clear() self.goto_nearest_boost() self.kickoff_done = True self.can_shoot = self.time self.print("All yours!") if not self.kickoff_done: if self.is_clear(): if len(self.friends) > 0: try: if almost_equals( min(self.predictions['teammates_to_ball']), self.predictions['self_to_ball'], 5): self.offensive_kickoff() elif almost_equals( max(self.predictions['teammates_to_ball']), self.predictions['self_to_ball'], 5): self.defensive_kickoff() except ValueError: return elif almost_equals(self.predictions['closest_enemy'], self.predictions['self_to_ball'], 50): self.offensive_kickoff() else: self.can_shoot = self.time self.defensive_kickoff() else: if self.can_shoot is not None and self.time - self.can_shoot >= 3: self.can_shoot = None if not self.is_clear( ) and self.stack[0].__class__.__name__ == "atba" and ( self.predictions['closest_enemy'] < 1000 or self.ball_to_goal > 1500): self.clear() elif self.is_clear() and self.predictions[ 'closest_enemy'] is not None and self.predictions[ 'closest_enemy'] > 2500 and self.ball_to_goal < 1500 and side( self.team) is sign(self.me.location.y) and abs( self.me.location.y) > 5400: self.push(atba()) self.playstyles_switch[self.playstyle]() if self.debug_ball_path: ball_prediction = self.predictions['ball_struct'] if ball_prediction is not None: for i in range( 0, ball_prediction.num_slices - (ball_prediction.num_slices % self.debug_ball_path_precision) - self.debug_ball_path_precision, self.debug_ball_path_precision): self.line( ball_prediction.slices[i].physics.location, ball_prediction.slices[ i + self.debug_ball_path_precision].physics. location) if self.shooting and self.shot_weight != -1: self.dbg_2d(self.stack[0].intercept_time - self.time) ""
def goto_nearest_boost(self, only_small=False, clear_on_valid=False): if self.is_clear() or clear_on_valid: self.send_quick_chat(QuickChats.CHAT_TEAM_ONLY, QuickChats.Information_NeedBoost) ball_slice = self.ball_prediction_struct.slices[min( round(self.future_ball_location_slice * 1.1), 6)].physics ball = Vector(ball_slice.location.x, ball_slice.location.y, ball_slice.location.z) ball_v = Vector(ball_slice.velocity.x, ball_slice.velocity.y, ball_slice.velocity.z) ball_y = ball.y * side(self.team) if not only_small: if len(self.friends) > 0: large_boosts = ( boost for boost in self.boosts if boost.large and boost.active and ( (self.playstyle is self.playstyles.Offensive and boost.location.y * side(self.team) < -3000) or (self.playstyle is self.playstyles.Neutral and boost.location.y * side(self.team) > -100) or (self.playstyle is self.playstyles.Defensive and boost.location.y * side(self.team) > 3000))) else: if (ball_v.angle2D(self.foe_goal.location - ball) < 1 and ball_y > 0) or abs( ball.x) < 900 or self.predictions['own_goal']: large_boosts = None else: ball_x = sign(ball.x) large_boosts = ( boost for boost in self.boosts if boost.large and boost.active and ( boost.location.y * side(self.team) > ball_y - 50) and sign(boost.location.x) == ball_x) if large_boosts is not None: closest = peek_generator(large_boosts) if closest is not None: closest_distance = closest.location.flat_dist( self.me.location) for item in large_boosts: item_distance = item.location.flat_dist( self.me.location) if item_distance is closest_distance: if item.location.flat_dist( self.me.location ) < closest.location.flat_dist( self.me.location): closest = item closest_distance = item_distance elif item_distance < closest_distance: closest = item closest_distance = item_distance if clear_on_valid: self.clear() self.push(goto_boost(closest)) return True if (ball_v.angle2D(self.foe_goal.location - ball) < 1 and ball_y > 0) or self.predictions['own_goal']: return False ball_x = sign(ball.x) small_boosts = (boost for boost in self.boosts if not boost.large and boost.active and boost.location.y * side(self.team) > ball_y - 50 and sign(boost.location.x) == ball_x) closest = peek_generator(small_boosts) if closest is not None: closest_distance = closest.location.flat_dist( self.me.location) + (closest.location.flat_dist( self.friend_goal.location) / 400) for item in small_boosts: item_distance = item.location.flat_dist( self.me.location) + (item.location.flat_dist( self.friend_goal.location) / 400) if item_distance < closest_distance: item_loc = item.location.y * side(self.team) if (self.playstyle is self.playstyles.Offensive and item_loc < -2560 ) or ( self.playstyle is self.playstyles.Neutral and item_loc < -100) or ( self.playstyle is self.playstyles.Defensive and item_loc > 1280): closest = item closest_distance = item_distance if clear_on_valid: self.clear() self.push(goto_boost(closest)) return True return False