Due: Friday, 4 Nov 2005 by 10 a.m.
This assignment will give you practice implementing your own classes, and calling methods within them. To give you a sense for the process of writing slightly larger programs, the next few assignments will build toward a simple text game.
Among the earliest computer games, developed in the 1970s, were text-based adventure games. The first of these was called Adventure; a later game built on the same principles was called Zork or sometimes Dungeon. Zork and the MIT team of students that developed it went on to form the company Infocom, which produced a series of commercially popular text-based adventures throughout the 80s when few computers had sophisticated graphics capabilities. Dungeon lent its name to an entire class of games that emerged as the Internet gained popularity, known as Multi-User Dungeons or MUDs. These are are the original massive multiplayer role-playing games (MMRPGs), essentially text-based precursors of modern graphical MMRPGs such as EverQuest or World of Warcraft. In the next few assignments you will build some of the components for a (very) simple text-based adventure game. Specifically, in this homework you will develop a Creature class to represent the creatures (warriors, monsters, wizards, etc.) in these games, and a Weapon class to represent objects (swords, spears, magic wands, etc) used to fight. Your classes will provide the attributes and methods to support a simple combat simulation.
The Creature class should use instance variables to represent the following attributes:
hit points (int): the amount of damage a creature can take before it dies. A creature's hit points are reduced when an opponent scores a hit: when the warrior successfully attacks the monster, it decreases the monster's hit points, and if the monster takes a bite out of the warrior, the warrior's hit points go down. If hit points reach or drops below zero, the creature dies.
strength (int): the maximum damage a creature can inflict. The strength represents the maximum number of hit points that will be deducted from the opponent if the creature scores a hit.
skill (int): the likelihood of a creature scoring a hit. This is an integer between 0 and 25. The higher the skill, the more likely the creature is to score a hit.
armor class (int): the armor class or AC of a creature represents how hard it is to damage. It is an integer between 0 and 20. The higher the AC, the less likely an opponent is to score a hit.
name (String): the name of the creature (e.g., "Frodo" or "Aaron Bloomfield").
type (String): a word or phrase describing the race or class of the creature (e.g., "hobbit" or "mighty warrior").
pronoun (String): the appropriate possessive pronoun to use for this creature (e.g., "his", "her", "its").
weapon (Weapon): a reference to the Weapon object wielded by the creature.
The Weapon class should use instance variables to represent the following attributes:
damage modifier (integer): an integer added to the damage inflicted when the creature scores a hit.
name (String): the name of the weapon (e.g., "sword" or "magic wand").
hit verb (String): a verb to describe the action of the weapon when it scores a hit (e.g., "slashes" or "zaps").
miss verb (String): a verb to describe the action of the weapon when it misses (e.g., "whiffs" or "misses").
Of course, these instance variables in both these classes should be declared private and manipulated via accessor and mutator methods as we have discussed during lecture. Thus, you must include an accessor and mutator method for each of the above fields in both classes. The name of the accessor/mutator should follow the standard Java naming conventions (i.e. getHitPoints(), setDamageModifier(), getName(), etc.).
The Creature class should also support the following methods:
boolean isAlive(): returns true if the creature is alive (that is, if its hit points are greater than zero) and false otherwise.
boolean tryToAttack(int targetAC): uses the Random class (see below) to get a random number between 0 and skill, where skill is the skill of the creature. Returns true if the resulting random number is greater than or equal to the targetAC parameter (which represents the opponent's armor class) and false otherwise.
int calcHitDamage(): computes the damage done if the creature scores a hit. This is a function of the creature's strength, adjusted to account for the weapon being wielded (i.e. a sword does more damage than bare hands). Generates a random number between zero and strength (where strength is the strength of the creature) and adjusts it by adding the damage modifier of the weapon being wielded, then returns this adjusted number.
void takeDamage(int amount): decrements the creature's hit points by amount.
String constructHitString(Creature opponent): returns a string of the form: "<name> the <type> <weapon hit verb> <opponent name> the <opponent type> with <pronoun> <weapon name>". For example, "Frodo the hobbit slashes Aaron Bloomfield the mighty warrior with his sword".
String constructMissString(Creature opponent): like constructHitString() but using the weapon's miss verb. For example, "Gnash the orc misses Frodo the hobbit with its spear".
Creature(): the default constructor should initialize hit points to 50, strength to 15, skill to 15, armor class to 5, name to "Somebody", type to "nondescript creature", pronoun to "its", and weapon to a new Weapon created with the Weapon() default constructor.
Creature(int hp, int str, int skl, int ac, String name, String type, String pronoun): a specific constructor that lets the programmer specify all the attributes of a creature except the weapon, which is still set a new Weapon object created with the Weapon() default constructor.
The Weapon class should support the necessary accessors and mutators, as well as the following constructors. We have provided a template of the Weapon.java file for you to start with.
Weapon(): the default constructor should initialize the damage modifier to 0, the name to "bare hands", the hit verb to "strikes" and the miss verb to "misses".
Weapon(int modifier, String name, String hit, String miss): this specific constructor should initialize all the attributes to the specified values.
To generate a random number, you must first create a Random object. Random is a class within the java.util.* library. A Random object is created via the default constructor: Random rand = new Random(); To generate a random integer, you then call nextInt(). For example, to generate a random number from 0 to 9, you would call: int x = rand.nextInt(10); Note that the integer generated is between 0 and n-1, where n is the parameter (in this case, 10). Ideally, the Random object should be an instance variable in the Creature class.
We have provided a CombatSimulation.java file which includes the main() method. This program creates and initializes two Creature objects, for example one called monster and the other called warrior. It then goes into a loop that repeats while both the monster and the warrior are alive. Each iteration of the loop the monster attempts to hit the warrior, and if the hit is successful, the warrior takes damage. The loop body then prints out an appropriate message using constructHitString()or constructMissString(). If still alive, the other creature then attacks back in the same way. You can use this class to see how the methods in your Creature and Weapon classes will be called, and as a test of the code you right. Though the outcome of the battle is different each time because of the use of the Random class, the output should look something like this:
Schmoo the gruesome monster slashes Gnusto Frotz the valiant warrior with its claws. Gnusto Frotz the valiant warrior swings at but misses Schmoo the gruesome monster with his sword. Schmoo the gruesome monster slashes Gnusto Frotz the valiant warrior with its claws. Gnusto Frotz the valiant warrior swings at but misses Schmoo the gruesome monster with his sword. Schmoo the gruesome monster slashes Gnusto Frotz the valiant warrior with its claws. Gnusto Frotz the valiant warrior stabs Schmoo the gruesome monster with his sword. Schmoo the gruesome monster swipes at but misses Gnusto Frotz the valiant warrior with its claws. Gnusto Frotz the valiant warrior swings at but misses Schmoo the gruesome monster with his sword. Schmoo the gruesome monster slashes Gnusto Frotz the valiant warrior with its claws. Gnusto Frotz the valiant warrior stabs Schmoo the gruesome monster with his sword. Schmoo the gruesome monster slashes Gnusto Frotz the valiant warrior with its claws. Gnusto Frotz dies. Schmoo is victorious! Press any key to continue...
Note that although we provide the CombatSimualtion.java code, it is important that you understand how it works (hint!).
There are a lot of methods that must be implemented for this homework. However, each method is relatively small. Focus on each method one at a time. This allows you to break down the bigger task (completing this homework) into much smaller tasks (implementing each method individually). Start with the Weapon class, as that class has the skeleton code available.
The CombatSimulation.java file includes most of what you will need to test your classes. You will want to adjust the constants to set up scenarios where you can predict the outcome (correctly setting the various attributes, for example, you could guarantee that the warrior will win in two "rounds") and verify that you get the outcome you expect. You should include a couple of these "test runs" as comments in your code. Feel free to choose creative verbs, names, and types in the process! (E.g., "John Doe the brilliant CS101 student astonishes Aaron Bloomfield the evil CS101 professor with his mind-warping code.")
When you are finished, submit your Creature.java and Weapon.java files. There is no need to submit the CombatSimulation.java file.