/
com/planet_ink/coffee_mud/Abilities/Common/
com/planet_ink/coffee_mud/Abilities/Diseases/
com/planet_ink/coffee_mud/Abilities/Druid/
com/planet_ink/coffee_mud/Abilities/Fighter/
com/planet_ink/coffee_mud/Abilities/Languages/
com/planet_ink/coffee_mud/Abilities/Misc/
com/planet_ink/coffee_mud/Abilities/Prayers/
com/planet_ink/coffee_mud/Abilities/Properties/
com/planet_ink/coffee_mud/Abilities/Skills/
com/planet_ink/coffee_mud/Abilities/Songs/
com/planet_ink/coffee_mud/Abilities/Spells/
com/planet_ink/coffee_mud/Abilities/Thief/
com/planet_ink/coffee_mud/Abilities/Traps/
com/planet_ink/coffee_mud/Behaviors/
com/planet_ink/coffee_mud/CharClasses/interfaces/
com/planet_ink/coffee_mud/Commands/
com/planet_ink/coffee_mud/Commands/interfaces/
com/planet_ink/coffee_mud/Common/
com/planet_ink/coffee_mud/Common/interfaces/
com/planet_ink/coffee_mud/Exits/interfaces/
com/planet_ink/coffee_mud/Items/Armor/
com/planet_ink/coffee_mud/Items/Basic/
com/planet_ink/coffee_mud/Items/CompTech/
com/planet_ink/coffee_mud/Items/MiscMagic/
com/planet_ink/coffee_mud/Items/Weapons/
com/planet_ink/coffee_mud/Items/interfaces/
com/planet_ink/coffee_mud/Libraries/
com/planet_ink/coffee_mud/Libraries/interfaces/
com/planet_ink/coffee_mud/Locales/
com/planet_ink/coffee_mud/MOBS/
com/planet_ink/coffee_mud/Races/
com/planet_ink/coffee_mud/Races/interfaces/
com/planet_ink/coffee_mud/WebMacros/
com/planet_ink/coffee_mud/WebMacros/interfaces/
com/planet_ink/coffee_mud/core/
com/planet_ink/coffee_mud/core/collections/
com/planet_ink/coffee_mud/core/interfaces/
com/planet_ink/coffee_mud/core/intermud/
com/planet_ink/coffee_mud/core/intermud/i3/
com/planet_ink/coffee_web/server/
com/planet_ink/siplet/applet/
lib/
resources/factions/
resources/fakedb/
resources/progs/autoplayer/
resources/quests/holidays/
web/
web/admin.templates/
web/admin/grinder/
web/admin/images/
web/clan.templates/
web/pub.templates/
web/pub/images/mxp/
web/pub/sounds/
web/pub/textedit/
package com.planet_ink.coffee_mud.Libraries;

import com.planet_ink.coffee_mud.core.exceptions.ScriptParseException;
import com.planet_ink.coffee_mud.core.interfaces.*;
import com.planet_ink.coffee_mud.core.*;
import com.planet_ink.coffee_mud.core.collections.*;
import com.planet_ink.coffee_mud.Abilities.interfaces.*;
import com.planet_ink.coffee_mud.Areas.interfaces.*;
import com.planet_ink.coffee_mud.Behaviors.interfaces.*;
import com.planet_ink.coffee_mud.CharClasses.interfaces.*;
import com.planet_ink.coffee_mud.Commands.interfaces.*;
import com.planet_ink.coffee_mud.Common.interfaces.*;
import com.planet_ink.coffee_mud.Exits.interfaces.*;
import com.planet_ink.coffee_mud.Items.interfaces.*;
import com.planet_ink.coffee_mud.Libraries.interfaces.*;
import com.planet_ink.coffee_mud.Libraries.interfaces.MaskingLibrary.CompiledZapperMask;
import com.planet_ink.coffee_mud.Libraries.interfaces.MaskingLibrary.CompiledZapperMaskEntry;
import com.planet_ink.coffee_mud.Locales.interfaces.*;
import com.planet_ink.coffee_mud.MOBS.interfaces.*;
import com.planet_ink.coffee_mud.Races.interfaces.*;

