For the second deliverable, you will implement the elements of actual swarm behavior so that your bugs will move in ways that reflect the movements of the other bugs. Swarming or flocking behavior relies on a population of critters (such as bugs) that are aware of and respond to other critters in their respective neighborhoods. Each critter steers left or right and speeds up or slows down based on the collective behaviors of its neighbors.
For this second deliverable, we will define neighborhoods for bugs and the features over neighborhoods that will be needed to determine the appropriate steering adjustments that give rise to swarming. The end goal is to arrive at the steering adjustment, which will be a vector that updates the current velocity vector. After reading the descriptions below, you may want to come back and read the sections on Separation, Cohesion and Alignment, as well as the section on Combining Behaviors, from this paper by Craig Reynolds.
In addition, we will refine our representation of a bug. Since we are anticipating bugs of different types (e.g., bees from different swarms), your bug data type should include fields type and color. In order to have everyone on the same page, you must use the following structure definition: (define-struct bug (loc vel type color)), where loc and vel are posns as before, type is a symbol, and color is a string.
We define the neighborhood of a bug to be that circular area surrounding and centered on the given bug out to the value of the global variable, NEIGHBORHOOD-RADIUS, excluding a wedge immediately behind the bug where it is not looking. The size of this excluded wedge is determined by another variable FIELD-OF-VIEW, which should be interpreted as an angle (in radians). (You should define these two global variables and use them throughout your code. I should be able to modify these values when grading your projects and then when I run your program the bugs' movements should reflect those changes accordingly.) The FIELD-OF-VIEW angle, deflecting to the left and right of the bug's current heading, defines how much of the circle is perceived by the bug. Essentially, bugs can see pretty much around them but not directly behind them with respect to the direction they are headed.
Given a bug and the neighborhood around it, the sub-swarm of bugs within the given bug's neighborhood are called neighbors.
Based on a set of neighbors for a given bug, you will implement three behaviors: separation, cohesion, and alignment. Bugs should avoid bumping into neighbors, essentially maintaining a ‘personal space’ separation around each bug. At the same time, bugs ‘want’ to stay close to the other bugs so as to travel in a cohesive group. In order to travel together in the group, the bugs want to align their speed and heading with their neighbors.
Each of the three behaviors -- separation, cohesion and alignment -- will be implemented by computing steering adjustment vectors that will be employed during each bug's update. That is, in your first deliverable you updated a bug's position by adding the velocity vector to its current position. Now, bugs' velocity vectors will be updated by adjustments based on the three behaviors. This updated velocity vector will be used to update the bug's position as before.
Separation. In order to implement separation, we will need to find the position offset (not just distance, but directional distance) from the given bug for each bug in the neighborhood. These vectors act as repelling forces and are scaled by the inverse-squares of the plain distances to each respective bug. Thus, a neighbor that is close to the bug will have a stronger repelling force than one that is just inside the NEIGHBOR-RADIUS. Given all the repelling forces for each bug in the neighborhood, the vectors are combined (summed) into a single separation steering vector.
Cohesion. In order to implement cohesion, we find the average position for all bugs in the neighborhood. This position is in some sense the place this bug wants to be. To generate a cohesion steering vector, we subtract our bug's current location from the desired location (i.e., the average location we found first).
Alignment. To implement alignment, we simply find the average velocity vector of all neighbors. This average is the desired (for the purposes of alignment) velocity vector. To generate an alignment steering vector, we subtract our bug's current velocity vector from the desired vector (i.e., the average we found first). The resulting vector, when added to our current velocity, would make the bug's velocity the same as the average of its neighbors.
Edge-avoidance Although we implemented our update such that bugs flying off one edge reappear at the other, we want bugs to avoid going off the edge. Thus, you will also implement an edge avoidance steering vector. Edge avoidance steering should be handled similarly to that of separation above. If an edge is ‘visible’ within the neighborhood, the edge-avoidance steering adjustment should produce a vector pointing away from the edge with a magnitude based on the inverse square of the distance to the edge. (Hint: treat the point of the edge that is nearest to the bug -- that is, in a perpendicular direction from the wall through the bug -- as a pseudo bug and create a separation vector based on that bug alone.)
Nominal-speed. Left to their own devices, the bugs in your swarm may all come to a halt. Consequently, the bugs in our swarms have an ‘innate drive’ to travel at a particular nominal speed. They will deviate from this in order avoid edges, align with other bugs, and so on. But there is always a push to go faster if they are currently moving slower than their nominal speed. Similarly, if they are traveling faster than their nominal speed (say, perhaps because of cohesion) then there is a contributing factor that wants to slow the bug down.
For your second project deliverable, you should define the global variables NEIGHBORHOOD-RADIUS and FIELD-OF-VIEW as described above. Revise your structure definition for bugs as described above. You must implement the following functions with their given signatures:
Finally, in order to implement the swarming required for this deliverable, you will need to modify your update-bug function so that the bug's new velocity takes into account the four steering vectors and the nominal speed vector implemented above. Your finished submission should be able to animate many bugs that start off randomly flying about and gradually cohere into an identifiable swarm.
To grade this deliverable, I will review your code (including contracts, purpose statements, indentation, etc.). I will run the four functions with my own swarm. It is important that you follow the instructions carefully. Remember to include the acknowledgment template at the top of your file. Submit your file with your user name in the title to Eureka before the deadline.