The goal of this lab is to practice using the strategy pattern.
Today we go back to the predator/prey simulation. This time we will be adjusting the algorithm the animals use to find prey and elude predators.
The current version of the simulation can be copied from a subdirectory of the course public directory.
cp -r /homes/tvandrun/Public/cs245/lab12/* .
(The -r
flag is for "recursive", and it indicates that
entire directories should be copied.)
The algorithm that all animals use is to scan the the visible area around it, starting with the lower left hand corner, and given the first thing seen that is either a predator or a prey,
We have seen the effects of this. Rabbits congregate on the lower left can corner of a patch of clover-- either moving right into a predator's mouth even though a there's a predator-free clover-filled area nearby, or forming a swarm which moves from left to right. Animals lower on the food chain get away from predators above and to the left of them, but are practically blind to those below or to the right. Predators chase rabbits to the left of the board, or compete with each other for the same rabbit, when a swarm is only a few squares to the right. These animals could help their survival and the survival of their species if they only had smarter behavior.
In the current version of the simulation, the behavior of the scan method is mostly delegated to a strategy.
First, you will become familiar to the changes in the code base.
The files relevant for this lab (ie, what you will need to know and possibly change)
are Animal
, ScanStrategy
,
StupidStrategy
, Position
, and
the animal subclasses.
Re-familiarize yourself with Animal
.
Most of the functionality has been pulled up here in a
variety of helper methods.
The information about speed, growth rate, etc, is almost all
that is left to the subclasses.
What has changed in Animal
(since the last iteration of this example) is that it has
an instance variable of type ScanStrategy
,
which the scan()
method make use of.
ScanStrategy
is an interface with one
method, which takes as parameters all the information
necessary to make a scan decision and pick a position to which to move..
Notice that findPosition()
als need a reference to the
Animal
calling it.
StupidStrategy
is the old scan algorithm we've used before,
now encapsulated in a class implementing ScanStrategy
.
Since findPosition()
must return both an x
and a y coordinate, we have the simple class Position
encapsulating those two things.
Finally, the Animal
subclasses pick a strategy
(right now there's only one) in their constructors.
It is conceivable that you will want some classes to have some of their
instances with one strategy, others with another.
In that case, the constructor will somehow need to pick which one.
Your task is to encode new behavior for the animals by writing new
ScanStrategy
classes.
Some things to think about:
weight()
is a public method, a predator can
pick its prey based on which is the fattest.
StupidStrategy
is a singleton, but Strateg
ies
don't have to be.
To remember who you're chasing, the strategy might need state.
Experiment. Start out by observing the current behavior. There basically are two possible outcomes: The clover wins, because all the rabbits are eaten before the clover is eaten, and then the clover expands with nothing to stop it; or, the rabbits win, by forming an unstoppable swarm that sweeps the clover off the map. I have found that if we hold constant the number of clover at 100, rabbits at 20, cougars at 1, and bears at 1 and vary the number of foxes, the boundary is somewhere around 12 foxes. At 10 foxes, the rabbits almost always win. At 15 foxes, the clover almost always wins.
When you write new Strategy classes, you'll have to change
the constructors of the animal classes in order to use them.
This may also require changing the place in PredPrey
where the constructors are called (ask for help if you need it).
You may also want to makes changes to the animals' getColor()
methods so that, for example, if you have two different strategies that
rabbits are using, you can trace which rabbits are using which.
To turn in: Leave the code in the appropriate directory. Make sure it is documented in a way that makes its intent clear.