Swarm Project: Part 3

Classes and Objects

For the third deliverable of your Swarm Project, you will modify your 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 if you have not done so already.
  3. Make sure you understand mutable structures and vectors as described in Section 40 and onward. You will need these for this final deliverable.
Bug Class and Objects

Apply the encapsulation techniques from Sections 39 through 41 to create a class, or interface, for a bug. The primary services that a bug must provide include: draw-self and update-self. To draw itself, the bug need only encapsulate its location and velocity vectors and its type and color so that it can draw a dot and a pointer in the appropriate color. However, to update itself, the bug needs to be able to determine its neighbors. Once it identifies the bugs in its neighborhood, it also needs to access the locations and velocities of each respective neighbor. Also, for reasons that will become apparent, we also need access to the type of a given bug. Thus, the bug interface must also support accessors for location, velocity, and type. Thus, we have the redefinition of a bug according to the following:
A bug is an interface:

  1. 'draw :: image -> image
  2. 'update-vel :: swarm -> (void)
  3. 'move :: (void)
  4. 'loc :: posn
  5. 'vel :: posn
  6. 'type :: symbol
We still define a swarm as a (listof bug), but now we are now talking about bug interfaces, or instances, rather than the structures we defined in deliverables 1 and 2. Rewrite your existing functions, such as draw-bug, update-bug, etc., to utilize this new formulation. Note, bug instances will support the various services, but you should still have top-level functions such as update-bug that consumes a bug and a swarm, or draw-bug that consumes a bug and an image.

Objects are instances of a pattern encoded in a class. These instances are generally intended to be somewhat persistent. In our case, you will create a swarm of bug instances at the beginning and then they will modify, or mutate themselves in response to messages that exercise the update service. Your constructor should consume a bug's initial location, velocity, type and color.

Bug Types and Species-selective Swarming

We want a bug to swarm with other bugs of its own type, but avoid bugs of a different type. When checking for neighbors, you will now also need to check for type. In addition, you will also need to be able to find neighbors of the other type. (Think about abstracting these.)

When considering bugs of its own type, a bug will use alignment, cohesion, and separation, much as before. But when considering neighbors of a different type, it will compute a separate separation vector and this will be included as a distinct contribution to the overall steering update. 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 efficiency improvements. When you find and make an efficiency improvement, be sure to include a comment describing what you did and why. To get you started, look for repeated computations -- especially computations that involve recursion or maps, folds, etc. Another clue is to avoid expensive operations such as sqrt or trig functions. You can also reduce your need for garbage collection by only creating new lists, posns or other instances of structures when absolutely necessary. (Note, you should not be creating bugs except to create the initial swarm for big-bang.

You can eyeball your progress by the visual flash as you animate a large swarm. You can also use the time function for your satisfaction. (I may use time to compare your time with mine on the same swarm for certain operations such as update.) 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., update-swarm), you will need to create a wrapper.


For this final project deliverable, you should have working code that implements:

  1. Functionality including everything from deliverable 2 (i.e., swarming and edge avoidance). Exceptions include the addition of a swarm argument to the update-bug function.
  2. Using the new interface definition of bugs described above, instantiate three or more different bug species, or types, that swarm independently and tend to avoid each other. For the purposes of this project, you should never create a new instance of a bug once the simulation has started. That is, bugs are persistent objects.
  3. Your bug constructor must conform to the following contract: make-bug : posn posn symbol symbol, where the two posns represent the new bug's initial location and velocity respectively, and the two symbols represent the bug's species and color respectively. You are welcome to provide additional constructors as wrappers but this one is required at a minimum.
  4. Improved efficiency sufficient to animate a swarm of three species of bugs with each type having about 30-40 bugs each (on the order of 100 bugs).


To grade this deliverable, I will review your code (including contracts, purpose statements, indentation, etc.) and I will run big-bang with my own swarm. It is important that you follow the instructions carefully.