package student.adventure; /** * This class is the main class for a "World of Zuul"-style adventure * game application. * "World of Zuul" is a very simple, text based adventure game. Users * can walk around some scenery. That's all. It should really be extended * to make it more interesting! * * To play this game, create your own subclass of Game, and define * your own {@link #createCommands()}, {@link #createRooms()}, * and {@link #welcomeMessage()} methods. Then create an instance * of your subclass and call the {@link #play()} method. * * This main class creates and initialises all the others: it creates all * rooms, creates the parser and starts the game. * * @author Stephen Edwards (based on original by Michael Kolling * and David J. Barnes) * @version 2003.11.10 */ public abstract class Game { private Parser parser; private Player player; private boolean initialized = false; /** * Create the game and initialise its internal map. * This also creates a {@link Player} to represent the player, * and a {@link Parser} to parse player commands. * The internal map is determined by the {@link #createRooms()} * method, and the list of supported commands is determined * by the {@link #createCommands()} method. */ public Game() { this( new Player(), new Parser() ); } /** * Create the game and initialise its internal map. * The provided {@link Player} object is used to represent the * player, and the provided {@link Parser} object is used to * parse player commands. This allows custom subclasses of * Player or Parser to be used if desired. * The internal map is determined by the {@link #createRooms()} * method, and the list of supported commands is determined * by the {@link #createCommands()} method. * @param player The player object to use * @param parser The parser to use */ public Game( Player player, Parser parser ) { this.player = player; this.parser = parser; // Cannot call these for initialization here, since // they are defined in a subclass and might therefore refer // to subclass fields that have not yet been initialized. // use lazy evaluation instead. // --- // createCommands(); // createRooms(); } /** * Make sure that the create methods have been called before * anything else. */ private void ensureInitialization() { if ( !initialized ) { initialized = true; createCommands(); createRooms(); } } /** * Access this game's player. * @return The player */ public final Player player() { ensureInitialization(); return player; } /** * Access this game's parser. * @return The parser */ public final Parser parser() { ensureInitialization(); return parser; } /** * Create all the commands this game knows about. * A subclass must define this method to provide its * own set of commands and associated words. A new * command is typically added like this: * <pre> * parser().commandWords.addCommand( "go", new GoCommand() ); * </pre> */ public abstract void createCommands(); /** * Create all the rooms and link their exits together. * A subclass must define this method to provide its * own map of rooms. */ public abstract void createRooms(); /** * Main play routine. Loops until end of play. */ public void play() { ensureInitialization(); printWelcome(); // Enter the main command loop. Here we repeatedly read commands and // execute them until the game is over. boolean finished = false; while(! finished) { Command command = parser.getCommand(); if(command == null) { System.out.println("I don't understand what you mean ..."); } else { finished = command.execute(player); } } System.out.println("Thank you for playing. Good bye."); } /** * Print out the opening message for the player. */ public void printWelcome() { ensureInitialization(); System.out.println(); System.out.println( welcomeMessage() ); System.out.println(); System.out.println(player.getCurrentRoom().getLongDescription()); } /** * Returns the welcome message printed when the game starts. * A subclass must define this method to provide the content of * the welcome message. * @return The welcome message */ public abstract String welcomeMessage(); }