Problem Solving Assignment 5

Due Tuesday of week 10 (6/2/2009) at 11:59pm

Point total: 25 points


Critters!

This assignment will give you practice using and understanding inheritance and polymorphism in Java. Specifically, you will be designing several classes that will create characters in a game called Critters, developed at the University of Washington by Stuart Reges and Marty Stepp (Mike's brother).

Program Behavior:

You will be provided with several classes that implement a graphical simulation of a 2D world with many animals moving around in it. You will write a set of classes that define the behavior of those animals. Different kinds of animals move and behave in different ways. As you write each class, you are defining those unique behaviors for each animal. The critter world is divided into cells with integer coordinates. The world is 60 cells wide and 50 cells tall. The upper-left cell has coordinates (0, 0); x increases to the right and y increases downward.

Movement

On each round of the simulation, the simulator asks each critter object which direction it wants to move. Each round a critter can move one square north, south, east, west, or stay at its current location. The world has a finite size, but it wraps around in all four directions (for example, moving east from the right edge brings you back to the left edge). You might want your critters to make several moves at once using a loop, but you can't. The only way a critter moves is to wait for the simulator to ask it for a single move and return that move.

Fighting/Mating

As the simulation runs, animals may collide by moving onto the same location. When two animals collide, if they are from different species, they fight. The winning animal survives and the losing animal is removed from the game. Each animal chooses one of Attack.ROAR, Attack.POUNCE, or Attack.SCRATCH. Each attack is strong against one other attack (e.g. roar beats scratch) and weak against another (roar loses to pounce). The following table summarizes the choices and which animal will win in each case. To remember which beats which, notice that the starting letters of "Roar, Pounce, Scratch" match those of "Rock, Paper, Scissors." If the animals make the same choice, the winner is chosen at random.

Critter #2
Attack.ROAR Attack.POUNCE Attack.SCRATCH
Attack.ROAR random winner #2 wins #1 wins
Critter #1 Attack.POUNCE #1 wins random winner #2 wins
Attack.SCRATCH #2 wins #1 wins random winner
If two animals of the same species collide, they "mate" to produce a baby. Animals are vulnerable to attack while mating: any other animal that collides with them will defeat them. An animal can mate only once during its lifetime.

Eating

The simulation world also contains food (represented by the period character, ".") for the animals to eat. There are pieces of food on the world initially, and new food slowly grows into the world over time. As an animal moves, it may encounter food, in which case the simulator will ask your animal whether it wants to eat it. Different kinds of animals have different eating behavior; some always eat, and others only eat under certain conditions. Every time one class of animals eats a few pieces of food, that animal will be put to "sleep" by the simulator for a small amount of time. While asleep, animals cannot move, and if they enter a fight with another animal, they will always lose.

Scoring

The simulator keeps a score for each class of animal, shown on the right side of the screen. A class's score is based on how many animals of that class are alive, how much food they have eaten, and how many other animals they have killed.

Provided Files:

Each class you'll write will extend a superclass named Critter. This is an example of inheritance, as discussed in the textbook. Inheritance makes it easier for our code to talk to your critter classes, and it helps us be sure that all your animal classes will implement all the methods we need. But to do this assignment you don't need to understand much about inheritance. Your class headers should indicate the inheritance by writing extends Critter, like the following:

public class Bear extends Critter { ...

The Critter class contains the following methods, which you must write in each of your classes:

Just by writing extends Critter as shown above, you receive a default version of these methods. The default behavior is to never eat, to always forfeit in a fight, to use the color black, to always stand still (a move of Direction.CENTER), and a toString of "?". If you don't want this default, rewrite (override) the methods in your class with your own behavior. For example, below is a critter class Stone. Stones are displayed with the letter "S", gray in color, never move, never eat, and always roar in a fight. Your classes will look like this class, except with fields, a constructor, and more sophisticated code. Note that the Stone does not need an eat() or getMove() method; it uses the default behavior for those operations.

import java.awt.*; // for Color
public class Stone extends Critter {
   public Attack fight(String opponent) {
      return Attack.ROAR;
   }
   public Color getColor() {
      return Color.GRAY;
   }
   public String toString() {
      return "S";
   }
}

Running the Simulator:

When you press the Go button on the simulator, it begins a series of turns. On each turn, the simulator repeats the following steps for each animal in the game:

After moving all animals, the simulator redraws the screen, asking each animal for its toString and getColor values.
It can be difficult to test and debug this program with so many animals on such a large screen. We suggest using a smaller game world and fewer animals (perhaps just 1 or 2 of each species) by adjusting the game's initial settings when you run it. There is also a Debug checkbox that, when checked, prints a large amount of console output about the game behavior.

The code for the simulator is provided below.


This homework requires skills with inheritance and polymorphism. You will need to write the following classes:

  1. Bear -- Bears are always hungry, scratch when fighting, and either move north or west.
  2. Lion -- Lions get hungry after they fight, they either roar or pounce, and they move in circles.
  3. Tiger -- Tigers have a fixed amount of food they can eat, either scratch or pounce, and move randomly.
  4. Triton -- Each Triton is unique, you will decide the behavior of your own Triton!

Details

You must put a comment at the top of your code that specifies your: real name, login name, email address, and PID. You must also include a two-to-four sentence description of the program. Use a multi-line comment (/* */). YOU MUST DO THIS FOR EVERY JAVA FILE!

Comments Comments in the style detailed in the book ARE required. Your code must be properly commented to receive full credit.

Comments and good style are worth (1pt).

Custom Critters:

Below are the descriptions of the Critters that you will write.

Bear

The Bear constructor accepts a parameter representing the type of bear it is: true means a grizzly bear, and false means a polar bear. Your Bear object should remember this and use it later whenever getColor is called on the Bear. If the bear is a grizzly, return a brown color (a new Color(190, 110, 50)), and otherwise a white color (Color.WHITE).

Lion

Think of the Lion as having a "hunger" that is triggered by fighting. Initially the Lion is not hungry (so eat returns false). But if the Lion gets into a fight or a series of fights (if fight is called on it one or more times), it becomes hungry. When a Lion is hungry, the next call to eat should return true. Eating once causes the Lion to become "full" again so that future calls to eat will return false, until the Lion's next fight or series of fights.

Tiger

The Tiger constructor accepts a parameter for the maximum number of food this Tiger will eat in its lifetime (the number of times it will return true from a call to eat). For example, a Tiger constructed with a parameter value of 8 will return true the first 8 times eat is called and false after that. Assume that the value passed for hunger is non-negative.

The toString method for a Tiger should return its remaining hunger, the number of times that a call to eat would return true for that Tiger. For example, if a new Tiger(5) is constructed, initially that Tiger's toString method should return "5". After eat has been called on that Tiger once, calls to toString should return "4", and so on, until the Tiger is no longer hungry, after which all calls to toString should return "0". Recall that you can convert a number to a string by concatenating it with an empty string. For example, "" + 7 evaluates to "7".

Triton

You will decide the behavior of your Triton class. Part of your grade will be based upon writing creative and non-trivial Triton behavior. The following are some guidelines and hints about how to write an interesting Triton. There are additional methods that each critter can use through inheritance from the Critter class. Your Triton may want to use these methods to guide its behavior. None of the methods below are needed for Bear, Lion, or Tiger.

Your Triton's fighting behavior may want to utilize the parameter to the fight method, opponent, which tells you what kind of critter you are fighting against (such as "B" if you are fighting against a Bear).

Your Triton can return any text you like from toString (besides null) and any color from getColor. Each critter's getColor and toString are called on each simulation round, so you can have a Triton that displays differently over time. The toString text is also passed to other animals when they fight your Triton; you may want to try to fool other animals.

On the last day of class, we will host a Critter tournament. In each battle, two students' Triton classes will be placed into the simulator along with the other standard animals, with 25 of each type. The simulator will run until no significant activity occurs or 1000 moves have passed. The student whose Triton has the higher score in the right sidebar advances.

No grade points will be based on tournament performance. For example, a Triton that sits completely still may fare well in the tournament, but it will not receive full grade points because it is too trivial.

Supplemental Files

In order to complete your assignment, you will need the code for the base class Critter. YOU MUST HAVE THIS FILE IN ORDER TO COMPILE YOUR CRITTERS. The source code for this class is here: Critter.java. You should save this code in a file named Critter.java, and put it in the same folder as the other classes you write for this assignment. YOU SHOULD NOT EDIT THE Critter.java FILE IN ANY WAY!!

Additionally, you can test your critters in the Critter colliseum using the CritterMain class, which is provided here: CritterMain.java. You should save this code into a file named CritterMain.java, and put it in the same folder as Critter.java and the other classes you write for this assignment. YOU SHOULD NOT EDIT THE CritterMain.java FILE IN ANY WAY!!!

YOU DO NOT NEED TO EDIT OR TURNIN Critter.java OR CritterMain.java.

Generating random numbers

In this assignment, at least for the Tiger class, you will need to generate random numbers. The easiest way to do this is to use the class java.util.Random. The Random class has a default constructor, which will create a new Random object that is ready to give you random numbers. The method you will most likely want to use is Random.nextInt(int n), which will return a random integer in the range 0 to (n-1).

So for instance in your Tiger class you are supposed to choose random directions. Since there are 4 of them, you can make a call to nextInt(4), which will return either 0,1,2, or 3. You can associate each of these with the directions NORTH, SOUTH, EAST, and WEST in whatever way you like.


Testing/Grading

You can test your Critters by running them in the Critter colliseum. To do this, simply download the CritterMain class and run it from the command line.

When you run CritterMain, it will scan the current folder and look for any class files that extend the Critter class. Then it will ask you which of those classes you would like to load into the colliseum. The best way to test your individual critters is to load them one at a time into the colliseum and see if they exhibit the correct behavior.

Turning in your homework

On ieng6 somewhere under your home directory you need to make a folder called PSA5. All of your files for this assignment must go in this folder.
The files you need to turn in for PSA5 are:

You should put these files into a folder named PSA5, then cd into that folder and run the command bundleP5.

NOTE: Even though we will provide you with Critter.java and CritterMain.java, you do not need to turn those in (and you should not edit them either).

(You will NOT need bookClasses for this assignment)