////////////////////////////////
//  File:        Doom.java    // 
//  Programmer:  Marc Douet   //
//  Date:        09/22/03     //
////////////////////////////////

import java.util.*;
import java.io.*;



//////////////////////////////////////////////////////////////////////////
//  Class Name:  Doom                  			   	            //
//							                              //
//  Description: Main driver class of the Doom Path Finder.  It is      //
//               responsible for reading in input, finding a path for   //
//               the explorer (if one is possible), and printing the	//
//		     results.                                               //
//////////////////////////////////////////////////////////////////////////
public class Doom {

	////////////////////
	//  Data Members  //
	////////////////////
	private String 		tag;		        // String to read in the START/END tag.
	private String 		line;		        // String to hold a line from input.
	private StringTokenizer tokenBuffer;        // Tokenizer to grab each data element.
	private BufferedReader 	in;		        // Buffered Reader to read in input.
	private String		startingRoomString; // String used to read in starting room.
	private String		numRoomsString;	  // String used to read in room count.
	private String		inputLine;	        // Line of input.
	private String		roomString;	        // String used to read in room info.
	private String		nextRoomString;	  // String to hold the room a door leads to.
	private int             startingRoom;       // The room the door man will start in.
	private int             numRooms;	        // The number of rooms in the house.
	private int             totalNumDoors;	  // Number of doors in the house.
	private int             nextRoom;	        // Room a door leads to (read from input).
      private int             numKeysHeld;        // Number of keys the traveler is holding.
	private Room[]		rooms;		  // List of all rooms in the house.
      private char[]          keysHeld;           // Keys the travels has picked up.

	private final int       MIN_ROOM_COUNT = 1;   // The minimum number of rooms.
	private final int       MAX_ROOM_COUNT = 20;  // The maximum number of rooms.
      private final int       MAX_KEY_COUNT  = 2600;// The maximum number of keys.
	

	////////////////////////
	//  Member Functions  //
	////////////////////////
	//////////////////////////////////////////////////////////////////
	// Function:  Constructor				                //
	// 							                      //
	// Synopsis:  public Doom(void)				          //
	//							                      //
	// Description: Initializes all data members of the Door Man    //
	//	          Path Finder.			                      //
      //                                                              //
	// Return Value: None.					                //
	//////////////////////////////////////////////////////////////////
	public Doom()
	{
		// Initialize all data members.
		in = new BufferedReader(new InputStreamReader(System.in));
		tag = null;			
		line = null;			
		tokenBuffer = null;			
		startingRoomString = null;
		numRoomsString = null;
		roomString = null;
		inputLine = null;
		nextRoomString = null;
		startingRoom = -1;
		numRooms = 0;
		totalNumDoors = 0;
		nextRoom = -1;
            numKeysHeld = 0;
		rooms = new Room[MAX_ROOM_COUNT];
            keysHeld = new char[MAX_KEY_COUNT];

            for(int keyIndex = 0; keyIndex < MAX_KEY_COUNT; keyIndex++)
                keysHeld[keyIndex] = '\0';
	}


