Introduction to Computer Science I Term
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
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
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,
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,
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
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
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
Everything from deliverable 2 (i.e., swarming and edge avoidance)
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.
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.