def validMove(board, color): moves = [] for i in range(8): for j in range(8): if gamePlay.valid(board, color, (i, j)): moves.append((i, j)) return moves
def nextMove(board, color, time): best_val = None best_move = None moves = [] for row in range(8): for col in range(8): if gamePlay.valid(board, color, (row, col)): moves.append((row, col)) #shuffle the moves in case it places the same position in every game #shuffle(moves) if len(moves) == 0: return "pass" if moves == "pass": return "pass" opp = gamePlay.opponent(color) #evaluate max's position and choose the best value if color == "B": for move in moves: newBoard = board[:] gamePlay.doMove(newBoard, color, move) #alpha = - INFINITY beta = INFINITY #we want to choose the max one if best_val = max(best_val, alpha_beta(newBoard, opp, 3, -INFINITY, INFINITY)): #update best move best_move = move
def getAllValidPos(board, color): valid_positions=[]; for i in range(len(board)): for j in range(len(board[0])): if valid(board, color, (i,j)): valid_positions.append((i,j)); return valid_positions;
def allPossibleMoves(cboard, color): #현재 내가 둘 수 있는 곳 들의 리스트 moves = [] for i in range(8): for j in range(8): if valid(cboard, color, (i, j)): moves.append((i, j)) return moves
def nextMove(board, color, time): root = Node() # 루트노드 생성 for i in range(8): for j in range(8): if valid(board, color, (i, j)): # 놓을 수 있는 곳이면 자식으로 추가 temp = Node() temp.data = (i,j) temp.board = deepcopy(board) doMove(temp.board, color, temp.data) root.children.append(temp) if len(root.children) == 0: return "pass" makeTree(root, color, 1) # 트리 생성 alphabeta(root, limitDepth, -INF, INF, MAX, color) # assign cost maxx = -INF bestmove = 0 n = len(root.children) for i in range(n): # 최대 이익을 선택 if maxx < root.children[i].cost: maxx = root.children[i].cost bestmove = root.children[i].data return bestmove
def alphabeta(board, alpha, beta, depth, color, player): can_moves = [] for i in range(8): for j in range(8): if gamePlay.valid(board, player, (i,j)): can_moves.append((i,j)) if depth == 0 or len(can_moves) == 0: return calculate_heuristic(board, color) if(player == color):#Maximizing v = -999999 for can_move in can_moves: temp_board = copy.deepcopy(board) gamePlay.doMove(temp_board, player, can_move) v = max(v, alphabeta(temp_board, alpha, beta, depth-1, color, gamePlay.opponent(player))) alpha = max(alpha, v) if(alpha >= beta): break return v else:#Minimizing v = 999999 for can_move in can_moves: temp_board = copy.deepcopy(board) gamePlay.doMove(temp_board, player, can_move) v = min(v, alphabeta(temp_board, alpha, beta, depth-1, color, gamePlay.opponent(player))) beta = min(beta, v) if (alpha >= beta): break return v
def generate_possible_moves(board, player): moves = [] for i in range(8): for j in range(8): if gamePlay.valid(board, player, (i, j)): moves.append((i, j)) return moves
def getMoves(board, color): moves = [] for i in range(8): for j in range(8): if gamePlay.valid(board, color, (i,j)): moves.append((i,j)) return moves
def mobility(board,color): '''Function to find the mobility of the current color/player on the Board''' mobilityCount = 0 # Counter to maintain the mobility for i in range(8): for j in range(8): if gamePlay.valid(board, color, (i,j)): # Check if the generated move is valid mobilityCount +=1 # Increment the mobility count return mobilityCount # Return the mobility
def mobility(board, player): opponent = flip_player(player) player_possible_moves = 0 opponent_possible_moves = 0 for i in range(8): for j in range(8): if gamePlay.valid(board, player, (i, j)): player_possible_moves += 1 if gamePlay.valid(board, opponent, (i, j)): opponent_possible_moves += 1 if (player_possible_moves + opponent_possible_moves) != 0: heuristic_value = 100 * ( player_possible_moves - opponent_possible_moves) / ( player_possible_moves + opponent_possible_moves) else: heuristic_value = 0 return heuristic_value
def expand(board, color, move): if valid(board, color, move): #deepcopy board: new_board=[None]*len(board); for i in range(len(board)): new_board[i]=map(lambda x:str(x),board[i]); new_board[move[0]][move[1]]=color; return new_board, move; else: raise ValueError("invalid spawnning of child node");
def nextMove(board, color, time): moves = [] for i in range(8): for j in range(8): if valid(board, color, (i, j)): moves.append((i, j)) if len(moves) == 0: return "pass" bestMove = moves[random.randint(0, len(moves) - 1)] return bestMove
def nextMove(board, color, time): moves = [] for i in range(8): for j in range(8): if valid(board, color, (i,j)): moves.append((i,j)) if len(moves) == 0: return "pass" bestMove = moves[random.randint(0,len(moves) - 1)] return bestMove
def successor(board, color): moves = [] for i in range(8): for j in range(8): if gamePlay.valid(board, color, (i,j)): moves.append((i,j)) #If no valid move, we "pass" if len(moves) == 0: return "pass" else: return moves
def getAllPossibleMovesFromState(kBoard, color): """ return array of moves (i,j) """ moves = [] for i in range(8): for j in range(8): if valid(kBoard, color, (i, j)): moves.append((i, j)) return moves
def nextMove(board, color, reversed = False): moves = [] for i in range(8): for j in range(8): if gamePlay.valid(board, color, (i,j)): moves.append((i,j)) if len(moves) == 0: return "pass" best = None for move in moves: newBoard = deepcopy(board) gamePlay.doMove(newBoard,color,move) moveVal = value(newBoard) if best == None or betterThan(moveVal, best, color, reversed): bestMove = move
def nextMove(board,color,time): decrease=0 #decrease the depth of alpha beta prunning. if time>=63.98:#at first, whichever piece we take, it is not a big deal.so we should save time at beginning. decrease=2 elif time<17 and time>=10: decrease=1 elif time<10: #when time is less than 10s decrease=2 elif time<=0: return "pass" moves=[] bonus=[] for i in range(8): for j in range(8): if gamePlay.valid(board,color,(i,j)): moves.append((i,j)) if len(moves)==0: return "pass" best=-100 alpha=-100 beta=100 if (0,0) in moves: bonus.append((0,0)) if(0,7) in moves: bonus.append((0,7)) if (7,0) in moves: bonus.append((7,0)) if (7,7) in moves: bonus.append((7,7)) if len(bonus)>0: for move in bonus: newBoard=deepcopy(board) gamePlay.doMove(newBoard,color,move) tmp=alphabeta(2-decrease,newBoard,alpha,beta,"MIN",color) if best<tmp: best=tmp bestMove=move else: for move in moves: newBoard=deepcopy(board) gamePlay.doMove(newBoard,color,move) tmp=alphabeta(5-decrease,newBoard,alpha,beta,"MIN",color) if best<tmp: best=tmp bestMove=move return bestMove
def nextMove(board, color, time, reversed = False): moves = [] for i in range(8): for j in range(8): if gamePlay.valid(board, color, (i,j)): moves.append((i,j)) if len(moves) == 0: return "pass" best = None for move in moves: newBoard = deepcopy(board) gamePlay.doMove(newBoard,color,move) moveVal = value(newBoard) if best == None or betterThan(moveVal, best, color, reversed): bestMove = move best = moveVal return bestMove
def makeTree(root, color, depth): # 트리 생성 함수 if depth >= limitDepth: # 한계 깊이 이상이면 종료 return moveslen = len(root.children) for k in range(moveslen): child = root.children[k] # 움직일 수 있는 곳을 하나씩 움직여봄 another = opponent(color) for i in range(8): for j in range(8): if valid(child.board, another, (i, j)): # 다음 턴에 놓을 수 있는 곳이면 자식으로 추가 temp = Node() temp.data = (i,j) temp.board = deepcopy(child.board) doMove(temp.board, another, temp.data) child.children.append(temp) if len(child.children) != 0: makeTree(child, another, depth + 1) # 재귀적으로 자식을 확장
def minimax(board, color, depth): #Find the best move in the game #if depth = 0, we calculate the score if depth == 0: return eval_fn(board, color) #if game is over, we calculate the score if gamePlay.gameOver(board): return gamePlay.score(board) best_val = None best_move = None opp = gamePlay.opponent(color) # valid moves moves = [] for row in range(8): for col in range(8): if gamePlay.valid(board, color, (row,col)): moves.append((row,col)) #shuffle the moves in case it places the same position in every game #shuffle(moves) if len(moves) == 0: return "pass" if move == "pass": return eval_fn(board, color) #try each move in valid moves #evaluate max's position and choose the best value if color == "B": for move in moves: newBoard = board[:] gamePlay.doMove(newboard, color, move) val = minimax(newBoard, opp, depth-1) if best_val is None or val > (best_val, best_move)[0]: (best_val, best_move) = (val, move) #evaluate min's position and choose the best value if color == "W": for move in moves: newBoard = board[:] gamePlay.doMove(newboard, color, move) val = minimax(newBoard, opp, depth-1) if best_val is None or val < (best_val, best_move)[0]: (best_val, best_move) = (val, move) return (best_val, best_move)[0]
def alpha_beta(board, color, depth, alpha, beta): """Find the utility value of the game and the best_val move in the game.""" if depth == 0: return eval_fn(board, color) if gamePlay.gameOver(board): return gamePlay.score(board) moves = [] for row in range(8): for col in range(8): if gamePlay.valid(board, color, (row, col)): moves.append((row, col)) #shuffle the moves in case it places the same position in every game #shuffle(moves) if len(moves) == 0: return "pass" if moves == "pass": return eval_fn(board, color) opp = gamePlay.opponent(color) # try each move #evaluate max's position and choose the best value if color == "B": for move in moves: newBoard = board[:] gamePlay.doMove(newBoard, color, move) #cut off the branches alpha = max(alpha, alpha_beta(newBoard, opp, depth-1, alpha, beta)) if beta <= alpha: return return alpha #evaluate min's position and choose the best value if color == "W": for move in moves: newBoard = board[:] gamePlay.doMove(newBoard, color, move) #cut off the branches beta = min(beta, alpha_beta(newBoard, opp, depth-1, alpha, beta)) if beta <= alpha: return return beta
def nextMove(board, color, time): limit_depth = 4 max_value = -999999 min_value = 99999 valid_count = 0 for i in range(8): for j in range(8): if gamePlay.valid(board ,color, (i,j)): valid_count += 1 temp_board = copy.deepcopy(board) gamePlay.doMove(temp_board, color, (i,j)) v = alphabeta(temp_board, max_value, min_value, limit_depth-1, color, gamePlay.opponent(color)) if v >= max_value: next_move = (i, j) max_value = v if valid_count == 0: return "pass" #gamePlay.printBoard(board) return next_move
def possibleChildMoves(board,color): '''Function to get the valid moves for a Board''' moves = [] # List to maintain the possible valid moves orderedMovesValues = [] # List to maintain the moves and their heuristic values orderedMoves = [] # List to maintain the ordered moves for i in range(8): for j in range(8): if gamePlay.valid(board, color, (i,j)): # Check if the generated move is valid moves.append((i,j)) # Append the move to the list for move in moves : newBoard = deepcopy(board) # Create a copy of the current board gamePlay.doMove(newBoard,color,move) # Play the move to check its heuristic value currHeurValue = heurValue(newBoard,color) # Find the heuristic value of the move orderedMovesValues.append([currHeurValue,move]) # Append the move along with its heuristic value to a new list orderedMovesValues.sort(key=lambda x: x[0],reverse = True) # Sort the list in Descending order based on heuristic value for i in range(0,len(orderedMovesValues)): orderedMoves.append(orderedMovesValues[i][1]) # Extract the set of moves from the Ordered Heuristic List return orderedMoves # Return the Ordered Moves
def isValid(board, color, pos): x, y = pos[0], pos[1] return ( pos == 'pass' or validPos(x, y) ) and valid(board, color, (x, y))
def eval_func2(board, player): opponent = flip_player(player) player_count = 0 opponent_count = 0 player_possible_moves = 0 opponent_possible_moves = 0 player_corners_cnt = 0 opponent_corners_cnt = 0 for i in range(8): for j in range(8): if board[i][j] == player: player_count += 1 if i == 0: if j == 0: player_corners_cnt += 1 if j == 7: player_corners_cnt += 1 if i == 7: if j == 0: player_corners_cnt += 1 if j == 7: player_corners_cnt += 1 elif board[i][j] == opponent: opponent_count += 1 if i == 0: if j == 0: opponent_corners_cnt += 1 if j == 7: opponent_corners_cnt += 1 if i == 7: if j == 0: opponent_corners_cnt += 1 if j == 7: opponent_corners_cnt += 1 if gamePlay.valid(board, player, (i, j)): player_possible_moves += 1 if gamePlay.valid(board, opponent, (i, j)): opponent_possible_moves += 1 if (player_count + opponent_count) != 0: coin_diff_heuristic_value = 100 * (player_count - opponent_count) / ( player_count + opponent_count) else: coin_diff_heuristic_value = 0 if (player_possible_moves + opponent_possible_moves) != 0: mobility_heuristic_value = 100 * ( player_possible_moves - opponent_possible_moves) / ( player_possible_moves + opponent_possible_moves) else: mobility_heuristic_value = 0 if (player_corners_cnt + opponent_corners_cnt) != 0: corners_heuristic_value = 100 * ( player_corners_cnt - opponent_corners_cnt) / (player_corners_cnt + opponent_corners_cnt) else: corners_heuristic_value = 0 #print coin_diff_heuristic_value, mobility_heuristic_value, corners_heuristic_value combined_heuristic_value = (coin_diff_heuristic_value + mobility_heuristic_value + corners_heuristic_value) / 3 return combined_heuristic_value
def get_successors(board, color): '''Get current situation's children nodes''' return [(i, j) for i in range(8) for j in range(8) if gamePlay.valid(board, color, (i, j))]
def alphabeta(limit,board,alpha,beta,turn,color):#limit is the depth of tree moves=[] if limit==0: ''' limit=0,then return the value''' moveVal=evaluateFunc(board,color) return moveVal for i in range(8): for j in range(8): if gamePlay.valid(board,color,(i,j)): moves.append((i,j)) if len(moves)==0: ''' if no moves, we just move to next turn except there is no empty block''' num=0 for row in board: for elem in row: if elem=='.': num=num+1 if num==0:#if no empty block,return the value moveVal=evaluateFunc(board,color) return moveVal if turn=="MAX": tmp=alphabeta(limit-1,board,alpha,beta,"MIN",color) if tmp>=beta: return beta else: return tmp if turn == "MIN": tmp=alphabeta(limit-1,board,alpha,beta,"MAX",color) if tmp<beta: beta=tmp if alpha>=beta: return alpha return beta if turn=="MAX": '''MAX-VALUE FUNCTION''' for move in moves: newBoard=deepcopy(board) gamePlay.doMove(newBoard,color,move) tmp=alphabeta(limit-1,newBoard,alpha,beta,"MIN",color) if tmp>alpha: alpha=tmp if alpha>=beta:#pruning return beta return alpha if turn=="MIN": '''MIN-VALUE FUNCTION''' for move in moves: newBoard=deepcopy(board) gamePlay.doMove(newBoard,color,move) tmp=alphabeta(limit-1,newBoard,alpha,beta,"MAX",color) if tmp<beta: beta=tmp if alpha>=beta: #pruning return alpha return beta