	//////////////////////////////////////////////////////////////////
	// Function:  reinitDoom			                      //
	// 								                //
	// Synopsis:  public void reinitDoom(void)	                //
	// 								                //
	// Description: Reinitializes the path finder so the object can //
	//		    be re-used.  This is called after each iteration//
	//		    through the Start() loop.			          //
	//								                //
	// Return Value: None.						          //
	//////////////////////////////////////////////////////////////////
	public void reinitDoom()
	{
		// Reinitialize all Room objects:
		for(int roomIndex = 0; roomIndex < numRooms; roomIndex++)
			rooms[roomIndex].reinitRoom();

            for(int keyIndex = 0; keyIndex < MAX_KEY_COUNT; keyIndex++)
                keysHeld[keyIndex] = '\0';

		// Reinitialize all Doom member variables:
		tag = null;			
		line = null;			
		tokenBuffer = null;			
		startingRoomString = null;
		numRoomsString = null;
		roomString = null;
		inputLine = null;
		nextRoomString = null;
		startingRoom = -1;
		numRooms = 0;
		totalNumDoors = 0;
		nextRoom = -1;
            numKeysHeld = 0;
	}

	
	//////////////////////////////////////////////////////////////////
	// Function:  start						          //
	// 								                //
	// Synopsis:  public void start(void)				    //
	// 								                //
	// Description: Starts the path finder by reading the data set  //
	//              building the rooms with doors connecting them,  //
	//		    finding the path, and printing the outcome.	    //
	//								                //
	// Return Value: None.						          //
	//////////////////////////////////////////////////////////////////
	public void start()
	{
		// Read in the first line of input.
		try {
                	line = in.readLine();
			tokenBuffer = new StringTokenizer(line);
			tag = tokenBuffer.nextToken();
            	} catch(IOException ioError) {
			System.out.println(
				"Error occurred while reading in the first line of input.");
                	ioError.printStackTrace();
			System.exit(1);
            	}

		// While we have found a START tag...
		while((tag != null) && (tag.equals("START"))) {
			// Get the starting room from the token buffer.
                	startingRoomString = tokenBuffer.nextToken();
            		
			// Get the number of rooms from the token buffer.
                	numRoomsString = tokenBuffer.nextToken();
            		
			// If this is an invalid room count, print an error and exit 1.
			numRooms = Integer.parseInt(numRoomsString);
			if((numRooms < MIN_ROOM_COUNT) 
					|| 
				(numRooms > MAX_ROOM_COUNT)) {
				System.out.println("Error: " + numRooms 
					+ " is an invalid room count.");
				System.exit(1);
			}

			// If this is an invalid room number, print an error and exit 1.
			startingRoom = Integer.parseInt(startingRoomString);
			if((startingRoom < MIN_ROOM_COUNT-1) 
					|| 
				(startingRoom > numRooms-1)) {
				System.out.println("Error: " + startingRoom 
					+ " is an invalid room number.");
				System.exit(1);
			}

			// Build the house by reading in all rooms and adding doors 
			// connecting them together.
			buildHouse();

			// Read in the END Tag.
			try {
				tag = null;
				line = null;
                		line = in.readLine();
				tokenBuffer = new StringTokenizer(line);
				tag = tokenBuffer.nextToken();
            		} catch(IOException ioError) {
				System.out.println(
					"Error occurred while reading in the End Tag.");
                		ioError.printStackTrace();
				System.exit(1);
            		}

			// IF the END Tag was not found, print an error and exit 1.
			if(!tag.equals("END")) {
				System.out.println(
					"Error: No END tag was found after the data set.");
				System.exit(1);
			}

			// Find a path for the door man and print the results.
			if(findPath(startingRoom))
				System.out.println("YES");
			else	System.out.println("NO");

			// Reinitialize the Doom object for the next data set run:
			reinitDoom();

			// Try to read the next START Tag/Player Count pair.
			try {
                		line = in.readLine();
            		} catch(IOException ioError) {
				System.out.println(
			   "Error occurred while reading in the start of the next data set.");
                		ioError.printStackTrace();
				System.exit(1);
            		}
			
			// If we were able to read another data line, tokenize and get the tag.
			try {
				if(line.startsWith("START")) {
					tokenBuffer = new StringTokenizer(line);
					tag = tokenBuffer.nextToken();
				}
			} catch(NullPointerException ptrError) {}
		}
	}


