CIS 120 Homework 2 - AdventureGame

Due Friday September 25, 2008 at 11:00am.


(Zork opening screenshot, credit Wikipedia.org)

In this homework you will be creating the core functionality of a simple text-based adventure game. The goals of this assignment are:

Important notes:

Here are the files you will need:

Sections in this document:

  1. Overview
  2. Running the Tester
  3. Problem 1: Basic Room Class
  4. Problem 2: Maze Class
  5. Problem 3: Item Class
  6. Problem 4: Character Class
  7. Problem 5: Adding Locked Doors
  8. Extra Credit: Exits in Arbitrary Directions

Overview

The ancestor of all text-based adventure games is Bill Crowther's Adventure, developed originally in Fortran back in 1975. A popular variant was called Zork, and this spawned many sequels (and whose introductory screen can be seen above). If you are interested in experiencing this classic, check out Infocom's official Zork download page (it's free).

Our adventure game is much simpler than these. The player's character moves from room to room exploring a maze, and can pick up and drop items. We will start by building the Rooms, then the Maze, then Items, and finally Characters.

 For the complete specification of all classes in this assignment, refer to the Javadocs.


Running the Tester

For this assignment, we've created a new (hopefully simpler and more robust) way for you to run the test script and see what grade you've achieved at the moment. The hw2.jar file includes a compiled version of the Tester class that you can run yourself, on whatever machine you are using to develop your solution. Here's what you need to do to run it. (You are strongly encouraged to try this out right now, before beginning on the assignment, and to run the tester to check the parts of your solution as you finish developing them.)

Now there are two methods for running the tests:


Problem 1 (18 Points): Basic Room Class (File to submit: Room.java)

Rooms in MazeTo begin, let's set up the basic structure of the world: the Room class.

Take a look at the javadoc documentation for the Room class. Your first job is to implement this class. This should be mostly straightforward...

Here are a few more notes that should help you:

Sample interactions: (problem1.hist)

> Room r1 = new Room("Ballroom")
> r1
Ballroom
> r1.getExit("north")
null
> Room r2 = new Room("Library") > r1.linkRooms(r2, "north", "south")
> r1.getExit("north")
Library

Problem 2 (24 points): Maze Class (File to submit: Maze.java)

Creating large worlds by creating individual rooms and linking them together can be a lot of work. Let's next build a helper class that simplifies the process by taking a two-dimensional array of strings and creating a world from it all at once. For any cell in our grid, if there is a non-null String value in that cell then a room should be created with that string as its description. Exits should be automatically created for any adjacent rooms. For example, if we give it an array that looks like this...

"A" "B" "C"
"D" null "E"
"F" "G" "H"

...it will create a "ring" of rooms whose descriptions are "A", "B", "C", etc. where going "east" from A reaches B, going "west" from B reaches A, going "east" from B reaches C, going "south" from C reaches E, etc.

See the javadocs for full details of what your solution must provide.

Sample interactions: (problem2.hist)

> String[][] descriptions = new String[3][3]
> descriptions[1][0] = "A dusty broom closet.";
> descriptions[1][1] = "A large and dimly-lit ballroom.";
> descriptions[0][1] = "A fancy dining room";
> Maze m = new Maze(descriptions, 0, 1) > m.getStartingRoom() A fancy dining room. > m.getStartingRoom().getExit("south") A large and dimly-lit ballroom.

Problem 3 (15 points): Items (File to submit: Item.java)

Now let's enrich rooms so they can contain things. Much of the work in this part is done for you by the Container class, which is provided for you in hw2.jar. Containers hold objects of the Item class. Items are simply game elements that have a description, and can be stored in containers. For problem 3, it is your job to write the Item class.

Sample interactions: (problem3.hist)

> Room r = new Room("A large and dimly-lit ballroom.")
> r
A large and dimly-lit ballroom.
> Item i = new Item("Coin", r) > r
A large and dimly-lit ballroom.
Contents: Coin

Problem 4 (26 points): Characters (File to submit: Character.java)

The last missing component of our adventure game is characters. For this problem you will write the Character class. Because characters are also entities in the game that will be held in Containers (in this case the Room they are in), the Character class will need to have similar functionality to the Item class (in addition to lots more specialized functionality specific to characters, like the ability to move around). In essence, you can think of a Character as a specialized type of Item that can do lots more stuff.

Sample interactions: (problem4.hist)

> Room r = new Room("An ancient temple.")
> Character c = new Character("Indiana Jones", r);
> c
Indiana Jones
> Item i = new Item("Fedora Hat", r) > c.pickUp("Fedora Hat") true > c
Indiana Jones (carrying Fedora Hat) > Room r2 = new Room("A small, damp stone alcove.") > r.linkRooms(r2, "north", "south") > c.move("west") false > c.move("north") true > c.getLocation() A small, damp stone alcove. Contents: Indiana Jones (carrying Fedora Hat)

Problem 5 (17 points): Locked Doors (File to submit: Room.java)

While technically we now have a fully functioning adventure game, our game isn't very interesting at the moment. To spice things up a little bit, let's now go back and add the capability for a door from one room to the next to be locked unless the character attempting to move is carrying the specific key.

Sample interactions: (problem5.hist)

> Room r = new Room("A large and dimly-lit ballroom.")
> Room r2 = new Room("A small, dusty broom closet.")
> r.linkRooms(r2, "west", "east");
> r.lockExit("west", "A small silver key");
true
> Character c = new Character("Sherlock Holmes", r);
> c.move("west")
false
> Item i = new Item("A small silver key", r) > c.pickUp("A small silver key") true > c
Sherlock Holmes (carrying A small silver key) > c.move("west") true > c.getLocation() A small, dusty broom closet. Contents: Sherlock Holmes (carrying A small silver key)

Extra Credit (10 points)

Finally (if you choose), let's make things a little more interesting by allowing rooms to have exits in "directions" with names other than the compass directions. Observe that we've already left room for this in the design — the methods of Room that deal with directions treat them as strings rather than as members of an enumerated type with just four possibilities. (This is also why the linkRooms method takes a description of the forward and backward directions when creating exits. While it may be well-defined what the opposite of "north" is, its not obvious what the opposite of the direction "a few steps to the left of the dusty old grand piano" is...) Your job is to rewrite your implementations of those methods so that they do the right thing with arbitrary strings.

One way to implement this functionality is to use a HashMap in each Room to represent the association between directions and neighboring rooms. Have a look at the documentation for HashMap (available in many places — it's a standard library class) for a detailed explanation of how it works. If you choose to use it, you'll need to put "import java.util.HashMap;" at the top of your Room.java file OUTSIDE the class definition.

This question doesn't require any new methods anywhere: just change your implementation of the preexisting framework.

Sample interactions:

> Room r = new Room("A large and dimly-lit ballroom.")
> Room r2 = new Room("A small, dusty broom closet.")
> r.linkRooms(r2, "into closet", "out of closet");
> Character c = new Character("Curious George", r);
> c.move("into closet")
true