CSE 142 Summer 2001

Homework #6

Due: At the beginning of class, Monday, August 6, 2001

 

Purpose

The purpose of this assignment is to extend a program that implements an environmental simulation.  This assignment builds on previous assignments - defining classes, sending messages (calling methods), using collections - and introduces the following topics:
  1. Time driven simulations, including pseudo-random numbers
  2. Creating classes that implement interfaces
  3. Extending code written by someone else, which contains some code that might not even make sense at this point - but which doesn't need to be understood to complete the job at hand
We will evaluate your work both on functionality (does it work?) and quality (how well is the program written). This means doing your best in terms of commenting and using good names in your program.

Problem Statement

In March of 1989, the Exxon Valdez oil tanker ran aground in the Gulf of Alaska, rupturing many of its oil compartments and ultimately spilling 11 million gallons of North Slope crude oil into Prince William Sound. In this assignment, we'll simulate the impact of an oil spill such as the above on an environment. We'll provide you with the simulation engine and a few simulation classes, and ask you to modify the existing classes and to add a few new ones, such as genetically engineered bacteria that can eat oil.

Out of the box, we provide the following classes, and one interface:

  1. Thing - this interface defines the basic behaviors that must be implemented by all objects in our simulation.
  2. Environment - this is the core of the simulation. It maintains a collection of all Things. The simulation begins by adding a bunch of Things to the Environment, and then simulating the passage of time by asking all of the objects to perform their basic behaviors over and over again. Each cycle of the simulation has several phases:
    1. Display: all Things are asked to display themselves onto the screen
    2. Interaction: all Things asked if they wish to "consume" other things that are nearby. If so, the other Things are removed from the simulation.
    3. Spawning: all Things are asked if they wish to reproduce and given the chance to add new Things to the simulation.
    4. Movement: all Things are asked to move about the world.
  3. Tanker - this kind of Thing travels across the screen spilling OilBlobs into the environment.
  4. OilBlob - this kind of Thing floats around and kills (consumes) Fish and Algae.
  5. Algae - this kind of Thing just floats around and gets eaten.
  6. Fish - this kind of Thing swims around and eats Algae. When it eats enough Algae, it reproduces.

Instructions/Hints

  1. The online copy of this assignment web page has links to the starter files for the project.  You can obtain the .java source files individually: Environment.java, Thing.java, Tanker.java, Algae.java, OilBlob.java, and Fish.java.  Or you can obtain the same six files in a single executable zip file, hw6files.exe.  Double click on the zip file to extract the Java source files.
  2. Save the files in a folder and open the folder in BlueJ.  Here is a quick description of the files:
    1. Environment.java defines the Environment class and the main driver for the application. You'll only make minor modifications here, but you'll want to read the comments, because you'll need to use some of the methods.
    2. Thing.java an interface description for all Things.
    3. Tanker.java defines the Tanker class
    4. Algae.java defines the Algae class
    5. OilBlob.java defines the OilBlob class
    6. Fish.java defines the Fish class
  3. First, you'll want to get the application working fully. Compile the files, then create an instance of Environment and start the simulation by executing it's startSimulation() method. You should see a bunch of green and yellow dots moving around. These are Algae and Fish. Run it for a while and watch the statistics that are printed out. To stop the simulation before it finishes, you can open the debugger (in the View Menu), and hit the "Stop" button, and then the "Terminate" button.
  4. Next introduce a Tanker into the mix. Check out the go() method in the Environment class and uncomment the place where the Tanker gets added. Run the simulation again and look at the impact of the OilBlobs on the environment.
  5. Now modify the spawn() method for the Fish class. After eating 5 algae, it should add another Fish. Check out the Tanker class's spawn method for hints on how to do this.
  6. Now modify the spawn() method for the Algae class. Algae should simply reproduce every so often. It's up to you to figure out how to implement this. Warning: adding a new Algae every turn will swamp the simulation. Probably using a random number generator and just reproducing about one time in a thousand should give decent results.
  7. Now its time to invent oil eating bacteria. Create a class called PoisonEatingBacteria which consumes OilBlobs. These bacteria shouldn't reproduce and are essentially indestructable (nobody else eats it). At first, it should just wander randomly around the world eating any oil it encounters. You can start by just copying the code for one of the other kinds of things, like Algae, and modifying its methods. You'll then have to modify the go() method in the Environment class to add about 50 (or so) of these bacteria to the environment.
  8. Make your PoisonEating bacteria smarter. Using the thingsEast(), thingsWest(), etc methods on the Environment to help your bacteria "smell" if there is Oil in a given direction. If so, it should move in that direction. The trick here is that when the Poison eating bacteria is created, it needs to be told about the environment it lives in, so it can call Environment methods that return collections of neighboring objects.
  9. There's lots of flexibility for how smart you make your bacteria. It could check north, south, east, and west, and move to where there is the most oil.
  10. Finally, we want you to add at least one more kind of thing in the world. Be creative -- you could add birds (who eat Fish and are killed by OilBlobs), otters, cleanup workers (who remove Oil, but are killed by PoisonEatingBacteria), etc. 
  11. We may have a contest to see who makes the smartest PoisonEating bacteria, if there is sufficient interest.

Notes on Random Numbers

For a simulation to be interesting, the individual objects in the world should not all do exactly the same thing at the same time.  A standard technique for producing variations in behavior is to use a random number generator.  Java contains a class Random that provides this capability.  An instance of class Random provides methods that return a new value each time they are called.  The most useful one for this simulation is method nextInt, which takes an integer argument n, and returns a random number in the range 0 to n-1.  If you look at the various Thing classes like Fish, you'll see examples.  Fish, for instance, calculates how far to move on each tick of the clock by evaluating rand.nextInt(5)-2, which yields a number between -2 and +2.  Use Jeva to experiment with Random objects and the nextInt method to see how it works.

What to Turn In

A turnin form is available.  Use that to turn in your (modified) copies of the original files, plus your PoisonEatingBacteria.java file and the file(s) containing your additional kind of thing(s).  You can either turn in all of your Java source files by selecting them one at a time, or you can create a single archive (a zip, jar, or tar file) containing your Java files and turn that in instead.