	//////////////////////////////////////////////////////////////////
	// Function:  buildHouse					          //
	//								                //
	// Synopsis:  public void buildHouse(void)			    //
	//								                //	      
	//								                //
	// Description: Build the house by building all room objects.   //
	//		    This includes adding doors to each room using   //
	//		    the inputted room numbers for each room's door. //
	//								                //
	// Return Value: None.						          //
	//////////////////////////////////////////////////////////////////
	public void buildHouse()
	{
		// For each line of input, read in the line, and add a door
		// connecting that room to the room the door leads to:
		for(int roomIndex = 0; roomIndex < numRooms; roomIndex++) {
			try {
                		inputLine = in.readLine();
				tokenBuffer = new StringTokenizer(inputLine);
				
				// Build the Room if it hasn't been built already:
				if(rooms[roomIndex] == null)
					rooms[roomIndex] = new Room();

				// Add all doors in the room and keep track of the door count:
				int tokenCount = tokenBuffer.countTokens();
				totalNumDoors += tokenCount;
				for(int tokenIndex = 0; tokenIndex < tokenCount; tokenIndex++) {
                              String keyList = "";
                              int    keyIndex;
					nextRoomString = "";
					nextRoomString = tokenBuffer.nextToken();

                              // Determine where the room number ends in the string.
                              for(keyIndex = 0; keyIndex < nextRoomString.length(); keyIndex++) {
                              	if(!Character.isDigit(nextRoomString.charAt(keyIndex)))
                                        break;
                              }

                              // If we didn't find a room number, that is bad!
                              if(keyIndex == 0) {
                                  System.out.println("Error: No room number was found preceeding the key list!");
                                  System.exit(1);
                              }

                              // If we didn't find a key list...
                              if(keyIndex == nextRoomString.length()) {
                              	keyIndex--;

                                    // If there is just one digit in the room number, just parse one character.
                                    if(keyIndex < 1) {
                                    	nextRoom = Integer.parseInt(nextRoomString.substring(0));                           
                                    }
                     
                                    // Else parse the whole string.
                                    else {
                                    	nextRoom = Integer.parseInt(nextRoomString.substring(0, keyIndex+1));
                                    }
                              }

                              // Else we found a key list, so parse it and the room number.
                              else {
                                    nextRoom = Integer.parseInt(nextRoomString.substring(0, keyIndex));
						keyList  = nextRoomString.substring(keyIndex);    
					} 

              			rooms[roomIndex].addDoorToRoom(nextRoom, keyList);
					
					if(rooms[nextRoom] == null)
						rooms[nextRoom] = new Room();
                                        
                    		rooms[nextRoom].addDoorToRoom(roomIndex, keyList);
				}
            		} catch(IOException ioError) {
				System.out.println(
					"Error occurred while reading in the room info.");
                		ioError.printStackTrace();
				System.exit(1);
            		}
		}

                // For each line of input, read in the line, and add the list of keys
                // that are found in that room:
                for(int roomIndex = 0; roomIndex < numRooms; roomIndex++) {
                        try {
                                inputLine = in.readLine();
                                tokenBuffer = new StringTokenizer(inputLine);

                                // Add all keys to the room:
                                int tokenCount = tokenBuffer.countTokens();
                                for(int tokenIndex = 0; tokenIndex < tokenCount; tokenIndex++) {
                                        String keyList = tokenBuffer.nextToken();
                                        rooms[roomIndex].addKeysToRoom(keyList);
                                }
                        } catch(IOException ioError) {
                                System.out.println(
                                        "Error occurred while reading in the room info.");
                                ioError.printStackTrace();
                                System.exit(1);
                        }
        	}
	}


	//////////////////////////////////////////////////////////////////
	// Function:  enterRoom						          //
	//								                //
	// Synopsis:  public int enterRoom(int oldRoom, int newRoom)    //
	//	        oldRoom	[IN]	Room ID of room we came from.	    //
	//	        newRoom	[IN]	Room ID of room we're entering.   //
	//								                //
	// Description: Enter a room by closing the door for both rooms //
	//		    and returning the ID of the new current room.   //
	//								                //
	// Return Value: The ID of the room we have entered.		    //
	//////////////////////////////////////////////////////////////////
	public int enterRoom(int oldRoom, int newRoom)
	{ 
     		rooms[newRoom].setLastRoomVisited(oldRoom);
		return newRoom;
	}


	//////////////////////////////////////////////////////////////////
	// Function:  leaveRoom						          //
	//								                //
	// Synopsis:  public void leaveRoom(int roomNum)		    //
	//	        roomNum	[IN]	Room ID of room we are leaving.   //
	//								                //
	// Description: Called when a dead end is hit and we need to    //
	//		    back out of the current room, opening the door  //
	//		    backing up and re-initializing previous room.   //
	//								                //
	// Return Value: None.						          //
	//////////////////////////////////////////////////////////////////
	public void leaveRoom(int roomNum)
	{
   		int previousRoom = rooms[roomNum].getLastRoomVisited();
            
		// Only close the doors if we actually came from a room, also return the keys:
		if(previousRoom != -1) {
			rooms[roomNum].doors[previousRoom].closeDoor();
                  numKeysHeld = rooms[roomNum].returnKeys(keysHeld, numKeysHeld);
			rooms[previousRoom].doors[roomNum].closeDoor();
                        
     		}
	}


