def chooseMove(self, board, prevMove): #REMEMBER TO CHECK IF FINDVALIDMOVES HAS BEEN CALLED BEFORE GETTING ''' board is a two-dimensional list representing the current board configuration. board is a copy of the original game board, so you can do to it as you wish. board[i][j] is 'W', 'B', 'G' when row i and column j contains a white piece, black piece, or no piece respectively. As usual i, j starts from 0, and board[0][0] is the top-left corner. prevMove gives the i, j coordinates of the last move made by your opponent. prevMove[0] and prevMove[1] are the i and j-coordinates respectively. prevMove may be None if your opponent has no move to make during his last turn. ''' memUsedMB = memory.getMemoryUsedMB() if memUsedMB > constants.MEMORY_LIMIT_MB - 100: #If I am close to memory limit #don't allocate memory, limit search depth, etc. #RandomPlayer uses very memory so it does nothing pass dirs = ((-1,-1), (-1,0), (-1,1), (0,-1), (0,1), (1,-1), (1,0), (1,1)) color = self.color if color == 'W': oppColor = 'B' elif color == 'B': oppColor = 'W' else: assert False, 'ERROR: Current player is not W or B!' self.numberOfPly +=1 colorValue = 1 if color == 'W' else -1 bitBoards = bu.convertToBitBoards(board) x=self.negamax(bitBoards,DEPTH,colorValue, -99999, 99999, None)[1] coordinates=None if x!=None: coordinates = divmod(x, constants.BRD_SIZE) print "Move: ", coordinates return coordinates
def run(self): data = self.player.getColor() assert data == 'W' or data == 'B', "ERROR: expecting color to be 'W' or 'B'" self.soc.send(data) while True: data = self.soc.recv(constants.BUF_SIZE) choice = int(data[0]) data = data[1:] outData = None if choice == 1: #chooseMove board = self.unpackBoard(data) a = constants.BRD_SIZE*constants.BRD_SIZE data = data[a:] cols = data.strip().split() prevMove = int(cols[0]), int(cols[1]) if prevMove[0] >= constants.BRD_SIZE or prevMove[1] >=constants.BRD_SIZE : prevMove = None move = self.player.chooseMove(board, prevMove) memMB = memory.getMemoryUsedMB() if move: outData = '%d %d %f' % (move[0], move[1], memMB) else: outData = '%d %d %f' % (constants.BRD_SIZE+1, constants.BRD_SIZE+1, memMB) #no move self.soc.send(outData) elif choice == 2: #gameEnd board = self.unpackBoard(data) self.player.gameEnd(board) outData = '0' #noop self.soc.send(outData) break else: assert False, 'ERROR: expect data[0] to be 0 or 1' self.soc.close()
def chooseMove(self, board, prevMove): ''' board is a two-dimensional list representing the current board configuration. board is a copy of the original game board, so you can do to it as you wish. board[i][j] is 'W', 'B', 'G' when row i and column j contains a white piece, black piece, or no piece respectively. As usual i, j starts from 0, and board[0][0] is the top-left corner. prevMove gives the i, j coordinates of the last move made by your opponent. prevMove[0] and prevMove[1] are the i and j-coordinates respectively. prevMove may be None if your opponent has no move to make during his last turn. ''' memUsedMB = memory.getMemoryUsedMB() if memUsedMB > constants.MEMORY_LIMIT_MB - 100: #If I am close to memory limit #don't allocate memory, limit search depth, etc. #RandomPlayer uses very memory so it does nothing pass dirs = ((-1,-1), (-1,0), (-1,1), (0,-1), (0,1), (1,-1), (1,0), (1,1)) color = self.color if color == 'W': oppColor = 'B' elif color == 'B': oppColor = 'W' else: assert False, 'ERROR: Current player is not W or B!' moves = [] for i in xrange(len(board)): for j in xrange(len(board[i])): if board[i][j] != 'G': continue #background is green, i.e., empty square for ddir in dirs: if self.validMove(board, (i,j), ddir, color, oppColor): moves.append((i,j)) break if len(moves) == 0: return None #no valid moves i = random.randint(0,len(moves)-1) #randomly pick a valid move return moves[i]
def chooseMove(self, board, prevMove): ''' board is a two-dimensional list representing the current board configuration. board is a copy of the original game board, so you can do to it as you wish. board[i][j] is 'W', 'B', 'G' when row i and column j contains a white piece, black piece, or no piece respectively. As usual i, j starts from 0, and board[0][0] is the top-left corner. prevMove gives the i, j coordinates of the last move made by your opponent. prevMove[0] and prevMove[1] are the i and j-coordinates respectively. prevMove may be None if your opponent has no move to make during his last turn. ''' memUsedMB = memory.getMemoryUsedMB() if memUsedMB > constants.MEMORY_LIMIT_MB - 100: #If I am close to memory limit #don't allocate memory, limit search depth, etc. #RandomPlayer uses very memory so it does nothing pass return self.pickBestMove(board)
def run(self): data = self.player.getColor() assert data == 'W' or data == 'B', "ERROR: expecting color to be 'W' or 'B'" self.soc.send(data) while True: data = self.soc.recv(constants.BUF_SIZE) choice = int(data[0]) data = data[1:] outData = None if choice == 1: #chooseMove board = self.unpackBoard(data) a = constants.BRD_SIZE * constants.BRD_SIZE data = data[a:] cols = data.strip().split() prevMove = int(cols[0]), int(cols[1]) if prevMove[0] >= constants.BRD_SIZE or prevMove[ 1] >= constants.BRD_SIZE: prevMove = None move = self.player.chooseMove(board, prevMove) memMB = memory.getMemoryUsedMB() if move: outData = '%d %d %f' % (move[0], move[1], memMB) else: outData = '%d %d %f' % ( constants.BRD_SIZE + 1, constants.BRD_SIZE + 1, memMB ) #no move self.soc.send(outData) elif choice == 2: #gameEnd board = self.unpackBoard(data) self.player.gameEnd(board) outData = '0' #noop self.soc.send(outData) break else: assert False, 'ERROR: expect data[0] to be 0 or 1' self.soc.close()
def chooseMove(self, board, prevMove): ''' board is a two-dimensional list representing the current board configuration. board is a copy of the original game board, so you can do to it as you wish. board[i][j] is 'W', 'B', 'G' when row i and column j contains a white piece, black piece, or no piece respectively. As usual i, j starts from 0, and board[0][0] is the top-left corner. prevMove gives the i, j coordinates of the last move made by your opponent. prevMove[0] and prevMove[1] are the i and j-coordinates respectively. prevMove may be None if your opponent has no move to make during his last turn. ''' memUsedMB = memory.getMemoryUsedMB() if memUsedMB > constants.MEMORY_LIMIT_MB - 100: #If I am close to memory limit #don't allocate memory, limit search depth, etc. #RandomPlayer uses very memory so it does nothing pass dirs = ((-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)) color = self.color if color == 'W': oppColor = 'B' elif color == 'B': oppColor = 'W' else: assert False, 'ERROR: Current player is not W or B!' moves = [] for i in xrange(len(board)): for j in xrange(len(board[i])): if board[i][j] != 'G': continue #background is green, i.e., empty square for ddir in dirs: if self.validMove(board, (i, j), ddir, color, oppColor): moves.append((i, j)) break if len(moves) == 0: return None #no valid moves i = random.randint(0, len(moves) - 1) #randomly pick a valid move return moves[i]
def chooseMove(self,board,prevMove): memUsedMB = memory.getMemoryUsedMB() if memUsedMB > constants.MEMORY_LIMIT_MB - 100: #If I am close to memory limit #don't allocate memory, limit search depth, etc. #RandomPlayer uses very memory so it does nothing pass dirs = ((-1,-1), (-1,0), (-1,1), (0,-1), (0,1), (1,-1), (1,0), (1,1)) color = self.color if color == 'W': oppColor = 'B' elif color == 'B': oppColor = 'W' else: assert False, 'ERROR: Current player is not W or B!' moves = [] for i in xrange(len(board)): for j in xrange(len(board[i])): if board[i][j] != 'G': continue #background is green, i.e., empty square for ddir in dirs: if self.validMove(board, (i,j), ddir, color, oppColor): moves.append((i,j)) break if len(moves) == 0: return None #no valid moves i = random.randint(0,len(moves)-1) #randomly pick a valid move return moves[i]
def chooseMove(self, board, prevMove): ''' board is a two-dimensional list representing the current board configuration. board is a copy of the original game board, so you can do to it as you wish. board[i][j] is 'W', 'B', 'G' when row i and column j contains a white piece, black piece, or no piece respectively. As usual i, j starts from 0, and board[0][0] is the top-left corner. prevMove gives the i, j coordinates of the last move made by your opponent. prevMove[0] and prevMove[1] are the i and j-coordinates respectively. prevMove may be None if your opponent has no move to make during his last turn. ''' # Check for the memory memUsedMB = memory.getMemoryUsedMB() if memUsedMB > constants.MEMORY_LIMIT_MB - 100: #If I am close to memory limit #don't allocate memory, limit search depth, etc. #RandomPlayer uses very memory so it does nothing print "Over memory limit, please alter!" # dirs = ((-1,-1), (-1,0), (-1,1), (0,-1), (0,1), (1,-1), (1,0), (1,1)) # same as the dirs in constants.py # color = self.myColor # if color == 'W': oppColor = 'B' # elif color == 'B': oppColor = 'W' # else: assert False, 'ERROR: Current player is not W or B!' # This is from random player # find all valid moves # to have a random element in our movement making randomSwitch = random.randint(0,1) # opening move database # parallel, diagonal and perpendicular openings # if white, parallel is the best. If black, avoid parallel boardParallel = [['G', 'G', 'G', 'G', 'G', 'G', 'G', 'G'], ['G', 'G', 'G', 'G', 'G', 'G', 'G', 'G'], ['G', 'G', 'G', 'B', 'W', 'G', 'G', 'G'], ['G', 'G', 'G', 'B', 'W', 'G', 'G', 'G'], ['G', 'G', 'G', 'B', 'W', 'G', 'G', 'G'], ['G', 'G', 'G', 'G', 'G', 'G' , 'G', 'G'], ['G', 'G', 'G', 'G', 'G', 'G', 'G', 'G'], ['G', 'G', 'G', 'G', 'G', 'G', 'G', 'G']] boardDiagonal1 = [['G', 'G', 'G', 'G', 'G', 'G', 'G', 'G'], ['G', 'G', 'G', 'G', 'G', 'G', 'G', 'G'], ['G', 'G', 'G', 'G', 'W', 'G', 'G', 'G'], ['G', 'G', 'G', 'W', 'W', 'G', 'G', 'G'], ['G', 'G', 'G', 'B', 'W', 'G', 'G', 'G'], ['G', 'G', 'G', 'G', 'G', 'G' , 'G', 'G'], ['G', 'G', 'G', 'G', 'G', 'G', 'G', 'G'], ['G', 'G', 'G', 'G', 'G', 'G', 'G', 'G']] boardDiagonal2 = [['G', 'G', 'G', 'G', 'G', 'G', 'G', 'G'], ['G', 'G', 'G', 'G', 'G', 'G', 'G', 'G'], ['G', 'G', 'G', 'G', 'G', 'G', 'G', 'G'], ['G', 'G', 'G', 'W', 'W', 'W', 'G', 'G'], ['G', 'G', 'G', 'B', 'W', 'G', 'G', 'G'], ['G', 'G', 'G', 'G', 'G', 'G' , 'G', 'G'], ['G', 'G', 'G', 'G', 'G', 'G', 'G', 'G'], ['G', 'G', 'G', 'G', 'G', 'G', 'G', 'G']] boardDiagonal3 = [['G', 'G', 'G', 'G', 'G', 'G', 'G', 'G'], ['G', 'G', 'G', 'G', 'G', 'G', 'G', 'G'], ['G', 'G', 'G', 'G', 'G', 'G', 'G', 'G'], ['G', 'G', 'G', 'W', 'B', 'G', 'G', 'G'], ['G', 'G', 'G', 'W', 'W', 'G', 'G', 'G'], ['G', 'G', 'G', 'W', 'G', 'G' , 'G', 'G'], ['G', 'G', 'G', 'G', 'G', 'G', 'G', 'G'], ['G', 'G', 'G', 'G', 'G', 'G', 'G', 'G']] boardDiagonal4 = [['G', 'G', 'G', 'G', 'G', 'G', 'G', 'G'], ['G', 'G', 'G', 'G', 'G', 'G', 'G', 'G'], ['G', 'G', 'G', 'G', 'G', 'G', 'G', 'G'], ['G', 'G', 'G', 'W', 'B', 'G', 'G', 'G'], ['G', 'G', 'W', 'W', 'W', 'G', 'G', 'G'], ['G', 'G', 'G', 'G', 'G', 'G' , 'G', 'G'], ['G', 'G', 'G', 'G', 'G', 'G', 'G', 'G'], ['G', 'G', 'G', 'G', 'G', 'G', 'G', 'G']] if self.moveCount == 0 and self.myColor == "W": self.moveCount += 1 return (2,4) if board == boardParallel and self.myColor == "W": return (3,2) if board == boardDiagonal1 and self.myColor == "B": return (2,5) if board == boardDiagonal2 and self.myColor == "B": return (2,5) if board == boardDiagonal3 and self.myColor == "B": return (5,2) if board == boardDiagonal4 and self.myColor == "B": return (5,2) # selection of moves moves = [] for i in xrange(len(board)): for j in xrange(len(board[i])): if board[i][j] != 'G': continue #background is green, i.e., empty square for ddir in constants.DIRECTIONS: if self.validMove(board, (i,j), ddir, self.myColor, self.oppoColor): moves.append((i,j)) break if len(moves) == 0: return None #no valid moves # Use minimax to get best move bestMove = moves[0] bestValue = self.bestValue # reverse the moves for a random ordering of the variables. if randomSwitch == 1: moves = moves[::-1] # print "reversed!" emptySpaces = self.count_empty(board) if emptySpaces < 12: print "Changing depth of search" self.depth = 11 for move in moves: # you are a max player value = self.max_value(board, move, self.depth, self.alpha, self.beta) print " M, V:", move, value if value > bestValue: bestValue = value bestMove = move print bestMove self.moveCount += 1 return bestMove
def chooseMove(self, board, prevMove): ''' board is a two-dimensional list representing the current board configuration. board is a copy of the original game board, so you can do to it as you wish. board[i][j] is 'W', 'B', 'G' when row i and column j contains a white piece, black piece, or no piece respectively. As usual i, j starts from 0, and board[0][0] is the top-left corner. prevMove gives the i, j coordinates of the last move made by your opponent. prevMove[0] and prevMove[1] are the i and j-coordinates respectively. prevMove may be None if your opponent has no move to make during his last turn. ''' # Check for the memory memUsedMB = memory.getMemoryUsedMB() if memUsedMB > constants.MEMORY_LIMIT_MB - 100: #If I am close to memory limit #don't allocate memory, limit search depth, etc. #RandomPlayer uses very memory so it does nothing print "Over memory limit, please alter!" # Get the current state of the board count_empty = self.count_empty(board) # dirs = ((-1,-1), (-1,0), (-1,1), (0,-1), (0,1), (1,-1), (1,0), (1,1)) # same as the dirs in constants.py # color = self.myColor # if color == 'W': oppColor = 'B' # elif color == 'B': oppColor = 'W' # else: assert False, 'ERROR: Current player is not W or B!' # This is from random player # find all valid moves state = 0 #state 0 = opening, state 1 = after opening, #parallel, diagonal and perpendicular openings # if white, parallel is the best. If black, avoid parallel opening_moves = {} moves = [] for i in xrange(len(board)): for j in xrange(len(board[i])): if board[i][j] != 'G': continue #background is green, i.e., empty square for ddir in constants.DIRECTIONS: if self.validMove(board, (i,j), ddir, self.myColor, self.oppoColor): moves.append((i,j)) break if len(moves) == 0: return None #no valid moves # Use minimax to get best move bestMove = moves[0] bestValue = self.bestValue for move in moves: # you are a max player # additional part for late game. if count_empty <= 12: value = self.max_value(board, move, 12, self.alpha, self.beta) else: value = self.max_value(board, move, self.depth, self.alpha, self.beta) print " M, V:", move, value if value > bestValue: bestValue = value bestMove = move print bestMove moveCount += 1 return bestMove
def chooseMove(self, board, prevMove): functionStartTime = time.time() ''' board is a two-dimensional list representing the current board configuration. board is a copy of the original game board, so you can do to it as you wish. board[i][j] is 'W', 'B', 'G' when row i and column j contains a white piece, black piece, or no piece respectively. As usual i, j starts from 0, and board[0][0] is the top-left corner. prevMove gives the i, j coordinates of the last move made by your opponent. prevMove[0] and prevMove[1] are the i and j-coordinates respectively. prevMove may be None if your opponent has no move to make during his last turn. ''' player, opponent = makeBitBoard(board, self.color) numEmptiesLeft = getNumEmptiesLeft(player, opponent) # Check if the engine unconventionally asks white to play first. # If yes, we flip horizontally for the game. if self.whiteStartFirst == -1: if numEmptiesLeft == 60: self.whiteStartFirst = self.color == 'W' elif numEmptiesLeft == 59: self.whiteStartFirst = self.color == 'B' if self.whiteStartFirst: print "White Starts First!" else: print "Black Starts First!" if self.whiteStartFirst: player = horizontalMirrorDiscsSingle(player) opponent = horizontalMirrorDiscsSingle(opponent) moveMade = False useOpeningBook = True validMoves = getMoves(player, opponent) score = "N.A." if validMoves: if useOpeningBook: # If opening book is to be used combined = (player << 128) | opponent unique, symmetryIndex = getUniqueBoard( combined) # Not rly a perf issue... only ~ 30x per game if unique in openingBook: move = getSymmetricMoveSingleInverse( random.choice(openingBook[unique]), symmetryIndex) moveMade = True print "Opening book used!" if not moveMade: searchDepth = getSuggestedDepthForCompetition( self.schedule["midGameTimeLeft"], self.schedule["gameTimeLeft"], self.schedule["endGameNumEmpties"], self.schedule["minSearchDepth"], player, opponent, self.schedule["previousDepthCounters"], self.schedule["previousSearchTime"]) isEndGame = searchDepth > 60 if isEndGame: print "Endgame Search, # Empties:", numEmptiesLeft else: print "Search Depth:", searchDepth # init schedule analysis stuff depthCounters = None if isEndGame else getNewDepthCounters( searchDepth) searchTimeStart = time.time() # do search searchResults = reversiABNegaScout(player, opponent, searchDepth, depthCounters) # record schedule analysis stuff searchTime = time.time() - searchTimeStart self.schedule["previousDepthCounters"] = depthCounters self.schedule["previousSearchTime"] = searchTime # assign search results move, score = searchResults moveMade = True else: return None # No valid move, better return None if self.printBoard: try: rev = [m[1] for m in validMoves if m[0] == move][0] printPlayer, printOpponent = getPut(player, opponent, move, rev) if self.whiteStartFirst: printPlayer = horizontalMirrorDiscsSingle(printPlayer) printOpponent = horizontalMirrorDiscsSingle(printOpponent) printBitBoard(printPlayer, printOpponent, self.color) except: pass # Print stats... ramUsage = "" try: ramUsage = " RAM: %2.1fMB" % memory.getMemoryUsedMB() except: pass printLines = ("Move: " + bitToLetterCoors[move] + " Score: " + str(score), "Time Left: %ds" % (self.schedule["gameTimeLeft"] - (time.time() - functionStartTime)) + ramUsage) print "\n".join(printLines) print "=" * max(len(l) for l in printLines) + "\n" # Flip back move if needed... if self.whiteStartFirst: move = bitToIndex2D[horizontalMirrorDiscsSingle(move)] else: move = bitToIndex2D[move] functionTime = time.time() - functionStartTime self.schedule["midGameTimeLeft"] -= functionTime self.schedule["gameTimeLeft"] -= functionTime return move