예제 #1
0
class Bot():
    def __init__(self):
        """Initialize instance variables."""
        self.ownBoard = Board((10, 10), None, own=True)
        self.enemyBoard = Board((10, 10), None, own=False)
        self.shipsToPlace = [[size, Ship(size).count] for size in Ship]
        self.lastCoord = (0, 0)

    def handle_result(self, text):
        """Handle the server's result message."""
        if text.find("RESULT HIT") != -1:
            self.enemyBoard.set(self.lastCoord, Tile.Ship)

    def handle_update(self, text):
        """Handle the server's update message."""
        if text.find("RESULT GOTISLAND"):
            tokens = text.strip().split()
            coord = (int(re.sub("\D", "",
                                tokens[2])), int(re.sub("\D", "", tokens[3])))
            self.ownBoard.set(coord, Tile.Island)

    def handle_command(self, text):
        """Handle the server's message."""
        tokens = text.strip().split()
        if tokens[0] == 'REQUEST' and tokens[1] == 'ACTION':
            if tokens[2] == 'SHIP':
                location = self.choose_ship_location()
                self.place_ship(location[0], location[1])
            if tokens[2] == 'ISLAND':
                coord = self.choose_island_location()
                self.place_island(coord)
            if tokens[2] == 'SHOT':
                coord = self.choose_shot_location()
                self.shoot(coord)
        if tokens[0] == 'RESULT':
            self.handle_result(text)
        if tokens[0] == 'UPDATE':
            self.handle_update(text)
        if tokens[0] == 'GAME' and tokens[1] == 'RESULT':
            self.done = True

    def choose_ship_location(self):
        """Return a location where a ship should be placed."""
        raise NotImplementedError(
            "You need to implement your own choose_ship_location method.")

    def choose_ship_size(self):
        """"Return a ship size that can be placed on the board."""
        shipSize = 0
        for index, (size, count) in enumerate(self.shipsToPlace):
            if count > 0:
                self.shipsToPlace[index][1] -= 1
                return self.shipsToPlace[index][0]
        return shipSize

    def choose_island_location(self):
        """Return the next island's location."""
        self.placementIndex += 1
        return (int(self.placementIndex / 10), self.placementIndex % 10)

    def choose_shot_location(self):
        """Return the next shot's location."""
        self.placementIndex += 1
        return (int(self.placementIndex / 10), self.placementIndex % 10)

    @staticmethod
    def formatCoord(coord):
        """Return a properly formatted coordinate string."""
        return "(" + str(coord[0]) + "," + str(coord[1]) + ")"

    def place_ship(self, start, end):
        """Print a command to stdout with the next ship's desired coordinates."""
        success = self.ownBoard.placeShip(start, end)
        if not success[0]:
            raise Exception("Illegal ship placement: {0}.", success[1])
        start = "(" + str(start[0]) + "," + str(start[1]) + ")"
        end = "(" + str(end[0]) + "," + str(end[1]) + ")"
        print("PLACE SHIP", start, end)
        sys.stdout.flush()  #Nodig?

    def place_island(self, coord):
        """Print a command to stdout with the next island's desired coordinates."""
        success = self.enemyBoard.placeIsland(coord)
        if not success:
            raise Exception("Illegal island placement.")
        coord = Bot.formatCoord(coord)
        print("PLACE ISLAND", coord)

    def shoot(self, coord):
        """Print a command to stdout with the next shot's desired coordinates."""
        self.lastCoord = coord
        coord = Bot.formatCoord(coord)
        print("SHOOT", coord)

    def run(self):
        """Run the bot."""
        self.done = False
        while self.done != True:
            command = input()
            self.handle_command(command)
