Ariel
Ariel

Reputation: 37

Minimax returning illegal uci move - move generation doesn't update?

When I test my code with the position r1bqkbr1/pp2pppp/2n1p2n/2p5/3P4/7N/PPP2PPP/RNBQKB1R w KQq - 3 6 the code below outputs ValueError: illegal uci: 'd8d7' in r1bqkbr1/pp2pppp/2n1p2n/2p5/3P4/7N/PPP2PPP/RNBQKB1R w KQq - 3 6 when run. The issue seems to be that the board is not updating after I push a new move (it still generates legal moves thinking it is black to move, when it is actually white to move). How do I fix this?

import random
import chess
import chess.polyglot as book
from evaluate import *

searched_position_evals = {}

def choose_move(board, depth, is_max):
  # TODO: endgame database
  best_move = ""
  best_eval = float('inf')
  if not is_max: best_eval *= -1
  if check_opening_book(board)[0]: return check_opening_book(board)[1].uci()
  for move in list(board.legal_moves):
    print(f"evaluating {move}")
    board.push_uci(move.uci())
    eval = minimax(board, depth, board.turn == chess.WHITE)
    if is_max: best_eval = max(best_eval, eval) 
    else: best_eval = min(best_eval, eval)
    if best_eval == eval: best_move = move
    board.pop()
  return best_move

def check_opening_book(board):
  with book.open_reader("assets/openings.bin") as reader:
    if len(list(reader.find_all(board))) == 0:
      return (False, "")
    else:
      return (True, list(reader.find_all(board))[random.choice(range(0, len(list(reader.find_all(board)))))].move)

def minimax(board, depth, is_max):
  if depth == 0: 
    return evaluate(board)
  elif board.fen in searched_position_evals: 
    board.pop()
    return searched_position_evals[board.fen]
  else:
    if is_max:
      max_eval = -float('inf')
      for move in list(board.legal_moves):
        board.push_uci(move.uci())
        searched_eval = minimax(board, depth - 1, False)
        searched_position_evals[board.fen] = searched_eval
        max_eval = max(max_eval, searched_eval)
        board.pop()
      return max_eval
    else:
      min_eval = float('inf')
      for move in list(board.legal_moves):
        board.push_uci(move.uci())
        searched_eval = minimax(board, depth - 1, True)
        searched_position_evals[board.fen] = searched_eval
        min_eval = min(min_eval, searched_eval)
        board.pop()
      return min_eval

print(choose_move(chess.Board("r1bqkb1r/pp2pppp/2n1p2n/2p5/3P4/7N/PPP2PPP/RNBQKB1R b KQkq - 2 5"), 3, False))

Upvotes: 0

Views: 72

Answers (1)

ferdy
ferdy

Reputation: 5014

Comment out the board.pop() in the following.

def minimax(board, depth, is_max):
  if depth == 0: 
    return evaluate(board)
  elif board.fen in searched_position_evals: 
    # board.pop()
    return searched_position_evals[board.fen]
...

Upvotes: 1

Related Questions