title: Zuul Locked Doors
body: <p>Ex. 6.44: Add locked exits to your game. The player needs to find (or otherwise obtain) a key to unlock the exit and enter a room. (You don't need to add a new class for doors or exits to your game). Make this as general as possible - in any room, any exit could potentially be locked.</p>
  
  <p>I have no idea how to do this. One idea was to make a HashMap with direction as keys and boolean (true/false) as values. Any suggestions?</p>
  
  <pre><code>*  This class is the main class of the "World of Zuul" 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 an instance of this class and call the "play"
   *  method.
   * 
   *  This main class creates and initialises all the others: it creates all
   *  rooms, creates the parser and starts the game.  It also evaluates and
   *  executes the commands that the parser returns.
   * 
   * @author  Michael Kölling and David J. Barnes
   * @version 2011.08.08
   */
  
  public class Game 
  {
      private Parser parser;
      private Room currentRoom;
      private Room roomStack[];
      private int top;
      private Player player;
      private Character character;
      /**
       * Create the game and initialise its internal map.
       */
      public Game() 
      {
          createRooms();
          parser = new Parser();
          roomStack = new Room[500];
          top = -1;
      }
  
      /**
       * Adds character object.
       */
      public void addCharacter(Character character)
      {
          this.character = character;
      }
  
      /**
       * Returns the character object.
       */
      public Character getCharacter()
      {
          return character;
      }
  
      /**
       * Prints the items possessed by a player
       */
      public void printItem()
      {
          System.out.println(player.getItems());
      }
  
      /**
       * Create all the rooms and link their exits together.
       */
      private void createRooms()
      {
          Room outside, theater, pub, lab, office, basement, dungeon;
  
          // create the rooms
          outside = new Room("outside the main entrance of the university");
          theater = new Room("in a lecture theater");
          pub = new Room("in the campus pub");
          lab = new Room("in a computing lab");
          office = new Room("in the computing admin office");
          basement = new Room("in the basement, where the key is!");
          dungeon = new Room("in the dungeon");
  
          // initialise room exits
          outside.setExit("east", theater);
          outside.setExit("south", lab);
          outside.setExit("west", pub);
  
          theater.setExit("west", outside);
  
          pub.setExit("east", outside);
  
          lab.setExit("north", outside);
          lab.setExit("east", office);
  
          office.setExit("west", lab);
  
          basement.setExit("north", office);
          basement.addItems("key", "key to unlock door", 1);
  
          currentRoom = outside;  // start game outside
      }
  
      /**
       *  Main play routine.  Loops until end of play.
       */
      public void play() 
      {            
          String name;
          System.out.println("Enter name:");
          reader = new Scanner(System.in);
          name = reader.nextLine();
          player = new Player(name);
          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();
              finished = processCommand(command);
          }
          System.out.println("Thank you " + player.getName() + " for playing.  Good bye.");
      }
  
      /**
       * Print out the opening message for the player.
       */
      private void printWelcome()
      {
          System.out.println();
          System.out.println("Hello " + player.getName() + ",");
          System.out.println("Welcome to the World of Zuul!");
          System.out.println("World of Zuul is a new, incredibly boring adventure game.");
          System.out.println("Type 'help' if you need help.");
          System.out.println();
          System.out.println(currentRoom.getLongDescription());
      }
  
      /**
       * Given a command, process (that is: execute) the command.
       * @param command The command to be processed.
       * @return true If the command ends the game, false otherwise.
       */
      private boolean processCommand(Command command) 
      {
          boolean wantToQuit = false;
  
          if(command.isUnknown()) {
              System.out.println("I don't know what you mean...");
              return false;
          }
  
          String commandWord = command.getCommandWord();
          if (commandWord.equals("help")) {
              printHelp();
          }
          else if (commandWord.equals("go")) {
              goRoom(command);
          }
          else if (commandWord.equals("quit")) {
              wantToQuit = quit(command);
          }
          else if (commandWord.equals("back")) {
              backRoom();
          }
          else if (commandWord.equals("eat")) {
              System.out.println("You have eaten now and are not hungry anymore.");
          }
          else if (commandWord.equals("take")) {
              player.pickUpItem();
          }
          else if (commandWord.equals("drop")) {
              player.dropItem();
          }
          else if (commandWord.equals("items")) {
              printItem();
          }
          else if (commandWord.equals("eatcookie")) {
              player.eatCookie();
          }
          // else command not recognised.
          return wantToQuit;
      }
  
      // implementations of user commands:
  
      /**
       * Print out some help information.
       * Here we print some stupid, cryptic message and a list of the 
       * command words.
       */
      private void printHelp() 
      {
          System.out.println("You are lost. You are alone. You wander");
          System.out.println("around at the university.");
          System.out.println();
          System.out.println("Your command words are:");
          parser.showCommands();
      }
  
      /** 
       * Try to in to one direction. If there is an exit, enter the new
       * room, otherwise print an error message.
       */
      private void goRoom(Command command) 
      {
          if(!command.hasSecondWord()) {
              // if there is no second word, we don't know where to go...
              System.out.println("Go where?");
              return;
          }
  
          String direction = command.getSecondWord();
  
          // Try to leave current room.
          Room nextRoom = currentRoom.getExit(direction);
  
          if (nextRoom == null) {
              System.out.println("There is no door!");
          }
          else {
              push(currentRoom);
              currentRoom = nextRoom;
              if(character != null &amp;&amp; !person.hasSpoken())
              {
                  System.out.println("There is a person in this room");
                  System.out.println(character.getName() + ": " + character.getDialogue());
                  person.setHasSpoken(true);
              }
              System.out.println(currentRoom.getLongDescription());
          }
      }
  
      /**
       * Attempt to go to the previous room, and display that
       * room's information.
       */
      private void backRoom()
      {
          currentRoom = pop();
          if(currentRoom != null)
          {
              System.out.println(currentRoom.getLongDescription());
          }
      }
  
      /**
       * Add the current room to the stack.
       * @param room The room to add to the stack.
       */
      private void push(Room room)
      {
          if(top == roomStack.length-1)
          {
              System.out.println("Room stack is full.");
          }
          else
          {
              roomStack[++top] = room;
          }
      }
  
      /**
       * Deletes the room at the top of the roomStack.
       * @return Room if it exists and null otherwise.
       */
      private Room pop()
      {
          if(top&lt;0)
          {
              System.out.println("Sorry, you are outside, and there is no previous room to which you can go back.");
              return null;                    
          }
          else
          {
              return roomStack[top--];
          }
      }
  
      /** 
       * "Quit" was entered. Check the rest of the command to see
       * whether we really quit the game.
       * @return true, if this command quits the game, false otherwise.
       */
      private boolean quit(Command command) 
      {
          if(command.hasSecondWord()) {
              System.out.println("Quit what?");
              return false;
          }
          else {
              return true;  // signal that we want to quit
          }
      }
  }
  import java.util.Set;
  import java.util.HashMap;
  
  /**
   * Class Room - a room in an adventure game.
   *
   * This class is part of the "World of Zuul" application. 
   * "World of Zuul" is a very simple, text based adventure game.  
   *
   * A "Room" represents one location in the scenery of the game.  It is 
   * connected to other rooms via exits.  For each existing exit, the room 
   * stores a reference to the neighboring room.
   * 
   * @author  Michael Kölling and David J. Barnes
   * @version 2011.08.08
   */
  
  public class Room 
  {
      private String description;
      private HashMap&lt;String, Room&gt; exits;        // stores exits of this room.
      private HashMap items;
      /**
       * Create a room described "description". Initially, it has
       * no exits. "description" is something like "a kitchen" or
       * "an open court yard".
       * @param description The room's description.
       */
      public Room(String description) 
      {
          this.description = description;
          exits = new HashMap&lt;String, Room&gt;();
          items = new HashMap();
      }
  
      /**
       * Define an exit from this room.
       * @param direction The direction of the exit.
       * @param neighbor  The room to which the exit leads.
       */
      public void setExit(String direction, Room neighbor) 
      {
          exits.put(direction, neighbor);
      }
  // 
  //      /**
  //      * This sets the doors of rooms as locked or not.
  //      */
  //     public void setRoomDoors(String direction, Room room, boolean locked)
  //     {
  //         exits.put(direction, room, locked);
  //     }
  
      /**
       * @return The short description of the room
       * (the one that was defined in the constructor).
       */
      public String getShortDescription()
      {
          return description;
      }
  
      /**
       * Return a description of the room in the form:
       *     You are in the kitchen.
       *     Exits: north west
       * @return A long description of this room
       */
      public String getLongDescription()
      {
          return "You are " + description + ".\n" + getExitString();
      }
  
      /**
       * Return a string describing the room's exits, for example
       * "Exits: north west".
       * @return Details of the room's exits.
       */
      private String getExitString()
      {
          String returnString = "Exits:";
          Set&lt;String&gt; keys = exits.keySet();
          for(String exit : keys) {
              returnString += " " + exit;
          }
          return returnString;
      }
  
      /**
       * Return the room that is reached if we go from this room in direction
       * "direction". If there is no room in that direction, return null.
       * @param direction The exit's direction.
       * @return The room in the given direction.
       */
      public Room getExit(String direction) 
      {
          return exits.get(direction);
      }
  
      /**
       * This method adds items to a room.
       */
      public void addItems(String item_name, String description, int weight)
      {
          items.put(item_name, new Item(description, weight));
      }
  }
  
  /**
   * This class is part of the "World of Zuul" application. 
   * "World of Zuul" is a very simple, text based adventure game.  
   *
   * This class holds information about a command that was issued by the user.
   * A command currently consists of two strings: a command word and a second
   * word (for example, if the command was "take map", then the two strings
   * obviously are "take" and "map").
   * 
   * The way this is used is: Commands are already checked for being valid
   * command words. If the user entered an invalid command (a word that is not
   * known) then the command word is &lt;null&gt;.
   *
   * If the command had only one word, then the second word is &lt;null&gt;.
   * 
   * @author  Michael Kölling and David J. Barnes
   * @version 2011.08.08
   */
  
  public class Command
  {
      private String commandWord;
      private String secondWord;
  
      /**
       * Create a command object. First and second word must be supplied, but
       * either one (or both) can be null.
       * @param firstWord The first word of the command. Null if the command
       *                  was not recognised.
       * @param secondWord The second word of the command.
       */
      public Command(String firstWord, String secondWord)
      {
          commandWord = firstWord;
          this.secondWord = secondWord;
      }
  
      /**
       * Return the command word (the first word) of this command. If the
       * command was not understood, the result is null.
       * @return The command word.
       */
      public String getCommandWord()
      {
          return commandWord;
      }
  
      /**
       * @return The second word of this command. Returns null if there was no
       * second word.
       */
      public String getSecondWord()
      {
          return secondWord;
      }
  
      /**
       * @return true if this command was not understood.
       */
      public boolean isUnknown()
      {
          return (commandWord == null);
      }
  
      /**
       * @return true if the command has a second word.
       */
      public boolean hasSecondWord()
      {
          return (secondWord != null);
      }
  }
  
  /**
   * This class is part of the "World of Zuul" application. 
   * "World of Zuul" is a very simple, text based adventure game.
   * 
   * This class holds an enumeration of all command words known to the game.
   * It is used to recognise commands as they are typed in.
   *
   * @author  Michael Kölling and David J. Barnes
   * @version 2011.08.08
   */
  
  public class CommandWords
  {
      // a constant array that holds all valid command words
      private static final String[] validCommands = {
          "go", "quit", "help", "back", "eat", "take", "drop", "items", "eatcookie"
      };
  
      /**
       * Constructor - initialise the command words.
       */
      public CommandWords()
      {
          // nothing to do at the moment...
      }
  
      /**
       * Check whether a given String is a valid command word. 
       * @return true if it is, false if it isn't.
       */
      public boolean isCommand(String aString)
      {
          for(int i = 0; i &lt; validCommands.length; i++) {
              if(validCommands[i].equals(aString))
                  return true;
          }
          // if we get here, the string was not found in the commands
          return false;
      }
  
      /**
       * Print all valid commands to System.out.
       */
      public void showAll() 
      {
          for(String command: validCommands) {
              System.out.print(command + "  ");
          }
          System.out.println();
      }
  }
  import java.util.Scanner;
  
  /**
   * This class is part of the "World of Zuul" application. 
   * "World of Zuul" is a very simple, text based adventure game.  
   * 
   * This parser reads user input and tries to interpret it as an "Adventure"
   * command. Every time it is called it reads a line from the terminal and
   * tries to interpret the line as a two word command. It returns the command
   * as an object of class Command.
   *
   * The parser has a set of known command words. It checks user input against
   * the known commands, and if the input is not one of the known commands, it
   * returns a command object that is marked as an unknown command.
   * 
   * @author  Michael Kölling and David J. Barnes
   * @version 2011.08.08
   */
  public class Parser 
  {
      private CommandWords commands;  // holds all valid command words
      private Scanner reader;         // source of command input
  
      /**
       * Create a parser to read from the terminal window.
       */
      public Parser() 
      {
          commands = new CommandWords();
          reader = new Scanner(System.in);
      }
  
      /**
       * @return The next command from the user.
       */
      public Command getCommand() 
      {
          String inputLine;   // will hold the full input line
          String word1 = null;
          String word2 = null;
  
          System.out.print("&gt; ");     // print prompt
  
          inputLine = reader.nextLine();
  
          // Find up to two words on the line.
          Scanner tokenizer = new Scanner(inputLine);
          if(tokenizer.hasNext()) {
              word1 = tokenizer.next();      // get first word
              if(tokenizer.hasNext()) {
                  word2 = tokenizer.next();      // get second word
                  // note: we just ignore the rest of the input line.
              }
          }
  
          // Now check whether this word is known. If so, create a command
          // with it. If not, create a "null" command (for unknown command).
          if(commands.isCommand(word1)) {
              return new Command(word1, word2);
          }
          else {
              return new Command(null, word2); 
          }
      }
  
      /**
       * Print out a list of valid command words.
       */
      public void showCommands()
      {
          commands.showAll();
      }
  }
  import java.util.HashMap;
  import java.util.ArrayList;
  /**
   * Write a description of class Item here.
   * 
   * @author (your name) 
   * @version (a version number or a date)
   */
  public class Item
  {
      // instance variables - replace the example below with your own
      private String name;
      private String description;
      private int weight;
      private String magicCookie;
      private HashMap items;
      /**
       * Constructor for objects of class Item
       */
      public Item(String description, int weight)
      {
         this.name = name;
         this.description = description;
         this.weight = weight;
         items = new HashMap();
         this.magicCookie = "Cookies";
      }
  
      /**
       * This returns the description of an item.
       * @return description
       */
      public String getDescription()
      {
          return description;
      }
  
      /**
       * This returns the weight of an item.
       * @return weight
       */
      public int getWeight()
      {
          return weight;
      }
  
      /**
       * This adds items to the items HashMap.
       */
      private void addItems()
      {
          items.put("bottle", new Item("A water bottle", 1));
          items.put("camera", new Item("digital camera", 2));
          items.put("clock", new Item("wall clock", 1));
          items.put("sponge", new Item("bath sponge", 1));
          items.put("key", new Item("key to unlock door", 1));
      }
  
      /**
       * Return a description of the items contained in a room.
       * @return a description of the item with weight.
       */
      public String getItemDescription()
      {
          String itemString = "This room contains :";
          itemString = itemString + this.name + "\n";
          itemString = itemString + "Description: " + this.description + "\n";
          itemString = itemString + "Weight: " + this.weight + "\n";
          itemString = itemString + "\nThis room has cookies";
          return itemString;
      }
  }
  </code></pre>