def minimax(board, color, time, alpha, beta, depth, maximizingPlayer, movesRemaining): moves = getAllPossibleMoves(board, color) if depth == 0 or not moves: return evaluation(board, color), [] if maximizingPlayer == True: best = float("-inf") for move in moves: newBoard = deepcopy(board) gamePlay.doMove(newBoard, move) alpha, x = minimax(newBoard, gamePlay.getOpponentColor(color), time, best, beta, depth - 1, False, movesRemaining) if best == float("-inf") or alpha > best: bestMove = move best = alpha if best >= beta: break return best, bestMove else: best = float("inf") for move in moves: newBoard = deepcopy(board) gamePlay.doMove(newBoard, move) beta, x = minimax(newBoard, gamePlay.getOpponentColor(color), time, alpha, best, depth - 1, True, movesRemaining) if best == float("inf") or beta < best: bestMove = move best = beta if alpha >= best: break return best, bestMove
def minimax(board, color, time, alpha, beta, depth, maximizingPlayer, movesRemaining): moves = getAllPossibleMoves(board, color) if depth == 0 or not moves: return evaluation(board, color), [] if maximizingPlayer == True: best = float("-inf") for move in moves: newBoard = deepcopy(board) gamePlay.doMove(newBoard,move) alpha, x = minimax(newBoard, gamePlay.getOpponentColor(color), time, best, beta, depth-1, False, movesRemaining) if best == float("-inf") or alpha > best: bestMove = move best = alpha if best >= beta: break return best, bestMove else: best = float("inf") for move in moves: newBoard = deepcopy(board) gamePlay.doMove(newBoard,move) beta, x = minimax(newBoard, gamePlay.getOpponentColor(color), time, alpha, best, depth-1, True, movesRemaining) if best == float("inf") or beta < best: bestMove = move best = beta if alpha >= best: break return best, bestMove
def safePawns(board, color): opponentColor = gamePlay.getOpponentColor(color) #get count of pawns on four edges for each player safePawnsOfPlayer = board[0].count(color) + board[7].count(color) + getColumn(board, 0).count(color) + getColumn(board, 7).count(color) safePawnsOfOpponent = board[0].count(opponentColor) + board[7].count(opponentColor) + getColumn(board, 0).count(opponentColor) + getColumn(board, 7).count(opponentColor) scoreMap['safePawns'] = safePawnsOfPlayer-safePawnsOfOpponent
def safeKings(board, color): opponentColor = gamePlay.getOpponentColor(color) #get count of kings on four edges for each player safeKingsOfPlayer = board[0].count(color.upper()) + board[7].count(color.upper()) + getColumn(board, 0).count(color.upper()) + getColumn(board, 7).count(color.upper()) safeKingsOfOpponent = board[0].count(opponentColor.upper()) + board[7].count(opponentColor.upper()) + getColumn(board, 0).count(opponentColor.upper()) + getColumn(board, 7).count(opponentColor.upper()) scoreMap['safeKings'] = safeKingsOfPlayer - safeKingsOfOpponent
def activeDefenseForKings(board, color): opponentColor = gamePlay.getOpponentColor(color) val1 = 0 val2 = 0 forwardRight = (1, -1) forwardLeft = (1, 1) backwardRight = (-1, -1) backwardLeft = (-1, 1) postNeighbors = list() postNeighbors = [backwardRight, backwardLeft] for i in range(1,33): xy = gamePlay.serialToGrid(i) x = xy[0] y = xy[1] if board[x][y] == color: #for post neighbors of kings, see if there are same colored pawns to rate defensiveness for item in postNeighbors: coord = tuple(sum(x) for x in zip(xy, item)) prev_xy = gridToSerial(coord[0], coord[1]) if prev_xy in range (1, 33): new_coord = gamePlay.serialToGrid(prev_xy) newx = new_coord[0] newy = new_coord[1] if board[newx][newy] == color: val1 += 1 elif board[x][y] == opponentColor.upper(): val2 += 1 return val1*val2
def evaluation7(board, color): opponentColor = gamePlay.getOpponentColor(color) list1 = [6, 7, 8, 9, 10, 11, 14, 15, 16, 17, 18, 19, 22, 23, 24, 25, 26, 27] value = 0 # Loop through all board positions for piece in list1: xy = gamePlay.serialToGrid(piece) x = xy[0] y = xy[1] if board[x][y].upper() == color.upper(): if board[x-1][y-1].upper() == color.upper(): value = value + 1 elif board[x-1][y+1].upper() == color.upper(): value = value + 1 elif board[x+1][y-1].upper() == color.upper(): value = value + 1 elif board[x+1][y+1].upper() == color.upper(): value = value + 1 elif board[x][y].upper() == opponentColor.upper(): if board[x-1][y-1].upper() == opponentColor.upper(): value = value - 1 elif board[x-1][y+1].upper() == opponentColor.upper(): value = value - 1 elif board[x+1][y-1].upper() == opponentColor.upper(): value = value - 1 elif board[x+1][y+1].upper() == opponentColor.upper(): value = value - 1 # Let us give weightage 10 #return value * 10 return value
def evaluation5(board, color): opponentColor = gamePlay.getOpponentColor(color) # 0th element is for top row from top; 7th element is the bottom row in the board list = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16], [17, 18, 19, 20], [21, 22, 23, 24], [25, 26, 27, 28], [29, 30, 31, 32]] value = 0 # Loop through all board positions for i in range(0, 8): for j in range(0, 4): piece = list[i][j] xy = gamePlay.serialToGrid(piece) x = xy[0] y = xy[1] if board[x][y].upper() == color.upper(): if color.upper() == 'R': # When R pieces reach bottom base line get score 7 value = value + i elif color.upper() == 'W': # When W pieces reach top base line get score 7 value = value + (7-i) elif board[x][y].upper() == opponentColor.upper(): if opponentColor.upper() == 'R': # When opponent's R pieces reach bottom base line get score -7 value = value - i elif opponentColor.upper() == 'W': # When opponent's W pieces reach top base line get score -7 value = value - (7-i) # Lets give weightage 2 #return value * 2 return value
def offense(board, color): opposideEnd = None; opponentColor = gamePlay.getOpponentColor(color) distanceMeasure = 0.0 count1 = 0 count2 = 0 if color == 'r': for i in range(1, 33): xy = gamePlay.serialToGrid(i) x = xy[0] y = xy[1] if board[x][y] == color: count1 += x elif board[x][y] == opponentColor: count2 += (7-x) elif color == 'w': for i in range(1,33): xy = gamePlay.serialToGrid(i) x = xy[0] y = xy[1] if board[x][y] == color: count1 += (7-x) elif board[x][y] == opponentColor: count2 += x scoreMap['offense'] = count1 - count2
def nextMove(board, color, time, movesRemaining): global myColor global opponentColor myColor = color opponentColor = gamePlay.getOpponentColor(color) #Trying to find the move where I have best score return iterativeDeepeningAlphaBetaPruning(board, time, movesRemaining)
def isFirstMove(board, color): opponentColor = gamePlay.getOpponentColor(color) value1 = 0 value2 = 0 # Loop through the middle two rows for piece in range(13, 21): xy = gamePlay.serialToGrid(piece) x = xy[0] y = xy[1] if board[x][y].upper() == color.upper(): value1 = value1 + 1 elif board[x][y].upper() == opponentColor.upper(): value1 = value1 + 1 # Loop through all the rows for piece in range(1, 33): xy = gamePlay.serialToGrid(piece) x = xy[0] y = xy[1] if board[x][y].upper() == color.upper(): value2 = value2 + 1 elif board[x][y].upper() == opponentColor.upper(): value2 = value2 + 1 # If it is first move middle two rows have one or less piece if value2 == 24 and value1 <= 1: return True else: return False
def evaluation(board, color): global myColor color = myColor global moveCount opponentColor = gamePlay.getOpponentColor(color) value = 0 global fourth_layer # Loop through all board positions for piece in range(1, 33): xy = gamePlay.serialToGrid(piece) x = xy[0] y = xy[1] # Eval on opponent pieces <= 7 or for first 10 moves(Be in attacking mode) if board[x][y].upper() == color.upper() and ( countPieces(board, opponentColor) <= 7 or moveCount <= 10): value = value + 1 continue elif board[x][y].upper() == opponentColor.upper() and ( countPieces(board, opponentColor) <= 7 or moveCount <= 10): value = value - 1 continue # Eval on pieces in fourth layer(pieces will tend to move towards 4th outer most layer ie defensive positions) if board[x][y].upper() == color.upper() and piece in fourth_layer: value = value + 4 continue elif board[x][y].upper() == opponentColor.upper( ) and piece in fourth_layer: value = value - 4 continue # Eval on pieces in third layer (pieces will tend to move towards 3rd layer on board) if board[x][y].upper() == color.upper() and piece in third_layer: value = value + 3 continue elif board[x][y].upper() == opponentColor.upper( ) and piece in third_layer: value = value - 3 continue # Eval on pieces in second layer (pieces will tend to move towards 2nd layer on board if board[x][y].upper() == color.upper() and piece in second_layer: value = value + 2 continue elif board[x][y].upper() == opponentColor.upper( ) and piece in second_layer: value = value - 2 continue # Eval on pieces in first layer (pieces will tend to move to center two pieces) if board[x][y].upper() == color.upper() and piece in first_layer: value = value + 1 continue elif board[x][y].upper() == opponentColor.upper( ) and piece in first_layer: value = value - 1 continue return value
def evaluation3(board, color): # Evaluation Function 3(matrix): Corners on all sides are given utmost importance # and hence my pawns will always tend to go towards the corner so that the pawns cannot be captured. evalMatrix = [ [ 0, 4, 0, 4, 0, 4, 0, 4], [ 4, 0, 3, 0, 3, 0, 3, 0], [ 0, 3, 0, 2, 0, 2, 0, 4], [ 4, 0, 2, 0, 1, 0, 3, 0], [ 0, 3, 0, 1, 0, 2, 0, 4], [ 4, 0, 2, 0, 2, 0, 3, 0], [ 0, 3, 0, 3, 0, 3, 0, 4], [ 4, 0, 4, 0, 4, 0, 4, 0] ] opponentColor = gamePlay.getOpponentColor(color) value = 0 for piece in range(1, 33): xy = gamePlay.serialToGrid(piece) x = xy[0] y = xy[1] if board[x][y].upper() == color.upper(): value = value + evalMatrix[x][y] elif board[x][y].upper() == opponentColor.upper(): value = value - evalMatrix[x][y] return value
def alphabetaPruning(board,color,alpha,beta, depth, maxval,movesRemaining): if depth == 0 or movesRemaining == 0: # Checking whether I am in the end node, then I will return my evaluation value return evaluation(board, maxColor) moves = getAllPossibleMoves(board,color) # Getting all values of the new board that I passed from nextMove opponentColor = gamePlay.getOpponentColor(color) # Getting the opponent color test = float("inf") # Assigning value for infinity if maxval: #Checking whether maxval is Max value = -test #Assigning the value of -infnity to value for move in moves: # looping through all the moves evalBoard = deepcopy(board) #Taking the deepcopy of board gamePlay.doMove(evalBoard,move) #value = evaluation(evalBoard, color) #print value, "VALUE" value = max(value,alphabetaPruning(evalBoard,opponentColor,alpha,beta, depth-1, False,movesRemaining)) # performing recursive call and assigning the maximum value to the "value" alpha = max(alpha, value) # Assigning the max value to alpha if beta <= alpha: #checking whether beta is lesser than alpha break return value # returning the value else: value = test # Assigning the positive max value to alpha for move in moves: # iterating through all the values evalBoard = deepcopy(board) #Making a deepcopy #value = evaluation(evalBoard, color) gamePlay.doMove(evalBoard,move) value = min(value,alphabetaPruning(evalBoard,opponentColor,alpha,beta, depth-1, True, movesRemaining)) # Performing the recursive call and assigning the minimum value to "value" #value = min(move, alphabetaPruning(move, depth-1, True)) beta = min(beta, value) # Assiging the minumum value to beta by comparing beta and value if beta <= alpha: # checking whether beta is lesser than alpha break return value # returning the value
def evaluation(board, color, depth, time): # This function adds the value obtained from each of the evaluation functions(which has their respective weights) and return a final value # When depth is even, max value gets evaluated, hence we send our color to each of the evaluation function # When depth is odd, min value gets evaluated, hence we send opponent's color to each of the evaluation function # TIME UPDATE: when there is plenty of time, use all the evaluation functions but when time is less than 10 seconds, I am only making use of only 2 evaluation functions, # namely, number of pawns and number of kings. if time > 10: if depth%2 == 0: value = 0.35 * evaluation1(board,color) + 0.20 * evaluation2(board,color) + 0.15 * evaluation3(board,color) + 0.2 * evaluation4(board,color) + 0.1 * evaluation5(board, color) else: value = 0.35 * evaluation1(board,gamePlay.getOpponentColor(color)) + 0.20 * evaluation2(board,gamePlay.getOpponentColor(color)) + 0.15 * evaluation3(board,gamePlay.getOpponentColor(color)) + 0.2 * evaluation4(board,gamePlay.getOpponentColor(color)) + 0.1 * evaluation5(board, gamePlay.getOpponentColor(color)) else: if depth%2 == 0: value = 0.6 * evaluation1(board,color) + 0.4 * evaluation2(board, color) else: value = 0.6 * evaluation1(board,gamePlay.getOpponentColor(color)) + 0.4 * evaluation2(board, gamePlay.getOpponentColor(color)) return value
def evaluation(board): global mycolor color = mycolor opponentColor = gamePlay.getOpponentColor(color) pawn, king, corner, edge, front, defence, defended_pawns = 0, 0, 0, 0, 0, 0, 0 for piece in range(1, 33): x, y = gamePlay.serialToGrid(piece) coin = board[x][y] #pawns and kings if coin.upper() == color.upper(): pawn += 1 if coin == color.upper(): king += 1 else: pawn -= 1 if coin == opponentColor.upper(): king -= 1 #corner - safe against attacks if piece in (4,29): if color == coin: corner += 1 else: corner -= 1 #edge - edges are safe, so coins must try to go there if piece in (5,13,21,12,20,28): if color == coin: edge += 1 else: edge -= 1 #front - if a pawn is <= 3 steps from becoming a king if coin == 'r': if piece > 20: if color == 'r': front += 1 else: front -= 1 else: if piece < 13: if color == 'w': front += 1 else: front -= 1 #defended_pawns - if a pawn cannot be attacked if coin == 'r' and x > 0 and y > 0 and y < 7 and board[x-1][y+1].upper() == coin.upper() and board[x-1][y-1].upper() == coin.upper(): if color == 'r': defended_pawns += 1 else: defended_pawns -= 1 elif x < 7 and y > 0 and y < 7 and board[x+1][y+1].upper() == coin.upper() and board[x+1][y-1].upper() == coin.upper(): if color == 'w': defended_pawns += 1 else: defended_pawns -= 1 #my_defence - the bottom row must not be moved unless opponent arrives, provides the best defence for piece in range(1, 5): if color == coin == 'r': defence += 1 for piece in range(29, 33): if color == coin == 'w': defence += 1 # Order of importance(descending) is 1.last layer defence 2.number of kings, #3.number of pawns, 4.defend most pawns, 5.corner, 6.edges, 7.attack(front) return (3*pawn + 7*king + 0.34*corner + 0.33*edge + 0.2*front + 25*defence + 0.5*defended_pawns)
def nextMove(board, color, time, movesRemaining): moves = getAllPossibleMoves(board, color) if len(moves) == 1: return moves[0] opponentColor = gamePlay.getOpponentColor(color) equalMoves = [] best = None alpha = None beta = float("inf") # If the time remaining < 3 seconds, then just apply simpleGreedy and increase depth according to time if time < 3: depth = 1 elif time < 10: depth = 2 elif time < 30: depth = 4 else: if movesRemaining > 40: depth = 8 else: depth = 6 for move in moves: # this is the max turn(1st level of minimax), so next should be min's turn newBoard = deepcopy(board) gamePlay.doMove(newBoard,move) #Beta is always inf here as there is no parent MIN node. So no need to check if we can prune or not. moveVal = evaluation(newBoard, color, depth, 'min', opponentColor, alpha, beta) if best == None or moveVal > best: bestMove = move best = moveVal equalMoves = [] equalMoves.append(move) elif moveVal == best: equalMoves.append(move) if best > alpha: alpha = best #So the equalMoves consists of all the moves that have ended up with same value after Minimax evaluation if len(equalMoves) > 1: #The below logic tries to see if there is any next move that will form a defensive structure from the #equalMoves list and returns it. for move in equalMoves: l = len(move) xy = gamePlay.serialToGrid(move[l-1]) x = xy[0] y = xy[1] if (x+1) <= 7: if (y+1) <= 7 and board[x+1][y+1].lower() == color.lower(): return move if (y-1) >= 0 and board[x+1][y-1].lower() == color.lower(): return move if (x-1) >= 0: if (y+1) <= 7 and board[x-1][y+1].lower() == color.lower(): return move if (y-1) >= 0 and board[x-1][y-1].lower() == color.lower(): return move return bestMove
def nextMove(board, color, time, movesRemaining): global my_color, init_time, time_set, init_moves my_color = color print "My move turn\n" moves = getAllPossibleMoves(board, color) #Trying to find the move where I have best score bestMove=None if len(moves)==1: ## return the move when only a single move is present bestMove = moves[0] print "return the only move left\n" else: ## more than one possible move is present. best = None depth =0 heuristic = curr_evaluation alpha = -float('inf') beta = float('inf') if not time_set: ## recording the time given so as to split into intervals time_set = True init_time = time init_moves=movesRemaining ##print init_time, "W##########" if init_time*3/4 <=time and time<init_time: ##game is in the first quarter if movesRemaining>146: depth = random.randrange(2,4) elif movesRemaining>138 and movesRemaining <=146: depth =5 elif movesRemaining > init_moves*2/3 and movesRemaining<=138: depth=6 else: depth=5 elif init_time/2 <=time and time< init_time*3/4: ## game is in the second quarter if movesRemaining>init_moves/3 and movesRemaining< 2*init_moves/3: depth = random.randrange(3,5) elif movesRemaining>0 and movesRemaining <=init_moves/3: depth = random.randrange(4,6) #heuristic = elif time>0 and time<= init_time/4: if movesRemaining>init_moves/3 and movesRemaining< 2*init_moves/3: depth = random.randrange(4,7) elif movesRemaining>0 and movesRemaining <=init_moves/3: depth = random.randrange(6,8) else: depth=5 ##heuristic = for move in moves: newBoard = deepcopy(board) gamePlay.doMove(newBoard,move) moveVal = miniMax(newBoard,depth,float('inf'), alpha, True, gamePlay.getOpponentColor(color), heuristic) ### we have already evaluated Max's childs here so, its Min's turn to make a move on each of these childs, so min turn is true. if best == None or moveVal > best: bestMove = move best = moveVal alpha = moveVal return bestMove
def nextMove(board, col, time, movesRemaining): #print "player color",color global currentPlayerColor currentPlayerColor=col global opponentPlayerColor opponentPlayerColor = getOpponentColor(col) moves = getAllPossibleMoves(board, currentPlayerColor) '''If there is only 1 move possible no need to evaluate just return that moves''' if len(moves)==1: return moves[0] else: best = None for move in moves: newBoard = deepcopy(board) gamePlay.doMove(newBoard,move) alpha = -sys.maxint - 1 beta = sys.maxint ''' Time and moves remaining are few based on the simple greedy evaluation of the board ''' if time < 5 or (movesRemaining)<4: moveVal = evaluation1(newBoard) else: ''' #if moves remaing are very few we donot go too deep ''' if (movesRemaining/2)<30: moveVal = minimax(newBoard,3,alpha,beta,True) '''inital moves''' elif movesRemaining>140: #start of the game heuristics handles the opening so dont need to go to deep moveVal = minimax(newBoard,3,alpha,beta,True) else: '''last moves''' if time < 5: moveVal = minimax(newBoard,1,alpha,beta,True) elif time<18: moveVal = minimax(newBoard,3,alpha,beta,True) elif time<23: moveVal = minimax(newBoard,5,alpha,beta,True) elif time<28: moveVal = minimax(newBoard,7,alpha,beta,True) '''middle moves''' else: moveVal = minimax(newBoard,5,alpha,beta,True) #moveVal = minimax(newBoard,depth,alpha,beta,True) #we cal minimax to evaluate if best == None or moveVal > best: bestMove = move best = moveVal return bestMove
def evaluation(board, color): global myColor color = myColor global moveCount opponentColor = gamePlay.getOpponentColor(color) value = 0 global fourth_layer # Loop through all board positions for piece in range(1, 33): xy = gamePlay.serialToGrid(piece) x = xy[0] y = xy[1] # Eval on opponent pieces <= 7 or for first 10 moves(Be in attacking mode) if board[x][y].upper() == color.upper() and (countPieces(board, opponentColor) <= 7 or moveCount <= 10): value = value + 1 continue elif board[x][y].upper() == opponentColor.upper() and (countPieces(board, opponentColor) <= 7 or moveCount <= 10): value = value - 1 continue # Eval on pieces in fourth layer(pieces will tend to move towards 4th outer most layer ie defensive positions) if board[x][y].upper() == color.upper() and piece in fourth_layer: value = value + 4 continue elif board[x][y].upper() == opponentColor.upper() and piece in fourth_layer: value = value - 4 continue # Eval on pieces in third layer (pieces will tend to move towards 3rd layer on board) if board[x][y].upper() == color.upper() and piece in third_layer: value = value + 3 continue elif board[x][y].upper() == opponentColor.upper() and piece in third_layer: value = value - 3 continue # Eval on pieces in second layer (pieces will tend to move towards 2nd layer on board if board[x][y].upper() == color.upper() and piece in second_layer: value = value + 2 continue elif board[x][y].upper() == opponentColor.upper() and piece in second_layer: value = value - 2 continue # Eval on pieces in first layer (pieces will tend to move to center two pieces) if board[x][y].upper() == color.upper() and piece in first_layer: value = value + 1 continue elif board[x][y].upper() == opponentColor.upper() and piece in first_layer: value = value - 1 continue return value
def nextMove(board, col, time, movesRemaining): global deep global timeList #Assigned global current and opponent color used to expand nodes and evaluate as per the player global currentPlayerColor currentPlayerColor=col global opponentPlayerColor opponentPlayerColor = getOpponentColor(col) moves = getAllPossibleMoves(board, currentPlayerColor)#returns a list of possible moves[] for the current player #Trying to find the move where my game has best score if len(moves)==1: return moves[0] timeList.append(time) elapsed=timeList[0]-time originalTime = elapsed + time print "timeList" , timeList if(len(timeList)>=2): print "secondLast", timeList[-2] differenceTime = timeList[-2]-timeList[-1] else: differenceTime=0 print "last",timeList[-1] best = None #if time==0 or ((differenceTime*2) >= timeList[-1]) or countPieces(board, currentPlayerColor)<= differenceTime: #or time differnce between last and second last if time<=3 or movesRemaining>=time: newBoard = deepcopy(board) print "calling random move" bestMove = randomMove(newBoard,currentPlayerColor) else: for move in moves: newBoard = deepcopy(board) gamePlay.doMove(newBoard,move)#get the possible states depth=deep alpha = -sys.maxint - 1 beta = sys.maxint print "calling next move" moveVal = minimax(newBoard,deep,alpha,beta,True) if best == None or moveVal > best: bestMove = move best = moveVal if deep<=7: deep=deep+1 print "increased depth,new depth is ",deep #timeList.append(time) print"time list after eval",timeList return bestMove
def getOpponentsLonerPieces(board, color): listOfLoners = list() opponentColor = gamePlay.getOpponentColor(color) #find loners of opponent for i in range(1,33): xy = gamePlay.serialToGrid(i) x = xy[0] y = xy[1] if board[x][y] == opponentColor.upper() or board[x][y] == opponentColor: listOfLoners.append(i) return listOfLoners
def nextMove(board, col, time, movesRemaining): #print "player color",color global currentPlayerColor currentPlayerColor = col global opponentPlayerColor opponentPlayerColor = getOpponentColor(col) moves = getAllPossibleMoves(board, currentPlayerColor) '''If there is only 1 move possible no need to evaluate just return that moves''' if len(moves) == 1: return moves[0] else: best = None for move in moves: newBoard = deepcopy(board) gamePlay.doMove(newBoard, move) alpha = -sys.maxint - 1 beta = sys.maxint ''' Time and moves remaining are few based on the simple greedy evaluation of the board ''' if time < 5 or (movesRemaining) < 4: moveVal = evaluation1(newBoard) else: ''' #if moves remaing are very few we donot go too deep ''' if (movesRemaining / 2) < 30: moveVal = minimax(newBoard, 3, alpha, beta, True) '''inital moves''' elif movesRemaining > 140: #start of the game heuristics handles the opening so dont need to go to deep moveVal = minimax(newBoard, 3, alpha, beta, True) else: '''last moves''' if time < 5: moveVal = minimax(newBoard, 1, alpha, beta, True) elif time < 18: moveVal = minimax(newBoard, 3, alpha, beta, True) elif time < 23: moveVal = minimax(newBoard, 5, alpha, beta, True) elif time < 28: moveVal = minimax(newBoard, 7, alpha, beta, True) '''middle moves''' else: moveVal = minimax(newBoard, 5, alpha, beta, True) #moveVal = minimax(newBoard,depth,alpha,beta,True) #we cal minimax to evaluate if best == None or moveVal > best: bestMove = move best = moveVal return bestMove
def cornerSquares(board, color): drawPositions = [5, 1, 32, 28] value = 0 opponentColor = gamePlay.getOpponentColor(color) for item in drawPositions: xy = gamePlay.serialToGrid(item) x = xy[0] y = xy[1] if board[x][y] == color or board[x][y] == color.upper(): value += 1 elif board[x][y] == opponentColor or board[x][y] == opponentColor.upper(): value -= 1 scoreMap['cornerSquare'] = value
def defenders(board, color): opponentColor = gamePlay.getOpponentColor(color) defendersOfPlayer = 0 defendersOfOpponent = 0 #get count of pawns and kings on edge rows for each player if color == 'w': defendersOfPlayer = board[0].count(color) + board[0].count(color.upper()) + board[1].count(color) + board[1].count(color.upper()) defendersOfOpponent = board[6].count(color) + board[6].count(color.upper()) + board[7].count(color) + board[7].count(color.upper()) else: defendersOfPlayer = board[6].count(color) + board[6].count(color.upper()) + board[7].count(color) + board[7].count(color.upper()) defendersOfOpponent = board[0].count(color) + board[0].count(color.upper()) + board[1].count(color) + board[1].count(color.upper()) scoreMap['defenders'] = 10*defendersOfPlayer-10*defendersOfOpponent
def attackers(board, color): opponentColor = gamePlay.getOpponentColor(color) attackersOfPlayer = 0 attackersOfOpponent = 0 #get count of pawns and kings on top most rows for each player if color == 'w': attackersOfPlayer = board[2].count(color) + board[2].count(color.upper()) + board[3].count(color) + board[3].count(color.upper()) + board[4].count(color) + board[4].count(color.upper()) attackersOfOpponent = board[5].count(color) + board[5].count(color.upper()) + board[4].count(color) + board[4].count(color.upper()) + board[3].count(color) + board[3].count(color.upper()) else: attackersOfOpponent = board[2].count(color) + board[2].count(color.upper()) + board[3].count(color) + board[3].count(color.upper()) + board[4].count(color) + board[4].count(color.upper()) attackersOfPlayer = board[5].count(color) + board[5].count(color.upper()) + board[4].count(color) + board[4].count(color.upper()) + board[3].count(color) + board[3].count(color.upper()) scoreMap['attackers'] = attackersOfPlayer-attackersOfOpponent
def getValueBasedOnCoinDiff(board, x, y, color): opponentColor = gamePlay.getOpponentColor(color) # Count how many pieces I have more than the opponent value = 0 if board[y][x] == color: value = value + ALIVE_POINT elif board[y][x] == opponentColor: value = value - ALIVE_POINT elif board[y][x] == color.upper(): value = value + ALIVE_POINT * 2 elif board[y][x] == opponentColor.upper(): value = value - ALIVE_POINT * 2 return value
def nextMove(board, color, time, movesRemaining): global myColor global opponentColor myColor = color opponentColor = gamePlay.getOpponentColor(color) #result = minimax_simple(board, color, 7, True) result = minimax_pruning(board, 5, -1000000000000, 1000000000000, True) #print "$"*40 #print result[0] #print time, "\t", movesRemaining return result[0]
def safeKings(board, color): opponentColor = gamePlay.getOpponentColor(color) corner = [5, 1, 32, 28, 29, 4] value = 0 for king in corner: xy = gamePlay.serialToGrid(king) x = xy[0] y = xy[1] if board[x][y] == color.upper(): value += 1 return value
def evaluation2(board,color): #Evaluation Function 2: Counting the number of kings of each player in the current state opponentColor = gamePlay.getOpponentColor(color) value = 0 for piece in range(1, 33): xy = gamePlay.serialToGrid(piece) x = xy[0] y = xy[1] if board[x][y] == "R" or board[x][y] == "W": if board[x][y] == color: value = value + 1.5 elif board[x][y] == opponentColor: value = value - 1.5 return value
def evaluation1(board, color): # Evaluation Function 1: Counting the number of pawns each player has in the current state opponentColor = gamePlay.getOpponentColor(color) value = 0 for piece in range(1, 33): xy = gamePlay.serialToGrid(piece) x = xy[0] y = xy[1] if board[x][y] == color: value = value + 1 elif board[x][y] == opponentColor: value = value - 1 return value
def unoccupiedFieldsOnPromotion(board, color): opponentColor = gamePlay.getOpponentColor(color) value = 0 if color == 'r': oppRow = [29,30,31,32] else: oppRow = [1,2,3,4] for item in oppRow: xy = gamePlay.serialToGrid(item) x = xy[0] y = xy[1] if board[x][y] == opponentColor or board[x][y] == opponentColor.upper(): value -= 1 scoreMap['unoccpromo'] = value
def pawnsOnDiagonal(board, color): diagonal = [9,14,18,23] opponentColor = gamePlay.getOpponentColor(color) value = 0 #loop through pieces on diagonals and find out pawns which are at the risk of being captured for item in diagonal: xy = gamePlay.serialToGrid(item) x = xy[0] y = xy[1] if board[x][y] == color or board[x][y] == color.upper(): value += 1 elif board[x][y] == opponentColor or board[x][y] == opponentColor.upper(): value -= 1 scoreMap['pawnsOnDiagonal'] = value
def miniMax(board, depth, beta, alpha, minPlayerTurn, color, heuristic): ## returns best value for max or min moves = getAllPossibleMoves(board, color) if depth==0 or len(moves)==0: ## base condition return if depth is reached or if there are no moves present return heuristic(board) if minPlayerTurn==False: # Max player for move in moves: newBoard = deepcopy(board) gamePlay.doMove(newBoard,move) alpha= max(alpha, miniMax(newBoard, depth-1, beta, alpha, True, gamePlay.getOpponentColor(color), heuristic)) ###recursive call to Min player if alpha >=beta: ## prune break return alpha elif minPlayerTurn==True: ## Min Player's turn for move in moves: newBoard = deepcopy(board) gamePlay.doMove(newBoard, move) beta= min(beta, miniMax(newBoard, depth-1, beta, alpha, False, gamePlay.getOpponentColor(color), heuristic)) ###recursive call to Max player if alpha >=beta: # prune break return beta
def isMyCapturePossibleFromPosition(board, x, y): # Returns whether (x,y) piece can make a capture at this time opponent = getOpponentColor(board[x][y]) # Check whether a jump possible to all four directions if canMoveToMyPosition(board, x, y, x-2, y-2) == True:#top left diagonal leaving 1 return True if canMoveToMyPosition(board, x, y, x-2, y+2) == True:#bottom left return True if canMoveToMyPosition(board, x, y, x+2, y-2) == True:#right top return True if canMoveToMyPosition(board, x, y, x+2, y+2) == True:#right bottom return True return False
def scoreKings(board, color): opponentColor = gamePlay.getOpponentColor(color) value = 0 # Loop through all board positions for piece in range(1, 33): xy = gamePlay.serialToGrid(piece) x = xy[0] y = xy[1] if board[x][y] == color.upper(): value = value + 2 elif board[x][y] == opponentColor.upper(): value = value - 2 scoreMap['kings'] = value
def isMyCapturePossibleFromPosition(board, x, y): # Returns whether (x,y) piece can make a capture at this time opponent = getOpponentColor(board[x][y]) # Check whether a jump possible to all four directions if canMoveToMyPosition(board, x, y, x - 2, y - 2) == True: #top left diagonal leaving 1 return True if canMoveToMyPosition(board, x, y, x - 2, y + 2) == True: #bottom left return True if canMoveToMyPosition(board, x, y, x + 2, y - 2) == True: #right top return True if canMoveToMyPosition(board, x, y, x + 2, y + 2) == True: #right bottom return True return False
def alphaBetaPruning(node, depth, time): moves = getAllPossibleMoves(node[0], node[2]) bestMove = moves[0] #to set the lower bound at max node bestScore = -float("inf") for move in moves: newBoard = deepcopy(node[0]) gamePlay.doMove(newBoard,move) #creating a new node from the initial board generation newNode = returnList(newBoard, node[1]+1, gamePlay.getOpponentColor(node[2])) #calls the min function next score = minimum(newNode, depth, -float("inf"), float("inf"), time) if score > bestScore: bestMove = move bestScore = score return bestMove
def nextMove(board, color, time, movesRemaining): moves = getAllPossibleMoves(board, color) opponentColor = gamePlay.getOpponentColor(color) depth = 5 best = None alpha = None beta = float("inf") for move in moves: # this is the max turn(1st level of minimax), so next should be min's turn newBoard = deepcopy(board) gamePlay.doMove(newBoard,move) #Beta is always inf here as there is no parent MIN node. So no need to check if we can prune or not. moveVal = evaluation(newBoard, color, depth, 'min', opponentColor, alpha, beta) if best == None or moveVal > best: bestMove = move best = moveVal if best > alpha: alpha = best return bestMove
def evaluation2(board, color): opponentColor = gamePlay.getOpponentColor(color) value = 0 # Loop through all board positions for piece in range(1, 33): xy = gamePlay.serialToGrid(piece) x = xy[0] y = xy[1] if board[x][y] == color.upper(): value = value + 1 elif board[x][y] == opponentColor.upper(): value = value - 1 # Let us give extra weightage 10 #return value * 10 return value
def evaluation(board, color): # Evaluation function 1 # Count how many more pieces I have than the opponent opponentColor = gamePlay.getOpponentColor(color) value = 0 # Loop through all board positions for piece in range(1, 33): xy = gamePlay.serialToGrid(piece) x = xy[0] y = xy[1] if board[x][y].upper() == color.upper(): value = value + 1 elif board[x][y].upper() == opponentColor.upper(): value = value - 1 return value
def evaluation3(board, color): opColor = gamePlay.getOpponentColor(color) value = 0 # Loop through all board positions for piece in range(1, 33): # Check if I can capture two # Check whether a jump possible to all four directions xy = gamePlay.serialToGrid(piece) x = xy[0] y = xy[1] if gamePlay.canMoveToPosition(board, x, y, x-2, y-2) == True: if gamePlay.isCapturePossibleFromPosition(board, x-2, y-2): if board[x][y].upper() == color.upper(): value = value + 1 elif board[x][y].upper() == opColor.upper(): value = value - 1 if gamePlay.canMoveToPosition(board, x, y, x-2, y+2) == True: if gamePlay.isCapturePossibleFromPosition(board, x-2, y+2): if board[x][y].upper() == color.upper(): value = value + 1 elif board[x][y].upper() == opColor.upper(): value = value - 1 if gamePlay.canMoveToPosition(board, x, y, x+2, y-2) == True: if gamePlay.isCapturePossibleFromPosition(board, x+2, y-2): if board[x][y].upper() == color.upper(): value = value + 1 elif board[x][y].upper() == opColor.upper(): value = value - 1 if gamePlay.canMoveToPosition(board, x, y, x+2, y+2) == True: if gamePlay.isCapturePossibleFromPosition(board, x+2, y+2): if board[x][y].upper() == color.upper(): value = value + 1 elif board[x][y].upper() == opColor.upper(): value = value - 1 # Lets give weightage 10 # Let us give extra weightage 10 return value
def nextMove(board, col, time, movesRemaining): #print "player color",color global currentPlayerColor currentPlayerColor=col global opponentPlayerColor opponentPlayerColor = getOpponentColor(col) moves = getAllPossibleMoves(board, currentPlayerColor)#returns a list of possible moves[] #Trying to find the move where I have best score best = None for move in moves: newBoard = deepcopy(board) gamePlay.doMove(newBoard,move)#get the possible states depth=5 alpha = -sys.maxint - 1 beta = sys.maxint moveVal = minimax(newBoard,depth,alpha,beta,True) #we cal minimax to evaluate if best == None or moveVal > best: bestMove = move best = moveVal return bestMove
def gamePhase(board, color): opponentColor = gamePlay.getOpponentColor(color) value2 = 0 # Loop through all the rows for piece in range(1, 33): xy = gamePlay.serialToGrid(piece) x = xy[0] y = xy[1] if board[x][y].upper() == color.upper(): value2 = value2 + 1 elif board[x][y].upper() == opponentColor.upper(): value2 = value2 + 1 if value2 > 18 and value2 <= 24: return 1 elif value2 > 10 and value2 <= 18: return 2 else: return 3
def minimax(board, maxP, color, alpha, beta, depth): #calculates maximum when maxP is True and minimum otherwise infty = float('inf') moves = getAllPossibleMoves(board, color) opponentColor = gamePlay.getOpponentColor(color) if maxP: if moves == [] or depth == 0: return [], evaluation(board) best_score = -infty best_move = moves[0] for move in moves: boardTemp = deepcopy(board) gamePlay.doMove(boardTemp,move) m,score = minimax(boardTemp,False,opponentColor,alpha,beta,depth-1) if score > best_score: best_move = move best_score = score alpha = max(alpha,score) #Beta cut-off if alpha >= beta: break else: if moves == [] or depth == 0: return [], evaluation(board) best_score = infty best_move = moves[0] for move in moves: boardTemp = deepcopy(board) gamePlay.doMove(boardTemp,move) m,score = minimax(boardTemp,True,opponentColor,alpha,beta,depth-1) if score < best_score: best_move = move best_score = score beta = min(beta,score) #Alpha cut-off if alpha >= beta: break return best_move, best_score
def evaluation4(board, color): opponentColor = gamePlay.getOpponentColor(color) value = 0 # Loop through all board positions in the list with weightage 4, 3, 2, 1 # The follwoing positions are at edge across the square board #list1 = [1, 2, 3, 4, 5, 12, 13, 20, 21, 28, 29, 30, 31, 32] # This is 2 level deep from the edge across the square board #list2 = [6, 7, 8, 9, 16, 17, 24, 25, 26, 27] # This is 3 level deep from the edge across the square board list3 = [10, 11, 14, 19, 22, 23] # This is 4 level deep from the edge across the square board list4 = [15, 18] for piece in list3: xy = gamePlay.serialToGrid(piece) x = xy[0] y = xy[1] if board[x][y].upper() == color.upper(): value = value + 1 elif board[x][y].upper() == opponentColor.upper(): value = value - 1 for piece in list4: xy = gamePlay.serialToGrid(piece) x = xy[0] y = xy[1] if board[x][y].upper() == color.upper(): value = value + 2 elif board[x][y].upper() == opponentColor.upper(): value = value - 2 # Lets give weightage 3 #return value * 3 return value
def nextMove(board, color, time, movesRemaining): possibleMoves = getAllPossibleMoves(board, color) opponentColor = gamePlay.getOpponentColor(color) #Trying to find the move where I have best score bestValue = None bestmove = possibleMoves[0] depth = 5 alpha = float("-inf") beta = float("inf") for move in possibleMoves: newBoard = deepcopy(board) gamePlay.doMove(newBoard,move) # #retrieves the value from minChance. #Here, alpha is the lower bound of the actual MiniMax value and beta is the upper bound of the actual MiniMax value. score = minChance(newBoard, depth-1,color, opponentColor, alpha, beta) # This is the max turn(1st level of minimax), so next should be min's turn if bestValue == None or score > bestValue: #If the better score is found than the current best value then that move is considered as the best move. Hence, it is taken. bestMove = move bestValue = score if bestValue > alpha: alpha = bestValue return bestMove
def nextMove(board, color, time, movesRemaining): # I will have different depth level as per time remaining if time > 120: depth = 8 elif time > 60: depth = 6 elif time > 5: depth = 4 else: depth = 2 #print "DBG", phase, depth, time #t1 = datetime.datetime.now() moves = getAllPossibleMoves(board, color) best = None opColor = gamePlay.getOpponentColor(color) # If only one move available no need for any computations if len(moves) == 1: bestMove = moves[0] return bestMove # Strategy1: If it is first move hardcoding the best move if isFirstMove(board, color): if color.upper() == 'R': bestMove = [11, 15] else: bestMove = [22, 18] return bestMove # Strategy2: Remove moves that lead to opponent captures my piece for move in moves: myBoard = deepcopy(board) gamePlay.doMove(myBoard,move) # Check if opponents capturing position gone if gamePlay.isCapturePossible(myBoard, opColor) == True: moves.remove(move) # Strategy3: Opponent captures one, but I capture double # Check if newBoard is giving Opponent a capture opMoves = getAllPossibleMoves(board, opColor) # At most of the capture, opMoves will have one element if gamePlay.isCapturePossible(board, opColor) == True: opMove = opMoves[0] opBoard = deepcopy(board) gamePlay.doMove(opBoard, opMove) myMoves = getAllPossibleMoves(opBoard, color) # Check if I can capture two pieces if len(myMoves) > 0: myMove = myMoves[0] # At double-capture, lenghth of the move will be >2 if len(myMove) > 2: # Do nothing, let opponent capture pass else: # Try to block the capture for move in moves: myBoard = deepcopy(board) gamePlay.doMove(myBoard,move) opMoves = getAllPossibleMoves(myBoard, opColor) #Check if opponents capturing position gone if not gamePlay.isCapturePossible(board, opColor): bestMove = move return bestMove # Now start the main MiniMax and alpha-beta here for move in moves: # Strategy4: If I can double-capture, thats best move, kind of greedy if len(move) > 2: bestMove = move return bestMove newBoard = deepcopy(board) alpha = -float('inf') beta = float('inf') # Calling with different depth depending on time remaining in the game alphaVal = alphaBeta(newBoard, move, depth, alpha, beta, True, color, opColor) if best == None or alphaVal > best: bestMove = move best = alphaVal #t2 = datetime.datetime.now() return bestMove