def use(car: Car): car_speed = Point(car.speed_x, car.speed_y) return (car.id != context.me.id and (context.speed.norm() > CAR_SPEED_FACTOR * car_speed.norm() or context.speed.norm() > 0 and (car_speed.norm() > 0 and abs(context.speed.cos(car_speed)) < cos(1) or car_speed.norm() == 0)))
def get_target_speed(course: Point, path, angle_to_direct_proportion, max_speed, min_power): direct_factor = 1 / (angle_to_direct_proportion + 1) angle_factor = direct_factor * angle_to_direct_proportion if len(path) > 2: angle_factor *= max(1e-8 - 1, min(1 - 1e-8, cos_product(path, min_power))) if course.norm() > 0: return course * max_speed / course.norm() * (direct_factor + angle_factor) else: return Point(0, 0)
def generate(): for car in context.opponents_cars: car_position = Point(car.x, car.y) car_speed = Point(car.speed_x, car.speed_y) car_barriers = list(make_units_barriers([car])) distance = (context.position - car_position).norm() if car_speed.norm() < 1: yield (not has_intersection_with_tiles(distance) and make_has_intersection_with_lane( position=context.position, course=tire_speed * 50, barriers=car_barriers, width=context.game.tire_radius, )(0)) else: car_line = Line(car_position, car_position + car_speed) tire_line = Line(context.position, context.position + tire_speed) intersection = tire_line.intersection(car_line) if intersection is None: continue if not is_in_world(intersection, world_tiles, tile_size): continue if is_in_empty_tile(intersection, world_tiles, tile_size): continue car_dir = intersection - car_position if car_dir.norm() > 0 and car_dir.cos(car_speed) < 0: continue if car_dir.norm() > context.game.tire_initial_speed * 50: continue tire_dir = intersection - context.position if tire_dir.norm() > 0 and tire_dir.cos(tire_speed) < 0: continue if has_intersection_with_tiles(tire_dir.norm()): continue car_time = car_dir.norm() / car_speed.norm() tire_time = tire_dir.norm() / tire_speed.norm() if abs(car_time - tire_time) <= TIRE_INTERVAL: yield True
def generate(): for car in context.opponents_cars: car_position = Point(car.x, car.y) car_speed = Point(car.speed_x, car.speed_y) car_barriers = list(make_units_barriers([car])) if car_speed.norm() < 1: for washer in washers: yield make_has_intersection_with_lane( position=washer.position, course=washer.speed * 150, barriers=car_barriers, width=context.game.washer_radius, )(0) else: car_line = Line(car_position, car_position + car_speed) for washer in washers: washer_line = Line(washer.position, washer.position + washer.speed) intersection = washer_line.intersection(car_line) if intersection is None: continue if not is_in_world(intersection, world_tiles, tile_size): continue if is_in_empty_tile(intersection, world_tiles, tile_size): continue car_dir = intersection - car_position if car_dir.norm() > 0 and car_dir.cos(car_speed) < 0: continue if car_dir.norm() > washer_speed * 150: continue washer_dir = intersection - washer.position if (washer_dir.norm() > 0 and washer_dir.cos(washer.speed) < 0): continue car_time = car_dir.norm() / car_speed.norm() washer_time = washer_dir.norm() / washer.speed.norm() if abs(car_time - washer_time) <= WASHER_INTERVAL: yield True
def __call__(self, course, angle, direct_speed: Point, angular_speed_angle, engine_power, wheel_turn, target_speed: Point, tick, backward): direction = Point(1, 0).rotate(angle) radius = -(direction * self.distance_to_wheels).rotate(pi / 2) angular_speed = radius.left_orthogonal() * angular_speed_angle speed = direct_speed + angular_speed target_acceleration = self.__speed(target_speed - speed) tangential_acceleration = speed - self.__previous_speed centripetal_acceleration = (-radius * self.__previous_angular_speed_angle**2) acceleration = tangential_acceleration + centripetal_acceleration acceleration_derivative = self.__acceleration(target_acceleration - acceleration) cos_val = acceleration_derivative.cos(direction) if -sqrt(2) / 2 < cos_val < sqrt(2) / 2: cos_val = sqrt(2) / 2 if cos_val >= 0 else -sqrt(2) / 2 target_engine_power = acceleration_derivative.norm() * cos_val target_engine_power = max(-1, min(1, target_engine_power)) if (speed.norm() > 0 and target_speed.norm() > 0 and speed.cos(target_speed) > -cos(1) or speed.norm() == 0): if speed.norm() > target_speed.norm(): target_engine_power = (1 if direction.cos(speed) > -cos(1) else -1) brake = True else: target_engine_power = ( 1 if direction.cos(target_speed) > -cos(1) else -1) brake = False else: brake = True target_angle = course.absolute_rotation() direction_angle_error = normalize_angle(target_angle - angle) direction_angle_error = relative_angle_error(direction_angle_error) speed_angle_error = normalize_angle(speed.absolute_rotation() - angle) speed_angle_error = relative_angle_error(speed_angle_error) if (backward and target_speed.norm() > 0 and direction.cos(target_speed) < -cos(1)): direction_angle_error = -direction_angle_error speed_angle_error = -speed_angle_error angle_error = max(direction_angle_error, speed_angle_error, key=abs) angle_derivative = self.__angle(angle_error) target_wheel_turn = self.__angular_speed_angle(angle_derivative - angular_speed_angle) target_wheel_turn = max(-1, min(1, target_wheel_turn)) self.__previous_speed = speed self.__previous_angular_speed_angle = angular_speed_angle if 'CONTROL_PLOTS' in environ and environ['CONTROL_PLOTS'] == '1': def append_point(name, current, target): # append_value(name + ' x', current.x, target.x) # append_value(name + ' y', current.y, target.y) append_value(name + ' norm', current.norm(), target.norm()) def append_value(name, current, target): history = self.history[name] history.current.append(current) history.target.append(target) append_point('speed', speed, target_speed) append_point('acceleration', acceleration, target_acceleration) append_value('engine_power', engine_power, target_engine_power) append_value('angle', angle, target_angle) append_value('wheel_turn', wheel_turn, target_wheel_turn) if tick % 50 == 0: def draw(name): plot = self.plots[name] history = self.history[name] plot.clear() plot.lines( range(tick + 1 - len(history.current), tick + 1), history.current) plot.lines(range(tick + 1 - len(history.target), tick + 1), history.target, linestyle='--') plot.draw() def draw_point(name): # draw(name + ' x') # draw(name + ' y') draw(name + ' norm') draw_point('speed') draw_point('acceleration') draw('engine_power') draw('angle') draw('wheel_turn') return Control(target_engine_power, target_wheel_turn, brake)
def update(self, speed: Point, durability): self.__history.append(self.Conf(speed.norm(), durability))