def reset(self) -> GameState: """Reinitialise this scenario when called. Is called upon initialization and when the reset conditions are met. :return: The freshly initialized game state for this scenario :rtype: GameState, optional """ self.timer = 0.0 left_or_right = (random.random() > 0.5) * 2 - 1 x_location = random.uniform( *Constants.line_x_side_range ) + left_or_right * Constants.line_x_side_offset car_pos = Vec3(x_location, random.uniform(*Constants.line_y_range), Constants.car_height) ball_pos = Vec3(car_pos.x, car_pos.y + Constants.ball_loc_y_offset, Constants.ball_radius) car_state = CarState(physics=Physics(location=car_pos, velocity=Vector3(0, -100, 0), rotation=Constants.car_rotation, angular_velocity=Vector3(0, 0, 0)), boost_amount=100) ball_state = BallState( physics=Physics(location=ball_pos, velocity=Vector3(0, 0, 1), rotation=Rotator(0, 0, 0), angular_velocity=Vector3(0, 0, 0))) return GameState(cars={0: car_state}, ball=ball_state)
def reset(self) -> GameState: """Reinitialise this scenario when called. Is called upon initialization and when the reset conditions are met. :return: The freshly initialized game state for this scenario :rtype: GameState, optional """ self.timer = 0.0 car_state = CarState(physics=Physics( location=Constants.goal_location.flatten(), velocity=Vec3(0, -100, 0), rotation=Constants.car_rotation, angular_velocity=Vector3(0, 0, 0)), boost_amount=100) # Normalize the direction we want the ball to go to, so we can manually define the speed ball_state = BallState( physics=Physics(location=Vec3(uniform(*Constants.ball_loc_x_range), uniform(*Constants.ball_loc_y_range), uniform( *Constants.ball_loc_z_range)), velocity=Vec3(uniform(*Constants.ball_vel_x_range), uniform(*Constants.ball_vel_y_range), uniform( *Constants.ball_vel_z_range)), rotation=Rotator(0, 0, 0), angular_velocity=Vec3(0, 0, 0))) return GameState(cars={0: car_state}, ball=ball_state)
def _calculate_attack_score(self) -> float: # Determine if we are closer to the ball or the opponent dist_us = 1.0 * (10**10) dist_opp = 1.0 * (10**10) ball_pos = Vec3.from_other_vec(self.world.ball.physics.location) for car in self.world.teams[self.opp_team].cars: vec_to_ball = ball_pos - Vec3.from_other_vec(car.physics.location) dist_opp = min(vec_to_ball.magnitude(), dist_opp) for car in self.world.teams[self.team].cars: vec_to_ball = ball_pos - Vec3.from_other_vec(car.physics.location) dist_us = min(vec_to_ball.magnitude(), dist_us) enemy_closer = dist_opp < dist_us if enemy_closer: closer_score = -1 else: closer_score = 1 # Calculate the ball speed towards the enemy goal and the position of the ball and turn them into a point value v_ball_score = -self.world.ball.physics.velocity.y * self.side / InGameConstants.MAX_BALL_VELOCITY ball_pos_score = -self.world.ball.physics.location.y * self.side / InGameConstants.MAX_BALL_POSITION # Calculate the total score by assigning a specific weight to each of the score values. total_score = (closer_score * self.weight_closest + v_ball_score * self.weight_velocity + ball_pos_score * self.weight_position) / ( self.weight_closest + self.weight_velocity + self.weight_position) return total_score
def reset(self) -> GameState: """Reinitialise this scenario when called. Is called upon initialization and when the reset conditions are met.รง :return: The freshly initialized game state for this scenario :rtype: GameState, optional """ self.timer = 0.0 car_pos = Vec3(random.uniform(*Constants.car_loc_x_range), random.uniform(*Constants.car_loc_y_range), Constants.car_loc_z) # Creates a vec between the goal location and the car location, to init the ball random_range = Constants.goal_car_vec_to_ball_start_location_scale_range length_fraction = ( random_range[0] + (random_range[1] - random_range[0]) * random.random()) ball_pos = (car_pos - Constants.goal_location ) * length_fraction + Constants.goal_location car_state = CarState(physics=Physics(location=car_pos, velocity=Vector3(0, -100, 0), rotation=Constants.car_rotation, angular_velocity=Vector3(0, 0, 0)), boost_amount=100) ball_state = BallState( physics=Physics(location=ball_pos + Vec3(0, 0, 40), velocity=Vector3(0, 0, 5), rotation=Rotator(0, 0, 0), angular_velocity=Vector3(0, 0, 0))) return GameState(cars={0: car_state}, ball=ball_state)
def __init__(self): # print("Captain Defense: Started") self.team = self.drones[0].team self.own_goal_location = Vec3( 0, self.LENGTH_MAP_ONE_SIDE * side(self.team), 0) # Clear the stacks for drone in self.drones: drone.flush_actions() # Closest car to the goal becomes the keeper goal_dist = {(Vec3.from_other_vec(car.physics.location) - self.own_goal_location).magnitude(): drone for car, drone in zip(self.world.teams[self.team].cars, self.drones)} self.keeper_drone = goal_dist[min(goal_dist.keys())] self.keeper_state = KeeperState.SHADOWING self.keeper_drone.assign(Shadowing()) # Other drones become interceptors self.interceptor_drones = [ drone for drone in self.drones if (drone != self.keeper_drone) ] self.interceptor_states = { drone: InterceptorState.COVER for drone in self.interceptor_drones } [ drone.assign(Cover(distance_ratio=self.INTERCEPTOR_COVER_RATIO)) for drone in self.interceptor_drones ]
def _get_target(self, agent: GoslingAgent) -> Optional[Slice]: """"Retrieves the interception target""" # For predicting the location of the ball for the coming 6 seconds. ball_prediction = Ball.get_ball_prediction() min_t, max_t = 0, ball_prediction.num_slices / 60 # By default (0, 6) - From RLBOT for i in range(min_t, round(max_t * self.GRID_SEARCH_INTERVAL)): # Grid time = i / self.GRID_SEARCH_INTERVAL target = ball_prediction.slices[self._time_to_idx(time)] # Skip if the target is too high or low! if target.physics.location.z > self.MAX_Z_INTERCEPT: continue offset_angle = Vec3.from_other_vec( self._calc_local_diff(agent, Vector3( target.physics.location))).angle_2d(Vec3(x=0, y=1, z=0)) if degrees(offset_angle) < self.SLICE_ANGLE: ball_distance = (agent.me.location - Vector3(target.physics.location)).magnitude() if self._in_range(time, ball_distance, agent.me.velocity.magnitude()): return target return None
def __init__(self): self.team = self.drones[0].team self.own_goal_location = Vec3( 0, self.LENGTH_MAP_ONE_SIDE * side(self.team), 0) self.other_goal_location = Vec3( 0, self.LENGTH_MAP_ONE_SIDE * side(self.team) * -1, 0) # Clear the stacks for drone in self.drones: drone.flush_actions() drone_closest_to_ball = self._get_teammate_closest_to_ball( prefer_friendly_side=True) self.attacker_drones = [drone_closest_to_ball] self.attacker_states = {drone_closest_to_ball: AttackerState.PREPARE} drone_closest_to_ball.assign(Prepare()) # Select keeper from remaining drones remaining_drones = [ drone for drone in self.drones if (drone != drone_closest_to_ball) ] if len(remaining_drones) > 0: goal_dist = {(Vec3.from_other_vec(drone.car.physics.location) - self.own_goal_location).magnitude(): drone for drone in remaining_drones} self.defender_drone = goal_dist[min(goal_dist.keys())] self.defender_state = DefenderState.COVER self.defender_drone.assign( Cover(distance_ratio=self.DEFENDER_COVER_DIST_RATIO)) else: self.defender_drone = None self.defender_state = DefenderState.INACTIVE # All other drones remaining_drones = [ drone for drone in remaining_drones if (drone != self.defender_drone) ] for idx, drone in enumerate(remaining_drones): self.attacker_states[drone] = AttackerState.COVER self.attacker_drones.append(drone) drone.assign(Cover(distance_ratio=self.ATTACKER_COVER_DIST_RATIO)) offsets = np.linspace(*self.ATTACKER_PREPARE_OFFSETS, num=len(self.attacker_drones)) self.attacker_offsets = { drone: offset for drone, offset in zip(self.attacker_drones, offsets) }
def _detect_bad_shot(self, drone: Drone) -> bool: """"Check if our shot is bad""" # Can only be False when we are close to the ball if (Vec3.from_other_vec(self.world.ball.physics.location) - Vec3.from_other_vec(drone.car.physics.location) ).magnitude() < self.ATTACKER_CANCEL_CHECK_RANGE: # Cancel if we expect to fire to our own goal if (self.world.ball.physics.location.y - drone.car.physics.location.y) * side(self.team) > 0: # print(f"Bad shot detected. Ball: {self.world.ball.physics.location.y} " # f"Drone: {drone.car.physics.location.y}") return True return False
def __init__(self): self.state = Status.RUNNING self.goal_target = Vec3(0, 5250, 350) # Initial role assignment! for drone in self.drones: drone.assign(Dribble(self.goal_target))
def _future_intercept_location(self, ball_slice_in_goal: Slice) -> Slice: time_of_goal = ball_slice_in_goal.game_seconds time_until_goal = time_of_goal - self.agent.time # Scaling linear based on ball velocity, 0 = 0.80, 3000 = 0.95 vel_ball = Vec3.from_other_vec( Ball.predict_future_goal().physics.velocity).magnitude() factor = (vel_ball - 0) / (3000 - 0) * ( 0.95 - 0.8) + 0.8 # TODO: Imre - Explain please :p time_we_intercept = self.agent.time + time_until_goal * factor return Ball.find_slice_at_time(time_we_intercept)
class Constants: timeout = 4.0 # Time after which the scenario resets radia_ball = 92.75 # Radius of the ball y_limit_before_reset = 5000 # Angle at which the ball will be shot to the center of the field ball_min_angle = -0.5 * pi * 0.8 # 20 percent to the right of down ball_max_angle = (1.0 + 0.5 * 0.8) * pi # 20 percent to the left of down # Ball initialization distance from center of the field ball_min_distance = 2000 ball_max_distance = 4000 # Ball speed ball_min_speed = 500 ball_max_speed = 2000 # Car initialization location_car = Vec3(0, -2000, 0) velocity_car = Vec3(0, -100, 0) rotation_car = Rotator(0, 1.57, 0) # Half pi rad
class Constants: timeout = 8.0 goal_location = Vec3(0, 5250, 600) y_limit_before_reset = 5000 car_rotation = Rotator(0, 1.57, 0) car_loc_x_range = [-2000, 2000] car_loc_y_range = [-2100, -300] car_loc_z = 17.02 # Fraction between car and goal location to place the ball on goal_car_vec_to_ball_start_location_scale_range = [0.75, 0.95]
def _detect_bad_shot(self, drone: Drone) -> bool: """"Check if our shot is bad""" # Can only be False when we are close to the ball if self.world.calc_dist_to_ball( drone.car) < self.INTERCEPTOR_CANCEL_CHECK_RANGE: drone_to_ball = ( Vec3.from_other_vec(self.world.ball.physics.location) - Vec3.from_other_vec(drone.car.physics.location)).normalize() drone_to_goal = ( Vec3.from_other_vec(self.own_goal_location) - Vec3.from_other_vec(drone.car.physics.location)).normalize() # Cancel if we expect to fire to our own goal if drone_to_ball * drone_to_goal > self.MINIMUM_DIRECTION_RATIO: # print(f"Bad shot detected for drone {drone.index}") # print(f"Bad shot detected. Ball: {self.world.ball.physics.location.y} " # f"Drone: {drone.car.physics.location.y}") return True return False
class Constants: timeout = 4.0 goal_location = Vec3(0, -5250, 600) ball_loc_x_range = [-1500, 1500] ball_loc_y_range = [-2000, 0] ball_loc_z_range = [100, 500] ball_vel_x_range = [-500, 500] ball_vel_y_range = [-1500, -2500] ball_vel_z_range = [-500, -500] car_rotation = Rotator(0, 1.57, 0) y_limit_before_reset = -5000
def _keeper_start_check(self) -> bool: """"Checks the conditions for the keeper to start""" ball_goal_dist = ( Vec3.from_other_vec(self.world.ball.physics.location) - self.own_goal_location).magnitude() future_goal_predicted = self._future_goal_is_imminent() in_goal_circle = ball_goal_dist < self.START_KEEPER_CIRCLE_RANGE on_opposite_corner = self.keeper_drone.car.physics.location.x * self.world.ball.physics.location.x < 1 and \ 0 < abs(self.world.ball.physics.location.x) < self.START_KEEPER_SIDE_RANGE and \ abs(self.own_goal_location.y - self.world.ball.physics.location.y) < \ self.START_KEEPER_CIRCLE_RANGE and self.world.ball.physics.location.z < self.JUMP_THRESHOLD return future_goal_predicted or in_goal_circle or on_opposite_corner
def reset(self) -> GameState: """Reinitialise this scenario when called. Is called upon initialization and when the reset conditions are met. :return: The freshly initialized game state for this scenario :rtype: GameState, optional """ self.timer = 0.0 # Ball random angle from center, with velocity towards center angle_ball = uniform(Constants.ball_min_angle, Constants.ball_max_angle) distance = uniform(Constants.ball_min_distance, Constants.ball_max_distance) speed_ball = uniform(Constants.ball_min_speed, Constants.ball_max_speed) # print(f'distance: {distance}, Angle: {angle_ball}, Speed: {speed_ball}') # Determine x and y position and velocity from generated random angle x_ball, y_ball = distance * cos(angle_ball), distance * sin(angle_ball) x_vel_ball, y_vel_ball = speed_ball * -cos( angle_ball), speed_ball * -sin(angle_ball) ball_state = BallState(physics=Physics( location=Vec3(x_ball, y_ball, Constants.radia_ball), # Always on the ground velocity=Vec3(x_vel_ball, y_vel_ball, 0), rotation=Rotator(0, 0, 0), angular_velocity=Vec3(0, 0, 0))) car_state = CarState(physics=Physics(location=Constants.location_car, velocity=Constants.velocity_car, rotation=Constants.rotation_car, angular_velocity=Vector3(0, 0, 0)), boost_amount=100) return GameState(cars={0: car_state}, ball=ball_state)
class Constants: timeout = 5.0 y_limit_before_reset = -5000 goal_location = Vec3(0, -5250, 600) ball_velocity = 2500 shot_target_x_range = [-850, 850] shot_target_z_range = [1000, 2500] car_location = Vector3(0, goal_location.y, 17.02) car_rotation = Rotator(0, 1.57, 0) ball_loc_x_range = [-2500, 2500] ball_loc_y = 0 ball_loc_z = 500
def calc_dist_to_ball(self, physics_object): return (Vec3.from_other_vec(physics_object.physics.location) - Vec3.from_other_vec( self.ball.physics.location)).magnitude()