Esempio n. 1
0
 def __init__(self, player_no: int, max_depth: int):
     super(MinMaxAgent, self).__init__(player_no)
     self.max_depth = max_depth
     self.zb = ZobristHash(player_no)
     self.squares = [[1], [3], [5], [7], [8], [10], [12], [14], [17], [19],
                     [21], [23], [24], [26], [28], [30], [33], [35], [37],
                     [39], [40], [42], [44], [46], [49], [51], [53], [55],
                     [56], [58], [60], [62]]
Esempio n. 2
0
 def __init__(self, name, color):
     # print "In ChessAI __init__"
     self.name = name
     self.color = color
     self.type = 'AI'
     self.table = ZobristHash(size=2**24)
Esempio n. 3
0
class ChessAI:
    def __init__(self, name, color):
        # print "In ChessAI __init__"
        self.name = name
        self.color = color
        self.type = 'AI'
        self.table = ZobristHash(size=2**24)

    def GetName(self):
        return self.name

    def GetColor(self):
        return self.color

    def GetType(self):
        return self.type

    def GetMove(self, currentNode, depth):
        actions = currentNode.Actions("black", self.table)
        bestMoveTuple = None

        bestMoveUtility = self.AlphaBetaSearch(currentNode=currentNode, depth=depth, actions=actions)

        #get the best move tuple
        for i in actions:
            if i.utility == bestMoveUtility:
                bestMoveTuple = i.GetMoveTuple()
                break
        return bestMoveTuple

    def AlphaBetaSearch(self, alpha=-10000, beta=10000, currentNode=None, maxPlayer=True, depth=0, actions=None):
        #use hashtable
        cachedValue = self.table.lookup(currentNode.board)
        if cachedValue != None:
            currentNode.SetUtility(cachedValue) #utility
            return cachedValue

        #terminal test1
        if depth == 0:
            Heuristic.ShannonHeuristic(currentNode, self.table)
            return currentNode.utility

        if actions == None:
            if maxPlayer:
                actions = currentNode.Actions("black", self.table)
            else:
                actions = currentNode.Actions("white", self.table)

        #terminal test2
        if len(actions) == 0:
            Heuristic.ShannonHeuristic(currentNode, self.table)
            return currentNode.utility

        # Max
        if maxPlayer:
            v = -10000
            for node in actions:
                v = max(v, self.AlphaBetaSearch( alpha, beta, node, False, depth-1 ) )
                if v >= beta:
                    return v
                alpha = max(alpha, v)
            self.table.insertUtility(currentNode.board, v)
            currentNode.SetUtility(v)
            return v

        # Min
        else:
            v = 10000
            for node in actions:
                v = min(v, self.AlphaBetaSearch( alpha, beta, node, True, depth-1 ) )
                if v <= alpha:
                    return v
                beta = max( beta, v)
            self.table.insertUtility(currentNode.board, v)
            currentNode.SetUtility(v)
            return v
Esempio n. 4
0
class MinMaxAgent(Agent):
    def __init__(self, player_no: int, max_depth: int):
        super(MinMaxAgent, self).__init__(player_no)
        self.max_depth = max_depth
        self.zb = ZobristHash(player_no)
        self.squares = [[1], [3], [5], [7], [8], [10], [12], [14], [17], [19],
                        [21], [23], [24], [26], [28], [30], [33], [35], [37],
                        [39], [40], [42], [44], [46], [49], [51], [53], [55],
                        [56], [58], [60], [62]]

    def play(self, moves: list, board: list):
        self.z_hash = {}
        _, move_index = self._minmax_ab(self.max_depth, -math.inf, math.inf,
                                        bool(self.player_no), board,
                                        self.player_no)
        return moves[move_index]

    def _minmax_ab(self, depth, alpha, beta, max_player, board, player_no):

        if player_no:
            steps = [-7, -9]
            player_num = 1
        else:
            steps = [9, 7]
            player_num = -1

        moves = Board.get_valid_moves(board, self.squares, steps, player_num,
                                      False, False)[::-1]

        length = len(moves)
        if depth == 0 or length == 0:
            return self._get_board_hash_score(board, player_no), 0

        if max_player:
            max_eval = -math.inf
            for i in range(length):
                next_board = [i for i in board]
                next_board = Board.play_move(next_board, moves[i], player_no)
                hash = self.zb.calculate_hash(next_board, player_no)
                if hash in self.z_hash:
                    eval = self.z_hash[hash]
                else:
                    eval, _ = self._minmax_ab(depth - 1, alpha, beta, False,
                                              next_board, 1 - player_no)
                if eval > max_eval:
                    max_index = i
                    max_eval = eval
                alpha = max(eval, alpha)
                if beta <= alpha:
                    break
            return max_eval, (length - 1) - max_index

        else:
            min_eval = math.inf
            for i in range(length):
                next_board = [i for i in board]
                next_board = Board.play_move(next_board, moves[i], player_no)
                hash = self.zb.calculate_hash(next_board, player_no)
                if hash in self.z_hash:
                    eval = self.z_hash[hash]
                else:
                    eval, _ = self._minmax_ab(depth - 1, alpha, beta, True,
                                              next_board, 1 - player_no)
                if eval < min_eval:
                    min_eval = eval
                    min_index = i
                min_eval = min(min_eval, eval)
                beta = min(eval, beta)
                if beta <= alpha:
                    break
            return min_eval, (length - 1) - min_index

    def _get_board_hash_score(self, board, player_no):
        hash = self.zb.calculate_hash(board, player_no)
        if hash not in self.z_hash:
            score = self._heuristicFunction(board)
            self.z_hash[hash] = score
        else:
            score = self.z_hash[hash]
        return score

    def _heuristicFunction(self, board: list) -> int:
        counter = collections.Counter(board)
        if -1 not in counter and -2 not in counter:
            return 72
        elif 1 not in counter and 2 not in counter:
            return -72

        return sum(board)