import java.util.*;
/*
   Copyright 2004-2016 Bo Zimmerman

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

	   http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/
public class MUDZapper extends StdLibrary implements MaskingLibrary
{
	@Override
	public String ID()
	{
		return "MUDZapper";
	}

	public Map<String,ZapperKey> zapCodes=new Hashtable<String,ZapperKey>();

	private static class SavedRace
	{
		public final String name;
		public final String upperName;
		public final String racialCategory;
		public final String upperCatName;
		public final String nameStart;
		public final String minusNameStart;
		public final String catNameStart;
		public final String minusCatNameStart;
		public SavedRace(final Race race, final int startChars)
		{
			name=race.name();
			upperName=name.toUpperCase();
			nameStart=CMStrings.safeLeft(name.toUpperCase(),startChars);
			minusNameStart="-"+nameStart;
			racialCategory=race.racialCategory();
			upperCatName=racialCategory.toUpperCase();
			catNameStart=CMStrings.safeLeft(racialCategory.toUpperCase(),startChars);
			minusCatNameStart="-"+catNameStart;
		}
	}
	
	private static class SavedClass
	{
		public final String id;
		public final String name;
		public final String upperName;
		public final String baseClass;
		public final String nameStart;
		public final String plusNameStart;
		public final String minusNameStart;
		public final String baseClassStart;
		public final String plusBaseClassStart;
		public SavedClass(final CharClass charClass, final int startChars)
		{
			name=charClass.name();
			id=charClass.ID();
			upperName=name.toUpperCase();
			nameStart=CMStrings.safeLeft(name.toUpperCase(),startChars);
			plusNameStart="+"+nameStart;
			minusNameStart="-"+nameStart;
			baseClass=charClass.baseClass();
			baseClassStart=CMStrings.safeLeft(baseClass.toUpperCase(),startChars);
			plusBaseClassStart="+"+baseClassStart;
		}
	}
	
	public static class CompiledZapperMaskEntryImpl implements CompiledZapperMaskEntry
	{
		private final ZapperKey maskType;
		private final Object[] parms;
		
		@Override
		public ZapperKey maskType()
		{
			return maskType;
		}
		
		@Override
		public Object[] parms()
		{
			return parms;
		}
		
		public CompiledZapperMaskEntryImpl(final ZapperKey type, final Object[] parms)
		{
			maskType = type;
			this.parms = parms;
		}
	}

	public static class CompiledZapperMaskImpl implements CompiledZapperMask
	{
		private final boolean[] flags;
		private final boolean empty;
		private final CompiledZapperMaskEntry[] entries;

		@Override
		public boolean[] flags()
		{
			return flags;
		}
		
		@Override
		public boolean empty()
		{
			return empty;
		}
		
		@Override
		public CompiledZapperMaskEntry[] entries()
		{
			return entries;
		}

		public CompiledZapperMaskImpl(final boolean[] flags, final CompiledZapperMaskEntry[] entries)
		{
			this.flags = flags;
			this.entries = entries;
			this.empty = false;
		}

		public CompiledZapperMaskImpl(final boolean[] flags, final CompiledZapperMaskEntry[] entries, final boolean empty)
		{
			this.flags = flags;
			this.entries = entries;
			this.empty = empty;
		}
	}
	
	protected MOB nonCrashingMOB=null;
	protected MOB nonCrashingMOB()
	{
		if(nonCrashingMOB!=null)
			return nonCrashingMOB;
		nonCrashingMOB=CMClass.getMOB("StdMOB");
		return nonCrashingMOB;
	}

	protected Item nonCrashingItem=null;
	protected Item nonCrashingItem(final MOB mob)
	{
		if(mob.numItems()>0)
		{
			final Item I = mob.getItem(0);
			if(I!=null)
				return I;
		}
		if(nonCrashingItem!=null)
			return nonCrashingItem;
		nonCrashingItem=CMClass.getItem("StdItem");
		return nonCrashingItem;
	}

	@Override
	public String rawMaskHelp()
	{
		String maskHelp = (String)Resources.getResource("SYSTEM_ZAPPERMASK_HELP");
		if(maskHelp == null)
		{
			final CMFile F = new CMFile(Resources.makeFileResourceName("help/zappermasks.txt"),null,CMFile.FLAG_LOGERRORS);
			if((F.exists()) && (F.canRead()))
			{
				List<String> lines=Resources.getFileLineVector(F.text());
				StringBuilder str = new StringBuilder("");
				for(String line : lines)
				{
					str.append(line.trim()).append("<BR>");
				}
				maskHelp = str.toString();
			}
			else
				maskHelp = "ZAPPERMASK HELP NOT FOUND at /resources/help/zappermasks.txt!";
			Resources.submitResource("SYSTEM_ZAPPERMASK_HELP",maskHelp);
		}
		return maskHelp;
	}

	protected volatile List<SavedClass> savedCharClasses = new Vector<SavedClass>(1);
	protected volatile List<SavedRace> savedRaces = new Vector<SavedRace>(1);
	protected volatile long savedClassUpdateTime=0;
	public synchronized void buildSavedClasses()
	{
		if(savedClassUpdateTime==CMClass.getLastClassUpdatedTime())
			return;
		final List<SavedClass> tempSavedCharClasses=new LinkedList<SavedClass>();
		final List<SavedRace> tempSavedRaces=new LinkedList<SavedRace>();
		for(final Enumeration<CharClass> c=CMClass.charClasses();c.hasMoreElements();)
		{
			final CharClass C=c.nextElement();
			tempSavedCharClasses.add(new SavedClass(C,4));
		}
		for(final Enumeration<Race> r=CMClass.races();r.hasMoreElements();)
		{
			final Race R=r.nextElement();
			tempSavedRaces.add(new SavedRace(R,6));
		}
		savedCharClasses=tempSavedCharClasses;
		savedRaces=tempSavedRaces;
		savedClassUpdateTime=CMClass.getLastClassUpdatedTime();
	}

	public final List<SavedClass> charClasses()
	{
		if(savedClassUpdateTime!=CMClass.getLastClassUpdatedTime())
			buildSavedClasses();
		return savedCharClasses;
	}
	public final List<SavedRace> races()
	{
		if(savedClassUpdateTime!=CMClass.getLastClassUpdatedTime())
			buildSavedClasses();
		return savedRaces;
	}

	@Override
	@SuppressWarnings("unchecked")
	public CompiledZapperMask getPreCompiledMask(final String str)
	{
		Map<String,CompiledZapperMask> H=(Map<String,CompiledZapperMask>)Resources.getResource("SYSTEM_HASHED_MASKS");
		if(H==null)
		{
			H=new PrioritizingLimitedMap<String,CompiledZapperMask>(200, 10*60*1000, Long.MAX_VALUE, 50);
			Resources.submitResource("SYSTEM_HASHED_MASKS",H);
		}
		final String lowerStr=(str==null)?"":str.toLowerCase().trim();
		CompiledZapperMask V=H.get(lowerStr);
		if(V==null)
		{
			V=maskCompile(str);
			H.put(lowerStr,V);
		}
		return V;
	}

	@Override
	public CompiledZapperMask createEmptyMask()
	{
		return new CompiledZapperMaskImpl(new boolean[2], new CompiledZapperMaskEntry[0], true);
	}
	
	@Override
	public Map<String,ZapperKey> getMaskCodes()
	{
		if(zapCodes.size()==0)
		{
			for(ZapperKey Z : ZapperKey.values())
			{
				for(String key : Z.keys())
					zapCodes.put(key, Z);
			}
		}
		return zapCodes;
	}

	@Override
	public String maskHelp(final String CR, final String word)
	{
		String copy=rawMaskHelp();
		if((CR!=null)&&(!CR.equalsIgnoreCase("<BR>")))
			copy=CMStrings.replaceAll(copy,"<BR>",CR);
		if((word==null)||(word.length()==0))
			copy=CMStrings.replaceAll(copy,"<WORD>","disallow");
		else
			copy=CMStrings.replaceAll(copy,"<WORD>",word);
		return copy;
	}

	protected Object makeSkillFlagObject(final String str)
	{
		Object o=null;
		final int x=str.indexOf('&');
		if(x>=0)
		{
			final Vector<Object> V=new Vector<Object>();
			V.addAll(CMParms.parseAny(str,'&',true));
			String s=null;
			for(int v=0;v<V.size();v++)
			{
				s=(String)V.elementAt(v);
				if(s.startsWith("!"))
				{
					V.setElementAt(s.substring(1),v);
					V.insertElementAt(Boolean.FALSE,v);
					v++;
				}
			}
			final Object[] o2=new Object[V.size()];
			for(int v=0;v<V.size();v++)
				if(V.elementAt(v) instanceof String)
					o2[v]=makeSkillFlagObject((String)V.elementAt(v));
				else
					o2[v]=V.elementAt(v);
			for(int i=0;i<o2.length;i++)
				if((o2[i]!=null)&&(!(o2[i] instanceof Boolean)))
				{ o=o2; break;}
		}
		if(o==null)
		{
			for(int d=0;d<Ability.ACODE_DESCS.length;d++)
			{
				if(Ability.ACODE_DESCS[d].equals(str))
				{
					o=Integer.valueOf(d);
					break;
				}
			}
		}
		if(o==null)
		{
			for(int d=0;d<Ability.DOMAIN_DESCS.length;d++)
			{
				if(Ability.DOMAIN_DESCS[d].startsWith(str)||Ability.DOMAIN_DESCS[d].endsWith(str))
				{
					o=Integer.valueOf(d<<5);
					break;
				}
			}
		}
		if(o==null)
		{
			for(int d=0;d<Ability.FLAG_DESCS.length;d++)
			{
				if(Ability.FLAG_DESCS[d].startsWith(str))
				{
					o=Long.valueOf(1<<d);
					break;
				}
			}
		}
		if(o==null)
		{
			for(short d=0;d<Ability.QUALITY_DESCS.length;d++)
			{
				if(Ability.QUALITY_DESCS[d].startsWith(str)||Ability.QUALITY_DESCS[d].endsWith(str))
				{
					o=new Short(d);
					break;
				}
			}
		}
		return o;
	}

	protected boolean evaluateSkillFlagObject(final Object o, final Ability A)
	{
		if(A!=null)
		{
			if(o instanceof Object[])
			{
				final Object[] set=(Object[])o;
				for(int i=0;i<set.length;i++)
				{
					if(set[i] instanceof Boolean)
					{
						if(evaluateSkillFlagObject(set[i+1],A))
							return false;
						i++;
					}
					else
					if(!evaluateSkillFlagObject(set[i],A))
						return false;
				}
				return true;
			}
			else
			if(o instanceof Integer)
			{
				final int val=((Integer)o).intValue();
				if(((A.classificationCode()&Ability.ALL_ACODES)==val)
				||((A.classificationCode()&Ability.ALL_DOMAINS)==val))
					return true;
			}
			else
			if(o instanceof Short)
			{
				final int val=((Short)o).intValue();
				if(A.abstractQuality()==val)
					return true;
			}
			else
			if(o instanceof Long)
			{
				final long val=((Long)o).longValue();
				if((A.flags()&val)==val)
					return true;
			}
		}
		return false;
	}


	protected boolean skillFlagCheck(final List<String> V, final char plusMinus, final int fromHere, final MOB mob)
	{
		for(int v=fromHere;v<V.size();v++)
		{
			final String str=V.get(v);
			if(str.length()==0)
				continue;
			if(getMaskCodes().containsKey(str))
				return false;
			final Object o=makeSkillFlagObject(str);
			if(o==null)
				continue;
			for(final Enumeration<Ability> a=mob.allAbilities();a.hasMoreElements();)
			{
				final Ability A=a.nextElement();
				if(evaluateSkillFlagObject(o,A))
					return true;
			}
		}
		return false;
	}

	protected CompiledZapperMaskEntry levelCompiledHelper(final String str, final char c)
	{
		final ArrayList<Object> parms=new ArrayList<Object>();
		ZapperKey entryType=null;
		if(str.startsWith(c+">=")&&(CMath.isNumber(str.substring(3).trim())))
		{
			entryType=getMaskCodes().get("+LVLGE");
			parms.add(Integer.valueOf(CMath.s_int(str.substring(3).trim())));
		}
		else
		if(str.startsWith(c+"<=")&&(CMath.isNumber(str.substring(3).trim())))
		{
			entryType=getMaskCodes().get("+LVLLE");
			parms.add(Integer.valueOf(CMath.s_int(str.substring(3).trim())));
		}
		else
		if(str.startsWith(c+">")&&(CMath.isNumber(str.substring(2).trim())))
		{
			entryType=getMaskCodes().get("+LVLGR");
			parms.add(Integer.valueOf(CMath.s_int(str.substring(2).trim())));
		}
		else
		if(str.startsWith(c+"<")&&(CMath.isNumber(str.substring(2).trim())))
		{
			entryType=getMaskCodes().get("+LVLLT");
			parms.add(Integer.valueOf(CMath.s_int(str.substring(2).trim())));
		}
		else
		if(str.startsWith(c+"=")&&(CMath.isNumber(str.substring(2).trim())))
		{
			entryType=getMaskCodes().get("+LVLEQ");
			parms.add(Integer.valueOf(CMath.s_int(str.substring(2).trim())));
		}
		if((entryType==null)||(parms.size()==0))
			return null;
		return new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0]));
	}

	protected StringBuilder levelHelp(final String lvl, final char c, final String append)
	{
		if(lvl.startsWith(c+">=")&&(CMath.isNumber(lvl.substring(3).trim())))
			return new StringBuilder(append+"levels greater than or equal to "+lvl.substring(3).trim()+".  ");
		else
		if(lvl.startsWith(c+"<=")&&(CMath.isNumber(lvl.substring(3).trim())))
			return new StringBuilder(append+"levels less than or equal to "+lvl.substring(3).trim()+".  ");
		else
		if(lvl.startsWith(c+">")&&(CMath.isNumber(lvl.substring(2).trim())))
			return new StringBuilder(append+"levels greater than "+lvl.substring(2).trim()+".  ");
		else
		if(lvl.startsWith(c+"<")&&(CMath.isNumber(lvl.substring(2).trim())))
			return new StringBuilder(append+"levels less than "+lvl.substring(2).trim()+".  ");
		else
		if(lvl.startsWith(c+"=")&&(CMath.isNumber(lvl.substring(2).trim())))
			return new StringBuilder(append+"level "+lvl.substring(2).trim()+".  ");
		return new StringBuilder("");
	}

	protected int determineSeasonCode(String str)
	{
		str=str.toUpperCase().trim();
		if(str.length()==0)
			return -1;
		final TimeClock.Season season=(TimeClock.Season)CMath.s_valueOf(TimeClock.Season.class, str);
		if(season != null)
			return season.ordinal();
		for(int i=0;i<TimeClock.Season.values().length;i++)
		{
			if(TimeClock.Season.values()[i].toString().startsWith(str))
				return i;
		}
		return -1;
	}

	protected int levelMinHelp(final String lvl, final char c, final int minMinLevel, final boolean reversed)
	{
		if(lvl.startsWith(c+">=")&&(CMath.isNumber(lvl.substring(3).trim())))
			return reversed?minMinLevel:CMath.s_int(lvl.substring(3).trim());
		else
		if(lvl.startsWith(c+"<=")&&(CMath.isNumber(lvl.substring(3).trim())))
			return reversed?CMath.s_int(lvl.substring(3).trim())+1:minMinLevel;
		else
		if(lvl.startsWith(c+">")&&(CMath.isNumber(lvl.substring(2).trim())))
			return reversed?minMinLevel:CMath.s_int(lvl.substring(2).trim())+1;
		else
		if(lvl.startsWith(c+"<")&&(CMath.isNumber(lvl.substring(2).trim())))
			return reversed?CMath.s_int(lvl.substring(2).trim()):minMinLevel;
		else
		if(lvl.startsWith(c+"=")&&(CMath.isNumber(lvl.substring(2).trim())))
			return reversed?minMinLevel:CMath.s_int(lvl.substring(2).trim());
		return Integer.MIN_VALUE;
	}

	protected boolean fromHereEqual(final List<String> V, final char plusMinus, final int fromHere, final String find)
	{
		for(int v=fromHere;v<V.size();v++)
		{
			final String str=V.get(v);
			if(str.length()==0)
				continue;
			if(getMaskCodes().containsKey(str))
				return false;
			if(str.equalsIgnoreCase(plusMinus+find))
				return true;
		}
		return false;
	}

	protected boolean fromHereStartsWith(final List<String> V, final char plusMinus, final int fromHere, final String find)
	{
		for(int v=fromHere;v<V.size();v++)
		{
			final String str=V.get(v);
			if(str.length()==0)
				continue;
			if(getMaskCodes().containsKey(str))
				return false;
			if(str.startsWith(plusMinus+find))
				return true;
		}
		return false;
	}

	protected Faction.FRange getRange(final String s)
	{
		return CMLib.factions().getFactionRangeByCodeName(s);
	}

	protected boolean fromHereEndsWith(final List<String> V, final char plusMinus, final int fromHere, final String find)
	{
		for(int v=fromHere;v<V.size();v++)
		{
			final String str=V.get(v);
			if(str.length()==0)
				continue;
			if(getMaskCodes().containsKey(str))
				return false;
			if((str.charAt(0)==plusMinus)&&str.endsWith(find))
				return true;
		}
		return false;
	}

	@Override
	public String maskDesc(final String text)
	{
		return maskDesc(text, false);
	}

	public int countQuals(final List<String> V, final int v, final String startsWith)
	{
		int ct=0;
		for(int v2=v+1;v2<V.size();v2++)
		{
			final String str2=V.get(v2);
			if(zapCodes.containsKey(str2))
				break;
			if(str2.startsWith(startsWith))
				ct++;
		}
		return ct;
	}

	public boolean multipleQuals(final List<String> V, final int v, final String startsWith)
	{
		return countQuals(V,v,startsWith)>1;
	}

	@Override
	public String maskDesc(final String text, final boolean skipFirstWord)
	{
		if(text.trim().length()==0)
			return L("Anyone");
		StringBuilder buf=new StringBuilder("");
		final Map<String,ZapperKey> zapCodes=getMaskCodes();
		final List<String> V=CMParms.parse(text.toUpperCase());
		int val=-1;
		for(int v=0;v<V.size();v++)
		{
			final String str=V.get(v);
			val=-1;
			if(zapCodes.containsKey(str))
			{
				switch(zapCodes.get(str))
				{
				case CLASS: // +class
					{
						buf.append(L("Disallows the following class"+(multipleQuals(V,v,"-")?"es":"")+": "));
						for(final SavedClass C : charClasses())
						{
							final String cstr=C.minusNameStart;
							for(int v2=v+1;v2<V.size();v2++)
							{
								final String str2=V.get(v2);
								if(str2.length()==0)
									continue;
								if(zapCodes.containsKey(str2))
									break;
								if(str2.startsWith(cstr))
									buf.append(C.name+", ");
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _CLASS: // -class
					{
						buf.append(L(skipFirstWord?"Only ":"Allows only "));
						for(final SavedClass C : charClasses())
						{
							final String cstr=C.plusNameStart;
							for(int v2=v+1;v2<V.size();v2++)
							{
								final String str2=V.get(v2);
								if(str2.length()==0)
									continue;
								if(zapCodes.containsKey(str2))
									break;
								if(str2.startsWith(cstr))
									buf.append(C.name+", ");
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case BASECLASS: // +baseclass
					{
						buf.append(L("Disallows the following types"+(multipleQuals(V,v,"-")?"s":"")+": "));
						final HashSet<String> seenBase=new HashSet<String>();
						for(final SavedClass C : charClasses())
						{
							if(!seenBase.contains(C.baseClass))
							{
								seenBase.add(C.baseClass);
								if(fromHereStartsWith(V,'-',v+1,C.baseClassStart))
									buf.append(C.baseClass+" types, ");
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _BASECLASS: // -baseclass
					{
						buf.append(L(skipFirstWord?"Only ":"Allows only "));
						final HashSet<String> seenBase=new HashSet<String>();
						for(final SavedClass C : charClasses())
						{
							final String cstr=C.plusBaseClassStart;
							if(!seenBase.contains(C.baseClass))
							{
								seenBase.add(C.baseClass);
								for(int v2=v+1;v2<V.size();v2++)
								{
									final String str2=V.get(v2);
									if(str2.length()==0)
										continue;
									if(zapCodes.containsKey(str2))
										break;
									if(str2.startsWith(cstr))
										buf.append(L("@x1 types, ",C.baseClass));
								}
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _RACE: // -Race
					{
						buf.append(L(skipFirstWord?"Only ":"Allows only "));
						final LinkedList<String> cats=new LinkedList<String>();
						for(final SavedRace R : races())
						{
							if((!cats.contains(R.name)
							&&(fromHereStartsWith(V,'+',v+1,R.nameStart))))
								cats.add(R.name);
						}
						for(final String s : cats)
							buf.append(s+", ");
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _RACECAT: // -Racecats
					{
						buf.append(L(skipFirstWord?"Only these racial categor"+(multipleQuals(V,v,"+")?"ies":"y")+" ":"Allows only these racial categor"+(multipleQuals(V,v,"+")?"ies":"y")+" "));
						final LinkedList<String> cats=new LinkedList<String>();
						for(final SavedRace R : races())
						{
							if((!cats.contains(R.racialCategory)
							&&(fromHereStartsWith(V,'+',v+1,R.upperCatName))))
								cats.add(R.racialCategory);
						}
						for(final String s : cats)
							buf.append(s+", ");
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case ALIGNMENT: // Alignment
					{
						buf.append(L("Disallows the following alignment"+(multipleQuals(V,v,"-")?"s":"")+": "));
						if(fromHereStartsWith(V,'-',v+1,Faction.Align.EVIL.toString().substring(0,3)))
							buf.append(L(Faction.Align.EVIL.toString().toLowerCase()+", "));
						if(fromHereStartsWith(V,'-',v+1,Faction.Align.GOOD.toString().substring(0,3)))
							buf.append(L(Faction.Align.GOOD.toString().toLowerCase()+", "));
						if(fromHereStartsWith(V,'-',v+1,Faction.Align.NEUTRAL.toString().substring(0,3)))
							buf.append(L(Faction.Align.NEUTRAL.toString().toLowerCase()+", "));
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _ALIGNMENT: // -Alignment
					{
						buf.append(L(skipFirstWord?"Only ":"Allows only "));
						if(fromHereStartsWith(V,'+',v+1,Faction.Align.EVIL.toString().substring(0,3)))
							buf.append(L(Faction.Align.EVIL.toString().toLowerCase()+", "));
						if(fromHereStartsWith(V,'+',v+1,Faction.Align.GOOD.toString().substring(0,3)))
							buf.append(L(Faction.Align.GOOD.toString().toLowerCase()+", "));
						if(fromHereStartsWith(V,'+',v+1,Faction.Align.NEUTRAL.toString().substring(0,3)))
							buf.append(L(Faction.Align.NEUTRAL.toString().toLowerCase()+", "));
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case GENDER:
					{
						buf.append(L("Disallows the following gender"+(multipleQuals(V,v,"-")?"s":"")+": "));
						if(fromHereStartsWith(V,'-',v+1,"MALE"))
							buf.append(L("Male, "));
						if(fromHereStartsWith(V,'-',v+1,"FEMALE"))
							buf.append(L("Female, "));
						if(fromHereStartsWith(V,'-',v+1,"NEUTER"))
							buf.append(L("Neuter"));
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _GENDER: // -Gender
					{
						buf.append(L(skipFirstWord?"Only ":"Allows only "));
						if(fromHereStartsWith(V,'+',v+1,"MALE"))
							buf.append(L("Male, "));
						if(fromHereStartsWith(V,'+',v+1,"FEMALE"))
							buf.append(L("Female, "));
						if(fromHereStartsWith(V,'+',v+1,"NEUTER"))
							buf.append(L("Neuter"));
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _LEVEL: // -Levels
					{
						for(int v2=v+1;v2<V.size();v2++)
							buf.append(levelHelp(V.get(v2),'+',L(skipFirstWord?"Only ":"Allows only ")));
					}
					break;
				case _CLASSLEVEL: // -ClassLevels
					{
						for(int v2=v+1;v2<V.size();v2++)
							buf.append(levelHelp(V.get(v2),'+',L(skipFirstWord?"Only class ":"Allows only class ")));
					}
					break;
				case _MAXCLASSLEVEL: // -MaxclassLevels
					{
						for(int v2=v+1;v2<V.size();v2++)
							buf.append(levelHelp(V.get(v2),'+',L(skipFirstWord?"Only highest class ":"Allows only highest class ")));
					}
					break;
				case _TATTOO: // -Tattoos
					{
						buf.append(L((skipFirstWord?"The":"Requires")+" the following tattoo"+(multipleQuals(V,v,"+")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
								buf.append(str2.substring(1)+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case TATTOO: // +Tattoos
					{
						buf.append(L("Disallows the following tattoo"+(multipleQuals(V,v,"-")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
								buf.append(str2.substring(1)+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _MOOD: // -Mood
					{
						buf.append(L((skipFirstWord?"The":"Requires")+" the following mood"+(multipleQuals(V,v,"+")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
								buf.append(str2.substring(1)+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case MOOD: // +Mood
					{
						buf.append(L("Disallows the following mood"+(multipleQuals(V,v,"-")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
								buf.append(str2.substring(1)+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _ACCCHIEVE: // -accchieves
					{
						buf.append(L((skipFirstWord?"The":"Requires")+" the following account achievement"+(multipleQuals(V,v,"+")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
							{
								final AchievementLibrary.Achievement A=CMLib.achievements().getAchievement(str2.substring(1));
								if(A!=null)
									buf.append(A.getDisplayStr()+", ");
								else
									buf.append(str2.substring(1)+", ");
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case ACCCHIEVE: // +accchieves
					{
						buf.append(L("Disallows the following account achievement"+(multipleQuals(V,v,"-")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
							{
								final AchievementLibrary.Achievement A=CMLib.achievements().getAchievement(str2.substring(1));
								if(A!=null)
									buf.append(A.getDisplayStr()+", ");
								else
									buf.append(str2.substring(1)+", ");
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _SECURITY: // -Security
					{
						buf.append(L((skipFirstWord?"The":"Requires")+" following security flag"+(multipleQuals(V,v,"+")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
								buf.append(str2.substring(1)+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case SECURITY: // +security
					{
						buf.append(L("Disallows the following security flag"+(multipleQuals(V,v,"-")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
								buf.append(str2.substring(1)+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _EXPERTISE: // -expertises
					{
						buf.append(L((skipFirstWord?"The":"Requires")+" following expertise"+(multipleQuals(V,v,"+")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
							{
								final ExpertiseLibrary.ExpertiseDefinition E=CMLib.expertises().getDefinition(str2.substring(1).toUpperCase().trim());
								if(E!=null)
									buf.append(E.name()+", ");
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case EXPERTISE: // +expertises
					{
						buf.append(L("Disallows the following expertise"+(multipleQuals(V,v,"-")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
							{
								final ExpertiseLibrary.ExpertiseDefinition E=CMLib.expertises().getDefinition(str2.substring(1).toUpperCase().trim());
								if(E!=null)
									buf.append(E.name()+", ");
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _SKILLFLAG: // -skillflags
					{
						buf.append(L((skipFirstWord?"A":"Requires a")+" skill of type: "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
							{
								final List<String> V3=CMParms.parseAny(str2.substring(1),'&',true);
								String str3=null;
								for(int v3=0;v3<V3.size();v3++)
								{
									str3=CMStrings.replaceAll(CMStrings.capitalizeAndLower(V3.get(v3)),"_"," ");
									if(str3.startsWith("!"))
										buf.append("not "+str3.substring(1));
									else
										buf.append(str3);
									if(v3<(V3.size()-1))
										buf.append(" and ");
									else
										buf.append(", ");
								}
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _SKILL: // -skills
					{
						buf.append(L((skipFirstWord?"O":"Requires o")+"ne of the following skills: "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
							{
								int prof=0;
								str2=str2.substring(1);
								final int x=str2.indexOf('(');
								if(x>0)
								{
									if(str2.endsWith(")"))
										prof=CMath.s_int(str2.substring(x+1,str2.length()-1));
									str2=str2.substring(0,x);
								}
								final Ability A=CMClass.getAbility(str2);
								if(A!=null)
								{
									if(prof<=0)
										buf.append(A.name()+", ");
									else
										buf.append(L("@x1 at @x2% proficiency, ",A.name(),""+prof));
								}
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case SKILL: // +skills
					{
						buf.append(L("Disallows the following skill"+(multipleQuals(V,v,"-")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
							{
								int prof=0;
								str2=str2.substring(1);
								final int x=str2.indexOf('(');
								if(x>0)
								{
									if(str2.endsWith(")"))
										prof=CMath.s_int(str2.substring(x+1,str2.length()-1));
									str2=str2.substring(0,x);
								}
								final Ability A=CMClass.getAbility(str2);
								if(A!=null)
								{
									if(prof<=0)
										buf.append(A.name()+", ");
									else
										buf.append(L("@x1 at more than @x2% proficiency, ",A.name(),""+prof));
								}
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case SKILLFLAG: // +skillflag
					{
						buf.append(L("Disallows the skill of type: "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
							{
								final List<String> V3=CMParms.parseAny(str2.substring(1),'&',true);
								String str3=null;
								for(int v3=0;v3<V3.size();v3++)
								{
									str3=CMStrings.replaceAll(CMStrings.capitalizeAndLower(V3.get(v3)),"_"," ");
									if(str3.startsWith("!"))
										buf.append("not "+str3.substring(1));
									else
										buf.append(str3);
									if(v3<(V3.size()-1))
										buf.append(" and ");
									else
										buf.append(", ");
								}
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _CLAN: // -Clan
					{
						buf.append(L((skipFirstWord?"M":"Requires m")+"embership in the following clan"+(multipleQuals(V,v,"+")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
								buf.append(str2.substring(1)+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case CLAN: // +Clan
					{
						buf.append(L("Disallows the following clan"+(multipleQuals(V,v,"-")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
								buf.append(str2.substring(1)+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _MATERIAL: // -Material
					{
						buf.append(L((skipFirstWord?"C":"Requires c")+"onstruction from the following material"+(multipleQuals(V,v,"+")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
							{
								final int code=CMLib.materials().getMaterialCode(str2.substring(1),false);
								if(code>=0)
									buf.append(RawMaterial.Material.findByMask(code).noun()+", ");
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case MATERIAL: // +Material
					{
						buf.append(L("Disallows items of the following material"+(multipleQuals(V,v,"-")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
							{
								final int code=CMLib.materials().getMaterialCode(str2.substring(1),false);
								if(code>=0)
									buf.append(RawMaterial.Material.findByMask(code).noun()+", ");
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _WORNON: // -wornon
					{
						buf.append(L((skipFirstWord?"A":"Requires a")+"bility to be worn: "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
							{
								final long code=Wearable.CODES.FIND_endsWith(str2.substring(1));
								if(code>=0)
									buf.append(Wearable.CODES.NAME(code)+", ");
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case WORNON: // +wornon
					{
						buf.append(L("Disallows items capable of being worn: "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
							{
								final long code=Wearable.CODES.FIND_endsWith(str2.substring(1));
								if(code>=0)
									buf.append(Wearable.CODES.NAME(code)+", ");
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _SENSES: // -senses
					{
						buf.append(L((skipFirstWord?"The":"Requires")+" following sense"+(multipleQuals(V,v,"+")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
							{
								final int code=CMLib.flags().getSensesIndex(str2.substring(1));
								if(code>=0)
									buf.append(PhyStats.CAN_SEE_DESCS[code]+", ");
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case SENSES: // +senses
					{
						buf.append(L("Disallows the following sense"+(multipleQuals(V,v,"-")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
							{
								final int code=CMLib.flags().getSensesIndex(str2.substring(1));
								if(code>=0)
									buf.append(PhyStats.CAN_SEE_DESCS[code]+", ");
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case HOUR: // +HOUR
					{
						buf.append(L("Disallowed during the following time"+(multipleQuals(V,v,"-")?"s":"")+" of the day: "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
								buf.append(CMath.s_int(str2.substring(1).trim())+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _HOUR: // -HOUR
					{
						buf.append(L((skipFirstWord?"Only ":"Allowed only ")+"during the following time"+(multipleQuals(V,v,"+")?"s":"")+" of the day: "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
								buf.append(CMath.s_int(str2.substring(1).trim())+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case SEASON: // +season
					{
						buf.append(L("Disallowed during the following season"+(multipleQuals(V,v,"-")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
							{
								if(CMath.isInteger(str2.substring(1).trim()))
								{
									final int season=CMath.s_int(str2.substring(1).trim());
									if((season>=0)&&(season<TimeClock.Season.values().length))
										buf.append(TimeClock.Season.values()[season].toString()+", ");
								}
								else
								{
									final int season=determineSeasonCode(str2.substring(1).trim());
									if((season>=0)&&(season<TimeClock.Season.values().length))
										buf.append(TimeClock.Season.values()[season].toString()+", ");
								}
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _SEASON: // -season
					{
						buf.append(L((skipFirstWord?"Only ":"Allowed only ")+"during the following season"+(multipleQuals(V,v,"+")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
							{
								if(CMath.isInteger(str2.substring(1).trim()))
								{
									final int season=CMath.s_int(str2.substring(1).trim());
									if((season>=0)&&(season<TimeClock.Season.values().length))
										buf.append(TimeClock.Season.values()[season].toString()+", ");
								}
								else
								{
									final int season=determineSeasonCode(str2.substring(1).trim());
									if((season>=0)&&(season<TimeClock.Season.values().length))
										buf.append(TimeClock.Season.values()[season].toString()+", ");
								}
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case WEATHER: // +weather
					{
						buf.append(L("Disallowed during the following weather condition"+(multipleQuals(V,v,"-")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
							{
								if(CMath.isInteger(str2.substring(1).trim()))
								{
									final int weather=CMath.s_int(str2.substring(1).trim());
									if((weather>=0)&&(weather<Climate.WEATHER_DESCS.length))
										buf.append(CMStrings.capitalizeAndLower(Climate.WEATHER_DESCS[weather])+", ");
								}
								else
								{
									final int weather=CMParms.indexOf(Climate.WEATHER_DESCS,str2.substring(1).toUpperCase().trim());
									if((weather>=0)&&(weather<Climate.WEATHER_DESCS.length))
										buf.append(CMStrings.capitalizeAndLower(Climate.WEATHER_DESCS[weather])+", ");
								}
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _WEATHER: // -weather
					{
						buf.append(L((skipFirstWord?"Only ":"Allowed only ")+"during the following weather condition"+(multipleQuals(V,v,"+")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
							{
								if(CMath.isInteger(str2.substring(1).trim()))
								{
									final int weather=CMath.s_int(str2.substring(1).trim());
									if((weather>=0)&&(weather<Climate.WEATHER_DESCS.length))
										buf.append(CMStrings.capitalizeAndLower(Climate.WEATHER_DESCS[weather])+", ");
								}
								else
								{
									final int weather=CMParms.indexOf(Climate.WEATHER_DESCS,str2.substring(1).toUpperCase().trim());
									if((weather>=0)&&(weather<Climate.WEATHER_DESCS.length))
										buf.append(CMStrings.capitalizeAndLower(Climate.WEATHER_DESCS[weather])+", ");
								}
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case MONTH: // +month
					{
						buf.append(L("Disallowed during the following month"+(multipleQuals(V,v,"-")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
								buf.append(CMath.s_int(str2.substring(1).trim())+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _MONTH: // -month
					{
						buf.append(L((skipFirstWord?"Only ":"Allowed only ")+"during the following month"+(multipleQuals(V,v,"+")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
								buf.append(CMath.s_int(str2.substring(1).trim())+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case DAY: // +day
					{
						buf.append(L("Disallowed during the following day"+(multipleQuals(V,v,"-")?"s":"")+" of the month: "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
								buf.append(CMath.s_int(str2.substring(1).trim())+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _DAY: // -day
					{
						buf.append(L((skipFirstWord?"Only ":"Allowed only ")+"on the following day"+(multipleQuals(V,v,"+")?"s":"")+" of the month: "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
								buf.append(CMath.s_int(str2.substring(1).trim())+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;

				case QUALLVL: // +quallvl
					if((v+1)<V.size())
					{
						final Ability A=CMClass.getAbility(V.get(v+1));
						if(A!=null)
						{
							int adjustment=0;
							if(((v+2)<V.size())&&(CMath.isInteger(V.get(v+2))))
								adjustment=CMath.s_int(V.get(v+2));
							buf.append(A.Name());
							if(adjustment!=0)
								buf.append(L("Qualifies for @x1",A.Name()));
							else
							if(adjustment<0)
								buf.append(L("@x1 levels before qualifying for @x2",""+(-adjustment),A.Name()));
							else
								buf.append(L("@x1 levels after qualifying for @x2",""+adjustment,A.Name()));
							buf.append(".  ");
						}
					}
					break;
				case _QUALLVL: // -quallvl
					if((v+1)<V.size())
					{
						final Ability A=CMClass.getAbility(V.get(v+1));
						if(A!=null)
						{
							int adjustment=0;
							if(((v+2)<V.size())&&(CMath.isInteger(V.get(v+2))))
								adjustment=CMath.s_int(V.get(v+2));
							buf.append(A.Name());
							if(adjustment!=0)
								buf.append(L("Does not qualify for @x1",A.Name()));
							else
							if(adjustment<0)
								buf.append(L("Still prior to @x1 levels before qualifying for @x2",""+(-adjustment),A.Name()));
							else
								buf.append(L("Still prior to @x1 levels after qualifying for @x2",""+adjustment,A.Name()));
							buf.append(".  ");
						}
					}
					break;
				case _DISPOSITION: // -disposition
					{
						buf.append(L((skipFirstWord?"The":"Requires")+" following disposition"+(multipleQuals(V,v,"+")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
							{
								final int code=CMLib.flags().getDispositionIndex(str2.substring(1));
								if(code>=0)
									buf.append(PhyStats.IS_DESCS[code]+", ");
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case DISPOSITION: // +disposition
					{
						buf.append(L("Disallows the following disposition"+(multipleQuals(V,v,"-")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
							{
								final int code=CMLib.flags().getDispositionIndex(str2.substring(1));
								if(code>=0)
									buf.append(PhyStats.IS_DESCS[code]+", ");
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _RESOURCE: // -Resource
					{
						buf.append(L((skipFirstWord?"C":"Requires c")+"onstruction from the following material"+(multipleQuals(V,v,"+")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
							{
								final int code=CMLib.materials().getResourceCode(str2.substring(1),false);
								if(code>=0)
									buf.append(CMStrings.capitalizeAndLower(RawMaterial.CODES.NAME(code))+", ");
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case RESOURCE: // +Resource
					{
						buf.append(L("Disallows items of the following material"+(multipleQuals(V,v,"-")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
							{
								final int code=CMLib.materials().getResourceCode(str2.substring(1),false);
								if(code>=0)
									buf.append(CMStrings.capitalizeAndLower(RawMaterial.CODES.NAME(code))+", ");
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _JAVACLASS: // -JavaClass
					{
						buf.append(L((skipFirstWord?"B":"Requires b")+"eing of the following type"+(multipleQuals(V,v,"+")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
								buf.append(str2.substring(1)+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case JAVACLASS: // +JavaClass
					{
						buf.append(L("Disallows being of the following type"+(multipleQuals(V,v,"-")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
								buf.append(str2.substring(1)+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _DEITY: // -Deity
					{
						buf.append(L((skipFirstWord?"W":"Requires w")+"orshipping the following deity"+(multipleQuals(V,v,"+")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
								buf.append(str2.substring(1)+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case DEITY: // +Deity
					{
						buf.append(L("Disallows the worshippers of: "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
								buf.append(str2.substring(1)+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case NAME: // +Names
					{
						buf.append(L("Disallows the following mob/player name"+(multipleQuals(V,v,"-")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
								buf.append(str2.substring(1)+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _NAME: // -Names
					{
						buf.append(L((skipFirstWord?"The":"Requires")+" following name"+(multipleQuals(V,v,"+")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
								buf.append(str2.substring(1)+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _QUESTWIN: // -Questwin
					{
						buf.append(L((skipFirstWord?"Completing":"Requires completing")+" the following quest"+(multipleQuals(V,v,"+")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
							{
								final Quest Q=CMLib.quests().fetchQuest(str2.substring(1));
								if(Q==null)
									buf.append(str2.substring(1)+", ");
								else
								if((Q.displayName()!=null)&&(Q.displayName().trim().length()>0))
									buf.append(Q.displayName()+", ");
								else
									buf.append(Q.name()+", ");
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case QUESTWIN: // +Questwin
					{
						buf.append(L("Disallows those who`ve won the following quest"+(multipleQuals(V,v,"-")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
							{
								final Quest Q=CMLib.quests().fetchQuest(str2.substring(1));
								if(Q==null)
									buf.append(str2.substring(1)+", ");
								else
								if((Q.displayName()!=null)&&(Q.displayName().trim().length()>0))
									buf.append(Q.displayName()+", ");
								else
									buf.append(Q.name()+", ");
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _PLAYER: // -Player
					buf.append(L("Disallows players.  "));
					break;
				case _NPC: // -MOB
					buf.append(L("Disallows mobs/npcs.  "));
					break;
				case RACE: // +races
					{
						buf.append(L("Disallows the following race"+(multipleQuals(V,v,"-")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
								buf.append(str2.substring(1)+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case RACECAT: // +racecats
					{
						buf.append(L("Disallows the following racial category"+(multipleQuals(V,v,"-")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
								buf.append(str2.substring(1)+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _ANYCLASSLEVEL: // -anyclasslevel
					{
						String className = "";
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String s = V.get(v2);
							if(getMaskCodes().containsKey(s))
								break;
							boolean checkForClass = true;
							boolean found=false;
							if(className.length()>0)
							{
								StringBuilder lvlHelp = levelHelp(V.get(v2),'+',L(skipFirstWord?"Only "+className+" ":"Allows only "+className+" "));
								if(lvlHelp.length()>0)
								{
									buf.append(lvlHelp);
									checkForClass = false;
									found=true;
								}
							}
							if(checkForClass)
							{
								for(final SavedClass C : charClasses())
								{
									if(s.startsWith('+'+C.nameStart))
									{
										className = C.name;
										found=true;
										break;
									}
								}
							}
							if(!found)
								break;
						}
					}
					break;
				case ANYCLASSLEVEL: // +anyclasslevel
					{
						String className = "";
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String s = V.get(v2);
							if(getMaskCodes().containsKey(s))
							{
								v=v2-1;
								break;
							}
							boolean checkForClass = true;
							boolean found=false;
							if(className.length()>0)
							{
								StringBuilder lvlHelp = levelHelp(V.get(v2),'-',"Disallows "+className+" ");
								if(lvlHelp.length()>0)
								{
									buf.append(lvlHelp);
									checkForClass = false;
									found = true;
								}
							}
							if(checkForClass)
							{
								for(final SavedClass C : charClasses())
								{
									if(s.startsWith('-'+C.nameStart))
									{
										className = C.name;
										found = true;
										break;
									}
								}
							}
							if(!found)
							{
								v=v2-1;
								break;
							}
							else
							if(v2==V.size()-1)
							{
								v=v2;
								break;
							}
						}
					}
					break;
				case _ANYCLASS: // -anyclass
					{
						buf.append(L((skipFirstWord?"L":"Requires l")+"evels in one of the following:  "));
						for(final SavedClass C : charClasses())
						{
							if(fromHereStartsWith(V,'+',v+1,C.nameStart))
								buf.append(C.name+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case ANYCLASS: // +anyclass
					{
						buf.append(L("Disallows any levels in any of the following:  "));
						for(final SavedClass C : charClasses())
						{
							if(fromHereStartsWith(V,'-',v+1,C.nameStart))
								buf.append(C.name+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case ADJSTRENGTH: // +adjstr
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" strength of at least @x1.  ",""+val));
					break;
				case ADJINTELLIGENCE: // +adjint
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"An":"Requires an")+" intelligence of at least @x1.  ",""+val));
					break;
				case ADJWISDOM: // +adjwis
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" wisdom of at least @x1.  ",""+val));
					break;
				case ADJDEXTERITY: // +adjdex
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" dexterity of at least @x1.  ",""+val));
					break;
				case ADJCONSTITUTION: // -adjcha
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" constitution of at least @x1.  ",""+val));
					break;
				case ADJCHARISMA: // +adjcha
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" charisma of at least @x1.  ",""+val));
					break;
				case _ADJSTRENGTH: // -adjstr
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" strength of at most @x1.  ",""+val));
					break;
				case _ADJINTELLIGENCE: // -adjint
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"An":"Requires an")+" intelligence of at most @x1.  ",""+val));
					break;
				case _ADJWISDOM: // -adjwis
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" wisdom of at most @x1.  ",""+val));
					break;
				case _ADJDEXTERITY: // -adjdex
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" dexterity of at most @x1.  ",""+val));
					break;
				case _ADJCONSTITUTION: // -adjcon
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" constitution of at most @x1.  ",""+val));
					break;
				case _ADJCHARISMA: // -adjcha
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" charisma of at most @x1.  ",""+val));
					break;
				case STRENGTH: // +str
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" base strength of at least @x1.  ",""+val));
					break;
				case INTELLIGENCE: // +int
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" base intelligence of at least @x1.  ",""+val));
					break;
				case WISDOM: // +wis
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" base wisdom of at least @x1.  ",""+val));
					break;
				case DEXTERITY: // +dex
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" base dexterity of at least @x1.  ",""+val));
					break;
				case CONSTITUTION: // +con
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" base constitution of at least @x1.  ",""+val));
					break;
				case CHARISMA: // +cha
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" base charisma of at least @x1.  ",""+val));
					break;
				case _STRENGTH: // -str
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" base strength of at most @x1.  ",""+val));
					break;
				case _INTELLIGENCE: // -int
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" base intelligence of at most @x1.  ",""+val));
					break;
				case _WISDOM: // -wis
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" base wisdom of at most @x1.  ",""+val));
					break;
				case _DEXTERITY: // -dex
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" base dexterity of at most @x1.  ",""+val));
					break;
				case _CONSTITUTION: // -con
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" base constitution of at most @x1.  ",""+val));
					break;
				case _CHARISMA: // -cha
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" base charisma of at most @x1.  ",""+val));
					break;
				case _CHANCE: // -chance
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"":"Allowed ")+" "+(100-val)+"% of the time.  "));
					break;
				case ABILITY: // +ability
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" magic/ability of at most @x1.  ",""+val));
					break;
				case _ABILITY: // -ability
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" magic/ability of at least @x1.  ",""+val));
					break;
				case VALUE: // +value
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" value of at most @x1.  ",""+val));
					break;
				case _VALUE: // -value
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" value of at least @x1.  ",""+val));
					break;
				case WEIGHT: // +weight
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" weight/encumbrance of at most @x1.  ",""+val));
					break;
				case _WEIGHT: // -weight
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" weight/encumbrance of at least @x1.  ",""+val));
					break;
				case ARMOR: // +armor
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" armor rating of at most @x1.  ",""+val));
					break;
				case _ARMOR: // -armor
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" armor rating of at least @x1.  ",""+val));
					break;
				case DAMAGE: // +damage
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" damage ability of at most @x1.  ",""+val));
					break;
				case _DAMAGE: // -damage
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" damage ability of at least @x1.  ",""+val));
					break;
				case ATTACK: // +attack
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"An":"Requires an")+" attack bonus of at most @x1.  ",""+val));
					break;
				case _ATTACK: // -attack
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"An":"Requires an")+" attack bonus of at least @x1.  ",""+val));
					break;
				case AREA: // +Area
					{
						buf.append(L("Disallows the following area"+(multipleQuals(V,v,"-")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
								buf.append(str2.substring(1)+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _AREA: // -Area
					{
						buf.append(L((skipFirstWord?"The":"Requires the")+" following area"+(multipleQuals(V,v,"+")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
								buf.append(str2.substring(1)+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case HOME: // +Home
					{
						buf.append(L("Disallows those whose home is the following area"+(multipleQuals(V,v,"-")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
								buf.append(str2.substring(1)+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _HOME: // -Home
					{
						buf.append(L((skipFirstWord?"From the":"Requires being from the")+" following area"+(multipleQuals(V,v,"+")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
								buf.append(str2.substring(1)+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case ITEM: // +Item
					{
						buf.append(L("Disallows those with the following item"+(multipleQuals(V,v,"-")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
								buf.append(str2.substring(1)+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case WORN:
					{
						buf.append(L((skipFirstWord?"The":"Requires the")+" following worn item"+(multipleQuals(V,v,"-")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
								buf.append(str2.substring(1)+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _ITEM:
					{
						buf.append(L((skipFirstWord?"H":"Requires h")+"aving the following item"+(multipleQuals(V,v,"+")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if((str2.startsWith("+"))||(str2.startsWith("-")))
								buf.append(str2.substring(1)+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _WORN: // -Worn
					{
						buf.append(L((skipFirstWord?"W":"Requires w")+"earing the following item"+(multipleQuals(V,v,"+")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if((str2.startsWith("+"))||(str2.startsWith("-")))
								buf.append(str2.substring(1)+", ");
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case EFFECT: // +Effects
					{
						buf.append(L("Disallows the following activities/effect"+(multipleQuals(V,v,"-")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
							{
								final Ability A=CMClass.getAbility(str2.substring(1));
								if(A!=null)
									buf.append(A.name()+", ");
								else
									buf.append(str2.substring(1)+", ");
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _EFFECT: // -Effects
					{
						buf.append(L((skipFirstWord?"P":"Requires p")+"articipation in the following activities/effect"+(multipleQuals(V,v,"+")?"s":"")+": "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
							{
								final Ability A=CMClass.getAbility(str2.substring(1));
								if(A!=null)
									buf.append(A.name()+", ");
								else
									buf.append(str2.substring(1)+", ");
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case FACTION: // +faction
					{
						buf.append(L("Disallows the following: "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("-"))
							{
								final Faction.FRange FR=getRange(str2.substring(1).toUpperCase().trim());
								if(FR!=null)
								{
									final String desc=CMLib.factions().rangeDescription(FR,"or ");
									if(desc.length()>0)
										buf.append(desc+"; ");
								}
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						if(buf.toString().endsWith("; "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _FACTION: // -faction
					{
						buf.append(L((skipFirstWord?"The":"Requires the")+" following: "));
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
							{
								final Faction.FRange FR=getRange(str2.substring(1).toUpperCase().trim());
								if(FR!=null)
								{
									final String desc=CMLib.factions().rangeDescription(FR,"or ");
									if(desc.length()>0)
										buf.append(desc+"; ");
								}
							}
						}
						if(buf.toString().endsWith(", "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						if(buf.toString().endsWith("; "))
							buf=new StringBuilder(buf.substring(0,buf.length()-2));
						buf.append(".  ");
					}
					break;
				case _GROUPSIZE: // -groupsize
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" group size of at most @x1.  ",""+val));
					break;
				case GROUPSIZE: // +groupsize
					val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
					buf.append(L((skipFirstWord?"A":"Requires a")+" group size of at least @x1.  ",""+val));
					break;
				case _IF: // -if
					buf.append(L((skipFirstWord?"n":"Requires n")+"ot meeting the following condition(s):"));
					for(int v2=v+1;v2<V.size();v2++)
					{
						final String str2=V.get(v2);
						if(zapCodes.containsKey(str2))
							break;
						buf.append(str2).append(" ");
					}
					break;
				case IF: // +if
					buf.append(L((skipFirstWord?"m":"Requires m")+"meets the following condition(s):"));
					for(int v2=v+1;v2<V.size();v2++)
					{
						final String str2=V.get(v2);
						if(zapCodes.containsKey(str2))
							break;
						buf.append(str2).append(" ");
					}
					break;
				case SUBOP:
					// this line intentionally left blank
					break;
				case SYSOP:
					// this line intentionally left blank
					break;
				case _SUBOP:
					// this line intentionally left blank
					break;
				case _SYSOP:
					// this line intentionally left blank
					break;
				case LVLEQ:
					// this line intentionally left blank
					break;
				case LVLGE:
					// this line intentionally left blank
					break;
				case LVLGR:
					// this line intentionally left blank
					break;
				case LVLLE:
					// this line intentionally left blank
					break;
				case LVLLT:
					// this line intentionally left blank
					break;
				}
			}
			else
			{
				for(final SavedClass C : charClasses())
				{
					if(str.startsWith("-"+C.nameStart))
						buf.append(L("Disallows @x1.  ",C.name));
				}
				final LinkedList<String> cats=new LinkedList<String>();
				for(final SavedRace R : races())
				{
					if((str.startsWith(R.minusCatNameStart))&&(!cats.contains(R.racialCategory)))
					{
						cats.add(R.racialCategory);
						buf.append(L("Disallows @x1.  ",R.racialCategory));
					}
				}
				if(str.startsWith("-"+Faction.Align.EVIL.toString().substring(0,3)))
					buf.append(L("Disallows "+Faction.Align.EVIL.toString().toLowerCase()+".  "));
				if(str.startsWith("-"+Faction.Align.GOOD.toString().substring(0,3)))
					buf.append(L("Disallows "+Faction.Align.GOOD.toString().toLowerCase()+".  "));
				if(str.startsWith("-"+Faction.Align.NEUTRAL.toString().substring(0,3)))
					buf.append(L("Disallows "+Faction.Align.NEUTRAL.toString().toLowerCase()+".  "));
				if(str.startsWith("-MALE"))
					buf.append(L("Disallows Males.  "));
				if(str.startsWith("-FEMALE"))
					buf.append(L("Disallows Females.  "));
				if(str.startsWith("-NEUTER"))
					buf.append(L((skipFirstWord?"Only ":"Allows only ")+"Males and Females.  "));
				buf.append(levelHelp(str,'-',L("Disallows ")));
				if(str.startsWith("-"))
				{
					final Faction.FRange FR=getRange(str.substring(1));
					final String desc=CMLib.factions().rangeDescription(FR,"and ");
					if(desc.length()>0)
						buf.append(L("Disallows ")+desc);
				}
			}
		}

		if(buf.length()==0)
			buf.append(L("Anyone."));
		return buf.toString();
	}

	@Override
	public boolean syntaxCheck(final String mask, final List<String> errorSink)
	{
		if(mask.trim().length()==0)
			return true;
		final List<String> V=CMParms.parse(mask.toUpperCase());
		for(int v=0;v<V.size();v++)
		{
			final String str=V.get(v);
			final Map<String,ZapperKey> zapCodes=getMaskCodes();
			if(zapCodes.containsKey(str))
				return true;
			for(final SavedClass C : charClasses())
			{
				if(str.startsWith(C.minusNameStart))
					return true;
			}
			for(final SavedRace R : races())
			{
				if(str.startsWith(R.minusNameStart))
					return true;
				if(str.startsWith(R.minusCatNameStart))
					return true;
			}
			if(str.startsWith("-"+Faction.Align.EVIL.toString().substring(0,3)))
				return true;
			if(str.startsWith("-"+Faction.Align.GOOD.toString().substring(0,3)))
				return true;
			if(str.startsWith("-"+Faction.Align.NEUTRAL.toString().substring(0,3)))
				return true;
			if(str.startsWith("-MALE"))
				return true;
			if(str.startsWith("-FEMALE"))
				return true;
			if(str.startsWith("-NEUTER"))
				return true;
			if(levelHelp(str,'-',"").length()>0)
				return true;
			if((str.startsWith("-"))
			&&(CMLib.factions().isRangeCodeName(str.substring(1))))
				return true;
		}
		errorSink.add("No valid zapper codes found.");
		return false;
	}

	@Override
	public List<String> getAbilityEduReqs(final String text)
	{
		final Vector<String> preReqs=new Vector<String>();
		if(text.trim().length()==0)
			return preReqs;
		final Map<String,ZapperKey> zapCodes=getMaskCodes();
		final List<String> V=CMParms.parse(text.toUpperCase());
		String str2;
		for(int v=0;v<V.size();v++)
		{
			final String str=V.get(v);
			if(zapCodes.containsKey(str))
			{
				switch(zapCodes.get(str))
				{
				case _EXPERTISE: // -expertises
					{
						for(int v2=v+1;v2<V.size();v2++)
						{
							str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
							{
								final ExpertiseLibrary.ExpertiseDefinition E=CMLib.expertises().getDefinition(str2.substring(1).toUpperCase().trim());
								if(E!=null)
									preReqs.addElement(E.ID());
							}
						}
					}
					break;
				case _SKILL: // -skills
					{
						for(int v2=v+1;v2<V.size();v2++)
						{
							str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
							{
								str2=str2.substring(1);
								final int x=str2.indexOf('(');
								if(x>0)
									str2=str2.substring(0,x);
								final Ability A=CMClass.getAbility(str2);
								if((A!=null)&&(!preReqs.contains(A.ID())))
									preReqs.addElement(A.ID());
							}
						}
					}
					break;
				case _SKILLFLAG: // -skillflag
					{
						final ArrayList<Object> objs=new ArrayList<Object>();
						Object o=null;
						for(int v2=v+1;v2<V.size();v2++)
						{
							str2=V.get(v2);
							if(zapCodes.containsKey(str2))
								break;
							if(str2.startsWith("+"))
							{
								str2=str2.substring(1);
								o=this.makeSkillFlagObject(str2);
								if(o!=null)
									objs.add(o);
							}
						}
						for(final Object O : objs)
						{
							for(final Enumeration<Ability> e=CMClass.abilities();e.hasMoreElements();)
							{
								final Ability A=e.nextElement();
								if((evaluateSkillFlagObject(O,A))
								&&(!preReqs.contains(A.ID())))
								{
									preReqs.addElement(A.ID());
								}
							}
						}
					}
					break;
				default:
					break;
				}
			}
		}
		return preReqs;
	}

	@Override
	public int minMaskLevel(final String text, final int minMinLevel)
	{
		int level=minMinLevel;
		final CompiledZapperMask cset=getPreCompiledMask(text);
		for(final CompiledZapperMaskEntry entry : cset.entries())
		{
			switch(entry.maskType())
			{
			case _LEVEL: // -level
				{
					for(int v=0;v<entry.parms().length-1;v+=2)
					{
						switch((ZapperKey)entry.parms()[v])
						{
						case LVLGR: // +lvlgr
							level=((Integer)entry.parms()[v+1]).intValue()+1;
							break;
						case LVLGE: // +lvlge
							level=((Integer)entry.parms()[v+1]).intValue();
							break;
						case LVLLT: // +lvlt
							level=minMinLevel;
							break;
						case LVLLE: // +lvlle
							level=minMinLevel;
							break;
						case LVLEQ: // +lvleq
							level=((Integer)entry.parms()[v+1]).intValue();
							break;
						default:
							break;
						}
					}
				}
				break;
			case _CLASSLEVEL: // -classlevel
				{
					for(int v=0;v<entry.parms().length-1;v+=2)
					{
						switch((ZapperKey)entry.parms()[v])
						{
						case LVLGR: // +lvlgr
							level=((Integer)entry.parms()[v+1]).intValue()+1;
							break;
						case LVLGE: // +lvlge
							level=((Integer)entry.parms()[v+1]).intValue();
							break;
						case LVLLT: // +lvlt
							level=minMinLevel;
							break;
						case LVLLE: // +lvlle
							level=minMinLevel;
							break;
						case LVLEQ: // +lvleq
							level=((Integer)entry.parms()[v+1]).intValue();
							break;
						default:
							break;
						}
					}
				}
				break;
			case _MAXCLASSLEVEL: // -maxclasslevel
				{
					for(int v=0;v<entry.parms().length-1;v+=2)
					{
						switch((ZapperKey)entry.parms()[v])
						{
						case LVLGR: // +lvlgr
							level=((Integer)entry.parms()[v+1]).intValue()+1;
							break;
						case LVLGE: // +lvlge
							level=((Integer)entry.parms()[v+1]).intValue();
							break;
						case LVLLT: // +lvlt
							level=minMinLevel;
							break;
						case LVLLE: // +lvlle
							level=minMinLevel;
							break;
						case LVLEQ: // +lvleq
							level=((Integer)entry.parms()[v+1]).intValue();
							break;
						default:
							break;
						}
					}
				}
				break;
			case LVLGR: // +lvlgr
				level=minMinLevel;
				break;
			case LVLGE: // +lvlge
				level=minMinLevel;
				break;
			case LVLLT: // +lvlt
				level=((Integer)entry.parms()[0]).intValue();
				break;
			case LVLLE: // +lvlle
				level=((Integer)entry.parms()[0]).intValue()+1;
				break;
			case LVLEQ: // +lvleq
				level=minMinLevel;
				break;
			default:
				break;
			}
		}
		return level;
	}

	@Override
	public CompiledZapperMask maskCompile(final String text)
	{
		final ArrayList<CompiledZapperMaskEntry> buf=new ArrayList<CompiledZapperMaskEntry>();
		if((text==null)||(text.trim().length()==0)) 
			return new CompiledZapperMaskImpl(new boolean[]{false,false},buf.toArray(new CompiledZapperMaskEntry[0]));
		final Map<String,ZapperKey> zapCodes=getMaskCodes();
		final List<String> V=CMParms.parse(text.toUpperCase());
		boolean buildItemFlag=false;
		boolean buildRoomFlag=false;
		ZapperKey entryType;
		for(int v=0;v<V.size();v++)
		{
			final String str=V.get(v);
			int val=-1;
			entryType=zapCodes.get(str);
			if(entryType!=null)
			{
				switch(entryType)
				{
				case _CLASS: // -class
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						for(final SavedClass C : charClasses())
						{
							if(fromHereStartsWith(V,'+',v+1,C.nameStart))
								parms.add(C.name);
						}
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case CLASS: // +class
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						for(final SavedClass C : charClasses())
						{
							if(fromHereStartsWith(V,'-',v+1,C.nameStart))
								parms.add(C.name);
						}
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case _BASECLASS: // -baseclass
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						final HashSet<String> seenBase=new HashSet<String>();
						for(final SavedClass C : charClasses())
						{
							if(!seenBase.contains(C.baseClass))
							{
								seenBase.add(C.baseClass);
								if(fromHereStartsWith(V,'+',v+1,C.baseClassStart))
									parms.add(C.baseClass);
							}
						}
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case BASECLASS: // +baseclass
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						final HashSet<String> seenBase=new HashSet<String>();
						for(final SavedClass C : charClasses())
						{
							if(!seenBase.contains(C.baseClass))
							{
								seenBase.add(C.baseClass);
								if(fromHereStartsWith(V,'-',v+1,C.baseClassStart))
									parms.add(C.baseClass);
							}
						}
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case _RACE: // -Race
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						final LinkedList<String> cats=new LinkedList<String>();
						for(final SavedRace R : races())
						{
							if((!cats.contains(R.name)
							&&(fromHereStartsWith(V,'+',v+1,R.nameStart))))
							   cats.add(R.name);
						}
						for(final String s : cats)
							parms.add(s);
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case _RACECAT: // -Racecats
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						final LinkedList<String> cats=new LinkedList<String>();
						for(final SavedRace R : races())
						{
							if((!cats.contains(R.racialCategory)
							&&(fromHereStartsWith(V,'+',v+1,R.upperCatName))))
							   cats.add(R.racialCategory);
						}
						for(final String s : cats)
							parms.add(s);
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case RACECAT: // +Racecats
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						final LinkedList<String> cats=new LinkedList<String>();
						for(final SavedRace R : races())
						{
							if((!cats.contains(R.racialCategory)
							&&(fromHereStartsWith(V,'-',v+1,R.upperCatName))))
							   cats.add(R.racialCategory);
						}
						for(final String s : cats)
							parms.add(s);
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case RACE: // +Race
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						for(final SavedRace R : races())
						{
							if(fromHereStartsWith(V,'-',v+1,R.upperName))
							   parms.add(R.name);
						}
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case ALIGNMENT: // +Alignment
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						if(fromHereStartsWith(V,'-',v+1,Faction.Align.EVIL.toString().substring(0,3)))
							parms.add(Faction.Align.EVIL.toString());
						if(fromHereStartsWith(V,'-',v+1,Faction.Align.GOOD.toString().substring(0,3)))
							parms.add(Faction.Align.GOOD.toString());
						if(fromHereStartsWith(V,'-',v+1,Faction.Align.NEUTRAL.toString().substring(0,3)))
							parms.add(Faction.Align.NEUTRAL.toString());
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case _ALIGNMENT: // -Alignment
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						if(fromHereStartsWith(V,'+',v+1,Faction.Align.EVIL.toString().substring(0,3)))
							parms.add(Faction.Align.EVIL.toString());
						if(fromHereStartsWith(V,'+',v+1,Faction.Align.GOOD.toString().substring(0,3)))
							parms.add(Faction.Align.GOOD.toString());
						if(fromHereStartsWith(V,'+',v+1,Faction.Align.NEUTRAL.toString().substring(0,3)))
							parms.add(Faction.Align.NEUTRAL.toString());
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case _GENDER: // -Gender
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						if(fromHereStartsWith(V,'+',v+1,"MALE"))
							parms.add("M");
						if(fromHereStartsWith(V,'+',v+1,"FEMALE"))
							parms.add("F");
						if(fromHereStartsWith(V,'+',v+1,"NEUTER"))
							parms.add("N");
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case GENDER: // +Gender
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						if(fromHereStartsWith(V,'-',v+1,"MALE"))
							parms.add("M");
						if(fromHereStartsWith(V,'-',v+1,"FEMALE"))
							parms.add("F");
						if(fromHereStartsWith(V,'-',v+1,"NEUTER"))
							parms.add("N");
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case _LEVEL: // -Levels
				case _CLASSLEVEL: // -ClassLevels
				case _MAXCLASSLEVEL: // -MaxclassLevels
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
							{
								v=v2-1;
								break;
							}
							final CompiledZapperMaskEntry e = levelCompiledHelper(str2,'+');
							if(e!=null)
							{
								parms.add(e.maskType());
								parms.add(e.parms()[0]);
							}
							v=V.size();
						}
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case ANYCLASSLEVEL: // +anyclasslevel
				case _ANYCLASSLEVEL: // -anyclasslevel
					{
						final char plusMinus = (entryType == ZapperKey.ANYCLASSLEVEL) ? '-' : '+';
						SavedClass charClassC = null;
						final ArrayList<Object> parms=new ArrayList<Object>();
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
							{
								v=v2-1;
								break;
							}
							boolean checkForClass = true;
							boolean found=false;
							if(charClassC!=null)
							{
								final CompiledZapperMaskEntry e = levelCompiledHelper(str2,plusMinus);
								if(e!=null)
								{
									CharClass C=CMClass.getCharClass(charClassC.id);
									if(C!=null)
									{
										parms.add(C);
										parms.add(e.maskType());
										parms.add(e.parms()[0]);
										checkForClass = false;
										found=true;
									}
								}
							}
							if(checkForClass)
							{
								for(final SavedClass C : charClasses())
								{
									if(str2.startsWith(plusMinus+C.nameStart))
									{
										charClassC = C;
										found=true;
										break;
									}
								}
							}
							if(!found)
							{
								v=v2-1;
								break;
							}
							else
							if(v2==V.size()-1)
							{
								v=v2;
								break;
							}
						}
						if(parms.size()>0)
							buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case _EFFECT: // -Effect
				case EFFECT: // +Effect
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						for(int v2=v+1;v2<V.size();v2++)
						{
							String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
							{
								v=v2-1;
								break;
							}
							else
							if((str2.startsWith("-"))||(str2.startsWith("+")))
							{
								str2=str2.substring(1);
								CMObject A=CMClass.getAbility(str2);
								if(A==null)
									A=CMClass.getBehavior(str2);
								if(A==null)
									A=CMClass.getAbilityByName(str2,true);
								if(A==null)
									A=CMClass.getBehaviorByName(str2,true);
								if(A==null)
									A=CMClass.getAbilityByName(str2,false);
								if(A==null)
									A=CMClass.getBehaviorByName(str2,false);
								if(A!=null)
									parms.add(A.ID());
							}
							v=V.size();
						}
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case SECURITY: // +security
				case _SECURITY: // -security
					{
						final String plusMinus=(entryType==ZapperKey._SECURITY)?"+":"-";
						final ArrayList<CMSecurity.SecFlag> parms=new ArrayList<CMSecurity.SecFlag>();
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
							{
								v=v2-1;
								break;
							}
							else
							if(str2.startsWith(plusMinus))
							{
								final CMSecurity.SecFlag flag=(CMSecurity.SecFlag)CMath.s_valueOf(CMSecurity.SecFlag.class,str2.substring(1).toUpperCase().trim().replace(' ','_'));
								if(flag == null)
									Log.errOut("MUDZapper","Illegal security flag '"+str2);
								else
									parms.add(flag);
							}
							v=V.size();
						}
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new CMSecurity.SecFlag[0])));
						break;
					}
				case _CLAN: // -Clan
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
							{
								v=v2-1;
								break;
							}
							else
							if(str2.startsWith("+"))
							{
								int x;
								if(((x=str2.lastIndexOf('('))>0)&&(str2.endsWith(")")))
									parms.add(new Pair<String,String>(str2.substring(1,x),str2.substring(x+1,str2.length()-1)));
								else
									parms.add(str2.substring(1));
							}
							v=V.size();
						}
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case _AREA: // -Area
					buildRoomFlag=true;
				//$FALL-THROUGH$
				case _TATTOO: // -Tattoos
				case _MOOD: // -Mood
				case _ACCCHIEVE: // -Accchieves
				case _EXPERTISE: // -expertise
				case _DEITY: // -Deity
				case _NAME: // -Names
				case _QUESTWIN: // -Questwin
				case _HOME: // -Home
				case _JAVACLASS: // -JavaClass
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
							{
								v=v2-1;
								break;
							}
							else
							if(str2.startsWith("+"))
								parms.add(str2.substring(1));
							v=V.size();
						}
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case FACTION: // +Faction
				case _FACTION: // -Faction
				{
					final String plusMinus=(entryType==ZapperKey._FACTION)?"+":"-";
					final ArrayList<Object> parms=new ArrayList<Object>();
					for(int v2=v+1;v2<V.size();v2++)
					{
						final String str2=V.get(v2);
						if(zapCodes.containsKey(str2))
						{
							v=v2-1;
							break;
						}
						else
						if(str2.startsWith(plusMinus))
						{
							final String str3=str2.substring(1).toUpperCase().trim();
							final Faction.FRange FR=getRange(str3);
							if(FR!=null)
								parms.add(str3);
						}
						v=V.size();
					}
					buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					break;
				}
				case CLAN: // +Clan
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
							{
								v=v2-1;
								break;
							}
							else
							if(str2.startsWith("-"))
							{
								int x;
								if(((x=str2.indexOf('('))>0)&&(str2.endsWith(")")))
									parms.add(new Pair<String,String>(str2.substring(1,x),str2.substring(x+1,str2.length()-1)));
								else
									parms.add(str2.substring(1));
							}
							v=V.size();
						}
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case AREA: // +Area
					buildRoomFlag=true;
				//$FALL-THROUGH$
				case TATTOO: // +Tattoos
				case MOOD: // +Mood
				case ACCCHIEVE: // +Accchieves
				case EXPERTISE: // +expertise
				case DEITY: // +Deity
				case NAME: // +Names
				case QUESTWIN: // +Questwin
				case HOME: // +Home
				case JAVACLASS: // +JavaClass
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
							{
								v=v2-1;
								break;
							}
							else
							if(str2.startsWith("-"))
								parms.add(str2.substring(1));
							v=V.size();
						}
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case _SKILL: // +skills
				case SKILL: // -skills
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						for(int v2=v+1;v2<V.size();v2++)
						{
							String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
							{
								v=v2-1;
								break;
							}
							else
							if((str2.startsWith("-"))||(str2.startsWith("+")))
							{
								str2=str2.substring(1);
								int prof=0;
								final int x=str2.indexOf('(');
								if(x>0)
								{
									if(str2.endsWith(")"))
										prof=CMath.s_int(str2.substring(x+1,str2.length()-1));
									str2=str2.substring(0,x);
								}
								final Ability A=CMClass.getAbility(str2);
								if(A!=null)
								{
									parms.add(A.ID());
									parms.add(Integer.valueOf(prof));
								}
							}
							v=V.size();
						}
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case _SKILLFLAG: // -skillflag
				case SKILLFLAG: // +skillflag
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						for(int v2=v+1;v2<V.size();v2++)
						{
							String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
							{
								v=v2-1;
								break;
							}
							else
							if((str2.startsWith("-"))||(str2.startsWith("+")))
							{
								str2=str2.substring(1).toUpperCase();
								final Object o=makeSkillFlagObject(str2);
								if(o!=null)
									parms.add(o);
							}
							v=V.size();
						}
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case ITEM: // +Item
				case WORN: // +Worn
				case _ITEM: // -Item
				case _WORN: // -Worn
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
							{
								v=v2-1;
								break;
							}
							else
							if((str2.startsWith("+"))||(str2.startsWith("-")))
								parms.add(str2.substring(1));
							v=V.size();
						}
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case MATERIAL: // +Material
				case _MATERIAL: // -Material
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						buildItemFlag=true;
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
							{
								v=v2-1;
								break;
							}
							else
							if((str2.startsWith("-"))||(str2.startsWith("+")))
							{
								final int code=CMLib.materials().getMaterialCode(str2.substring(1),false);
								if(code>=0)
									parms.add(RawMaterial.Material.findByMask(code&RawMaterial.MATERIAL_MASK).desc());
							}
							v=V.size();
						}
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case WORNON: // -WornOn
				case _WORNON: // +WornOn
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						buildItemFlag=true;
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
							{
								v=v2-1;
								break;
							}
							else
							if((str2.startsWith("-"))||(str2.startsWith("+")))
							{
								final long code=Wearable.CODES.FIND_endsWith(str2.substring(1));
								if(code>=0)
									parms.add(Long.valueOf(code));
							}
							v=V.size();
						}
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case DISPOSITION: // +Disposition
				case _DISPOSITION: // -Disposition
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
							{
								v=v2-1;
								break;
							}
							else
							if((str2.startsWith("-"))||(str2.startsWith("+")))
							{
								final int code=CMLib.flags().getDispositionIndex(str2.substring(1));
								if(code>=0)
									parms.add(Integer.valueOf((int)CMath.pow(2,code)));
							}
							v=V.size();
						}
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case SENSES: // +Senses
				case _SENSES: // -Senses
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
							{
								v=v2-1;
								break;
							}
							else
							if((str2.startsWith("-"))||(str2.startsWith("+")))
							{
								final int code=CMLib.flags().getSensesIndex(str2.substring(1));
								if(code>=0)
									parms.add(Integer.valueOf((int)CMath.pow(2,code)));
							}
							v=V.size();
						}
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case SEASON: // +Season
				case _SEASON: // -Season
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						buildRoomFlag=true;
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
							{
								v=v2-1;
								break;
							}
							else
							if((str2.startsWith("-"))||(str2.startsWith("+")))
							{
								if(CMath.isInteger(str2.substring(1).trim()))
									parms.add(Integer.valueOf(CMath.s_int(str2.substring(1).trim())));
								else
								{
									final int seasonCode=determineSeasonCode(str2.substring(1).trim());
									if(seasonCode>=0)
										parms.add(Integer.valueOf(seasonCode));
								}
							}
							v=V.size();
						}
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case WEATHER: // +weather
				case _WEATHER: // -weather
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						buildRoomFlag=true;
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
							{
								v=v2-1;
								break;
							}
							else
							if((str2.startsWith("-"))||(str2.startsWith("+")))
							{
								if(CMath.isInteger(str2.substring(1).trim()))
									parms.add(Integer.valueOf(CMath.s_int(str2.substring(1).trim())));
								else
								if(CMParms.indexOf(Climate.WEATHER_DESCS,str2.substring(1).trim())>=0)
									parms.add(Integer.valueOf(CMParms.indexOf(Climate.WEATHER_DESCS,str2.substring(1).trim())));
							}
							v=V.size();
						}
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case HOUR: // +HOUR
				case _HOUR: // -HOUR
				case MONTH: // +MONTH
				case _MONTH: // -MONTH
				case DAY: // +DAY
				case _DAY: // -DAY
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						buildRoomFlag=true;
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
							{
								v=v2-1;
								break;
							}
							else
							if((str2.startsWith("-"))||(str2.startsWith("+")))
								parms.add(Integer.valueOf(CMath.s_int(str2.substring(1).trim())));
							v=V.size();
						}
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case QUALLVL: // +quallvl
				case _QUALLVL: // -quallvl
					if((v+1)<V.size())
					{
						final Ability A=CMClass.getAbility(V.get(v+1));
						if(A!=null)
						{
							int adjustment=0;
							if(((v+2)<V.size())&&(CMath.isInteger(V.get(v+2))))
								adjustment=CMath.s_int(V.get(v+2));
							final ArrayList<Object> parms=new ArrayList<Object>();
							parms.add(A.ID());
							parms.add(Integer.valueOf(adjustment));
							buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
						}
					}
					break;
				case SUBOP: // +subop
				case _SUBOP: // +subop
					buildRoomFlag=true;
				//$FALL-THROUGH$
				case SYSOP: // +sysop
				case _SYSOP: // +sysop
				{
					buf.add(new CompiledZapperMaskEntryImpl(entryType,new Object[0]));
					break;
				}
				case RESOURCE: // +Resource
				case _RESOURCE: // -Resource
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						buildItemFlag=true;
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2))
							{
								v=v2-1;
								break;
							}
							else
							if((str2.startsWith("-"))||(str2.startsWith("+")))
							{
								final int code=CMLib.materials().getResourceCode(str2.substring(1),false);
								if(code>=0)
									parms.add(RawMaterial.CODES.NAME(code));
							}
							v=V.size();
						}
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case _PLAYER: // -Player
				case _NPC: // -MOB
					{
						buf.add(new CompiledZapperMaskEntryImpl(entryType,new Object[0]));
						break;
					}
				case _ANYCLASS: // -anyclass
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						for(final SavedClass C : charClasses())
						{
							if(fromHereStartsWith(V,'+',v+1,C.nameStart))
								parms.add(C.name);
						}
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case ANYCLASS: // +anyclass
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						for(final SavedClass C : charClasses())
						{
							if(fromHereStartsWith(V,'-',v+1,C.nameStart))
								parms.add(C.name);
						}
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
					}
					break;
				case VALUE: // +value
				case _VALUE: // -value
					buildItemFlag=true;
				//$FALL-THROUGH$
				case ADJSTRENGTH: // +adjstr
				case ADJINTELLIGENCE: // +adjint
				case ADJWISDOM: // +adjwis
				case ADJDEXTERITY: // +adjdex
				case ADJCONSTITUTION: // -adjcha
				case ADJCHARISMA: // +adjcha
				case _ADJSTRENGTH: // -adjstr
				case _ADJINTELLIGENCE: // -adjint
				case _ADJWISDOM: // -adjwis
				case _ADJDEXTERITY: // -adjdex
				case _ADJCONSTITUTION: // -adjcon
				case _ADJCHARISMA: // -adjcha
				case STRENGTH: // +str
				case INTELLIGENCE: // +int
				case WISDOM: // +wis
				case DEXTERITY: // +dex
				case CONSTITUTION: // +con
				case CHARISMA: // +cha
				case _STRENGTH: // -str
				case _INTELLIGENCE: // -int
				case _WISDOM: // -wis
				case _DEXTERITY: // -dex
				case _CONSTITUTION: // -con
				case _CHARISMA: // -cha
				case _CHANCE: // -chance
				case ABILITY: // +ability
				case _ABILITY: // -ability
				case WEIGHT: // +weight
				case _WEIGHT: // -weight
				case ARMOR: // +armor
				case _ARMOR: // -armor
				case DAMAGE: // +damage
				case _DAMAGE: // -damage
				case ATTACK: // +attack
				case _ATTACK: // -attack
				case _GROUPSIZE: // -groupsize
				case GROUPSIZE: // +groupsize
					{
						val=((++v)<V.size())?CMath.s_int(V.get(v)):0;
						final ArrayList<Object> parms=new ArrayList<Object>();
						parms.add(Integer.valueOf(val));
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
						break;
					}
				case _IF: // -if
				case IF: // +if
					{
						final ArrayList<Object> parms=new ArrayList<Object>();
						for(int v2=v+1;v2<V.size();v2++)
						{
							final String str2=V.get(v2);
							if(zapCodes.containsKey(str2)||(str2.startsWith("+"))||(str2.startsWith("-")))
							{
								v=v2-1;
								break;
							}
							else
							{
								final ScriptingEngine SE = (ScriptingEngine)CMClass.getCommon("DefaultScriptingEngine");
								SE.setSavable(false);
								SE.setVarScope("*");
								try
								{
									final String[] tt = SE.parseEval(str2);
									parms.add(SE);
									final String[][] EVAL={tt};
									parms.add(EVAL); // the compiled eval
									final Object[] tmp = new Object[ScriptingEngine.SPECIAL_NUM_OBJECTS];
									parms.add(tmp);
								}
								catch(final ScriptParseException spe)
								{
									Log.errOut("MUDZapper","Script parse Exception for "+str2);
									Log.errOut("MUDZapper",spe);
								}
							}
							v=V.size();
						}
						buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
						break;
					}
				case LVLEQ:
					// intentially left blank
					break;
				case LVLGE:
					// intentially left blank
					break;
				case LVLGR:
					// intentially left blank
					break;
				case LVLLE:
					// intentially left blank
					break;
				case LVLLT:
					// intentially left blank
					break;
				}
			}
			else
			{
				boolean found=false;
				if(!found)
				{
					for(final SavedClass C : charClasses())
					{
						if(str.equals("-"+C.upperName))
						{
							final ArrayList<Object> parms=new ArrayList<Object>();
							entryType=ZapperKey.CLASS;
							parms.add(C.name);
							found=true;
							buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
							break;
						}
					}
				}
				if(!found)
				{
					for(final SavedRace R : races())
					{
						if(str.equals("-"+R.upperName))
						{
							final ArrayList<Object> parms=new ArrayList<Object>();
							entryType=ZapperKey.RACE;
							parms.add(R.name);
							found=true;
							buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
							break;
						}
					}
				}
				if((!found)
				&&(str.equals("-"+Faction.Align.EVIL.toString())))
				{
					final ArrayList<Object> parms=new ArrayList<Object>();
					entryType=ZapperKey.ALIGNMENT;
					parms.add(Faction.Align.EVIL.toString());
					found=true;
					buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
				}
				if((!found)
				&&(str.equals("-"+Faction.Align.GOOD.toString())))
				{
					final ArrayList<Object> parms=new ArrayList<Object>();
					entryType=ZapperKey.ALIGNMENT;
					parms.add(Faction.Align.GOOD.toString());
					found=true;
					buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
				}
				if((!found)
				&&(str.equals("-"+Faction.Align.NEUTRAL.toString())))
				{
					final ArrayList<Object> parms=new ArrayList<Object>();
					entryType=ZapperKey.ALIGNMENT;
					parms.add(Faction.Align.NEUTRAL.toString());
					found=true;
					buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
				}
				if((!found)&&(str.equals("-MALE")))
				{
					final ArrayList<Object> parms=new ArrayList<Object>();
					entryType=ZapperKey.GENDER;
					parms.add("M");
					found=true;
					buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
				}
				if((!found)&&(str.equals("-FEMALE")))
				{
					final ArrayList<Object> parms=new ArrayList<Object>();
					entryType=ZapperKey.GENDER;
					parms.add("F");
					found=true;
					buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
				}
				if((!found)&&(str.equals("-NEUTER")))
				{
					final ArrayList<Object> parms=new ArrayList<Object>();
					entryType=ZapperKey.GENDER;
					parms.add("N");
					found=true;
					buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
				}
				if((!found)
				&&(str.startsWith("-"))
				&&(CMLib.factions().isRangeCodeName(str.substring(1))))
				{
					final ArrayList<Object> parms=new ArrayList<Object>();
					entryType=ZapperKey.FACTION;
					parms.add(str.substring(1));
					found=true;
					buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
				}
				if(!found)
				{
					for(final SavedClass C : charClasses())
					{
						if(str.startsWith(C.minusNameStart))
						{
							final ArrayList<Object> parms=new ArrayList<Object>();
							entryType=ZapperKey.CLASS;
							parms.add(C.name);
							found=true;
							buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
							break;
						}
					}
				}
				if(!found)
				{
					for(final SavedRace R : races())
					{
						if(str.startsWith(R.minusNameStart))
						{
							final ArrayList<Object> parms=new ArrayList<Object>();
							entryType=ZapperKey.RACE;
							parms.add(R.name);
							found=true;
							buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
							break;
						}
					}
				}
				if(!found)
				{
					for(final SavedRace R : races())
					{
						if(str.startsWith(R.minusCatNameStart))
						{
							final ArrayList<Object> parms=new ArrayList<Object>();
							entryType=ZapperKey.RACECAT;
							parms.add(R.racialCategory);
							buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
						}
					}
				}
				if((!found)
				&&(str.startsWith("-"+Faction.Align.EVIL.toString().substring(0,3))))
				{
					final ArrayList<Object> parms=new ArrayList<Object>();
					entryType=ZapperKey.ALIGNMENT;
					parms.add(Faction.Align.EVIL.toString());
					found=true;
					buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
				}
				if((!found)
				&&(str.startsWith("-"+Faction.Align.GOOD.toString().substring(0,3))))
				{
					final ArrayList<Object> parms=new ArrayList<Object>();
					entryType=ZapperKey.ALIGNMENT;
					parms.add(Faction.Align.GOOD.toString());
					found=true;
					buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
				}
				if((!found)
				&&(str.startsWith("-"+Faction.Align.NEUTRAL.toString().substring(0,3))))
				{
					final ArrayList<Object> parms=new ArrayList<Object>();
					entryType=ZapperKey.ALIGNMENT;
					parms.add(Faction.Align.NEUTRAL.toString());
					found=true;
					buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
				}
				if((!found)
				&&(str.startsWith("-MALE")))
				{
					final ArrayList<Object> parms=new ArrayList<Object>();
					entryType=ZapperKey.GENDER;
					parms.add("M");
					found=true;
					buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
				}
				if((!found)
				&&(str.startsWith("-FEMALE")))
				{
					final ArrayList<Object> parms=new ArrayList<Object>();
					entryType=ZapperKey.GENDER;
					parms.add("F");
					found=true;
					buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
				}
				if((!found)
				&&(str.startsWith("-NEUTER")))
				{
					final ArrayList<Object> parms=new ArrayList<Object>();
					entryType=ZapperKey.GENDER;
					parms.add("N");
					found=true;
					buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
				}
				if((!found)
				&&(str.startsWith("-"))
				&&(CMLib.factions().isRangeCodeName(str.substring(1))))
				{
					final ArrayList<Object> parms=new ArrayList<Object>();
					entryType=ZapperKey.FACTION;
					parms.add(str.substring(1));
					found=true;
					buf.add(new CompiledZapperMaskEntryImpl(entryType,parms.toArray(new Object[0])));
				}
				if(!found)
				{
					final CompiledZapperMaskEntry entry=levelCompiledHelper(str,'-');
					if(entry!=null)
						buf.add(entry);
				}
			}
		}
		return new CompiledZapperMaskImpl(new boolean[]{buildItemFlag,buildRoomFlag},buf.toArray(new CompiledZapperMaskEntry[0]));
	}

	protected Room outdoorRoom(Area A)
	{
		Room R=null;
		for(final Enumeration<Room> e=A.getMetroMap();e.hasMoreElements();)
		{
			R=e.nextElement();
			if((R.domainType()&Room.INDOORS)==0)
				return R;
		}
		return A.getRandomMetroRoom();
	}

	protected CharStats getBaseCharStats(CharStats base, MOB mob)
	{
		if(base==null)
		{
			base=(CharStats)mob.baseCharStats().copyOf();
			base.getMyRace().affectCharStats(mob,base);
		}
		return base;
	}

	@Override
	public boolean maskCheck(final String text, final Environmental E, final boolean actual)
	{
		return maskCheck(getPreCompiledMask(text), E, actual);
	}

	@SuppressWarnings("unchecked")
	@Override
	public boolean maskCheck(final CompiledZapperMask cset, final Environmental E, final boolean actual)
	{
		if(E==null)
			return true;
		if((cset==null)||(cset.entries().length<1))
			return true;
		getMaskCodes();
		CharStats base=null;
		final MOB mob=(E instanceof MOB)?(MOB)E:nonCrashingMOB();
		final boolean[] flags=cset.flags();
		final Item item=flags[0]?((E instanceof Item)?(Item)E:nonCrashingItem(mob)):null;
		final Room room = flags[1]?((E instanceof Area)?outdoorRoom((Area)E):CMLib.map().roomLocation(E)):null;
		final Physical P = (E instanceof Physical)?(Physical)E:null;
		if((mob==null)||(flags[0]&&(item==null)))
			return false;
		for(final CompiledZapperMaskEntry entry : cset.entries())
		{
			try
			{
				switch(entry.maskType())
				{
				case SYSOP: // +sysop
					if(CMSecurity.isASysOp(mob))
						return true;
					break;
				case _SYSOP: // -sysop
					if(CMSecurity.isASysOp(mob))
						return false;
					break;
				case SUBOP: // +subop
					if(CMSecurity.isASysOp(mob)
					||((room!=null)&&(room.getArea().amISubOp(mob.Name()))))
						return true;
					break;
				case _SUBOP: // -subop
					if(CMSecurity.isASysOp(mob)
					||((room!=null)&&(room.getArea().amISubOp(mob.Name()))))
						return false;
					break;
				case CLASS: // +class
					if(CMParms.contains(entry.parms(),actual?mob.baseCharStats().getCurrentClass().name():mob.charStats().displayClassName()))
						return false;
					break;
				case _CLASS: // -class
				{
					if(!CMParms.contains(entry.parms(),actual?mob.baseCharStats().getCurrentClass().name():mob.charStats().displayClassName()))
						return false;
					break;
				}
				case _BASECLASS: // -baseclass
				{
					String baseClass=mob.baseCharStats().getCurrentClass().baseClass();
					if((!actual)&&(!baseClass.equals(mob.charStats().displayClassName())))
					{
						final CharClass C=CMClass.getCharClass(mob.charStats().displayClassName());
						if(C!=null)
							baseClass=C.baseClass();
					}
					if(!CMParms.contains(entry.parms(),baseClass))
						return false;
					break;
				}
				case BASECLASS: // +baseclass
				{
					String baseClass=mob.baseCharStats().getCurrentClass().baseClass();
					if((!actual)&&(!baseClass.equals(mob.charStats().displayClassName())))
					{
						final CharClass C=CMClass.getCharClass(mob.charStats().displayClassName());
						if(C!=null)
							baseClass=C.baseClass();
					}
					if(CMParms.contains(entry.parms(),baseClass))
						return false;
					break;
				}
				case _RACE: // -race
					if(!CMParms.contains(entry.parms(),actual?mob.baseCharStats().getMyRace().name():mob.charStats().raceName()))
						return false;
					break;
				case _ALIGNMENT: // -alignment
					if(!CMParms.contains(entry.parms(),CMLib.flags().getAlignmentName(mob)))
						return false;
					break;
				case _GENDER: // -gender
				{
					base=getBaseCharStats(base,mob);
					if(!CMParms.contains(entry.parms(),actual?(""+((char)base.getStat(CharStats.STAT_GENDER))):(""+(Character.toUpperCase(mob.charStats().genderName().charAt(0))))))
						return false;
					break;
				}
				case _LEVEL: // -level
					if(P!=null)
					{
						final int level=actual?P.basePhyStats().level():P.phyStats().level();
						boolean found=false;
						for(int v=0;v<entry.parms().length-1;v+=2)
						{
							switch((ZapperKey)entry.parms()[v])
							{
							case LVLGR: // +lvlgr
								if(level>((Integer)entry.parms()[v+1]).intValue())
									found=true;
								break;
							case LVLGE: // +lvlge
								if(level>=((Integer)entry.parms()[v+1]).intValue())
									found=true;
								break;
							case LVLLT: // +lvlt
								if(level<((Integer)entry.parms()[v+1]).intValue())
									found=true;
								break;
							case LVLLE: // +lvlle
								if(level<=((Integer)entry.parms()[v+1]).intValue())
									found=true;
								break;
							case LVLEQ: // +lvleq
								if(level==((Integer)entry.parms()[v+1]).intValue())
									found=true;
								break;
							default:
								break;
							}
						}
						if(!found)
							return false;
					}
					break;
				case _CLASSLEVEL: // -classlevel
					{
						boolean found=false;
						final int cl=actual?mob.baseCharStats().getClassLevel(mob.baseCharStats().getCurrentClass())
									 :mob.charStats().getClassLevel(mob.charStats().getCurrentClass());
						for(int v=0;v<entry.parms().length-1;v+=2)
						{
							switch((ZapperKey)entry.parms()[v])
							{
							case LVLGR: // +lvlgr
								if(cl>((Integer)entry.parms()[v+1]).intValue())
									found=true;
								break;
							case LVLGE: // +lvlge
								if(cl>=((Integer)entry.parms()[v+1]).intValue())
									found=true;
								break;
							case LVLLT: // +lvlt
								if(cl<((Integer)entry.parms()[v+1]).intValue())
									found=true;
								break;
							case LVLLE: // +lvlle
								if(cl<=((Integer)entry.parms()[v+1]).intValue())
									found=true;
								break;
							case LVLEQ: // +lvleq
								if(cl==((Integer)entry.parms()[v+1]).intValue())
									found=true;
								break;
							default:
								break;
							}
						}
						if(!found)
							return false;
					}
					break;
				case _ANYCLASSLEVEL: // -anyclasslevel
					{
						boolean allFound = false;
						for(int i=0;i<entry.parms().length;i+=3)
						{
							boolean found=false;
							final CharClass C = (CharClass)entry.parms()[i];
							final int cl=actual?mob.baseCharStats().getClassLevel(C)
												:mob.charStats().getClassLevel(C);
							if(cl < 0)
								found = false;
							else
							switch((ZapperKey)entry.parms()[i+1])
							{
							case LVLGR: // +lvlgr
								if(cl>((Integer)entry.parms()[i+2]).intValue())
									found=true;
								break;
							case LVLGE: // +lvlge
								if(cl>=((Integer)entry.parms()[i+2]).intValue())
									found=true;
								break;
							case LVLLT: // +lvlt
								if(cl<((Integer)entry.parms()[i+2]).intValue())
									found=true;
								break;
							case LVLLE: // +lvlle
								if(cl<=((Integer)entry.parms()[i+2]).intValue())
									found=true;
								break;
							case LVLEQ: // +lvleq
								if(cl==((Integer)entry.parms()[i+2]).intValue())
									found=true;
								break;
							default:
								break;
							}
							allFound = allFound || found;
						}
						if(!allFound)
							return false;
					}
					break;
				case ANYCLASSLEVEL: // +classlevel
					{
						for(int i=0;i<entry.parms().length;i+=3)
						{
							final CharClass C = (CharClass)entry.parms()[i+0];
							final int cl=actual?mob.baseCharStats().getClassLevel(C)
												:mob.charStats().getClassLevel(C);
							if(cl >= 0)
							{
								switch((ZapperKey)entry.parms()[i+1])
								{
								case LVLGR: // lvlgr
									if(cl>((Integer)entry.parms()[i+2]).intValue())
										return false;
									break;
								case LVLGE: // lvlge
									if(cl>=((Integer)entry.parms()[i+2]).intValue())
										return false;
									break;
								case LVLLT: // lvlt
									if(cl<((Integer)entry.parms()[i+2]).intValue())
										return false;
									break;
								case LVLLE: // lvlle
									if(cl<=((Integer)entry.parms()[i+2]).intValue())
										return false;
									break;
								case LVLEQ: // +lvleq
									if(cl==((Integer)entry.parms()[i+2]).intValue())
										return false;
									break;
								default:
									break;
								}
							}
						}
					}
					break;
				case _MAXCLASSLEVEL: // -maxclasslevel
					{
						boolean found=false;
						int cl=0;
						int c2=0;
						if(actual)
						{
							cl=mob.baseCharStats().getClassLevel(mob.baseCharStats().getMyClass(0));
							for(int v=1;v<mob.baseCharStats().numClasses();v++)
							{
								c2=mob.baseCharStats().getClassLevel(mob.baseCharStats().getMyClass(v));
								if(c2>cl)
									cl=c2;
							}
						}
						else
						{
							cl=mob.charStats().getClassLevel(mob.charStats().getMyClass(0));
							for(int v=1;v<mob.charStats().numClasses();v++)
							{
								c2=mob.charStats().getClassLevel(mob.charStats().getMyClass(v));
								if(c2>cl)
									cl=c2;
							}
						}
						for(int v=0;v<entry.parms().length-1;v+=2)
						{
							switch((ZapperKey)entry.parms()[v])
							{
							case LVLGR: // +lvlgr
								if(cl>((Integer)entry.parms()[v+1]).intValue())
									found=true;
								break;
							case LVLGE: // +lvlge
								if(cl>=((Integer)entry.parms()[v+1]).intValue())
									found=true;
								break;
							case LVLLT: // +lvlt
								if(cl<((Integer)entry.parms()[v+1]).intValue())
									found=true;
								break;
							case LVLLE: // +lvlle
								if(cl<=((Integer)entry.parms()[v+1]).intValue())
									found=true;
								break;
							case LVLEQ: // +lvleq
								if(cl==((Integer)entry.parms()[v+1]).intValue())
									found=true;
								break;
							default:
								break;
							}
						}
						if(!found)
							return false;
					}
					break;
				case _TATTOO: // -tattoo
					{
						boolean found=false;
						for(final Object o : entry.parms())
						{
							if((mob.findTattoo((String)o)!=null)
							||((room!=null)&&(room.getArea().getBlurbFlag((String)o)!=null)))
							{
								found = true;
								break;
							}
						}
						if(!found)
							return false;
					}
					break;
				case TATTOO: // +tattoo
					{
						for(final Object o : entry.parms())
						{
							if((mob.findTattoo((String)o)!=null)
							||((room!=null)&&(room.getArea().getBlurbFlag((String)o)!=null)))
								return false;
						}
					}
					break;
				case _MOOD: // -mood
					{
						String moodName = "NORMAL";
						final Ability A = mob.fetchEffect("Mood");
						if((A!=null)&&(A.text().trim().length()>0))
							moodName=A.text().toUpperCase().trim();
						if(!CMParms.contains(entry.parms(),moodName))
							return false;
					}
					break;
				case MOOD: // +mood
					{
						final String moodName;
						final Ability A = mob.fetchEffect("Mood");
						if((A!=null)&&(A.text().trim().length()>0))
							moodName=A.text().toUpperCase().trim();
						else
							moodName= "NORMAL";
						if(CMParms.contains(entry.parms(),moodName))
							return false;
					}
					break;
				case _ACCCHIEVE: // -accchieves
					{
						boolean found=false;
						final PlayerStats playerStats = mob.playerStats();
						if((playerStats != null) && (mob.playerStats().getAccount()!=null))
						{
							final PlayerAccount acct = playerStats.getAccount();
							for(final Object o : entry.parms())
							{
								if((acct.findTattoo((String)o)!=null)
								||((room!=null)&&(room.getArea().getBlurbFlag((String)o)!=null)))
								{
									found = true;
									break;
								}
							}
						}
						if(!found)
							return false;
					}
					break;
				case ACCCHIEVE: // +accchieves
					{
						final PlayerStats playerStats = mob.playerStats();
						if((playerStats != null) && (mob.playerStats().getAccount()!=null))
						{
							final PlayerAccount acct = playerStats.getAccount();
							for(final Object o : entry.parms())
							{
								if((acct.findTattoo((String)o)!=null)
								||((room!=null)&&(room.getArea().getBlurbFlag((String)o)!=null)))
									return false;
							}
						}
					}
					break;
				case _EXPERTISE: // -expertise
					{
						boolean found=false;
						for(final Object o : entry.parms())
						{
							if(mob.fetchExpertise((String)o)!=null)
							{
								found = true;
								break;
							}
						}
						if(!found)
							return false;
					}
					break;
				case EXPERTISE: // +expertise
					{
						for(final Object o : entry.parms())
						{
							if(mob.fetchExpertise((String)o)!=null)
								return false;
						}
					}
					break;
				case _QUESTWIN: // -questwin
					{
						boolean found=false;
						for(final Object o : entry.parms())
						{
							final Quest Q=CMLib.quests().fetchQuest((String)o);
							if((Q!=null)&&(Q.wasWinner(mob.Name())))
							{
								found = true;
								break;
							}
						}
						if(!found)
							return false;
					}
					break;
				case QUESTWIN: // +questwin
					{
						for(final Object o : entry.parms())
						{
							final Quest Q=CMLib.quests().fetchQuest((String)o);
							if((Q!=null)&&(Q.wasWinner(mob.Name())))
								return false;
						}
					}
					break;
				case _SKILL: // -skill
					{
						boolean found=false;
						for(int v=0;v<entry.parms().length-1;v+=2)
						{
							final Ability A=mob.fetchAbility((String)entry.parms()[v]);
							if((A!=null)&&(A.proficiency()>=((Integer)entry.parms()[v+1]).intValue()))
							{
								found = true;
								break;
							}
						}
						if(!found)
							return false;
					}
					break;
				case _SKILLFLAG: // -skillflag
					{
						boolean found=false;
						for(final Object o : entry.parms())
						{
							for(final Enumeration<Ability> a=mob.allAbilities();a.hasMoreElements();)
							{
								final Ability A=a.nextElement();
								if(evaluateSkillFlagObject(o,A))
								{
									found = true;
									break;
								}
							}
							if(found)
								break;
						}
						if(!found)
							return false;
					}
					break;
				case SKILL: // +skill
					{
						for(int v=0;v<entry.parms().length-1;v+=2)
						{
							final Ability A=mob.fetchAbility((String)entry.parms()[v]);
							if((A!=null)&&(A.proficiency()>=((Integer)entry.parms()[v+1]).intValue()))
								return false;
						}
					}
					break;
				case SKILLFLAG: // +skillflag
					{
						for(final Object o : entry.parms())
						{
							for(final Enumeration<Ability> a=mob.allAbilities();a.hasMoreElements();)
							{
								final Ability A=a.nextElement();
								if(evaluateSkillFlagObject(o,A))
									return false;
							}
						}
					}
					break;
				case _SECURITY: // -security
					{
						boolean found=false;
						for(final Object o : entry.parms())
						{
							if(CMSecurity.isAllowed(mob,room,(CMSecurity.SecFlag)o))
							{
								found = true;
								break;
							}
						}
						if(!found)
							return false;
					}
					break;
				case SECURITY: // +security
					{
						for(final Object o : entry.parms())
						{
							if(CMSecurity.isAllowed(mob,room,(CMSecurity.SecFlag)o))
								return false;
						}
					}
					break;
				case _NAME: // -names
					{
						boolean found=false;
						final String name=actual?E.Name():E.name();
						for(final Object o : entry.parms())
						{
							if(name.equalsIgnoreCase((String)o))
							{
								found = true;
								break;
							}
						}
						if(!found)
							return false;
					}
					break;
				case _PLAYER: // -player
					if(!mob.isMonster())
						return false;
					break;
				case _NPC: // -npc
					if(mob.isMonster())
						return false;
					break;
				case _RACECAT: // -racecat
				{
					String raceCat=mob.baseCharStats().getMyRace().racialCategory();
					if((!actual)&&(!mob.baseCharStats().getMyRace().name().equals(mob.charStats().raceName())))
					{
						final Race R2=CMClass.getRace(mob.charStats().raceName());
						if(R2!=null)
							raceCat=R2.racialCategory();
					}
					if(!CMParms.contains(entry.parms(),raceCat))
						return false;
					break;
				}
				case RACE: // +race
				{
					String race=mob.baseCharStats().getMyRace().name();
					if((!actual)&&(!mob.baseCharStats().getMyRace().name().equals(mob.charStats().raceName())))
						race=mob.charStats().raceName();
					if(CMParms.contains(entry.parms(),race))
						return false;
					break;
				}
				case RACECAT: // +racecat
				{
					String raceCat=mob.baseCharStats().getMyRace().racialCategory();
					if((!actual)&&(!mob.baseCharStats().getMyRace().name().equals(mob.charStats().raceName())))
					{
						final Race R2=CMClass.getRace(mob.charStats().raceName());
						if(R2!=null)
							raceCat=R2.racialCategory();
					}
					if(CMParms.contains(entry.parms(),raceCat))
						return false;
					break;
				}
				case _CLAN: // -clan
					{
						boolean found=false;
						if(E instanceof ClanItem)
						{
							final String clanID=((ClanItem)E).clanID();
							for(final Object o : entry.parms())
								if(o instanceof String)
								{
									if((clanID.equalsIgnoreCase((String)o))
									||(((String)o).equals("*")))
									{ 
										found=true; 
										break;
									}
								}
								else
								if(o instanceof Pair)
								{
									if(clanID.equalsIgnoreCase(((Pair<String,String>)o).first)
									||((((Pair<String,String>)o).first).equals("*")))
									{ 
										found=true; 
										break;
									}
								}
						}
						else
						if(E instanceof MOB)
						{
							for(final Pair<Clan,Integer> c : ((MOB)E).clans())
							{
								for(final Object o : entry.parms())
								{
									if(o instanceof String)
									{
										if(c.first.clanID().equalsIgnoreCase((String)o)
										||(((String)o).equals("*")))
										{ 
											found=true; 
											break;
										}
									}
									else
									if(o instanceof Pair)
									{
										if(c.first.clanID().equalsIgnoreCase(((Pair<String,String>)o).first)
										||((((Pair<String,String>)o).first).equals("*")))
										{ 
											if((((Pair<String,String>)o).second).equals("*"))
											{
												found=true; 
												break;
											}
											else
											{
												ClanPosition cP=c.first.getGovernment().getPosition(((Pair<String,String>)o).second);
												if((cP==null)||(cP.getRoleID()==c.second.intValue()))
												{
													found=true; 
													break;
												}
											}
										}
									}
								}
							}
						}
						if(!found)
							return false;
					}
					break;
				case CLAN: // +clan
					if(E instanceof ClanItem)
					{
						final String clanID=((ClanItem)E).clanID();
						for(final Object o : entry.parms())
						{
							if(o instanceof String)
							{
								if((clanID.equalsIgnoreCase((String)o))
								||(((String)o).equals("*")))
									return false;
							}
							else
							if(o instanceof Pair)
							{
								if(clanID.equalsIgnoreCase(((Pair<String,String>)o).first)
								||((((Pair<String,String>)o).first).equals("*")))
									return false;
							}
						}
					}
					else
					if(E instanceof MOB)
					{
						for(final Pair<Clan,Integer> c : ((MOB)E).clans())
						{
							for(final Object o : entry.parms())
							{
								if(o instanceof String)
								{
									if(c.first.clanID().equalsIgnoreCase((String)o)
									||(((String)o).equals("*")))
										return false;
								}
								else
								if(o instanceof Pair)
								{
									if(c.first.clanID().equalsIgnoreCase(((Pair<String,String>)o).first)
									||((((Pair<String,String>)o).first).equals("*")))
									{ 
										if((((Pair<String,String>)o).second).equals("*"))
											return false;
										else
										{
											ClanPosition cP=c.first.getGovernment().getPosition(((Pair<String,String>)o).second);
											if((cP!=null)&&(cP.getRoleID()==c.second.intValue()))
												return false;
										}
									}
								}
							}
						}
					}
					break;
				case MATERIAL: // +material
					if((item!=null)&&CMParms.contains(entry.parms(),RawMaterial.Material.findByMask(item.material()&RawMaterial.MATERIAL_MASK).desc()))
						return false;
					break;
				case _MATERIAL: // -material
					if((item!=null)&&(!CMParms.contains(entry.parms(),RawMaterial.Material.findByMask(item.material()&RawMaterial.MATERIAL_MASK).desc())))
						return false;
					break;
				case WORNON: // +wornOn
					if(item!=null)
					{
						for(final Object o : entry.parms())
						{
							if((item.rawProperLocationBitmap()&((Long)o).longValue())>0)
								return false;
						}
					}
					break;
				case _WORNON: // -wornOn
					{
						boolean found=false;
						if(item!=null)
						{
							for(final Object o : entry.parms())
							{
								if((item.rawProperLocationBitmap()&((Long)o).longValue())>0)
								{
									found = true;
									break;
								}
							}
						}
						if(!found)
							return false;
					}
					break;
				case DISPOSITION: // +disposition
					if(P!=null)
					{
						for(final Object o : entry.parms())
						{
							if((P.phyStats().disposition()&((Integer)o).intValue())>0)
								return false;
						}
					}
					break;
				case _DISPOSITION: // -disposition
					if(P!=null)
					{
						boolean found=false;
						for(final Object o : entry.parms())
						{
							if((P.phyStats().disposition()&((Integer)o).intValue())>0)
							{
								found = true;
								break;
							}
						}
						if(!found)
							return false;
					}
					break;
				case SENSES: // +senses
					if(P!=null)
					{
						for(final Object o : entry.parms())
						{
							if((P.phyStats().sensesMask()&((Integer)o).intValue())>0)
								return false;
						}
					}
					break;
				case _SENSES: // -senses
					if(P!=null)
					{
						boolean found=false;
						for(final Object o : entry.parms())
						{
							if((P.phyStats().sensesMask()&((Integer)o).intValue())>0)
							{
								found = true;
								break;
							}
						}
						if(!found)
							return false;
					}
					break;
				case HOUR: // +HOUR
					{
						if(room!=null)
						{
							for(final Object o : entry.parms())
							{
								if(room.getArea().getTimeObj().getHourOfDay()==((Integer)o).intValue())
									return false;
							}
						}
					}
					break;
				case _HOUR: // -HOUR
					{
						boolean found=false;
						if(room!=null)
						{
							for(final Object o : entry.parms())
							{
								if(room.getArea().getTimeObj().getHourOfDay()==((Integer)o).intValue())
								{
									found = true;
									break;
								}
							}
						}
						if(!found)
							return false;
					}
					break;
				case SEASON: // +season
					{
						if(room!=null)
						{
							for(final Object o : entry.parms())
							{
								if(room.getArea().getTimeObj().getSeasonCode().ordinal()==((Integer)o).intValue())
									return false;
							}
						}
					}
					break;
				case _SEASON: // -season
					{
						boolean found=false;
						if(room!=null)
						{
							for(final Object o : entry.parms())
							{
								if(room.getArea().getTimeObj().getSeasonCode().ordinal()==((Integer)o).intValue())
								{
									found = true;
									break;
								}
							}
						}
						if(!found)
							return false;
					}
					break;
				case WEATHER: // +weather
					{
						if(room!=null)
						{
							for(final Object o : entry.parms())
							{
								if(room.getArea().getClimateObj().weatherType(room)==((Integer)o).intValue())
									return false;
							}
						}
					}
					break;
				case _WEATHER: // -weather
					{
						boolean found=false;
						if(room!=null)
						{
							for(final Object o : entry.parms())
							{
								if(room.getArea().getClimateObj().weatherType(room)==((Integer)o).intValue())
								{
									found = true;
									break;
								}
							}
						}
						if(!found)
							return false;
					}
					break;
				case MONTH: // +month
					{
						if(room!=null)
						{
							for(final Object o : entry.parms())
							{
								if(room.getArea().getTimeObj().getMonth()==((Integer)o).intValue())
									return false;
							}
						}
					}
					break;
				case _MONTH: // -month
					{
						boolean found=false;
						if(room!=null)
						{
							for(final Object o : entry.parms())
							{
								if(room.getArea().getTimeObj().getMonth()==((Integer)o).intValue())
								{
									found = true;
									break;
								}
							}
						}
						if(!found)
							return false;
					}
					break;
				case DAY: // +day
					{
						if(room!=null)
						{
							for(final Object o : entry.parms())
							{
								if(room.getArea().getTimeObj().getDayOfMonth()==((Integer)o).intValue())
									return false;
							}
						}
					}
					break;
				case _DAY: // -day
					{
						boolean found=false;
						if(room!=null)
						{
							for(final Object o : entry.parms())
							{
								if(room.getArea().getTimeObj().getDayOfMonth()==((Integer)o).intValue())
								{
									found = true;
									break;
								}
							}
						}
						if(!found)
							return false;
					}
					break;
				case QUALLVL: // +quallvl
					if(entry.parms().length>1)
					{
						final Ability A=CMClass.getAbility((String)entry.parms()[0]);
						final int adjustment=((Integer)entry.parms()[1]).intValue();
						final int lvl=CMLib.ableMapper().qualifyingClassLevel(mob,A);
						final int clvl=CMLib.ableMapper().qualifyingLevel(mob,A)+adjustment;
						if(lvl<clvl)
							return false;
					}
					break;
				case _QUALLVL: // -quallvl
					if(entry.parms().length>1)
					{
						final Ability A=CMClass.getAbility((String)entry.parms()[0]);
						final int adjustment=((Integer)entry.parms()[1]).intValue();
						final int lvl=CMLib.ableMapper().qualifyingClassLevel(mob,A);
						final int clvl=CMLib.ableMapper().qualifyingLevel(mob,A)+adjustment;
						if(lvl>clvl)
							return false;
					}
					break;
				case RESOURCE: // +resource
					if((item!=null)&&CMParms.contains(entry.parms(),RawMaterial.CODES.NAME(item.material())))
						return false;
					break;
				case _RESOURCE: // -resource
					if((item!=null)&&(!CMParms.contains(entry.parms(),RawMaterial.CODES.NAME(item.material()))))
						return false;
					break;
				case _JAVACLASS: // -JavaClass
					{
						boolean found=false;
						for(final Object o : entry.parms())
						{
							if(E.ID().equalsIgnoreCase((String)o))
							{
								found = true;
								break;
							}
						}
						if(!found)
							return false;
					}
					break;
				case JAVACLASS: // +JavaClass
					for(final Object o : entry.parms())
					{
						if(E.ID().equalsIgnoreCase((String)o))
							return false;
					}
					break;
				case _DEITY: // -deity
					{
						if(mob.getWorshipCharID().length()==0)
							return false;
						boolean found=false;
						for(final Object o : entry.parms())
						{
							if(mob.getWorshipCharID().equalsIgnoreCase((String)o)||((String)o).equals("ANY"))
							{
								found = true;
								break;
							}
						}
						if(!found)
							return false;
					}
					break;
				case DEITY: // +deity
					{
						if(mob.getWorshipCharID().length()>0)
						{
							for(final Object o : entry.parms())
							{
								if(mob.getWorshipCharID().equalsIgnoreCase((String)o))
									return false;
							}
						}
					}
					break;
				case _EFFECT: // -effects
					{
						boolean found=false;
						if(E instanceof PhysicalAgent)
						{
							for(final Object o : entry.parms())
							{
								if(((Physical)E).fetchEffect((String)o)!=null)
								{
									found = true;
									break;
								}
							}
						}
						if((!found)&&(E instanceof PhysicalAgent))
						{
							for(final Object o : entry.parms())
							{
								if(((PhysicalAgent)E).fetchBehavior((String)o)!=null)
								{
									found = true;
									break;
								}
							}
						}
						if(!found)
							return false;
					}
					break;
				case _FACTION: // -faction
					{
						boolean found=false;
						for(final Object o : entry.parms())
						{
							final Faction.FRange FR=getRange((String)o);
							if((FR!=null)&&(CMLib.factions().isFactionedThisWay(mob,FR)))
							{
								found=true;
								break;
							}
						}
						if(!found)
							return false;
					}
					break;
				case FACTION: // +faction
					{
						for(final Object o : entry.parms())
						{
							final Faction.FRange FR=getRange((String)o);
							if((FR!=null)&&(CMLib.factions().isFactionedThisWay(mob,FR)))
								return false;
						}
					}
					break;
				case EFFECT: // +effects
					{
						if(E instanceof Physical)
						{
							for(final Object o : entry.parms())
							{
								if(((Physical)E).fetchEffect((String)o)!=null)
									return false;
							}
						}
						if(E instanceof PhysicalAgent)
						{
							for(final Object o : entry.parms())
							{
								if(((PhysicalAgent)E).fetchBehavior((String)o)!=null)
									return false;
							}
						}
					}
					break;
				case NAME: // +name
					{
						final String name=actual?E.Name():E.name();
						for(final Object o : entry.parms())
						{
							if(name.equalsIgnoreCase((String)o))
								return false;
						}
					}
					break;
				case _ANYCLASS: // -anyclass
					{
						boolean found=false;
						if(actual)
						{
							for(final Object o : entry.parms())
							{
								if(mob.baseCharStats().getClassLevel((String)o)>=0)
								{
									found = true;
									break;
								}
							}
						}
						else
						{
							for(final Object o : entry.parms())
							{
								if((mob.charStats().getClassLevel((String)o)>=0)
								||(mob.charStats().displayClassName().equalsIgnoreCase((String)o)))
								{
									found = true;
									break;
								}
							}
						}
						if(!found)
							return false;
					}
					break;
				case ANYCLASS: // +anyclass
					if(actual)
					{
						for(final Object o : entry.parms())
						{
							if(mob.baseCharStats().getClassLevel((String)o)>=0)
								return false;
						}
					}
					else
					{
						for(final Object o : entry.parms())
						{
							if((mob.charStats().getClassLevel((String)o)>=0)
							||(mob.charStats().displayClassName().equalsIgnoreCase((String)o)))
								return false;
						}
					}
					break;
				case ADJSTRENGTH: // +adjstr
					if((entry.parms().length>0)&&(mob.charStats().getStat(CharStats.STAT_STRENGTH)<(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case ADJINTELLIGENCE: // +adjint
					if((entry.parms().length>0)&&(mob.charStats().getStat(CharStats.STAT_INTELLIGENCE)<(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case ADJWISDOM: // +adjwis
					if((entry.parms().length>0)&&(mob.charStats().getStat(CharStats.STAT_WISDOM)<(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case ADJDEXTERITY: // +adjdex
					if((entry.parms().length>0)&&(mob.charStats().getStat(CharStats.STAT_DEXTERITY)<(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case ADJCONSTITUTION: // -adjcha
					if((entry.parms().length>0)&&(mob.charStats().getStat(CharStats.STAT_CONSTITUTION)<(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case ADJCHARISMA: // +adjcha
					if((entry.parms().length>0)&&(mob.charStats().getStat(CharStats.STAT_CHARISMA)<(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case _ADJSTRENGTH: // -adjstr
					if((entry.parms().length>0)&&(mob.charStats().getStat(CharStats.STAT_STRENGTH)>(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case _ADJINTELLIGENCE: // -adjint
					if((entry.parms().length>0)&&(mob.charStats().getStat(CharStats.STAT_INTELLIGENCE)>(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case _ADJWISDOM: // -adjwis
					if((entry.parms().length>0)&&(mob.charStats().getStat(CharStats.STAT_WISDOM)>(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case _ADJDEXTERITY: // -adjdex
					if((entry.parms().length>0)&&(mob.charStats().getStat(CharStats.STAT_DEXTERITY)>(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case _ADJCONSTITUTION: // -adjcon
					if((entry.parms().length>0)&&(mob.charStats().getStat(CharStats.STAT_CONSTITUTION)>(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case _ADJCHARISMA: // -adjcha
					if((entry.parms().length>0)&&(mob.charStats().getStat(CharStats.STAT_CHARISMA)>(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case STRENGTH: // +str
					base=getBaseCharStats(base,mob);
					if((entry.parms().length>0)&&(base.getStat(CharStats.STAT_STRENGTH)<(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case INTELLIGENCE: // +int
					base=getBaseCharStats(base,mob);
					if((entry.parms().length>0)&&(base.getStat(CharStats.STAT_INTELLIGENCE)<(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case WISDOM: // +wis
					base=getBaseCharStats(base,mob);
					if((entry.parms().length>0)&&(base.getStat(CharStats.STAT_WISDOM)<(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case DEXTERITY: // +dex
					base=getBaseCharStats(base,mob);
					if((entry.parms().length>0)&&(base.getStat(CharStats.STAT_DEXTERITY)<(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case CONSTITUTION: // +con
					base=getBaseCharStats(base,mob);
					if((entry.parms().length>0)&&(base.getStat(CharStats.STAT_CONSTITUTION)<(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case CHARISMA: // +cha
					base=getBaseCharStats(base,mob);
					if((entry.parms().length>0)&&(base.getStat(CharStats.STAT_CHARISMA)<(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case _STRENGTH: // -str
					base=getBaseCharStats(base,mob);
					if((entry.parms().length>0)&&(base.getStat(CharStats.STAT_STRENGTH)>(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case _INTELLIGENCE: // -int
					base=getBaseCharStats(base,mob);
					if((entry.parms().length>0)&&(base.getStat(CharStats.STAT_INTELLIGENCE)>(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case _WISDOM: // -wis
					base=getBaseCharStats(base,mob);
					if((entry.parms().length>0)&&(base.getStat(CharStats.STAT_WISDOM)>(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case _DEXTERITY: // -dex
					base=getBaseCharStats(base,mob);
					if((entry.parms().length>0)&&(base.getStat(CharStats.STAT_DEXTERITY)>(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case _CONSTITUTION: // -con
					base=getBaseCharStats(base,mob);
					if((entry.parms().length>0)&&(base.getStat(CharStats.STAT_CONSTITUTION)>(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case _CHARISMA: // -cha
					base=getBaseCharStats(base,mob);
					if((entry.parms().length>0)
					&&(base.getStat(CharStats.STAT_CHARISMA)>(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case _CHANCE: // -chance
					if((entry.parms().length>0)
					&&(CMLib.dice().rollPercentage()<(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case ABILITY: // +ability
					if((entry.parms().length>0)
					&&(P != null)
					&&(P.phyStats().ability()>(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case _ABILITY: // -ability
					if((entry.parms().length>0)
					&&(P != null)
					&&(P.phyStats().ability()<(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case WEIGHT: // +weight
					if((entry.parms().length>0)
					&&(P != null)
					&&(P.phyStats().weight()>(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case _WEIGHT: // -weight
					if((entry.parms().length>0)
					&&(P != null)
					&&(P.phyStats().weight()<(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case ARMOR: // +armor
					if((entry.parms().length>0)
					&&(P != null)
					&&(P.phyStats().armor()>(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case _ARMOR: // -armor
					if((entry.parms().length>0)
					&&(P != null)
					&&(P.phyStats().armor()<(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case DAMAGE: // +damage
					if((entry.parms().length>0)
					&&(P != null)
					&&(P.phyStats().damage()>(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case _DAMAGE: // -damage
					if((entry.parms().length>0)
					&&(P != null)
					&&(P.phyStats().damage()<(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case ATTACK: // +attack
					if((entry.parms().length>0)
					&&(P != null)
					&&(P.phyStats().attackAdjustment()>(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case _ATTACK: // -attack
					if((entry.parms().length>0)
					&&(P != null)
					&&(P.phyStats().attackAdjustment()<(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case VALUE: // +value
					if(E instanceof MOB)
					{
						if((entry.parms().length>0)
						&&(CMLib.beanCounter().getTotalAbsoluteValueAllCurrencies(mob)>(((Integer)entry.parms()[0]).intValue())))
							return false;
					}
					else
					{
						if((entry.parms().length>0)
						&&(item!=null)&&(item.baseGoldValue()>(((Integer)entry.parms()[0]).intValue())))
							return false;
					}
					break;
				case _VALUE: // -value
					if(E instanceof MOB)
					{
						if((entry.parms().length>0)
						&&(CMLib.beanCounter().getTotalAbsoluteValueAllCurrencies(mob)<(((Integer)entry.parms()[0]).intValue())))
							return false;
					}
					else
					{
						if((entry.parms().length>0)
						&&(item!=null)&&(item.baseGoldValue()<(((Integer)entry.parms()[0]).intValue())))
							return false;
					}
					break;
				case _AREA: // -area
					{
						boolean found=false;
						if(room!=null)
						{
							for(final Object o : entry.parms())
							{
								if(room.getArea().Name().equalsIgnoreCase((String)o))
								{
									found = true;
									break;
								}
							}
						}
						if(!found)
							return false;
					}
					break;
				case AREA: // +area
					{
						if(room!=null)
						{
							for(final Object o : entry.parms())
							{
								if(room.getArea().Name().equalsIgnoreCase((String)o))
									return false;
							}
						}
						break;
					}
				case _HOME: // -home
					{
						boolean found=false;
						final Area A=CMLib.map().getStartArea(E);
						if(A!=null)
						{
							for(final Object o : entry.parms())
							{
								if(A.Name().equalsIgnoreCase((String)o))
								{
									found = true;
									break;
								}
							}
						}
						if(!found)
							return false;
					}
					break;
				case HOME: // +home
					{
						final Area A=CMLib.map().getStartArea(E);
						if(A!=null)
						{
							for(final Object o : entry.parms())
							{
								if(A.Name().equalsIgnoreCase((String)o))
									return false;
							}
						}
					}
					break;
				case ITEM: // +item
					{
						for(final Object o : entry.parms())
						{
							if(mob.findItem((String)o)!=null)
								return false;
						}
					}
					break;
				case _ITEM: // -item
					{
						boolean found=false;
						for(final Object o : entry.parms())
						{
							if(mob.findItem((String)o)!=null)
							{
								found = true;
								break;
							}
						}
						if(!found)
							return false;
					}
					break;
				case WORN: // +worn
					{
						if(E instanceof MOB)
						{
							for(final Object o : entry.parms())
							{
								Item I = mob.findItem((String)o);
								if((I!=null)&&(!I.amWearingAt(Wearable.IN_INVENTORY)))
									return false;
							}
						}
						else
						if(E instanceof Item)
						{
							if(((Item)E).amWearingAt(Wearable.IN_INVENTORY))
								return false;
						}
					}
					break;
				case _WORN: // -worn
					if(E instanceof MOB)
					{
						boolean found=false;
						for(final Object o : entry.parms())
						{
							final Item I=mob.findItem((String)o);
							if((I!=null)&&(!I.amWearingAt(Wearable.IN_INVENTORY)))
							{
								found = true;
								break;
							}
						}
						if(!found)
							return false;
					}
					else
					if(E instanceof Item)
					{
						if(((Item)E).amWearingAt(Wearable.IN_INVENTORY))
							return false;
					}
					break;
				case ALIGNMENT: // +alignment
					if(CMParms.contains(entry.parms(),CMLib.flags().getAlignmentName(mob)))
						return false;
					break;
				case GENDER: // +gender
					base=getBaseCharStats(base,mob);
					if(CMParms.contains(entry.parms(),actual?(""+((char)base.getStat(CharStats.STAT_GENDER))):(""+Character.toUpperCase(mob.charStats().genderName().charAt(0)))))
						return false;
					break;
				case LVLGR: // +lvlgr
					if((entry.parms().length>0)
					&&(P!=null)
					&&((actual?P.basePhyStats().level():P.phyStats().level())>((Integer)entry.parms()[0]).intValue()))
						return false;
					break;
				case LVLGE: // +lvlge
					if((entry.parms().length>0)
					&&(P!=null)
					&&((actual?P.basePhyStats().level():P.phyStats().level())>=((Integer)entry.parms()[0]).intValue()))
						return false;
					break;
				case LVLLT: // +lvlt
					if((entry.parms().length>0)
					&&(P!=null)
					&&((actual?P.basePhyStats().level():P.phyStats().level())<((Integer)entry.parms()[0]).intValue()))
						return false;
					break;
				case LVLLE: // +lvlle
					if((entry.parms().length>0)
					&&(P!=null)
					&&((actual?P.basePhyStats().level():P.phyStats().level())<=((Integer)entry.parms()[0]).intValue()))
						return false;
					break;
				case LVLEQ: // +lvleq
					if((entry.parms().length>0)
					&&(P!=null)
					&&((actual?P.basePhyStats().level():P.phyStats().level())==((Integer)entry.parms()[0]).intValue()))
						return false;
					break;
				case GROUPSIZE: // +groupsize
					if((entry.parms().length>0)
					&&(mob.getGroupMembers(new HashSet<MOB>(1)).size()<(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case _GROUPSIZE: // -groupsize
					if((entry.parms().length>0)
					&&(mob.getGroupMembers(new HashSet<MOB>(1)).size()>(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case _IF: // -if
					{
						boolean oneIsOK = false;
						if(E instanceof PhysicalAgent)
						{
							for(int v=0;v<entry.parms().length-2;v+=3)
							{
								final ScriptingEngine SE = (ScriptingEngine)entry.parms()[v];
								final String[][] EVAL = (String[][])entry.parms()[v+1];
								final Object[] tmp = (Object[])entry.parms()[v+2];
								final MOB M = SE.getMakeMOB(E);
								final Item defaultItem=(E instanceof Item)?(Item)E:null;
								if(SE.eval((PhysicalAgent)E, M, null,M, defaultItem, null, "", tmp, EVAL, 0))
								{
									oneIsOK = true;
									break;
								}
							}
						}
						if(!oneIsOK)
							return false;
						break;
					}
				case IF: // +if
					{
						if(E instanceof PhysicalAgent)
						{
							for(int v=0;v<entry.parms().length-2;v+=3)
							{
								final ScriptingEngine SE = (ScriptingEngine)entry.parms()[v];
								final String[][] EVAL = (String[][])entry.parms()[v+1];
								final Object[] tmp = (Object[])entry.parms()[v+2];
								final MOB M = SE.getMakeMOB(E);
								final Item defaultItem=(E instanceof Item)?(Item)E:null;
								if(E instanceof PhysicalAgent)
								{
									if(SE.eval((PhysicalAgent)E, M, null,M, defaultItem, null, "", tmp, EVAL, 0))
										return true;
								}
							}
						}
						break;
					}
				}
			}
			catch (final NullPointerException n)
			{
			}
		}
		return true;
	}

	@Override
	public boolean maskCheck(final String text, final PlayerLibrary.ThinPlayer E)
	{
		return maskCheck(getPreCompiledMask(text), E);
	}

	@Override
	public boolean maskCheck(final CompiledZapperMask cset, final PlayerLibrary.ThinPlayer E)
	{
		if(E==null)
			return true;
		if((cset==null)||(cset.empty())||(cset.entries().length<1))
			return true;
		getMaskCodes();
		//boolean[] flags=(boolean[])cset.firstElement();
		for(final CompiledZapperMaskEntry entry : cset.entries())
		{
			try
			{
				switch(entry.maskType())
				{
				case SYSOP: // +sysop
					if(CMSecurity.isASysOp(E))
						return true;
					break;
				case _SYSOP: // -sysop
					if(CMSecurity.isASysOp(E))
						return false;
					break;
				case SUBOP: // +subop
					if(CMSecurity.isASysOp(E))
						return true;
					for(final Enumeration<Area> e=CMLib.map().areas();e.hasMoreElements();)
						if(e.nextElement().amISubOp(E.name()))
							return true;
					break;
				case _SUBOP: // -subop
					if(CMSecurity.isASysOp(E))
						return false;
					for(final Enumeration<Area> e=CMLib.map().areas();e.hasMoreElements();)
						if(e.nextElement().amISubOp(E.name()))
							return false;
					break;
				case _CLASS: // -class
					{
						final CharClass C=CMClass.getCharClass(E.charClass());
						if((C==null)||(!CMParms.contains(entry.parms(),C.name())))
							return false;
					}
					break;
				case _BASECLASS: // -baseclass
					{
						final CharClass C=CMClass.getCharClass(E.charClass());
						if((C==null)||(!CMParms.contains(entry.parms(),C.baseClass())))
							return false;
					}
					break;
				case BASECLASS: // +baseclass
					{
						final CharClass C=CMClass.getCharClass(E.charClass());
						if((C!=null)&&(CMParms.contains(entry.parms(),C.baseClass())))
							return false;
					}
					break;
				case _RACE: // -race
					{
						final Race R=CMClass.getRace(E.race());
						if((R==null)||(!CMParms.contains(entry.parms(),R.name())))
							return false;
					}
					break;
				case _LEVEL: // -level
					{
						final int level=E.level();
						boolean found=false;
						for(int v=0;v<entry.parms().length-1;v+=2)
						{
							switch((ZapperKey)entry.parms()[v])
							{
							case LVLGR: // +lvlgr
								if(level>((Integer)entry.parms()[v+1]).intValue())
									found=true;
								break;
							case LVLGE: // +lvlge
								if(level>=((Integer)entry.parms()[v+1]).intValue())
									found=true;
								break;
							case LVLLT: // +lvlt
								if(level<((Integer)entry.parms()[v+1]).intValue())
									found=true;
								break;
							case LVLLE: // +lvlle
								if(level<=((Integer)entry.parms()[v+1]).intValue())
									found=true;
								break;
							case LVLEQ: // +lvleq
								if(level==((Integer)entry.parms()[v+1]).intValue())
									found=true;
								break;
							default:
								break;
							}
						}
						if(!found)
							return false;
					}
					break;
				case _QUESTWIN: // -questwin
					{
						boolean found=false;
						for(final Object o : entry.parms())
						{
							final Quest Q=CMLib.quests().fetchQuest((String)o);
							if((Q!=null)&&(Q.wasWinner(E.name())))
							{
								found = true;
								break;
							}
						}
						if(!found)
							return false;
					}
					break;
				case QUESTWIN: // +questwin
					{
						for(final Object o : entry.parms())
						{
							final Quest Q=CMLib.quests().fetchQuest((String)o);
							if((Q!=null)&&(Q.wasWinner(E.name())))
								return false;
						}
					}
					break;
				case _NAME: // -names
					{
						boolean found=false;
						final String name=E.name();
						for(final Object o : entry.parms())
						{
							if(name.equalsIgnoreCase((String)o))
							{
								found = true;
								break;
							}
						}
						if(!found)
							return false;
					}
					break;
				case _NPC: // -npc
					break; // always true
				case _RACECAT: // -racecat
					{
						final Race R=CMClass.getRace(E.race());
						if((R==null)||(!CMParms.contains(entry.parms(),R.racialCategory())))
							return false;
					}
					break;
				case RACE: // +race
					{
						final Race R=CMClass.getRace(E.race());
						if((R!=null)&&(CMParms.contains(entry.parms(),R.name())))
							return false;
					}
					break;
				case RACECAT: // +racecat
					{
						final Race R=CMClass.getRace(E.race());
						if((R!=null)&&(CMParms.contains(entry.parms(),R.racialCategory())))
							return false;
					}
					break;
				case _JAVACLASS: // -JavaClass
					{
						boolean found=false;
						for(final Object o : entry.parms())
						{
							if("StdMOB".equalsIgnoreCase((String)o))
							{
								found = true;
								break;
							}
						}
						if(!found)
							return false;
					}
					break;
				case JAVACLASS: // +JavaClass
					for(final Object o : entry.parms())
					{
						if("StdMOB".equalsIgnoreCase((String)o))
						{
							return false;
						}
					}
					break;
				case NAME: // +name
					{
						final String name=E.name();
						for(final Object o : entry.parms())
						{
							if(name.equalsIgnoreCase((String)o))
							{
								return false;
							}
						}
					}
					break;
				case _ANYCLASS: // -anyclass
					{
						boolean found=false;
						final CharClass C=CMClass.getCharClass(E.charClass());
						if(C!=null)
						{
							for(final Object o : entry.parms())
							{
								if(C.name().equalsIgnoreCase((String)o))
								{
									found = true;
									break;
								}
							}
						}
						if(!found)
							return false;
					}
					break;
				case ANYCLASS: // +anyclass
					{
						final CharClass C=CMClass.getCharClass(E.charClass());
						if(C!=null)
						{
							for(final Object o : entry.parms())
							{
								if(C.name().equalsIgnoreCase((String)o))
								{
									return false;
								}
							}
						}
					}
					break;
				case _ALIGNMENT: // -alignment
				case _GENDER: // -gender
				case _CLASSLEVEL: // -classlevel
				case _MAXCLASSLEVEL: // -maxclasslevel
				case ANYCLASSLEVEL: // +anyclasslevel
				case _ANYCLASSLEVEL: // -anyclasslevel
				case _TATTOO: // -tattoo
				case TATTOO: // +tattoo
				case _MOOD: // -mood
				case MOOD: // +mood
				case _ACCCHIEVE: // -accchieves
				case ACCCHIEVE: // +accchieves
				case _EXPERTISE: // -expertise
				case EXPERTISE: // +expertise
				case _SKILL: // -skill
				case _SKILLFLAG: // -skillflag
				case SKILL: // +skill
				case SKILLFLAG: // +skillflag
				case _SECURITY: // -security
				case SECURITY: // +security
				case _PLAYER: // -player
				case _CLAN: // -clan
				case CLAN: // +clan
				case MATERIAL: // +material
				case _MATERIAL: // -material
				case WORNON: // +wornOn
				case _WORNON: // -wornOn
				case DISPOSITION: // +disposition
				case _DISPOSITION: // -disposition
				case SENSES: // +senses
				case _SENSES: // -senses
				case HOUR: // +HOUR
				case _HOUR: // -HOUR
				case SEASON: // +season
				case _SEASON: // -season
				case WEATHER: // +weather
				case _WEATHER: // -weather
				case MONTH: // +month
				case _MONTH: // -month
				case DAY: // +day
				case _DAY: // -day
				case QUALLVL: // +quallvl
				case _QUALLVL: // -quallvl
				case RESOURCE: // +resource
				case _RESOURCE: // -resource
				case _DEITY: // -deity
				case DEITY: // +deity
				case _EFFECT: // -effects
				case _FACTION: // -faction
				case FACTION: // +faction
				case EFFECT: // +effects
				case ADJSTRENGTH: // +adjstr
				case ADJINTELLIGENCE: // +adjint
				case ADJWISDOM: // +adjwis
				case ADJDEXTERITY: // +adjdex
				case ADJCONSTITUTION: // +adjcon
				case ADJCHARISMA: // +adjcha
				case _ADJSTRENGTH: // -adjstr
				case _ADJINTELLIGENCE: // -adjint
				case _ADJWISDOM: // -adjwis
				case _ADJDEXTERITY: // -adjdex
				case _ADJCONSTITUTION: // -adjcon
				case _ADJCHARISMA: // -adjcha
				case STRENGTH: // +str
				case INTELLIGENCE: // +int
				case WISDOM: // +wis
				case DEXTERITY: // +dex
				case CONSTITUTION: // +con
				case CHARISMA: // +cha
				case _STRENGTH: // -str
				case _INTELLIGENCE: // -int
				case _WISDOM: // -wis
				case _DEXTERITY: // -dex
				case _CONSTITUTION: // -con
				case _CHARISMA: // -cha
				case ABILITY: // +ability
				case _ABILITY: // -ability
				case WEIGHT: // +weight
				case _WEIGHT: // -weight
				case ARMOR: // +armor
				case _ARMOR: // -armor
				case DAMAGE: // +damage
				case _DAMAGE: // -damage
				case ATTACK: // +attack
				case _ATTACK: // -attack
				case VALUE: // +value
				case _VALUE: // -value
				case _AREA: // -area
				case AREA: // +area
				case _HOME: // -home
				case HOME: // +home
				case _ITEM: // -item
				case _WORN: // -worn
				case ITEM: // +item
				case WORN: // +worn
				case ALIGNMENT: // +alignment
				case GENDER: // +gender
				case GROUPSIZE: // +groupsize
				case _GROUPSIZE: // -groupsize
				case _IF: // -if
				case IF: // +if
					return false;
				case LVLGR: // +lvlgr
					if((entry.parms().length>0)&&((E.level())>((Integer)entry.parms()[0]).intValue()))
						return false;
					break;
				case LVLGE: // +lvlge
					if((entry.parms().length>0)&&((E.level())>=((Integer)entry.parms()[0]).intValue()))
						return false;
					break;
				case LVLLT: // +lvlt
					if((entry.parms().length>0)&&((E.level())<((Integer)entry.parms()[0]).intValue()))
						return false;
					break;
				case LVLLE: // +lvlle
					if((entry.parms().length>0)&&((E.level())<=((Integer)entry.parms()[0]).intValue()))
						return false;
					break;
				case LVLEQ: // +lvleq
					if((entry.parms().length>0)&&((E.level())==((Integer)entry.parms()[0]).intValue()))
						return false;
					break;
				case _CHANCE: // -chance
					if((entry.parms().length>0)&&(CMLib.dice().rollPercentage()<(((Integer)entry.parms()[0]).intValue())))
						return false;
					break;
				case CLASS: // +class
				{
					final CharClass C=CMClass.getCharClass(E.charClass());
					if(C!=null)
					if(CMParms.contains(entry.parms(),C.name()))
						return false;
					break;
				}
				}
			}
			catch (final NullPointerException n)
			{
			}
		}
		return true;
	}

	@Override
	public String[] separateMaskStrs(final String newText)
	{
		final String[] strs=new String[2];
		final int maskindex=newText.toUpperCase().indexOf("MASK=");
		if(maskindex>0)
		{
			strs[1]=newText.substring(maskindex+5).trim();
			strs[0]=newText.substring(0,maskindex).trim();
		}
		else
		{
			strs[0]=newText;
			strs[1]="";
		}
		return strs;
	}
}