Home  |   Notes  |   Homework  |   Labs  |   Programs
Program 6: Adventure

Due midnight the evening of 12/05

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!

 
Learning Objectives
  •  Exposure to object-oriented dispatch
  •  Familiarity with interfaces
  •  Familiarity with creating subclasses
  •  Familiarity with overriding methods
  •  Familiarity with polymorphism
  •  Familiarity with using library classes
  • 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:

    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:

    All together, the classes in the cs1705.adventure and their relationships are summarized in this simplified UML diagram:

    cs1705.adventure class 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:

    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:

    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:

    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

    copyright © 2003 Virginia Tech, ALL RIGHTS RESERVED
    Last modified: December 03, 2003, 10:39:46 am EST, by Stephen Edwards <edwards@cs.vt.edu>