docs: def is_nash(self, action_profile, tol=None):
          """
          Return True if `action_profile` is a Nash equilibrium.
  
          Parameters
          ----------
          action_profile : array_like(int or array_like(float))
              An array of N objects, where each object must be an integer
              (pure action) or an array of floats (mixed action).
  
          tol : scalar(float)
              Tolerance level used in determining best responses. If None,
              default to each player's `tol` attribute value.
  
          Returns
          -------
          bool
              True if `action_profile` is a Nash equilibrium; False
              otherwise.
  
          """
          if self.N == 2:
              for i, player in enumerate(self.players):
                  own_action, opponent_action = \
                      action_profile[i], action_profile[1-i]
                  if not player.is_best_response(own_action, opponent_action,
                                                 tol):
                      return False
  
          elif self.N >= 3:
              for i, player in enumerate(self.players):
                  own_action = action_profile[i]
                  opponents_actions = \
                      tuple(action_profile[i+1:]) + tuple(action_profile[:i])
  
                  if not player.is_best_response(own_action, opponents_actions,
                                                 tol):
                      return False
  
          else:  # Trivial case with self.N == 1
              if not self.players[0].is_best_response(action_profile[0], None,
                                                      tol):
                  return False
  
          return True