def get_shot(self) -> Point: """ Called each round by the game engine to get the next point to shoot on the opponents board. :return: The next point to shoot on the opponents board """ # Get the status of your last shot - could be useful in planning your next move! last_shot_status = self.last_shot_status # Example response: # { # 'shot': Point(4, 5), # type: Point # 'is_hit': True, # type: bool # 'is_sunk' True, # type: bool # 'ship_sunk': <ShipType.Battleship: 'Battleship'>, # type: ShipType # 'error': None # type: Union[None, Exception] # } x = random.randrange(0, BOARD_SIZE) y = random.randrange(0, BOARD_SIZE) while Point(x, y) in self.my_shots: x = random.randrange(0, BOARD_SIZE) y = random.randrange(0, BOARD_SIZE) self.my_shots.append(Point(x, y)) return Point(x, y)
def get_ship_placements( self, ships: List[Ship]) -> List[Tuple[Ship, Point, Orientation]]: """ Returns a set of point at which a ship will be placed. For each ship, you must return a tuple of [Ship, Point, Orientation], where Point corresponds to the bottom left corner of the Ship, e.g: - x - - - or - - x and Orientation is one of Orientation.Vertical and Orientation.Horizontal :param ships: A List of Ship which your bot should return placements for :return: A list of placements for each ship in 'ships' """ ships = sorted(ships, key=lambda x: len(x.horizontal_offsets)) placed = [ (ships[0], Point(0, 6), Orientation.Horizontal), (ships[1], Point(1, 1), Orientation.Vertical), (ships[2], Point(6, 2), Orientation.Horizontal), (ships[3], Point(3, 8), Orientation.Horizontal), (ships[4], Point(1, 5), Orientation.Horizontal), ] return placed
def get_ship_placements( self, ships: List[Ship]) -> List[Tuple[Ship, Point, Orientation]]: """ Returns a set of point at which a ship will be placed. For each ship, you must return a tuple of [Ship, Point, Orientation], where Point corresponds to the bottom left corner of the Ship, e.g: - x - - - or - - x and Orientation is one of Orientation.Vertical and Orientation.Horizontal :param ships: A List of Ship which your bot should return placements for :return: A list of placements for each ship in 'ships' """ PLACEMENTS = [ [ (ships[0], Point(1, 1), Orientation.Horizontal), (ships[1], Point(7, 2), Orientation.Vertical), (ships[2], Point(6, 8), Orientation.Horizontal), (ships[3], Point(2, 7), Orientation.Horizontal), (ships[4], Point(1, 4), Orientation.Horizontal), ], ] ships = sorted(ships, key=lambda x: len(x), reverse=True) return random.choice(PLACEMENTS)
def vicinity(p): return [ x for x in [ Point(p.x - 1, p.y), Point(p.x + 1, p.y), Point(p.x, p.y - 1), Point(p.x, p.y + 1) ] if 0 <= x.x < BOARD_SIZE and 0 <= x.y < BOARD_SIZE ]
def _destroy_area(self, pt): search_area = [ Point(pt.x - 1, pt.y), Point(pt.x + 1, pt.y), Point(pt.x, pt.y - 1), Point(pt.x, pt.y + 1), ] for p in search_area: if _is_valid(p) and p not in self.explored: self.to_check.add(p)
def staircase(last_shot_status, step_size): if last_shot_status['shot'] is None: return Point(0, 0) last_pt = last_shot_status['shot'] y = last_pt.y x = last_pt.x + step_size if x >= BOARD_SIZE: y = (y + 1) % BOARD_SIZE x = x % BOARD_SIZE return Point(x, y)
def _adjancent_points(p): points = [ Point(x=p.x, y=p.y + 1), Point(x=p.x, y=p.y - 1), Point(x=p.x + 1, y=p.y), Point(x=p.x - 1, y=p.y), ] return [ p for p in points if 0 <= p.x < BOARD_SIZE and 0 <= p.y < BOARD_SIZE ]
def get_best_shot(self): squares = [] # tuple of (x, y, score) bestScore = -999999 best = [] for x in range(10): for y in range(10): score = 0 if self.map[x][ y]: # if we've already fired at this square, skip continue if x > 0 and self.map[x - 1][y] == 'H': score += 10 if x > 1 and self.map[x - 2][y] == 'H': score += 10 elif x > 1 and self.map[x - 2][y] == 'H': score += 10 if x < 9 and self.map[x + 1][y] == 'H': score += 10 if x < 8 and self.map[x + 2][y] == 'H': score += 10 if y > 0 and self.map[x][y - 1] == 'H': score += 10 if y > 1 and self.map[x][y - 2] == 'H': score += 10 if y < 9 and self.map[x][y + 1] == 'H': score += 10 if y < 8 and self.map[x][y + 2] == 'H': score += 10 score -= self.seenX[x] score -= self.seenY[y] if ((x == 0 or self.map[x - 1][y] == 'M') and (x == 9 or self.map[x + 1][y] == 'M') and (y == 0 or self.map[x][y - 1] == 'M') and (y == 9 or self.map[x][y + 1] == 'M')): score -= 10 if score == bestScore: best.append(Point(x, y)) if score > bestScore: bestScore = score best = [Point(x, y)] return random.sample(best, 1)[0]
def get_ship_placements( self, ships: List[Ship]) -> List[Tuple[Ship, Point, Orientation]]: """ Returns a set of point at which a ship will be placed. For each ship, you must return a tuple of [Ship, Point, Orientation], where Point corresponds to the bottom left corner of the Ship, e.g: - x - - - or - - x and Orientation is one of Orientation.Vertical and Orientation.Horizontal :param ships: A List of Ship which your bot should return placements for :return: A list of placements for each ship in 'ships' """ # Perform random ship placement while True: placements = [] for ship in ships: random_orientation = random.choice(list(Orientation)) random_point = Point(random.randrange(0, BOARD_SIZE), random.randrange(0, BOARD_SIZE)) placements.append((ship, random_point, random_orientation)) if Board.is_valid_ship_placement(placements): break return placements
def get_neighbours(point: Point) -> List[Point]: neighbours = [] for x, y in NEIGHBOURS: neighbour = Point(point.x + x, point.y + y) if is_valid_point(neighbour): neighbours.append(neighbour) return neighbours
def __init__(self): super().__init__() self.my_shots = [] self.points = (i for i in reversed( list( Point(s[1], s[0]) for s in itertools.product( range(BOARD_SIZE), range(BOARD_SIZE)))))
def __init__(self): super().__init__() self.my_shots = [] self.next_steps = [] self.shots = [] for x in range(BOARD_SIZE): for y in range(BOARD_SIZE): if ((x % 2) == 0 and (y % 2) == 1) or ((x % 2) == 1 and (y % 2) == 0): self.shots.append(Point(x=x, y=y))
def _place_simple( self, ships: List[Ship]) -> List[Tuple[Ship, Point, Orientation]]: while True: placements = [] for ship in ships: next_point = Point(len(placements) * 2, 3) placements.append((ship, next_point, Orientation.Vertical)) if Board.is_valid_ship_placement(placements): break return placements
def get_shot(self) -> Point: """ Called each round by the game engine to get the next point to shoot on the opponents board. :return: The next point to shoot on the opponents board """ # Get the status of your last shot - could be useful in planning your next move! last = self.last_shot_status # Example response: # { # 'shot': Point(4, 5), # type: Point # 'is_hit': True, # type: bool # 'is_sunk' True, # type: bool # 'ship_sunk': <ShipType.Battleship: 'Battleship'>, # type: ShipType # 'error': None # type: Union[None, Exception] # } if last is not None and last.get('shot') is not None: # Don't pick last shot again self.grid[last['shot'].x][last['shot'].y] = 0. # If was a hit, increase likelihood in neighbours if last['is_hit']: x, y = last['shot'] points = [ (x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1), ] for x, y in points: if 0 <= x < BOARD_SIZE and 0 <= y < BOARD_SIZE: self.grid[x][y] *= 100. # Pick next shot based on likelihoods choices = [] weights = [] for x in range(BOARD_SIZE): for y in range(BOARD_SIZE): point = Point(x, y) weight = self.grid[x][y] if weight > 0: choices.append(point) weights.append(weight) choice = random.choices(choices, weights)[0] return choice
def get_ship_placements( self, ships: List[Ship]) -> List[Tuple[Ship, Point, Orientation]]: """ Returns a set of point at which a ship will be placed. For each ship, you must return a tuple of [Ship, Point, Orientation], where Point corresponds to the bottom left corner of the Ship, e.g: - x - - - or - - x and Orientation is one of Orientation.Vertical and Orientation.Horizontal :param ships: A List of Ship which your bot should return placements for :return: A list of placements for each ship in 'ships' """ placements = [ (ships[0], Point(2, 4), Orientation.Vertical), (ships[1], Point(1, 0), Orientation.Horizontal), (ships[2], Point(8, 3), Orientation.Vertical), (ships[3], Point(4, 5), Orientation.Vertical), (ships[4], Point(1, 2), Orientation.Horizontal), ] # lol return placements
def get_shot(self) -> Point: """ Called each round by the game engine to get the next point to shoot on the opponents board. :return: The next point to shoot on the opponents board """ # Get the status of your last shot - could be useful in planning your next move! last_shot_status = self.last_shot_status # Example response: # { # 'shot': Point(4, 5), # type: Point # 'is_hit': True, # type: bool # 'is_sunk' True, # type: bool # 'ship_sunk': <ShipType.Battleship: 'Battleship'>, # type: ShipType # 'error': None # type: Union[None, Exception] # } # last_shot_status(self, value: Dict[str, Union[Point, bool, ShipType, None]]): last_shot_status = self.last_shot_status last_shot = last_shot_status['shot'] is_hit = last_shot_status['is_hit'] is_sunk = last_shot_status['is_sunk'] is_error = last_shot_status['error'] ship_sunk = last_shot_status['ship_sunk'] first_shot = last_shot is not None previous_hit = None if not len(self.hits) else self.hits[-1] if is_hit: self.hits.append(last_shot) if previous_hit: if previous_hit.x == last_shot.x: for dy in [-1, 1]: yy = max(0, min(previous_hit.y + dy, BOARD_SIZE - 1)) point = Point(previous_hit.x, yy) if point not in self.my_shots: self.my_shots.append(point) return point if previous_hit.y == last_shot.y: for dx in [-1, 1]: xx = max(0, min(previous_hit.x + dx, BOARD_SIZE - 1)) point = Point(xx, previous_hit.y) if point not in self.my_shots: self.my_shots.append(point) return point if not is_sunk: for dx in [-1, 1]: for dy in [-1, 1]: xx = last_shot.x + dx yy = last_shot.y + dy xx = max(0, min(xx, BOARD_SIZE - 1)) yy = max(0, min(yy, BOARD_SIZE - 1)) point = Point(xx, yy) if point not in self.my_shots: self.my_shots.append(point) return point else: self.misses.append(last_shot) if is_error: print('error', is_error) x = random.randrange(0, BOARD_SIZE) y = random.randrange(0, BOARD_SIZE) while Point(x, y) in self.my_shots: x = random.randrange(0, BOARD_SIZE) y = random.randrange(0, BOARD_SIZE) self.my_shots.append(Point(x, y)) return Point(x, y) if is_sunk: pass if ship_sunk: pass
def get_shot(self) -> Point: """ Called each round by the game engine to get the next point to shoot on the opponents board. :return: The next point to shoot on the opponents board """ # Get the status of your last shot - could be useful in planning your next move! last_shot_status = self.last_shot_status # Example response: # { # 'shot': Point(4, 5), # type: Point # 'is_hit': True, # type: bool # 'is_sunk' True, # type: bool # 'ship_sunk': <ShipType.Battleship: 'Battleship'>, # type: ShipType # 'error': None # type: Union[None, Exception] # } last_shot = self.last_shot_status last_point = last_shot.get('shot') error = last_shot.get('error') if not error: if last_point: x = last_point.x y = last_point.y mx, my = 0, 0 for i in range(BOARD_SIZE): if Point(i, y) in self.my_shots: mx += 1 if Point(x, i) in self.my_shots: my += 1 self.hit_xs[x] = mx self.hit_ys[y] = my self.my_shots[last_point] = last_shot is_sunk = last_shot.get('is_sunk', False) is_hit = last_shot.get('is_hit', False) if is_hit and not is_sunk: self.hunt_mode = True self.hunted = self.hunted.union( self.vicinity(last_point)) - set(self.my_shots.keys()) elif is_sunk: self.hunt_mode = False if not self.hunt_mode: min_x = min(self.hit_xs) min_y = min(self.hit_ys) ix = [i for i, v in enumerate(self.hit_xs) if v == min_x] iy = [i for i, v in enumerate(self.hit_ys) if v == min_y] x = random.randrange(0, BOARD_SIZE) y = random.randrange(0, BOARD_SIZE) while Point(x, y) in self.my_shots: x = random.randrange(0, BOARD_SIZE) y = random.randrange(0, BOARD_SIZE) return Point(x, y) else: return self.hunted.pop()
def get_shot(self) -> Point: """ Called each round by the game engine to get the next point to shoot on the opponents board. :return: The next point to shoot on the opponents board """ # Get the status of your last shot - could be useful in planning your next move! last_shot_status = self.last_shot_status self.last_responses.append(last_shot_status) # Example response: # { # 'shot': Point(4, 5), # type: Point # 'is_hit': True, # type: bool # 'is_sunk' True, # type: bool # 'ship_sunk': <ShipType.Battleship: 'Battleship'>, # type: ShipType # 'error': None # type: Union[None, Exception] # } if last_shot_status['is_hit']: last_shot = last_shot_status['shot'] self.board[last_shot.x][last_shot.y][1] = 1 if last_shot_status['is_sunk']: self.board[last_shot.x][last_shot.y][2] = 1 next_score = {} for x in range(BOARD_SIZE): for y in range(BOARD_SIZE): if self.board[x][y][1] == 1: hit_neighbours = get_neighbours(Point(x, y)) for neighbour in hit_neighbours: if neighbour not in self.my_shots: return self.shoot(neighbour) if self.board[x][y][0] == 0: left_count = min(get_left_count(self.board, x, y), 5) right_count = min(get_right_count(self.board, x, y), 5) top_count = min(get_top_count(self.board, x, y), 5) bottom_count = min(get_bottom_count(self.board, x, y), 5) next_score[Point( x, y )] = left_count**2 + right_count**2 + top_count**2 + bottom_count**2 next_score_sorted = sorted(next_score.items(), key=lambda x: x[1], reverse=True) # print(next_score_sorted) # print(next_score_sorted) # exit(1) return self.shoot(next_score_sorted[0][0]) x = random.randrange(0, BOARD_SIZE) y = random.randrange(0, BOARD_SIZE) while Point(x, y) in self.my_shots: x = random.randrange(0, BOARD_SIZE) y = random.randrange(0, BOARD_SIZE) return self.shoot(Point(x, y))