'Return corresponding observations, actions, rewards, terminal status,
and next_observations for batch_size randomly chosen state transitions.'

def random_batch(self, batch_size):

    observations = np.zeros(((batch_size, self.concat_length) + self.observation_shape), dtype=self.observation_dtype)
    actions = np.zeros((batch_size, self.action_dim), dtype=self.action_dtype)
    rewards = np.zeros((batch_size,), dtype=floatX)
    terminals = np.zeros((batch_size,), dtype='bool')
    if (self.extras is not None):
        extras = np.zeros(((batch_size,) + self.extras.shape[1:]), dtype=self.extras.dtype)
        next_extras = np.zeros(((batch_size,) + self.extras.shape[1:]), dtype=self.extras.dtype)
    else:
        extras = None
        next_extras = None
    next_observations = np.zeros(((batch_size, self.concat_length) + self.observation_shape), dtype=self.observation_dtype)
    next_actions = np.zeros((batch_size, self.action_dim), dtype=self.action_dtype)
    count = 0
    while (count < batch_size):
        index = self.rng.randint(self.bottom, ((self.bottom + self.size) - self.concat_length))
        initial_indices = np.arange(index, (index + self.concat_length))
        transition_indices = (initial_indices + 1)
        end_index = ((index + self.concat_length) - 1)
        if np.any(self.terminals.take(initial_indices[0:(-1)], mode='wrap')):
            continue
        observations[count] = self.observations.take(initial_indices, axis=0, mode='wrap')
        actions[count] = self.actions.take(end_index, mode='wrap')
        rewards[count] = self.rewards.take(end_index, mode='wrap')
        terminals[count] = self.terminals.take(end_index, mode='wrap')
        if (self.extras is not None):
            extras[count] = self.extras.take(end_index, axis=0, mode='wrap')
            next_extras[count] = self.extras.take(transition_indices, axis=0, mode='wrap')
        next_observations[count] = self.observations.take(transition_indices, axis=0, mode='wrap')
        next_actions[count] = self.actions.take(transition_indices, axis=0, mode='wrap')
        count += 1
    if (not self.concat_observations):
        observations = np.squeeze(observations, axis=1)
        next_observations = np.squeeze(next_observations, axis=1)
    return dict(observations=observations, actions=actions, rewards=rewards, next_observations=next_observations, next_actions=next_actions, terminals=terminals, extras=extras, next_extras=next_extras)