	//////////////////////////////////////////////////////////////////
	// Function:  findPath						          //
	// 								                //
	// Synopsis:  private boolean findPath(int currentRoom)	    //
	//								                //
	// Desciption: Uses recursion to try every possible path to find//
	//             a path where the door man makes it back to his   //
	//	         room after closing all doors in the house.	    //
	//								                //
	// Return Value: true if a path was found			          //
	//		     false if the path came to a dead end		    //
	//////////////////////////////////////////////////////////////////
	private boolean findPath(int currentRoom)
	{
		// Save a copy of the last room visited before this room:
		int lastRoom = rooms[currentRoom].getLastRoomVisited();

		// BASE CASE - IF CurrentRoom is Room 0, return true:
		if(currentRoom == 0) 
			return true;
		
            // Pick up keys found in the current room.
            numKeysHeld = rooms[currentRoom].pickUpKeys(keysHeld, numKeysHeld);

		// FOR every door in CurrentRoom...
		for(int doorIndex = 0; doorIndex <= rooms[currentRoom].maxDoorNum; doorIndex++) {
     			// IF the door is open and it leads to a room...
			if(rooms[currentRoom].doors[doorIndex].openDoor(keysHeld, numKeysHeld)) {
			    // Enter the room the door leads to and continue 
			    // searching from there.  IF there is a path, return true:
			    int newRoom =  rooms[currentRoom].doors[doorIndex].getRoomDoorOpensTo();

			    if(findPath(enterRoom(currentRoom, newRoom))) 
			        return true;
			}
		}

		// IF we got here, there are no more doors in this room to try, so back up
		// and return false, restoring the original last room visited:
		rooms[currentRoom].setLastRoomVisited(lastRoom);
		leaveRoom(currentRoom);
		
		return false;
	}


	//////////////////////////////////////////////////////////////////
	//  Function:  main						          //
	//								                //
	//  Synopsis:  public static void main(String args[])		    //
	//	         args  [IN]  Not used.				    //
	//								                //
	//  Description: The main driver of the Door Man Path Finder.   //
	//	           Creates an instance of the path finder, and    //
	//		     starts it up.				          //
	//								                //
	//  Return Value: None.						          //
	//////////////////////////////////////////////////////////////////
	public static void main(String args[])
	{
		// Create an instance of the Door Man Path Finder
		Doom pathFinder = new Doom();	

		// Start the Door Man Path Finder
		pathFinder.start();

		// We are done, so exit without errors.
		System.exit(0);
	}
}



///////////////////////////////////////////////////////////////////////////
//  Class Name:  Room	                 				             //
//									                   //
//  Description: Object to represent the state of each room in the house.//
///////////////////////////////////////////////////////////////////////////
class Room {

	////////////////////
	//  Data Members  //
	////////////////////
	private int		lastRoomVisited; // The room visited before this room.
	public  int		maxDoorNum;	     // The largest door number so far.
      public  int       numKeys;         // The number of keys found in this room.
	public Door[]	doors;           // List of doors in this room.
      public char[]     keys;            // List of keys in this room.

	private final int	MAX_DOOR_COUNT = 20;  // The max number of doors.
      private final int MAX_KEY_COUNT  = 26;  // The max number of keys per room.


	////////////////////////
	//  Member Functions  //
	////////////////////////
	//////////////////////////////////////////////////////////////////
	// Function:  Constructor					          //
	//								                //
	// Synopsis:  public Room(void)					    //
	//								                //
	// Description: Create an instance of the Room object by 	    //
	//              intializing all of it's data members.		    //
	//								                //
	// Return Value: None.						          //
	//////////////////////////////////////////////////////////////////
	public Room()
	{
		lastRoomVisited = -1;
		maxDoorNum = -1;
            numKeys = 0;
		doors = new Door[MAX_DOOR_COUNT];
            keys = new char[MAX_KEY_COUNT];
		
		for(int doorIndex = 0; doorIndex < MAX_DOOR_COUNT; doorIndex++)
			doors[doorIndex] = new Door();

            for(int keyIndex = 0; keyIndex < MAX_KEY_COUNT; keyIndex++)
                  keys[keyIndex] = '\0';
	}