예제 #2
0
class Bot:
    def __init__(self):
        """Initialize instance variables."""
        self.board = Board((15, 15))
        self.done = False
        self.water_rounds = []
        self.you = None

    def handle_config(self, config_info: str):
        config_info = config_info.split(maxsplit=3)
        if config_info[0] == "WATER" and config_info[1] == "ROUND":
            self.water_rounds.append(int(config_info[2]))

        elif config_info[0] == "TILE":
            coord = Bot.get_coord(config_info[1] + config_info[2])
            lookup = {
                "WATER": Tile.Water,
                "MOUNTAIN": Tile.Mountain,
                "TREE": Tile.Tree,
                "EMPTY": Tile.Empty
            }
            self.board.set(coord, lookup[config_info[3]])

        elif config_info[0] == "PLAYER":
            p_id = config_info[2]

            if p_id not in self.board.players:
                self.board.players[p_id] = {'name': None, 'pos': None,
                                            'lives': None}

            if config_info[1] == "NAME":
                self.board.players[p_id]['name'] = config_info[3]
            elif config_info[1] == "PLACE":
                self.board.players[p_id]['pos'] = Bot.get_coord(config_info[3])
            elif config_info[1] == "LIVES":
                self.board.players[p_id]['lives'] = int(config_info[3])

        elif config_info[0] == "YOU":
            self.you = config_info[1]

    def handle_update(self, update_info: str):
        update_info = update_info.split(maxsplit=2)
        if update_info[0] == "PLAYER":
            user_data = update_info[2].split(maxsplit=1)
            p_id = user_data[0]

            if update_info[1] == "LOC":
                self.board.players[p_id]['pos'] = Bot.get_coord(user_data[1])

            elif update_info[1] == "STATUS":
                if user_data[1] == "HIT":
                    self.board.players[p_id]['lives'] -= 1

                elif user_data[1] == "DEAD":
                    self.board.players[p_id]['lives'] = 0

        if update_info[0] == "BOMB":
            coord = Bot.get_coord(update_info[2])

            if update_info[1] == "PLACED":
                self.board.bombs[coord] = 8
            elif update_info[1] == "EXPLODED":
                if coord in self.board.bombs:
                    del self.board.bombs[coord]

        if update_info[0] == "TILE" and update_info[1] == "GONE":
            coord = Bot.get_coord(update_info[2])
            self.board.set(coord, Tile.Empty)

    def handle_command(self, text: str):
        """Handle the server's message."""

        tokens = text.strip().split(maxsplit=1)

        if tokens[0] == 'CONFIG':
            self.handle_config(tokens[1])
        elif tokens[0] == 'START':
            self.initialise()
        elif tokens[0] == 'REQUEST':
            for b_coord in self.board.bombs.keys():
                self.board.bombs[b_coord] -= 1
                if self.board.bombs[b_coord] == 0:
                    log("bomb exploded at: " + str(b_coord))
            self.report_move()
        elif tokens[0] == 'UPDATE':
            self.handle_update(tokens[1])
        elif tokens[0] == "YOU":
            if "LOST" in tokens[1]:
                log(tokens[1])
            self.done = True

    def do_move(self):
        raise NotImplementedError("Implement this function to do a move")

    def report_move(self):
        move = self.do_move()
        direction = move['dir']  #: Tuple[int, int]
        bomb = move['bomb']  #: bool

        if max(direction) > 1 or min(direction) < -1:
            raise ValueError("one of the dims is out of range")

        if not self.board.is_valid_move(
                tuple(map(operator.add,
                          self.board.players[self.you]['pos'],
                          direction))):
            raise ValueError("This is not a valid location: {} {} {}".format(self.board.players[self.you]['pos'],
                          direction, tuple(map(operator.add,
                          self.board.players[self.you]['pos'],
                          direction))))

        if bomb:
            print("BOMBWALK {}".format(Bot.format_dir(direction)))
        else:
            print("WALK {}".format(Bot.format_dir(direction)))

    def initialise(self):
        pass

    def run(self):
        """Run the bot."""
        self.done = False
        while not self.done:
            command = input()
            self.handle_command(command)

    def get_valid_dirs(self) -> List[Tuple[int, int]]:
        x, y = self.board.players[self.you]['pos']
        choices = ([(1, 0)] if x != 13 else []) \
                  + ([(0, 1)] if y != 13 else []) \
                  + ([(-1, 0)] if x != 1 else []) \
                  + ([(0, -1)] if y != 1 else [])
        choices = list(filter((lambda coord:
                               self.board.board[y + coord[1]][x + coord[0]]
                               == Tile.Empty),
                              choices))

        return choices

    @staticmethod
    def format_dir(coord: Tuple[int, int]):
        """Return a direction according to a coord"""
        dirs = {(0, -1): "UP", (0, 1): "DOWN",
                (-1, 0): "LEFT", (1, 0): "RIGHT",
                (0, 0): "STAY"}
        return dirs[coord]

    @staticmethod
    def format_coord(coord: Tuple[int, int]):
        """Return a properly formatted coordinate string."""
        return "(" + str(coord[0]) + ", " + str(coord[1]) + ")"

    @staticmethod
    def get_coord(coord_str: str) -> Tuple[int, int]:
        coord_strs = coord_str.split(',')
        return int(coord_strs[0][1:]), int(coord_strs[1][:-1])