public void send(TreeFormationMessage msg) {
   // System.out.println(msg);
   if (msg.getType() == TreeFormationMessage.MessageType.JOIN) {
     if (groupIDMin == msg.getGroupIDMin() && groupIDMax == msg.groupIDMax) {
       // Message sent from a node in the same group
       msg.sender.send(
           new TreeFormationMessage(
               this, msg.sender, TreeFormationMessage.MessageType.REJECT, groupIDMax, groupIDMin));
       loopyNodes.add(msg.sender);
     } else {
       // Not from same group; OK to join.
       groupIDMax = Math.max(groupIDMax, msg.getGroupIDMax());
       groupIDMin = Math.min(groupIDMin, msg.getGroupIDMin());
       msg.sender.send(
           new TreeFormationMessage(
               this, msg.sender, TreeFormationMessage.MessageType.ACCEPT, groupIDMax, groupIDMin));
       internalNodes.add(msg.sender);
     }
   } else if (msg.getType() == TreeFormationMessage.MessageType.REJECT) {
     loopyNodes.add(msg.sender);
   } else if (msg.getType() == TreeFormationMessage.MessageType.ACCEPT) {
     groupIDMax = Math.max(groupIDMax, msg.getGroupIDMax());
     groupIDMin = Math.min(groupIDMin, msg.getGroupIDMin());
     for (TreeFormingAgent node : internalNodes) {
       node.send(
           new TreeFormationMessage(
               this, node, TreeFormationMessage.MessageType.NOTIFY, groupIDMax, groupIDMin));
     }
     internalNodes.add(msg.sender);
   } else if (msg.getType() == TreeFormationMessage.MessageType.NOTIFY) {
     groupIDMax = msg.getGroupIDMax();
     groupIDMin = msg.getGroupIDMin();
   }
 }
 public void initialise() {
   for (TreeFormingAgent neighbour : neighbours) {
     if (!internalNodes.contains(neighbour) && !loopyNodes.contains(neighbour)) {
       neighbour.send(
           new TreeFormationMessage(
               this, neighbour, TreeFormationMessage.MessageType.JOIN, groupIDMax, groupIDMin));
     }
   }
 }