	//////////////////////////////////////////////////////////////////
	// Function:  reinitRoom					          //
	// 								                //
	// Synopsis:  public void reinitRoom(void)			    //
	// 								                //
	// Description: Reinitializes the Room object so the object can //
	//		    be re-used.  This is called by the Doom re-	    //
	//		    init method.					          //
	//								                //
	// Return Value: None.						          //
	//////////////////////////////////////////////////////////////////
	public void reinitRoom()
	{
		// Reinitialize all member variables:
		lastRoomVisited = -1;
		maxDoorNum = -1;
            numKeys = 0;

		// Reinitialize all Door objects:
		for(int doorIndex = 0; doorIndex < MAX_DOOR_COUNT; doorIndex++)
			doors[doorIndex].reinitDoor();

            for(int keyIndex = 0; keyIndex < MAX_KEY_COUNT; keyIndex++)
                  keys[keyIndex] = '\0';
	}

	
	//////////////////////////////////////////////////////////////////
	// Function:  addDoorToRoom					          //
	//								                //
	// Synopsis:  public void addDoorToRoom(int roomNum)		    //
	//	        roomNum	[IN]	Room ID of the room the new door  //
	//				      will open to.			    //
	//								                //
	// Description: Add this door to this room and mark as opening  //
	//		    to the room passed in.				    //
	//								                //
	// Return Value: None.						          //
	//////////////////////////////////////////////////////////////////
	public void addDoorToRoom(int roomNum, String locks)
	{
      	int  numLocks = locks.length();
            char lockList[] = new char[numLocks];

            for(int lockIndex = 0; lockIndex < numLocks; lockIndex++)
                  lockList[lockIndex] = locks.charAt(lockIndex);

		// Add the door to the list of doors for this room:
		doors[roomNum].addDoor(roomNum, lockList, numLocks);

		// Update the max door number seen so far if necessary:
		if(roomNum > maxDoorNum)
			maxDoorNum = roomNum;
	}


        //////////////////////////////////////////////////////////////////
        // Function:  addKeysToRoom                                     //
        //                                                              //
        // Synopsis:  public void addKeysToRoom(char keys[])            //
        //              roomNum [IN]    Room ID of the room the new door//
        //                              will open to.                   //
        //                                                              //
        // Description: Add the list of keys found in this room.        //
        //                                                              //
        // Return Value: None.                                          //
        //////////////////////////////////////////////////////////////////
        public void addKeysToRoom(String keyList)
        {
            int  keyCount = keyList.length();

            for(int keyIndex = 0; keyIndex < keyCount; keyIndex++) {
                keys[numKeys++] = keyList.charAt(keyIndex); 
            }
        }

      
        //////////////////////////////////////////////////////////////////
        // Function:  pickUpKeys                                        //
        //                                                              //
        // Synopsis:  public int pickUpKeys(char keysList[],            //
        //                                  int numKeysHeld)            //
        //                                                              //
        //            keysList    [IN/OUT] List of keys held.           //
        //            numKeysHeld [IN/OUT] Number of keys held.         //
        //                                                              //
        // Description: Add the list of keys found in this room to the  //
        //              traveler's list of keys held and return the     //
        //              number of keys he's holding afterwards.         //
        //                                                              //
        // Return Value: None.                                          //
        //////////////////////////////////////////////////////////////////
        public int pickUpKeys(char keysList[], int numKeysHeld)
        {
            for(int keyIndex = 0; keyIndex < numKeys; keyIndex++) {
                keysList[numKeysHeld++] = keys[keyIndex];
            }
         
            return numKeysHeld;
        }


