Summer 2014, The College of Saint Rose

Lab 8: The Wizard's Castle
Lecture and Practice Due: 4:30 PM, Tuesday, July 22, 2014
Programming Assignment Due: 4:30 PM, Tuesday, July 29, 2014

This week's lab will give you practice using inheritance, culminating in a fairly substantial program that will play a text-based game called The Wizard's Castle.

You may work alone or in a group of 2 or 3 on this lab. Only one submission per group is needed.

Getting Set Up

Start by downloading a working solution for the programming assignment and a lot of starter code here.

Create a document where you will record your answers to the lecture assignment and lab questions. If you use plain text, call it "lab8.txt". If it's a Word document, you can call it whatever you'd like, but when you submit, be sure you convert it to a PDF document "lab8.pdf" before you submit it.

Lecture Assignment Questions

We will usually discuss these questions at the start of class on the lab due date, so no credit can be earned for late submissions of lecture assignment questions.

LA Question 1: Gaddis Checkpoint exercise 11.2, p. 671-672. (3 points)

LA Question 2: Gaddis Checkpoint exercise 11.4, p. 679-680. (2 points)

LA Question 3: Gaddis Checkpoint exercise 11.5, p. 680. (2 points)

LA Question 4: Gaddis Checkpoint exercise 11.17, p. 703. (1 point)

LA Question 5: Gaddis Checkpoint exercise 11.18, p. 707-708. (3 points)

LA Question 6: Gaddis Algorithm Workbench exercise 1, p. 732. (1 point)

LA Question 7: Gaddis Algorithm Workbench exercise 2, p. 732. (1 point)

LA Question 8: Gaddis Algorithm Workbench exercise 3, p. 732. (4 points)

LA Question 9: Gaddis Algorithm Workbench exercise 5, p. 732-733. (1 point)

LA Question 10: Gaddis Algorithm Workbench exercise 7, p. 733. (1 point)

LA Question 11: Gaddis Algorithm Workbench exercise 8, p. 733. (1 point)

Practice Programs

Practice Program: Gaddis Programming Challenge exercise 10, p. 737-738. (6 points)

We can provide information to a Java application through the args parameter to its main method. As you can see from the main method signature we have been using all semester, it is an array of Strings. These String values come from what the program's user types after its name on the command line when running the program. Different Java IDEs provide different mechanisms for specifying these Strings, known as command-line parameters. In BlueJ, these are specified in a dialog box that we have been ignoring each time we run a Java application - the one that comes up after you choose main from the right-click menu to run your application. To specify the command-line parameters, we specify them as an array of String with the same syntax as a statically initialized array in Java. For example, we could specify an array of 3 String values:

```  { "Java", "is", "fun" }
```

The Java run-time system will construct and initialize an array with these values, and we can access "Java" as args[0], "is" as args[1], and "fun" as args[2] in our program's main method.

Practice Program: Write a Java application in a program ArgAdder.java that takes any number of integers as command-line parameters (though they will come to you as String values) and prints their sum. (5 points)

Programming Assignment: The Wizard's Castle

Long before first-person shooters and texture-mapping 3D graphics processing units, there were text-based games. A favorite from my Commodore 64 days was called The Wizard's Castle. The game was written in BASIC in 1980 by Joseph Power, and the version I used was converted to Commodore Basic by Jim Pryzyblo in 1983.

After coming across a "vintage" version on the web, I converted it to Java. The BASIC program origwiz.bas included in the starter you downloaded. In this lab, you will implement part of this program. The basic rules of the game are described in the file castle.txt, also in the starter download.

Try it out to get a feel for the game. Issue the command "h" to learn more about the interface. If you provide any command-line parameter when you run this version, you will enter a debugging mode, where some additional information about the game is printed. This allows you to test features of the game that would otherwise be difficult to test (such as finding which of the 65 monsters in the castle has the Runestaff).

I am providing the source code for many of the classes from my implementation. You can get them from the starter package. The classes that implement the castle itself are omitted. Your task is to develop a Castle class, and any additional classes you deem appropriate, that will work with the rest of my implementation.

