def ones_defense_offense_switch_test(agent): #returns 1 if the bot should go on offense, 0 if it should go on defense, and -1 if it should go on panic defence. my_align = align_goalposts(agent.me.location, agent.ball.location, agent.foe_goal.left_post, agent.foe_goal.right_post) foe_align = align_goalposts(agent.foes[0].location, agent.ball.location, agent.friend_goal.left_post, agent.friend_goal.right_post) my_distance_to_ball = (agent.me.location - agent.ball.location).magnitude() foe_distance_to_ball = (agent.foes[0].location - agent.ball.location).magnitude() if my_align > 0.0 and foe_align < 0.0: if my_distance_to_ball < foe_distance_to_ball or ball_going_into_their_danger_zone( agent): return 2 else: return 1 elif my_align < 0.0 and foe_align > 0.0: return -1 elif my_align > 0.0 and foe_align < 0.0: if agent.ball_location.y * side(agent.team) > 3600: return 0 elif my_distance_to_ball * 3.1 < foe_distance_to_ball or ball_going_into_their_danger_zone( agent): return 2 elif my_distance_to_ball * 1.5 < foe_distance_to_ball: return 1 else: return 0 return -1
def get_closest_post_vector(agent, future_ball_location=None): y = 4400 * utils.side(agent.team) z = 0 closest_post = closest_point( agent.me.location, [agent.friend_goal.left_post, agent.friend_goal.right_post]) return_value = Vector3(closest_post.x, y, z) return return_value
def __init__(self, bbox): filename, x1, x2, x3, x4, y1, y2, y3, y4, ground_truth, language = bbox['filename'], \ bbox['x1'], bbox['x2'], bbox['x3'], \ bbox['x4'], bbox['y1'], bbox['y2'], \ bbox['y3'], bbox['y4'], \ bbox['ground_truth'], bbox['language'] self.top_left = pd.concat([x1, y1], axis=1) self.top_right = pd.concat([x2, y2], axis=1) self.bottom_right = pd.concat([x3, y3], axis=1) self.bottom_left = pd.concat([x4, y4], axis=1) self.side1 = side(self.top_right, self.top_left) self.side2 = side(self.top_right, self.bottom_right) self.side3 = side(self.bottom_left, self.bottom_right) self.side4 = side(self.top_left, self.bottom_left) self.label = ground_truth self.height = pd.concat([self.side2, self.side4], axis=1).max(axis=1) self.width = pd.concat([self.side1, self.side3], axis=1).max(axis=1) self.corners = [ self.top_left, self.top_right, self.bottom_right, self.bottom_left ]
def get_back_post_vector(agent, future_ball_location=None): #returns the location of our goal's back post. y = 4400 * utils.side(agent.team) z = 0 ball_location = future_ball_location if future_ball_location is not None else agent.ball.location if ball_location[0] > 0: x = -850 else: x = +850 back_post = Vector3(x, y, z) return back_post
def ball_going_into_their_danger_zone(agent): slices = get_slices(agent, 6) if slices is not None: for slice in slices: ball_location = Vector3(slice.physics.location) if side( agent.team ) * ball_location.y < -3600 and -1600 < ball_location.x < 1600: return True return False
def ball_going_into_our_net(agent): #left post and right post are as you're looking at it when you're facing the goal ball_prediction = agent.get_ball_prediction_struct() slices = get_slices(agent, 6) if slices is not None: for slice in slices: prediction_slice = slice ball_location = Vector3(prediction_slice.physics.location.x, prediction_slice.physics.location.y, prediction_slice.physics.location.z) if -side(agent.team) * ball_location.y < -5200: return True return False
def determine_shot(agent, target_override=None, min_shot_speed=0, max_shot_time=3.0, offense_defense=1): #gosling's hit finding algorithm is pretty good, but there's definitely room for improvement: #1. it exhaustively calculates every single possible shot at a target, even though bots typically only use the first one #2. it looks for shots at more than one target at a time. This does allow for "if shots are not available for this target, then use another target", but it tanks performance #3. it doesn't check if the approach vector is inside the field (but this can probably be changed) #4. it will sometimes return shots that are really, really slow (the original PotatOSBB needed a separate determine shot function to figure that out) #I think the plan with this is to wrap it in a determine_shot() function that decides the target location and what the minimum hit speed needs to be. #Then we call that every four ticks or so (or when the latest_touch var updates) slices = get_slices(agent, 6) if slices is None: return None else: for slice in slices: intercept_time = slice.game_seconds time_remaining = intercept_time - agent.time if time_remaining > 0: ball_location = Vector3(slice.physics.location) ball_velocity = Vector3(slice.physics.velocity).magnitude() if abs(ball_location[1]) > 5250: return None #abandon search if ball scored after this point car_to_ball = ball_location - agent.me.location #Adding a True to a vector's normalize will have it also return the magnitude of the vector direction, distance = car_to_ball.normalize(True) #How far the car must turn in order to face the ball, for forward and reverse forward_angle = direction.angle(agent.me.forward) backward_angle = math.pi - forward_angle #Accounting for the average time it takes to turn and face the ball #Backward is slightly longer as typically the car is moving forward and takes time to slow down forward_time = time_remaining - (forward_angle * 0.318) backward_time = time_remaining - (backward_angle * 0.418) #If the car only had to drive in a straight line, we ensure it has enough time to reach the ball (a few assumptions are made) forward_flag = forward_time > 0.0 and ( distance * 1.025 / forward_time ) < (2299 if agent.me.boost > distance / 100 else max( 1400, 0.8 * agent.me.velocity.flatten().magnitude())) backward_flag = distance < 1500 and backward_time > 0.0 and ( distance * 1.05 / backward_time) < 1200 #Provided everything checks out, we begin to look at the target pairs if forward_flag or backward_flag: min_shot_alignment = CTOOLS_DETERMINE_SHOT_MIN_SHOT_ALIGNMENT_DEFAULT #target selection if target_override is not None: target = target_override else: if offense_defense == -1: #panic defense mode target = agent.anti_target min_shot_alignment = -1 else: if agent.ball_going_into_our_net or agent.ball_going_into_danger_zone or ( (ball_location.y * side(agent.team)) > 4400): target = agent.anti_target min_shot_alignment = -1 elif (ball_location.y * side(agent.team)) > 4500: if ball_location.x * side(agent.team) < 0: target = agent.left_side_shot else: target = agent.right_side_shot # elif ball_location.y * side(agent.team) < 3600 or not agent.closest_to_ball: # target = agent.foe_goal_shot # else: # target = agent.upfield_shot elif offense_defense == 0: target = agent.upfield_shot else: target = agent.foe_goal_shot shot_alignment = align_goalposts(agent.me.location, ball_location, target[0], target[1]) #First we correct the target coordinates to account for the ball's radius #If fits == True, the ball can be scored between the target coordinates left, right, fits = post_correction( ball_location, target[0], target[1]) if fits: #Now we find the easiest direction to hit the ball in order to land it between the target points left_vector = (left - ball_location).normalize() right_vector = (right - ball_location).normalize() best_shot_vector = direction.clamp( left_vector, right_vector) #Check to make sure our approach is inside the field if in_field(ball_location - (700 * best_shot_vector), 1): #The slope represents how close the car is to the chosen vector, higher = better #A slope of 1.0 would mean the car is 45 degrees off considered_shots = [] slope = find_slope(best_shot_vector.flatten(), car_to_ball.flatten()) if forward_flag: if ( ball_location[2] <= 300 or (not in_field(ball_location, 200) and not in_field(agent.me.location, 100)) ) and slope > 0.0 and shot_alignment > min_shot_alignment: considered_shots.append( jump_shot(ball_location, intercept_time, best_shot_vector, slope)) if (ball_location[2] > 325 and slope > 1 and cap(ball_location[2] - 400, 100, 2000) * 0.1 < agent.me.boost and abs((car_to_ball / forward_time) - agent.me.velocity).magnitude() - 300 < 400 * forward_time): considered_shots.append( aerial_shot(ball_location, intercept_time, best_shot_vector, slope)) # elif backward_flag and ball_location[2] <= 280 and slope > 0.25: # considered_shots.append(jump_shot(ball_location,intercept_time,best_shot_vector,slope,-1)) for considered_shot in considered_shots: #speed consideration - this way we don't have to go for really slow shots unless it's needed. #also integrating this into find_hit means that the bot can keep scanning the struct for possible shots if the first one isn't possible. shot_distance = (agent.me.location - considered_shot.ball_location ).flatten().magnitude() shot_time = considered_shot.intercept_time - agent.time average_speed = shot_distance / shot_time if average_speed > min_shot_speed and considered_shot.intercept_time - agent.time < max_shot_time: return considered_shot