        //////////////////////////////////////////////////////////////////
        // Function:  returnKeys                                        //
        //                                                              //
        // Synopsis:  public int returnKeys(char keysList[],            //
        //                                  int numKeysHeld)            //
        //                                                              //
        //            keysList    [IN/OUT] List of keys held.           //
        //            numKeysHeld [IN/OUT] Number of keys held.         //
        //                                                              //
        // Description: Remove the list of keys found in this room from //
        //              the traveler's list of keys held and return the //
        //              number of keys he's holding afterwards.         //
        //                                                              //
        // Return Value: None.                                          //
        //////////////////////////////////////////////////////////////////
        public int returnKeys(char keysList[], int numKeysHeld)
        {
            int totalKeysHeld = numKeysHeld;

            if(numKeysHeld <= 0)
                return numKeysHeld;

            for(int keyIndex = 0; keyIndex < numKeys; keyIndex++) {
                for(int keyHeldIndex = 0; keyHeldIndex < totalKeysHeld; keyHeldIndex++) {
                    if(keysList[keyHeldIndex] == keys[keyIndex]) {
                        keysList[keyHeldIndex] = '\0';
                        numKeysHeld--;
                        break;
                    }
                }
            }

            return numKeysHeld;
        }


	//////////////////////////////////////////////////////////////////
	// Function:  setLastRoomVisited				          //
	//								                //
	// Synopsis:  public void setLastRoomVisited(int roomNum)	    //
	//	        roomNum	[in]	ID of the room to set as the 	    //
	//	                        room that was visited last.	    //
	//	      							          //
	// Description: Set the room last visited before entering this  //
	//		    room.						          //
	//								                //
	// Return Value: None.						          //
	//////////////////////////////////////////////////////////////////
	public void setLastRoomVisited(int roomNum)
	{	
		lastRoomVisited = roomNum;
	}
		

	//////////////////////////////////////////////////////////////////
	// Function:  getLastRoomVisited				          //
	//								                //
	// Synopsis:  public int getLastRoomVisited(void)		    //
	//	      							          //
	// Description: Get the room last visited before entering this  //
	//		    room.						          //
	//								                //
	// Return Value: Returns the ID of the room visited last.	    //
	//////////////////////////////////////////////////////////////////
	public int getLastRoomVisited()
	{	
		return lastRoomVisited;
	}
}



//////////////////////////////////////////////////////////////////////////
//  Class Name:  Door	                 				            //
//									                  //
//  Description: Object to represent the state of each door in a room.	//
//////////////////////////////////////////////////////////////////////////
class Door {

	////////////////////
	//  Data Members  //
	////////////////////
	private boolean   isClosed;      // Tells if this door is closed.
	private int	      opensTo;       // Tells where this door opens to.
	public  int	      numInstances;  // Tells how many instances of this door exist.
      public  char[][]  locks;         // List of keys required to unlock this door.        
      private final int MAX_LOCK_COUNT = 26;  // The max number of locks per door.
      private final int MAX_INSTANCES  = 20;  // The max number of instances of this door. 


	////////////////////////
	//  Member Functions  //
	////////////////////////
	//////////////////////////////////////////////////////////////////
	// Function:  Constructor					          //
	//								                //
	// Synopsis:  public Door(void)					    //
	//								                //
	// Description: Create an instance of the Door object by 	    //
	//              intializing all of it's data members.		    //
	//								                //
	// Return Value: None.						          //
	//////////////////////////////////////////////////////////////////
	public Door()
	{
		isClosed = true;
		opensTo = -1;
		numInstances = 0;
            locks = new char[MAX_INSTANCES][MAX_LOCK_COUNT];

            for(int instanceIndex = 0; instanceIndex < MAX_INSTANCES; instanceIndex++)
                for(int lockIndex = 0; lockIndex < MAX_LOCK_COUNT; lockIndex++)
                    locks[instanceIndex][lockIndex] = '\0'; 
	}


	//////////////////////////////////////////////////////////////////
	// Function:  reinitDoor					          //
	// 								                //
	// Synopsis:  public void reinitDoor(void)			    //
	// 								                //
	// Description: Reinitializes the Door object so the object can //
	//		    be re-used.  This is called by the Room reinit  //
	//		    method.						          //
	//								                //
	// Return Value: None.						          //
	//////////////////////////////////////////////////////////////////
	public void reinitDoor()
	{
		// Reinitialize all member variables:
		isClosed = true;
		opensTo = -1;
		numInstances = 0;

            for(int instanceIndex = 0; instanceIndex < MAX_INSTANCES; instanceIndex++)
                for(int lockIndex = 0; lockIndex < MAX_LOCK_COUNT; lockIndex++)
                    locks[instanceIndex][lockIndex] = '\0';
	}


