code: def a2s_rules(server_addr, timeout=2, challenge=0):
      
      ss = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
      ss.connect(server_addr)
      ss.settimeout(timeout)
  
      # request challenge number
      if challenge in (-1, 0):
          ss.send(_pack('<lci', -1, b'V', challenge))
          try:
              _, header, challenge = _unpack_from('<lcl', ss.recv(512))
          except:
              ss.close()
              raise
  
          if header != b'A':
              raise RuntimeError("Unexpected challenge response")
  
      # request player info
      ss.send(_pack('<lci', -1, b'V', challenge))
  
      try:
          data = StructReader(_handle_a2s_response(ss))
      finally:
          ss.close()
  
      header, num_rules = data.unpack('<4xcH')
  
      if header != b'E':
          raise RuntimeError("Invalid reponse header - %s" % repr(header))
  
      rules = {}
  
      while len(rules) != num_rules:
          name = data.read_cstring()
          value = data.read_cstring()
  
          if _re_match(r'^\-?[0-9]+$', value):
              value = int(value)
          elif _re_match(r'^\-?[0-9]+\.[0-9]+$', value):
              value = float(value)
  
          rules[name] = value
  
      return rules
docs: Get rules from server
  
      :param server_addr: (ip, port) for the server
      :type  server_addr: tuple
      :param timeout: (optional) timeout in seconds
      :type  timeout: float
      :param challenge: (optional) challenge number
      :type  challenge: int
      :raises: :class:`RuntimeError`, :class:`socket.timeout`
      :returns: a list of players
      :rtype: :class:`list`