def _get_places_near_mothership(self): """ Выбор точки возле матери для защиты. :return: список доступных точек для защиты вокруг матери. """ point_list = list() directions_list = list() start_vector = Vector(x=self.mothership.x, y=self.mothership.y) for direction in range(0, 361, 5): point_dir = start_vector.from_direction(direction=direction, module=int(MOTHERSHIP_HEALING_DISTANCE * 0.9)) point_x = point_dir.x + start_vector.x point_y = point_dir.y + start_vector.y if (theme.FIELD_WIDTH - self.radius >= point_x >= self.radius) \ and (theme.FIELD_HEIGHT - self.radius >= point_y >= self.radius): directions_list.append(direction) start = 0 stop = len(directions_list) step = len(directions_list) // (len(self.teammates) + 1) angle_list = list() for angle in range(start, stop, step): angle_list.append(directions_list[angle]) new_point = start_vector.from_direction(direction=directions_list[angle], module=int(MOTHERSHIP_HEALING_DISTANCE * 0.9)) point_x = new_point.x + start_vector.x point_y = new_point.y + start_vector.y point_list.append(Point(point_x, point_y)) return point_list
def devide_step_path(self, drone, target): if drone.distance_to(target) > 150: for angle_delta in range(12): vec = Vector.from_points(drone.coord, target.coord) vec = Vector.from_direction( vec.direction + randint(angle_delta * 5, angle_delta * 5), 150) flag = True for d in drone.scene.drones: if d.team != drone.team and drone.distance_to( d) < drone.gun.shot_distance: vec2 = Vector.from_points(d.coord, target.coord) if ((abs(180 - abs(d.direction - vec.direction)) < 5 or (abs(d.direction - vec.direction) < 5 and abs(vec2.direction - vec.direction) < 5))): flag = False if flag: break else: vec = Vector.from_points(drone.coord, target.coord) vec = Vector.from_direction(vec.direction, 150) new_coord = Point(x=drone.coord.x + vec.x, y=drone.coord.y + vec.y) drone.actions.append(['move_step', new_coord]) return # передвигаемся не по прямой до цели, а по 150 точек, со случайным углом new_coord = Point(x=drone.coord.x + vec.x, y=drone.coord.y + vec.y) drone.actions.append(['move_step', new_coord]) else: if drone.distance_to(target) > 1: drone.actions.append(['move', target])
def on_born(self): self.my_team.append(self) self.update_all_data() max_id = len(self.scene.drones) // self.scene.teams_count near_aster = sorted(self.asteroids, key=lambda asteroid: self.distance_to(asteroid)) near_aster = near_aster[:7] vec = Vector.from_direction(self.direction, 250) self.first_coord = Point(x=int(self.x + vec.x), y=int(self.y + vec.y)) coord_1 = [[-100, -100], [100, 100], [-250, -250], [250, 250], [-400, -400], [400, 400]] coord_2 = [[100, -100], [-100, 100], [250, -250], [-250, 250], [400, -400], [-400, 400]] if 1 < self.team_number < 4: self.optimal_coord = [ Point(x=int(self.first_coord.x + coord[0]), y=int(self.first_coord.y + coord[1])) for coord in coord_1 ] else: self.optimal_coord = [ Point(x=int(self.first_coord.x + coord[0]), y=int(self.first_coord.y + coord[1])) for coord in coord_2 ] if self.have_gun: self.attack_range = self.gun.shot_distance self.move_to_optimal_position() return elif len(near_aster) >= max_id: self.task = (self.move_to, near_aster[self.my_team.index(self)]) return self.next_action() else: self.task = (self.move_to, choice(near_aster)) self.next_action()
def get_point_on_way_to(unit, target, at_distance=None): if at_distance is None: at_distance = theme.CARGO_TRANSITION_DISTANCE * 0.9 va = Vector.from_points(unit.coord, target.coord) vb = Vector.from_direction(va.direction, at_distance) vb.rotate(180.0) return Point(unit.x + va.x + vb.x, unit.y + va.y + vb.y)
def _turn_to_purpose(self, drone, purpose): """ Поворот к цели :param drone: экземпляр класса OkhotnikovFNDrone :param purpose: обект, колученный в методе next_purpose """ if hasattr(purpose, 'is_moving') and purpose.is_moving: purpose_vec = Vector.from_direction(direction=purpose.direction, module=1) drone_purpose_vec = Vector.from_points(purpose.coord, drone.coord) length = drone_purpose_vec.module if drone_purpose_vec.module > 0 else 1 _cos = ((purpose_vec.x * drone_purpose_vec.x + purpose_vec.y * drone_purpose_vec.y) / (length * purpose_vec.module)) coef_b = (PROJECTILE_SPEED**2 - DRONE_SPEED**2) coef_d = (2 * DRONE_SPEED * length * _cos)**2 + 4 * coef_b * (length**2) coef = round((-2 * DRONE_SPEED * length + coef_d**0.5) / (2 * coef_b) * DRONE_SPEED) purpose_vec = purpose_vec * coef possible_purpose = Point(purpose.coord.x + purpose_vec.x, purpose.coord.y + purpose_vec.y) drone.actions.append(['turn', possible_purpose]) else: drone.actions.append(['turn', purpose])
def on_born(self): if not theme.DRONES_CAN_FIGHT: self.scene.remove_object(self) return vector = Vector.from_direction(self._owner.direction, module=PlasmaProjectile.max_distance) point = self._owner.coord.copy() + vector super(Projectile, self).move_at(point, speed=self.__speed)
def move_to_position(self, object): distance = min(random.randint(100, 250), max(50, self.distance_to(object) - 50)) vec = Vector.from_direction(self.direction, distance) new_coord = Point(x=int(self.coord.x + vec.x), y=int(self.coord.y + vec.y)) self.move_at(new_coord)
def pursue(self, target_coord): """Двигаемся немного вперед к цели""" vec1 = Vector.from_points(self.coord, target_coord, module=1) self.vector = vec1 vec2 = Vector.from_direction(round(self.direction), 30) new_coord = Point(round(int(self.x + vec2.x)), y=round(int(self.y + vec2.y))) self.task = (self.move_to, new_coord) self.next_action()
def _get_places_near_enemy(self): """ Выбор точки возле противника для атаки. :return: список доступных точек для атаки. """ point_list = list() directions_list = list() start_vector = Vector(x=self.target_to_shoot[0].x, y=self.target_to_shoot[0].y) distance_to_target = self.distance_to(self.target_to_shoot[0]) shot_dist_with_rate = self.gun.shot_distance * 0.7 distance_to_shot = distance_to_target \ if shot_dist_with_rate > distance_to_target \ else shot_dist_with_rate for direction in range(0, 361, 5): point_dir = start_vector.from_direction(direction=direction, module=int(distance_to_shot)) point_x = point_dir.x + start_vector.x point_y = point_dir.y + start_vector.y if (theme.FIELD_WIDTH - self.radius >= point_x >= self.radius) \ and (theme.FIELD_HEIGHT - self.radius >= point_y >= self.radius): directions_list.append(direction) start = 0 stop = len(directions_list) step = len(directions_list) // 10 if len(directions_list) // 10 > self.dict_analytic['alive_teammates'] else 5 angle_list = list() for angle in range(start, stop, step): angle_list.append(directions_list[angle]) new_point = start_vector.from_direction(direction=directions_list[angle], module=int(distance_to_shot)) point_x = new_point.x + start_vector.x point_y = new_point.y + start_vector.y point_list.append(Point(point_x, point_y)) return point_list
def avoid_friendly_fire(self): """ Метод меняет позицию дрона-истребителя на случайно генерируемую в пределах 150 от изначальной. Вызывается если в других методах valide_position() вернул False. :return: None """ vec = Vector(self.drone.position.x, self.drone.position.y) point = vec.from_direction(direction=random.choice([90, 180, 270, 360]), module=random.choice([100, 150, 200])) self.change_position( position=Point(x=self.drone.coord.x + point.x, y=self.drone.coord.y + point.y))
def get_coords_for_attak(self, drones_in_my_team, mothership_name): mothership = self.scene.get_mothership(mothership_name) drones = list(d for d in self.scene.drones if d.team == mothership.team) quantity = drones_in_my_team if mothership != self.mothership: distance = 400 else: distance = 300 angle = 85 / (quantity - 1) rotate = -5 self.target_for_attack = None if mothership.x > self.scene.field[ 0] / 2 and mothership.y > self.scene.field[1] / 2: p = Point(mothership.x, mothership.y - distance) v = Vector.from_points(mothership.coord, p) angle = 40 / (quantity - 1) rotate = 0 elif mothership.x > self.scene.field[ 0] / 2 and mothership.y < self.scene.field[1] / 2: p = Point(mothership.x - distance, mothership.y) v = Vector.from_points(mothership.coord, p) angle = 40 / (quantity - 1) rotate = -50 elif mothership.x < self.scene.field[ 0] / 2 and mothership.y > self.scene.field[1] / 2: p = Point(mothership.x + distance, mothership.y) v = Vector.from_points(mothership.coord, p) angle = 40 / (quantity - 1) rotate = -50 elif mothership.x < self.scene.field[ 0] / 2 and mothership.y < self.scene.field[1] / 2: p = Point(mothership.x, mothership.y + distance) v = Vector.from_points(mothership.coord, p) angle = 40 / (quantity - 1) rotate = 0 len_alive = len(set(m for m in self.scene.motherships if m.is_alive)) if len_alive == 2: angle = 90 / (quantity - 1) rotate = 0 v.rotate(rotate) p = Point(mothership.x + v.x, mothership.y + v.y) points_to_stop = [p] difference = angle while len(points_to_stop) < quantity: next_v = Vector.from_direction(v.direction - angle, v.module) next_p = Point(mothership.x + next_v.x, mothership.y + next_v.y) points_to_stop.append(next_p) angle += difference for d in my_team: d.point_to_attack_mothership = points_to_stop.pop() d.move_at(self.point_to_attack_mothership) self.action = 'move_to_plase_for_attack'
def get_point_near_target(self): """ Метод рассчитывает начальную точку атаки рядом с целью. :return: Point-class instance """ vec = Vector.from_points(self.drone.coord, self.drone.aim.coord) dist = (self.drone.distance_to(self.drone.aim) - self.drone.gun.shot_distance) * 1.05 direction = vec.direction vec_attack = Vector.from_direction(direction=direction + self.drone.hq.courses_k[self.drone.inner_team_id - 1], module=dist) point = Point(self.drone.coord.x + vec_attack.x, self.drone.coord.y + vec_attack.y) return point
def game_step(self): if self.is_alive: self.__ttl = max( self.__ttl - self.__projectile._owner.scene.game_speed, 0) else: return # Были прикреплены к оппоненту, анимируем попадание direction = -self.__initial_target_direction + self.__target.direction + self.__direction vector = Vector.from_direction(direction, module=self.__distance) self.__projectile.coord.x = self.__target.x + vector.x self.__projectile.coord.y = self.__target.y + vector.y if not self.is_alive: self.__projectile.scene.remove_object(self.__projectile)
def get_turret_points(self): """ Метод создает стартовые точки расстановки дронов :return: None """ vec = Vector.from_points(self.my_mothership.coord, self.hq.center_field) dir = vec.direction angles_set = [dir - 70, dir + 40, dir + 10, dir - 10, dir - 40] for angle in angles_set: vec_turret = Vector.from_direction(direction=angle, module=MOTHERSHIP_HEALING_DISTANCE * 0.9) point_turret = Point(self.my_mothership.coord.x + vec_turret.x, self.my_mothership.coord.y + vec_turret.y) self.hq.TURRET_POINTS.append(Point(x=point_turret.x, y=point_turret.y))
def create_attack_positions(self): """создание позиций для атаки""" self.attack_positions = [] main_vector = self.advance_distance * (self.attack_stage + 1) central_position = Point(self.my_mothership.x + main_vector.x, self.my_mothership.y + main_vector.y) self.attack_positions.append(central_position) for angle in [-90, 90]: wing_angle = normalise_angle(main_vector.direction + angle) wing_vector = Vector.from_direction(wing_angle, 100) point1 = Point(central_position.x + wing_vector.x, central_position.y + wing_vector.y) if not 0 <= point1.x <= 1200 or not 0 <= point1.y <= 1200: point1 = self.rebase_drone_in_formation(point1, wing_vector) self.attack_positions.append(point1) point2 = Point(central_position.x + (wing_vector * 2).x, central_position.y + (wing_vector * 2).y) if not 0 <= point2.x <= 1200 or not 0 <= point2.y <= 1200: point2 = self.rebase_drone_in_formation(point2, wing_vector) self.attack_positions.append(point2)
def __init__(self, coord=None, radius=None, direction=None): if self.__scene is None: raise RobogameException("You must create Scene instance at first!") if self.auto_team: self.scene.register_to_team(obj=self) if radius is None: radius = self.__class__.radius self.coord = coord if coord else Point(0, 0) self.radius = radius self.__container.append(self) GameObject.__objects_count += 1 self.id = GameObject.__objects_count if direction is None: direction = randint(0, 360) self.vector = Vector.from_direction(direction, module=1) self.target = None self.state = StateStopped(obj=self) self._heartbeat_tics = theme.HEARTBEAT_INTERVAL self._events = Queue() self._commands = Queue() self._selected = False self.add_event(EventBorned(self)) self.debug('born {coord} {vector}')
def __init__(self, coord=None, radius=None, direction=None): if self.__scene is None: raise RobogameException("You must create Scene instance at first!") if self.auto_team: self.__team = self.scene.get_team(cls=self.__class__) if radius is None: radius = self.__class__.radius self.coord = coord if coord else Point(0, 0) self.radius = radius self.__container.append(self) GameObject.__objects_count += 1 self.id = GameObject.__objects_count if direction is None: direction = randint(0, 360) self.vector = Vector.from_direction(direction, module=1) self.target = None self.state = StateStopped(obj=self) self._heartbeat_tics = theme.HEARTBEAT_INTERVAL self._events = Queue() self._commands = Queue() self._selected = False self.add_event(EventBorned(self)) self.debug('born {coord} {vector}')
def pursue(self): """Двигаемся немного вперед к цели""" vec2 = Vector.from_direction(round(self.direction), 30) new_coord = Point(x=round(int(self.x + vec2.x)), y=round(int(self.y + vec2.y))) return new_coord
def move_to_step(self, object): distance = min(250, max(100, self.distance_to(object) - 50)) vec = Vector.from_direction(self.direction, distance) new_coord = Point(x=int(self.coord.x + vec.x), y=int(self.coord.y + vec.y)) self.move_to(new_coord)
def nearest_angle_distance(left, right): lv = Vector.from_direction(left, module=10) rv = Vector.from_direction(right, module=10) return normalise_angle( math.atan2(rv.y - lv.y, rv.x - lv.x) * 180 / math.pi)