Esempio n. 1
0
    def next_move(self, board: Board):
        """ returns the called AIPlayer's next move for a game on
            the specified Board object.
            input: board is a Board object for the game that the called
                     Player is playing.
            return: row, col are the coordinated of a vacant location on the board
        """
        assert (not board.is_full())
        assert (self.depth % 2 == 1)

        self.num_moves += 1
        self.__init_nextMove()
        if board.is_empty():
            # if it's the 1st move, and it's AI's turn
            # then ai will randomly choose one in the center of the board.
            cent_row = board.width // 2
            cent_col = board.height // 2
            buff_row = round(board.width / 20)
            buff_col = round(board.width / 20)
            self.__next_moves.append(
                (random.randint(-buff_row, buff_row) + cent_row,
                 random.randint(-buff_col, buff_col) + cent_col))
        else:
            self.__temp_record = np.zeros((board.height, board.width, 4),
                                          dtype=np.bool)
            self.__my_max(board)
        # in the most case, AI will choose the 1st move
        row, col = self.__next_moves[0]
        # TODO: in the rare case, AI will choose other moves
        # row, col = random.choice(self.__next_moves)
        return row, col
Esempio n. 2
0
    def __my_max(self,
                 board: Board,
                 depth=0,
                 alpha=float("-inf"),
                 beta=float("inf")):
        # quit condition:
        if depth >= self.depth:
            # here the negative symbol is a key point.
            return -self.__evaluate(board)

        me_chk_id = board.get_checker_id(self.checker)
        op_chk_id = board.get_checker_id(self.opponent_checker)
        for n_row, n_col in board.iter_recent_empty():
            if not board.has_neighbor(
                    n_row, n_col):  # TODO: this step can also be optimized!
                continue
            if depth % 2 == 0:
                board.add_checker_id(me_chk_id, n_row, n_col)
            else:
                board.add_checker_id(op_chk_id, n_row, n_col)
            value = -self.__my_max(board, depth + 1, -beta, -alpha)
            board.delete_checker(n_row, n_col)
            if value > alpha:
                if depth == 0:
                    self.__next_moves.clear()
                    self.__next_moves.append((n_row, n_col))
                if value >= beta:
                    return beta
                alpha = value
            elif value == alpha:
                if depth == 0:
                    self.__next_moves.append((n_row, n_col))

        return alpha
Esempio n. 3
0
def gomoku(p1, p2):
    """ Plays the Gomoku between the two specified players,
        and returns the Board object as it looks at the end of the game.
        inputs: p1 and p2 are objects representing players 
          One player should use 'X' checkers and the other should
          use 'O' checkers.
    """
    # Make sure one player is 'X' and one player is 'O'.
    if p1.checker not in 'XO' or p2.checker not in 'XO' \
       or p1.checker == p2.checker:
        print('need one X player and one O player.')
        return None

    print('Welcome to Gomoku!')
    print()
    b = Board(10, 10)
    print(b)
    p1.num_moves = 0
    p2.num_moves = 0

    while True:
        if process_move(p1, b) == True:
            return b

        if process_move(p2, b) == True:
            return b
Esempio n. 4
0
    def __evaluate(self, board: Board):
        """
        Evaluate the score of the current board.
        :param board: The board object
        :return: A score, numeric.
        """
        assert (self.__temp_record is not None)
        self.__temp_record.fill(0)
        # score_board has 3 dims: row, col, and 4 different directions.
        me_chk_id = board.get_checker_id(self.checker)
        op_chk_id = board.get_checker_id(self.opponent_checker)

        score_count = {me_chk_id: [0] * 8, op_chk_id: [0] * 8}

        # we only iterate slots which has been used
        nz = board.slots != 0
        rows, cols = np.where(nz)

        for row, col in zip(rows, cols):
            if board.slots[row, col] == me_chk_id:
                self.__check_point(board, row, col, score_count)
            else:
                self.__check_point(board, row, col, score_count)
        return self.__calc_score(score_count, me_chk_id, op_chk_id)