Given a sequence of moves, returns a string representing the sequence
        in standard algebraic notation (e.g., ``1. e4 e5 2. Nf3 Nc6`` or
        ``37...Bg6 38. fxg6``).

        The board will not be modified as a result of calling this.

        :raises: :exc:`ValueError` if any moves in the sequence are illegal.

def variation_san(self, variation: Iterable[Move]) -> str:
        """
        Given a sequence of moves, returns a string representing the sequence
        in standard algebraic notation (e.g., ``1. e4 e5 2. Nf3 Nc6`` or
        ``37...Bg6 38. fxg6``).

        The board will not be modified as a result of calling this.

        :raises: :exc:`ValueError` if any moves in the sequence are illegal.
        """
        board = self.copy(stack=False)
        san = []

        for move in variation:
            if not board.is_legal(move):
                raise ValueError("illegal move {} in position {}".format(move, board.fen()))

            if board.turn == WHITE:
                san.append("{}. {}".format(board.fullmove_number, board.san(move)))
            elif not san:
                san.append("{}...{}".format(board.fullmove_number, board.san(move)))
            else:
                san.append(board.san(move))

            board.push(move)

        return " ".join(san)