protected List<Room> findWorldRoomsLiberally(MOB mob,
												 String cmd,
												 String srchWhatAERIPMVK,
												 Area area,
												 boolean returnFirst,
												 int timePct,
												 long maxMillis)
	{
		Room room=null;
		// wish this stuff could be cached, even temporarily, however,
		// far too much of the world is dynamic, and far too many searches
		// are looking for dynamic things.  the cached results would be useless
		// as soon as they are put away -- that's why the limited caches time them out!
		final boolean disableCaching= CMProps.getBoolVar(CMProps.Bool.MAPFINDSNOCACHE);

		final Vector<Room> rooms=(returnFirst)?null:new Vector<Room>();
		final Room curRoom=(mob!=null)?mob.location():null;

		boolean searchWeakAreas=false;
		boolean searchStrictAreas=false;
		boolean searchRooms=false;
		boolean searchPlayers=false;
		boolean searchItems=false;
		boolean searchInhabs=false;
		boolean searchInventories=false;
		boolean searchStocks=false;
		final char[] flags = srchWhatAERIPMVK.toUpperCase().toCharArray();
		for (final char flag : flags)
		{
			switch(flag)
			{
				case 'E': searchWeakAreas=true;   break;
				case 'A': searchStrictAreas=true; break;
				case 'R': searchRooms=true; 	  break;
				case 'P': searchPlayers=true;	 break;
				case 'I': searchItems=true; 	  break;
				case 'M': searchInhabs=true;	  break;
				case 'V': searchInventories=true; break;
				case 'K': searchStocks=true;	  break;
			}
		}
		final long startTime = System.currentTimeMillis();
		if(searchRooms)
		{
			final int dirCode=CMLib.directions().getGoodDirectionCode(cmd);
			if((dirCode>=0)&&(curRoom!=null))
				room=addWorldRoomsLiberally(rooms,curRoom.rawDoors()[dirCode]);
			if(room==null)
				room=addWorldRoomsLiberally(rooms,getRoom(cmd));
			if((room == null) && (curRoom != null) && (curRoom.getArea()!=null))
				room=addWorldRoomsLiberally(rooms,curRoom.getArea().getRoom(cmd));
		}

		if(room==null)
		{
			// first get room ids
			if((cmd.charAt(0)=='#')&&(curRoom!=null)&&(searchRooms))
			{
				room=addWorldRoomsLiberally(rooms,getRoom(curRoom.getArea().Name()+cmd));
				if(room == null)
					room=addWorldRoomsLiberally(rooms,curRoom.getArea().getRoom(curRoom.getArea().Name()+cmd));
			}
			else
			{
				final String srchStr=cmd;

				if(searchPlayers)
				{
					// then look for players
					final MOB M=CMLib.sessions().findPlayerOnline(srchStr,false);
					if(M!=null)
						room=addWorldRoomsLiberally(rooms,M.location());
				}
				if(enforceTimeLimit(startTime,maxMillis))
					return returnResponse(rooms,room);

				// search areas strictly
				if(searchStrictAreas && (room==null) && (area==null))
				{
					area=getArea(srchStr);
					if((area!=null) &&(area.properSize()>0) &&(area.getProperRoomnumbers().roomCountAllAreas()>0))
						room=addWorldRoomsLiberally(rooms,area);
					area=null;
				}
				if(enforceTimeLimit(startTime,maxMillis))
					return returnResponse(rooms,room);

				final Area A=area;
				final MultiEnumeratorBuilder<Room> roomer = new MultiEnumeratorBuilder<Room>()
				{
					@SuppressWarnings("unchecked")
					@Override
					public MultiEnumeration<Room> getList()
					{
						if(A==null)
							return new MultiEnumeration<Room>(roomsFilled());
						else
							return new MultiEnumeration<Room>(new Enumeration[]{A.getProperMap(),shipsRoomEnumerator(A)});
					}
				};

				// no good, so look for room inhabitants
				if(searchInhabs && room==null)
				{
					final Map<String,List<MOB>> finder=getMOBFinder();
					List<MOB> candidates=null;

					if((mob==null)||(mob.isMonster()))
					{
						candidates=checkMOBCachedList(finder.get(srchStr.toLowerCase()));
						if(returnFirst&&(candidates!=null)&&(candidates.size()>1))
							candidates=new XVector<MOB>(candidates.get(0));
					}
					if(candidates==null)
					{
						candidates=findInhabitants(roomer.getList(), mob, srchStr,returnFirst, timePct);
						if((!disableCaching)&&(!returnFirst)&&((mob==null)||(mob.isMonster())))
							finder.put(srchStr.toLowerCase(), candidates);

					}
					if(candidates.size()>0)
						room=addWorldRoomsLiberally(rooms,candidates);
				}
				if(enforceTimeLimit(startTime,maxMillis))
					return returnResponse(rooms,room);

				// now check room text
				if(searchRooms && room==null)
				{
					final Map<String,List<Room>> finder=getRoomFinder();
					List<Room> candidates=null;
					if((mob==null)||(mob.isMonster()))
					{
						candidates=finder.get(srchStr.toLowerCase());
						if(returnFirst&&(candidates!=null)&&(candidates.size()>1))
							candidates=new XVector<Room>(candidates.get(0));
					}
					if(candidates==null)
					{
						candidates=findRooms(roomer.getList(), mob, srchStr, false,returnFirst, timePct);
						if((!disableCaching)&&(!returnFirst)&&((mob==null)||(mob.isMonster())))
							finder.put(srchStr.toLowerCase(), candidates);
					}
					if(candidates.size()>0)
						room=addWorldRoomsLiberally(rooms,candidates);
				}
				if(enforceTimeLimit(startTime,maxMillis))
					return returnResponse(rooms,room);

				// check floor items
				if(searchItems && room==null)
				{
					final Map<String,List<Item>> finder=getRoomItemFinder();
					List<Item> candidates=null;
					if((mob==null)||(mob.isMonster()))
					{
						candidates=checkRoomItemCachedList(finder.get(srchStr.toLowerCase()));
						if(returnFirst&&(candidates!=null)&&(candidates.size()>1))
							candidates=new XVector<Item>(candidates.get(0));
					}
					if(candidates==null)
					{
						candidates=findRoomItems(roomer.getList(), mob, srchStr, false,returnFirst,timePct);
						if((!disableCaching)&&(!returnFirst)&&((mob==null)||(mob.isMonster())))
							finder.put(srchStr.toLowerCase(), candidates);
					}
					if(candidates.size()>0)
						room=addWorldRoomsLiberally(rooms,candidates);
				}
				if(enforceTimeLimit(startTime,maxMillis))
					return returnResponse(rooms,room);

				if(enforceTimeLimit(startTime,maxMillis))
					return returnResponse(rooms,room);

				// check inventories
				if(searchInventories && room==null)
				{
					final Map<String,List<Item>> finder=getInvItemFinder();
					List<Item> candidates=null;
					if((mob==null)||(mob.isMonster()))
					{
						candidates=checkInvCachedList(finder.get(srchStr.toLowerCase()));
						if(returnFirst&&(candidates!=null)&&(candidates.size()>1))
							candidates=new XVector<Item>(candidates.get(0));
					}
					if(candidates==null)
					{
						candidates=findInventory(roomer.getList(), mob, srchStr, returnFirst,timePct);
						if((!disableCaching)&&(!returnFirst)&&((mob==null)||(mob.isMonster())))
							finder.put(srchStr.toLowerCase(), candidates);
					}
					if(candidates.size()>0)
						room=addWorldRoomsLiberally(rooms,candidates);
				}
				if(enforceTimeLimit(startTime,maxMillis))
					return returnResponse(rooms,room);

				// check stocks
				if(searchStocks && room==null)
				{
					final Map<String,List<Environmental>> finder=getStockFinder();
					List<Environmental> candidates=null;
					if((mob==null)||(mob.isMonster()))
					{
						candidates=finder.get(srchStr.toLowerCase());
						if(returnFirst&&(candidates!=null)&&(candidates.size()>1))
							candidates=new XVector<Environmental>(candidates.get(0));
					}
					if(candidates==null)
					{
						candidates=findShopStock(roomer.getList(), mob, srchStr, returnFirst,false,timePct);
						if((!disableCaching)&&(!returnFirst)&&((mob==null)||(mob.isMonster())))
							finder.put(srchStr.toLowerCase(), candidates);
					}
					if(candidates.size()>0)
						room=addWorldRoomsLiberally(rooms,candidates);
				}
				if(enforceTimeLimit(startTime,maxMillis))
					return returnResponse(rooms,room);

				// search areas weakly
				if(searchWeakAreas && (room==null) && (A==null))
				{
					Area A2=findArea(srchStr);
					if((A2!=null) &&(A2.properSize()>0) &&(A2.getProperRoomnumbers().roomCountAllAreas()>0))
						room=addWorldRoomsLiberally(rooms,A2);
				}
			}
		}
		final List<Room> responseSet = returnResponse(rooms,room);
		return responseSet;
	}