示例#1
0
    def action(self, turns):
        self.minimax.update_board(self.board)
        # if action is called first the board representation move counter will be zero
        # this indicates that this player is the first one to move

        # if update is called before action the board representation counter will be 1,
        # this indicates that the player is the second to move

        if turns == 0 and self.board.phase == constant.MOVING_PHASE:
            self.board.move_counter = 0
            self.board.phase = constant.MOVING_PHASE

        # create the node to search on
        root = self.minimax.create_node(self.colour, None)
        # update the board representation and the available moves
        self.minimax.update_minimax_board(None, root, start_node=True)
        # print(self.minimax.available_actions)
        best_move = self.minimax.alpha_beta_minimax(3, root)

        # do an alpha beta search on this node
        # once we have found the best move we must apply it to the board representation
        if self.board.phase == constant.PLACEMENT_PHASE:
            # print(best_move)
            self.board.update_board(best_move, self.colour)
            self.minimax.update_board(self.board)
            return best_move
        else:
            # (best_move is None)
            # print(best_move[0],best_move[1])
            new_pos = Board.convert_move_type_to_coord(best_move[0],
                                                       best_move[1])
            self.board.update_board(best_move, self.colour)
            self.minimax.update_board(self.board)
            return best_move[0], new_pos
    def action(self, turns):

        if turns == 0 and self.board.phase == constant.PLACEMENT_PHASE:
            self.board.set_player_to_move(self.colour)

        if turns == 24 and self.board.phase == constant.PLACEMENT_PHASE:
            self.board.move_counter = 0
            self.board.phase = constant.MOVING_PHASE

        root = self.minimax.create_node(self.colour, None)
        self.minimax.update_minimax_board(None, root)
        # self.minimax.update_available_actions(None)
        # best_move = self.minimax.alpha_beta_minimax(2,root)
        # best_move = self.minimax.iterative_deepening_alpha_beta(root)
        best_move = self.minimax.alpha_beta_minimax(3, root)

        # do an alpha beta search on this node
        if self.board.phase == constant.PLACEMENT_PHASE:
            # print(best_move)
            self.board.update_board(best_move, self.colour)
            self.minimax.update_board(self.board)
            return best_move
        else:
            # (best_move is None)
            # print(best_move[0],best_move[1])
            new_pos = Board.convert_move_type_to_coord(best_move[0],
                                                       best_move[1])
            self.board.update_board(best_move, self.colour)
            self.minimax.update_board(self.board)
            return best_move[0], new_pos
示例#3
0
    def update_surrounding_pieces(self, center_pos):
        for move_type in range(constant.MAX_MOVETYPE):
            potential_piece = Board.convert_move_type_to_coord(
                center_pos, move_type)

            # check if the potential piece is a piece
            if potential_piece in self.available_actions[constant.WHITE_PIECE]:
                # then it is a piece on the board
                # update this piece
                self.update_actions_dict_entry(potential_piece,
                                               constant.WHITE_PIECE)
            elif potential_piece in self.available_actions[
                    constant.BLACK_PIECE]:
                self.update_actions_dict_entry(potential_piece,
                                               constant.BLACK_PIECE)
示例#4
0
    def action(self, turns):
        self.strategy.num_nodes = 0
        self.strategy.update_board(self.board)

        if turns == 0 and self.board.phase == constant.MOVING_PHASE:
            self.board.move_counter = 0
            self.board.phase = constant.MOVING_PHASE

        best_move = self.strategy.MCTS()
        # print("NUM NODE IN THIS TREE: " + str(self.strategy.num_nodes))

        # once we have found the best move we must apply it to the board representation
        if self.board.phase == constant.PLACEMENT_PHASE:
            self.board.update_board(best_move, self.colour)
            return best_move
        else:

            new_pos = Board.convert_move_type_to_coord(best_move[0],
                                                       best_move[1])
            self.board.update_board(best_move, self.colour)
            return best_move[0], new_pos
