【发布时间】:2022-01-14 15:22:07
【问题描述】:
我试图为国际象棋创建一个极小极大算法,但它不起作用。它现在在第 118 行给出元组实例和浮点数之间不支持'NoneTypes。有人知道解决这个问题的方法吗?
import chess
from numpy import Infinity
import numpy as np
import random
board = chess.Board()
def random_board(max_depth=200):
board = chess.Board()
depth = random.randrange(0, max_depth)
for _ in range(depth):
all_moves = list(board.legal_moves)
random_move = random.choice(all_moves)
board.push(random_move)
if board.is_game_over():
break
return board
board = random_board()
pawn_square_value = np.array([0, 0, 0, 0, 0, 0, 0, 0, 5, 10, 10, -20, -20, 10, 10, 5, 5, -5, -10, 0, 0, -10, -5, 5, 0, 0, 0, 20, 20, 0, 0, 0, 5, 5, 10, 25, 25, 10, 5, 5, 10, 10, 20, 30, 30, 20, 10, 10, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0, 0, 0])
knight_square_value = np.array([-50,-40,-30,-30,-30,-30,-40,-50, -40,-20, 0, 5, 5, 0, -20, -40, -30, 5, 10, 15, 15, 10, 5, -30, -30, 0, 15, 20, 20, 15, 0,-30, -30, 5, 15, 20, 20, 15, 5,-30, -30, 0, 10, 15, 15, 10, 0,-30, -40,-20, 0, 0, 0, 0,-20,-40, -50,-40,-30,-30,-30,-30,-40,-50])
bishop_square_value = np.array([-20,-10,-10,-10,-10,-10,-10,-20, -10, 5, 0, 0, 0, 0, 5,-10,-10, 10, 10, 10, 10, 10, 10,-10, -10, 0, 10, 10, 10, 10, 0,-10, -10, 5, 5, 10, 10, 5, 5,-10,-10, 0, 5, 10, 10, 5, 0,-10, -10, 0, 0, 0, 0, 0, 0,-10, -20,-10,-10,-10,-10,-10,-10,-20])
rook_square_value = np.array([0, 0, 0, 5, 5, 0, 0, 0, -5, 0, 0, 0, 0, 0, 0, -5, -5, 0, 0, 0, 0, 0, 0, -5, -5, 0, 0, 0, 0, 0, 0, -5, -5, 0, 0, 0, 0, 0, 0, -5, -5, 0, 0, 0, 0, 0, 0, -5, 5, 10, 10, 10, 10, 10, 10, 5, 0, 0, 0, 0, 0, 0, 0, 0])
queen_square_value = np.array([-20,-10,-10, -5, -5,-10,-10,-20, -10, 0, 5, 0, 0, 0, 0,-10,-10, 5, 5, 5, 5, 5, 0,-10, -10, 5, 5, 5, 5, 5, 0,-10, -5, 0, 5, 5, 5, 5, 0, -5, -10, 0, 5, 5, 5, 5, 0,-10, -10, 0, 0, 0, 0, 0, 0,-10, -20,-10,-10, -5, -5,-10,-10,-20,])
king_square_value = np.array([20, 30, 10, 0, 0, 10, 30, 20, 20, 20, 0, 0, 0, 0, 20, 20, -10,-20,-20,-20,-20,-20,-20,-10, -20,-30,-30,-40,-40,-30,-30,-20, -30,-40,-40,-50,-50,-40,-40,-30, -30,-40,-40,-50,-50,-40,-40,-30, -30,-40,-40,-50,-50,-40,-40,-30, -30,-40,-40,-50,-50,-40,-40,-30])
def init_evaluation():
wp = len(board.pieces(chess.PAWN, chess.WHITE))
bp = len(board.pieces(chess.PAWN, chess.BLACK))
wn = len(board.pieces(chess.KNIGHT, chess.WHITE))
bn = len(board.pieces(chess.KNIGHT, chess.BLACK))
wb = len(board.pieces(chess.BISHOP, chess.WHITE))
bb = len(board.pieces(chess.BISHOP, chess.BLACK))
wr = len(board.pieces(chess.ROOK, chess.WHITE))
br = len(board.pieces(chess.ROOK, chess.BLACK))
wq = len(board.pieces(chess.QUEEN, chess.WHITE))
bq = len(board.pieces(chess.QUEEN, chess.BLACK))
material = 100 *(wp-bp) + 320 * (wn-bn) + 330 * (wb-bb) + 500 * (wr-br) + 900 * (wq - bq)
pawnsq = sum([pawn_square_value[i] for i in board.pieces(chess.PAWN, chess.WHITE)])
pawnsq = pawnsq + sum([-pawn_square_value[chess.square_mirror(i)]
for i in board.pieces(chess.PAWN, chess.BLACK)])
knightsq = sum([knight_square_value[i] for i in board.pieces(chess.KNIGHT, chess.WHITE)])
knightsq = knightsq + sum([-knight_square_value[chess.square_mirror(i)]
for i in board.pieces(chess.KNIGHT, chess.BLACK)])
bishopsq= sum([bishop_square_value[i] for i in board.pieces(chess.BISHOP, chess.WHITE)])
bishopsq= bishopsq + sum([-bishop_square_value[chess.square_mirror(i)]
for i in board.pieces(chess.BISHOP, chess.BLACK)])
rooksq = sum([rook_square_value[i] for i in board.pieces(chess.ROOK, chess.WHITE)])
rooksq = rooksq + sum([-rook_square_value[chess.square_mirror(i)]
for i in board.pieces(chess.ROOK, chess.BLACK)])
queensq = sum([queen_square_value[i] for i in board.pieces(chess.QUEEN, chess.WHITE)])
queensq = queensq + sum([-queen_square_value[chess.square_mirror(i)]
for i in board.pieces(chess.QUEEN, chess.BLACK)])
kingsq = sum([king_square_value[i] for i in board.pieces(chess.KING, chess.WHITE)])
kingsq = kingsq + sum([-king_square_value[chess.square_mirror(i)]
for i in board.pieces(chess.KING, chess.BLACK)])
boardvalue = material + pawnsq + knightsq + bishopsq + rooksq + queensq + kingsq
return boardvalue
def evaluate_board():
if board.is_checkmate() == True:
if board.turn:
return -9999
else:
return 9999
elif board.is_stalemate() == True:
return 0
elif board.is_insufficient_material() == True:
return 0
else:
return init_evaluation()
print(evaluate_board())
print(board)
board.legal_moves
#Een minimax met alpha-beta pruning:
def minimax(bord, max_depth, depth, alpha, beta):
if depth == max_depth or board.is_checkmate() == True:
return evaluate_board(), None
best_move = None
if board.turn == chess.WHITE:
best_score = -Infinity
else:
best_score = Infinity
for move in board.legal_moves:
newBoard = board.copy()
newBoard.push(move)
current_score = minimax(newBoard, max_depth, depth+1, alpha, beta)
if board.turn == chess.WHITE:
if current_score > best_score:
best_score = current_score
best_move = move
else:
if current_score < best_score:
best_score = current_score
best_move = move
return best_score, best_move
def get_best_move():
move = minimax(board, 3, 0, -Infinity, Infinity)
return move
print(get_best_move())
【问题讨论】:
-
minimax返回一个包含 2 个东西的元组。但是在current_score = minimax(...)你只期待一个。如果您不需要第二个,请执行current_score, _ = minimax(...)。 -
我们在 StackOverflow 上看不到行号。当然,您可以创建一个不包含太多代码的minimal reproducible example。
-
您的极小值返回两个值,您将这两个值保存为当前分数。因此你得到一个元组。正如@TimRoberts 所说,您实际上需要将它们保存为两个单独的变量,以使用逗号分隔符来防止这种情况发生,或者在比较时只需访问
current_score[0]。