	//////////////////////////////////////////////////////////////////
	// Function:  addDoor						          //
	//								                //
	// Synopsis:  public void addDoor(int doorNum, char keys[])	    //
	//								                //
	// Description: Add this door to a room by setting what room    //
	//		    this door will open to and incrementing the     //
	//		    number of instances created so far.		    //
	//								                //
	// Return Value: None.						          //
	//////////////////////////////////////////////////////////////////
	public void addDoor(int doorNum, char keys[], int numKeys)
	{
      	for(int index = 0; index < numKeys; index++) {
            	locks[numInstances][index] = keys[index];
         	}
	
		opensTo = doorNum;
          	numInstances++;
	}

	
	//////////////////////////////////////////////////////////////////
	// Function:  openDoor						          //
	//								                //
	// Synopsis:  public void openDoor(char keys[], int numKeys)    //
	//								                //
      //            keys    [IN]  Keys the traveler is holding        //
      //            numkeys [IN] Num keys the traveler is holding     //
      //                                                              //
	// Description: Determine whether the traveler can unlock this  //
      //              door, and if so mark this door as 'opened'.	    //
	//								                //
	// Return Value: TRUE if the traveler was able to unlock and    //
      //               open the door, FALSE otherwise.	          //
	//////////////////////////////////////////////////////////////////
	public boolean openDoor(char keys[], int numKeys)
	{
      	boolean FoundMatch = false,
                    FoundLock  = false;
          	int     instanceIndex,
                    lockIndex,
                    keyIndex;

            // IF this door is already open or it it leads nowhere, return false.
         	if(!doorIsClosed() || opensTo == -1) {
                return false; 
            }

            
            for(instanceIndex = 0; instanceIndex < numInstances; instanceIndex++) {
            	for(lockIndex = 0; lockIndex < MAX_LOCK_COUNT; lockIndex++) {
                  	if(locks[instanceIndex][lockIndex] == '\0')
                        	break;
                        else  FoundLock = true;

                        for(keyIndex = 0; keyIndex < numKeys; keyIndex++) {
                            if(locks[instanceIndex][lockIndex] == keys[keyIndex]) {
                                FoundMatch = true; 
                                break;  
                            }
                        }

                        if(keyIndex >= numKeys) {
                            FoundMatch = false;
                            break;
                        }
                    }

                if(FoundMatch) {
                    isClosed = false;
                    break;
                }
            }

            if(!FoundLock) {
                	isClosed = false;
                	return true;
            }
      	else  return FoundMatch;
	}


      //////////////////////////////////////////////////////////////////
	// Function:  closeDoor  					          //
	//								                //
	// Synopsis:  public void closeDoor(void)           		    //
	//	      							          //
	// Description: Mark this door as closed.              	    //
	//								                //
	// Return Value: None                                           //
	//////////////////////////////////////////////////////////////////
    	public void closeDoor()
      {
      	isClosed = true;
    	}


	//////////////////////////////////////////////////////////////////
	// Function:  doorIsClosed					          //
	//								                //
	// Synopsis:  public boolean doorIsClosed(void)			    //
	//	      							          //
	// Description: Tell whether this door is closed or not.	    //
	//								                //
	// Return Value: true if the door is closed, false if its open. //
	//////////////////////////////////////////////////////////////////
	public boolean doorIsClosed()
	{	
		return isClosed;
	}

	
	//////////////////////////////////////////////////////////////////
	// Function:  getRoomDoorOpensTo				          //
	//								                //
	// Synopsis:  public int getRoomDoorOpensTo(void)		    //
	//	      							          //
	// Description: Returns the room this door opens to.		    //
	//								                //
	// Return Value: The ID of the room this door opens to.	    //
	//////////////////////////////////////////////////////////////////
	public int getRoomDoorOpensTo()
	{	
		return opensTo;
	}
}