code: def _nonterminal_experience(
      self,
      *,
      parallel,
      buffer_start,
      buffer_index,
      reward_horizon,
      num_complete,
      reward_discount,
  ):
      # (similar to _terminal_experience_parallel)
      one = tf_util.constant(value=1, dtype="int")
      capacity = tf_util.constant(
          value=self.buffer_capacity, dtype="int"
      )
  
      # Whether to predict horizon values now
      if self.predict_horizon_values != "early":
          assert self.trace_decay.is_constant(value=1.0)
          horizon_values = tf_util.zeros(
              shape=tf.expand_dims(input=num_complete, axis=0),
              dtype="float",
          )
  
      else:
          # Baseline horizon
          baseline_horizon = self.baseline.past_horizon(on_policy=True)
          if self.trace_decay.is_constant(value=1.0):
              assertion = tf.debugging.assert_less_equal(
                  x=baseline_horizon,
                  y=reward_horizon,
                  message="Baseline on-policy horizon greater than reward estimation horizon "
                  'currently not supported if prediction_horizon_values = "early".',
              )
          else:
              zero = tf_util.constant(value=0, dtype="int")
              assertion = tf.debugging.assert_less_equal(
                  x=baseline_horizon,
                  y=zero,
                  message="Baseline on-policy horizon currently not supported if "
                  "trace_decay != 1.0.",
              )
  
          with tf.control_dependencies(control_inputs=(assertion,)):
              # Index range to gather from buffers
              if self.trace_decay.is_constant(value=1.0):
                  # Only indices relevant for horizon values
                  indices = tf.range(
                      start=(
                          buffer_start
                          + reward_horizon
                          - baseline_horizon
                      ),
                      limit=buffer_index,
                  )
                  ints_end = num_complete
                  auxs_start = baseline_horizon
                  horizons_start = tf.range(num_complete)
                  horizons_length = tf.fill(
                      dims=(num_complete,),
                      value=(baseline_horizon + one),
                  )
              else:
                  # All indices
                  indices = tf.range(
                      start=(buffer_start + one), limit=buffer_index
                  )
                  ints_end = None
                  auxs_start = None
                  horizons_start = tf.range(
                      buffer_index - buffer_start - one
                  )
                  horizons_length = tf.ones_like(input=horizons_start)
              indices = tf.math.mod(x=indices, y=capacity)
  
              # Return-sequence per timestep, as horizons indexing tensor
              horizons = tf.stack(
                  values=(horizons_start, horizons_length), axis=1
              )
  
              # Gather states
              function = lambda x: tf.gather(
                  params=x[parallel], indices=indices
              )
              states = self.states_buffer.fmap(
                  function=function, cls=TensorDict
              )
  
              # Gather internals, only for return-sequence start
              function = lambda x: tf.gather(
                  params=x[parallel], indices=indices[:ints_end]
              )
              key = "baseline" if self.separate_baseline else "policy"
              if len(self.internals_spec[key]) > 0:
                  internals = self.internals_buffer[key].fmap(
                      function=function, cls=TensorDict
                  )
              else:
                  internals = TensorDict()
  
              # Gather auxiliaries (and actions), only for return-sequence end
              function = lambda x: tf.gather(
                  params=x[parallel], indices=indices[auxs_start:]
              )
              auxiliaries = self.auxiliaries_buffer.fmap(
                  function=function, cls=TensorDict
              )
  
              # Predict values
              if self.predict_action_values:
                  # TODO: option to re-sample action deterministically?
                  actions = self.actions_buffer.fmap(
                      function=function, cls=TensorDict
                  )
                  values = self.baseline.action_value(
                      states=states,
                      horizons=horizons,
                      internals=internals,
                      auxiliaries=auxiliaries,
                      actions=actions,
                  )
              else:
                  values = self.baseline.state_value(
                      states=states,
                      horizons=horizons,
                      internals=internals,
                      auxiliaries=auxiliaries,
                  )
  
              # Horizon values
              if self.trace_decay.is_constant(value=1.0):
                  horizon_values = values
              else:
                  horizon_values = values[reward_horizon - one :]
  
      # Gather all rewards (incl return-horizon) from buffer
      indices = tf.range(start=buffer_start, limit=(buffer_index - one))
      indices = tf.math.mod(x=indices, y=capacity)
      reward = tf.gather(
          params=self.reward_buffer[parallel], indices=indices
      )
  
      # Recursive return
      if self.trace_decay.is_constant(value=1.0):
          # Discounted cumulative sum
          def recursive_return(next_return, index):
              return (
                  reward[index : index + num_complete]
                  + reward_discount * next_return
              )
  
      else:
          # TD-lambda
          one_float = tf_util.constant(value=1.0, dtype="float")
          trace_decay = self.trace_decay.value()
  
          def recursive_return(next_return, index):
              next_value = values[index : index + num_complete]
              next_return = (
                  one_float - trace_decay
              ) * next_value + trace_decay * next_return
              return (
                  reward[index : index + num_complete]
                  + reward_discount * next_return
              )
  
      reward = tf.foldr(
          fn=recursive_return,
          elems=tf.range(reward_horizon),
          initializer=horizon_values,
      )
  
      # Gather other values of completed timesteps from buffers
      indices = tf.range(
          start=buffer_start, limit=(buffer_start + num_complete)
      )
      indices = tf.math.mod(x=indices, y=capacity)
      function = lambda x: tf.gather(
          params=x[parallel], indices=indices
      )
      states = self.states_buffer.fmap(
          function=function, cls=TensorDict
      )
      internals = self.internals_buffer.fmap(
          function=function, cls=TensorDict
      )
      auxiliaries = self.auxiliaries_buffer.fmap(
          function=function, cls=TensorDict
      )
      actions = self.actions_buffer.fmap(
          function=function, cls=TensorDict
      )
      terminal = function(self.terminal_buffer)
  
      # Store completed timesteps
      experienced = self.memory.enqueue(
          states=states,
          internals=internals,
          auxiliaries=auxiliaries,
          actions=actions,
          terminal=terminal,
          reward=reward,
      )
  
      # Increment buffer start index
      with tf.control_dependencies(control_inputs=(indices,)):
          updates = tf.expand_dims(input=num_complete, axis=0)
          indices = tf.expand_dims(
              input=tf.expand_dims(input=parallel, axis=0), axis=1
          )
          value = tf.tensor_scatter_nd_add(
              tensor=self.buffer_start, indices=indices, updates=updates
          )
          assignment = self.buffer_start.assign(value=value)
          # sparse_delta = tf.IndexedSlices(values=num_complete, indices=parallel)
          # assignment = self.buffer_start.scatter_add(sparse_delta=sparse_delta)
  
      return tf.group((experienced, assignment))
  
imports: import logging
  import tensorflow
  from tensorforce import TensorforceError
  from tensorforce.core import ModuleDict, memory_modules, optimizer_modules, parameter_modules, SignatureDict, TensorDict, TensorSpec, TensorsSpec, tf_function, tf_util, VariableDict
  from tensorforce.core.models import Model
  from tensorforce.core.networks import Preprocessor
  from tensorforce.core.objectives import objective_modules
  from tensorforce.core.policies import policy_modules, StochasticPolicy
label_desc: Use image node_id 14 for calling the TensorforceModel obj's underlying member method code with example usage: obj._nonterminal_experience() and returns: tf, unknown, unknown