| Home | Notes | Homework | Labs | Programs |
| Program 6: Adventure |
| Goal |
|
In your final programming assignment, you will be inventing and implementing an adventure game. You will use classes based on the "World of Zuul" adventure game example from B&K Chapter 7. You will be working with a number of classes, many of which will be subclasses of existing classes provided for you. You will also be working with interfaces. Adventure games have been around for a long time, as discussed in B&K (see the web links in Section 7.1). Although B&K provide links for information about the Colossal Cave Adventure, there is more to the history of adventure gaming than this initial spark. In particular, Infocom was famous as a computer game producer who made text (and later, graphic) adventure games. Zork, their oldest adventure game, is considered by many to be the most famous of all text adventures, or "interactive fiction games". You can even download and play Zork I, II, and III. There is even an on-line PHP version of Zork you can play in your web browser. You can also read the definitive history of Zork, or read its entry in the wikipedia. This assignment offers you a large amount of creative freedom, so do not hesitate to have fun with it! |
|
| Inventing Your Game |
This is similar to exercise 7.3 in the text. First, you should decide what the goal of your game is. It should be something along the lines of: You have to find some items and take them to a certain room (or a certain person?). Then you can get another item. If you take that to another room, you win.
For example: You are a freshman in CS1705 at Virginia Tech. You have to find out when and where your final exam is. To get this information, you have to find the CS department office and ask. At the end, you need to find the exam room. If you get there on time, and you have found your textbook somewhere along the way, and you have also been to the tutorial class, then you win.
Or: You are lost in a dungeon. You meet a troll. If you find something to eat that you can give to the troll, then the troll tells you where to find a magic wand. If you use the magic wand in the big cave, the exit opens, you get out and win.
It can be anything, really. Think about the scenery you want to use (a dungeon, a city, a building, a local park, an historic site) and decide what your locations (rooms) are. Make it interesting, but don't make it too complicated (we suggest no more than 15-20 rooms.) Put objects in the scenery, maybe people, monsters, things that can be picked up or things that are stationary. Decide what task(s) the player has to master.
| WoZ Support Classes |
Just as in program 5, you are
being provided with a number of support classes that will help in
constructing an adventure game similar to the "World of Zuul" (WoZ).
Make sure to
update your
cs1705.jar file so that you have these classes.
The are four main classes for creating adventure games in the package
cs1705.adventure:
Game represents the main class of a game.
It sets the game up, and then enters a loop to read and
execute player commands. Note that Game is
an abstract class: that means you cannot create an
object of this class directly, because some of its methods
have not been given definitions. Instead, you must create your
own subclass that defines the missing pieces.
Player represents the person playing the game.
The cs1705.adventure.Player class is essentially the
same as the one described in Chapter 7. However, you can create
your own custom subclass of Player that adds any
new features you wish.
Room represents a location in the game.
The cs1705.adventure.Room class is essentially the
same as the one described in Chapter 7. However, you can create
your own custom subclass of Room that adds any
new features you wish.
Command is an interface that defines the common
properties of all command objects. In particular, it requires
every command object to implement an execute() method.
There are three classes that implement this interface that are
also provided for you in the cs1705.adventure
package: GoCommand, HelpCommand, and
QuitCommand. You can use these three commands, and
create any new ones you like.
These four classes (well, three classes and one interface) are
the aspects of the cs1705.adventure package that you
will use most often. You will probably need to create your own
subclasses of each one at some point, although you can work toward
a solution incrementally. Study their javadoc documentation on
the course web site well so that you understand what their methods
do.
In addition, the cs1705.adventure package contains
two other classes to help you implement a game:
CommandWords represents the dictionary of
known commands in a game. Unlike the implementation of this
class discussed in Chapter 7, the version in
cs1705.adventure uses a Map to
associate Command objects with words. This
makes it easy to add new commands without affecting the
structure of this class.
Parser reads command lines and breaks them up
into words, looking the command word up using a
CommandWords object. The parser implemented here
understands one- and two-word input lines, where a one-word
command is a verb (like "quit"), and a two-word command is
a verb followed by an object (like "go east" or "take wand").
All together, the classes in the cs1705.adventure
and their relationships are summarized in this simplified UML diagram:
| Requirements for Your Game Implementation |
You will need to extend several classes to implement a base level of required features in your game. Your game implementation must do the following:
Include your own custom subclass of Game.
Include your own custom subclass of Player.
Include your own custom subclass of Room.
Include a variety of locations/rooms (a minimum of 10).
It must be possible for a player to reach each of the locations/rooms.
You must extend the basic game from the text to support items. Each item should initially be located in some room. Every room can hold any number of items. Some items can be picked up by the player, others cannot. The player can carry some items with him or her. Every item has a weight. The player can carry items only up to a certain total weight.
Your game must support the commands take and
drop for manipulating items, and inventory
(abbreviation: i) for listing out the items currently
being carried by the player.
The player can win. There has to be some situation that is recognised as the end of the game where the player is informed that he/she has won.
In addition to the "go" command (which is already implemented
for you in the GoCommand class), you must also
support the following one-word movement commands: north, south,
east, west, up, and down, together with one-letter
abbreviations for each: n, s, e, w, u, d. Note: you
can support all of these with a single command class, so you will
loose points if you use six (or twelve!).
Implement a command back that takes you back to the
last room you've been in.
In addition to the commands provided in the
cs1705.adventure package and the additional commands
explicitly required in this list, add at least four new commands of
your own devising.
Beyond these basic requirements, you are free to explore any other game features you wish to provide. Feel free to take advantage of this flexibility to have fun while you complete the assignment.
| Implementing an Adventure Game |
Before you get too far into the design of your adventure game, it may help to play around with the classes a bit and try out a few exploratory changes. This will help you get a feel for making small extensions to the existing features in a way where you can try out each change as you go. Then, as you pursue your design in more detail, you always can keep in mind the concept of incremental development--adding one piece of your design at a time, and making sure it works as intended before moving on to the next.
To see how to start creating your own game, let's work through a trivial
example based on B&K Chapter 7. First, create
a new Game subclass:
import cs1705.adventure.*;
public class BoringGame
extends Game
{
public BoringGame()
{
}
}
We cannot yet create any objects from this class, since the
base class Game is abstract--that means there are
some methods that it declares, but it does not provide code for
them. Instead, we need to provide our own code for them in our
subclass. These methods are: welcomeMessage(),
createRooms(), and createCommands().
First, let's implement welcomeMessage() in our game
subclass. This method just determines the message printed when the
game starts up. This message is taken from Chapter 7:
public String welcomeMessage()
{
return
"Welcome to The World of Zuul!\n"
+ "The World of Zuul is a new, incredibly boring adventure game.\n"
+ "Type 'help' if you need help.";
}
Next, let's decide on our map. We can use a couple of rooms from the Chapter 7 example:
public void createRooms()
{
// create the rooms
Room outside = new Room( "outside McBryde Hall" );
Room lab = new Room( "in a computing lab" );
// initialise room exits
outside.setExit( "south", lab );
lab.setExit( "north", outside );
// the player starts the game outside
player().setCurrentRoom( outside );
}
Finally, we need to add some commands. There are already three
commands provided in the cs1705.adventure package that
we can use.
public void createCommands()
{
CommandWords commands = parser().commandWords();
commands.addCommand( "go", new GoCommand() );
commands.addCommand( "help", new HelpCommand( commands ) );
commands.addCommand( "quit", new QuitCommand() );
}
Now try compiling your game subclass. You can run your game by
creating an object from your subclass on the object bench, and then
running its play() method. Type your commands into
the terminal window. It's pretty boring, but it will get you started.
Chapter 7 also tells us how to run complete Java programs from outside of BlueJ. Add the following method to your game subclass:
public static void main( String[] args )
{
Game game = new BoringGame();
game.play();
}
You should now be able to play your game from a windows command prompt
window. Just change directory to your project directory, and then
execute the following from the command line (assuming BlueJ was installed
in C:\BlueJ --adjust the path if you installed at a different
location):
java -cp .;C:/BlueJ/lib/cs1705.jar BoringGame
Note that the name on the end of the line is the name of your
game subclass. When you run a program this way, java will look for
a public static void method called main() in the class you
named on the command line, and then execute that method. As you can
see above, our main() method simply creates a new
game object (the way you did on the object bench) and then calls its
play() method.
Now that we've discussed the basics of implementing a rudimentary game, you should probably "warm up" by making some basic changes and extensions. For example, you can:
Change the description of a location to something different.
Change the exits of a location: pick a room that currently is to the north of another room and put it to the west, for example.
Add a room (or two, or three, ...).
Add a new command: say, the command "north" that makes you walk to the north.
Exercises like this should help build your confidence in how the library classes operate, and familiarize you with the basic mechanics of implementing a game. Next, map out your game design--draw yourself a map, write up a list of objects you want to include in the game, and jot down a list of puzzles or tasks you want the player to solve. You can also come up with a list of commands you wish to add--both those that are part of the base-level requirements, and additional commands you want to add in order to support your puzzles or one of your objects.
In implementing your game, the map is a great place to start. Work on implementing the full map you've worked out, which should be quick and easy. Afterward, begin prioritizing your list of commands. You can implement them one at a time, and try each one out. Remember to write test cases for each one as you go. You might consider implementing all the commands that do not involve objects first, and save those that do involve objects until you've implemented some way for players to carry things (and rooms to hold them).
Proceeding incrementally and testing as you go is a big help with an assignment this large. It helps to manage the complexity of the task, and also gives you some degree of assurance that what you've completed so far really works--and that when you added a new feature, you didn't break any of your past work.
When you do move on to implementing game objects, you will probably need
to create your own subclass of Player.
class to your project that extends Player. Using your new
class in your game is easy too. Just modify your constructor a little
to provide the player and parser objects you want to use up to the
Game class constructor:
public BoringGame()
{
// Use alternate superclass constructor that takes
// the player and parser as parameters:
super( new MyPlayer(), new Parser() );
}
This code snippet assumes a player subclass called MyPlayer,
but your class names are hopefully more meaningful.
| Testing Your Game |
As with other work in this course, you are responsible for writing tests for all the code you write. In this case, that means providing a test class for each class you write, and providing test cases for each public method you write.
There is no need to test all the inherited methods in your
classes, however. For example, if you create a Player
subclass that adds methods called take() and
drop(), then you definitely need to write test cases
for these new methods. There is no reason for you to write additional
tests for the other methods inherited from the Player
base class, however (methods like getCurrentRoom() or
walk(), for example). The only time you need to write
additional tests for inherited methods is when you provide your
own overriding definition for such a method, or when you otherwise
intend to alter an inherited method's behavior in a significant way
by other changes that you have made in your subclass.
Most students at first consider testing such an application to be a daunting task, because they imagine trying to test the entire game state as specific top-level player commands are entered. Don't think of it that way. Instead, remember that you are writing individual test cases for a specific method on a specific class. It is much easier to test this way. For example, it is easy to write a test case that creates a room, creates a player, sets the player's current room, and then calls some method on the player. The same is true when you are trying to test interactions between an object and a room, a player and an object, and so on. Make sure that in the classes you have written, it is easy to set up a reasonable test state without having to play through a significant game scenario.
Finally, note that you are not expected to (or required to)
test the main() method of your game subclass! Instead,
ignore that method for the purposes of testing in this assignment.
You must write appropriate test cases for all other public methods in
all classes that you write, however.
| Submit Your Solution |
Program submissions work just like lab submissions.
On BlueJ's main menu, click Tools->Submit.... Click on
"Browse...", double-click to open the
"CS 1705 Programs" folder, and select
Program 6. Click "OK".
Click "Submit". Click on the link provided
in the submission response in order to view the results of the
automated phase of program grading.
If no "Program 6" entry is visible on BlueJ's submission menu, then the Web-CAT Grader is not yet accepting submissions for this assignment. Wait for a message posted to the course web site that submissions are being accepted, and try again.
If any errors, warnings or suggestions are indicated, you can fix them and resubmit. You are expected to fix all such issues in your code. You may resubmit as many times as you like, up until the deadline. Be careful as the due time approaches--if you submit just over the deadline, a late penalty will be assessed.
| Adventure Game Contest |
If you are willing to take the challenge, you can enter your solution to Program 6 into a contest among all the students in this course this semester. The top contestants from both lecture sections will be presented in class during the last class meeting on 12/10, and students will vote for the winner in each lecture period. Prizes will be given to the winners.
Contest entries will be judged primarily on artistic merit. You can gather game ideas and logic puzzles from friends or classmates, but you must design and write all the code yourself.
To qualify as a contest entry, an adventure game must meet the following criteria:
Your game must meet fully all the base-level requirements laid out in this assignment.
Your contest submission must be made before the due time for Program 6 (i.e., no late submissions for the contest).
You cannot duplicate logic puzzles or scenarios from published sources, including commericial adventure games or publicly available interactive fiction. (Parodies are OK.)
Your game must implement at least one significant internal design
change above and beyond the base-level requirements. For example,
you might decide to add characters to your game (non-players that
move locations on their own), or you might add a special "magical
transporter" location that zaps you randomly to a new location within
your game, or you might provide your own parser that understands
three-word sentences (like "give wand troll"), or you
might add special features of rooms that can only be discovered
(and shown in the room description) when the player searches for
them or performs some special action. The game feature is up to
you, but it must require a significant implementation enhancement
above that needed for the base-level requirements.
The README.TXT file for your project (you know, the
little icon in the upper left of your project that looks like a page),
must start with a written summary of your game not to exceed
200 words. Your summary must describe the significant feature(s)
you have implemented above and beyond the base-level requirements.
Further, your summary must describe the most interesting and innovative
aspects of your game. Remember--we don't have time to play
200 adventure games during the last week of classes, so this summary
is your chance to "sell" the merits of your work. Given a huge pile
of entries, we'll use summaries to determine which ones we want to
look at in-depth.
After the summary, the README.TXT file should also
include a complete walkthrough of your game. That sounds like a
lot of work, but it isn't too hard. In BlueJ, use View->Show
Terminal, then choose Options->Unlimited buffering from the terminal
window. Now start your game, and play it through to the end. Now
use your mouse to select all of the text from the terminal window
and copy it to the clipboard using Ctrl-C. Open your
README.TXT file and paste it on the end. Now you have
an instant transcript of the entire game!
To submit to the contest, first submit program 6 as usual. Second,
submit your program a second time using the
Adventure Contest submission selection
(also under "CS 1705 Programs" in the BlueJ submitter).
You won't get any feedback other than a submission confirmation, and
you won't receive any meaningful grade information.
Remember that to participate in the contest, you must submit two times,
once each
to both Program 6 and Adventure
Contest. If you only submit to Program 6, your
code will not be considered for the contest. If you only submit to
Adventure Contest, then your code will not appear for
grading by your TA and you won't get credit for completing this assignment.
Good luck to all students who choose to participate in the contest, and have fun with it!
| Home | Notes | Homework | Labs | Programs |