Python国际象棋引擎Move Ordering功能实现问题及优化求助
核心修改方案
1. 修复domove函数的致命逻辑错误
你当前domove函数的try-except-finally结构完全错误:finally块的代码无论前面是否触发返回都会强制执行,等于开局库查询、走法排序的结果全部被覆盖,这是你走法排序完全不生效的核心原因。同时开局库连续赋值三次move只会保留最后一个库的查询结果,没有容错逻辑。
修改后的代码:
def domove(depth): # 优先查询开局库 book_paths = [ "C:/Users/bruno/Desktop/chess/books/pecg_book.bin", "C:/Users/bruno/Desktop/chess/books/human.bin", "C:/Users/bruno/Desktop/chess/books/computer.bin" ] for path in book_paths: try: with chess.polyglot.MemoryMappedReader(path) as reader: move = reader.weighted_choice(board).move() movehistory.append(move) return move except: continue # 开局库无匹配,先对走法排序 ordered_moves = orderMoves(board) bestMove = chess.Move.null() bestValue = -9999 alpha = -10000 beta = 10000 # 用排序后的走法做alpha-beta搜索 for move in ordered_moves: make_move(move) boardValue = -negamax(board, depth-1, -beta, -alpha) unmake_move() if boardValue > bestValue: bestValue = boardValue bestMove = move if boardValue > alpha: alpha = boardValue if alpha >= beta: break movehistory.append(bestMove) return bestMove
2. 重写orderMoves走法排序函数
你原有orderMoves逻辑完全混乱:没有对走法做排序、参数无意义、异常滥用。走法排序的核心是给所有合法走法计算优先级分数,按分数从高到低返回排序后的走法列表,而非直接返回某个走法。
修改后的代码:
def orderMoves(board): move_scores = {} # 先获取所有合法走法 legal_moves = list(board.legal_moves) for move in legal_moves: score = 0 # 优先级1:置换表中存储的当前局面最优走法 tt_entry = transpositionTableLookup(board) if tt_entry.is_valid and tt_entry.best_move == move: score += 10000 # 优先级2:一步将死走法 board.push(move) if board.is_checkmate(): score += 9000 board.pop() # 优先级3:吃子走法用MVV-LVA规则打分 if board.is_capture(move): victim = board.piece_at(move.to_square).piece_type attacker = board.piece_at(move.from_square).piece_type # 子力价值参考:兵1、马3、象3、车5、后9、王0 piece_values = {1:1, 2:3, 3:3, 4:5, 5:9, 6:0} score += 100 * piece_values[victim] - piece_values[attacker] move_scores[move] = score # 按分数从高到低排序 legal_moves.sort(key=lambda x: move_scores[x], reverse=True) return legal_moves
3. 修复negamax函数逻辑错误
你原有negamax存在参数冗余、置换表存储缩进错误、递归调用逻辑混乱的问题:置换表存储代码被写在for循环内,只有触发剪枝时才会执行存储,大部分情况不会写入置换表,同时参数score、bestValue不需要外部传入。
修改后的代码:
def negamax(node, depth, alpha, beta): alphaOrig = alpha EXACT = 0 LOWERBOUND = 1 UPPERBOUND = 2 # 置换表查询 ttEntry = transpositionTableLookup(node) if ttEntry.is_valid: if ttEntry.depth >= depth: if ttEntry.flag == EXACT: return ttEntry.value elif ttEntry.flag == LOWERBOUND: alpha = max(alpha, ttEntry.value) elif ttEntry.flag == UPPERBOUND: beta = min(beta, ttEntry.value) if alpha >= beta: return ttEntry.value # 递归终止条件:深度为0或者局面终局 if depth == 0 or node.is_game_over(): return evaluate(node) # 替换为你自己的局面评估函数 # 获取排序后的走法 ordered_moves = orderMoves(node) bestValue = -99999 best_move = None for move in ordered_moves: node.push(move) current_value = -negamax(node, depth - 1, -beta, -alpha) node.pop() if current_value > bestValue: bestValue = current_value best_move = move alpha = max(alpha, bestValue) if alpha >= beta: break # 置换表存储 ttEntry.value = bestValue ttEntry.best_move = best_move if bestValue <= alphaOrig: ttEntry.flag = UPPERBOUND elif bestValue >= beta: ttEntry.flag = LOWERBOUND else: ttEntry.flag = EXACT ttEntry.depth = depth transpositionTableStore(node, ttEntry) return bestValue
4. 验证优化步骤
- 先单独测试
orderMoves函数,打印排序后的走法顺序,确认高优先级走法(吃子、将死、置换表最优走法)排在最前 - 暂时关闭开局库、置换表,验证基础negamax+alpha-beta搜索的正确性,24个测试用例全部通过后再逐步开启其他模块
- 确认你的局面评估函数
evaluate逻辑正确,这是搜索结果准确的基础
内容的提问来源于stack exchange,提问作者Bruno
相关产品推荐
相关产品推荐

