def linear(x: float, target: float, span: float, symmetric = False) -> float:
  """Create a linearly sloped reward space.

  Args:
    x (float): Value to evaluate the reward space at.
    target (float): The value s.t. when x == target, this function 
      returns 1.
    span (float): The value s.t. when x >= target + span, this function returns 
      0. symmetric (bool, optional): If true, then this function works if x is 
      over or under target. Defaults to False.

  Returns:
    float: A value between 0 and 1. x == target evaluates to 1, x >= target +
      span evaluates to 0. Every value in between is evalulated as the linear
      interpolation between `target` and `span`.
  """
  if span == 0:
    return 1. if x == target else 0.

  x_delta = x - target
  
  if abs(x_delta) > abs(span):
    return 0.
  
  ratio = x_delta / span
  if not symmetric and ratio < 0:
    return 0
  
  return 1 - abs(ratio)