CS010 Introduction to Computer Science I
Term Project
Deliverable Three

Swarm and Flocking Behavior:
Classes and Objects
(last updated 11/22/2007)

For the third deliverable of the Swarm Project this semester, we will modify our program to use an object-oriented style; that is, we will use encapsulation and classes (what the text calls interfaces) as discussed in class and in the text (Part VIII, Sections 39-43). We will also be adding a few new features that should make the overall behavior more interesting.

Hints and Suggestions Before Starting
1. Before starting on this deliverable, make sure you simplify and streamline your second deliverable as much as you can. You will benefit from organizing your functions into groups that have related purposes.
2. If you had explored the extra links I had provided on the previous deliverables, you will have noticed that it is most effective to normalize all of the steering vectors and then weight them by their respective weights. I highly recommend you implement this approach.

Critter Class and Objects
Apply the encapsulation techniques from Sections 39 through 41 to create a class, or interface, for a critter. The primary services that a critter must provide include: draw-self, clear-self, and update-self. To draw and clear, the critter need only encapsulate its location and velocity vectors, its type and color so that it can draw a dot and a pointer in the appropriate color. However, to update itself, the critter needs to be able to determine its neighbors. Once it identifies its neighboring critters, it also needs to access the locations and velocities of each respective neighbor. Also, for reasons we will see, we also need access to the type of a given critter. Thus, the critter interface must also support accessors for location, velocity, and type. Thus, we have the redefinition of critter according to the following:
A critter is an interface:
1. 'draw:: true
2. 'clear:: true
3. 'update-vel:: swarm -> true
4. 'move:: void
5. 'loc:: posn
6. 'vel:: posn
7. 'type:: symbol

We still define a swarm as a (listof critter) but now we are now talking about critter interfaces or instances rather than the structures we used in deliverables 1 and 2. 

Rewrite your existing functions, such as draw-critter, clear-critter, update-critter, etc., to utilize this new formulation.

Objects are instances of a pattern encoded in a class. These instances are generally intended to be somewhat persistant. In our case, you will create a swarm of instances at the beginning and then they will modify, or mutate themselves in response to messages that are sent to them. Your constructor should consume at least a critter-type and a color. You may add other parameters if you want to provide type-specific qualities such as nominal speed, alien avoidance factor (how willing a critter would be to fly into a swarm of other critters), neighbor radius, field of view, etc.

Critter Types and Species-selective Swarming
We want a critter to swarm with other critters of its own type, but avoid critters of a different type.  When checking for neighbors, you will now also want to check for type. In addition, you will also need to be able to find neighbors of the other type. (Think about abstracting these.)

Basically, when considering critters of its own type, a critter will use alignment, cohesion, and separation, much as before.  But when considering neighbors of a different type, it will compute a separation vector and this will be included as a distinct contribution to the overall steering.  Naturally, it will need its own weight that is distinct from the separation weight (e.g., SEPARATION-W) that is used for basic swarming with one's own kind.


I am sending you on a treasure hunt for other efficiency improvements. When you find and make an efficiency improvement, be sure to place a comment starting with ";;E: " and followed by a short note of what you changed. One thing to look for are repeated computations -- especially computations that involve recursion or maps, folds, etc.  Another clue is to avoid expensive operations such as sqrt. You can also reduce your need for garbage collection by only creating new instances of structures or classes when absolutely necessary. 

You can eyeball your progress by the visual flash as you animate a swarm of a given size.  You can also use the time function for your satisfaction. (I will use time to compare your time with mine on the same swarm.) You are free to extend the data definitions if you think it will improve your efficiency. If you intend to change the contract of a primary function (e.g., animate-swarm), you probably want to create a wrapper.

For this final project deliverable, you should have working code that implements:
  1. Everything from deliverable 2 (i.e., swarming and edge avoidance)
  2. Using a class definition, instantiate three or more different critter species that swarm independently and tend to avoid each other. For the purposes of our project, you should never create a new instance of a critter once the simulation has started.
  3. Improved efficiency sufficient to animate a swarm of three types of critters of about a dozen critters each.
To grade this deliverable, I will review your code (including contracts, purpose statements, indentation, etc.) and I will run the animate-swarm with my own swarm. It is important that you follow the instructions carefully.