Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
if self.castling_rights | CASTLING_BLACK_KINGSIDE and not (F8 | G8) & self.occupied:
if not self.is_attacked_by(WHITE, E8) and not self.is_attacked_by(WHITE, F8) and not self.is_attacked_by(WHITE, G8):
yield Move(E8, F8)
# Castling long.
if self.castling_rights | CASTLING_BLACK_QUEENSIDE and not (B8 | C8 | D8) & self.occupied:
if not self.is_attacked_by(WHITE, C8) and not self.is_attacked_by(WHITE, D8) and not self.is_attacked_by(WHITE, E8):
yield Move(E8, C8)
# En passant moves.
movers = self.pawns & self.occupied_co[BLACK]
if self.ep_square:
moves = BB_PAWN_ATTACKS[WHITE][self.ep_square] & movers
while moves:
from_square, moves = next_bit(moves)
yield Move(from_square, self.ep_square)
# Pawn captures.
moves = shift_down_left(movers) & self.occupied_co[WHITE]
while moves:
to_square, moves = next_bit(moves)
from_square = to_square + 9
if rank_index(to_square) != 0:
yield Move(from_square, to_square)
else:
yield Move(from_square, to_square, QUEEN)
yield Move(from_square, to_square, KNIGHT)
yield Move(from_square, to_square, ROOK)
yield Move(from_square, to_square, BISHOP)
moves = shift_down_right(movers) & self.occupied_co[WHITE]
while moves:
# Queen moves.
movers = self.queens & self.occupied_co[self.turn]
while movers:
from_square, movers = next_bit(movers)
moves = self.queen_attacks_from(from_square) & ~self.occupied_co[self.turn]
while moves:
to_square, moves = next_bit(moves)
yield Move(from_square, to_square)
# King moves.
from_square = self.king_squares[self.turn]
moves = self.king_attacks_from(from_square) & ~self.occupied_co[self.turn]
while moves:
to_square, moves = next_bit(moves)
yield Move(from_square, to_square)
movers = self.pawns & self.occupied_co[BLACK]
if self.ep_square:
moves = BB_PAWN_ATTACKS[WHITE][self.ep_square] & movers
while moves:
from_square, moves = next_bit(moves)
yield Move(from_square, self.ep_square)
# Pawn captures.
moves = shift_down_left(movers) & self.occupied_co[WHITE]
while moves:
to_square, moves = next_bit(moves)
from_square = to_square + 9
if rank_index(to_square) != 0:
yield Move(from_square, to_square)
else:
yield Move(from_square, to_square, QUEEN)
yield Move(from_square, to_square, KNIGHT)
yield Move(from_square, to_square, ROOK)
yield Move(from_square, to_square, BISHOP)
moves = shift_down_right(movers) & self.occupied_co[WHITE]
while moves:
to_square, moves = next_bit(moves)
from_square = to_square + 7
if rank_index(to_square) != 0:
yield Move(from_square, to_square)
else:
yield Move(from_square, to_square, QUEEN)
yield Move(from_square, to_square, KNIGHT)
yield Move(from_square, to_square, ROOK)
yield Move(from_square, to_square, BISHOP)
if self.turn == WHITE:
single_moves = pawns << 8 & ~self.occupied
double_moves = single_moves << 8 & ~self.occupied & (BB_RANK_3 | BB_RANK_4)
else:
single_moves = pawns >> 8 & ~self.occupied
double_moves = single_moves >> 8 & ~self.occupied & (BB_RANK_6 | BB_RANK_5)
single_moves &= to_mask
double_moves &= to_mask
# Generate single pawn moves.
for to_square in scan_reversed(single_moves):
from_square = to_square + (8 if self.turn == BLACK else -8)
if square_rank(to_square) in [0, 7]:
yield Move(from_square, to_square, QUEEN)
yield Move(from_square, to_square, ROOK)
yield Move(from_square, to_square, BISHOP)
yield Move(from_square, to_square, KNIGHT)
else:
yield Move(from_square, to_square)
# Generate double pawn moves.
for to_square in scan_reversed(double_moves):
from_square = to_square + (16 if self.turn == BLACK else -16)
yield Move(from_square, to_square)
# Generate en passant captures.
if self.ep_square:
yield from self.generate_pseudo_legal_ep(from_mask, to_mask)
def parse_san(self, san):
# Castling.
if san in ("O-O", "O-O+", "O-O#"):
move = Move(E1, G1) if self.turn == WHITE else Move(E8, G8)
if self.kings & self.occupied_co[self.turn] & BB_SQUARES[move.from_square] and self.is_legal(move):
return move
else:
raise ValueError("Invalid SAN: Can not castle short.")
elif san in ("O-O-O", "O-O-O+", "O-O-O#"):
move = Move(E1, C1) if self.turn == WHITE else Move(E8, C8)
if self.kings & self.occupied_co[self.turn] & BB_SQUARES[move.from_square] and self.is_legal(move):
return move
else:
raise ValueError("Invalid SAN: Can not castle long.")
# Match normal moves.
match = SAN_REGEX.match(san)
if not match:
raise ValueError("Invalid SAN.")
# Get target square.
to_square = SQUARE_NAMES.index(match.group(4))
# Get the promotion type.
if not match.group(5):
promotion = NONE
def _from_chess960(self, chess960, from_square, to_square, promotion=None, drop=None):
if not chess960 and drop is None:
if from_square == E1 and self.kings & BB_E1:
if to_square == H1:
return Move(E1, G1)
elif to_square == A1:
return Move(E1, C1)
elif from_square == E8 and self.kings & BB_E8:
if to_square == H8:
return Move(E8, G8)
elif to_square == A8:
return Move(E8, C8)
return Move(from_square, to_square, promotion, drop)
from_square = bit_scan(movers)
while from_square != -1 and from_square is not None:
moves = self.queen_attacks_from(from_square) & ~self.occupied_co[self.turn]
to_square = bit_scan(moves)
while to_square != - 1 and to_square is not None:
yield Move(from_square, to_square)
to_square = bit_scan(moves, to_square + 1)
from_square = bit_scan(movers, from_square + 1)
if king:
# King moves.
from_square = self.king_squares[self.turn]
moves = self.king_attacks_from(from_square) & ~self.occupied_co[self.turn]
to_square = bit_scan(moves)
while to_square != - 1 and to_square is not None:
yield Move(from_square, to_square)
to_square = bit_scan(moves, to_square + 1)
def generate_pseudo_legal_ep(self, from_mask=BB_ALL, to_mask=BB_ALL):
if not self.ep_square or not BB_SQUARES[self.ep_square] & to_mask:
return
if BB_SQUARES[self.ep_square] & self.occupied:
return
capturers = (
self.pawns & self.occupied_co[self.turn] & from_mask &
BB_PAWN_ATTACKS[not self.turn][self.ep_square] &
BB_RANKS[4 if self.turn else 3])
for capturer in scan_reversed(capturers):
yield Move(capturer, self.ep_square)
def _from_chess960(self, chess960, from_square, to_square, promotion=None, drop=None):
if not chess960 and drop is None:
if from_square == E1 and self.kings & BB_E1:
if to_square == H1:
return Move(E1, G1)
elif to_square == A1:
return Move(E1, C1)
elif from_square == E8 and self.kings & BB_E8:
if to_square == H8:
return Move(E8, G8)
elif to_square == A8:
return Move(E8, C8)
return Move(from_square, to_square, promotion, drop)
# Generate pawn captures.
capturers = pawns
for from_square in scan_reversed(capturers):
targets = (
BB_PAWN_ATTACKS[self.turn][from_square] &
self.occupied_co[not self.turn] & to_mask)
for to_square in scan_reversed(targets):
if square_rank(to_square) in [0, 7]:
yield Move(from_square, to_square, QUEEN)
yield Move(from_square, to_square, ROOK)
yield Move(from_square, to_square, BISHOP)
yield Move(from_square, to_square, KNIGHT)
else:
yield Move(from_square, to_square)
# Prepare pawn advance generation.
if self.turn == WHITE:
single_moves = pawns << 8 & ~self.occupied
double_moves = single_moves << 8 & ~self.occupied & (BB_RANK_3 | BB_RANK_4)
else:
single_moves = pawns >> 8 & ~self.occupied
double_moves = single_moves >> 8 & ~self.occupied & (BB_RANK_6 | BB_RANK_5)
single_moves &= to_mask
double_moves &= to_mask
# Generate single pawn moves.
for to_square in scan_reversed(single_moves):
from_square = to_square + (8 if self.turn == BLACK else -8)