docs: def best_response(self, opponents_actions, tie_breaking='smallest',
                        payoff_perturbation=None, tol=None, random_state=None):
          """
          Return the best response action(s) to `opponents_actions`.
  
          Parameters
          ----------
          opponents_actions : scalar(int) or array_like
              A profile of N-1 opponents' actions, represented by either
              scalar(int), array_like(float), array_like(int), or
              array_like(array_like(float)). If N=2, then it must be a
              scalar of integer (in which case it is treated as the
              opponent's pure action) or a 1-dimensional array of floats
              (in which case it is treated as the opponent's mixed
              action). If N>2, then it must be an array of N-1 objects,
              where each object must be an integer (pure action) or an
              array of floats (mixed action).
  
          tie_breaking : str, optional(default='smallest')
              str in {'smallest', 'random', False}. Control how, or
              whether, to break a tie (see Returns for details).
  
          payoff_perturbation : array_like(float), optional(default=None)
              Array of length equal to the number of actions of the player
              containing the values ("noises") to be added to the payoffs
              in determining the best response.
  
          tol : scalar(float), optional(default=None)
              Tolerance level used in determining best responses. If None,
              default to the value of the `tol` attribute.
  
          random_state : int or np.random.RandomState, optional
              Random seed (integer) or np.random.RandomState instance to
              set the initial state of the random number generator for
              reproducibility. If None, a randomly initialized RandomState
              is used. Relevant only when tie_breaking='random'.
  
          Returns
          -------
          scalar(int) or ndarray(int, ndim=1)
              If tie_breaking=False, returns an array containing all the
              best response pure actions. If tie_breaking='smallest',
              returns the best response action with the smallest index; if
              tie_breaking='random', returns an action randomly chosen
              from the best response actions.
  
          """
          if tol is None:
              tol = self.tol
  
          payoff_vector = self.payoff_vector(opponents_actions)
          if payoff_perturbation is not None:
              try:
                  payoff_vector += payoff_perturbation
              except TypeError:  # type mismatch
                  payoff_vector = payoff_vector + payoff_perturbation
  
          best_responses = \
              np.where(payoff_vector >= payoff_vector.max() - tol)[0]
  
          if tie_breaking == 'smallest':
              return best_responses[0]
          elif tie_breaking == 'random':
              return self.random_choice(best_responses,
                                        random_state=random_state)
          elif tie_breaking is False:
              return best_responses
          else:
              msg = "tie_breaking must be one of 'smallest', 'random', or False"
              raise ValueError(msg)