def to_move(cls, position, san): san = str(san) # Castling moves. if san == "O-O" or san == "O-O-O": # TODO: Support Chess960, check the castling moves are valid. rank = 1 if position.fen.turn == "w" else 8 if san == "O-O": return Move( source=Square.from_rank_and_file(rank, 'e'), target=Square.from_rank_and_file(rank, 'g')) else: return Move( source=Square.from_rank_and_file(rank, 'e'), target=Square.from_rank_and_file(rank, 'c')) # Regular moves. else: matches = cls.san_regex.match(san) if not matches: raise ValueError("Invalid SAN: %s." % repr(san)) if matches.group(1): klass = Piece.klass(matches.group(1).lower()) else: klass = PAWN piece = Piece.from_klass_and_color(klass, position.fen._to_move) target = Square(matches.group(4)) source = None for m in position.get_legal_moves(): if position._pieces[m.source._x88] != piece or m.target != target: continue if matches.group(2) and matches.group(2) != m.source.file: continue if matches.group(3) and matches.group(3) != str(m.source.rank): continue # Move matches. Assert it is not ambiguous. if source: raise MoveError( "Move is ambiguous: %s matches %s and %s." % san, source, m) source = m.source if not source: raise MoveError("No legal move matches %s." % san) return Move(source, target, matches.group(5) or None)
def to_move(cls, position, san): san = str(san) # Castling moves. if san == "O-O" or san == "O-O-O": # TODO: Support Chess960, check the castling moves are valid. rank = 1 if position.fen.turn == "w" else 8 if san == "O-O": return Move(source=Square.from_rank_and_file(rank, 'e'), target=Square.from_rank_and_file(rank, 'g')) else: return Move(source=Square.from_rank_and_file(rank, 'e'), target=Square.from_rank_and_file(rank, 'c')) # Regular moves. else: matches = cls.san_regex.match(san) if not matches: raise ValueError("Invalid SAN: %s." % repr(san)) if matches.group(1): klass = Piece.klass(matches.group(1).lower()) else: klass = PAWN piece = Piece.from_klass_and_color(klass, position.fen._to_move) target = Square(matches.group(4)) source = None for m in position.get_legal_moves(): if position._pieces[ m.source._x88] != piece or m.target != target: continue if matches.group(2) and matches.group(2) != m.source.file: continue if matches.group(3) and matches.group(3) != str(m.source.rank): continue # Move matches. Assert it is not ambiguous. if source: raise MoveError( "Move is ambiguous: %s matches %s and %s." % san, source, m) source = m.source if not source: raise MoveError("No legal move matches %s." % san) return Move(source, target, matches.group(5) or None)
def test_from_rank_and_file(self): square = Square.from_rank_and_file('1', 'a') self.assertEqual('a1', str(square))