7.6. How Do You Kill Off Those Poor Little Devils?

If you look at Swarm examples for any amount of time, you can't help but run into objects that get dropped. Little "helper objects" like indexes for lists are created and just as readily discarded with the command:

  [someIndexName drop];

If everything goes the way it is supposed to, this should take the object out of memory and free that memory for the program to reuse.

What if the objects inside your simulation are supposed to be born and killed through time? The Swarm bug tutorial mainly focuses on models in which a population of actors is created at the outset and those individuals remain in existence throughout the length of the program. What if we wanted code to model a world in which the happy HeatBugs could reproduce themselves, or what if the unhappy ones could die and be freed from their never ending search for a place neither too cool or too hot?

The Swarm SugarScape model provides an excellent example of a way to manage the birth and death of agents in an on-going model. The sss model's ModelSwarm.m file contains the critical ingredients. It has a method addNewRandomAgent which does what spawnOneBug does--it includes all the commands that create an instance of a SwarmObject and initializes it. sss also provides a handy structure to kill off agents and replace them with new ones. This is managed in a three stage process. The model swarm creates a Swarm list object called reaperQueue. When an event occurs that forces an object below the survival threshold, then that object is added to the reaperQueue by the agentDeath method. Then the model Swarm's schedule includes a command that removes the dead agents from the reaperQueue. The reapAgents method transverses the list of agents who are to die, it removes them from the list of active agents and then tells them to drop themselves from memory.

- agentDeath: (SugarAgent *)agent 
{
  [reaperQueue addLast: agent];
  if (replacement)				  // Replacement rule R (p.32)
    [self addNewRandomAgent];
  return self;
}

// remove all the agents on the reaperQueue from the agentList
// This allows us to defer the death of an agent until it's safe to
// remove it from the list.
- reapAgents 
{
  id index, agent;

  index = [reaperQueue begin: [self getZone]] ;
  while ((agent = [index next])) {
    [agentList remove: agent];
    [agent drop];
  }
  [reaperQueue removeAll];
  [index drop];
  return self;
}