''' 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": 180, "1": 200, "6": 150, "5": 100, "4": 60, "3": 50, "2": 81} mouse_score = [[13, 13, 13, 13, 12, 11, 10, 9, 8], [25, 20, 15, 18, 16, 13, 10, 9, 8], [50, 25, 20, 16, 15, 13, 10, 9, 8], [1919810, 50, 20, 11, 9, 9, 9, 9, 0], [50, 25, 20, 16, 14, 12, 8, 8, 8], [25, 20, 15, 17, 15, 12, 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, 14, 13, 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, 14, 11], [50, 20, 20, 0, 0, 0, 10, 8, 10], [1919810, 50, 20, 13, 12, 11, 11, 10, 0], [50, 20, 20, 0, 0, 0, 10, 8, 11], [15, 12, 15, 0, 0, 0, 10, 14, 11], [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]] wolf_score = [[11, 12, 14, 13, 12, 11, 10, 10, 8], [15, 15, 14, 0, 0, 0, 10, 14, 10], [50, 20, 20, 0, 0, 0, 10, 12, 10], [1919810, 50, 20, 12, 11, 10, 11, 12, 0], [50, 20, 20, 0, 0, 0, 10, 13, 10], [15, 12, 15, 0, 0, 0, 13, 14, 8], [11, 12, 14, 13, 12, 10, 11, 12, 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 # input: current game_state 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): # 对于各个参数的理解: # game_state:当前状态 # valid_moves:可行的行动列表 # depth:当前深度 # DEPTH:限制深度 # alpha:alpha限制值 # beta:beta限制值 # turn_multiplier:NegaMax特性 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