This is my search function for python chess engine:
def search(pos: position.Position, depth: int, alpha: int, beta: int, side_to_move: chess.Color, root: bool = False):
global nodes, best_score, best_move, max_score, min_score, killers
bestMove = None
"""Search the position to a given depth."""
if depth == 0 or pos.board.chess_board().is_game_over():
nodes += 1
return evaluate.evaluate(pos, side_to_move), best_move
for move in pos.board.chess_board().legal_moves:
if stop_search.search_has_stopped():
return best_score, best_move
if prune(pos, move, alpha, beta, side_to_move, depth):
continue
pos.board.chess_board().push(move)
score, _ = search(pos, depth - 1, -beta, -alpha, not side_to_move, root=False)
score = -score
pos.board.chess_board().pop()
if score > best_score:
best_score = score
best_move = move
if score > max_score:
max_score = score
if score < min_score:
min_score = score
if score > alpha:
alpha = score
bestMove = move
if score >= beta:
best_move = bestMove
return beta, bestMove
else:
killers.append(move)
return alpha, bestMove
When I run it, the results are fine until depth 4, where I get this strange error:
File "path/to/search.py", line 66, in search
pos.board.chess_board().pop()
File "path/to/chess/__init__.py", line 2267, in pop
move = self.move_stack.pop()
^^^^^^^^^^^^^^^^^^^^^
IndexError: pop from empty list
I assume this means that pushing the move to the position was not successful.
I do not know why this occurs, because I am certain that the generated move
is legal (it uses the default legal move generator).
Any help on this would be much appreciated.
I've made a chess engine in python before, so I hope I can be helpful here. First of all the error you are getting doesn't mean that pushing the move was unsuccessful, but rather that undoing it was impossible, because no move was recorded: In python chess, the move_stack
is a list stored in the Board
class which contains the moves that were played. In your case,
IndexError: pop from empty list
This means that the move_stack
is empty. For debugging purposes you can access it with board.move_stack
and get something like [Move.from_uci('e2e4'), Move.from_uci('e7e5')]
.
Ok, now that we know this, there is only one way the error can happen: at some point in your code, you run pop()
once more than push()
. In the code you provide, pop()
is always run after a push()
call, so the issue doesn't seem to come from here. However, I searched for all the times you use pop()
in the github code, and if I am not mistaken in the see_eval()
function you run
if e > 0:
pos.board.chess_board().pop()
return capturedV - capturingV
without pushing before. This could be the cause of your issue. I hope this helps anyways!