示例#5
0
    def action(self, turns):
        self.minimax.update_board(self.board)
        # print(self.board.piece_pos)
        # if action is called first the board representation move counter will be zero
        # this indicates that this player is the first one to move

        # if update is called before action the board representation counter will be 1,
        # this indicates that the player is the second to move

        if turns == 0 and self.board.phase == constant.MOVING_PHASE:
            self.board.move_counter = 0
            self.board.phase = constant.MOVING_PHASE

        # create the node to search on
        # update the board representation and the available moves
        # print(self.minimax.available_actions)
        # best_move = self.minimax.alpha_beta_minimax(3)
        best_move = self.minimax.itr_negamax()
        # best_move = self.minimax.alpha_beta(3)
        self.depth_eval = self.minimax.eval_depth
        self.minimax_val = self.minimax.minimax_val

        # do an alpha beta search on this node
        # once we have found the best move we must apply it to the board representation
        if self.board.phase == constant.PLACEMENT_PHASE:
            # print(best_move)
            self.board.update_board(best_move, self.colour)
            self.minimax.update_board(self.board)
            return best_move
        else:
            if best_move is None:
                return None
            # (best_move is None)
            # print(best_move[0],best_move[1])
            new_pos = Board.convert_move_type_to_coord(best_move[0], best_move[1])
            self.board.update_board(best_move, self.colour)
            self.minimax.update_board(self.board)
            return best_move[0], new_pos
示例#6
0
    def update_available_moves(self, action, colour):

        # if there were any eliminated pieces last move retrieve them from the stack -- but make sure not to pop them
        # off the stack completely
        eliminated_pieces = self.board.eliminated_pieces_last_move(
            self.board.phase, self.board.move_counter, pop=False)

        # action is in the form (position, movetype)
        #       -- i,e. we are moving the piece at position by the movetype
        #       -- when an action is called we have move that piece already and we need to change
        #       -- the entries in the dictionary according to that move
        # colour is the colour of the piece we have moved
        # read in the pieces on the board -- if they already exist in the dictionary
        # then we dont need to do anything -- if they don't exist in the dictionary
        # need to look at all the eliminated pieces on the board
        #   -- look for pieces in the vicinity of that space
        #   -- delete keys associated with those eliminated pieces as these are pieces on the board
        #   -- that do not exists anymore, therefore there are no associated moves with this piece
        #   -- update the available moves of the pieces that can move into that square
        # need to update the available moves of the piece at its new location
        # delete entry in the dictionary that corresponds to the old position
        old_pos = action[0]
        #print(old_pos)
        #print(action)
        new_pos = Board.convert_move_type_to_coord(old_pos, action[1])

        # first we need to update the dictionary by removing the old piece from the
        # dictionary -- as this is not an available move anymore
        if old_pos in self.available_actions[colour]:
            #print("old")
            self.available_actions[colour].pop(old_pos)
        else:
            pass
            # need to raise an error saying

        # then add an entry into the dictionary corresponding to the new location of the piece
        # after the move has been applied
        if new_pos not in self.available_actions[colour]:
            self.update_actions_dict_entry(new_pos, colour)
        else:
            pass
            # need to raise an error

        # remove all eliminated pieces from the dictionary
        for piece_type in (constant.WHITE_PIECE, constant.BLACK_PIECE):
            for piece in eliminated_pieces[piece_type]:
                if piece in self.available_actions[piece_type]:
                    self.available_actions[piece_type].pop(piece)
                else:
                    pass
                    # need to raise an error

        # update any piece that is surrounding the old position but also any eliminated pieces and update
        # their available moves by adding the corresponding move type to that list
        # this old position is now a free space on the board and therefore pieces are able to now move into it
        # need to test all positions surround this newly freed space and update their available actions
        for move_type in range(constant.MAX_MOVETYPE):
            # iterate through all the possible moves at the old location, checking
            # whether or not there is a piece there
            # if there is a piece at that location we can update that piece's available moves
            piece = Board.convert_move_type_to_coord(old_pos, move_type)
            for piece_colour in (constant.WHITE_PIECE, constant.BLACK_PIECE):
                if piece in self.available_actions[piece_colour]:
                    if move_type < 4:
                        self.update_actions_dict_entry(piece, piece_colour)
                    else:
                        if self.board.can_jump_into_position(
                                old_pos, move_type):
                            self.update_actions_dict_entry(piece, piece_colour)

            # update the pieces around any eliminated pieces
            for piece_colour in (constant.WHITE_PIECE, constant.BLACK_PIECE):
                # iterate through all the eliminated pieces on the board
                for elim_piece in eliminated_pieces[piece_colour]:
                    # for each eliminated piece we apply a move (move_type to it), checking if there is a piece
                    # at this position on the board, we do this by checking the available moves dictionary
                    # if there is a piece associated with that position on the board then if it is a one step move
                    # we just need to update that pieces available moves, if it is a jump, then we need to test if there
                    # is an adjacent piece between the jump and the free space -- do this by calling
                    # can_jump_into_position -- for a given space, if we apply a move_type corresponding to a
                    # two piece move, can we jump into this free spot
                    # if we can then we just need to update this pieces available actions

                    piece = Board.convert_move_type_to_coord(
                        elim_piece, move_type)
                    '''
                    # if this piece corresponds to an entry in the dictionary, then there is a piece at this location
                    if piece in self.available_actions[piece_colour]:
                        # one step moves
                        if move_type < 4:
                            self.update_actions_dict_entry(piece,piece_colour)
                        else:
                            # need to check if a jump is available into the free space
                            # if the piece at the jump location is in the available_action dict
                            if self.board.can_jump_into_position(elim_piece,move_type):
                                self.update_actions_dict_entry(piece,piece_colour)
                    '''
                    self.update_surrounding_pieces(piece)
            # update the available moves of the pieces that surround where the
            # new position of the piece is -- this is no longer an occupied space therefore pieces surrounding
            # it cannot move into this space anymore
            piece = Board.convert_move_type_to_coord(new_pos, move_type)
            for piece_colour in (constant.WHITE_PIECE, constant.BLACK_PIECE):
                if piece in self.available_actions[piece_colour]:
                    '''
                    if move_type < 4:
                        self.update_actions_dict_entry(piece,piece_colour)
                    else:
                        # treat this old position as a free space -- if there are pieces
                        # that can jump into this piece we have to update these pieces available
                        # actions because this space is no longer free
                        if self.board.can_jump_into_position(new_pos,move_type):
                            self.update_actions_dict_entry(piece,piece_colour)
                    '''
                    self.update_surrounding_pieces(piece)
