pythonsearchchessalpha-beta-pruningpython-chess

Python chess search function: pop from empty list


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.


Solution

  • 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!