Exemple #1
0
    def policy_moves_cmd(self, args):
        # if the game is already end
        if (self.board.check_game_end_gomoku()[0]):
            self.respond()
            return

        # check if still have the empty points
        if len(GoBoardUtil.generate_legal_moves_gomoku(self.board)) == 0:
            self.respond()
            return

        # use copy board
        cboard = self.board.copy()

        # check policy
        if self.policy_type == "random":
            moves = GoBoardUtil.generate_legal_moves_gomoku(self.board)
            moves_string = []
            for move in moves:
                move_coord = point_to_coord(move, self.board.size)
                move_as_string = format_point(move_coord)
                moves_string.append(move_as_string)
            sorted_moves = ' '.join(sorted(moves_string))
            self.respond("Random {}".format(sorted_moves))
        else:
            policy, moves = PatternUtil.generate_policy_moves(cboard)

            moves_string = []
            for move in moves:
                move_coord = point_to_coord(move, self.board.size)
                move_as_string = format_point(move_coord)
                moves_string.append(move_as_string)

            sorted_moves = ' '.join(sorted(moves_string))
            self.respond(policy + " " + sorted_moves)
Exemple #2
0
def solve(board):
    result = game_end(board)
    if (result != None):
        return result, "First"
    alpha, beta = -1, 1
    haveDraw = False
    solvePoint = board.list_solve_point()
    if solvePoint:
        #print(solvePoint[0])
        board.play_move_gomoku(solvePoint[0], board.current_player)
        result = -alphabeta(board, -beta, -alpha)
        undo(board, solvePoint[0])
        if (result == 1):
            return True, solvePoint[0]
        elif (result == 0):
            haveDraw = True
    else:
        for m in GoBoardUtil.generate_legal_moves_gomoku(board):
            board.play_move_gomoku(m, board.current_player)
            result = -alphabeta(board, -beta, -alpha)
            #print(GoBoardUtil.get_twoD_board(board))
            #print(result)
            undo(board, m)
            if (result == 1):
                return True, m
            elif (result == 0):
                haveDraw = True
    return haveDraw, "NoMove"
    """
Exemple #3
0
    def simulate(self, board, color, legal_moves, mode):
        winList = []
        if not legal_moves:
            legal_moves = GoBoardUtil.generate_legal_moves_gomoku(board)
        check = board.check_game_end_gomoku()

        if check[0] == True:
            return
        elif legal_moves == []:
            return
        if mode == 'random':
            mode_sim = 'random'
        else:
            mode_sim = 'rule'
        for move in legal_moves:
            s = 0
            for i in range(self.N):
                temp_b = board.copy()
                temp_b.play_move_gomoku(move, color)
                s = s + self.simulate_iter(temp_b, color, mode_sim)
            s = s / 10
            winList.append(s)

        index = winList.index(max(winList))
        if winList:
            index = winList.index(max(winList))
        best = legal_moves[index]
        return best
Exemple #4
0
 def get_move(self, board, color_to_play):
     """
     The genmove function called by gtp_connection
     """
     moves = GoBoardUtil.generate_legal_moves_gomoku(board)
     toplay = board.current_player
     best_result, best_move = -1.1, None
     best_move = moves[0]
     wins = np.zeros(len(moves))
     visits = np.zeros(len(moves))
     while True:
         for i, move in enumerate(moves):
             play_move(board, move, toplay)
             res = game_result(board)
             if res == toplay:
                 undo(board, move)
                 #This move is a immediate win
                 self.best_move = move
                 return move
             ret = self._do_playout(board, toplay)
             wins[i] += ret
             visits[i] += 1
             win_rate = wins[i] / visits[i]
             if win_rate > best_result:
                 best_result = win_rate
                 best_move = move
                 self.best_move = best_move
             undo(board, move)
     assert (best_move is not None)
     return best_move
Exemple #5
0
 def BlockWin(self):
     legal_moves = GoBoardUtil.generate_legal_moves_gomoku(self.board)
     opp = GoBoardUtil.opponent(self.board.current_player)
     result = self.Win(opp)
     if result:
         return result
     return False
    def alphabetaDL(self, alpha, beta, depth):

        moves = self.board.get_empty_points()
        board_full = (len(moves) == 0)  #board full check
        win_step = []
        if self.board.check_game_end_gomoku(
        )[0] or depth == 0 or board_full:  #checking end game, no depth, draw
            return self.staticallyEvaluateForToPlay()
        for move in GoBoardUtil.generate_legal_moves_gomoku(
                self.board):  #moves inlegal move
            self.board.play_move_gomoku(
                move, self.board.current_player)  #play a stone
            value = -self.alphabetaDL(-beta, -alpha,
                                      depth - 1)[0]  #alphabeta search
            if value > alpha:
                alpha = value
                win_step.clear()
                win_step.append(move)
                '''
            if value == alpha:
                win_step.append(move)'''
            self.board.undo(move)
            if value >= beta:
                return beta, win_step  # or value in failsoft (later)

        return alpha, win_step
Exemple #7
0
    def my_policy_moves(self,board,color):

        points = GoBoardUtil.generate_legal_moves_gomoku(board)
        moves = self.legalMoves(board)
        self.move_to_point=dict(zip(moves,points))
        self.point_to_move=dict(zip(points,moves))

        empty_moves = self.legalMoves(board)
        win_moves = []
        block_win_moves = []
        open_four_moves = []
        block_open_four_moves = []
        open_three_moves = []
        steps = [1,board.NS,board.NS-1,board.NS+1]
        for move in empty_moves:
            for step in steps:
                point = self.move_to_point[move]
                if board.five_in_row(point,board.current_player,step):
                    win_moves.append(move)
                elif board.five_in_row(point,GoBoardUtil.opponent(board.current_player),step):
                    block_win_moves.append(move)
                elif board.OpenFour(point,board.current_player,step):
                    open_four_moves.append(move)
                elif board.BlockOpenFour(point,GoBoardUtil.opponent(board.current_player),step):
                    block_open_four_moves.append(move)

        move_types=["Win ","BlockWin ","OpenFour ","BlockOpenFour ","Random "]
        moves=[win_moves,block_win_moves,open_four_moves,block_open_four_moves,empty_moves]
        for i in range(len(move_types)):
            if moves[i]:
                return move_types,moves[i]
Exemple #8
0
def alphabeta(board, alpha, beta):
    #print(GoBoardUtil.get_twoD_board(board),alpha,beta)
    result = game_end(board)
    if (result != None):
        return result
    solvePoint = board.list_solve_point()
    if solvePoint:
        #print(solvePoint[0])
        board.play_move_gomoku(solvePoint[0], board.current_player)
        result = -alphabeta(board, -beta, -alpha)
        if (result > alpha):
            alpha = result
        undo(board, solvePoint[0])
        if (result >= beta):
            return beta
    else:
        for m in GoBoardUtil.generate_legal_moves_gomoku(board):
            board.play_move_gomoku(m, board.current_player)
            result = -alphabeta(board, -beta, -alpha)
            if (result > alpha):
                alpha = result
            undo(board, m)
            if (result >= beta):
                return beta
    return alpha
Exemple #9
0
    def get_pattern_move_by_signal(self, board, color_to_play):
        ## RAY's before Apr.6, 2019 ######
        # ret = board.get_pattern_moves()
        # if ret is None:
        #     return GoBoardUtil.generate_random_move_gomoku(board)
        # movetype_id, moves = ret
        # move = random.choice(moves)
        # return move
        ##################################

        ## RAY's after Apr.6 2019 ########
        ret = board.get_pattern_moves()
        if ret is None:
            moves = GoBoardUtil.generate_legal_moves_gomoku(board)
        else:
            movetype_id, moves = ret

        best_move = moves[0]
        best_score = -math.inf
        # print(moves)

        for move in moves:
            board.play_move_gomoku(move, color_to_play)
            score = board.board_searcher.evaluator.evaluate(
                board.twoDBoard, color_to_play)

            if score > best_score:
                best_score = score
                best_move = move

            board.undo_move_gomoku()
        return best_move
Exemple #10
0
    def policy_moves_cmd(self, args):
        checkpoint = "Random"

        moves = GoBoardUtil.generate_legal_moves_gomoku(self.board)
        color = self.board.current_player
        if self.policytype == "rule_based":
            if self.Win(color):
                checkpoint = "Win"
                moves = self.Win(color)
            elif self.BlockWin():
                checkpoint = "BlockWin"
                moves = self.BlockWin()
            elif self.OpenFour(color):
                checkpoint = "OpenFour"
                moves = self.OpenFour(color)
            elif self.BlockOpenFour(color):
                checkpoint = "BlockOpenFour"
                moves = self.BlockOpenFour(color)

        move = []

        for i in moves:
            move_coord = point_to_coord(i, self.board.size)
            move_as_string = format_point(move_coord)
            move.append(move_as_string)

        move.sort()
        for i in move:
            checkpoint += " " + i
        if checkpoint == "Random":
            checkpoint = ""
        self.respond(checkpoint)
Exemple #11
0
    def __init__(self, go_engine, board, debug_mode=False):
        """
        Manage a GTP connection for a Go-playing engine

        Parameters
        ----------
        go_engine:
            a program that can reply to a set of GTP commandsbelow
        board: 
            Represents the current board state.
        """
        self._debug_mode = debug_mode
        self.go_engine = go_engine
        self.board = board
        self.policy_type = "rule_based"
        #signal.signal(signal.SIGALRM, self.handler)
        self.commands = {
            "protocol_version": self.protocol_version_cmd,
            "quit": self.quit_cmd,
            "name": self.name_cmd,
            "boardsize": self.boardsize_cmd,
            "showboard": self.showboard_cmd,
            "clear_board": self.clear_board_cmd,
            "komi": self.komi_cmd,
            "version": self.version_cmd,
            "known_command": self.known_command_cmd,
            "genmove": self.genmove_cmd,
            "list_commands": self.list_commands_cmd,
            "play": self.play_cmd,
            "legal_moves": self.legal_moves_cmd,
            "gogui-rules_game_id": self.gogui_rules_game_id_cmd,
            "gogui-rules_board_size": self.gogui_rules_board_size_cmd,
            "gogui-rules_legal_moves": self.gogui_rules_legal_moves_cmd,
            "gogui-rules_side_to_move": self.gogui_rules_side_to_move_cmd,
            "gogui-rules_board": self.gogui_rules_board_cmd,
            "gogui-rules_final_result": self.gogui_rules_final_result_cmd,
            "gogui-analyze_commands": self.gogui_analyze_cmd,
            "timelimit": self.timelimit_cmd,
            "policy_moves": self.policy_moves_cmd,
            "policy": self.policy_cmd,
            "count": self.count_color_cmd
        }
        self.timelimit = 60
        self.open = False
        # used for argument checking
        # values: (required number of arguments,
        #          error message on argnum failure)
        self.argmap = {
            "boardsize": (1, 'Usage: boardsize INT'),
            "komi": (1, 'Usage: komi FLOAT'),
            "known_command": (1, 'Usage: known_command CMD_NAME'),
            "genmove": (1, 'Usage: genmove {w,b}'),
            "play": (2, 'Usage: play {b,w} MOVE'),
            "legal_moves": (1, 'Usage: legal_moves {w,b}')
        }
        self.all_points = GoBoardUtil.generate_legal_moves_gomoku(self.board)
        moves = self.legalMoves()
        self.move_to_point = dict(zip(moves, self.all_points))
        self.point_to_move = dict(zip(self.all_points, moves))
def MinimaxBooleanAND(board, depth, color, alpha, beta, start_time):
    moves = GoBoardUtil.generate_legal_moves_gomoku(board)
    worst_points = 10000

    time_elapsed = time.time() - start_time
    #DEBUG - remove later
    print(time_elapsed)
    #check to see if out of time
    if time_elapsed >= TIME_LIMIT:
        return False, EMPTY, 0

    #check to see if terminal state
    check_win, check_color = board.check_game_end_gomoku()
    if check_win == True:
        if check_color == color:
            return False, check_color, 0
        else:
            return True, check_color, 10000

    #base case
    if (depth == 0 or len(moves) == 0):
        if len(moves) == 0:
            return board.StatisticallyEvaluate(False)
        return board.StatisticallyEvaluate()

    for move in moves:

        save_board(board)
        board.play_move_gomoku(move, color)
        win, col, points = MinimaxBooleanOR(board, depth - 1,
                                            opposite_color(color), alpha, beta,
                                            start_time)

        if win == False and col == EMPTY:
            return False, EMPTY, 0

        if col != opposite_color(color):
            win = False
            points = -points
        if not win:
            board = undo()
            return False, col, 0
        if points < worst_points:
            worst_points = points

        board = undo()

        # deal with alpha-beta values
        #if worst_points <= alpha:
        #alert("alpha cutoff: " + str(alpha))
        #return False, opposite_color(color), worst_points
        if worst_points <= beta:
            beta = points

    #DEBUG
    #print("Worst points: " + str(worst_points))
    #print("MinimaxAND: ")
    #print(str(GoBoardUtil.get_twoD_board(board)))
    return True, opposite_color(color), 10000
Exemple #13
0
    def BlockOpenFour(self, color):
        legal_moves = GoBoardUtil.generate_legal_moves_gomoku(self.board)
        opp = GoBoardUtil.opponent(color)
        result = self.OpenFour_my(opp)
        if result:

            return result
        return False
Exemple #14
0
    def legalMoves(self):
        moves = GoBoardUtil.generate_legal_moves_gomoku(self.board)
        gtp_moves = []
        for move in moves:
            coords = point_to_coord(move, self.board.size)
            gtp_moves.append(format_point(coords))

        return gtp_moves
Exemple #15
0
    def genmove_cmd(self, args):
        """
        Generate a move for the color args[0] in {'b', 'w'}, for the game of gomoku.
        """
        board_color = args[0].lower()
        color = color_to_int(board_color)
        game_end, winner = self.board.check_game_end_gomoku()
        if game_end:
            if winner == color:
                self.respond("pass")
            else:
                self.respond("resign")
            return
        move = GoBoardUtil.generate_legal_moves_gomoku(self.board)
        if (self.policytype == "random"):
            best = None
            cur_max = 0
            for i in move:
                if best == None:
                    best = i
                gmax = 0
                for _ in range(10):
                    result = self.random(self.board, color, color)
                    gmax += result
                if (gmax / 10) > cur_max:
                    best = i
                    cur_max = (gmax / 10)
        elif (self.policytype == "rule_based"):
            best = None
            cur_max = 0
            for i in move:
                if best == None:
                    best = i
                gmax = 0
                self.board.play_move_gomoku(i, color)

                for _ in range(10):
                    result = self.rules(self.board, color,
                                        GoBoardUtil.opponent(color))
                    gmax += result
                    #print(wins)

                if (gmax / 10) > cur_max:
                    best = i
                    #print(best_move)
                    cur_max = (gmax / 10)
                self.board.reset_point_gomoku(i, color)

        if best == PASS:
            self.respond("pass")
            return
        move_coord = point_to_coord(best, self.board.size)
        move_as_string = format_point(move_coord)
        if self.board.is_legal_gomoku(best, color):
            self.board.play_move_gomoku(best, color)
            self.respond(move_as_string)
        else:
            self.respond("illegal move: {}".format(move_as_string))
def Minimax(board, depth, color):
    start_time = time.time()
    moves = GoBoardUtil.generate_legal_moves_gomoku(board)
    best_points = 0
    best_move = None
    is_win = 0
    alpha = NINFINITY
    beta = INFINITY

    #special case: check to see if current board already has a winner
    win, col = board.check_game_end_gomoku()
    if win == True:
        #if the opposite color already won, then return win=0
        if col == opposite_color(color):
            return 0, None
        #if our current winner already won, return

    for move in moves:
        time_elapsed = time.time() - start_time
        if time_elapsed >= TIME_LIMIT:
            return 4, None
        #DEBUG - remove later
        print(time_elapsed)
        save_board(board)
        board.play_move_gomoku(move, color)
        win, col, points = MinimaxBooleanAND(board, depth - 1,
                                             opposite_color(color), alpha,
                                             beta, start_time)

        if col == EMPTY:
            return 4, None

        #DEBUG
        move_coord = point_to_coord(move, board.size)
        move_as_string = format_point(move_coord)
        print("move: " + move_as_string + ", points: " + str(points))

        if win and col == color:
            is_win = 2
            best_move = move
            best_points = points
            alpha = best_points
            return is_win, best_move

        if not win and col == opposite_color(color):
            is_win = 0
            best_move = None

        #process a draw, best condition if win not an option
        #if ((is_win != 2 and is_win != 0) and points == 0):
        if not win and col == None:
            is_win = 1
            best_move = move

        board = undo()

    return is_win, best_move
Exemple #17
0
 def reset(self, size):
     """
     Reset the board to empty board of given size
     """
     self.board.reset(size)
     points = GoBoardUtil.generate_legal_moves_gomoku(self.board)
     moves = self.legalMoves()
     self.move_to_point = dict(zip(moves, points))
     self.point_to_move = dict(zip(points, moves))
Exemple #18
0
 def expand(self, board, color):
     """
     Expands tree by creating new children.
     """
     moves = GoBoardUtil.generate_legal_moves_gomoku(board)
     for move in moves:
         if move not in self._children:
             self._children[move] = TreeNode(self)
             self._children[move]._move = move
     self._expanded = True
Exemple #19
0
 def Win(self, color):
     legal_moves = GoBoardUtil.generate_legal_moves_gomoku(self.board)
     shuai = []
     for point in legal_moves:
         rt_moves = self.detect_immediate_win_for_a_point(point, color)
         if len(rt_moves) != 0:
             shuai.append(rt_moves[0])
     if len(shuai) > 0:
         # print("shuai:", shuai)
         return shuai
     return False
Exemple #20
0
 def get_policy_moves(self, board, useRules=True):
     if (useRules):
         MoveType, moves = GoBoardUtil.generate_rule_based_moves(board)
         if (MoveType != "Random"):
             return MoveType, moves
     # if we're not using rules
     # or generate_rule_based_moves(..) returned nothing
     moves = GoBoardUtil.generate_legal_moves_gomoku(board)
     if (len(moves) > 0):
         return "Random", moves
     return "", []
Exemple #21
0
    def BlockOpenFour(self, color):
        legal_moves = GoBoardUtil.generate_legal_moves_gomoku(self.board)
        opp = GoBoardUtil.opponent(color)
        result = self.OpenFour_my(opp)
        if result:
            if len(result) == 1:
                for node in legal_moves:
                    check_3_connect(point)

            else:
                return result
        return False
Exemple #22
0
 def gogui_rules_legal_moves_cmd(self, args):
     game_end, _ = self.board.check_game_end_gomoku()
     if game_end:
         self.respond()
         return
     moves = GoBoardUtil.generate_legal_moves_gomoku(self.board)
     gtp_moves = []
     for move in moves:
         coords = point_to_coord(move, self.board.size)
         gtp_moves.append(format_point(coords))
     sorted_moves = ' '.join(sorted(gtp_moves))
     self.respond(sorted_moves)
Exemple #23
0
def policy_moves(board, color_to_play):
    # if(self.playout_policy=='random'):
    #    return "Random", self._random_moves(board, color_to_play)
    #else:
    #   assert(self.playout_policy=='rule_based')
    #  assert(isinstance(board, SimpleGoBoard))
    pattern_list = ['Win', 'BlockWin', 'OpenFour', 'BlockOpenFour', 'Random']
    ret = board.get_pattern_moves()
    if ret is None:
        return "Random", GoBoardUtil.generate_legal_moves_gomoku(board)

    movetype_id, moves = ret
    return pattern_list[movetype_id], moves
Exemple #24
0
 def gogui_rules_legal_moves_cmd(self, args):
     game_end,_ = self.board.check_game_end_gomoku()
     if game_end:
         self.respond()
         return
     moves = GoBoardUtil.generate_legal_moves_gomoku(self.board)
     gtp_moves = []
     for move in moves:
         coords = point_to_coord(move, self.board.size)
         gtp_moves.append(format_point(coords))
     # adding sort key sorts by letter first then the numeric value A1, A2, > A10
     sorted_moves = ' '.join(sorted(gtp_moves, key=lambda m: (m[0:1], int(m[1:]))))
     self.respond(sorted_moves)
def solve(board):
    result=game_end(board)
    if (result!=None):
        return result,"First"
    alpha,beta=-1,1
    haveDraw=False
    solvePoint=board.list_solve_point()
    if solvePoint:
        #print(solvePoint[0])
        board.play_move_gomoku(solvePoint[0],board.current_player)
        result=-int(alphabeta(board,-beta,-alpha))
        undo(board,solvePoint[0])
        if(result==1):
            return True,solvePoint[0]
        elif(result==0):
            haveDraw=True
    else: 
        for m in GoBoardUtil.generate_legal_moves_gomoku(board):
            board.play_move_gomoku(m,board.current_player)
            result=-int(alphabeta(board,-beta,-alpha))
            #print(GoBoardUtil.get_twoD_board(board))
            #print(result)
            undo(board,m)
            if(result==1):
                return True,m
            elif(result==0):
                haveDraw=True
    return haveDraw,"NoMove"


    

    # for m in board.legal_moves():
    #     history_set.add(str(board.get_twoD_board())+str(board.current_player))
    #     board.move(m, board.current_player)
    #     result,move=None, None
    #     if board.end_of_game():
    #         result,move = isSuccess(board, komi), "NoMove"
    #     elif str(board.get_twoD_board())+str(board.current_player) in history_set:
    #         board.undo_move()
    #         continue
    #     if result==None and move==None:
    #         result, move = negamaxBoolean(board, komi, history_set)
    #     success = not result
    #     board.undo_move()

    #     history_set.remove(str(board.get_twoD_board())+str(board.current_player))
    #     if success:
    #         return True, m
    # return False, "NoMove"
    
    def get_move(self, board, color_to_play):
        """
        The genmove function called by gtp_connection
        """

        sensible_moves = GoBoardUtil.generate_legal_moves_gomoku(board)
        if len(sensible_moves) > 0:
            start = timer()
            move = self.mcts.get_move(board)
            end = timer()
            self.mcts.update_with_move(-1)
            print("time = ", end - start)
            return move
        else:
            print("WARNING: the board is full")
Exemple #27
0
 def detect_immediate_win_for_a_point(self, current,
                                      color):  # BLACK or WHITE, aka 1 or 2
     occu = GoBoardUtil.generate_current_color(self.board, color)  # #
     legal = GoBoardUtil.generate_legal_moves_gomoku(self.board)
     i_win_list = []
     # print(current, color)
     check = self.four_in_5(current, occu)
     #print(check)
     upper = (self.board.size + 1)**2
     if check in [int(i) for i in legal]:
         # print("pass")
         if check not in i_win_list:
             i_win_list.append(check)
     # print(i_win_list)
     return i_win_list  #the list with points that fits
Exemple #28
0
    def firstsixteen(self, board, color):
        game_end, win = self.board.check_game_end_gomoku()
        checkpoint = "killer mode"
        if self.Win(color):
            checkpoint = "Win"
            moves = self.Win(color)

        elif self.BlockWin():
            checkpoint = "BlockWin"
            moves = self.BlockWin()

        elif self.OpenFour(color):
            checkpoint = "OpenFour"
            moves = self.OpenFour(color)

        elif self.BlockOpenFour(color):
            checkpoint = "BlockOpenFour"
            moves = self.BlockOpenFour(color)

        else:

            moves = GoBoardUtil.generate_legal_moves_gomoku(board)
            cur = GoBoardUtil.generate_current_color(board, color)
            if len(cur) == 0:  #first step to go
                move = 35
                #print(type(move))
                print(1)
                return int(move)
            seikiro = []  #a list for ranking of best points
            xianfengsi = []
            for i in moves:
                length, point = self.findlongestsequence(i, cur)
                if length != False:
                    seikiro.append([length, point])
            print(seikiro)
            for i in seikiro:
                if i[1] in moves:

                    xianfengsi.append(i)
            print(moves)

            geili = sorted(xianfengsi, key=lambda x: x[0], reverse=True)
            print(geili)

            return geili[0][1]  #return the best point

        return moves[0]  #return
Exemple #29
0
    def get_move(self, board, color):
        """
        Run one-player MC simulations to get a move to play
        """
        color = board.current_player
        cboard = board.copy()
        if self.random_simulation:
            moves = GoBoardUtil.generate_legal_moves_gomoku(board)
        else:
            _, moves = PatternUtil.generate_policy_moves(board)

        move_wins = []
        for move in moves:
            wins = self.simulate_move(cboard, move, color)
            move_wins.append(wins)

        return select_best_move(board, moves, move_wins)
Exemple #30
0
    def check_game_end_gomoku(self):
        """
            Check if the game ends for the game of Gomoku.
            """
        white_points = where1d(self.board == WHITE)
        black_points = where1d(self.board == BLACK)

        if len(GoBoardUtil.generate_legal_moves_gomoku(self)) == 0:
            return True, TIE

        for point in white_points:
            if self.point_check_game_end_gomoku(point):
                return True, WHITE

        for point in black_points:
            if self.point_check_game_end_gomoku(point):
                return True, BLACK

        return False, None