0

I am creating a chess game in Python for a school project, but don't know how to check if a move is legal without causing a stack overflow.

  1. My algorithm works by making the move
  2. Checking if the king is now in check (by seeing if the king's position is in a piece's legal moves)
  3. Undoing the move and checking the next

If any move places the king in check, the move is illegal, so I don't return it.

I have defined the Board as a 2d list:

[[None for i in range(8)] for j in range(8)]

with pieces on each correct position, and I have defined a method in each piece class to return a list of legal moves. However, I don't know how to check if a move puts the king in check, thus meaning it is illegal. I tried by making a move, then calling the in_check method:

def in_check(self, colour):
    king_pos = None
    for piece in pieces:
      if isinstance(piece, King) and piece.colour == colour:
        king_pos = piece.pos
        break

    return bool([piece for piece in pieces if king_pos in piece.legal_moves(self.board.board)])

to see if it put the king in check, but that in turn calls each piece's legal_moves method:

new_legal_moves = []
for move in legal:
    g.board.move_piece(self.pos, move)
    if not g.in_check(self.colour):
        new_legal_moves.append(move)

    g.board.move_piece(move, self.pos)

    return new_legal_moves

How do I avoid avoid infinite recursion?

Added the rest of my code here: https://pastebin.com/GP4z5KuX

Freddie
  • 1
  • 2
  • 1
    you need to share full code in order for SO community to replicate. – sahasrara62 Feb 21 '23 at 11:53
  • Let's say you check legal move of a white piece then according to the rules the black pieces which could reach the white king don't have to care if their moves would bring the black king into check because they don't actually move. – Michael Butscher Feb 21 '23 at 11:54
  • This is pretty good. A simple solution is to consider that putting yourself in check is a very special way for a move to be be illegal. So you can have two separate methods `piece.legal_moves()` and `piece.basic_legal_moves()`, such that `piece.basic_legal_moves()` doesn't care about checks, and only `piece.legal_moves()` filters out the moves that put yourself in check. – Stef Feb 21 '23 at 14:48
  • And then inside `in_check` your return `return bool([piece for piece in pieces if king_pos in piece.basic_legal_moves(self.board.board)])` – Stef Feb 21 '23 at 14:49
  • Also, you could replace `def in_check(self, colour):` with `def in_check(self, colour, king_pos = None):`; and then you start with `if king_pos is None: king_pos = next(piece for piece in pieces if isinstance(piece, King) and piece.colour == colour)`. This allows you to pass `king_pos` as argument to `in_check`. This way you don't need to 1) Make the move 2) Call `in_check` 3) Undo the move; instead you can call `in_check` directly and tell it where the King *would* be. – Stef Feb 21 '23 at 14:51

0 Answers0