def decide_convert_ship_position(ally_shipyard_positions, ships, size) -> Optional[Tuple[int]]: if len(ally_shipyard_positions) == 0: return None ships = [ ship for ship in ships if ship.position not in ally_shipyard_positions ] far_away_ships = [ ship for ship in ships if calculate_distance( ally_shipyard_positions[0], ship.position, size) >= 8 ] if far_away_ships: heaviest_ship = max(far_away_ships, key=lambda ship: ship.halite) return heaviest_ship.position a_little_far_away_shps = [ ship for ship in ships if calculate_distance( ally_shipyard_positions[0], ship.position, size) >= 5 ] if a_little_far_away_shps: heaviest_ship = max(a_little_far_away_shps, key=lambda ship: ship.halite) return heaviest_ship.position if ships: heaviest_ship = max(ships, key=lambda ship: ship.halite) return heaviest_ship.position return None
def decide_direction_in_responsive_area(board, my_position, size, safe_directions, responsive_area, halite_thresholds): for halite_threshold in halite_thresholds: candidate_positions = [pos for pos in responsive_area if board.cells[pos].halite >= halite_threshold] if candidate_positions: destination = min(candidate_positions, key=lambda x: calculate_distance(x, my_position, size)) return decide_direction(safe_directions, my_position, destination, size) return np.random.choice(safe_directions)
def decide_direction_for_rich_position(board, ship, size, safe_directions, percentile_threshold, search_width): threshold = np.percentile([cell.halite for cell in board.cells.values()], percentile_threshold) search_range = [((ship.position[0] + i) % size, (ship.position[0] + j) % size) for i in range(search_width) for j in range(search_width)] target_map = {pos: board.cells[pos].halite for pos in search_range if board.cells[pos].halite >= threshold} if target_map: destination = min(target_map.keys(), key=lambda x: calculate_distance(x, ship.position, size)) return decide_direction(safe_directions, ship.position, destination, size) return np.random.choice(safe_directions)
def attack_heavy_target_ship2(safe_directions, enemy_ship_halites, my_halite, my_position, enemy_ship_ids, target_enemy_id, size): heavier_enemy_ship_positions = {k: v for k, v in enemy_ship_halites.items() if v > my_halite} heavier_target_enemy_ship_positions = {pos: halite for pos, halite in heavier_enemy_ship_positions.items() if enemy_ship_ids[pos] == target_enemy_id} heavier_target_close_enemy_ship_positions = {pos: halite for pos, halite in heavier_target_enemy_ship_positions.items() if calculate_distance(pos, my_position, size) <= 100} if heavier_target_close_enemy_ship_positions: return attack_heaviest_ship(safe_directions, heavier_target_close_enemy_ship_positions, my_position, size) if heavier_target_enemy_ship_positions: return attack_heaviest_ship(safe_directions, heavier_target_enemy_ship_positions, my_position, size) if heavier_enemy_ship_positions: return attack_nearest_ship(safe_directions, enemy_ship_halites, my_position, size) return np.random.choice(safe_directions)
def decide_next_action(self): MAXIMUM_NUM_OF_SHIPYARDS = 2 MINE_HALITE_WHEN_HALITE_UNDER_GROUND_IS_OVER = 100 GO_SHIPYARD_WHEN_CARGO_IS_OVER = 500 # 「最終ターン」かつ「haliteを500以上積んでいる」ならばconvertする if self._step == 398 and self._my_halite > 500: return ShipAction.CONVERT, 'final_convert' # 動ける場所がないならconvertする if len(self._safe_directions) == 0 and self._my_whole_halite > 500: return ShipAction.CONVERT, 'negative_convert' if len(self._safe_directions) == 0: return None, 'nothing_to_do' condition1 = len(self._ally_shipyard_ids) < min(self._get_required_shipyards(self._step), MAXIMUM_NUM_OF_SHIPYARDS) condition2 = self._my_whole_halite >= 500 condition3 = 'stay' in self._safe_directions condition4 = self._my_position not in self._ally_shipyard_ids.keys() condition5 = (self._convert_ship_position is None) or (self._my_position == self._convert_ship_position) if condition1 and condition2 and condition3 and condition4 and condition5: return ShipAction.CONVERT, 'positive_convert' # その場にhaliteがたくさんあるなら拾う if self._halite_under > MINE_HALITE_WHEN_HALITE_UNDER_GROUND_IS_OVER and 'stay' in self._safe_directions: return None, 'mine' if len(self._ally_shipyard_ids) > 0: # 「序盤でない」かつ「haliteをたくさん載せている」ならshipyardsに帰る condition1 = self._my_halite > GO_SHIPYARD_WHEN_CARGO_IS_OVER and self._step > 80 # 「shipyardの近くにいる」かつ「haliteをそこそこ載せている」ならshipyardに帰る # TODO: 複数shipyardに対応する condition2 = self._my_halite > 100 and calculate_distance(self._my_position, list(self._ally_shipyard_ids.keys())[0], self._size) <= 5 if condition1 or condition2: direction = decide_direction_for_shipyard(ally_shipyard_ids=self._ally_shipyard_ids, my_position=self._my_position, safe_directions=self._safe_directions, size=self._size) return direction_mapper[direction], 'go_home' # 閾値以上のhaliteがある場所を探す # TODO: boardはあまり使いたくないが・・・ direction = decide_direction_in_responsive_area(board=self._board, my_position=self._my_position, size=self._size, safe_directions=self._safe_directions, responsive_area=self._responsive_area, halite_thresholds=[100, 50, 25, 5, 0]) return direction_mapper[direction], 'discover_halite'
def decide_direction_for_shipyard(ally_shipyard_ids, my_position, safe_directions, size): destination = min(ally_shipyard_ids.keys(), key=lambda x: calculate_distance(x, my_position, size)) return decide_direction(safe_directions, my_position, destination, size)
def attack_nearest_shipyard(my_position, size, safe_directions, enemy_shipyard_positions): destination = min(enemy_shipyard_positions, key=lambda x: calculate_distance(x, my_position, size)) return decide_direction(safe_directions, my_position, destination, size)