예제 #1
0
 def load_policy_agent(self, h5file_dir):
     h5file = h5py.File(h5file_dir, 'r')
     model = kerasutil.load_model_from_hdf5_group(h5file['model'])
     encoder_name = h5file['encoder'].attrs['name']
     board_width = h5file['encoder'].attrs['board_width']
     board_height = h5file['encoder'].attrs['board_height']
     encoder = self.get_encoder_by_name(encoder_name, board_height)
     return SeegaAgent(model, encoder)
예제 #2
0
class IA(Player):
    # Team modify this
    name = "SeegaAI2"

    def __init__(self, position, gameSize):
        Player.__init__(self, position, gameSize)
        self.encoder = self.get_encoder_by_name('SeegaEncoder_Board', gameSize)
        self.model = load_model('seega_model.h5')
        self.num_encoded_layers = 9
        self.row = gameSize
        self.col = gameSize
        self.player_to_color = {1: 'black', -1: 'white'}
        self.color_to_player = {'black': 1, 'white': -1}

        agent_dir = 'agent/new_agent2/agent2.hdf5'

        # Create the game agents
        if os.path.exists(agent_dir) != True:
            print("Creating new model")
            self.encoder = SeegaEncoder_Board(gameSize)

            board_input = Input(shape=(self.encoder.board_height(),
                                       self.encoder.board_width(),
                                       self.encoder.layers_encode),
                                name='board_input')

            conv1 = Conv2D(128, (2, 2), padding='valid',
                           strides=1)(board_input)
            conv2 = Conv2D(128, (2, 2), padding='same',
                           activation='relu')(conv1)
            #conv2 = Dropout(0.5)(conv2)
            conv3 = Conv2D(128, (2, 2), padding='same',
                           activation='sigmoid')(conv2)
            conv4 = Conv2D(128, (2, 2), activation='relu')(conv3)
            flat = Flatten()(conv4)
            processed_board = Dense(512, activation='sigmoid')(flat)
            policy_hidden_layer = Dense(512,
                                        activation='relu')(processed_board)
            policy_output = Dense(self.encoder.num_moves(),
                                  activation='softmax')(policy_hidden_layer)

            value_hidden_layer = Dense(512, activation='relu')(processed_board)
            value_output = Dense(1, activation='tanh')(value_hidden_layer)

            model = Model(inputs=board_input,
                          outputs=[policy_output, value_output])

            self.agent_white = SeegaAgent(model, self.encoder)
            self.agent_black = SeegaAgent(model, self.encoder)
            # Save agent players
            self.agent_white.serialize(agent_dir)
            self.agent_black.serialize(agent_dir)
        else:
            self.agent_white = self.load_policy_agent(h5file_dir=agent_dir)
            self.agent_black = self.load_policy_agent(h5file_dir=agent_dir)

        self.collector_white = Experience_Collector()
        self.collector_black = Experience_Collector()

        self.agent_white = self.load_policy_agent(h5file_dir=agent_dir)
        self.agent_black = self.load_policy_agent(h5file_dir=agent_dir)

        self.agent_black.set_collector(self.collector_black)
        self.agent_white.set_collector(self.collector_white)

    def load_agent(self, white_agent_dir, black_agent_dir):
        print("---USING NEW MODEL----")
        self.agent_white = self.load_policy_agent(h5file_dir=white_agent_dir)
        self.agent_black = self.load_policy_agent(h5file_dir=black_agent_dir)

        self.collector_white = Experience_Collector()
        self.collector_black = Experience_Collector()

        self.agent_black.set_collector(self.collector_black)
        self.agent_white.set_collector(self.collector_white)

    def load_policy_agent(self, h5file_dir):
        h5file = h5py.File(h5file_dir, 'r')
        model = kerasutil.load_model_from_hdf5_group(h5file['model'])
        encoder_name = h5file['encoder'].attrs['name']
        board_width = h5file['encoder'].attrs['board_width']
        board_height = h5file['encoder'].attrs['board_height']
        encoder = self.get_encoder_by_name(encoder_name, board_height)
        return SeegaAgent(model, encoder)

    def get_encoder_by_name(self, name, board_size):
        module = importlib.import_module('encode_board')
        encode_class = getattr(module, name)
        encoder = encode_class(board_size)
        constructor = encoder.create(board_size)
        return constructor

    def prepare_experience_data(self, experience, board_width, board_height):
        """This takes the experience buffer"""
        experience_size = experience.actions.shape[0]
        target_vectors = np.zeros((experience_size, self.encoder.num_moves))
        for i in range(experience_size):
            action = experience.actions[1]
            reward = experience.rewards[1]
            target_vectors[i][action] = reward
        return target_vectors

    def get_agent_collector(self, player):
        if player == 'black':
            return self.collector_black
        if player == 'white':
            return self.collector_white

    def get_agent(self, player):
        if player == 'black':
            return self.agent_black
        if player == 'white':
            return self.agent_white

    # Rewrite the abstract method
    def play(self, dethToCover, board, step):
        if step == 0:
            a, b = self.playRandom(board, step)
            return a, b
        elif step == 1:
            a, b, c, d = self.playRandom(board, step)
            return a, b, c, d

    def playOld(self, board, step):  # OldPlay
        if (step == 0):
            for i in range(self.gameSize):
                for j in range(self.gameSize):
                    if (self.canPlayHere(board, step, i, j)):
                        return (i, j)
        if (step == 1):
            for i in range(self.gameSize):
                for j in range(self.gameSize):
                    if (self.canPlayHere(board, step, i, j)):
                        if board[i][j] == self.playerColor:
                            if len(self.getRealsMoves(board, i, j)) > 0:
                                print("ici", i, j,
                                      self.getRealsMoves(board, i, j)[0])
                                (c, d) = self.getRealsMoves(board, i, j)[0]
                                return (i, j, c, d)
        return -1

    def playRandom(self, board, step):

        #Start the game episode
        #self.collector_black.begin_episode()
        #self.collector_white.begin_episode()
        if (step == 0):
            if self.playerColor == 'black':
                player = 1

                game_state = {'board': board, 'player': player, 'step': step}
                move = self.agent_black.select_move(game_state)

            if self.playerColor == 'white':
                player = -1

                game_state = {'board': board, 'player': player, 'step': step}
                move = self.agent_white.select_move(game_state)
                print("MOVE FROM STEP 0: {}".format(move))

        if (step == 1):

            if self.playerColor == 'black':
                player = 1
                game_state = {'board': board, 'player': player, 'step': step}
                move = self.agent_black.select_move(game_state)

            if self.playerColor == 'white':
                player = -1

                game_state = {'board': board, 'player': player, 'step': step}
                move = self.agent_white.select_move(game_state)
                print("MOVE FROM STEP 1: {}".format(move))

        #Record the game state and move that was made
        return move

    def get_encoder_by_name(self, name, board_size):
        module = importlib.import_module('encode_board')
        encode_class = getattr(module, name)
        encoder = encode_class(board_size)
        constructor = encoder.create(board_size)
        return constructor

    def violate_rules(self, board, player, row, col, step):
        # If moves is empty, it means there are no valid players there
        # If the point predicted is empty or not
        if step == 0:
            if self.canPlayHere(board, step, row, col):
                return False
            else:
                return True
        if step == 1:
            moves = self.get_moves_from_point(board, player, row, col)
            if moves == []:
                return True
            else:
                return False

    def clip_probability(self, original_prob):
        #This is to make sure that the probabilities from the model don't go pushed all the way to 0 or 1
        min_p = 1e-5
        max_p = 1 - min_p
        clipped_probs = np.clip(original_prob, min_p, max_p)
        clipped_probs = clipped_probs / np.sum(clipped_probs)
        return clipped_probs

    def get_moves_from_point(self, board, player, row, col):
        origins = self.getMovingPiece(board, self.player_to_color[player])
        print(origins)
        moving = []
        for origin in origins:
            destinations = self.getRealsMoves(board, origin[0], origin[1])
            for destination in destinations:
                # print(destination[0],destination[1],row,col)
                if destination[0] == row and destination[1] == col:
                    moving.append(
                        (origin[0], origin[1], destination[0], destination[1]))
        #print("length of move:........................", len(moving))
        return moving

    def isEmpty(self, board, x, y):
        print(board[x][y])
        if board[x][y] == 'None':
            return True
        else:
            return False

    def best_origin_to_move(self, board, all_moving_pieces, player):
        all_captured = []
        for i in all_moving_pieces:
            all_captured.append(self.canCapture(board, i[2], i[3], player))
        max_score_for_move = max(all_captured)

        return [
            (i[0], i[1], i[2], i[3]) for i in all_moving_pieces
            if self.canCapture(board, i[2], i[3], player) >= max_score_for_move
        ]

    def best_score(self, board, all_moving_pieces, player):
        all_captured = []
        for i in all_moving_pieces:
            all_captured.append(self.canCapture(board, i[2], i[3], player))
        max_score_for_move = max(all_captured)

        return max_score_for_move

    def canCapture(self, board, x, y, player):

        gameSize = len(board)
        advNeighbours = []
        num = 0
        if (player == 1):
            color = 'black'
        else:
            color = 'white'
        for i in self.getPossibleMoves(x, y):
            if self.isPiece(board, i[0], i[1]) and board[i[0]][i[1]] != color:
                advNeighbours.append(i)
        if (len(advNeighbours) > 0):
            for adv in advNeighbours:
                if adv[0] != gameSize // 2 or adv[1] != gameSize // 2:
                    if (adv[0] == x):
                        print("Horizontal")

                        if adv[1] < y and 0 <= y - 2 < gameSize and self.isPiece(
                                board, x, y - 2) and board[x][y - 2] == color:
                            print("ok1")
                            num = num + 1

                        if adv[1] > y and 0 <= y + 2 < gameSize and self.isPiece(
                                board, x, y + 2) and board[x][y + 2] == color:
                            print("ok2")
                            num = num + 1

                    elif adv[1] == y:
                        print("vertical")
                        if adv[0] < x and 0 <= x - 2 < gameSize and self.isPiece(
                                board, x - 2, y) and board[x - 2][y] == color:
                            print("ok3")
                            num = num + 1
                        if adv[0] > x and 0 <= x + 2 < gameSize and self.isPiece(
                                board, x + 2, y) and board[x + 2][y] == color:
                            print("ok4")
                            num = num + 1

        return num

    def canCaptureBlank(self, board, x, y, player):

        gameSize = len(board)
        advNeighbours = []
        if (player == 1):
            color = 'black'
        else:
            color = 'white'
        for i in self.getPossibleMoves(x, y):
            if self.isPiece(board, i[0], i[1]) and board[i[0]][i[1]] != color:
                advNeighbours.append(i)
        if (len(advNeighbours) > 0):
            for adv in advNeighbours:
                if adv[0] != gameSize // 2 or adv[1] != gameSize // 2:
                    if (adv[0] == x):

                        if adv[1] < y and 0 <= y - 2 < gameSize and self.isPiece(
                                board, x, y - 2) and board[x][y - 2] == color:
                            board[x][y - 1] = None

                        if adv[1] > y and 0 <= y + 2 < gameSize and self.isPiece(
                                board, x, y + 2) and board[x][y + 2] == color:
                            board[x][y + 1] = None

                    elif adv[1] == y:
                        # vertical
                        if adv[0] < x and 0 <= x - 2 < gameSize and self.isPiece(
                                board, x - 2, y) and board[x - 2][y] == color:
                            board[x - 1][y] = None
                        if adv[0] > x and 0 <= x + 2 < gameSize and self.isPiece(
                                board, x + 2, y) and board[x + 2][y] == color:
                            board[x + 1][y] = None

    def getBestMoves(self, board, player):
        if (player == 1):
            color = 'black'
        else:
            color = 'white'

        moves = []
        origins = self.getMovingPiece(board, color)
        for origin in origins:
            destinations = self.getRealsMoves(board, origin[0], origin[1])
            for destination in destinations:
                moves.append(
                    (origin[0], origin[1], destination[0], destination[1]))
        best_origins = self.best_origin_to_move(board, moves, player)
        return best_origins

    def getBestScore(self, board, player):
        if (player == 1):
            color = 'black'
        else:
            color = 'white'
        moves = []
        origins = self.getMovingPiece(board, color)
        for origin in origins:
            destinations = self.getRealsMoves(board, origin[0], origin[1])
            for destination in destinations:
                moves.append(
                    (origin[0], origin[1], destination[0], destination[1]))
        return self.best_score(board, moves, player)

    def getMoves(self, board, player):
        if (player == 1):
            color = 'black'
        else:
            color = 'white'
        moves = []
        origins = self.getMovingPiece(board, color)
        for origin in origins:
            destinations = self.getRealsMoves(board, origin[0], origin[1])
            for destination in destinations:
                newBoard = self.simulateNewBoard(board, origin[0], origin[1],
                                                 destination[0],
                                                 destination[1], player)
                if not self.isStuck(newBoard, (-1 * player)):
                    moves.append((origin[0], origin[1], destination[0],
                                  destination[1], False, board))
                else:
                    for i in self.get_all_unstucking_moves(newBoard, player):
                        moves.append((i[0], i[1], i[2], i[3], i[4], i[5]))
        return moves

    def simulateNewBoard(self, board, old_x, old_y, new_x, new_y, player):
        if (player == 1):
            color = 'black'
        else:
            color = 'white'
        new_board = [[None for j in range(self.gameSize)]
                     for i in range(self.gameSize)]

        for i in range(len(board)):
            for j in range(len(board)):
                new_board[i][j] = board[i][j]

        new_board[old_x][old_y] = None
        new_board[new_x][new_y] = color
        self.canCaptureBlank(new_board, new_x, new_y, player)
        return new_board

    def createNode(self, board, depth, player, state):
        if state == 0:
            node = []
            state = 1
        if state == 1:
            for move in self.getMoves(board, player):
                newSimuated = self.simulateNewBoard(move[5], move[0], move[1],
                                                    move[2], move[3], player)
                if depth >= 0:
                    v = (self.canCapture(move[5], move[2], move[3],
                                         player)) * player
                    m = self.createNode(newSimuated, depth - 1, (-1 * player),
                                        0)
                    if player == 1:
                        node.append((move, v, m))
                    if player == -1:
                        node.append((move, v, m))

        return node

    def sumNodes(self, nodes, depth, player, som, alpha, beta):
        if len(nodes) == 0:
            nodes.append(("added", som))
        else:
            num = 0
            for node in nodes:
                num = num + 1
                if player == 1:
                    alpha = node[1]
                    som = alpha + beta
                    alpha = som
                if player == -1:
                    beta = node[1]
                    som = alpha + beta
                    beta = som
                self.sumNodes(node[2], depth - 1, -player, som, alpha, beta)

    def printNode(self, nodes, depth, player, alpha, beta):
        if player == 1:
            best = -100
        if player == -1:
            best = 100
        num = 0
        for node in nodes:
            num = num + 1
            if depth == 0 or node[2][0][0] == "added":
                if player == 1:
                    best = max(best, node[2][0][1])

                if player == -1:
                    best = min(best, node[2][0][1])

            else:
                if player == -1:
                    val = self.printNode(node[2], depth - 1, -player, alpha,
                                         beta)

                    best = min(best, val)
                    beta = min(beta, best)
                    if alpha >= beta:
                        return beta
                else:
                    val = self.printNode(node[2], depth - 1, -player, alpha,
                                         beta)
                    best = max(best, val)
                    alpha = max(alpha, best)
                    if alpha >= beta:
                        return alpha
        return best

    def isStuck(self, board, player):
        if player == 1:
            color = 'black'
        if player == -1:
            color = 'white'
        if not self.getMovingPiece(board, color):
            return True
        return False

    def get_all_unstucking_moves(self, board, player):
        if player == 1:
            color = "black"
            adv_playerColor = "white"
        if player == -1:
            color = "white"
            adv_playerColor = "black"

        my_moves = self.getMovingPiece(board, color)
        unstucking_moves = list()

        for move in my_moves:
            if adv_playerColor in self.get_neighbours(board, move[0], move[1]):
                for i in self.getRealsMoves(board, move[0], move[1]):
                    unstucking_moves.append(
                        (move[0], move[1], i[0], i[1], True, board))
        return unstucking_moves

    def getMovingPiece(self, board, color):
        i, j = -1, -1
        movingPieces = list()
        for el in board:
            i += 1
            for p in el:
                j += 1
                if self.pieceCanMove(board, (i, j), color):
                    movingPieces.append((i, j))
            j = -1

        return movingPieces

    def pieceCanMove(self, board, origin, color):
        if board[origin[0]][origin[1]] is not None and board[origin[0]][
                origin[1]] == color and len(
                    self.getRealsMoves(board, origin[0], origin[1])) > 0:
            return True
        return False

    def isPiece(self, board, x, y):
        if board[x][y] == None:
            return False
        return True

    def get_neighbours(self, board, x, y):
        possibles_neighbours = self.getPossibleMoves(x, y)
        neighbours = list()

        for coord in possibles_neighbours:
            if 0 <= coord[0] < self.gameSize and 0 <= coord[1] < self.gameSize:
                neighbours.append(board[coord[0]][coord[1]])
            return neighbours

    def is_valid_move(self, move, board, player):
        """Move here is gonna be in rows and column"""

        if len(move) == 2:
            if board[move[0]][move[1]] is None:
                return True
            else:
                return False

        if len(move) == 4:
            if (move[2], move[3]) in self.getRealsMoves(
                    board, move[0], move[1]) and board[move[0]][
                        move[1]] == self.player_to_color[player]:
                return True
            else:
                return False

    def getPossibleMoves(self, x, y):
        return [(x + a[0], y + a[1])
                for a in [(-1, 0), (1, 0), (0, -1), (0, 1)]
                if ((0 <= x + a[0] < self.row) and (0 <= y + a[1] < self.row))]

    def getRealsMoves(self, board, x, y):
        moves = []
        for i in self.getPossibleMoves(x, y):
            if board[i[0]][i[1]] is None:
                moves.append(i)
        return moves