def __init__(self, config, state): self.x_cells_count = config['x_cells_count'] self.y_cells_count = config['y_cells_count'] self.width = config['width'] # changes inplace further self.start_points = { normalize_point_cords((x, y), self.width) for x, y in state['players']['i']['territory'] } my_position = state['players']['i']['position'] self.end_point = normalize_point_cords(my_position, self.width) self.lines = { normalize_point_cords((x, y), self.width) for x, y in state['players']['i']['lines'] } self.map = initialize_map(self.x_cells_count, self.y_cells_count) for point in self.start_points: self.map[point[0]][point[1]] = 0 self.path_to_territory = [] self.n_steps_to_save = None
def __init__(self, config, state): self.x_cells_count = config['x_cells_count'] self.y_cells_count = config['y_cells_count'] self.width = config['width'] # changes inplace further self.visited_points = { normalize_point_cords((x, y), self.width) for x, y in state['players']['i']['lines'] } my_position = state['players']['i']['position'] self.prev_location = normalize_point_cords(my_position, self.width) self.my_territory = { normalize_point_cords((x, y), self.width) for x, y in state['players']['i']['territory'] } self.enemy_points = set() for player_id, player_info in state['players'].items(): if player_id != 'i': x, y = player_info['position'] self.enemy_points.add(normalize_point_cords((x, y), self.width)) self.n_steps_to_enemy = None self.map = initialize_map(self.x_cells_count, self.y_cells_count) self.run_bfs_from_enemies()
def compute_distance_to_second_enemy(self): end_points = set() for player_id, player_info in self.state['players'].items(): if player_id != 'i' and player_id != self.enemy_id: x, y = player_info['position'] end_points.add(normalize_point_cords((x, y), width=self.width)) queue = deque(self.full_tail) visited = self.full_tail n_steps = 0 while queue: n_steps += 1 for _ in range(len(queue)): point = queue.popleft() for neighbor in get_neighbors(point): if neighbor in visited: continue if not in_arena_bounds(neighbor): continue if neighbor in end_points: self.n_steps_to_second_enemy = n_steps return visited.add(neighbor) queue.append(neighbor)
def compute_enemy_distance_to_territory(self): """ считаем расстояние от текущей локации врага до его территории минуя его шлейф """ if self.n_steps_to_enemy is None: return None enemy_id = self.line_cords_to_id[self.nearest_attack_point] self.enemy_id = enemy_id start_point = normalize_point_cords( self.state['players'][enemy_id]['position'], self.width) end_points = { normalize_point_cords((x, y), self.width) for x, y in self.state['players'][enemy_id]['territory'] } visited = { normalize_point_cords((x, y), self.width) for x, y in self.state['players'][enemy_id]['lines'] } if start_point in end_points: self.n_steps_for_enemy_save = 0 return queue = deque([start_point]) n_steps = 0 while queue: n_steps += 1 for _ in range(len(queue)): point = queue.popleft() for neighbor in get_neighbors(point): if neighbor in visited: continue if not in_arena_bounds(neighbor): continue if neighbor in end_points: self.n_steps_for_enemy_save = n_steps return visited.add(neighbor) queue.append(neighbor)
def on_tick(self, state): start_time = time.time() self.state = state self.risky_location = None self.move = None self.curr_position = state['players']['i']['position'] self.curr_territory = state['players']['i']['territory'] self.have_enemies = True if len(state['players']) > 1 else False moves = self.get_valid_moves() if self.in_territory_bounds(): self.move = self.attack_attempt() if not self.move: self.move = self.leave_territory() # если следующая локация находится вне границ территории if self.risky_location: threats_map = ThreatsMap(self.config, self.state) if not threats_map.is_save_location(self.risky_location, normalize=False): moves = self.filter_dangerous_moves(moves, threats_map) self.move = None # попытаться сделать случайный шаг в пределах своей территории if not self.move: self.move = random.choice(moves) if moves else LEFT else: self.move = self.attack_attempt() if not self.move: routes_maker = RoutesMaker(self.config, self.state, self.prev_move) next_location = routes_maker.get_next_step() if next_location: self.move = get_command_from_points( normalize_point_cords(self.curr_position, self.width), next_location) if not self.move or self.move not in moves: saves_map = SavesMap(self.config, self.state) saves_map.compute() path_to_territory = saves_map.get_path_to_territory() return_commands = path_to_commands(path_to_territory, self.curr_position, self.width) if return_commands: self.move, return_commands = follow_path( return_commands) if not self.move: self.move = self.choose_arbitrary_move( moves, saves_map) self.prev_move = self.move print( json.dumps({ "command": self.move, "debug": f"time = {time.time()-start_time}" }))
def __init__(self, config, state): self.state = state self.width = config['width'] self.x_cells_count = config['x_cells_count'] self.y_cells_count = config['y_cells_count'] my_position = state['players']['i']['position'] self.start_point = normalize_point_cords(my_position, self.width) self.lines = { normalize_point_cords((x, y), self.width) for x, y in state['players']['i']['lines'] } self.territory = { normalize_point_cords((x, y), self.width) for x, y in state['players']['i']['territory'] } self.line_cords_to_id = {} for player_id, player_info in state['players'].items(): if player_id != 'i': for x, y in player_info['lines']: self.line_cords_to_id[normalize_point_cords( (x, y), self.width)] = player_id self.enemy_id = None self.map = initialize_map(self.x_cells_count, self.y_cells_count) self.second_map = initialize_map(self.x_cells_count, self.y_cells_count) self.nearest_attack_point = None self.n_steps_to_enemy = None self.n_steps_for_enemy_save = None self.n_steps_from_attack_point = None self.path_to_enemy = None self.path_from_enemy = None self.final_point = None self.full_tail = None self.n_steps_to_second_enemy = None
def is_save_location(self, location, normalize=True): if normalize: x, y = normalize_point_cords(location, self.width) else: x, y = location if (x, y) in self.my_territory: return True if self.map[x][y] is not None and self.map[x][y] < 4: return False return True
def __init__(self, config, state, prev_location): self.prev_location = prev_location self.state = state self.width = config['width'] self.x_cells_count = config['x_cells_count'] self.y_cells_count = config['y_cells_count'] self.my_territory = { normalize_point_cords((x, y), self.width) for x, y in state['players']['i']['territory'] } self.enemy_points = set() self.enemy_territory = set() my_position = state['players']['i']['position'] self.curr_pos = normalize_point_cords(my_position, self.width) # карта для bfs от вражеской территории до меня и bfs от меня до границ self.map = initialize_map(self.x_cells_count, self.y_cells_count) for player_id, player_info in state['players'].items(): if player_id != 'i': x, y = player_info['position'] self.enemy_points.add(normalize_point_cords((x, y), self.width)) for territory_point in player_info['territory']: x_ter, y_ter = normalize_point_cords( territory_point, self.width) self.map[x_ter][y_ter] = 0 self.enemy_territory.add((x_ter, y_ter)) # карта для поиска ближайшего пути до лучшей точки self.second_map = initialize_map(self.x_cells_count, self.y_cells_count) self.bordering_points_set = set() self.best_point = None self.path_to_point = None
def choose_arbitrary_move(self, moves, saves_map): moves_info = {} for move in moves: next_point = get_next_point(self.curr_position, move, self.width) next_point = normalize_point_cords(next_point, self.width) moves_info[move] = saves_map.get_distance_from_point_to_territory( next_point) move_chosen = False while not move_chosen: move = random.choice(moves) if moves_info[move] is not None: move_chosen = True return move
def __init__(self, config, state, prev_move): self.state = state self.x_cells_count = config['x_cells_count'] self.y_cells_count = config['y_cells_count'] self.width = config['width'] self.prev_move = prev_move self.slows = { normalize_point_cords(bonus['position'], self.width) for bonus in state['bonuses'] if bonus['type'] == 's' } self.is_slow = any(bonus['type'] == 's' for bonus in state['players']['i']['bonuses']) self.remaining_ticks = ( (2500 - self.state['tick_num']) / config['speed']) - 1 # self.remaining_ticks = float('inf') my_position = state['players']['i']['position'] self.curr_position = normalize_point_cords(my_position, self.width) min_max = MinMax() self.my_territory, self.x_set, self.y_set = set(), set(), set() for cords in state['players']['i']['territory']: x, y = normalize_point_cords(cords, self.width) self.my_territory.add((x, y)) self.x_set.add(x) self.y_set.add(y) min_max.update((x, y)) self.min_max = min_max self.lines = { normalize_point_cords((x, y), self.width) for x, y in state['players']['i']['lines'] } for point in self.lines: min_max.update(point) self.backward_direction = opposite_directions[self.prev_move] self.side_directions = SIDE_DIRECTIONS[prev_move] self.enemy_points = set() self.enemy_territory = set() for player_id, player_info in state['players'].items(): if player_id != 'i': for x, y in player_info['territory']: self.enemy_territory.add( normalize_point_cords((x, y), self.width)) x, y = player_info['position'] self.enemy_points.add(normalize_point_cords((x, y), self.width)) if not self.enemy_points: self.map = initialize_map(self.x_cells_count, self.y_cells_count, initial_value=self.remaining_ticks) else: self.map = initialize_map(self.x_cells_count, self.y_cells_count) self.run_bfs_from_enemies() self.routes = []