def __init__(self, initialgamestate, aistonetype, plydepth, tilesearchrange, analyzerparameter): BaseAI.__init__(self, initialgamestate, aistonetype) self.EnemyStoneType = "black" if self.AIStoneType == "white" else "white" self.PlyDepth = plydepth self.OpenSearchRange = tilesearchrange self.analyzerparameter = analyzerparameter
def checkforwork(self): while True: data = self.InputQueue.get() if data[0] == "START": board = data[1] self.aiutils = BaseAI(board, self.AIStoneType) hashtable_size = [] #print("*" * 10) self.Zobrist_Hash_Table = [] for depth in range(1, self.PlyDepth + 1): self.TerminalNodes = 0 startnode = Node(None, None, None, -10000000, 10000000) self.alphabeta(self.aiutils.duplicateboard(board), startnode, depth, True, self.OpenSearchRange, self.CurrentDepth) self.CurrentDepth += 1 #print("DEPTH", depth, "HASH SIZE:", len(self.Zobrist_Hash_Table)) hashtable_size.append(len(self.Zobrist_Hash_Table)) best = max(startnode.children, key=lambda x: x.value) #print("RESULT:", best.position, best.value, "ITERATIONS:", self.Iterations, "TERMINAL_NODES:", self.TerminalNodes) self.OutputQueue.put( ((best.value, best.position), hashtable_size)) elif data == "EXIT": break
def __init__(self, initialgamestate, aistonetype, timelimit, remote=True): BaseAI.__init__(self, initialgamestate, aistonetype) self.EnemyStoneType = "black" if self.AIStoneType == "white" else "white" self.This2ActuatorQ = multiprocessing.Queue() self.Actuator2ThisQ = multiprocessing.Queue() self.TimeLimit = timelimit self.ReportHook = lambda x: None self.Process = None self.datalist = [] self.PID = None self.Remote = remote
def CheckForWork(self, board): self.aiutils = BaseAI(board, self.AIStoneType) startnode = Node(None, None, None) self.AlphaBeta(self.aiutils.duplicateboard(board), startnode, self.PlyDepth, True, -10000000, 10000000, self.OpenSearchRange) result = [] for items in startnode.children: result.append((items.value, items.position)) result = sorted(result, key=lambda x: x[0], reverse=True) try: return result[0] except: print("Damn an error has occured") print("result:", result) print("startnode.children:", startnode.children) print("getopenmoves of default board:", self.aiutils.getopenmoves())
def __init__(self, initialgamestate, aistonetype, plydepth, tilesearchrange, use_xta, xta_coefficient, remote=True): BaseAI.__init__(self, initialgamestate, aistonetype) self.EnemyStoneType = "black" if self.AIStoneType == "white" else "white" self.PlyDepth = plydepth self.This2ActuatorQ = multiprocessing.Queue() self.Actuator2ThisQ = multiprocessing.Queue() self.OpenSearchRange = tilesearchrange self.ReportHook = lambda x: None self.Process = None self.datalist = [] self.PID = None self.Use_XTA = True if use_xta else False self.XTA_Coefficient = xta_coefficient self.Remote = remote
def runmcts(self, startnode): starttime = time.time() node = startnode iters = 0 while True: if time.time() - starttime > self.TimeLimit: break else: boardg = BaseAI(node.GameState, self.AIStoneType) newb = boardg.duplicateboard(node.GameState) while True: if node.Children: node = node.getbestchild() else: break if boardg.getlimitedopenmoves(node.GameState): m = random.choice( boardg.getlimitedopenmoves(node.GameState)) newb.addstone(m, newb.Turn) g = Node(m, newb, parent=node) newb = boardg.duplicateboard(newb) node = g result = 0 while True: if boardg.getlimitedopenmoves(newb): newb.addstone( random.choice( boardg.getlimitedopenmoves(newb)), newb.Turn) check = WinChecker(newb) if check.check(self.AIStoneType): result = 1 break elif check.check(self.EnemyStoneType): result = -1 break else: break else: break node.update(result) iters += 1 print("iters", iters) return 0
def AlphaBeta(self, board, node, depth, isMaximizingPlayer, alpha, beta, tilesearchrange): #print("CURRENT POSITION",move,isMaximizingPlayer) if WinChecker(board).checkboth() or depth == 0 or BaseAI( board, self.AIStoneType).getopenmoves() == 0: ganalyst = Analyzer(board, self.analyzer[0], self.analyzer[1], self.analyzer[2], self.analyzer[3]) return ganalyst.grader(self.AIStoneType) - ganalyst.grader( self.EnemyStoneType) if isMaximizingPlayer: v = -10000000 for moves in self.aiutils.getlimitedopenmoves( board, self.OpenSearchRange): g = Node(moves, None, node) dupedboard = self.aiutils.duplicateboard(board) dupedboard.addstone(moves, self.AIStoneType) v = max( v, self.AlphaBeta(dupedboard, g, depth - 1, False, alpha, beta, tilesearchrange)) g.value = v alpha = max(alpha, v) if beta <= alpha: #print("BETA CUTOFF") break return v else: v = 10000000 for moves in self.aiutils.getlimitedopenmoves( board, self.OpenSearchRange): g = Node(moves, None, node) dupedboard = self.aiutils.duplicateboard(board) dupedboard.addstone(moves, self.AIStoneType) v = min( v, self.AlphaBeta(dupedboard, g, depth - 1, True, alpha, beta, tilesearchrange)) g.value = v beta = min(beta, v) if beta <= alpha: #print("ALPHA CUTOFF") break return v
class AlphaBetaActuator(): def __init__(self, aistonetype, depth, tilesearchrange, analyzerparameter): self.AIStoneType = aistonetype self.EnemyStoneType = "black" if self.AIStoneType == "white" else "white" self.PlyDepth = depth self.OpenSearchRange = tilesearchrange self.analyzer = analyzerparameter def CheckForWork(self, board): self.aiutils = BaseAI(board, self.AIStoneType) startnode = Node(None, None, None) self.AlphaBeta(self.aiutils.duplicateboard(board), startnode, self.PlyDepth, True, -10000000, 10000000, self.OpenSearchRange) result = [] for items in startnode.children: result.append((items.value, items.position)) result = sorted(result, key=lambda x: x[0], reverse=True) try: return result[0] except: print("Damn an error has occured") print("result:", result) print("startnode.children:", startnode.children) print("getopenmoves of default board:", self.aiutils.getopenmoves()) def AlphaBeta(self, board, node, depth, isMaximizingPlayer, alpha, beta, tilesearchrange): #print("CURRENT POSITION",move,isMaximizingPlayer) if WinChecker(board).checkboth() or depth == 0 or BaseAI( board, self.AIStoneType).getopenmoves() == 0: ganalyst = Analyzer(board, self.analyzer[0], self.analyzer[1], self.analyzer[2], self.analyzer[3]) return ganalyst.grader(self.AIStoneType) - ganalyst.grader( self.EnemyStoneType) if isMaximizingPlayer: v = -10000000 for moves in self.aiutils.getlimitedopenmoves( board, self.OpenSearchRange): g = Node(moves, None, node) dupedboard = self.aiutils.duplicateboard(board) dupedboard.addstone(moves, self.AIStoneType) v = max( v, self.AlphaBeta(dupedboard, g, depth - 1, False, alpha, beta, tilesearchrange)) g.value = v alpha = max(alpha, v) if beta <= alpha: #print("BETA CUTOFF") break return v else: v = 10000000 for moves in self.aiutils.getlimitedopenmoves( board, self.OpenSearchRange): g = Node(moves, None, node) dupedboard = self.aiutils.duplicateboard(board) dupedboard.addstone(moves, self.AIStoneType) v = min( v, self.AlphaBeta(dupedboard, g, depth - 1, True, alpha, beta, tilesearchrange)) g.value = v beta = min(beta, v) if beta <= alpha: #print("ALPHA CUTOFF") break return v
class AlphaBetaActuator: def __init__(self, inputqueue, outputqueue, aistonetype, depth, tilesearchrange, use_xta, xta_coefficient): self.AIStoneType = aistonetype self.EnemyStoneType = "black" if self.AIStoneType == "white" else "white" self.InputQueue = inputqueue self.OutputQueue = outputqueue self.PlyDepth = depth self.OpenSearchRange = tilesearchrange self.aiutils = None self.Matrix = generate_random_matrix( 25 ) # Select default Zobrist matrix size as 25, change if necessary self.Zobrist_Hash_Table = [ ] # Moved the below 2 lines of code up to __init__ to avoid PEP warnings self.CurrentDepth = 1 self.Iterations = 0 self.TerminalNodes = 0 self.Use_XTA = True if use_xta else False self.XTA_Coefficient = xta_coefficient self.checkforwork() def checkforwork(self): while True: data = self.InputQueue.get() if data[0] == "START": board = data[1] self.aiutils = BaseAI(board, self.AIStoneType) hashtable_size = [] #print("*" * 10) self.Zobrist_Hash_Table = [] for depth in range(1, self.PlyDepth + 1): self.TerminalNodes = 0 startnode = Node(None, None, None, -10000000, 10000000) self.alphabeta(self.aiutils.duplicateboard(board), startnode, depth, True, self.OpenSearchRange, self.CurrentDepth) self.CurrentDepth += 1 #print("DEPTH", depth, "HASH SIZE:", len(self.Zobrist_Hash_Table)) hashtable_size.append(len(self.Zobrist_Hash_Table)) best = max(startnode.children, key=lambda x: x.value) #print("RESULT:", best.position, best.value, "ITERATIONS:", self.Iterations, "TERMINAL_NODES:", self.TerminalNodes) self.OutputQueue.put( ((best.value, best.position), hashtable_size)) elif data == "EXIT": break def alphabeta(self, board, node, depth, ismaximizingplayer, tilesearchrange, originaldepth): self.Iterations += 1 # Hash table is disabled for now until I'm sure it helps with performance """hashval = board.generatehash(self.Matrix) for hash in self.Zobrist_Hash_Table: if hash[0] == hashval: if hash[2] < originaldepth - 1: self.Zobrist_Hash_Table.remove(hash) else: return hash[1]""" # print("CURRENT POSITION",move,isMaximizingPlayer) if WinChecker(board).checkboth() or depth == 0: """hashval = board.generatehash(self.Matrix) for hash in self.Zobrist_Hash_Table: if hash[0] == hashval: if hash[2] < originaldepth-1: self.Zobrist_Hash_Table.remove(hash) else: return hash[1]""" ganalyst = Analyzer(board) aiscore = ganalyst.grader(self.AIStoneType) enemyscore = ganalyst.grader(self.EnemyStoneType) if self.Use_XTA: coefficient = ExtensiveAnalysis(board).grader(self.AIStoneType) # Hash table is disabled for now until I'm sure it helps with performance # self.Zobrist_Hash_Table.append((hashval, aiscore - enemyscore - (self.XTA_Coefficient*coefficient), originaldepth)) return aiscore - enemyscore - (self.XTA_Coefficient * coefficient) else: # Hash table is disabled for now until I'm sure it helps with performance #self.Zobrist_Hash_Table.append((hashval, aiscore - enemyscore, originaldepth)) return aiscore - enemyscore if ismaximizingplayer: v = -10000000 for move in self.aiutils.getlimitedopenmoves( board, self.OpenSearchRange): g = Node(move, None, node, node.alpha, node.beta) if depth == 1: self.TerminalNodes += 1 dupedboard = self.aiutils.duplicateboard(board) dupedboard.addstone(move, self.AIStoneType) v = max( v, self.alphabeta(dupedboard, g, depth - 1, False, tilesearchrange, originaldepth)) g.value = v node.alpha = max(node.alpha, v) if node.beta <= node.alpha: break return v else: v = 10000000 for move in self.aiutils.getlimitedopenmoves( board, self.OpenSearchRange): g = Node(move, None, node, node.alpha, node.beta) if depth == 1: self.TerminalNodes += 1 dupedboard = self.aiutils.duplicateboard(board) dupedboard.addstone(move, self.EnemyStoneType) v = min( v, self.alphabeta(dupedboard, g, depth - 1, True, tilesearchrange, originaldepth)) g.value = v node.beta = min(node.beta, v) if node.beta <= node.alpha: break return v