示例#7
0
class Player:
    def __init__(self, colour):
        if colour == 'white':
            self.colour = constant.WHITE_PIECE
        elif colour == 'black':
            self.colour = constant.BLACK_PIECE

        self.available_moves = []

        # each players internal board representation
        self.board = Board()

        # initialise the available moves
        self.init_start_moves()

        self.opponent = self.board.get_opp_piece_type(self.colour)

        # print(self.opponent)

    # set up the board for the first time
    def init_start_moves(self):
        # set the initial board parameters
        # no pieces on the board
        # available moves is the entire starting zone for each player

        if self.colour == constant.WHITE_PIECE:
            # set the white pieces available moves
            for row in range(0, constant.BOARD_SIZE - 2):
                for col in range(constant.BOARD_SIZE):
                    if (row, col) not in self.board.corner_pos:
                        self.available_moves.append((col, row))
        else:
            # set the black piece available moves
            for row in range(2, constant.BOARD_SIZE):
                for col in range(constant.BOARD_SIZE):
                    if (row, col) not in self.board.corner_pos:
                        # append the available move in the list in the form col, row
                        self.available_moves.append((col, row))

    def update(self, action):
        # print("UPDATING THIS ACTION : " + str(action))
        if self.board.move_counter == 0:
            # then the opponent is the first person to move
            self.board.set_player_to_move(self.opponent)

        # update the board based on the action of the opponent
        # get move type
        if self.board.phase == constant.PLACEMENT_PHASE:

            # update board also returns the pieces of the board that will be eliminated
            self.board.update_board(action, self.opponent)
            eliminated_pieces = self.board.eliminated_pieces[self.opponent]
            # remove the eliminated pieces from the available moves of this player
            for piece in eliminated_pieces:
                if piece in self.available_moves and Player.within_starting_area(
                        piece, self.colour):
                    # self.available_moves.remove(piece)
                    self.available_moves.append(piece)
            # remove the opponent piece from the available moves list
            if action in self.available_moves:
                self.available_moves.remove(action)

            # print(self.available_moves)
        elif self.board.phase == constant.MOVING_PHASE:
            if isinstance(action[0], tuple) is False:
                # print("WHYYYYYYYY")
                return

            move_type = self.board.convert_coord_to_move_type(
                action[0], action[1])
            # print("MOVETYPE: " + str(move_type))
            # print(action[0])
            self.board.update_board((action[0], move_type), self.opponent)

    def action(self, turns):
        # print("TURNS SO FAR ---------- " + str(turns))
        # print("ACTION CALLED: BOARD REPRESENTATION COUNTER: " + str(self.board.move_counter))
        if turns == 0 and self.board.phase == constant.PLACEMENT_PHASE:
            # then we are first person to move
            self.board.set_player_to_move(self.colour)

        if turns < 24 and self.board.phase == constant.PLACEMENT_PHASE:

            # then we pick the best move to make based on a search algorithm
            search_algorithm = Random(len(self.available_moves))
            next_move = self.available_moves[search_algorithm.choose_move()]

            # making moves during the placement phase
            self.board.update_board(next_move, self.colour)
            eliminated_pieces = self.board.eliminated_pieces[self.colour]
            # remove the move made from the available moves
            self.available_moves.remove(next_move)
            if len(eliminated_pieces) != 0:
                for piece in eliminated_pieces:
                    if piece in self.available_moves:
                        self.available_moves.remove(piece)
            return next_move

        elif self.board.phase == constant.MOVING_PHASE:
            if turns == 0 or turns == 1:
                # if the turns is 0 or 1 and the board is in moving phase then the
                # all players have placed their pieces on the board, we can call update_available_moves to update the
                # available moves available to this player
                # clear the list
                self.available_moves = []
                # update the lists available moves -- now in the form ((col,row),move_type)
                # self.update_available_moves()
                # print(self.available_moves)
            # we are making a move in the moving phase
            #print(self.available_moves)

            self.update_available_moves()
            # if there are no available moves to be made we can return None:
            if len(self.available_moves) == 0:
                return None
            # print("AVAILABLE MOVES: " + str(self.colour) + " " + str(self.available_moves))
            # if there is a move to be made we can return the best move

            # TODO : THIS IS WHERE WE CARRY OUT OUR SEARCH ALGORITHM
            # then we pick the best move to make based on a search algorithm
            search_algorithm = Random(len(self.available_moves))
            next_move = self.available_moves[search_algorithm.choose_move()]

            self.board.update_board(next_move, self.colour)

            new_pos = self.board.convert_move_type_to_coord(
                next_move[0], next_move[1])
            # print(self.colour + "  " + str(self.board.piece_pos))

            # TODO - need to double check if this update_available_moves is necessary
            self.update_available_moves()

            #print(getsizeof(self.board.piece_pos))
            #print(getsizeof(self.board.board_state))
            #print(getsizeof(self.available_moves))
            return next_move[0], new_pos

    # updates the available moves a piece can make after it has been moved
    # this way we don;t need to calculate all the available moves on the board
    # as pieces that have been eliminated also get rid of those associated available moves
    def update_available_moves(self):
        # clear the available moves
        available_moves = []
        self.available_moves = []

        # recalculate the moves a piece can make based on the available pieces on the board
        # print(self.colour)
        # print("-"*20)
        # self.board.print_board()
        # print("-"*20)
        # print("THIS PLAYERS CURRENT PIECES: " + str(self.colour) + str(self.board.piece_pos[self.colour]))
        for piece in self.board.piece_pos[self.colour]:
            for move_type in range(constant.MAX_MOVETYPE):
                if self.board.is_legal_move(piece, move_type):
                    available_moves.append((piece, move_type))

        self.available_moves = available_moves

    @staticmethod
    def within_starting_area(move, colour):
        if colour == constant.WHITE_PIECE:
            # update the starting rows based off the player colour
            if colour == constant.WHITE_PIECE:
                min_row = 0
                max_row = 6
            elif colour == constant.BLACK_PIECE:
                min_row = 2
                max_row = 8
            col, row = move

            if min_row <= row <= max_row:
                return True
            else:
                return False