Here is a brief description of the classes.

Game Control

class WizardsCastle is responsible for setting up the game and managing game play. The main method simply constructs an instance of WizardsCastle and calls its setup and play methods. The setup and play methods interact with the Castle class (which you will write) through the public interface described later in this document.

Player

class Player and class Species define the player and his or her inventory and attributes.

Castle Rooms

The abstract class RoomContents defines the common behavior of all of the items that can be placed throughout the Castle. A major part of your task in developing the Castle will be to manage the 512 instances of RoomContents subclasses.

RoomContents defines one instance variable visible and appropriate accessor and mutator methods to access this variable. It determines whether the player is aware of the contents of that room (by having been there or seen it by light of a flare, a lamp, or by gazing into a Crystal Orb).

RoomContents provides default implementations of two methods that are overridden by some subclasses: take and interact. The take method is overridden by classes that represent objects that can be picked up by the player. The interact method is overridden by classes that define a room containing something the player can interact with. It also defines two abstract methods, mapSymbol and contents, which must be provided by all classes extending RoomContents.

The following classes extend RoomContents:

• class Book - The player in this room can open the book, which disappears after being opened, making the room empty.
• class Chest - The player in this room can open the chest, which disappears after being opened, making the room empty.
• class CrystalOrb - The player in this room can gaze into the orb, which never disappears.
• class EmptyRoom - There's not much you can do here.
• class Entrance - The player starts here, and if the player goes north from this room, he or she exits the castle. It otherwise behaves as an empty room.
• class Flares - When the player enters a room that contains flares, the player picks up the flares and the room becomes empty.
• class GoldPieces - When the player enters a room that contains gold pieces, the player picks up the gold pieces and the room becomes empty.
• class Monster - When the player enters a room that contains a monster, he or she must fight the monster to the death or escape by retreating or bribing the monster. Should the monster be killed by the player, the room becomes empty.
• class Pool - The player in this room can drink from the pool, which never disappears.
• class Sinkhole - When the player enters a room with a sinkhole, he or she falls through to the next level of the castle.
• class StairsDown - The player in this room may choose to descend the stairs to the next level.
• class StairsUp - The player in this room may choose to ascend the stairs to the next level.
• class Treasure - When the player enters a room with a treasure, the player picks up the treasure and the room becomes empty.
• class Vendor - When the player enters a room with a vendor, he may trade with or attack the vendor. If any vendor in the castle is attacked, all vendors become hostile and refuse to trade and otherwise behave like monsters (and powerful ones at that). To restore good relations, the player must bribe any vendor successfully. If a vendor is killed, the room becomes empty.
• class Warp - When the player enters a warp room, he or she is transported to a random location in the castle.
Miscellaneous Utilities

Two utility classes are provided that do not implement any part of the game directly, but are used by other parts of the program.

• class Location - encapsulates a row/column pair and is used for parameters and return values throughout the program.
• class Prompter - provides two prompt methods. The first presents a prompt and waits for the player to specify one of a list of valid single-character responses. The second presents a prompt and waits for the player to specify a number in the given range.

Question 1: Describe the purpose of the abstract class RoomContents and discuss why it is not a regular class or an interface. (4 points)

Question 2: One of the important goals of our course is to understand object-oriented design. Describe the responsibilities of each class (treat all of the classes that extend RoomContents as a single entity for the purposes of this question) and describe how they interact with each other. (4 points)

You will be developing your implementation of the Castle class for this program. You should not make any changes to the other classes provided.

Your implementation of class Castle is up to you, but in order to make it work with the rest of the program, you will need to take care that your class provides the required constructor and public methods. Here are the specifications:

• public Castle();

The constructor takes no parameters. It creates the internal storage for the castle and initializes the castle contents. Immediately after construction, the castle should contain:

