pythonchesspython-chess

How to fix LegalMoveGenerator "LegalMoveGenerator object is not callable" error in python-chess?


I am trying to make a chess Minimax algorithm. However, I encountered a problem.

This is my code:

import random
import itertools
from chess import Board, Move, LegalMoveGenerator

def legal_move_to_move(legal_move):
    """
    Converts a LegalMoveGenerator object to a Move object.

    Args:
        legal_move: A LegalMoveGenerator object.

    Returns:
        A Move object with the `from_square` and `to_square` attributes set to the values of the `LegalMoveGenerator` object.
    """
    return Move(legal_move.from_square, legal_move.to_square)

class ChessAI:
    def __init__(self, board):
        self.board = board

    def get_best_move(self):
        moves = []
        for legal_move in self.board.legal_moves():
            moves.append(legal_move_to_move(legal_move))

        best_move = None
        best_value = -float("inf")

        for move in moves:
            # explicitly convert the LegalMoveGenerator object to a Move object
            move = legal_move_to_move(move)
            board.push(move)
            value = -self.minimax(board, depth=1, alpha=-float("inf"), beta=float("inf"))
            board.pop()

            if value > best_value:
                best_value = value
                best_move = move

        return best_move

    def minimax(self, board, depth=1, alpha=-float("inf"), beta=float("inf")):
        if depth == 0:
            return 0

        if board.is_checkmate():
            return -10000
        elif board.is_stalemate():
            return 0

        moves = []
        for legal_move in self.board.legal_moves():
            moves.append(legal_move_to_move(legal_move))

        best_value = -float("inf")

        for move in moves:
            move = legal_move_to_move(move)
            board.push(move)
            value = -self.minimax(board, depth - 1, alpha, beta)
            board.pop()

            best_value = max(best_value, value)
            if best_value >= beta:
                return best_value

            alpha = max(alpha, best_value)

        return best_value

def main():
    board = Board()
    ai = ChessAI(board)

    while not board.is_game_over():
        if board.turn == 1:
            move = ai.get_best_move()
        else:
            move = input("Your move: ")

        board.push(move)

    print(board.result())

if __name__ == "__main__":
    main()

Here is the full error:

Traceback (most recent call last):
  File "main.py", line 86, in <module>
    main()
  File "main.py", line 77, in main
    move = ai.get_best_move()
  File "main.py", line 23, in get_best_move
    for legal_move in self.board.legal_moves():
TypeError: 'LegalMoveGenerator' object is not callable

It says that object LegalMoveGenerator isn't callable. Is there any way to fix this?

I tried creating functions to convert LegalMoveGenerator to a list, and updating the library, but nothing seems to work. I was expecting a full working game with Minimax AI, but the error occured.


Solution

  • That error means that self.board.legal_moves is not a function(isn't callable) and you hence cannot use the parenthesis on it to execute something(like a variable). It is actually a generator and you can get a list of all legal moves using list(self.board.legal_moves) and then iterate over them instead.

    If you do not want to convert it into a list you can also try the following: for legal_move in self.board.legal_moves: