''' Notice that we are using 2 unique moving functions for: fox_moves and eagle_moves varies on the two genres ''' import random from math import inf import collections piece_score = {"7": 120, "1": 100, "6": 120, "5": 80, "4": 60,"3": 70,"2": 100} mouse_score = [[13, 13, 13, 13, 12, 11, 10, 9, 8], [25, 20, 15, 13, 12, 12, 10, 9, 8], [50, 25, 20, 12, 11, 11, 10, 9, 8], [1919810, 50, 20, 11, 9, 9, 9, 9, 0], [50, 25, 20, 9, 8, 8, 8, 8, 8], [25, 20, 15, 9, 8, 8, 8, 8, 8], [11, 11, 10, 8, 8, 8, 8, 8, 8]] # eagle_score = [[ 11, 12, 14, 13, 12, 11, 10, 8, # 8], # [ 15, 15, 14, 14, 0, 0, 0, 8, # 8], # [ 50, 20, 20, 0, 0, 0, 0, 8, # 8], # [100000, 50, 20, 13, 12, 11, 10, 8, # 0], # [ 50, 20, 20, 14, 0, 0, 0, 8, # 8], # [ 15, 12, 15, 14, 0, 0, 0, 8, # 8], # [ 11, 12, 14, 13, 12, 11, 10, 8, # 8]] eagle_score = [[14,13,10,12,14,13,10,8,7], [15,15,14,0,0,0,9,8,6], [50,20,20,0,0,0,7,5,4], [1919810,50,20,13,12,11,10,8,0], [50,20,20,0,0,0,7,5,4], [15,12,15,0,0,0,9,8,6], [14,12,10,13,14,13,10,8,7]] fox_score = [[ 11, 12, 14, 13, 12, 11, 10, 8, 8], [ 15, 15, 14, 0, 0, 0, 10, 8, 8], [ 50, 20, 20, 0, 0, 0, 10, 9, 10], [1919810, 50, 20, 13, 12, 11, 11, 10, 0], [ 50, 20, 20, 0, 0, 0, 10, 9, 10], [ 15, 12, 15, 0, 0, 0, 10, 8, 8], [ 11, 12, 14, 13, 12, 11, 10, 8, 8]] wolf_score = [[ 11, 12, 14, 13, 12, 11, 10, 8, 8], [ 15, 15, 14, 0, 0, 0, 10, 8, 8], [ 50, 20, 20, 0, 0, 0, 10, 9, 10], [1919810, 50, 20, 13, 12, 11, 11, 10, 0], [ 50, 20, 20, 0, 0, 0, 10, 9, 10], [ 15, 12, 15, 0, 0, 0, 10, 8, 8], [ 11, 12, 14, 13, 12, 11, 10, 8, 8]] leopard_score = [[ 11, 12, 14, 13, 12, 11, 10, 8, 8], [ 15, 15, 14, 0, 0, 0, 10, 8, 8], [ 50, 20, 20, 0, 0, 0, 10, 9, 10], [1919810, 50, 20, 13, 12, 11, 11, 10, 0], [ 50, 20, 20, 0, 0, 0, 10, 9, 10], [ 15, 12, 15, 0, 0, 0, 10, 8, 8], [ 11, 12, 14, 13, 12, 11, 10, 8, 8]] lion_score = [[ 20, 20, 18, 15, 12, 11, 14, 12, 5], [ 40, 25, 30, 0, 0, 0, 16, 12, 12], [ 50, 40, 30, 0, 0, 0, 16, 12, 12], [1919810, 50, 20, 15, 15, 15, 9, 12, 0], [ 50, 40, 30, 0, 0, 0, 16, 12, 12], [ 40, 25, 30, 0, 0, 0, 16, 12, 12], [ 20, 20, 18, 15, 12, 11, 14, 12, 5]] elephant_score = [[ 20, 20, 18, 15, 12, 11, 14, 12, 5], [ 40, 25, 30, 0, 0, 0, 16, 12, 12], [ 50, 40, 30, 0, 0, 0, 16, 12, 12], [1919810, 50, 20, 15, 15, 15, 9, 12, 0], [ 50, 40, 30, 0, 0, 0, 16, 12, 12], [ 40, 25, 30, 0, 0, 0, 16, 12, 12], [ 20, 20, 18, 15, 12, 11, 14, 12, 5]] piece_position_scores = {"r1": mouse_score, "b1": [line[::-1] for line in mouse_score[::-1]], "r2": eagle_score, "b2": [line[::-1] for line in eagle_score[::-1]], "r3": fox_score, "b3": [line[::-1] for line in fox_score[::-1]], "r4": wolf_score, "b4": [line[::-1] for line in wolf_score[::-1]], "r5": leopard_score, "b5": [line[::-1] for line in leopard_score[::-1]], "r6": lion_score, "b6": [line[::-1] for line in lion_score[::-1]], "r7": elephant_score, "b7": [line[::-1] for line in elephant_score[::-1]], } DEN_CONQUESTED=10000 DRAW=0 global DEPTH #=4 def findRandomMove(valid_moves): return valid_moves[random.randint(0,len(valid_moves)-1)] #is greedy_move function used here? def find_GreadyMove(game_state, valid_moves): turnMultiplier = 1 if game_state.red_to_move else -1 maxScore = -DEN_CONQUESTED bestMove = None for playerMove in valid_moves: game_state.makeMove(playerMove) score = turnMultiplier * scoreMaterial(game_state) if score > maxScore: maxScore = score bestMove = playerMove game_state.undoMove() return bestMove def scoreMaterial(game_state): # get the score score = 0 penalty_for_rep = 0 for row in range(len(game_state.board)): for col in range(len(game_state.board[row])): piece = game_state.board[row][col] if piece != "00": piece_position_score = 0 piece_position_score = piece_position_scores[piece][row][col] if piece_position_scores[piece][row][col] in last_moves: penalty_for_rep += 70 if piece[0] == 'r': score += piece_position_score + piece_score[piece[1]] - penalty_for_rep elif piece[0] == 'b': score -= piece_position_score + piece_score[piece[1]] - penalty_for_rep return score def findMove_NegaMaxAlphaBeta(game_state, valid_moves, depth,DEPTH, alpha, beta, turn_multiplier): global next_move if depth == 0: return turn_multiplier * scoreMaterial(game_state) max_score = -inf for move in valid_moves: game_state.makeMove(move) next_moves = game_state.getAllMoves() score = -findMove_NegaMaxAlphaBeta(game_state, next_moves, depth - 1,DEPTH, -beta, -alpha, -turn_multiplier) if score > max_score: # > or >= ?? max_score = score if depth == DEPTH: next_move = move game_state.undoMove() if max_score > alpha: alpha = max_score if alpha >= beta: break return max_score def findMove_MiniMaxAlphaBeta(game_state, valid_moves, depth, alpha, beta, turn_multiplier): global next_move def max_value(game_state,next_moves, alpha, beta,depth): if depth == 0: return turn_multiplier * scoreMaterial(game_state) v = -inf for move in valid_moves: next_moves = game_state.getAllMoves() v = max(v, min_value(game_state,next_moves, alpha, beta,depth - 1)) game_state.undoMove() if v >= beta: return v alpha = max(alpha, v) return v def min_value(game_state,next_moves, alpha, beta,depth): if depth == 0: return turn_multiplier * scoreMaterial(game_state) v = -inf for move in valid_moves: next_moves = game_state.getAllMoves() v = min(v, max_value(game_state,next_moves, alpha, beta,depth - 1)) game_state.undoMove() if v <= alpha: return v beta = min(beta, v) return v # Body of alpha_beta_search: best_score = -inf beta = inf best_action = None for move in valid_moves: v = min_value(game_state,valid_moves, best_score, beta,depth) if v > best_score: best_score = v best_action = move return best_action def find_BestMove(game_state, valid_moves,depth_p): global next_move DEPTH= depth_p next_move = None global last_moves last_moves = collections.deque(maxlen=12) random.shuffle(valid_moves) ordered_valid_moves=orderby_GreadyMove(game_state, valid_moves) # for i in valid_moves: # print(f"Possible: {i}") # for i in ordered_valid_moves: # print(f"New possible: {i}") findMove_NegaMaxAlphaBeta(game_state, ordered_valid_moves,depth_p,DEPTH, -DEN_CONQUESTED, DEN_CONQUESTED,1 if game_state.red_to_move else -1) last_moves.append(next_move) return next_move def orderby_GreadyMove(game_state, valid_moves): turnMultiplier = 1 if game_state.red_to_move else -1 maxScore = -DEN_CONQUESTED de = collections.deque([]) for playerMove in valid_moves: game_state.makeMove(playerMove) score = turnMultiplier * scoreMaterial(game_state) if score > maxScore: maxScore = score de.appendleft(playerMove) else: de.append(playerMove) game_state.undoMove() return de