• The entrance on Level 1, Location (1,4).
• Two corresponding pairs of rooms containing stairs connecting Level 1 to Level 2, Level 2 to Level 3, ..., and Level 7 to Level 8. Since the top level is Level 1 and higher-numbered levels descend into the dungeon, Level 1 should have two rooms with stairs going down, Levels 2-7 should have two rooms with stairs going up and two rooms with stairs going down, and Level 8 should have two rooms with stairs going up. And all stairs going in one direction should lead to a room with stairs going in the other direction.
• One of each type of monster on each level. The monster types range from 1 to Monster.NUM_MONSTERS, with the monster type specified in the Monster constructor.
• Three of each of these items on each level:
• books
• crystal orbs
• pools
• chests
• rooms containing flares
• rooms containing gold pieces
• sinkholes (even on Level 8, where they allow the player to "fall" through back up to Level 1)
• warps
• vendors
• One of each type of treasure randomly throughout the castle. The treasure types range from 1 to Treasure.NUM_TREASURES, with the treasure type specified in the Treasure constructor.
• One additional monster of a random type placed at a random location in the castle. This monster has the Runestaff. Your castle implementation will need to remember which location has been assigned the Runestaff.
• One additional warp placed at a random location in the castle. This warp hides the Orb of Zot. Your castle implementation will need to remember which location has been assigned the Runestaff.
• All remaining rooms are empty. However, three of them should be selected to hold curses. One room should be designated for each of the lethargy, leech, and forgetful curses.
• public RoomContents roomAt(int level, Location pos);

Returns the contents of the room on the specified level and position.

• public void printMap(int level, Location pos);

Prints a map of the specified level of the castle, with the room at pos printed enclosed in angle brackets (indicating the current location of the player). Actual contents of rooms should be displayed only if the player has been in that room (the room's isVisible() method returns true). Otherwise, the room should be denoted with ".". Note that the map symbol for a visible room can be displayed using its toString() method.

• public void printMapRevealed(int level, Location pos);

Same as printMap, except the contents of all rooms are displayed, not just visible rooms. This is used only in debugging mode.

• public void makeEmpty(int level, Location pos);

Replaces the room at the given level and position with an empty room.

• public int randomCoord();

Returns a random number in the range 1 through WizardsCastle.NUM_LEVELS. In addition to be called by other classes, this will be a useful helper method for castle initialization.

• public boolean isOrb(int level, Location pos);

Returns true if the given level and position specifies the room containing the Orb of Zot.

• public boolean isRunestaff(int level, Location pos);

Returns true if the given level and position specifies the room containing the Runestaff.

• public void printOrbLocation();

Prints (using System.out.println) the location of the Orb of Zot. This is used when gazing into a crystal orb.

• public void forgetRandomRoom();

Takes a random room anywhere in the castle and makes it invisible. This implements the effect of the forgetful curse.

• public boolean isLethargyRoom(int level, Location pos);

Returns true if the given level and position specifies the room that contains the lethargy curse.

• public boolean isLeechRoom(int level, Location pos);

Returns true if the given level and position specifies the room that contains the leech curse.

• public boolean isForgetfulRoom(int level, Location pos);

Returns true if the given level and position specifies the room that contains the forgetful curse.

There are a number of ways that you can approach this task. Here is one possibility:

1. Start writing the constructor. At first, just initialize the castle to contain all empty rooms.
2. Write the printMapRevealed method.
3. Write a main method for class Castle. This will allow you to test the Castle class as you go without having to write all of the methods to test it with the real game. This main method should just construct a Castle and display it with calls to printMapRevealed.
4. Incrementally develop the constructor to add the required rooms to the castle. Test as you go.
5. Once you have the contents of the castle created correctly, implement the other methods listed above so you can test with the entire game.

Submitting

Before 4:30 PM, Tuesday, July 22, 2014, submit your lab for grading. There are two things you need to do to complete the submission: (i) Copy your file with the answers to the lecture assignment and lab questions into your project directory. Be sure to use the correct file name. If you prepared your answers in Word, export to a PDF file and submit that. (ii) Upload a copy of your lab (a .7z or .zip file containing your project directory) using Submission Box under assignment "Lab8".