docs: def boltzmann_exploration(actions, utilities, temperature, action_counter):
      '''returns an action with a probability depending on utilities and temperature'''
      utilities = [utilities[x] for x in actions]
      temperature = max(temperature, 0.01)
      _max = max(utilities)
      _min = min(utilities)
      if _max == _min:
          return random.choice(actions)
  
      utilities = [math.exp(((u - _min) / (_max - _min)) / temperature) for u in utilities]
      probs = [u / sum(utilities) for u in utilities]
      i = 0
      tot = probs[i]
      r = random.random()
      while i < len(actions) and r >= tot:
          i += 1
          tot += probs[i]
      return actions[i]