/
com/planet_ink/coffee_mud/Abilities/
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/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/Areas/interfaces/
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/Exits/interfaces/
com/planet_ink/coffee_mud/Items/Armor/
com/planet_ink/coffee_mud/Items/Basic/
com/planet_ink/coffee_mud/Items/MiscMagic/
com/planet_ink/coffee_mud/Items/Software/
com/planet_ink/coffee_mud/Items/Weapons/
com/planet_ink/coffee_mud/Libraries/interfaces/
com/planet_ink/coffee_mud/Locales/
com/planet_ink/coffee_mud/Locales/interfaces/
com/planet_ink/coffee_mud/MOBS/
com/planet_ink/coffee_mud/MOBS/interfaces/
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/application/
com/planet_ink/coffee_mud/core/smtp/
com/planet_ink/siplet/applet/
lib/
resources/examples/
resources/fakedb/
resources/quests/delivery/
resources/quests/diseased/
resources/quests/drowning/
resources/quests/gobwar/
resources/quests/holidays/
resources/quests/robbed/
resources/quests/smurfocide/
resources/quests/stolen/
resources/quests/templates/
resources/quests/treasurehunt/
resources/quests/vengeance/
web/
web/admin.templates/
web/admin/images/
web/pub.templates/
web/pub/images/mxp/
web/pub/sounds/
package com.planet_ink.coffee_mud.Commands;
import com.planet_ink.coffee_mud.core.interfaces.*;
import com.planet_ink.coffee_mud.core.*;
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.Locales.interfaces.*;
import com.planet_ink.coffee_mud.Libraries.interfaces.*;
import com.planet_ink.coffee_mud.MOBS.interfaces.*;
import com.planet_ink.coffee_mud.Races.interfaces.*;


import java.util.*;
import java.io.ByteArrayInputStream;
import java.io.IOException;


/*
   Copyright 2000-2006 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 BaseGenerics extends StdCommand
{
	private final long maxLength=Long.MAX_VALUE;
	// showNumber should always be a valid number no less than 1
	// showFlag should be a valid number for editing, or -1 for skipping

	protected void genName(MOB mob, Environmental E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Name: '"+E.Name()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter a new one\n\r:","");
		if(newName.length()>0)
			E.setName(newName);
		else
			mob.tell("(no change)");
	}

	protected void genImage(MOB mob, Environmental E, int showNumber, int showFlag)
	throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". MXP file: '"+E.rawImage()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter a new filename\n\r:","");
		if(newName.length()>0)
			E.setImage(newName);
		else
			mob.tell("(no change)");
	}

	protected void genCorpseData(MOB mob, DeadBody E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Corpse Data: '"+E.mobName()+"/"+E.killerName()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
        mob.tell("Dead MOB name: '"+E.mobName()+"'.");
		String newName=mob.session().prompt("Enter a new name\n\r:","");
		if(newName.length()>0) E.setMobName(newName);
		else mob.tell("(no change)");
		mob.tell("Dead MOB Description: '"+E.mobDescription()+"'.");
		newName=mob.session().prompt("Enter a new description\n\r:","");
		if(newName.length()>0) E.setMobDescription(newName);
		else mob.tell("(no change)");
        mob.tell("Is a Players corpse: "+E.playerCorpse());
        newName=mob.session().prompt("Enter a new true/false\n\r:","");
        if((newName.length()>0)&&(newName.equalsIgnoreCase("true")||newName.equalsIgnoreCase("false")))
            E.setPlayerCorpse(Boolean.valueOf(newName.toLowerCase()).booleanValue());
        else mob.tell("(no change)");
        mob.tell("Dead mobs PK flag: "+E.mobPKFlag());
        newName=mob.session().prompt("Enter a new true/false\n\r:","");
        if((newName.length()>0)&&(newName.equalsIgnoreCase("true")||newName.equalsIgnoreCase("false")))
            E.setMobPKFlag(Boolean.valueOf(newName.toLowerCase()).booleanValue());
        else mob.tell("(no change)");
        genCharStats(mob,E.charStats());
		mob.tell("Killers Name: '"+E.killerName()+"'.");
		newName=mob.session().prompt("Enter a new killer\n\r:","");
		if(newName.length()>0) E.setKillerName(newName);
		else mob.tell("(no change)");
        mob.tell("Killer is a player: "+E.killerPlayer());
        newName=mob.session().prompt("Enter a new true/false\n\r:","");
        if((newName.length()>0)&&(newName.equalsIgnoreCase("true")||newName.equalsIgnoreCase("false")))
            E.setKillerPlayer(Boolean.valueOf(newName.toLowerCase()).booleanValue());
        else mob.tell("(no change)");
        mob.tell("Time of death: "+CMLib.time().date2String(E.timeOfDeath()));
        newName=mob.session().prompt("Enter a new value\n\r:","");
        if(newName.length()>0) E.setTimeOfDeath(CMLib.time().string2Millis(newName));
        else mob.tell("(no change)");
        mob.tell("Last message string: "+E.lastMessage());
        newName=mob.session().prompt("Enter a new value\n\r:","");
        if(newName.length()>0) E.setLastMessage(newName);
        else mob.tell("(no change)");
	}

	protected void genAuthor(MOB mob, Area A, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Author: '"+A.getAuthorID()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter a new one\n\r:","");
		if(newName.length()>0)
			A.setAuthorID(newName);
		else
			mob.tell("(no change)");
	}

	protected void genPanelType(MOB mob, ShipComponent.ShipPanel S, int showNumber, int showFlag)
	throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		String componentType=CMStrings.capitalizeAndLower(ShipComponent.ShipPanel.COMPONENT_PANEL_DESC[S.panelType()].toLowerCase());
		mob.tell(showNumber+". Panel Type: '"+componentType+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		boolean continueThis=true;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(continueThis))
		{
		    continueThis=false;
			String newName=mob.session().prompt("Enter a new one (?)\n\r:","");
			if(newName.length()>0)
			{
			    if(newName.equalsIgnoreCase("?"))
			    {
			        mob.tell("Component Types: "+CMParms.toStringList(ShipComponent.ShipPanel.COMPONENT_PANEL_DESC));
			        continueThis=true;
			    }
			    else
			    {
			        int newType=-1;
			        for(int i=0;i<ShipComponent.ShipPanel.COMPONENT_PANEL_DESC.length;i++)
			            if(ShipComponent.ShipPanel.COMPONENT_PANEL_DESC[i].equalsIgnoreCase(newName))
			                newType=i;
			        if(newType<0)
			        {
			            mob.tell("'"+newName+"' is not recognized.  Try '?' for a list.");
			            continueThis=true;
			        }
			        else
			            S.setPanelType(newType);
			    }
			}
			else
				mob.tell("(no change)");
		}
	}

	protected void genCurrency(MOB mob, Area A, int showNumber, int showFlag)
	throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		String currencyName=A.getCurrency().length()==0?"Default":A.getCurrency();
		mob.tell(showNumber+". Currency: '"+currencyName+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter a new one or 'DEFAULT'\n\r:","");
		if(newName.length()>0)
		{
		    if(newName.equalsIgnoreCase("default"))
		        A.setCurrency("");
		    else
		    if((newName.indexOf("=")<0)&&(!CMLib.beanCounter().getAllCurrencies().contains(newName.trim().toUpperCase())))
		    {
		        Vector V=CMLib.beanCounter().getAllCurrencies();
		        mob.tell("'"+newName.trim().toUpperCase()+"' is not a known currency. Existing currencies include: DEFAULT"+CMParms.toStringList(V));
		    }
		    else
		    if(newName.indexOf("=")>=0)
		        A.setCurrency(newName.trim());
		    else
				A.setCurrency(newName.toUpperCase().trim());
		}
		else
			mob.tell("(no change)");
	}

	protected void genTimeClock(MOB mob, Area A, int showNumber, int showFlag)
	throws IOException
	{

		if((showFlag>0)&&(showFlag!=showNumber)) return;
		TimeClock TC=A.getTimeObj();
		StringBuffer report=new StringBuffer("");
		if(TC==CMClass.globalClock())
			report.append("Default -- Can't be changed.");
		else
		{
		    report.append(TC.getHoursInDay()+" hrs-day/");
		    report.append(TC.getDaysInMonth()+" days-mn/");
		    report.append(TC.getMonthsInYear()+" mnths-yr");
		}
		mob.tell(showNumber+". Calendar: '"+report.toString()+"'.");
		if(TC==CMClass.globalClock()) return;
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName="";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(newName.length()==0))
		{
			report=new StringBuffer("\n\rCalendar/Clock settings:\n\r");
		    report.append("1. "+TC.getHoursInDay()+" hours per day\n\r");
		    report.append("2. Dawn Hour: "+TC.getDawnToDusk()[TimeClock.TIME_DAWN]+"\n\r");
		    report.append("3. Day Hour: "+TC.getDawnToDusk()[TimeClock.TIME_DAY]+"\n\r");
		    report.append("4. Dusk Hour: "+TC.getDawnToDusk()[TimeClock.TIME_DUSK]+"\n\r");
		    report.append("5. Night Hour: "+TC.getDawnToDusk()[TimeClock.TIME_NIGHT]+"\n\r");
		    report.append("6. Weekdays: "+CMParms.toStringList(TC.getWeekNames())+"\n\r");
		    report.append("7. Months: "+CMParms.toStringList(TC.getMonthNames())+"\n\r");
		    report.append("8. Year Title(s): "+CMParms.toStringList(TC.getYearNames()));
		    mob.tell(report.toString());
			newName=mob.session().prompt("Enter one to change:","");
			if(newName.length()==0) break;
			int which=CMath.s_int(newName);

			if((which<0)||(which>8))
				mob.tell("Invalid: "+which+"");
			else
			if(which<=5)
			{
			    newName="";
			    String newNum=mob.session().prompt("Enter a new number:","");
			    int val=CMath.s_int(newNum);
			    if(newNum.length()==0)
			        mob.tell("(no change)");
			    else
				switch(which)
			    {
		        case 1:
		            TC.setHoursInDay(val);
		            break;
		        case 2:
		            TC.getDawnToDusk()[TimeClock.TIME_DAWN]=val;
		            break;
		        case 3:
		            if((val>=0)&&(TC.getDawnToDusk()[TimeClock.TIME_DAWN]>=val))
                        mob.tell("That value is before the dawn!");
		            else
			            TC.getDawnToDusk()[TimeClock.TIME_DAY]=val;
		            break;
		        case 4:
		            if((val>=0)&&(TC.getDawnToDusk()[TimeClock.TIME_DAWN]>=val))
                        mob.tell("That value is before the dawn!");
		            else
		            if((val>=0)&&(TC.getDawnToDusk()[TimeClock.TIME_DAY]>=val))
                        mob.tell("That value is before the day!");
		            else
			            TC.getDawnToDusk()[TimeClock.TIME_DUSK]=val;
		            break;
		        case 5:
		            if((val>=0)&&(TC.getDawnToDusk()[TimeClock.TIME_DAWN]>=val))
                        mob.tell("That value is before the dawn!");
		            else
		            if((val>=0)&&(TC.getDawnToDusk()[TimeClock.TIME_DAY]>=val))
                        mob.tell("That value is before the day!");
		            else
		            if((val>=0)&&(TC.getDawnToDusk()[TimeClock.TIME_DUSK]>=val))
                        mob.tell("That value is before the dusk!");
		            else
			            TC.getDawnToDusk()[TimeClock.TIME_NIGHT]=val;
		            break;
			    }
			}
			else
			{
			    newName="";
			    String newNum=mob.session().prompt("Enter a new list (comma delimited)\n\r:","");
			    if(newNum.length()==0)
			        mob.tell("(no change)");
			    else
			    switch(which)
			    {
		        case 6:
		            TC.setDaysInWeek(CMParms.toStringArray(CMParms.parseCommas(newNum,true)));
		            break;
		        case 7:
		            TC.setMonthsInYear(CMParms.toStringArray(CMParms.parseCommas(newNum,true)));
		            break;
		        case 8:
		            TC.setYearNames(CMParms.toStringArray(CMParms.parseCommas(newNum,true)));
		            break;
			    }
			}
		}
		TC.save();
	}

	protected void genClan(MOB mob, MOB E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag<=0)||(showFlag==showNumber))
		{
			mob.tell(showNumber+". Clan (ID): '"+E.getClanID()+"'.");
			if((showFlag==showNumber)||(showFlag<=-999))
			{
				String newName=mob.session().prompt("Enter a new one (null)\n\r:","");
				if(newName.equalsIgnoreCase("null"))
					E.setClanID("");
				else
				if(newName.length()>0)
				{
					E.setClanID(newName);
					E.setClanRole(Clan.POS_MEMBER);
				}
				else
					mob.tell("(no change)");
			}
		}
		if(((showFlag<=0)||(showFlag==showNumber))
		   &&(!E.isMonster())
		   &&(E.getClanID().length()>0)
		   &&(CMLib.clans().getClan(E.getClanID())!=null))
		{

			Clan C=CMLib.clans().getClan(E.getClanID());
			mob.tell(showNumber+". Clan (Role): '"+CMLib.clans().getRoleName(C.getGovernment(),E.getClanRole(),true,false)+"'.");
			if((showFlag==showNumber)||(showFlag<=-999))
			{
				String newName=mob.session().prompt("Enter a new one\n\r:","");
				if(newName.length()>0)
				{
					int newRole=-1;
					for(int i=0;i<Clan.ROL_DESCS[C.getGovernment()].length;i++)
						if(newName.equalsIgnoreCase(Clan.ROL_DESCS[C.getGovernment()][i]))
						{
							newRole=(int)CMath.pow(2,i-1);
							break;
						}
					if(newRole<0)
						mob.tell("That role is invalid. Try: "+CMParms.toStringList(Clan.ROL_DESCS[C.getGovernment()]));
					else
						E.setClanRole(newRole);
				}
				else
					mob.tell("(no change)");
			}
		}
	}

	protected void genArchivePath(MOB mob, Area E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Archive file name: '"+E.getArchivePath()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter a new one (null=default)\n\r:","");
		if(newName.equalsIgnoreCase("null"))
			E.setArchivePath("");
		else
		if(newName.length()>0)
			E.setArchivePath(newName);
		else
			mob.tell("(no change)");
	}

	public Room changeRoomType(Room R, Room newRoom)
	{
		if((R==null)||(newRoom==null)) return R;
		synchronized(("SYNC"+R.roomID()).intern())
		{
			R=CMLib.map().getRoom(R);
			Room oldR=R;
			R=newRoom;
	        Vector oldBehavsNEffects=new Vector();
			for(int a=oldR.numEffects()-1;a>=0;a--)
			{
				Ability A=oldR.fetchEffect(a);
				if(A!=null)
				{
	                if(!A.canBeUninvoked())
	                {
	                    oldBehavsNEffects.addElement(A);
	                    oldR.delEffect(A);
	                }
	                else
	    				A.unInvoke();
				}
			}
	        for(int b=0;b<oldR.numBehaviors();b++)
	        {
	            Behavior B=oldR.fetchBehavior(b);
	            if(B!=null)
	                oldBehavsNEffects.addElement(B);
	        }
			CMLib.threads().deleteTick(oldR,-1);
			R.setRoomID(oldR.roomID());
			Area A=oldR.getArea();
			if(A!=null) A.delProperRoom(oldR);
			R.setArea(A);
			for(int d=0;d<R.rawDoors().length;d++)
				R.rawDoors()[d]=oldR.rawDoors()[d];
			for(int d=0;d<R.rawExits().length;d++)
				R.rawExits()[d]=oldR.rawExits()[d];
			R.setDisplayText(oldR.displayText());
			R.setDescription(oldR.description());
            if(R.image().equalsIgnoreCase(CMProps.getDefaultMXPImage(oldR))) R.setImage(null);
			if((R instanceof GridLocale)&&(oldR instanceof GridLocale))
			{
				((GridLocale)R).setXGridSize(((GridLocale)oldR).xGridSize());
				((GridLocale)R).setYGridSize(((GridLocale)oldR).yGridSize());
				((GridLocale)R).clearGrid(null);
			}
			Vector allmobs=new Vector();
			int skip=0;
			while(oldR.numInhabitants()>(skip))
			{
				MOB M=oldR.fetchInhabitant(skip);
				if(M.savable())
				{
					if(!allmobs.contains(M))
						allmobs.addElement(M);
					oldR.delInhabitant(M);
				}
				else
				if(oldR!=R)
				{
					oldR.delInhabitant(M);
					R.bringMobHere(M,true);
				}
				else
					skip++;
			}
			Vector allitems=new Vector();
			while(oldR.numItems()>0)
			{
				Item I=oldR.fetchItem(0);
				if(!allitems.contains(I))
					allitems.addElement(I);
				oldR.delItem(I);
			}
	
			for(int i=0;i<allitems.size();i++)
			{
				Item I=(Item)allitems.elementAt(i);
				if(!R.isContent(I))
				{
					if(I.subjectToWearAndTear())
						I.setUsesRemaining(100);
					I.recoverEnvStats();
					R.addItem(I);
					R.recoverRoomStats();
				}
			}
			for(int m=0;m<allmobs.size();m++)
			{
				MOB M=(MOB)allmobs.elementAt(m);
				if(!R.isInhabitant(M))
				{
					MOB M2=(MOB)M.copyOf();
					M2.setStartRoom(R);
					M2.setLocation(R);
	                long rejuv=Tickable.TICKS_PER_RLMIN+Tickable.TICKS_PER_RLMIN+(Tickable.TICKS_PER_RLMIN/2);
	                if(rejuv>(Tickable.TICKS_PER_RLMIN*20)) rejuv=(Tickable.TICKS_PER_RLMIN*20);
					M2.envStats().setRejuv((int)rejuv);
					M2.recoverCharStats();
					M2.recoverEnvStats();
					M2.recoverMaxState();
					M2.resetToMaxState();
					M2.bringToLife(R,true);
					R.recoverRoomStats();
					M.destroy();
				}
			}
	
			try
			{
				for(Enumeration r=CMLib.map().rooms();r.hasMoreElements();)
				{
					Room R2=(Room)r.nextElement();
					for(int d=0;d<R2.rawDoors().length;d++)
						if(R2.rawDoors()[d]==oldR)
						{
							R2.rawDoors()[d]=R;
							if(R2 instanceof GridLocale)
								((GridLocale)R2).buildGrid();
						}
				}
		    }catch(NoSuchElementException e){}
		    try
		    {
				for(Enumeration e=CMLib.map().players();e.hasMoreElements();)
				{
					MOB M=(MOB)e.nextElement();
					if(M.getStartRoom()==oldR)
						M.setStartRoom(R);
					else
					if(M.location()==oldR)
						M.setLocation(R);
				}
		    }catch(NoSuchElementException e){}
			R.getArea().fillInAreaRoom(R);
	        for(int i=0;i<oldBehavsNEffects.size();i++)
	        {
	            if(oldBehavsNEffects.elementAt(i) instanceof Behavior)
	                R.addBehavior((Behavior)oldBehavsNEffects.elementAt(i));
	            else
	                R.addNonUninvokableEffect((Ability)oldBehavsNEffects.elementAt(i));
	        }
			CMLib.database().DBUpdateRoom(R);
			CMLib.database().DBUpdateMOBs(R);
			CMLib.database().DBUpdateItems(R);
	        oldR.destroy();
	        R.getArea().addProperRoom(R); // necessary because of the destroy
			R.setImage(R.rawImage());
			R.startItemRejuv();
		}
		return R;
	}

	Room genRoomType(MOB mob, Room R, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return R;
		mob.tell(showNumber+". Type: '"+CMClass.classID(R)+"'");
		if((showFlag!=showNumber)&&(showFlag>-999)) return R;
		String newName="";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(newName.length()==0))
		{
			newName=mob.session().prompt("Enter a new one (?)\n\r:","");
			if(newName.trim().equals("?"))
			{
				mob.tell(CMLib.lister().reallyList2Cols(CMClass.locales(),-1,null).toString()+"\n\r");
				newName="";
			}
			else
			if(newName.length()>0)
			{
				Room newRoom=CMClass.getLocale(newName);
				if(newRoom==null)
					mob.tell("'"+newName+"' does not exist. No Change.");
				else
				if(mob.session().confirm("This will change the room type of room "+R.roomID()+". It will automatically save any mobs and items in this room permanently.  Are you absolutely sure (y/N)?","N"))
					R=changeRoomType(R,newRoom);
				R.recoverRoomStats();
			}
			else
			{
				mob.tell("(no change)");
				break;
			}
		}
		return R;
	}

	protected void genDescription(MOB mob, Environmental E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Description: '"+E.description()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter a new one (null = empty)\n\r:","");
		if(newName.trim().equalsIgnoreCase("null"))
			E.setDescription("");
		else
		if(newName.length()>0)
			E.setDescription(newName);
		else
			mob.tell("(no change)");
	}

	protected void genNotes(MOB mob, MOB E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Private notes: '"+((E.playerStats()!=null)?E.playerStats().notes():"")+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter something new\n\r:","");
		if((newName.length()>0)&&(E.playerStats()!=null))
			E.playerStats().setNotes(newName);
		else
			mob.tell("(no change)");
	}

	protected void genPassword(MOB mob, MOB E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Password: ********.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter a new one to reset\n\r:","");
		if((newName.length()>0)&&(E.playerStats()!=null))
		{
			E.playerStats().setPassword(newName);
			CMLib.database().DBUpdatePassword(E);
		}
		else
			mob.tell("(no change)");
	}

	protected void genEmail(MOB mob, MOB E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		if(E.playerStats()!=null)
			mob.tell(showNumber+". Email: "+E.playerStats().getEmail());
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter a new one\n\r:","");
		if((newName.length()>0)&&(E.playerStats()!=null))
			E.playerStats().setEmail(newName);
		else
			mob.tell("(no change)");
	}

	protected void genDisplayText(MOB mob, Environmental E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Display: '"+E.displayText()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=null;
		if(E instanceof Item)
			newName=mob.session().prompt("Enter something new (null == blended)\n\r:","");
		else
		if(E instanceof Exit)
			newName=mob.session().prompt("Enter something new (null == see-through)\n\r:","");
		else
			newName=mob.session().prompt("Enter something new (null = empty)\n\r:","");
		if(newName.length()>0)
		{
			if(newName.trim().equalsIgnoreCase("null"))
				newName="";
			E.setDisplayText(newName);
		}
		else
			mob.tell("(no change)");
		if((E instanceof Item)&&(E.displayText().length()==0))
			mob.tell("(blended)");
	}
	protected void genClosedText(MOB mob, Exit E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		if(E instanceof Item)
			mob.tell(showNumber+". Exit Closed Text: '"+E.closedText()+"'.");
		else
			mob.tell(showNumber+". Closed Text: '"+E.closedText()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter something new (null=blank)\n\r:","");
		if(newName.equals("null"))
			E.setExitParams(E.doorName(),E.closeWord(),E.openWord(),"");
		else
		if(newName.length()>0)
			E.setExitParams(E.doorName(),E.closeWord(),E.openWord(),newName);
		else
			mob.tell("(no change)");
	}
	protected void genDoorName(MOB mob, Exit E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		if(E instanceof Item)
			mob.tell(showNumber+". Exit Direction: '"+E.doorName()+"'.");
		else
			mob.tell(showNumber+". Door Name: '"+E.doorName()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter something new\n\r:","");
		if(newName.length()>0)
			E.setExitParams(newName,E.closeWord(),E.openWord(),E.closedText());
		else
			mob.tell("(no change)");
	}

	protected void genBurnout(MOB mob, Light E, int showNumber, int showFlag)
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Is destroyed after burnout: '"+E.destroyedWhenBurnedOut()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		E.setDestroyedWhenBurntOut(!E.destroyedWhenBurnedOut());
	}

	protected void genOpenWord(MOB mob, Exit E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Open Word: '"+E.openWord()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter something new\n\r:","");
		if(newName.length()>0)
			E.setExitParams(E.doorName(),E.closeWord(),newName,E.closedText());
		else
			mob.tell("(no change)");
	}

	protected void genSubOps(MOB mob, Area A, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		String newName="Q";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(newName.length()>0))
		{
			mob.tell(showNumber+". Area staff names: "+A.getSubOpList());
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			newName=mob.session().prompt("Enter a name to add or remove\n\r:","");
			if(newName.length()>0)
			{
				if(A.amISubOp(newName))
				{
					A.delSubOp(newName);
					mob.tell("Staff removed.");
				}
				else
				if(CMLib.database().DBUserSearch(null,newName))
				{
					A.addSubOp(newName);
					mob.tell("Staff added.");
				}
				else
					mob.tell("'"+newName+"' is not recognized as a valid user name.");
			}
		}
	}

    protected void genParentAreas(MOB mob, Area A, int showNumber, int showFlag)
            throws IOException
    {
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		String newArea="Q";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(newArea.length()>0))
		{
		    mob.tell(showNumber+". Parent Areas: "+A.getParentsList());
		    if((showFlag!=showNumber)&&(showFlag>-999)) return;
		    newArea=mob.session().prompt("Enter an area name to add or remove\n\r:","");
		    if(newArea.length()>0)
		    {
		        Area lookedUp=CMLib.map().getArea(newArea);
		        if(lookedUp!=null)
		        {
		            if (lookedUp.isChild(A))
					{
						// this new area is already a parent to A,
						// they must want it removed
						A.removeParent(lookedUp);
						lookedUp.removeChild(A);
						mob.tell("Enter an area name to add or remove\n\r:");
		            }
		            else
					{
		                if(A.canParent(lookedUp))
						{
		                    A.addParent(lookedUp);
		                    lookedUp.addChild(A);
		                    mob.tell("Area '"+lookedUp.Name()+"' added.");
		                }
		                else
		                {
		                    mob.tell("Area '"+lookedUp.Name()+"" +"' cannot be added because this would create a circular reference.");
		                }
		            }
		        }
		        else
		            mob.tell("'"+newArea+"' is not recognized as a valid area name.");
		    }
		}
    }

    protected void genChildAreas(MOB mob, Area A, int showNumber, int showFlag)
            throws IOException
    {
        if((showFlag>0)&&(showFlag!=showNumber)) return;
        String newArea="Q";
        while((mob.session()!=null)&&(!mob.session().killFlag())&&(newArea.length()>0))
        {
            mob.tell(showNumber+". Area Children: "+A.getChildrenList());
            if((showFlag!=showNumber)&&(showFlag>-999)) return;
            newArea=mob.session().prompt("Enter an area name to add or remove\n\r:","");
            if(newArea.length()>0)
            {
                Area lookedUp=CMLib.map().getArea(newArea);
                if(lookedUp!=null)
                {
                    if (lookedUp.isParent(A))
					{
                        // this area is already a child to A, they must want it removed
                        A.removeChild(lookedUp);
                        lookedUp.removeParent(A);
                        mob.tell("Enter an area name to add or remove\n\r:");
                    }
                    else
					{
                        if(A.canChild(lookedUp))
						{
                            A.addChild(lookedUp);
                            lookedUp.addParent(A);
                            mob.tell("Area '"+ lookedUp.Name()+"' added.");
                        }
                        else
                        {
                            mob.tell("Area '"+ lookedUp.Name()+"" +"' cannot be added because this would create a circular reference.");
                        }
                    }
                }
                else
                    mob.tell("'"+newArea+"' is not recognized as a valid area name.");
            }
        }
    }

	protected void genCloseWord(MOB mob, Exit E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Close Word: '"+E.closeWord()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter something new\n\r:","");
		if(newName.length()>0)
			E.setExitParams(E.doorName(),newName,E.openWord(),E.closedText());
		else
			mob.tell("(no change)");
	}

	protected void genExitMisc(MOB mob, Exit E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		if(E.hasALock())
		{
			E.setReadable(false);
			mob.tell(showNumber+". Assigned Key Item: '"+E.keyName()+"'.");
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			String newName=mob.session().prompt("Enter something new (null=blank)\n\r:","");
			if(newName.equalsIgnoreCase("null"))
				E.setKeyName("");
			else
			if(newName.length()>0)
				E.setKeyName(newName);
			else
				mob.tell("(no change)");
		}
		else
		{
			if((showFlag!=showNumber)&&(showFlag>-999))
			{
				if(!E.isReadable())
					mob.tell(showNumber+". Door not is readable.");
				else
					mob.tell(showNumber+". Door is readable: "+E.readableText());
				return;
			}
			else
			if(genGenericPrompt(mob,"Is this door ",E.isReadable()))
			{
				E.setReadable(true);
				mob.tell("\n\rText: '"+E.readableText()+"'.");
				String newName=mob.session().prompt("Enter something new (null=blank)\n\r:","");
				if(newName.equalsIgnoreCase("null"))
					E.setReadableText("");
				else
				if(newName.length()>0)
					E.setReadableText(newName);
				else
					mob.tell("(no change)");
			}
			else
				E.setReadable(false);
		}
	}

	protected void genReadable1(MOB mob, Item E, int showNumber, int showFlag)
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;

		if((E instanceof Wand)
		 ||(E instanceof SpellHolder)
		 ||(E instanceof Light)
		 ||(E instanceof Container)
		 ||(E instanceof Ammunition)
		 ||((E instanceof ClanItem)
			 &&((((ClanItem)E).ciType()==ClanItem.CI_GATHERITEM)
				 ||(((ClanItem)E).ciType()==ClanItem.CI_CRAFTITEM)
				 ||(((ClanItem)E).ciType()==ClanItem.CI_SPECIALAPRON)))
		 ||(E instanceof Key))
			CMLib.flags().setReadable(E,false);
		else
		if((CMClass.classID(E).endsWith("Readable"))
		||(E instanceof Recipe)
		||(E instanceof com.planet_ink.coffee_mud.Items.interfaces.Map))
			CMLib.flags().setReadable(E,true);
		else
		if((showFlag!=showNumber)&&(showFlag>-999))
			mob.tell(showNumber+". Item is readable: "+CMLib.flags().isReadable(E)+"");
		else
			CMLib.flags().setReadable(E,genGenericPrompt(mob,showNumber+". Is this item readable",CMLib.flags().isReadable(E)));
	}

	protected void genReadable2(MOB mob, Item E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;

		if((CMLib.flags().isReadable(E))
		 ||(E instanceof SpellHolder)
		 ||(E instanceof Ammunition)
		 ||(E instanceof Recipe)
		 ||(E instanceof Exit)
		 ||(E instanceof Wand)
		 ||(E instanceof ClanItem)
		 ||(E instanceof Light)
		 ||(E instanceof Key))
		{
			boolean ok=false;
			while((mob.session()!=null)&&(!mob.session().killFlag())&&(!ok))
			{
				if(CMClass.classID(E).endsWith("SuperPill"))
				{
					mob.tell(showNumber+". Assigned Spell or Parameters: '"+E.readableText()+"'.");
					ok=true;
				}
				else
				if(E instanceof SpellHolder)
					mob.tell(showNumber+". Assigned Spell(s) ( ';' delimited)\n: '"+E.readableText()+"'.");
				else
				if(E instanceof Ammunition)
				{
					mob.tell(showNumber+". Ammunition type: '"+E.readableText()+"'.");
					ok=true;
				}
				else
				if(E instanceof Exit)
				{
					mob.tell(showNumber+". Assigned Room IDs: '"+E.readableText()+"'.");
					ok=true;
				}
				else
				if(E instanceof Wand)
					mob.tell(showNumber+". Assigned Spell Name: '"+E.readableText()+"'.");
				else
				if(E instanceof Key)
				{
					mob.tell(showNumber+". Assigned Key Code: '"+E.readableText()+"'.");
					ok=true;
				}
				else
				if(E instanceof com.planet_ink.coffee_mud.Items.interfaces.Map)
				{
					mob.tell(showNumber+". Assigned Map Area(s): '"+E.readableText()+"'.");
					ok=true;
				}
				else
				if(E instanceof Light)
				{
					mob.tell(showNumber+". Light duration (before burn out): '"+CMath.s_int(E.readableText())+"'.");
					ok=true;
				}
				else
				{
					mob.tell(showNumber+". Assigned Read Text: '"+E.readableText()+"'.");
					ok=true;
				}

				if((showFlag!=showNumber)&&(showFlag>-999)) return;
				String newName=null;

				if((E instanceof Wand)
				||((E instanceof SpellHolder)&&(!(CMClass.classID(E).endsWith("SuperPill")))))
				{
					newName=mob.session().prompt("Enter something new (?)\n\r:","");
					if(newName.length()==0)
						ok=true;
					else
					{
						if(newName.equalsIgnoreCase("?"))
							mob.tell(CMLib.lister().reallyList(CMClass.abilities(),-1).toString());
						else
						if(E instanceof Wand)
						{
							if(CMClass.getAbility(newName)!=null)
								ok=true;
							else
								mob.tell("'"+newName+"' is not recognized.  Try '?'.");
						}
						else
						if(E instanceof SpellHolder)
						{
							String oldName=newName;
							if(!newName.endsWith(";")) newName+=";";
							int x=newName.indexOf(";");
							while(x>=0)
							{
								String spellName=newName.substring(0,x).trim();
								if(CMClass.getAbility(spellName)!=null)
									ok=true;
								else
								{
									mob.tell("'"+spellName+"' is not recognized.  Try '?'.");
									break;
								}
								newName=newName.substring(x+1).trim();
								x=newName.indexOf(";");
							}
							newName=oldName;
						}
					}
				}
				else
					newName=mob.session().prompt("Enter something new (null=blank)\n\r:","");

				if(ok)
				{
					if(newName.equalsIgnoreCase("null"))
						E.setReadableText("");
					else
					if(newName.length()>0)
						E.setReadableText(newName);
					else
						mob.tell("(no change)");
				}
			}
		}
		else
		if(E instanceof Drink)
		{
			mob.session().println(showNumber+". Current liquid type: "+RawMaterial.RESOURCE_DESCS[((Drink)E).liquidType()&RawMaterial.RESOURCE_MASK]);
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			boolean q=false;
			while((mob.session()!=null)&&(!mob.session().killFlag())&&(!q))
			{
				String newType=mob.session().prompt("Enter a new type (?)\n\r:",RawMaterial.RESOURCE_DESCS[((Drink)E).liquidType()&RawMaterial.RESOURCE_MASK]);
				if(newType.equals("?"))
				{
					StringBuffer say=new StringBuffer("");
					for(int i=0;i<RawMaterial.RESOURCE_DESCS.length-1;i++)
						if((RawMaterial.RESOURCE_DATA[i][0]&RawMaterial.MATERIAL_MASK)==RawMaterial.MATERIAL_LIQUID)
							say.append(RawMaterial.RESOURCE_DESCS[i]+", ");
					mob.tell(say.toString().substring(0,say.length()-2));
					q=false;
				}
				else
				{
					q=true;
					int newValue=-1;
					for(int i=0;i<RawMaterial.RESOURCE_DESCS.length-1;i++)
						if((RawMaterial.RESOURCE_DATA[i][0]&RawMaterial.MATERIAL_MASK)==RawMaterial.MATERIAL_LIQUID)
							if(newType.equalsIgnoreCase(RawMaterial.RESOURCE_DESCS[i]))
								newValue=RawMaterial.RESOURCE_DATA[i][0];
					if(newValue>=0)
						((Drink)E).setLiquidType(newValue);
					else
						mob.tell("(no change)");
				}
			}
		}
	}

	protected void genRecipe(MOB mob, Recipe E, int showNumber, int showFlag)
	throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		String prompt="Recipe Data ";
		mob.tell(showNumber+". "+prompt+": "+E.getCommonSkillID()+".");
		mob.tell(CMStrings.padRight(" ",(""+showNumber).length()+2+prompt.length())+": "+CMStrings.replaceAll(E.getRecipeCodeLine(),"\t",",")+".");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		while(!mob.session().killFlag())
		{
			String newName=mob.session().prompt("Enter new skill id (?)\n\r:","");
			if(newName.equalsIgnoreCase("?"))
			{
			    StringBuffer str=new StringBuffer("");
			    Ability A=null;
				for(Enumeration e=CMClass.abilities();e.hasMoreElements();)
				{
				 	A=(Ability)e.nextElement();
				 	if(((A.classificationCode()&Ability.ALL_ACODES)==Ability.ACODE_COMMON_SKILL)
				 	&&((A.classificationCode()&Ability.ALL_DOMAINS)==Ability.DOMAIN_CRAFTINGSKILL))
				 	    str.append(A.ID()+"\n\r");
				}
				mob.tell("\n\rCommon Skills:\n\r"+str.toString()+"\n\r");
			}
			else
			if((newName.length()>0)
			&&(CMClass.getAbility(newName)!=null)
			&&((CMClass.getAbility(newName).classificationCode()&Ability.ALL_ACODES)==Ability.ACODE_COMMON_SKILL))
			{
			    E.setCommonSkillID(CMClass.getAbility(newName).ID());
			    break;
			}
			else
			if(newName.length()>0)
			    mob.tell("'"+newName+"' is not a valid common skill.  Try ?.");
			else
			{
				mob.tell("(no change)");
				break;
			}
		}
		String newName=mob.session().prompt("Enter new data line\n\r:","");
		if(newName.length()>0)
			E.setRecipeCodeLine(CMStrings.replaceAll(newName,",","\t"));
		else
			mob.tell("(no change)");
	}

	protected void genGettable(MOB mob, Item E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		if(E instanceof Potion)
			((Potion)E).setDrunk(false);

		String c="Q";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!c.equals("\n")))
		{
			mob.session().println(showNumber+". A) Is Gettable   : "+(!CMath.bset(E.baseEnvStats().sensesMask(),EnvStats.SENSE_ITEMNOTGET)));
			mob.session().println("    B) Is Droppable  : "+(!CMath.bset(E.baseEnvStats().sensesMask(),EnvStats.SENSE_ITEMNODROP)));
			mob.session().println("    C) Is Removable  : "+(!CMath.bset(E.baseEnvStats().sensesMask(),EnvStats.SENSE_ITEMNOREMOVE)));
			mob.session().println("    D) Non-Locatable : "+(((E.baseEnvStats().sensesMask()&EnvStats.SENSE_UNLOCATABLE)>0)?"true":"false"));
			if(E instanceof Weapon)
				mob.session().println("    E) Is Two-Handed : "+E.rawLogicalAnd());
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			c=mob.session().choose("Enter one to change, or ENTER when done:","ABCDE\n","\n").toUpperCase();
			switch(Character.toUpperCase(c.charAt(0)))
			{
			case 'A': CMLib.flags().setGettable(E,(CMath.bset(E.baseEnvStats().sensesMask(),EnvStats.SENSE_ITEMNOTGET))); break;
			case 'B': CMLib.flags().setDroppable(E,(CMath.bset(E.baseEnvStats().sensesMask(),EnvStats.SENSE_ITEMNODROP))); break;
			case 'C': CMLib.flags().setRemovable(E,(CMath.bset(E.baseEnvStats().sensesMask(),EnvStats.SENSE_ITEMNOREMOVE))); break;
			case 'D': if((E.baseEnvStats().sensesMask()&EnvStats.SENSE_UNLOCATABLE)>0)
						  E.baseEnvStats().setSensesMask(E.baseEnvStats().sensesMask()-EnvStats.SENSE_UNLOCATABLE);
					  else
						  E.baseEnvStats().setSensesMask(E.baseEnvStats().sensesMask()|EnvStats.SENSE_UNLOCATABLE);
					  break;
			case 'E': if(E instanceof Weapon)
						  E.setRawLogicalAnd(!E.rawLogicalAnd());
					  break;
			}
		}
	}

	protected void toggleDispositionMask(EnvStats E, int mask)
	{
		int current=E.disposition();
		if((current&mask)==0)
			E.setDisposition(current|mask);
		else
			E.setDisposition(current&((int)(EnvStats.ALLMASK-mask)));
	}

	protected void genDisposition(MOB mob, EnvStats E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		int[] disps={EnvStats.IS_INVISIBLE,
					 EnvStats.IS_HIDDEN,
					 EnvStats.IS_NOT_SEEN,
					 EnvStats.IS_BONUS,
					 EnvStats.IS_GLOWING,
					 EnvStats.IS_LIGHTSOURCE,
					 EnvStats.IS_FLYING,
					 EnvStats.IS_CLIMBING,
					 EnvStats.IS_SNEAKING,
					 EnvStats.IS_SWIMMING,
					 EnvStats.IS_EVIL,
					 EnvStats.IS_GOOD};
		String[] briefs={"invisible",
						 "hide",
						 "unseen",
						 "magical",
						 "glowing",
						 "lightsrc",
						 "fly",
						 "climb",
						 "sneak",
						 "swimmer",
						 "evil",
						 "good"};
		if((showFlag!=showNumber)&&(showFlag>-999))
		{
			StringBuffer buf=new StringBuffer(showNumber+". Dispositions: ");
			for(int i=0;i<disps.length;i++)
			{
				int mask=disps[i];
				if((E.disposition()&mask)!=0)
					buf.append(briefs[i]+" ");
			}
			mob.tell(buf.toString());
			return;
		}
		String c="Q";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!c.equals("\n")))
		{
			char letter='A';
			String letters="";
			for(int i=0;i<disps.length;i++)
			{
				int mask=disps[i];
				for(int num=0;num<EnvStats.dispositionsDesc.length;num++)
					if(mask==CMath.pow(2,num))
					{
						mob.session().println("    "+letter+") "+CMStrings.padRight(EnvStats.dispositionsDesc[num],20)+":"+((E.disposition()&mask)!=0));
						letters+=letter;
						break;
					}
				letter++;
			}
			c=mob.session().choose("Enter one to change, or ENTER when done: ",letters+"\n","\n").toUpperCase();
			letter='A';
			for(int i=0;i<disps.length;i++)
			{
				int mask=disps[i];
				if(letter==Character.toUpperCase(c.charAt(0)))
				{
					toggleDispositionMask(E,mask);
					break;
				}
				letter++;
			}
		}
	}

	public boolean genGenericPrompt(MOB mob, String prompt, boolean val)
	{
		try
		{
			prompt=CMStrings.padRight(prompt,35);
			if(val)
				prompt+="(Y/n): ";
			else
				prompt+="(y/N): ";

			return mob.session().confirm(prompt,val?"Y":"N");
		}
		catch(IOException e)
		{
			return val;
		}
	}

	protected void toggleSensesMask(EnvStats E, int mask)
	{
		int current=E.sensesMask();
		if((current&mask)==0)
			E.setSensesMask(current|mask);
		else
			E.setSensesMask(current&((int)(EnvStats.ALLMASK-mask)));
	}

	protected void toggleClimateMask(Area A, int mask)
	{
		int current=A.climateType();
		if((current&mask)==0)
			A.setClimateType(current|mask);
		else
			A.setClimateType(current&((int)(EnvStats.ALLMASK-mask)));
	}



	protected void genClimateType(MOB mob, Area A, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		String c="Q";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!c.equals("\n")))
		{
			mob.session().println(""+showNumber+". Climate:");
			mob.session().println("    R) Wet and Rainy    : "+((A.climateType()&Area.CLIMASK_WET)>0));
			mob.session().println("    H) Excessively hot  : "+((A.climateType()&Area.CLIMASK_HOT)>0));
			mob.session().println("    C) Excessively cold : "+((A.climateType()&Area.CLIMASK_COLD)>0));
			mob.session().println("    W) Very windy       : "+((A.climateType()&Area.CLIMATE_WINDY)>0));
			mob.session().println("    D) Very dry         : "+((A.climateType()&Area.CLIMASK_DRY)>0));
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			c=mob.session().choose("Enter one to change, or ENTER when done: ","RHCWD\n","\n").toUpperCase();
			switch(c.charAt(0))
			{
			case 'C': toggleClimateMask(A,Area.CLIMASK_COLD); break;
			case 'H': toggleClimateMask(A,Area.CLIMASK_HOT); break;
			case 'R': toggleClimateMask(A,Area.CLIMASK_WET); break;
			case 'W': toggleClimateMask(A,Area.CLIMATE_WINDY); break;
			case 'D': toggleClimateMask(A,Area.CLIMASK_DRY); break;
			}
		}
	}

    protected void genCharStats(MOB mob, CharStats E)
    throws IOException
    {
        String c="Q";
        String commandStr="ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()=+-";
        while((mob.session()!=null)&&(!mob.session().killFlag())&&(!c.equals("\n")))
        {
            for(int i=0;i<CharStats.STAT_DESCS.length;i++)
                if(i!=CharStats.STAT_GENDER)
                    mob.session().println("    "+commandStr.charAt(i)+") "+CMStrings.padRight(CharStats.STAT_DESCS[i],20)+":"+((E.getStat(i))));
            c=mob.session().choose("Enter one to change, or ENTER when done: ",commandStr.substring(0,CharStats.STAT_DESCS.length)+"\n","\n").toUpperCase();
            int num=commandStr.indexOf(c);
            if(num>=0)
            {
                String newVal=mob.session().prompt("Enter a new value:  "+CharStats.STAT_DESCS[num]+" ("+E.getStat(num)+"): ","");
                if(((CMath.s_int(newVal)>0)||(newVal.trim().equals("0")))
                &&(num!=CharStats.STAT_GENDER))
                    E.setStat(num,CMath.s_int(newVal));
                else
                    mob.tell("(no change)");
            }
        }
    }
    
    
	protected void genCharStats(MOB mob, MOB E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		if((showFlag!=showNumber)&&(showFlag>-999))
		{
			StringBuffer buf=new StringBuffer(showNumber+". Stats: ");
			for(int i=0;i<CharStats.NUM_BASE_STATS;i++)
				buf.append(CharStats.STAT_ABBR[i]+":"+E.baseCharStats().getStat(i)+" ");
			mob.tell(buf.toString());
			return;
		}
		String c="Q";
		String commandStr="ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()=+-";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!c.equals("\n")))
		{
			for(int i=0;i<CharStats.STAT_DESCS.length;i++)
				if(i!=CharStats.STAT_GENDER)
					mob.session().println("    "+commandStr.charAt(i)+") "+CMStrings.padRight(CharStats.STAT_DESCS[i],20)+":"+((E.baseCharStats().getStat(i))));
			c=mob.session().choose("Enter one to change, or ENTER when done: ",commandStr.substring(0,CharStats.STAT_DESCS.length)+"\n","\n").toUpperCase();
			int num=commandStr.indexOf(c);
			if(num>=0)
			{
				String newVal=mob.session().prompt("Enter a new value:  "+CharStats.STAT_DESCS[num]+" ("+E.baseCharStats().getStat(num)+"): ","");
				if(((CMath.s_int(newVal)>0)||(newVal.trim().equals("0")))
				&&(num!=CharStats.STAT_GENDER))
				{
					E.baseCharStats().setStat(num,CMath.s_int(newVal));
					if((num==CharStats.STAT_AGE)&&(E.playerStats()!=null)&&(E.playerStats().getBirthday()!=null))
					    E.playerStats().getBirthday()[2]=CMClass.globalClock().getYear()-CMath.s_int(newVal);
				}
				else
					mob.tell("(no change)");
			}
		}
	}

	protected void genSensesMask(MOB mob, EnvStats E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		int[] senses={EnvStats.CAN_SEE_DARK,
					  EnvStats.CAN_SEE_HIDDEN,
					  EnvStats.CAN_SEE_INVISIBLE,
					  EnvStats.CAN_SEE_SNEAKERS,
					  EnvStats.CAN_SEE_INFRARED,
					  EnvStats.CAN_SEE_GOOD,
					  EnvStats.CAN_SEE_EVIL,
					  EnvStats.CAN_SEE_BONUS,
					  EnvStats.CAN_NOT_SPEAK,
					  EnvStats.CAN_NOT_HEAR,
					  EnvStats.CAN_NOT_SEE};
		String[] briefs={"darkvision",
						 "hidden",
						 "invisible",
						 "sneakers",
						 "infrared",
						 "good",
						 "evil",
						 "magic",
						 "MUTE",
						 "DEAF",
						 "BLIND"};
		if((showFlag!=showNumber)&&(showFlag>-999))
		{
			StringBuffer buf=new StringBuffer(showNumber+". Senses: ");
			for(int i=0;i<senses.length;i++)
			{
				int mask=senses[i];
				if((E.sensesMask()&mask)!=0)
					buf.append(briefs[i]+" ");
			}
			mob.tell(buf.toString());
			return;
		}
		String c="Q";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!c.equals("\n")))
		{
			char letter='A';
			String letters="";
			for(int i=0;i<senses.length;i++)
			{
				int mask=senses[i];
				for(int num=0;num<EnvStats.sensesDesc.length;num++)
					if(mask==CMath.pow(2,num))
					{
						letters+=letter;
						mob.session().println("    "+letter+") "+CMStrings.padRight(EnvStats.sensesDesc[num],20)+":"+((E.sensesMask()&mask)!=0));
						break;
					}
				letter++;
			}
			c=mob.session().choose("Enter one to change, or ENTER when done: ",letters+"\n","\n").toUpperCase();
			letter='A';
			for(int i=0;i<senses.length;i++)
			{
				int mask=senses[i];
				if(letter==Character.toUpperCase(c.charAt(0)))
				{
					toggleSensesMask(E,mask);
					break;
				}
				letter++;
			}
		}
	}

	protected void genDoorsNLocks(MOB mob, Exit E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		boolean HasDoor=E.hasADoor();
		boolean Open=E.isOpen();
		boolean DefaultsClosed=E.defaultsClosed();
		boolean HasLock=E.hasALock();
		boolean Locked=E.isLocked();
		boolean DefaultsLocked=E.defaultsLocked();
		if((showFlag!=showNumber)&&(showFlag>-999)){
			mob.tell(showNumber+". Has a door: "+E.hasADoor()
					+"\n\r   Has a lock  : "+E.hasALock()
					+"\n\r   Open ticks: "+E.openDelayTicks());
			return;
		}

		if(genGenericPrompt(mob,"Has a door",E.hasADoor()))
		{
			HasDoor=true;
			DefaultsClosed=genGenericPrompt(mob,"Defaults closed",E.defaultsClosed());
			Open=!DefaultsClosed;
			if(genGenericPrompt(mob,"Has a lock",E.hasALock()))
			{
				HasLock=true;
				DefaultsLocked=genGenericPrompt(mob,"Defaults locked",E.defaultsLocked());
				Locked=DefaultsLocked;
			}
			else
			{
				HasLock=false;
				Locked=false;
				DefaultsLocked=false;
			}
			mob.tell("\n\rReset Delay (# ticks): '"+E.openDelayTicks()+"'.");
			int newLevel=CMath.s_int(mob.session().prompt("Enter a new delay\n\r:",""));
			if(newLevel>0)
				E.setOpenDelayTicks(newLevel);
			else
				mob.tell("(no change)");
		}
		else
		{
			HasDoor=false;
			Open=true;
			DefaultsClosed=false;
			HasLock=false;
			Locked=false;
			DefaultsLocked=false;
		}
		E.setDoorsNLocks(HasDoor,Open,DefaultsClosed,HasLock,Locked,DefaultsLocked);
	}

	public String makeContainerTypes(Container E)
	{
		String canContain=", "+Container.CONTAIN_DESCS[0];
		if(E.containTypes()>0)
		{
			canContain="";
			for(int i=0;i<20;i++)
				if(CMath.isSet((int)E.containTypes(),i))
					canContain+=", "+Container.CONTAIN_DESCS[i+1];
		}
		return canContain.substring(2);
	}


	protected void genLidsNLocks(MOB mob, Container E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		if((showFlag!=showNumber)&&(showFlag>-999)){
			mob.tell(showNumber+". Can contain : "+makeContainerTypes(E)
					+"\n\r   Has a lid   : "+E.hasALid()
					+"\n\r   Has a lock  : "+E.hasALock()
					+"\n\r   Key name    : "+E.keyName());
			return;
		}
		String change="NO";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(change.length()>0))
		{
			mob.tell("\n\rCan only contain: "+makeContainerTypes(E));
			change=mob.session().prompt("Enter a type to add/remove (?)\n\r:","");
			if(change.length()==0) break;
			int found=-1;
			if(change.equalsIgnoreCase("?"))
				for(int i=0;i<Container.CONTAIN_DESCS.length;i++)
					mob.tell(Container.CONTAIN_DESCS[i]);
			else
			{
				for(int i=0;i<Container.CONTAIN_DESCS.length;i++)
					if(Container.CONTAIN_DESCS[i].startsWith(change.toUpperCase()))
						found=i;
				if(found<0)
					mob.tell("Unknown type.  Try '?'.");
				else
				if(found==0)
					E.setContainTypes(0);
				else
				if(CMath.isSet((int)E.containTypes(),found-1))
					E.setContainTypes(E.containTypes()-CMath.pow(2,found-1));
				else
					E.setContainTypes(E.containTypes()|CMath.pow(2,found-1));
			}
		}

		if(genGenericPrompt(mob,"Has a lid " ,E.hasALid()))
		{
			E.setLidsNLocks(true,false,E.hasALock(),E.isLocked());
			if(genGenericPrompt(mob,"Has a lock",E.hasALock()))
			{
				E.setLidsNLocks(E.hasALid(),E.isOpen(),true,true);
				mob.tell("\n\rKey code: '"+E.keyName()+"'.");
				String newName=mob.session().prompt("Enter something new\n\r:","");
				if(newName.length()>0)
					E.setKeyName(newName);
				else
					mob.tell("(no change)");
			}
			else
			{
				E.setKeyName("");
				E.setLidsNLocks(E.hasALid(),E.isOpen(),false,false);
			}
		}
		else
		{
			E.setKeyName("");
			E.setLidsNLocks(false,true,false,false);
		}
	}

	protected void genLevel(MOB mob, Environmental E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		if(E.baseEnvStats().level()<0)
			E.baseEnvStats().setLevel(1);
		mob.tell(showNumber+". Level: '"+E.baseEnvStats().level()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		E.baseEnvStats().setLevel(getNumericData(mob,"Enter a new level\n\r:",E.baseEnvStats().level()));
	}

	protected void genRejuv(MOB mob, Environmental E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		if(E instanceof Item)
			mob.tell(showNumber+". Rejuv/Pct: '"+E.baseEnvStats().rejuv()+"' (0=special).");
		else
			mob.tell(showNumber+". Rejuv Ticks: '"+E.baseEnvStats().rejuv()+"' (0=never).");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String rlevel=mob.session().prompt("Enter new amount\n\r:","");
		int newLevel=CMath.s_int(rlevel);
		if((newLevel>0)||(rlevel.trim().equals("0")))
		{
			E.baseEnvStats().setRejuv(newLevel);
			if((E.baseEnvStats().rejuv()==0)&&(E instanceof MOB))
			{
				E.baseEnvStats().setRejuv(Integer.MAX_VALUE);
				mob.tell(E.Name()+" will now never rejuvinate.");
			}
		}
		else
			mob.tell("(no change)");
	}

	protected void genUses(MOB mob, Item E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Uses Remaining: '"+E.usesRemaining()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		E.setUsesRemaining(getNumericData(mob,"Enter a new value\n\r:",E.usesRemaining()));
	}

	protected void genMaxUses(MOB mob, Wand E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Maximum Uses: '"+E.maxUses()+"" +"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		E.setMaxUses(getNumericData(mob,"Enter a new value\n\r:",E.maxUses()));
	}

	protected void genCondition(MOB mob, Item E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Condition: '"+E.usesRemaining()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		E.setUsesRemaining(getNumericData(mob,"Enter a new value\n\r:",E.usesRemaining()));
	}

	protected void genMiscSet(MOB mob, Environmental E)
		throws IOException
	{
		if(E instanceof ShopKeeper)
			modifyGenShopkeeper(mob,(ShopKeeper)E);
		else
		if(E instanceof MOB)
		{
			if(((MOB)E).isMonster())
				modifyGenMOB(mob,(MOB)E);
			else
				modifyPlayer(mob,(MOB)E);
		}
		else
		if((E instanceof Exit)&&(!(E instanceof Item)))
			modifyGenExit(mob,(Exit)E);
		else
		if(E instanceof com.planet_ink.coffee_mud.Items.interfaces.Map)
			modifyGenMap(mob,(com.planet_ink.coffee_mud.Items.interfaces.Map)E);
		else
		if(E instanceof Armor)
			modifyGenArmor(mob,(Armor)E);
		else
		if(E instanceof MusicalInstrument)
			modifyGenInstrument(mob,(MusicalInstrument)E);
		else
		if(E instanceof Food)
			modifyGenFood(mob,(Food)E);
		else
		if((E instanceof Drink)&&(E instanceof Item))
			modifyGenDrink(mob,(Drink)E);
		else
		if(E instanceof Weapon)
			modifyGenWeapon(mob,(Weapon)E);
		else
		if(E instanceof Container)
			modifyGenContainer(mob,(Container)E);
		else
		if(E instanceof Item)
		{
			if(E.ID().equals("GenWallpaper"))
				modifyGenWallpaper(mob,(Item)E);
			else
				modifyGenItem(mob,(Item)E);
		}
	}


	public int getNumericData(MOB mob, String prompt, int oldValue)
		throws IOException
	{
		String value=mob.session().prompt(prompt,"");
		int numValue=CMath.s_int(value);
		if((numValue==0)&&(!value.trim().equals("0")))
		{
			mob.tell("(no change)");
			return oldValue;
		}
		return numValue;
	}

	public boolean getBooleanData(MOB mob, String prompt, boolean oldValue)
	throws IOException
	{
		boolean bool=mob.session().confirm(prompt,oldValue?"Y":"N");
		if(bool==oldValue)
			mob.tell("(no change)");
		return bool;
	}
	
	public long getLongData(MOB mob, String prompt, long oldValue)
	throws IOException
	{
		String value=mob.session().prompt(prompt,"");
		long numValue=CMath.s_long(value);
		if((numValue==0)&&(!value.trim().equals("0")))
		{
			mob.tell("(no change)");
			return oldValue;
		}
		return numValue;
	}

	public String getTextData(MOB mob, String prompt, String oldValue)
	throws IOException
	{
		String value=mob.session().prompt(prompt,"").trim();
		if(value.length()==0)
		{
			mob.tell("(no change)");
			return oldValue;
		}
		if(value.equalsIgnoreCase("null"))
		    value="";
		return value;
	}

	public double getDoubleData(MOB mob, String prompt, double oldValue)
		throws IOException
	{
		String value=mob.session().prompt(prompt,"");
		double numValue=CMath.s_double(value);
		if((numValue==0.0)&&(!value.trim().equals("0")))
		{
			mob.tell("(no change)");
			return oldValue;
		}
		return numValue;
	}

	protected void genMiscText(MOB mob, Environmental E, int showNumber, int showFlag)
		throws IOException
	{
		if(E.isGeneric())
			genMiscSet(mob,E);
		else
		{
			if((showFlag>0)&&(showFlag!=showNumber)) return;
			mob.tell(showNumber+". Misc Text: '"+E.text()+"'.");
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			String newText=mob.session().prompt("Re-enter now (null=blank)\n\r:","");
			if(newText.equalsIgnoreCase("NULL"))
				E.setMiscText("");
			else
			if(newText.length()>0)
				E.setMiscText(newText);
			else
				mob.tell("(no change)");
		}

	}

	protected void genTitleRoom(MOB mob, LandTitle E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Land plot ID: '"+E.landPropertyID()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newText="?!?!";
		while((mob.session()!=null)&&(!mob.session().killFlag())
			&&((newText.length()>0)&&(CMLib.map().getRoom(newText)==null)))
		{
			newText=mob.session().prompt("New Property ID:","");
			if((newText.length()==0)
			&&(CMLib.map().getRoom(newText)==null)
			&&(CMLib.map().getArea(newText)==null))
				mob.tell("That property (room ID) doesn't exist!");
		}
		if(newText.length()>0)
			E.setLandPropertyID(newText);
		else
			mob.tell("(no change)");

	}

	protected void genAbility(MOB mob, Environmental E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Magical Ability: '"+E.baseEnvStats().ability()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		E.baseEnvStats().setAbility(getNumericData(mob,"Enter a new value (0=no magic)\n\r:",E.baseEnvStats().ability()));
	}

	protected void genCoinStuff(MOB mob, Coins E, int showNumber, int showFlag)
	throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Money data: '"+E.getNumberOfCoins()+" x "+CMLib.beanCounter().getDenominationName(E.getCurrency(),E.getDenomination())+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		boolean gocontinue=true;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(gocontinue))
		{
		    gocontinue=false;
		    String oldCurrency=E.getCurrency();
		    if(oldCurrency.length()==0) oldCurrency="Default";
			oldCurrency=mob.session().prompt("Enter currency code (?):",oldCurrency).trim().toUpperCase();
			if(oldCurrency.equalsIgnoreCase("Default"))
			{
			    if(E.getCurrency().length()>0)
				    E.setCurrency("");
			    else
			        mob.tell("(no change)");
			}
			else
			if((oldCurrency.length()==0)||(oldCurrency.equalsIgnoreCase(E.getCurrency())))
			    mob.tell("(no change)");
			else
			if(!CMLib.beanCounter().getAllCurrencies().contains(oldCurrency))
			{
			    Vector V=CMLib.beanCounter().getAllCurrencies();
			    for(int v=0;v<V.size();v++)
			        if(((String)V.elementAt(v)).length()==0)
			            V.setElementAt("Default",v);
			    mob.tell("'"+oldCurrency+"' is not a known currency. Existing currencies include: DEFAULT"+CMParms.toStringList(V));
			    gocontinue=true;
			}
			else
			    E.setCurrency(oldCurrency.toUpperCase().trim());
		}
		gocontinue=true;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(gocontinue))
		{
		    gocontinue=false;
		    String newDenom=mob.session().prompt("Enter denomination (?):",""+E.getDenomination()).trim().toUpperCase();
			DVector DV=CMLib.beanCounter().getCurrencySet(E.getCurrency());
			if((newDenom.length()>0)
			&&(!CMath.isDouble(newDenom))
			&&(!newDenom.equalsIgnoreCase("?")))
			{
			    double denom=CMLib.english().matchAnyDenomination(E.getCurrency(),newDenom);
			    if(denom>0.0) newDenom=""+denom;
			}
		    if((newDenom.length()==0)
		    ||(CMath.isDouble(newDenom)
	            &&(!newDenom.equalsIgnoreCase("?"))
	            &&(CMath.s_double(newDenom)==E.getDenomination())))
			        mob.tell("(no change)");
		    else
			if((!CMath.isDouble(newDenom))
			||(newDenom.equalsIgnoreCase("?"))
			||((DV!=null)&&(!DV.contains(new Double(CMath.s_double(newDenom))))))
			{
			    StringBuffer allDenoms=new StringBuffer("");
			    for(int i=0;i<DV.size();i++)
			        allDenoms.append(((Double)DV.elementAt(i,1)).doubleValue()+"("+((String)DV.elementAt(i,2))+"), ");
			    if(allDenoms.toString().endsWith(", "))
			        allDenoms=new StringBuffer(allDenoms.substring(0,allDenoms.length()-2));
			    mob.tell("'"+newDenom+"' is not a defined denomination. Try one of these: "+allDenoms.toString()+".");
			    gocontinue=true;
			}
			else
			    E.setDenomination(CMath.s_double(newDenom));
		}
		E.setNumberOfCoins(getLongData(mob,"Enter stack size\n\r:",E.getNumberOfCoins()));
	}

	protected void genHitPoints(MOB mob, MOB E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		if(E.isMonster())
			mob.tell(showNumber+". Hit Points/Level Modifier (hp=((level*level) + (random*level*THIS))) : '"+E.baseEnvStats().ability()+"'.");
		else
			mob.tell(showNumber+". Ability (unused) : '"+E.baseEnvStats().ability()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newLevelStr=mob.session().prompt("Enter a new value\n\r:","");
		int newLevel=CMath.s_int(newLevelStr);
		if((newLevel!=0)||(newLevelStr.equals("0")))
			E.baseEnvStats().setAbility(newLevel);
		else
			mob.tell("(no change)");
	}

	protected void genValue(MOB mob, Item E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Base Value: '"+E.baseGoldValue()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		E.setBaseValue(getNumericData(mob,"Enter a new value\n\r:",E.baseGoldValue()));
	}

	protected void genWeight(MOB mob, Environmental E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Weight: '"+E.baseEnvStats().weight()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		E.baseEnvStats().setWeight(getNumericData(mob,"Enter a new weight\n\r:",E.baseEnvStats().weight()));
	}


	protected void genClanItem(MOB mob, ClanItem E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Clan: '"+E.clanID()+"', Type: "+ClanItem.CI_DESC[E.ciType()]+".");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String clanID=E.clanID();
		E.setClanID(mob.session().prompt("Enter a new clan\n\r:",clanID));
		if(E.clanID().equals(clanID))
			mob.tell("(no change)");
		String clanType=ClanItem.CI_DESC[E.ciType()];
		String s="?";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(s.equals("?")))
		{
			s=mob.session().prompt("Enter a new type (?)\n\r:",clanType);
			if(s.equalsIgnoreCase("?"))
				mob.tell("Types: "+CMParms.toStringList(ClanItem.CI_DESC));
			else
			if(s.equalsIgnoreCase(clanType))
			{
				mob.tell("(no change)");
				break;
			}
			else
			{
				boolean found=false;
				for(int i=0;i<ClanItem.CI_DESC.length;i++)
					if(ClanItem.CI_DESC[i].equalsIgnoreCase(s))
					{ found=true; E.setCIType(i); break;}
				if(!found)
				{
					mob.tell("'"+s+"' is unknown.  Try '?'");
					s="?";
				}
			}
		}
	}

	protected void genHeight(MOB mob, Environmental E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Height: '"+E.baseEnvStats().height()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		E.baseEnvStats().setHeight(getNumericData(mob,"Enter a new height\n\r:",E.baseEnvStats().height()));
	}


	protected void genSize(MOB mob, Armor E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Size: '"+E.baseEnvStats().height()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		E.baseEnvStats().setHeight(getNumericData(mob,"Enter a new size\n\r:",E.baseEnvStats().height()));
	}


	protected void genLayer(MOB mob, Armor E, int showNumber, int showFlag)
	throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber))  return;
		boolean seeThroughBool=CMath.bset(E.getLayerAttributes(),Armor.LAYERMASK_SEETHROUGH);
		boolean multiWearBool=CMath.bset(E.getLayerAttributes(),Armor.LAYERMASK_MULTIWEAR);
		String seeThroughStr=(!seeThroughBool)?" (opaque)":" (see-through)";
		String multiWearStr=multiWearBool?" (multi)":"";
		mob.tell(showNumber+". Layer: '"+E.getClothingLayer()+"'"+seeThroughStr+""+multiWearStr+".");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		E.setClothingLayer((short)getNumericData(mob,"Enter a new layer\n\r:",E.getClothingLayer()));
		boolean newSeeThrough=getBooleanData(mob,"Is see-through (Y/N)? ",seeThroughBool);
		boolean multiWear=getBooleanData(mob,"Is multi-wear (Y/N)? ",multiWearBool);
		E.setLayerAttributes((short)0);
		E.setLayerAttributes((short)(E.getLayerAttributes()|(newSeeThrough?Armor.LAYERMASK_SEETHROUGH:0)));
		E.setLayerAttributes((short)(E.getLayerAttributes()|(multiWear?Armor.LAYERMASK_MULTIWEAR:0)));
	}
	
	
	protected void genCapacity(MOB mob, Container E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Capacity: '"+E.capacity()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		E.setCapacity(getNumericData(mob,"Enter a new capacity\n\r:",E.capacity()));
	}

	protected void genAttack(MOB mob, Environmental E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". AttackAdjustment: '"+E.baseEnvStats().attackAdjustment()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		E.baseEnvStats().setAttackAdjustment(getNumericData(mob,"Enter a new value\n\r:",E.baseEnvStats().attackAdjustment()));
	}

	protected void genDamage(MOB mob, Environmental E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Damage/Hit: '"+E.baseEnvStats().damage()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		E.baseEnvStats().setDamage(getNumericData(mob,"Enter a new value\n\r:",E.baseEnvStats().damage()));
	}

	protected void genBanker1(MOB mob, Banker E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Coin Interest: '"+E.getCoinInterest()+"'% per real day.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		E.setCoinInterest(getDoubleData(mob,"Enter a new value\n\r:",E.getCoinInterest()));
	}
	protected void genBanker2(MOB mob, Banker E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Item Interest: '"+E.getItemInterest()+"'% per real day.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		E.setItemInterest(getDoubleData(mob,"Enter a new value\n\r:",E.getItemInterest()));
	}
	protected void genBanker3(MOB mob, Banker E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Bank Chain   : '"+E.bankChain()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newValue=mob.session().prompt("Enter a new chain\n\r:","");
		if(newValue.length()>0)
			E.setBankChain(newValue);
		else
			mob.tell("(no change)");
	}
	protected void genBanker4(MOB mob, Banker E, int showNumber, int showFlag)
	throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Loan Interest: '"+E.getLoanInterest()+"'% per mud month.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		E.setLoanInterest(getDoubleData(mob,"Enter a new value\n\r:",E.getLoanInterest()));
	}

	protected void genSpeed(MOB mob, Environmental E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Attacks/Round: '"+((int)Math.round(E.baseEnvStats().speed())+"")+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		E.baseEnvStats().setSpeed(getNumericData(mob,"Enter a new value\n\r:",(int)Math.round(E.baseEnvStats().speed())));
	}

	protected void genArmor(MOB mob, Environmental E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		if(E instanceof MOB)
			mob.tell(showNumber+". Armor (lower-better): '"+E.baseEnvStats().armor()+"'.");
		else
			mob.tell(showNumber+". Armor (higher-better): '"+E.baseEnvStats().armor()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		E.baseEnvStats().setArmor(getNumericData(mob,"Enter a new value\n\r:",E.baseEnvStats().armor()));
	}

	protected void genMoney(MOB mob, MOB E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Money: '"+CMLib.beanCounter().getMoney(E)+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		CMLib.beanCounter().setMoney(E,getNumericData(mob,"Enter a new value\n\r:",CMLib.beanCounter().getMoney(E)));
	}

	protected void genWeaponAmmo(MOB mob, Weapon E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		String defaultAmmo=(E.requiresAmmunition())?"Y":"N";
		if((showFlag!=showNumber)&&(showFlag>-999))
		{
			mob.tell(showNumber+". Ammo required: "+E.requiresAmmunition()+" ("+E.ammunitionType()+")");
			return;
		}

		if(mob.session().confirm("Does this weapon require ammunition (default="+defaultAmmo+") (Y/N)?",defaultAmmo))
		{
			mob.tell("\n\rAmmo type: '"+E.ammunitionType()+"'.");
			String newName=mob.session().prompt("Enter a new one\n\r:","");
			if(newName.length()>0)
			{
				E.setAmmunitionType(newName);
				mob.tell("(Remember to create a GenAmmunition item with '"+E.ammunitionType()+"' in the secret identity, and the uses remaining above 0!");
			}
			else
				mob.tell("(no change)");
			mob.tell("\n\rAmmo capacity: '"+E.ammunitionCapacity()+"'.)");
			int newValue=CMath.s_int(mob.session().prompt("Enter a new value\n\r:",""));
			if(newValue>0)
				E.setAmmoCapacity(newValue);
			else
				mob.tell("(no change)");
			E.setAmmoRemaining(E.ammunitionCapacity());
		}
		else
		{
			E.setAmmunitionType("");
			E.setAmmoCapacity(0);
		}
	}
	protected void genWeaponRanges(MOB mob, Weapon E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Minimum/Maximum Ranges: "+Math.round(E.minRange())+"/"+Math.round(E.maxRange())+".");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newMinStr=mob.session().prompt("Enter a new minimum range\n\r:","");
		String newMaxStr=mob.session().prompt("Enter a new maximum range\n\r:","");
		if((newMinStr.length()==0)&&(newMaxStr.length()==0))
			mob.tell("(no change)");
		else
		{
			E.setRanges(CMath.s_int(newMinStr),CMath.s_int(newMaxStr));
			if((E.minRange()>E.maxRange())||(E.minRange()<0)||(E.maxRange()<0))
			{
				mob.tell("(defective entries.  resetting.)");
				E.setRanges(0,0);
			}
		}
	}

	protected void genWeaponType(MOB mob, Weapon E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Weapon Attack Type: '"+Weapon.typeDescription[E.weaponType()]+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		boolean q=false;
		String sel="NSPBFMR";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!q))
		{
			String newType=mob.session().choose("Enter a new value\n\r:",sel+"?","");
			if(newType.equals("?"))
			{
				for(int i=0;i<sel.length();i++)
					mob.tell(sel.charAt(i)+") "+Weapon.typeDescription[i]);
				q=false;
			}
			else
			{
				q=true;
				int newValue=-1;
				if(newType.length()>0)
					newValue=sel.indexOf(newType.toUpperCase());
				if(newValue>=0)
					E.setWeaponType(newValue);
				else
					mob.tell("(no change)");
			}
		}
	}

	protected void genTechLevel(MOB mob, Area A, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Theme setting: '"+Area.THEME_DESCS[A.getTechLevel()]+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		boolean q=false;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!q))
		{
			String newType=mob.session().prompt("Enter a new level (?)\n\r",Area.THEME_DESCS[A.getTechLevel()]);
			if(newType.equals("?"))
			{
				StringBuffer say=new StringBuffer("");
				for(int i=1;i<Area.THEME_DESCS.length;i++)
					say.append(i+") "+Area.THEME_DESCS[i]+"\n\r");
				mob.tell(say.toString());
				q=false;
			}
			else
			{
				q=true;
				int newValue=-1;
				if(CMath.s_int(newType)>0)
				    newValue=CMath.s_int(newType);
				else
				for(int i=0;i<Area.THEME_DESCS.length;i++)
					if(Area.THEME_DESCS[i].toUpperCase().startsWith(newType.toUpperCase()))
						newValue=i;
				if(newValue>=0)
					A.setTechLevel(newValue);
				else
					mob.tell("(no change)");
			}
		}
	}


	protected void genMaterialCode(MOB mob, Item E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Material Type: '"+RawMaterial.RESOURCE_DESCS[E.material()&RawMaterial.RESOURCE_MASK]+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		boolean q=false;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!q))
		{
			String newType=mob.session().prompt("Enter a new material (?)\n\r:",RawMaterial.RESOURCE_DESCS[E.material()&RawMaterial.RESOURCE_MASK]);
			if(newType.equals("?"))
			{
				StringBuffer say=new StringBuffer("");
				for(int i=0;i<RawMaterial.RESOURCE_DESCS.length-1;i++)
					say.append(RawMaterial.RESOURCE_DESCS[i]+", ");
				mob.tell(say.toString().substring(0,say.length()-2));
				q=false;
			}
			else
			{
				q=true;
				int newValue=-1;
				for(int i=0;i<RawMaterial.RESOURCE_DESCS.length-1;i++)
					if(newType.equalsIgnoreCase(RawMaterial.RESOURCE_DESCS[i]))
						newValue=RawMaterial.RESOURCE_DATA[i][0];
				if(newValue>=0)
					E.setMaterial(newValue);
				else
					mob.tell("(no change)");
			}
		}
	}

	protected void genInstrumentType(MOB mob, MusicalInstrument E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Instrument Type: '"+MusicalInstrument.TYPE_DESC[E.instrumentType()]+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		boolean q=false;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!q))
		{
			String newType=mob.session().prompt("Enter a new type (?)\n\r:",MusicalInstrument.TYPE_DESC[E.instrumentType()]);
			if(newType.equals("?"))
			{
				StringBuffer say=new StringBuffer("");
				for(int i=0;i<MusicalInstrument.TYPE_DESC.length-1;i++)
					say.append(MusicalInstrument.TYPE_DESC[i]+", ");
				mob.tell(say.toString().substring(0,say.length()-2));
				q=false;
			}
			else
			{
				q=true;
				int newValue=-1;
				for(int i=0;i<MusicalInstrument.TYPE_DESC.length-1;i++)
					if(newType.equalsIgnoreCase(MusicalInstrument.TYPE_DESC[i]))
						newValue=i;
				if(newValue>=0)
					E.setInstrumentType(newValue);
				else
					mob.tell("(no change)");
			}
		}
	}

    protected void genSpecialFaction(MOB mob, MOB E, int showNumber, int showFlag, Faction F)
    throws IOException
    {
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		if(F==null) return;
		Faction.FactionRange myFR=CMLib.factions().getRange(F.factionID(),E.fetchFaction(F.factionID()));
		mob.tell(showNumber+". "+F.name()+": "+((myFR!=null)?myFR.name():"UNDEFINED")+" ("+E.fetchFaction(F.factionID())+")");
	    if((showFlag!=showNumber)&&(showFlag>-999)) return;
	    if(F.ranges()!=null)
	    for(int v=0;v<F.ranges().size();v++)
	    {
	        Faction.FactionRange FR=(Faction.FactionRange)F.ranges().elementAt(v);
	        mob.tell(CMStrings.padRight(FR.name(),20)+": "+FR.low()+" - "+FR.high()+")");
	    }
		String newOne=mob.session().prompt("Enter a new value\n\r:");
		if(CMath.isInteger(newOne))
		{
		    E.addFaction(F.factionID(),CMath.s_int(newOne));
	        return;
		}
	    for(int v=0;v<F.ranges().size();v++)
	    {
	        Faction.FactionRange FR=(Faction.FactionRange)F.ranges().elementAt(v);
	        if(FR.name().toUpperCase().startsWith(newOne.toUpperCase()))
	        {
	            if(FR.low()==F.lowest())
	                E.addFaction(F.factionID(),FR.low());
	            else
	            if(FR.high()==F.highest())
	                E.addFaction(F.factionID(),FR.high());
	            else
	                E.addFaction(F.factionID(),FR.low()+((FR.high()-FR.low())/2));
	            return;
	        }
	    }
	    mob.tell("(no change)");
    }
    protected void genFaction(MOB mob, MOB E, int showNumber, int showFlag)
    throws IOException
    {
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		String newFact="Q";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(newFact.length()>0))
		{
		    mob.tell(showNumber+". Factions: "+E.getFactionListing());
		    if((showFlag!=showNumber)&&(showFlag>-999)) return;
		    newFact=mob.session().prompt("Enter a faction name to add or remove\n\r:","");
		    if(newFact.length()>0)
		    {
		        Faction lookedUp=CMLib.factions().getFactionByName(newFact);
		        if(lookedUp==null) lookedUp=CMLib.factions().getFaction(newFact);
		        if(lookedUp!=null)
		        {
		            if (E.fetchFaction(lookedUp.factionID())!=Integer.MAX_VALUE)
		            {
		                // this mob already has this faction, they must want it removed
		                E.removeFaction(lookedUp.factionID());
		                mob.tell("Faction '"+lookedUp.name()  +"' removed.");
		            }
		            else
		            {
						int value =new Integer(mob.session().prompt("How much faction ("+lookedUp.findDefault(E)+")?",
						           new Integer(lookedUp.findDefault(E)).toString())).intValue();
			            if(value<lookedUp.minimum()) value=lookedUp.minimum();
					    if(value>lookedUp.maximum()) value=lookedUp.maximum();
		                E.addFaction(lookedUp.factionID(),value);
		                mob.tell("Faction '"+lookedUp.name() +"' added.");
		            }
		         }
		         else
		            mob.tell("'"+newFact+"' is not recognized as a valid faction name or file.");
		    }
		}
	}

	protected void genGender(MOB mob, MOB E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Gender: '"+Character.toUpperCase((char)E.baseCharStats().getStat(CharStats.STAT_GENDER))+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newType=mob.session().choose("Enter a new gender (M/F/N)\n\r:","MFN","");
		int newValue=-1;
		if(newType.length()>0)
			newValue=("MFN").indexOf(newType.trim().toUpperCase());
		if(newValue>=0)
		{
			switch(newValue)
			{
			case 0:
				E.baseCharStats().setStat(CharStats.STAT_GENDER,'M');
				break;
			case 1:
				E.baseCharStats().setStat(CharStats.STAT_GENDER,'F');
				break;
			case 2:
				E.baseCharStats().setStat(CharStats.STAT_GENDER,'N');
				break;
			}
		}
		else
			mob.tell("(no change)");
	}

	protected void genWeaponClassification(MOB mob, Weapon E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Weapon Classification: '"+Weapon.classifictionDescription[E.weaponClassification()]+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		boolean q=false;
		String sel=("ABEFHKPRSDTN");
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!q))
		{
			String newType=mob.session().choose("Enter a new value (?)\n\r:",sel+"?","");
			if(newType.equals("?"))
			{
				for(int i=0;i<sel.length();i++)
					mob.tell(sel.charAt(i)+") "+Weapon.classifictionDescription[i]);
				q=false;
			}
			else
			{
				q=true;
				int newValue=-1;
				if(newType.length()>0)
					newValue=sel.indexOf(newType.toUpperCase());
				if(newValue>=0)
					E.setWeaponClassification(newValue);
				else
					mob.tell("(no change)");
			}
		}
	}

	protected void genSecretIdentity(MOB mob, Item E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Secret Identity: '"+E.rawSecretIdentity()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newValue=mob.session().prompt("Enter a new identity (null=blank)\n\r:","");
		if(newValue.equalsIgnoreCase("null"))
			E.setSecretIdentity("");
		else
		if(newValue.length()>0)
			E.setSecretIdentity(newValue);
		else
			mob.tell("(no change)");
	}

	protected void genNourishment(MOB mob, Food E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Nourishment/Eat: '"+E.nourishment()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		int newValue=CMath.s_int(mob.session().prompt("Enter a new amount\n\r:",""));
		if(newValue>0)
			E.setNourishment(newValue);
		else
			mob.tell("(no change)");
	}

	protected void genRace(MOB mob, MOB E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		String raceID="begin!";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(raceID.length()>0))
		{
			mob.tell(showNumber+". Race: '"+E.baseCharStats().getMyRace().ID()+"'.");
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			raceID=mob.session().prompt("Enter a new race (?)\n\r:","").trim();
			if(raceID.equalsIgnoreCase("?"))
				mob.tell(CMLib.lister().reallyList(CMClass.races(),-1).toString());
			else
			if(raceID.length()==0)
				mob.tell("(no change)");
			else
			{
				Race R=CMClass.getRace(raceID);
				if(R!=null)
				{
					E.baseCharStats().setMyRace(R);
					E.baseCharStats().getMyRace().startRacing(E,false);
					E.baseCharStats().getMyRace().setHeightWeight(E.baseEnvStats(),(char)E.baseCharStats().getStat(CharStats.STAT_GENDER));
				}
				else
					mob.tell("Unknown race! Try '?'.");
			}
		}
	}

	protected void genCharClass(MOB mob, MOB E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		String classID="begin!";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(classID.length()>0))
		{
			StringBuffer str=new StringBuffer("");
			for(int c=0;c<E.baseCharStats().numClasses();c++)
			{
				CharClass C=E.baseCharStats().getMyClass(c);
				str.append(C.ID()+"("+E.baseCharStats().getClassLevel(C)+") ");
			}
			mob.tell(showNumber+". Class: '"+str.toString()+"'.");
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			classID=mob.session().prompt("Enter a class to add/remove(?)\n\r:","").trim();
			if(classID.equalsIgnoreCase("?"))
				mob.tell(CMLib.lister().reallyList(CMClass.charClasses(),-1).toString());
			else
			if(classID.length()==0)
				mob.tell("(no change)");
			else
			{
				CharClass C=CMClass.getCharClass(classID);
				if(C!=null)
				{
					if(E.baseCharStats().getClassLevel(C)>=0)
					{
						if(E.baseCharStats().numClasses()<2)
							mob.tell("Final class may not be removed.  To change a class, add the new one first.");
						else
						{
							StringBuffer charClasses=new StringBuffer("");
							StringBuffer classLevels=new StringBuffer("");
							for(int c=0;c<E.baseCharStats().numClasses();c++)
							{
								CharClass C2=E.baseCharStats().getMyClass(c);
								int L2=E.baseCharStats().getClassLevel(C2);
								if(C2!=C)
								{
									charClasses.append(";"+C2.ID());
									classLevels.append(";"+L2);
								}
							}
							E.baseCharStats().setMyClasses(charClasses.toString());
							E.baseCharStats().setMyLevels(classLevels.toString());
						}
					}
					else
					{
						int highLvl=Integer.MIN_VALUE;
						CharClass highestC=null;
						for(int c=0;c<E.baseCharStats().numClasses();c++)
						{
							CharClass C2=E.baseCharStats().getMyClass(c);
							if(E.baseCharStats().getClassLevel(C2)>highLvl)
							{
								highestC=C2;
								highLvl=E.baseCharStats().getClassLevel(C2);
							}
						}
						E.baseCharStats().setCurrentClass(C);
						int levels=E.baseCharStats().combinedSubLevels();
						levels=E.baseEnvStats().level()-levels;
						String lvl=null;
						if(levels>0)
						{
							lvl=mob.session().prompt("Levels to give this class ("+levels+")\n\r:",""+levels).trim();
							int lvl2=CMath.s_int(lvl);
							if(lvl2>levels) lvl2=levels;
							E.baseCharStats().setClassLevel(C,lvl2);
						}
						else
						{
							lvl=mob.session().prompt("Levels to siphon from "+highestC.ID()+" for this class (0)\n\r:",""+0).trim();
							int lvl2=CMath.s_int(lvl);
							if(lvl2>highLvl) lvl2=highLvl;
							E.baseCharStats().setClassLevel(highestC,highLvl-lvl2);
							E.baseCharStats().setClassLevel(C,lvl2);
						}

					}
					int levels=E.baseCharStats().combinedSubLevels();
					levels=E.baseEnvStats().level()-levels;
					C=E.baseCharStats().getCurrentClass();
					E.baseCharStats().setClassLevel(C,levels);
				}
				else
					mob.tell("Unknown character class! Try '?'.");
			}
		}
	}

	protected void genTattoos(MOB mob, MOB E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		String behave="NO";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(behave.length()>0))
		{
			String tattoostr="";
			for(int b=0;b<E.numTattoos();b++)
			{
				String B=E.fetchTattoo(b);
				if(B!=null)	tattoostr+=B+", ";
			}
			if(tattoostr.length()>0)
                tattoostr=tattoostr.substring(0,tattoostr.length()-2);
            if((tattoostr.length()>60)&&((showFlag!=showNumber)&&(showFlag>-999)))
                tattoostr=tattoostr.substring(0,60)+"...";
			mob.tell(showNumber+". Tattoos: '"+tattoostr+"'.");
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			behave=mob.session().prompt("Enter a tattoo to add/remove\n\r:","");
			if(behave.length()>0)
			{
				String tattoo=behave;
				if((tattoo.length()>0)
				&&(Character.isDigit(tattoo.charAt(0)))
				&&(tattoo.indexOf(" ")>0)
				&&(CMath.isNumber(tattoo.substring(0,tattoo.indexOf(" ")))))
					tattoo=tattoo.substring(tattoo.indexOf(" ")+1).trim();
				if(E.fetchTattoo(tattoo)!=null)
				{
					mob.tell(tattoo.trim().toUpperCase()+" removed.");
					E.delTattoo(behave);
				}
				else
				{
					mob.tell(behave.trim().toUpperCase()+" added.");
					E.addTattoo(behave);
				}
			}
			else
				mob.tell("(no change)");
		}
	}

	protected void genTitles(MOB mob, MOB E, int showNumber, int showFlag)
	throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		if(E.playerStats()==null) return;
		String behave="NO";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(behave.length()>0))
		{
			String behaviorstr="";
			for(int b=0;b<E.playerStats().getTitles().size();b++)
			{
				String B=(String)E.playerStats().getTitles().elementAt(b);
				if(B!=null)	behaviorstr+=B+", ";
			}
			if(behaviorstr.length()>0)
				behaviorstr=behaviorstr.substring(0,behaviorstr.length()-2);
			mob.tell(showNumber+". Titles: '"+behaviorstr+"'.");
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			behave=mob.session().prompt("Enter a title to add or a number to remove\n\r:","");
			if(behave.length()>0)
			{
				String tattoo=behave;
				if((tattoo.length()>0)
				&&(CMath.isInteger(tattoo))
				&&(CMath.s_int(tattoo)>0)
				&&(CMath.s_int(tattoo)<=E.playerStats().getTitles().size()))
					tattoo=(String)E.playerStats().getTitles().elementAt(CMath.s_int(tattoo)-1);
				else
				if((tattoo.length()>0)
				&&(Character.isDigit(tattoo.charAt(0)))
				&&(tattoo.indexOf(" ")>0)
				&&(CMath.isNumber(tattoo.substring(0,tattoo.indexOf(" ")))))
					tattoo=tattoo.substring(tattoo.indexOf(" ")+1).trim();
				if(E.playerStats().getTitles().contains(tattoo))
				{
					mob.tell(tattoo.trim().toUpperCase()+" removed.");
					E.playerStats().getTitles().remove(tattoo);
				}
				else
				{
					mob.tell(behave.trim().toUpperCase()+" added.");
					E.playerStats().getTitles().addElement(tattoo);
				}
			}
			else
				mob.tell("(no change)");
		}
	}

	protected void genExpertises(MOB mob, MOB E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		String behave="NO";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(behave.length()>0))
		{
			String behaviorstr="";
			for(int b=0;b<E.numExpertises();b++)
			{
				String B=E.fetchExpertise(b);
				if(B!=null)	behaviorstr+=B+", ";
			}
			if(behaviorstr.length()>0)
				behaviorstr=behaviorstr.substring(0,behaviorstr.length()-2);
            if((behaviorstr.length()>60)&&((showFlag!=showNumber)&&(showFlag>-999)))
                behaviorstr=behaviorstr.substring(0,60)+"...";
			mob.tell(showNumber+". Expertises: '"+behaviorstr+"'.");
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			behave=mob.session().prompt("Enter a lesson to add/remove\n\r:","");
			if(behave.length()>0)
			{
				if(E.fetchExpertise(behave)!=null)
				{
					mob.tell(behave+" removed.");
					E.delExpertise(behave);
				}
				else
				{
					mob.tell(behave+" added.");
					E.addExpertise(behave);
				}
			}
			else
				mob.tell("(no change)");
		}
	}

	protected void genSecurity(MOB mob, MOB E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		PlayerStats P=E.playerStats();
		if(P==null) return;
		String behave="NO";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(behave.length()>0))
		{
			String behaviorstr="";
			for(int b=0;b<P.getSecurityGroups().size();b++)
			{
				String B=(String)P.getSecurityGroups().elementAt(b);
				if(B!=null)	behaviorstr+=B+", ";
			}
			if(behaviorstr.length()>0)
				behaviorstr=behaviorstr.substring(0,behaviorstr.length()-2);
			mob.tell(showNumber+". Security Groups: '"+behaviorstr+"'.");
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			behave=mob.session().prompt("Enter a group to add/remove\n\r:","");
			if(behave.length()>0)
			{
				if(P.getSecurityGroups().contains(behave.trim().toUpperCase()))
				{
					P.getSecurityGroups().remove(behave.trim().toUpperCase());
					mob.tell(behave+" removed.");
				}
				else
                if((behave.trim().toUpperCase().startsWith("AREA "))
                &&(!CMSecurity.isAllowedAnywhere(mob,behave.trim().toUpperCase().substring(5).trim())))
                    mob.tell("You do not have clearance to add security code '"+behave+"' to this class.");
                else
                if((!behave.trim().toUpperCase().startsWith("AREA "))
                &&(!CMSecurity.isAllowedEverywhere(mob,behave.trim().toUpperCase())))
                    mob.tell("You do not have clearance to add security code '"+behave+"' to this class.");
                else
				{
					P.getSecurityGroups().addElement(behave.trim().toUpperCase());
					mob.tell(behave+" added.");
				}
			}
			else
				mob.tell("(no change)");
		}
	}

	protected void genBehaviors(MOB mob, Environmental E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		String behave="NO";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(behave.length()>0))
		{
			String behaviorstr="";
			for(int b=0;b<E.numBehaviors();b++)
			{
				Behavior B=E.fetchBehavior(b);
				if((B!=null)&&(B.isSavable()))
				{
					behaviorstr+=B.ID();
					if(B.getParms().trim().length()>0)
						behaviorstr+="("+B.getParms().trim()+"), ";
					else
						behaviorstr+=", ";
				}
			}
			if(behaviorstr.length()>0)
				behaviorstr=behaviorstr.substring(0,behaviorstr.length()-2);
			mob.tell(showNumber+". Behaviors: '"+behaviorstr+"'.");
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			behave=mob.session().prompt("Enter a behavior to add/remove (?)\n\r:","");
			if(behave.length()>0)
			{
				if(behave.equalsIgnoreCase("?"))
					mob.tell(CMLib.lister().reallyList(CMClass.behaviors(),-1).toString());
				else
				{
					Behavior chosenOne=null;
					for(int b=0;b<E.numBehaviors();b++)
					{
						Behavior B=E.fetchBehavior(b);
						if((B!=null)&&(B.ID().equalsIgnoreCase(behave)))
							chosenOne=B;
					}
					if(chosenOne!=null)
					{
						mob.tell(chosenOne.ID()+" removed.");
						E.delBehavior(chosenOne);
					}
					else
					{
						chosenOne=CMClass.getBehavior(behave);
						if(chosenOne!=null)
						{
							boolean alreadyHasIt=false;
							for(int b=0;b<E.numBehaviors();b++)
							{
								Behavior B=E.fetchBehavior(b);
								if((B!=null)&&(B.ID().equals(chosenOne.ID())))
								{
									alreadyHasIt=true;
									chosenOne=B;
								}
							}
                            String parms="?";
                            while(parms.equals("?"))
                            {
    							parms=chosenOne.getParms();
    							parms=mob.session().prompt("Enter any behavior parameters (?)\n\r:"+parms);
                                if(parms.equals("?")){ StringBuffer s2=CMLib.help().getHelpText(chosenOne.ID(),mob,true); if(s2!=null) mob.tell(s2.toString()); else mob.tell("no help!");}
                            }
							chosenOne.setParms(parms.trim());
							if(!alreadyHasIt)
							{
								mob.tell(chosenOne.ID()+" added.");
								E.addBehavior(chosenOne);
							}
							else
								mob.tell(chosenOne.ID()+" re-added.");
						}
						else
						{
							mob.tell("'"+behave+"' is not recognized.  Try '?'.");
						}
					}
				}
			}
			else
				mob.tell("(no change)");
		}
	}

	protected void genAffects(MOB mob, Environmental E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		String behave="NO";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(behave.length()>0))
		{
			String affectstr="";
			for(int b=0;b<E.numEffects();b++)
			{
				Ability A=E.fetchEffect(b);
				if((A!=null)&&(A.savable()))
				{
					affectstr+=A.ID();
					if(A.text().trim().length()>0)
						affectstr+="("+A.text().trim()+"), ";
					else
						affectstr+=", ";
				}

			}
			if(affectstr.length()>0)
				affectstr=affectstr.substring(0,affectstr.length()-2);
			mob.tell(showNumber+". Effects: '"+affectstr+"'.");
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			behave=mob.session().prompt("Enter an effect to add/remove (?)\n\r:","");
			if(behave.length()>0)
			{
				if(behave.equalsIgnoreCase("?"))
					mob.tell(CMLib.lister().reallyList(CMClass.abilities(),-1).toString());
				else
				{
					Ability chosenOne=null;
					for(int a=0;a<E.numEffects();a++)
					{
						Ability A=E.fetchEffect(a);
						if((A!=null)&&(A.ID().equalsIgnoreCase(behave)))
							chosenOne=A;
					}
					if(chosenOne!=null)
					{
						mob.tell(chosenOne.ID()+" removed.");
						E.delEffect(chosenOne);
					}
					else
					{
						chosenOne=CMClass.getAbility(behave);
						if(chosenOne!=null)
						{
                            String parms="?";
                            while(parms.equals("?"))
                            {
                                parms=chosenOne.text();
                                parms=mob.session().prompt("Enter any effect parameters (?)\n\r:"+parms);
                                if(parms.equals("?")){ StringBuffer s2=CMLib.help().getHelpText(chosenOne.ID(),mob,true); if(s2!=null) mob.tell(s2.toString()); else mob.tell("no help!");}
                            }
							chosenOne.setMiscText(parms.trim());
							mob.tell(chosenOne.ID()+" added.");
							E.addNonUninvokableEffect(chosenOne);
						}
						else
						{
							mob.tell("'"+behave+"' is not recognized.  Try '?'.");
						}
					}
				}
			}
			else
				mob.tell("(no change)");
		}
	}

	protected void genRideable1(MOB mob, Rideable R, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Rideable Type: '"+Rideable.RIDEABLE_DESCS[R.rideBasis()]+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		boolean q=false;
		String sel="LWACBTEDG";
		while(!q)
		{
			String newType=mob.session().choose("Enter a new value (?)\n\r:",sel+"?","");
			if(newType.equals("?"))
			{
				for(int i=0;i<sel.length();i++)
					mob.tell(sel.charAt(i)+") "+Rideable.RIDEABLE_DESCS[i].toLowerCase());
				q=false;
			}
			else
			{
				q=true;
				int newValue=-1;
				if(newType.length()>0)
					newValue=sel.indexOf(newType.toUpperCase());
				if(newValue>=0)
					R.setRideBasis(newValue);
				else
					mob.tell("(no change)");
			}
		}
	}
	protected void genRideable2(MOB mob, Rideable R, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Number of MOBs held: '"+R.riderCapacity()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newLevelStr=mob.session().prompt("Enter a new value\n\r:","");
		int newLevel=CMath.s_int(newLevelStr);
		if(newLevel>0)
			R.setRiderCapacity(newLevel);
		else
			mob.tell("(no change)");
	}

	protected void genShopkeeper1(MOB mob, ShopKeeper E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Shopkeeper type: '"+E.storeKeeperString()+"'.");
		StringBuffer buf=new StringBuffer("");
		StringBuffer codes=new StringBuffer("");
		String codeStr="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
		if(E instanceof Banker)
		{
			int r=ShopKeeper.DEAL_BANKER;
			char c=codeStr.charAt(r);
			codes.append(c);
			buf.append(c+") "+ShopKeeper.DEAL_DESCS[r]+"\n\r");
			r=ShopKeeper.DEAL_CLANBANKER;
			c=codeStr.charAt(r);
			codes.append(c);
			buf.append(c+") "+ShopKeeper.DEAL_DESCS[r]+"\n\r");
		}
		else
        if(E instanceof PostOffice)
        {
            int r=ShopKeeper.DEAL_POSTMAN;
            char c=codeStr.charAt(r);
            codes.append(c);
            buf.append(c+") "+ShopKeeper.DEAL_DESCS[r]+"\n\r");
            r=ShopKeeper.DEAL_CLANPOSTMAN;
            c=codeStr.charAt(r);
            codes.append(c);
            buf.append(c+") "+ShopKeeper.DEAL_DESCS[r]+"\n\r");
        }
        else
		for(int r=0;r<ShopKeeper.DEAL_DESCS.length;r++)
		{
			if((r!=ShopKeeper.DEAL_CLANBANKER)
            &&(r!=ShopKeeper.DEAL_BANKER)
            &&(r!=ShopKeeper.DEAL_CLANPOSTMAN)
            &&(r!=ShopKeeper.DEAL_POSTMAN))
			{
				char c=codeStr.charAt(r);
				codes.append(c);
				buf.append(c+") "+ShopKeeper.DEAL_DESCS[r]+"\n\r");
			}
		}
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newType=mob.session().choose(buf.toString()+"Enter a new value\n\r: ",codes.toString(),"");
		int newValue=-1;
		if(newType.length()>0)
			newValue=codeStr.indexOf(newType.toUpperCase());
		if(newValue>=0)
		{
			boolean reexamine=(E.whatIsSold()!=newValue);
			E.setWhatIsSold(newValue);
            if(reexamine)
            {
                Vector V=E.getShop().getStoreInventory();
                for(int b=0;b<V.size();b++)
                    if(!E.doISellThis((Environmental)V.elementAt(b)))
                        E.getShop().delAllStoreInventory((Environmental)V.elementAt(b),E.whatIsSold());
            }
		}
	}

	protected void genShopkeeper2(MOB mob, ShopKeeper E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		String itemstr="NO";
		while(itemstr.length()>0)
		{
			String inventorystr="";
			Vector V=E.getShop().getStoreInventory();
			for(int b=0;b<V.size();b++)
			{
				Environmental E2=(Environmental)V.elementAt(b);
				if(E2.isGeneric())
					inventorystr+=E2.name()+" ("+E.getShop().numberInStock(E2)+"), ";
				else
					inventorystr+=CMClass.classID(E2)+" ("+E.getShop().numberInStock(E2)+"), ";
			}
			if(inventorystr.length()>0)
				inventorystr=inventorystr.substring(0,inventorystr.length()-2);
			mob.tell(showNumber+". Inventory: '"+inventorystr+"'.");
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			itemstr=mob.session().prompt("Enter something to add/remove (?)\n\r:","");
			if(itemstr.length()>0)
			{
				if(itemstr.equalsIgnoreCase("?"))
				{
					mob.tell(CMLib.lister().reallyList(CMClass.abilities(),-1).toString());
					mob.tell(CMLib.lister().reallyList(CMClass.armor(),-1).toString());
					mob.tell(CMLib.lister().reallyList(CMClass.weapons(),-1).toString());
					mob.tell(CMLib.lister().reallyList(CMClass.miscMagic(),-1).toString());
					mob.tell(CMLib.lister().reallyList(CMClass.miscTech(),-1).toString());
					mob.tell(CMLib.lister().reallyList(CMClass.clanItems(),-1).toString());
					mob.tell(CMLib.lister().reallyList(CMClass.basicItems(),-1).toString());
					mob.tell(CMLib.lister().reallyList(CMClass.mobTypes(),-1).toString());
					mob.tell("* Plus! Any items on the ground.");
					mob.tell("* Plus! Any mobs hanging around in the room.");
				}
				else
				{
					Environmental item=E.getShop().getStock(itemstr,null,E.whatIsSold(),null);
					if(item!=null)
					{
						mob.tell(item.ID()+" removed.");
						E.getShop().delAllStoreInventory((Environmental)item.copyOf(),E.whatIsSold());
					}
					else
					{
						item=CMClass.getUnknown(itemstr);
						if((item==null)&&(mob.location()!=null))
						{
							Room R=mob.location();
							item=R.fetchItem(null,itemstr);
							if(item==null)
							{
								item=R.fetchInhabitant(itemstr);
								if((item instanceof MOB)&&(!((MOB)item).isMonster()))
									item=null;
							}
						}
						if(item!=null)
						{
							item=(Environmental)item.copyOf();
							item.recoverEnvStats();
							boolean ok=E.doISellThis(item);
							if((item instanceof Ability)
							   &&((E.whatIsSold()==ShopKeeper.DEAL_TRAINER)||(E.whatIsSold()==ShopKeeper.DEAL_CASTER)))
								ok=true;
							else
							if(E.whatIsSold()==ShopKeeper.DEAL_INVENTORYONLY)
								ok=true;
							if(!ok)
							{
								mob.tell("The shopkeeper does not sell that.");
							}
							else
							{
								boolean alreadyHasIt=false;

								if(E.getShop().doIHaveThisInStock(item.Name(),null,E.whatIsSold(),null))
								   alreadyHasIt=true;

								if(!alreadyHasIt)
								{
									mob.tell(item.ID()+" added.");
									int num=1;
									if(!(item instanceof Ability))
										num=CMath.s_int(mob.session().prompt("How many? :",""));
									int price=CMath.s_int(mob.session().prompt("At what price? :",""));
									E.getShop().addStoreInventory(item,num,price,E);
								}
							}
						}
						else
						{
							mob.tell("'"+itemstr+"' is not recognized.  Try '?'.");
						}
					}
				}
			}
			else
				mob.tell("(no change)");
		}
	}
	protected void genEconomics1(MOB mob, Economics E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Prejudice: '"+E.prejudiceFactors()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newValue=mob.session().prompt("Enter a new string (null=default)\n\r:","");
		if(newValue.equalsIgnoreCase("null"))
			E.setPrejudiceFactors("");
		else
		if(newValue.length()>0)
			E.setPrejudiceFactors(newValue);
		else
			mob.tell("(no change)");
	}

    protected void genEconomics2(MOB mob, Economics E, int showNumber, int showFlag)
    throws IOException
    {
        if((showFlag>0)&&(showFlag!=showNumber)) return;
        String header=showNumber+". Item Pricing Factors: ";
        String[] prics=E.itemPricingAdjustments();
        if((showFlag!=showNumber)&&(showFlag>-999))
        {
            if(prics.length<1) 
                mob.tell(header+"''.");
            else
            if(prics.length==1) 
                mob.tell(header+"'"+prics[0]+"'.");
            else
                mob.tell(header+prics.length+" defined..");
            return;
        }
        String behave="NO";
        while((mob.session()!=null)&&(!mob.session().killFlag())&&(behave.length()>0))
        {
            mob.tell(header+"\n\r");
            for(int p=0;p<prics.length;p++)
                mob.tell(CMStrings.SPACES.substring(0,header.length()-3)
                        +(p+1)+") "+prics[p]+"\n\r");
            String newValue=mob.session().prompt("Enter # to remove, or A to add:\n\r:","");
            if(CMath.isInteger(newValue))
            {
                int x=CMath.s_int(newValue);
                if((x>0)&&(x<=prics.length))
                {
                    String[] newPrics=new String[prics.length-1];
                    int y=0;
                    for(int i=0;i<prics.length;i++)
                        if(i!=(x-1))
                            newPrics[y++]=prics[i];
                    prics=newPrics;
                }
            }
            else
            if(newValue.toUpperCase().startsWith("A"))
            {
                double dbl=CMath.s_double(mob.session().prompt("Enter a price multiplier between 0.0 and X.Y\n\r: "));
                String mask="?";
                while(mask.equals("?"))
                {
                    mask=mob.session().prompt("Now enter a mask that describes the item (? for syntax)\n\r: "); 
                    if(mask.equals("?"))
                        mob.tell(CMLib.masking().maskHelp("\n\r","disallow"));
                }
                String[] newPrics=new String[prics.length+1];
                for(int i=0;i<prics.length;i++)
                    newPrics[i]=prics[i];
                newPrics[prics.length]=dbl+" "+mask;
                prics=newPrics;
            }
            else
            {
                mob.tell("(no change)");
                break;
            }
        }
        E.setItemPricingAdjustments(prics);
    }
    
    protected void genAreaBlurbs(MOB mob, Area E, int showNumber, int showFlag)
    throws IOException
    {
        if((showFlag>0)&&(showFlag!=showNumber)) return;
        String header=showNumber+". Area Blurb Flags: ";
        if((showFlag!=showNumber)&&(showFlag>-999))
        {
            int numFlags=E.numBlurbFlags();
            if(numFlags<1) 
                mob.tell(header+"''.");
            else
            if(numFlags==1) 
                mob.tell(header+"'"+E.getBlurbFlag(0)+": "+E.getBlurbFlag(E.getBlurbFlag(0))+"'.");
            else
                mob.tell(header+numFlags+" defined..");
            return;
        }
        String behave="NO";
        while((mob.session()!=null)&&(!mob.session().killFlag())&&(behave.length()>0))
        {
            mob.tell(header+"\n\r");
            for(int p=0;p<E.numBlurbFlags();p++)
                mob.tell((E.getBlurbFlag(p))+": "+E.getBlurbFlag(E.getBlurbFlag(p)));
            String newValue=mob.session().prompt("Enter flag to remove, or A to add:\n\r:","");
            if(E.getBlurbFlag(newValue.toUpperCase().trim())!=null)
            {
                E.delBlurbFlag(newValue.toUpperCase().trim());
                mob.tell(newValue.toUpperCase().trim()+" removed");
            }
            else
            if(newValue.toUpperCase().equals("A"))
            {
                String flag=mob.session().prompt("Enter a new flag: ");
                if(flag.trim().length()==0) continue;
                String desc=mob.session().prompt("Enter a flag blurb (or nothing): ");
                E.addBlurbFlag((flag.toUpperCase().trim()+" "+desc).trim());
                mob.tell(flag.toUpperCase().trim()+" added");
            }
            else
            if(newValue.length()==0)
            {
                mob.tell("(no change)");
                break;
            }
        }
    }
    
	protected void genEconomics3(MOB mob, Economics E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Budget: '"+E.budget()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newValue=mob.session().prompt("Enter a new string (null=default)\n\r:","");
		if(newValue.equalsIgnoreCase("null"))
			E.setBudget("");
		else
		if(newValue.length()>0)
			E.setBudget(newValue);
		else
			mob.tell("(no change)");
	}

	protected void genEconomics4(MOB mob, Economics E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Devaluation rate(s): '"+E.devalueRate()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newValue=mob.session().prompt("Enter a new string (null=default)\n\r:","");
		if(newValue.equalsIgnoreCase("null"))
			E.setDevalueRate("");
		else
		if(newValue.length()>0)
			E.setDevalueRate(newValue);
		else
			mob.tell("(no change)");
	}
	protected void genEconomics5(MOB mob, Economics E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Inventory reset rate: "+E.invResetRate()+" ticks.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newValue=mob.session().prompt("Enter a new number\n\r:","");
		if(newValue.equals("0")||(CMath.s_int(newValue)!=0))
			E.setInvResetRate(CMath.s_int(newValue));
		else
			mob.tell("(no change)");
	}

    protected void genEconomics6(MOB mob, Economics E, int showNumber, int showFlag)
    throws IOException
    {
        if((showFlag>0)&&(showFlag!=showNumber)) return;
        mob.tell(showNumber+". Ignore Mask: '"+E.ignoreMask()+"'.");
        if((showFlag!=showNumber)&&(showFlag>-999)) return;
        String newValue=mob.session().prompt("Enter a new string (null=no mask)\n\r:","");
        if(newValue.equalsIgnoreCase("null"))
            E.setIgnoreMask("");
        else
        if(newValue.length()>0)
            E.setIgnoreMask(newValue);
        else
            mob.tell("(no change)");
    }

	protected void genAbilities(MOB mob, MOB E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		String behave="NO";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(behave.length()>0))
		{
			String abilitiestr="";
			for(int a=0;a<E.numLearnedAbilities();a++)
			{
				Ability A=E.fetchAbility(a);
				if((A!=null)&&(A.savable()))
					abilitiestr+=A.ID()+", ";
			}
			if(abilitiestr.length()>0)
				abilitiestr=abilitiestr.substring(0,abilitiestr.length()-2);
            if((abilitiestr.length()>60)&&((showFlag!=showNumber)&&(showFlag>-999)))
                abilitiestr=abilitiestr.substring(0,60)+"...";
			mob.tell(showNumber+". Abilities: '"+abilitiestr+"'.");
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			behave=mob.session().prompt("Enter an ability to add/remove (?)\n\r:","");
			if(behave.length()>0)
			{
				if(behave.equalsIgnoreCase("?"))
					mob.tell(CMLib.lister().reallyList(CMClass.abilities(),-1).toString());
				else
				{
					Ability chosenOne=null;
					for(int a=0;a<E.numLearnedAbilities();a++)
					{
						Ability A=E.fetchAbility(a);
						if((A!=null)&&(A.ID().equalsIgnoreCase(behave)))
							chosenOne=A;
					}
					if(chosenOne!=null)
					{
						mob.tell(chosenOne.ID()+" removed.");
						E.delAbility(chosenOne);
						if(E.fetchEffect(chosenOne.ID())!=null)
							E.delEffect(E.fetchEffect(chosenOne.ID()));
					}
					else
					{
						chosenOne=CMClass.getAbility(behave);
						if(chosenOne!=null)
						{
							boolean alreadyHasIt=(E.fetchAbility(chosenOne.ID())!=null);
							if(!alreadyHasIt)
								mob.tell(chosenOne.ID()+" added.");
							else
								mob.tell(chosenOne.ID()+" re-added.");
							if(!alreadyHasIt)
							{
								chosenOne=(Ability)chosenOne.copyOf();
								E.addAbility(chosenOne);
								chosenOne.setProficiency(50);
								chosenOne.autoInvocation(mob);
							}
						}
						else
						{
							mob.tell("'"+behave+"' is not recognized.  Try '?'.");
						}
					}
				}
			}
			else
				mob.tell("(no change)");
		}
	}

	protected void genClanMembers(MOB mob, Clan E, int showNumber, int showFlag)
	throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		String behave="NO";
		DVector members=E.getMemberList();
		DVector membersCopy=members.copyOf();
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(behave.length()>0))
		{
			String memberStr="";
			for(int m=0;m<members.size();m++)
				memberStr+=((String)members.elementAt(m,1))+" ("+CMLib.clans().getRoleName(E.getGovernment(),((Integer)members.elementAt(m,2)).intValue(),true,false)+"), ";
			if(memberStr.length()>0)
				memberStr=memberStr.substring(0,memberStr.length()-2);
			mob.tell(showNumber+". Clan Members : '"+memberStr+"'.");
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			behave=mob.session().prompt("Enter a name to add/remove\n\r:","");
			if(behave.length()>0)
			{
				int chosenOne=-1;
				for(int m=0;m<members.size();m++)
					if(behave.equalsIgnoreCase((String)members.elementAt(m,1)))
						chosenOne=m;
				if(chosenOne>=0)
				{
					mob.tell((String)members.elementAt(chosenOne,1)+" removed.");
					members.removeElementAt(chosenOne);
				}
				else
				{
					MOB M=CMLib.map().getLoadPlayer(behave);
					if(M!=null)
					{
						int oldNum=-1;
						for(int m=0;m<membersCopy.size();m++)
							if(behave.equalsIgnoreCase((String)membersCopy.elementAt(m,1)))
							{
								oldNum=m;
								members.addElement(membersCopy.elementAt(m,1),membersCopy.elementAt(m,2),membersCopy.elementAt(m,3));
								break;
							}
						int index=oldNum;
						if(index<0)
						{
							index=members.size();
							members.addElement(M.Name(),new Integer(Clan.POS_MEMBER),new Long(M.playerStats().lastDateTime()));
						}
						
						int newRole=-1;
						while((mob.session()!=null)&&(!mob.session().killFlag())&&(newRole<0))
						{
							String newRoleStr=mob.session().prompt("Enter this members role (?) '"+CMLib.clans().getRoleName(E.getGovernment(),((Integer)members.elementAt(index,2)).intValue(),true,false)+"': ","");
							StringBuffer roles=new StringBuffer();
							for(int i=0;i<Clan.ROL_DESCS[E.getGovernment()].length;i++)
							{
								roles.append(Clan.ROL_DESCS[E.getGovernment()][i]+", ");
								if(newRoleStr.equalsIgnoreCase(Clan.ROL_DESCS[E.getGovernment()][i]))
									newRole=Clan.POSORDER[i];
							}
							roles=new StringBuffer(roles.substring(0,roles.length()-2));
							if(newRole<0)
								mob.tell("That role is invalid.  Valid roles include: "+roles.toString());
							else
								break;
						}
						if(oldNum<0)
							mob.tell(M.Name()+" added.");
						else
							mob.tell(M.Name()+" re-added.");
						members.setElementAt(index,2,new Integer(newRole));
					}
					else
					{
						mob.tell("'"+behave+"' is an unrecognized player name.");
					}
				}
				// first add missing ones
				for(int m=0;m<members.size();m++)
				{
					String newName=(String)members.elementAt(m,1);
					if(!membersCopy.contains(newName))
					{
						MOB M=CMLib.map().getLoadPlayer(newName);
						if(M!=null)
						{
							Clan oldC=CMLib.clans().getClan(M.getClanID());
							if((oldC!=null)
							&&(!M.getClanID().equalsIgnoreCase(E.clanID())))
							{
								M.setClanID("");
								M.setClanRole(Clan.POS_APPLICANT);
								oldC.updateClanPrivileges(M);
							}
							Integer role=(Integer)members.elementAt(m,2);
							CMLib.database().DBUpdateClanMembership(M.Name(), E.clanID(), role.intValue());
							M.setClanID(E.clanID());
							M.setClanRole(role.intValue());
							E.updateClanPrivileges(M);
						}
					}
				}
				// now adjust changed roles
				for(int m=0;m<members.size();m++)
				{
					String newName=(String)members.elementAt(m,1);
					if(membersCopy.contains(newName))
					{
						MOB M=CMLib.map().getLoadPlayer(newName);
						int newRole=((Integer)members.elementAt(m,2)).intValue();
						if((M!=null)&&(newRole!=M.getClanRole()))
						{
							CMLib.database().DBUpdateClanMembership(M.Name(), E.clanID(), newRole);
							M.setClanRole(newRole);
							E.updateClanPrivileges(M);
						}
					}
				}
				// now remove old members
				for(int m=0;m<membersCopy.size();m++)
				{
					String newName=(String)membersCopy.elementAt(m,1);
					if(!members.contains(newName))
					{
						MOB M=CMLib.map().getLoadPlayer(newName);
						if(M!=null)
						{
							M.setClanID("");
							M.setClanRole(Clan.POS_APPLICANT);
							E.updateClanPrivileges(M);
						}
					}
				}
			}
			else
				mob.tell("(no change)");
		}
	}
	
	protected void genDeity1(MOB mob, Deity E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Cleric Requirements: '"+E.getClericRequirements()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newValue=mob.session().prompt("Enter new requirements\n\r:","");
		if(newValue.length()>0)
			E.setClericRequirements(newValue);
		else
			mob.tell("(no change)");
	}
	protected void genDeity2(MOB mob, Deity E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Cleric Ritual: '"+E.getClericRitual()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newValue=mob.session().prompt("Enter new ritual\n\r:","");
		if(newValue.length()>0)
			E.setClericRitual(newValue);
		else
			mob.tell("(no change)");
	}
	protected void genDeity3(MOB mob, Deity E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Worshiper Requirements: '"+E.getWorshipRequirements()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newValue=mob.session().prompt("Enter new requirements\n\r:","");
		if(newValue.length()>0)
			E.setWorshipRequirements(newValue);
		else
			mob.tell("(no change)");
	}
	protected void genDeity4(MOB mob, Deity E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Worshiper Ritual: '"+E.getWorshipRitual()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newValue=mob.session().prompt("Enter new ritual\n\r:","");
		if(newValue.length()>0)
			E.setWorshipRitual(newValue);
		else
			mob.tell("(no change)");
	}
	protected void genDeity5(MOB mob, Deity E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		String behave="NO";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(behave.length()>0))
		{
			String abilitiestr="";
			for(int a=0;a<E.numBlessings();a++)
			{
				Ability A=E.fetchBlessing(a);
				if((A!=null)&&(A.savable()))
					abilitiestr+=A.ID()+", ";
			}
			if(abilitiestr.length()>0)
				abilitiestr=abilitiestr.substring(0,abilitiestr.length()-2);
			mob.tell(showNumber+". Blessings: '"+abilitiestr+"'.");
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			behave=mob.session().prompt("Enter an ability to add/remove (?)\n\r:","");
			if(behave.length()>0)
			{
				if(behave.equalsIgnoreCase("?"))
					mob.tell(CMLib.lister().reallyList(CMClass.abilities(),-1).toString());
				else
				{
					Ability chosenOne=null;
					for(int a=0;a<E.numBlessings();a++)
					{
						Ability A=E.fetchBlessing(a);
						if((A!=null)&&(A.ID().equalsIgnoreCase(behave)))
							chosenOne=A;
					}
					if(chosenOne!=null)
					{
						mob.tell(chosenOne.ID()+" removed.");
						E.delBlessing(chosenOne);
					}
					else
					{
						chosenOne=CMClass.getAbility(behave);
						if(chosenOne!=null)
						{
							boolean alreadyHasIt=false;
							for(int a=0;a<E.numBlessings();a++)
							{
								Ability A=E.fetchBlessing(a);
								if((A!=null)&&(A.ID().equals(chosenOne.ID())))
									alreadyHasIt=true;
							}
                            boolean clericOnly=mob.session().confirm("Is this for clerics only (y/N)?","N");
							if(!alreadyHasIt)
								mob.tell(chosenOne.ID()+" added.");
							else
								mob.tell(chosenOne.ID()+" re-added.");
							if(!alreadyHasIt)
								E.addBlessing((Ability)chosenOne.copyOf(),clericOnly);
						}
						else
						{
							mob.tell("'"+behave+"' is not recognized.  Try '?'.");
						}
					}
				}
			}
			else
				mob.tell("(no change)");
		}
	}

	protected void genDeity6(MOB mob, Deity E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		String behave="NO";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(behave.length()>0))
		{
			String abilitiestr="";
			for(int a=0;a<E.numCurses();a++)
			{
				Ability A=E.fetchCurse(a);
				if((A!=null)&&(A.savable()))
					abilitiestr+=A.ID()+", ";
			}
			if(abilitiestr.length()>0)
				abilitiestr=abilitiestr.substring(0,abilitiestr.length()-2);
			mob.tell(showNumber+". Curses: '"+abilitiestr+"'.");
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			behave=mob.session().prompt("Enter an ability to add/remove (?)\n\r:","");
			if(behave.length()>0)
			{
				if(behave.equalsIgnoreCase("?"))
					mob.tell(CMLib.lister().reallyList(CMClass.abilities(),-1).toString());
				else
				{
					Ability chosenOne=null;
					for(int a=0;a<E.numCurses();a++)
					{
						Ability A=E.fetchCurse(a);
						if((A!=null)&&(A.ID().equalsIgnoreCase(behave)))
							chosenOne=A;
					}
					if(chosenOne!=null)
					{
						mob.tell(chosenOne.ID()+" removed.");
						E.delCurse(chosenOne);
					}
					else
					{
						chosenOne=CMClass.getAbility(behave);
						if(chosenOne!=null)
						{
							boolean alreadyHasIt=false;
							for(int a=0;a<E.numCurses();a++)
							{
								Ability A=E.fetchCurse(a);
								if((A!=null)&&(A.ID().equals(chosenOne.ID())))
									alreadyHasIt=true;
							}
                            boolean clericOnly=mob.session().confirm("Is this for clerics only (y/N)?","N");
							if(!alreadyHasIt)
								mob.tell(chosenOne.ID()+" added.");
							else
								mob.tell(chosenOne.ID()+" re-added.");
							if(!alreadyHasIt)
								E.addCurse((Ability)chosenOne.copyOf(),clericOnly);
						}
						else
						{
							mob.tell("'"+behave+"' is not recognized.  Try '?'.");
						}
					}
				}
			}
			else
				mob.tell("(no change)");
		}
	}

	protected void genDeity7(MOB mob, Deity E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		String behave="NO";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(behave.length()>0))
		{
			String abilitiestr="";
			for(int a=0;a<E.numPowers();a++)
			{
				Ability A=E.fetchPower(a);
				if((A!=null)&&(A.savable()))
					abilitiestr+=A.ID()+", ";
			}
			if(abilitiestr.length()>0)
				abilitiestr=abilitiestr.substring(0,abilitiestr.length()-2);
			mob.tell(showNumber+". Granted Powers: '"+abilitiestr+"'.");
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			behave=mob.session().prompt("Enter an ability to add/remove (?)\n\r:","");
			if(behave.length()>0)
			{
				if(behave.equalsIgnoreCase("?"))
					mob.tell(CMLib.lister().reallyList(CMClass.abilities(),-1).toString());
				else
				{
					Ability chosenOne=null;
					for(int a=0;a<E.numPowers();a++)
					{
						Ability A=E.fetchPower(a);
						if((A!=null)&&(A.ID().equalsIgnoreCase(behave)))
							chosenOne=A;
					}
					if(chosenOne!=null)
					{
						mob.tell(chosenOne.ID()+" removed.");
						E.delPower(chosenOne);
					}
					else
					{
						chosenOne=CMClass.getAbility(behave);
						if(chosenOne!=null)
						{
							boolean alreadyHasIt=false;
							for(int a=0;a<E.numPowers();a++)
							{
								Ability A=E.fetchPower(a);
								if((A!=null)&&(A.ID().equals(chosenOne.ID())))
									alreadyHasIt=true;
							}
							if(!alreadyHasIt)
								mob.tell(chosenOne.ID()+" added.");
							else
								mob.tell(chosenOne.ID()+" re-added.");
							if(!alreadyHasIt)
								E.addPower((Ability)chosenOne.copyOf());
						}
						else
						{
							mob.tell("'"+behave+"' is not recognized.  Try '?'.");
						}
					}
				}
			}
			else
				mob.tell("(no change)");
		}
	}
	protected void genDeity8(MOB mob, Deity E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Cleric Sin: '"+E.getClericSin()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newValue=mob.session().prompt("Enter new sin ritual\n\r:","");
		if(newValue.length()>0)
			E.setClericSin(newValue);
		else
			mob.tell("(no change)");
	}
	protected void genDeity9(MOB mob, Deity E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Worshiper Sin: '"+E.getWorshipSin()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newValue=mob.session().prompt("Enter new sin ritual\n\r:","");
		if(newValue.length()>0)
			E.setWorshipSin(newValue);
		else
			mob.tell("(no change)");
	}
	protected void genDeity0(MOB mob, Deity E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Cleric Power Ritual: '"+E.getClericPowerup()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newValue=mob.session().prompt("Enter new power ritual\n\r:","");
		if(newValue.length()>0)
			E.setClericPowerup(newValue);
		else
			mob.tell("(no change)");
	}
    protected void genDeity11(MOB mob, Deity E, int showNumber, int showFlag)
    throws IOException
    {
        if((showFlag>0)&&(showFlag!=showNumber)) return;
        mob.tell(showNumber+". Service Ritual  : '"+E.getServiceRitual()+"'.");
        if((showFlag!=showNumber)&&(showFlag>-999)) return;
        String newValue=mob.session().prompt("Enter new ritual\n\r:","");
        if(newValue.length()>0)
            E.setServiceRitual(newValue);
        else
            mob.tell("(no change)");
    }
	protected void genGridLocaleX(MOB mob, GridZones E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Size (X): '"+E.xGridSize()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newValue=mob.session().prompt("Enter a new size\n\r:","");
		if(CMath.s_int(newValue)>0)
			E.setXGridSize(CMath.s_int(newValue));
		else
			mob.tell("(no change)");
	}

	protected void genGridLocaleY(MOB mob, GridZones E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Size (Y): '"+E.yGridSize()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newValue=mob.session().prompt("Enter a new size\n\r:","");
		if(CMath.s_int(newValue)>0)
			E.setYGridSize(CMath.s_int(newValue));
		else
			mob.tell("(no change)");
	}

	protected void genWornLocation(MOB mob, Item E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		if((showFlag!=showNumber)&&(showFlag>-999))
		{
			StringBuffer buf=new StringBuffer(showNumber+". ");
			if(!E.rawLogicalAnd())
				buf.append("Wear on any one of: ");
			else
				buf.append("Worn on all of: ");
			for(int l=0;l<Item.WORN_CODES.length;l++)
			{
				long wornCode=1<<l;
				if((CMLib.flags().wornLocation(wornCode).length()>0)
				&&(((E.rawProperLocationBitmap()&wornCode)==wornCode)))
					buf.append(CMLib.flags().wornLocation(wornCode)+" ");
			}
			mob.tell(buf.toString());
			return;
		}
		int codeVal=-1;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(codeVal!=0))
		{
			mob.tell("Wearing parameters\n\r0: Done");
			if(!E.rawLogicalAnd())
				mob.tell("1: Able to worn on any ONE of these locations:");
			else
				mob.tell("1: Must be worn on ALL of these locations:");
			for(int l=0;l<Item.WORN_CODES.length;l++)
			{
				long wornCode=1<<l;
				if(CMLib.flags().wornLocation(wornCode).length()>0)
				{
					String header=(l+2)+": ("+CMLib.flags().wornLocation(wornCode)+") : "+(((E.rawProperLocationBitmap()&wornCode)==wornCode)?"YES":"NO");
					mob.tell(header);
				}
			}
			codeVal=CMath.s_int(mob.session().prompt("Select an option number above to TOGGLE\n\r: "));
			if(codeVal>0)
			{
				if(codeVal==1)
					E.setRawLogicalAnd(!E.rawLogicalAnd());
				else
				{
					int wornCode=1<<(codeVal-2);
					if((E.rawProperLocationBitmap()&wornCode)==wornCode)
						E.setRawProperLocationBitmap(E.rawProperLocationBitmap()-wornCode);
					else
						E.setRawProperLocationBitmap(E.rawProperLocationBitmap()|wornCode);
				}
			}
		}
	}

	protected void genThirstQuenched(MOB mob, Drink E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Quenched/Drink: '"+E.thirstQuenched()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		E.setThirstQuenched(getNumericData(mob,"Enter a new amount\n\r:",E.thirstQuenched()));
	}

	protected void genDrinkHeld(MOB mob, Drink E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Amount of Drink Held: '"+E.liquidHeld()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		E.setLiquidHeld(getNumericData(mob,"Enter a new amount\n\r:",E.liquidHeld()));
		E.setLiquidRemaining(E.liquidHeld());
	}

	protected void genText(MOB mob, Race E, int showNumber, int showFlag, String FieldDisp, String Field)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". "+FieldDisp+": '"+E.getStat(Field)+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter a new one\n\r:","");
        if(newName.equals("null"))
            E.setStat(Field,"");
        else
		if(newName.length()>0)
			E.setStat(Field,newName);
		else
			mob.tell("(no change)");
	}
	protected void genText(MOB mob, Environmental E, String help, int showNumber, int showFlag, String FieldDisp, String Field)
	throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.session().rawPrintln(showNumber+". "+FieldDisp+": '"+E.getStat(Field)+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter a new one\n\r:","");
		if(newName.equalsIgnoreCase("?")&&(mob.session()!=null)&&(!mob.session().killFlag())&&(help!=null)&&(help.length()>0))
		{
			mob.tell(help);
			genText(mob,E,help,showNumber,showFlag,FieldDisp,Field);
			return;
		}
		else
		if(newName.equalsIgnoreCase("null"))
			E.setStat(Field,"");
		else
		if(newName.length()>0)
			E.setStat(Field,newName);
		else
			mob.tell("(no change)");
	}
	protected void genText(MOB mob, CharClass E, int showNumber, int showFlag, String FieldDisp, String Field)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". "+FieldDisp+": '"+E.getStat(Field)+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter a new one\n\r:","");
		if(newName.equalsIgnoreCase("null"))
			E.setStat(Field,"");
		else
		if(newName.length()>0)
			E.setStat(Field,newName);
		else
			mob.tell("(no change)");
	}
	protected void genAttackAttribute(MOB mob, CharClass E, int showNumber, int showFlag, String FieldDisp, String Field)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". "+FieldDisp+": '"+CharStats.STAT_DESCS[CMath.s_int(E.getStat(Field))]+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter a new one\n\r:","");
		String newStat="";
		for(int i=0;i<CharStats.NUM_BASE_STATS;i++)
			if(newName.equalsIgnoreCase(CharStats.STAT_DESCS[i]))
				newStat=""+i;
		if(newStat.length()>0)
			E.setStat(Field,newStat);
		else
			mob.tell("(no change)");
	}
	protected void genArmorCode(MOB mob, CharClass E, int showNumber, int showFlag, String FieldDisp, String Field)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". "+FieldDisp+": '"+CharClass.ARMOR_LONGDESC[CMath.s_int(E.getStat(Field))]+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter ("+CMParms.toStringList(CharClass.ARMOR_DESCS)+")\n\r:","");
		String newStat="";
		for(int i=0;i<CharClass.ARMOR_DESCS.length;i++)
			if(newName.equalsIgnoreCase(CharClass.ARMOR_DESCS[i]))
				newStat=""+i;
		if(newStat.length()>0)
			E.setStat(Field,newStat);
		else
			mob.tell("(no change)");
	}
	protected void genQualifications(MOB mob, CharClass E, int showNumber, int showFlag, String FieldDisp, String Field)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". "+FieldDisp+": '"+CMLib.masking().maskDesc(E.getStat(Field))+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName="?";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(newName.equals("?")))
		{
			newName=mob.session().prompt("Enter a new mask (?)\n\r:","");
			if(newName.equals("?"))
				mob.tell(CMLib.masking().maskHelp("\n","disallow"));
		}
		if((newName.length()>0)&&(!newName.equals("?")))
			E.setStat(Field,newName);
		else
			mob.tell("(no change)");
	}
	protected void genClanAccept(MOB mob, Clan E, int showNumber, int showFlag)
	throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Clan Qualifications: '"+CMLib.masking().maskDesc(E.getAcceptanceSettings())+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName="?";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(newName.equals("?")))
		{
			newName=mob.session().prompt("Enter a new mask (?)\n\r:","");
			if(newName.equals("?"))
				mob.tell(CMLib.masking().maskHelp("\n","disallow"));
		}
		if((newName.length()>0)&&(!newName.equals("?")))
			E.setAcceptanceSettings(newName);
		else
			mob.tell("(no change)");
	}
	protected void genWeaponRestr(MOB mob, CharClass E, int showNumber, int showFlag, String FieldDisp, String FieldNum, String Field)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		Vector set=CMParms.parseCommas(E.getStat(Field),true);
		StringBuffer str=new StringBuffer("");
		for(int v=0;v<set.size();v++)
			str.append(" "+Weapon.classifictionDescription[CMath.s_int((String)set.elementAt(v))].toLowerCase());

		mob.tell(showNumber+". "+FieldDisp+": '"+str.toString()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName="?";
		boolean setChanged=false;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(newName.equals("?")))
		{
			newName=mob.session().prompt("Enter a weapon class to add/remove (?)\n\r:","");
			if(newName.equals("?"))
				mob.tell(CMParms.toStringList(Weapon.classifictionDescription));
			else
			if(newName.length()>0)
			{
				int foundCode=-1;
				for(int i=0;i<Weapon.classifictionDescription.length;i++)
					if(Weapon.classifictionDescription[i].equalsIgnoreCase(newName))
						foundCode=i;
				if(foundCode<0)
				{
					mob.tell("'"+newName+"' is not recognized.  Try '?'.");
					newName="?";
				}
				else
				{
					int x=set.indexOf(""+foundCode);
					if(x>=0)
					{
						setChanged=true;
						set.removeElementAt(x);
						mob.tell("'"+newName+"' removed.");
						newName="?";
					}
					else
					{
						set.addElement(""+foundCode);
						setChanged=true;
						mob.tell("'"+newName+"' added.");
						newName="?";
					}
				}
			}
		}
		if(setChanged)
			E.setStat(Field,CMParms.toStringList(set));
		else
			mob.tell("(no change)");
	}
    
    protected void genWeaponMaterials(MOB mob, CharClass E, int showNumber, int showFlag, String FieldDisp, String FieldNum, String Field)
    throws IOException
    {
        if((showFlag>0)&&(showFlag!=showNumber)) return;
        Vector set=CMParms.parseCommas(E.getStat(Field),true);
        StringBuffer str=new StringBuffer("");
        for(int v=0;v<set.size();v++)
            str.append(" "+CMLib.materials().getMaterialDesc(CMath.s_int((String)set.elementAt(v))));
    
        mob.tell(showNumber+". "+FieldDisp+": '"+str.toString()+"'.");
        if((showFlag!=showNumber)&&(showFlag>-999)) return;
        String newName="?";
        boolean setChanged=false;
        while((mob.session()!=null)&&(!mob.session().killFlag())&&(newName.equals("?")))
        {
            newName=mob.session().prompt("Enter a material type to add/remove to requirements (?)\n\r:","");
            if(newName.equals("?"))
                mob.tell(CMParms.toStringList(RawMaterial.MATERIAL_DESCS));
            else
            if(newName.length()>0)
            {
                int foundCode=CMLib.materials().getMaterialCode(newName,true);
                if(foundCode<0) foundCode=CMLib.materials().getMaterialCode(newName,false);
                if(foundCode<0)
                {
                    mob.tell("'"+newName+"' is not recognized.  Try '?'.");
                    newName="?";
                }
                else
                {
                    int x=set.indexOf(""+foundCode);
                    if(x>=0)
                    {
                        setChanged=true;
                        set.removeElementAt(x);
                        mob.tell("'"+newName+"' removed.");
                        newName="?";
                    }
                    else
                    {
                        set.addElement(""+foundCode);
                        setChanged=true;
                        mob.tell("'"+newName+"' added.");
                        newName="?";
                    }
                }
            }
        }
        if(setChanged)
            E.setStat(Field,CMParms.toStringList(set));
        else
            mob.tell("(no change)");
    }
    
    
	protected void genInt(MOB mob, CharClass E, int showNumber, int showFlag, String FieldDisp, String Field)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". "+FieldDisp+": '"+E.getStat(Field)+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter a new one\n\r:","");
		if((newName.length()>0)&&((newName.trim().equals("0"))||(CMath.s_int(newName)!=0)))
			E.setStat(Field,""+CMath.s_int(newName));
		else
			mob.tell("(no change)");
	}
	protected void genInt(MOB mob, Environmental E, String help, int showNumber, int showFlag, String FieldDisp, String Field)
	throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". "+FieldDisp+": '"+E.getStat(Field)+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter a new one\n\r:","");
		if(newName.equalsIgnoreCase("?")&&(mob.session()!=null)&&(!mob.session().killFlag())&&(help!=null)&&(help.length()>0))
		{
			mob.tell(help);
			genInt(mob,E,help,showNumber,showFlag,FieldDisp,Field);
			return;
		}
		else
		if((newName.length()>0)&&((newName.trim().equals("0"))||(CMath.s_int(newName)!=0)))
			E.setStat(Field,""+CMath.s_int(newName));
		else
			mob.tell("(no change)");
	}
	protected void genInt(MOB mob, Race E, int showNumber, int showFlag, String FieldDisp, String Field)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". "+FieldDisp+": '"+E.getStat(Field)+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter a new one\n\r:","");
		if((newName.length()>0)&&((newName.trim().equals("0"))||(CMath.s_int(newName)!=0)))
			E.setStat(Field,""+CMath.s_int(newName));
		else
			mob.tell("(no change)");
	}
	protected void genBool(MOB mob, Race E, int showNumber, int showFlag, String FieldDisp, String Field)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". "+FieldDisp+": '"+E.getStat(Field)+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter a new true/false\n\r:","");
		if((newName.length()>0)&&(newName.equalsIgnoreCase("true")||newName.equalsIgnoreCase("false")))
			E.setStat(Field,newName.toLowerCase());
		else
			mob.tell("(no change)");
	}
	protected void genBool(MOB mob, Environmental E, int showNumber, int showFlag, String FieldDisp, String Field)
	throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". "+FieldDisp+": '"+E.getStat(Field)+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter a new true/false\n\r:","");
		if((newName.length()>0)&&(newName.equalsIgnoreCase("true")||newName.equalsIgnoreCase("false")))
			E.setStat(Field,newName.toLowerCase());
		else
			mob.tell("(no change)");
	}
	protected void genBool(MOB mob, CharClass E, int showNumber, int showFlag, String FieldDisp, String Field)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". "+FieldDisp+": '"+E.getStat(Field)+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter a new true/false\n\r:","");
		if((newName.length()>0)&&(newName.equalsIgnoreCase("true")||newName.equalsIgnoreCase("false")))
			E.setStat(Field,newName.toLowerCase());
		else
			mob.tell("(no change)");
	}
	
	protected void genDisableFlags(MOB mob, Race E, int showNumber, int showFlag)
	throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		int flags=CMath.s_int(E.getStat("DISFLAGS"));
		String newName="?";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(newName.equals("?")))
		{
			StringBuffer disabled=new StringBuffer("");
			for(int i=0;i<Race.GENFLAG_DESCS.length;i++)
				if(CMath.isSet(flags,i))
					disabled.append(Race.GENFLAG_DESCS[i]);
			
			mob.tell(showNumber+". Disabled: '"+disabled+"'.");
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			
			newName=mob.session().prompt("Enter flag to toggle (?)\n\r:","").toUpperCase();
			if(newName.length()==0)
				mob.tell("(no change)");
			else
			if(CMParms.contains(Race.GENFLAG_DESCS,newName))
			{
				int bit=CMParms.indexOf(Race.GENFLAG_DESCS,newName);
				if(CMath.isSet(flags,bit))
					flags=flags-(int)CMath.pow(2,bit);
				else
					flags=flags+(int)CMath.pow(2,bit);
			}
			else
			if(newName.equalsIgnoreCase("?"))
			{
			    StringBuffer str=new StringBuffer("Valid values: \n\r");
			    for(int i=0;i<Race.GENFLAG_DESCS.length;i++)
			        str.append(Race.GENFLAG_DESCS[i]+"\n\r");
			    mob.tell(str.toString());
			}
			else
				mob.tell("(no change)");
		}
		E.setStat("DISFLAGS",""+flags);
	}
	
	protected void genRaceWearFlags(MOB mob, Race E, int showNumber, int showFlag)
	throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		int flags=CMath.s_int(E.getStat("WEAR"));
		String newName="?";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(newName.equals("?")))
		{
			StringBuffer wearable=new StringBuffer("");
			for(int i=1;i<Item.WORN_DESCS.length;i++)
				if(CMath.isSet(flags,i-1))
					wearable.append(Item.WORN_DESCS[i]+" ");
			
			mob.tell(showNumber+". UNWearable locations: '"+wearable+"'.");
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			
			newName=mob.session().prompt("Enter a location to toggle (?)\n\r:","").toUpperCase();
			if(newName.length()==0)
				mob.tell("(no change)");
			else
			if(CMParms.contains(Item.WORN_DESCS,newName))
			{
				int bit=CMParms.indexOf(Item.WORN_DESCS,newName)-1;
				if(bit>=0)
				{
					if(CMath.isSet(flags,bit))
						flags=flags-(int)CMath.pow(2,bit);
					else
						flags=flags+(int)CMath.pow(2,bit);
				}
			}
			else
			if(newName.equalsIgnoreCase("?"))
			{
			    StringBuffer str=new StringBuffer("Valid values: \n\r");
			    for(int i=0;i<Item.WORN_DESCS.length;i++)
			        str.append(Item.WORN_DESCS[i]+" ");
			    mob.tell(str.toString());
			}
			else
				mob.tell("(no change)");
		}
		E.setStat("WEAR",""+flags);
	}
	
	
	protected void genRaceAvailability(MOB mob, Race E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Availability: '"+Area.THEME_DESCS_EXT[CMath.s_int(E.getStat("AVAIL"))]+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName="?";
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(newName.equals("?")))
		{
			newName=mob.session().prompt("Enter a new value (?)\n\r:","");
			if(newName.length()==0)
				mob.tell("(no change)");
			else
			if((CMath.isNumber(newName))&&(CMath.s_int(newName)<Area.THEME_DESCS_EXT.length))
				E.setStat("AVAIL",""+CMath.s_int(newName));
			else
			if(newName.equalsIgnoreCase("?"))
			{
			    StringBuffer str=new StringBuffer("Valid values: \n\r");
			    for(int i=0;i<Area.THEME_DESCS_EXT.length;i++)
			        str.append(i+") "+Area.THEME_DESCS_EXT[i]+"\n\r");
			    mob.tell(str.toString());
			}
			else
				mob.tell("(no change)");
		}
	}
	
    void genClassAvailability(MOB mob, CharClass E, int showNumber, int showFlag)
    throws IOException
    {
        if((showFlag>0)&&(showFlag!=showNumber)) return;
        mob.tell(showNumber+". Availability: '"+Area.THEME_DESCS_EXT[CMath.s_int(E.getStat("PLAYER"))]+"'.");
        if((showFlag!=showNumber)&&(showFlag>-999)) return;
        String newName="?";
        while((mob.session()!=null)&&(!mob.session().killFlag())&&(newName.equals("?")))
        {
            newName=mob.session().prompt("Enter a new value (?)\n\r:","");
            if(newName.length()==0)
                mob.tell("(no change)");
            else
            if((CMath.isNumber(newName))&&(CMath.s_int(newName)<Area.THEME_DESCS_EXT.length))
                E.setStat("PLAYER",""+CMath.s_int(newName));
            else
            if(newName.equalsIgnoreCase("?"))
            {
                StringBuffer str=new StringBuffer("Valid values: \n\r");
                for(int i=0;i<Area.THEME_DESCS_EXT.length;i++)
                    str.append(i+") "+Area.THEME_DESCS_EXT[i]+"\n\r");
                mob.tell(str.toString());
            }
            else
                mob.tell("(no change)");
        }
    }
    
	protected void genCat(MOB mob, Race E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Racial Category: '"+E.racialCategory()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter a new one\n\r:","");
		if(newName.length()>0)
		{
			boolean found=false;
			if(newName.startsWith("new "))
			{
				newName=CMStrings.capitalizeAndLower(newName.substring(4));
				if(newName.length()>0)
					found=true;
			}
			else
			for(Enumeration r=CMClass.races();r.hasMoreElements();)
			{
				Race R=(Race)r.nextElement();
				if(newName.equalsIgnoreCase(R.racialCategory()))
				{
					newName=R.racialCategory();
					found=true;
					break;
				}
			}
			if(!found)
			{
				StringBuffer str=new StringBuffer("That category does not exist.  Valid categories include: ");
				HashSet H=new HashSet();
				for(Enumeration r=CMClass.races();r.hasMoreElements();)
				{
					Race R=(Race)r.nextElement();
					if(!H.contains(R.racialCategory()))
					{
						H.add(R.racialCategory());
						str.append(R.racialCategory()+", ");
					}
				}
				mob.tell(str.toString().substring(0,str.length()-2)+".");
			}
			else
				E.setStat("CAT",newName);
		}
		else
			mob.tell("(no change)");
	}
	
	
	protected void genRaceBuddy(MOB mob, Race E, int showNumber, int showFlag, String prompt, String flag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". "+prompt+": '"+E.getStat(flag)+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter a new one\n\r:","");
		if(newName.length()>0)
		{
			Race R2=CMClass.getRace(newName);
			if(R2==null) R2=(Race)CMClass.unsortedLoadClass("RACE",newName);
			if((R2!=null)&&(R2.isGeneric()))
				R2=null;
			if(R2==null)
			{
				StringBuffer str=new StringBuffer("That race name is invalid or is generic.  Valid races include: ");
				for(Enumeration r=CMClass.races();r.hasMoreElements();)
				{
					Race R=(Race)r.nextElement();
					if(!R.isGeneric())
						str.append(R.ID()+", ");
				}
				mob.tell(str.toString().substring(0,str.length()-2)+".");
			}
			else
			if(CMClass.getRace(newName)==R2)
				E.setStat(flag,R2.ID());
			else
				E.setStat(flag,R2.getClass().getName());
		}
		else
			mob.tell("(no change)");
	}
    
    protected void genClassBuddy(MOB mob, CharClass E, int showNumber, int showFlag, String prompt, String flag)
    throws IOException
    {
        if((showFlag>0)&&(showFlag!=showNumber)) return;
        mob.tell(showNumber+". "+prompt+": '"+E.getStat(flag)+"'.");
        if((showFlag!=showNumber)&&(showFlag>-999)) return;
        String newName=mob.session().prompt("Enter a new one\n\r:","");
        if(newName.length()>0)
        {
            CharClass C2=CMClass.getCharClass(newName);
            if(C2==null) C2=(CharClass)CMClass.unsortedLoadClass("CHARCLASS",newName);
            if((C2!=null)&&(C2.isGeneric()))
                C2=null;
            if(C2==null)
            {
                StringBuffer str=new StringBuffer("That char class name is invalid or is generic.  Valid char classes include: ");
                for(Enumeration r=CMClass.charClasses();r.hasMoreElements();)
                {
                    CharClass C=(CharClass)r.nextElement();
                    if(!C.isGeneric())
                        str.append(C.ID()+", ");
                }
                mob.tell(str.toString().substring(0,str.length()-2)+".");
            }
            else
            if(CMClass.getCharClass(newName)==C2)
                E.setStat(flag,C2.ID());
            else
                E.setStat(flag,C2.getClass().getName());
        }
        else
            mob.tell("(no change)");
    }
    
    
	protected void genBodyParts(MOB mob, Race E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		StringBuffer parts=new StringBuffer("");
		for(int i=0;i<Race.BODYPARTSTR.length;i++)
			if(E.bodyMask()[i]!=0) parts.append(Race.BODYPARTSTR[i].toLowerCase()+"("+E.bodyMask()[i]+") ");
		mob.tell(showNumber+". Body Parts: "+parts.toString()+".");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter a body part\n\r:","");
		if(newName.length()>0)
		{
			int partNum=-1;
			for(int i=0;i<Race.BODYPARTSTR.length;i++)
				if(newName.equalsIgnoreCase(Race.BODYPARTSTR[i]))
				{ partNum=i; break;}
			if(partNum<0)
			{
				StringBuffer str=new StringBuffer("That body part is invalid.  Valid parts include: ");
				for(int i=0;i<Race.BODYPARTSTR.length;i++)
					str.append(Race.BODYPARTSTR[i]+", ");
				mob.tell(str.toString().substring(0,str.length()-2)+".");
			}
			else
			{
				newName=mob.session().prompt("Enter new number ("+E.bodyMask()[partNum]+"), 0=none\n\r:",""+E.bodyMask()[partNum]);
				if(newName.length()>0)
					E.bodyMask()[partNum]=CMath.s_int(newName);
				else
					mob.tell("(no change)");
			}
		}
		else
			mob.tell("(no change)");
	}
	protected void genEStats(MOB mob, Race R, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
        EnvStats S=(EnvStats)CMClass.getCommon("DefaultEnvStats");
        S.setAllValues(0);
		CMLib.coffeeMaker().setEnvStats(S,R.getStat("ESTATS"));
		StringBuffer parts=new StringBuffer("");
		for(int i=0;i<S.getCodes().length;i++)
			if(CMath.s_int(S.getStat(S.getCodes()[i]))!=0)
				parts.append(CMStrings.capitalizeAndLower(S.getCodes()[i])+"("+S.getStat(S.getCodes()[i])+") ");
		mob.tell(showNumber+". EStat Adjustments: "+parts.toString()+".");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
        boolean done=false;
        while((!done)&&(mob.session()!=null)&&(!mob.session().killFlag()))
        {
    		String newName=mob.session().prompt("Enter a stat name\n\r:","");
    		if(newName.length()>0)
    		{
    			String partName=null;
    			for(int i=0;i<S.getCodes().length;i++)
    				if(newName.equalsIgnoreCase(S.getCodes()[i]))
    				{ partName=S.getCodes()[i]; break;}
    			if(partName==null)
    			{
    				StringBuffer str=new StringBuffer("That stat is invalid.  Valid stats include: ");
    				for(int i=0;i<S.getCodes().length;i++)
    					str.append(S.getCodes()[i]+", ");
    				mob.tell(str.toString().substring(0,str.length()-2)+".");
    			}
    			else
    			{
    				boolean checkChange=false;
    				if(partName.equals("DISPOSITION"))
    				{
    					genDisposition(mob,S,0,0);
    					checkChange=true;
    				}
    				else
    				if(partName.equals("SENSES"))
    				{
    					genSensesMask(mob,S,0,0);
    					checkChange=true;
    				}
    				else
    				{
    					newName=mob.session().prompt("Enter a value\n\r:","");
    					if(newName.length()>0)
    					{
    						S.setStat(partName,newName);
    						checkChange=true;
    					}
    					else
    						mob.tell("(no change)");
    				}
    				if(checkChange)
    				{
    					boolean zereoed=true;
    					for(int i=0;i<S.getCodes().length;i++)
    					{
    						if(CMath.s_int(S.getStat(S.getCodes()[i]))!=0)
    						{ zereoed=false; break;}
    					}
    					if(zereoed)
    						R.setStat("ESTATS","");
    					else
    						R.setStat("ESTATS",CMLib.coffeeMaker().getEnvStatsStr(S));
    				}
    			}
    		}
    		else
            {
                mob.tell("(no change)");
                done=true;
            }
        }
	}
	protected void genAState(MOB mob,
	        			  Race R,
	        			  String field,
	        			  String prompt,
	        			  int showNumber,
	        			  int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		CharState S=(CharState)CMClass.getCommon("DefaultCharState"); S.setAllValues(0);
		CMLib.coffeeMaker().setCharState(S,R.getStat(field));
		StringBuffer parts=new StringBuffer("");
		for(int i=0;i<S.getStatCodes().length;i++)
			if(CMath.s_int(S.getStat(S.getStatCodes()[i]))!=0)
				parts.append(CMStrings.capitalizeAndLower(S.getStatCodes()[i])+"("+S.getStat(S.getStatCodes()[i])+") ");
		mob.tell(showNumber+". "+prompt+": "+parts.toString()+".");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
        boolean done=false;
        while((!done)&&(mob.session()!=null)&&(!mob.session().killFlag()))
        {
    		String newName=mob.session().prompt("Enter a stat name\n\r:","");
    		if(newName.length()>0)
    		{
    			String partName=null;
    			for(int i=0;i<S.getStatCodes().length;i++)
    				if(newName.equalsIgnoreCase(S.getStatCodes()[i]))
    				{ partName=S.getStatCodes()[i]; break;}
    			if(partName==null)
    			{
    				StringBuffer str=new StringBuffer("That stat is invalid.  Valid stats include: ");
    				for(int i=0;i<S.getStatCodes().length;i++)
    					str.append(S.getStatCodes()[i]+", ");
    				mob.tell(str.toString().substring(0,str.length()-2)+".");
    			}
    			else
    			{
    				newName=mob.session().prompt("Enter a value\n\r:","");
    				if(newName.length()>0)
    				{
    					S.setStat(partName,newName);
    					boolean zereoed=true;
    					for(int i=0;i<S.getStatCodes().length;i++)
    					{
    						if(CMath.s_int(S.getStat(S.getStatCodes()[i]))!=0)
    						{ zereoed=false; break;}
    					}
    					if(zereoed)
    						R.setStat(field,"");
    					else
    						R.setStat(field,CMLib.coffeeMaker().getCharStateStr(S));
    				}
    				else
    					mob.tell("(no change)");
    			}
    		}
    		else
            {
                mob.tell("(no change)");
                done=true;
            }
        }
	}
	protected void genAStats(MOB mob, Race R, String Field, String FieldName, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
        CharStats S=(CharStats)CMClass.getCommon("DefaultCharStats"); S.setAllValues(0);
		CMLib.coffeeMaker().setCharStats(S,R.getStat(Field));
		StringBuffer parts=new StringBuffer("");
		for(int i=0;i<CharStats.STAT_DESCS.length;i++)
			if(S.getStat(i)!=0)
				parts.append(CMStrings.capitalizeAndLower(CharStats.STAT_DESCS[i])+"("+S.getStat(i)+") ");
		mob.tell(showNumber+". "+FieldName+": "+parts.toString()+".");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
        boolean done=false;
        while((!done)&&(mob.session()!=null)&&(!mob.session().killFlag()))
        {
    		String newName=mob.session().prompt("Enter a stat name\n\r:","");
    		if(newName.length()>0)
    		{
    			int partNum=-1;
    			for(int i=0;i<CharStats.STAT_DESCS.length;i++)
    				if(newName.equalsIgnoreCase(CharStats.STAT_DESCS[i]))
    				{ partNum=i; break;}
    			if(partNum<0)
    			{
    				StringBuffer str=new StringBuffer("That stat is invalid.  Valid stats include: ");
    				for(int i=0;i<CharStats.STAT_DESCS.length;i++)
    					str.append(CharStats.STAT_DESCS[i]+", ");
    				mob.tell(str.toString().substring(0,str.length()-2)+".");
    			}
    			else
    			{
    				newName=mob.session().prompt("Enter a value\n\r:","");
    				if(newName.length()>0)
    				{
    					if(newName.trim().equalsIgnoreCase("0"))
        					S.setStat(partNum,CMath.s_int(newName));
    					else
                        if(partNum==CharStats.STAT_GENDER)
                            S.setStat(partNum,(int)newName.charAt(0));
                        else
        					S.setStat(partNum,CMath.s_int(newName));
    					boolean zereoed=true;
    					for(int i=0;i<CharStats.STAT_DESCS.length;i++)
    					{
    						if(S.getStat(i)!=0)
    						{ zereoed=false; break;}
    					}
    					if(zereoed)
    						R.setStat(Field,"");
    					else
    						R.setStat(Field,CMLib.coffeeMaker().getCharStatsStr(S));
    				}
    				else
    					mob.tell("(no change)");
    			}
    		}
    		else
            {
    			mob.tell("(no change)");
                done=true;
            }
        }
	}

	protected void genEStats(MOB mob, CharClass R, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
        EnvStats S=(EnvStats)CMClass.getCommon("DefaultEnvStats");
        S.setAllValues(0);
		CMLib.coffeeMaker().setEnvStats(S,R.getStat("ESTATS"));
		StringBuffer parts=new StringBuffer("");
		for(int i=0;i<S.getCodes().length;i++)
			if(CMath.s_int(S.getStat(S.getCodes()[i]))!=0)
				parts.append(CMStrings.capitalizeAndLower(S.getCodes()[i])+"("+S.getStat(S.getCodes()[i])+") ");
		mob.tell(showNumber+". EStat Adjustments: "+parts.toString()+".");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
        boolean done=false;
        while((!done)&&(mob.session()!=null)&&(!mob.session().killFlag()))
        {
    		String newName=mob.session().prompt("Enter a stat name\n\r:","");
    		if(newName.length()>0)
    		{
    			String partName=null;
    			for(int i=0;i<S.getCodes().length;i++)
    				if(newName.equalsIgnoreCase(S.getCodes()[i]))
    				{ partName=S.getCodes()[i]; break;}
    			if(partName==null)
    			{
    				StringBuffer str=new StringBuffer("That stat is invalid.  Valid stats include: ");
    				for(int i=0;i<S.getCodes().length;i++)
    					str.append(S.getCodes()[i]+", ");
    				mob.tell(str.toString().substring(0,str.length()-2)+".");
    			}
    			else
    			{
    				boolean checkChange=false;
    				if(partName.equals("DISPOSITION"))
    				{
    					genDisposition(mob,S,0,0);
    					checkChange=true;
    				}
    				else
    				if(partName.equals("SENSES"))
    				{
    					genSensesMask(mob,S,0,0);
    					checkChange=true;
    				}
    				else
    				{
    					newName=mob.session().prompt("Enter a value\n\r:","");
    					if(newName.length()>0)
    					{
    						S.setStat(partName,newName);
    						checkChange=true;
    					}
    					else
    						mob.tell("(no change)");
    				}
    				if(checkChange)
    				{
    					boolean zereoed=true;
    					for(int i=0;i<S.getCodes().length;i++)
    					{
    						if(CMath.s_int(S.getStat(S.getCodes()[i]))!=0)
    						{ zereoed=false; break;}
    					}
    					if(zereoed)
    						R.setStat("ESTATS","");
    					else
    						R.setStat("ESTATS",CMLib.coffeeMaker().getEnvStatsStr(S));
    				}
    			}
    		}
    		else
            {
    			mob.tell("(no change)");
                done=true;
            }
        }
	}
	protected void genAState(MOB mob,
	        			  CharClass R,
	        			  String field,
	        			  String prompt,
	        			  int showNumber,
	        			  int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
        CharState S=(CharState)CMClass.getCommon("DefaultCharState"); S.setAllValues(0);
		CMLib.coffeeMaker().setCharState(S,R.getStat(field));
		StringBuffer parts=new StringBuffer("");
		for(int i=0;i<S.getStatCodes().length;i++)
			if(CMath.s_int(S.getStat(S.getStatCodes()[i]))!=0)
				parts.append(CMStrings.capitalizeAndLower(S.getStatCodes()[i])+"("+S.getStat(S.getStatCodes()[i])+") ");
		mob.tell(showNumber+". "+prompt+": "+parts.toString()+".");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
        boolean done=false;
        while((!done)&&(mob.session()!=null)&&(!mob.session().killFlag()))
        {
    		String newName=mob.session().prompt("Enter a stat name\n\r:","");
    		if(newName.length()>0)
    		{
    			String partName=null;
    			for(int i=0;i<S.getStatCodes().length;i++)
    				if(newName.equalsIgnoreCase(S.getStatCodes()[i]))
    				{ partName=S.getStatCodes()[i]; break;}
    			if(partName==null)
    			{
    				StringBuffer str=new StringBuffer("That stat is invalid.  Valid stats include: ");
    				for(int i=0;i<S.getStatCodes().length;i++)
    					str.append(S.getStatCodes()[i]+", ");
    				mob.tell(str.toString().substring(0,str.length()-2)+".");
    			}
    			else
    			{
    				newName=mob.session().prompt("Enter a value\n\r:","");
    				if(newName.length()>0)
    				{
    					S.setStat(partName,newName);
    					boolean zereoed=true;
    					for(int i=0;i<S.getStatCodes().length;i++)
    					{
    						if(CMath.s_int(S.getStat(S.getStatCodes()[i]))!=0)
    						{ zereoed=false; break;}
    					}
    					if(zereoed)
    						R.setStat(field,"");
    					else
    						R.setStat(field,CMLib.coffeeMaker().getCharStateStr(S));
    				}
    				else
    					mob.tell("(no change)");
    			}
    		}
    		else
            {
    			mob.tell("(no change)");
                done=true;
            }
        }
	}
	protected void genAStats(MOB mob, CharClass R, String Field, String FieldName, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
        CharStats S=(CharStats)CMClass.getCommon("DefaultCharStats"); S.setAllValues(0);
		CMLib.coffeeMaker().setCharStats(S,R.getStat(Field));
		StringBuffer parts=new StringBuffer("");
		for(int i=0;i<CharStats.STAT_DESCS.length;i++)
			if(S.getStat(i)!=0)
				parts.append(CMStrings.capitalizeAndLower(CharStats.STAT_DESCS[i])+"("+S.getStat(i)+") ");
		mob.tell(showNumber+". "+FieldName+": "+parts.toString()+".");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
        boolean done=false;
        while((!done)&&(mob.session()!=null)&&(!mob.session().killFlag()))
        {
    		String newName=mob.session().prompt("Enter a stat name\n\r:","");
    		if(newName.length()>0)
    		{
    			int partNum=-1;
    			for(int i=0;i<CharStats.STAT_DESCS.length;i++)
    				if(newName.equalsIgnoreCase(CharStats.STAT_DESCS[i]))
    				{ partNum=i; break;}
    			if(partNum<0)
    			{
    				StringBuffer str=new StringBuffer("That stat is invalid.  Valid stats include: ");
    				for(int i=0;i<CharStats.STAT_DESCS.length;i++)
    					str.append(CharStats.STAT_DESCS[i]+", ");
    				mob.tell(str.toString().substring(0,str.length()-2)+".");
    			}
    			else
    			{
    				newName=mob.session().prompt("Enter a value\n\r:","");
    				if(newName.length()>0)
    				{
    					S.setStat(partNum,CMath.s_int(newName));
    					boolean zereoed=true;
    					for(int i=0;i<CharStats.STAT_DESCS.length;i++)
    					{
    						if(S.getStat(i)!=0)
    						{ zereoed=false; break;}
    					}
    					if(zereoed)
    						R.setStat(Field,"");
    					else
    						R.setStat(Field,CMLib.coffeeMaker().getCharStatsStr(S));
    				}
    				else
    					mob.tell("(no change)");
    			}
    		}
    		else
            {
    			mob.tell("(no change)");
                done=true;
            }
        }
	}
	protected void genResources(MOB mob, Race E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(true))
		{
			StringBuffer parts=new StringBuffer("");
			int numResources=CMath.s_int(E.getStat("NUMRSC"));
			DVector DV=new DVector(2);
			for(int r=0;r<numResources;r++)
			{
				Item I=CMClass.getItem(E.getStat("GETRSCID"+r));
				if(I!=null)
				{
					I.setMiscText(E.getStat("GETRSCPARM"+r));
					I.recoverEnvStats();
                    boolean done=false;
                    for(int v=0;v<DV.size();v++)
                        if(I.sameAs((Environmental)DV.elementAt(v,1)))
                        { DV.setElementAt(v,2,new Integer(((Integer)DV.elementAt(v,2)).intValue()+1)); done=true; break;}
                    if(!done)
                        DV.addElement(I,new Integer(1));
				}
                else
                    parts.append("Unknown: "+E.getStat("GETRSCID"+r)+", ");
			}
            for(int v=0;v<DV.size();v++)
            {
                Item I=(Item)DV.elementAt(v,1);
                int i=((Integer)DV.elementAt(v,2)).intValue();
                if(i<2)
                    parts.append(I.name()+", ");
                else
                    parts.append(I.name()+" ("+i+"), ");
            }
			if(parts.toString().endsWith(", "))
			{parts.deleteCharAt(parts.length()-1);parts.deleteCharAt(parts.length()-1);}
			mob.tell(showNumber+". Resources: "+parts.toString()+".");
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			String newName=mob.session().prompt("Enter a resource name to remove or\n\rthe word new and an item name to add from your inventory\n\r:","");
			if(newName.length()>0)
			{
				int partNum=-1;
				for(int i=0;i<DV.size();i++)
					if(CMLib.english().containsString(((Item)DV.elementAt(i,1)).name(),newName))
					{ partNum=i; break;}
				boolean updateList=false;
				if(partNum<0)
				{
					if(!newName.toLowerCase().startsWith("new "))
						mob.tell("That is neither an existing resource name, or the word new followed by a valid item name.");
					else
					{
						Item I=mob.fetchCarried(null,newName.substring(4).trim());
						if(I!=null)
						{
							I=(Item)I.copyOf();
                            boolean done=false;
                            for(int v=0;v<DV.size();v++)
                                if(I.sameAs((Environmental)DV.elementAt(v,1)))
                                { DV.setElementAt(v,2,new Integer(((Integer)DV.elementAt(v,2)).intValue()+1)); done=true; break;}
                            if(!done)
                                DV.addElement(I,new Integer(1));
							mob.tell(I.name()+" added.");
							updateList=true;
						}

					}
				}
				else
				{
					Item I=(Item)DV.elementAt(partNum,1);
                    int i=((Integer)DV.elementAt(partNum,2)).intValue();
                    if(i<2)
    					DV.removeElementAt(partNum);
                    else
                        DV.setElementAt(partNum,2,new Integer(i-1));
					mob.tell(I.name()+" removed.");
					updateList=true;
				}
				if(updateList)
				{
                    int dex=0;
                    for(int i=0;i<DV.size();i++)
                        dex+=((Integer)DV.elementAt(i,2)).intValue();
					E.setStat("NUMRSC",""+dex);
                    dex=0;
                    Item I=null;
                    Integer N=null;
					for(int i=0;i<DV.size();i++)
                    {
                        I=(Item)DV.elementAt(i,1);
                        N=(Integer)DV.elementAt(i,2);
                        for(int n=0;n<N.intValue();n++)
    						E.setStat("GETRSCID"+(dex++),I.ID());
                    }
                    dex=0;
					for(int i=0;i<DV.size();i++)
                    {
                        I=(Item)DV.elementAt(i,1);
                        N=(Integer)DV.elementAt(i,2);
                        for(int n=0;n<N.intValue();n++)
                            E.setStat("GETRSCPARM"+(dex++),I.text());
                    }
				}
			}
			else
			{
				mob.tell("(no change)");
				return;
			}
		}
	}
	protected void genOutfit(MOB mob, Race E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(true))
		{
			StringBuffer parts=new StringBuffer("");
			int numResources=CMath.s_int(E.getStat("NUMOFT"));
			Vector V=new Vector();
			for(int v=0;v<numResources;v++)
			{
				Item I=CMClass.getItem(E.getStat("GETOFTID"+v));
				if(I!=null)
				{
					I.setMiscText(E.getStat("GETOFTPARM"+v));
					I.recoverEnvStats();
					parts.append(I.name()+", ");
					V.addElement(I);
				}
			}
			if(parts.toString().endsWith(", "))
			{parts.deleteCharAt(parts.length()-1);parts.deleteCharAt(parts.length()-1);}
			mob.tell(showNumber+". Outfit: "+parts.toString()+".");
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			String newName=mob.session().prompt("Enter an item name to remove or\n\rthe word new and an item name to add from your inventory\n\r:","");
			if(newName.length()>0)
			{
				int partNum=-1;
				for(int i=0;i<V.size();i++)
					if(CMLib.english().containsString(((Item)V.elementAt(i)).name(),newName))
					{ partNum=i; break;}
				boolean updateList=false;
				if(partNum<0)
				{
					if(!newName.toLowerCase().startsWith("new "))
						mob.tell("That is neither an existing item name, or the word new followed by a valid item name.");
					else
					{
						Item I=mob.fetchCarried(null,newName.substring(4).trim());
						if(I!=null)
						{
							I=(Item)I.copyOf();
							V.addElement(I);
							mob.tell(I.name()+" added.");
							updateList=true;
						}

					}
				}
				else
				{
					Item I=(Item)V.elementAt(partNum);
					V.removeElementAt(partNum);
					mob.tell(I.name()+" removed.");
					updateList=true;
				}
				if(updateList)
				{
					E.setStat("NUMOFT","");
					for(int i=0;i<V.size();i++)
						E.setStat("GETOFTID"+i,((Item)V.elementAt(i)).ID());
					for(int i=0;i<V.size();i++)
						E.setStat("GETOFTPARM"+i,((Item)V.elementAt(i)).text());
				}
			}
			else
			{
				mob.tell("(no change)");
				return;
			}
		}
	}
	protected void genOutfit(MOB mob, CharClass E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(true))
		{
			StringBuffer parts=new StringBuffer("");
			int numResources=CMath.s_int(E.getStat("NUMOFT"));
			Vector V=new Vector();
			for(int v=0;v<numResources;v++)
			{
				Item I=CMClass.getItem(E.getStat("GETOFTID"+v));
				if(I!=null)
				{
					I.setMiscText(E.getStat("GETOFTPARM"+v));
					I.recoverEnvStats();
					parts.append(I.name()+", ");
					V.addElement(I);
				}
			}
			if(parts.toString().endsWith(", "))
			{parts.deleteCharAt(parts.length()-1);parts.deleteCharAt(parts.length()-1);}
			mob.tell(showNumber+". Outfit: "+parts.toString()+".");
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			String newName=mob.session().prompt("Enter an item name to remove or\n\rthe word new and an item name to add from your inventory\n\r:","");
			if(newName.length()>0)
			{
				int partNum=-1;
				for(int i=0;i<V.size();i++)
					if(CMLib.english().containsString(((Item)V.elementAt(i)).name(),newName))
					{ partNum=i; break;}
				boolean updateList=false;
				if(partNum<0)
				{
					if(!newName.toLowerCase().startsWith("new "))
						mob.tell("That is neither an existing item name, or the word new followed by a valid item name.");
					else
					{
						Item I=mob.fetchCarried(null,newName.substring(4).trim());
						if(I!=null)
						{
							I=(Item)I.copyOf();
							V.addElement(I);
							mob.tell(I.name()+" added.");
							updateList=true;
						}

					}
				}
				else
				{
					Item I=(Item)V.elementAt(partNum);
					V.removeElementAt(partNum);
					mob.tell(I.name()+" removed.");
					updateList=true;
				}
				if(updateList)
				{
					E.setStat("NUMOFT","");
					for(int i=0;i<V.size();i++)
						E.setStat("GETOFTID"+i,((Item)V.elementAt(i)).ID());
					for(int i=0;i<V.size();i++)
						E.setStat("GETOFTPARM"+i,((Item)V.elementAt(i)).text());
				}
			}
			else
			{
				mob.tell("(no change)");
				return;
			}
		}
	}
	protected void genWeapon(MOB mob, Race E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		StringBuffer parts=new StringBuffer("");
		Item I=CMClass.getItem(E.getStat("WEAPONCLASS"));
		if(I!=null)
		{
			I.setMiscText(E.getStat("WEAPONXML"));
			I.recoverEnvStats();
			parts.append(I.name());
		}
		mob.tell(showNumber+". Natural Weapon: "+parts.toString()+".");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		String newName=mob.session().prompt("Enter a weapon name from your inventory to change, or 'null' for human\n\r:","");
		if(newName.equalsIgnoreCase("null"))
		{
			E.setStat("WEAPONCLASS","");
			mob.tell("Human weapons set.");
		}
		else
		if(newName.length()>0)
		{
			I=mob.fetchCarried(null,newName);
			if(I==null)
			{
				mob.tell("'"+newName+"' is not in your inventory.");
				mob.tell("(no change)");
				return;
			}
			I=(Item)I.copyOf();
			E.setStat("WEAPONCLASS",I.ID());
			E.setStat("WEAPONXML",I.text());
		}
		else
		{
			mob.tell("(no change)");
			return;
		}
	}

    protected void modifyDField(DVector fields, String fieldName, String value)
    {
        int x=fields.indexOf(fieldName.toUpperCase());
        if(x<0) return;
        fields.setElementAt(x,2,value);
    }
    
	protected void genAgingChart(MOB mob, Race E, int showNumber, int showFlag)
	throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;

		mob.tell(showNumber+". Aging Chart: "+CMParms.toStringList(E.getAgingChart())+".");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(true))
		{
			String newName=mob.session().prompt("Enter a comma-delimited list of 9 numbers, running from infant -> ancient\n\r:","");
			if(newName.length()==0)
			{
				mob.tell("(no change)");
				return;
			}
			Vector V=CMParms.parseCommas(newName,true);
			if(V.size()==9)
			{
			    int highest=-1;
			    boolean cont=false;
			    for(int i=0;i<V.size();i++)
			    {
			        if(CMath.s_int((String)V.elementAt(i))<highest)
			        {
			            mob.tell("Entry "+((String)V.elementAt(i))+" is out of place.");
			            cont=true;
			            break;
			        }
			        highest=CMath.s_int((String)V.elementAt(i));
			    }
			    if(cont) continue;
			    E.setStat("AGING",newName);
			    break;
			}
		}
	}

	protected void genClassFlags(MOB mob, CharClass E, int showNumber, int showFlag)
	throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber))
		    return;

		int flags=CMath.s_int(E.getStat("DISFLAGS"));
		StringBuffer sets=new StringBuffer("");
	    if(CMath.bset(flags,CharClass.GENFLAG_NORACE))
		    sets.append("Raceless ");
	    if(CMath.bset(flags,CharClass.GENFLAG_NOLEVELS))
		    sets.append("Leveless ");
	    if(CMath.bset(flags,CharClass.GENFLAG_NOEXP))
		    sets.append("Expless ");

		mob.tell(showNumber+". Extra CharClass Flags: "+sets.toString()+".");
		if((showFlag!=showNumber)&&(showFlag>-999))
		    return;
		String newName=mob.session().prompt("Enter: 1) Classless, 2) Leveless, 3) Expless\n\r:","");
		switch(CMath.s_int(newName))
		{
		case 1:
		    if(CMath.bset(flags,CharClass.GENFLAG_NORACE))
		        flags=CMath.unsetb(flags,CharClass.GENFLAG_NORACE);
		    else
		        flags=flags|CharClass.GENFLAG_NORACE;
		    break;
		case 2:
		    if(CMath.bset(flags,CharClass.GENFLAG_NOLEVELS))
		        flags=CMath.unsetb(flags,CharClass.GENFLAG_NOLEVELS);
		    else
		        flags=flags|CharClass.GENFLAG_NOLEVELS;
		    break;
		case 3:
		    if(CMath.bset(flags,CharClass.GENFLAG_NOEXP))
		        flags=CMath.unsetb(flags,CharClass.GENFLAG_NOEXP);
		    else
		        flags=flags|CharClass.GENFLAG_NOEXP;
		    break;
		default:
			mob.tell("(no change)");
			break;
		}
		E.setStat("DISFLAGS",""+flags);
	}

	protected void genRacialAbilities(MOB mob, Race E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(true))
		{
			StringBuffer parts=new StringBuffer("");
			int numResources=CMath.s_int(E.getStat("NUMRABLE"));
			Vector ables=new Vector();
			Vector data=new Vector();
			for(int v=0;v<numResources;v++)
			{
				Ability A=CMClass.getAbility(E.getStat("GETRABLE"+v));
				if(A!=null)
				{
					parts.append("("+A.ID()+"/"+E.getStat("GETRABLELVL"+v)+"/"+E.getStat("GETRABLEQUAL"+v)+"/"+E.getStat("GETRABLEPROF"+v)+"), ");
					ables.addElement(A);
					data.addElement(A.ID()+";"+E.getStat("GETRABLELVL"+v)+";"+E.getStat("GETRABLEQUAL"+v)+";"+E.getStat("GETRABLEPROF"+v));
				}
			}
			if(parts.toString().endsWith(", "))
			{parts.deleteCharAt(parts.length()-1);parts.deleteCharAt(parts.length()-1);}
			mob.tell(showNumber+". Racial Abilities: "+parts.toString()+".");
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			String newName=mob.session().prompt("Enter an ability name to add or remove (?)\n\r:","");
			if(newName.equalsIgnoreCase("?"))
				mob.tell(CMLib.lister().reallyList(CMClass.abilities(),-1).toString());
			else
			if(newName.length()>0)
			{
				int partNum=-1;
				for(int i=0;i<ables.size();i++)
					if(CMLib.english().containsString(((Ability)ables.elementAt(i)).ID(),newName))
					{ partNum=i; break;}
				boolean updateList=false;
				if(partNum<0)
				{
					Ability A=CMClass.getAbility(newName);
					if(A==null)
						mob.tell("That is neither an existing ability name, nor a valid one to add.  Use ? for a list.");
					else
					if(A.isAutoInvoked())
						mob.tell("'"+A.name()+"' cannot be named, as it is autoinvoked.");
					else
					if((A.triggerStrings()==null)||(A.triggerStrings().length==0))
						mob.tell("'"+A.name()+"' cannot be named, as it has no trigger/command words.");
					else
					{
						StringBuffer str=new StringBuffer(A.ID()+";");
						String level=mob.session().prompt("Enter the level of this skill (1): ","1");
						str.append((""+CMath.s_int(level))+";");
						if(mob.session().confirm("Is this skill automatically gained (Y/n)?","Y"))
							str.append("false;");
						else
							str.append("true;");
						String prof=mob.session().prompt("Enter the (perm) proficiency level (100): ","100");
						str.append((""+CMath.s_int(prof)));
						data.addElement(str.toString());
						ables.addElement(A);
						mob.tell(A.name()+" added.");
						updateList=true;
					}
				}
				else
				{
					Ability A=(Ability)ables.elementAt(partNum);
					ables.removeElementAt(partNum);
					data.removeElementAt(partNum);
					updateList=true;
					mob.tell(A.name()+" removed.");
				}
				if(updateList)
				{
					if(data.size()>0)
						E.setStat("NUMRABLE",""+data.size());
					else
						E.setStat("NUMRABLE","");
					for(int i=0;i<data.size();i++)
					{
						Vector V=CMParms.parseSemicolons((String)data.elementAt(i),false);
						E.setStat("GETRABLE"+i,((String)V.elementAt(0)));
						E.setStat("GETRABLELVL"+i,((String)V.elementAt(1)));
						E.setStat("GETRABLEQUAL"+i,((String)V.elementAt(2)));
						E.setStat("GETRABLEPROF"+i,((String)V.elementAt(3)));
					}
				}
			}
			else
			{
				mob.tell("(no change)");
				return;
			}
		}
	}
	protected void genRacialEffects(MOB mob, Race E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(true))
		{
			StringBuffer parts=new StringBuffer("");
			int numResources=CMath.s_int(E.getStat("NUMREFF"));
			Vector ables=new Vector();
			Vector data=new Vector();
			for(int v=0;v<numResources;v++)
			{
				Ability A=CMClass.getAbility(E.getStat("GETREFF"+v));
				if(A!=null)
				{
					parts.append("("+A.ID()+"/"+E.getStat("GETREFFLVL"+v)+"/"+E.getStat("GETREFFPARM"+v)+"), ");
					ables.addElement(A);
					data.addElement(A.ID()+"~"+E.getStat("GETREFFLVL"+v)+"~"+E.getStat("GETREFFPARM"+v));
				}
			}
			if(parts.toString().endsWith(", "))
			{parts.deleteCharAt(parts.length()-1);parts.deleteCharAt(parts.length()-1);}
			mob.tell(showNumber+". Racial Effects: "+parts.toString()+".");
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			String newName=mob.session().prompt("Enter an effect name to add or remove\n\r:","");
			if(newName.equalsIgnoreCase("?"))
				mob.tell(CMLib.lister().reallyList(CMClass.abilities(),-1).toString());
			else
			if(newName.length()>0)
			{
				int partNum=-1;
				for(int i=0;i<ables.size();i++)
					if(CMLib.english().containsString(((Ability)ables.elementAt(i)).ID(),newName))
					{ partNum=i; break;}
				boolean updateList=false;
				if(partNum<0)
				{
					Ability A=CMClass.getAbility(newName);
					if(A==null)
						mob.tell("That is neither an existing effect name, nor a valid one to add.  Use ? for a list.");
					else
					{
						StringBuffer str=new StringBuffer(A.ID()+"~");
						String level=mob.session().prompt("Enter the level to gain this effect (1): ","1");
						str.append((""+CMath.s_int(level))+"~");
						String prof=mob.session().prompt("Enter any parameters: ","");
						str.append(""+prof);
						data.addElement(str.toString());
						ables.addElement(A);
						mob.tell(A.name()+" added.");
						updateList=true;
					}
				}
				else
				{
					Ability A=(Ability)ables.elementAt(partNum);
					ables.removeElementAt(partNum);
					data.removeElementAt(partNum);
					updateList=true;
					mob.tell(A.name()+" removed.");
				}
				if(updateList)
				{
					if(data.size()>0)
						E.setStat("NUMREFF",""+data.size());
					else
						E.setStat("NUMREFF","");
					for(int i=0;i<data.size();i++)
					{
						Vector V=CMParms.parseSquiggleDelimited((String)data.elementAt(i),false);
						E.setStat("GETREFF"+i,((String)V.elementAt(0)));
						E.setStat("GETREFFLVL"+i,((String)V.elementAt(1)));
						E.setStat("GETREFFPARM"+i,((String)V.elementAt(2)));
					}
				}
			}
			else
			{
				mob.tell("(no change)");
				return;
			}
		}
	}
    
    protected DVector genClassAbleMod(MOB mob, DVector sets, String ableID, int origLevelIndex, int origAbleIndex)
    throws IOException
    {
        
        Integer level=null;
        if(origLevelIndex>=0)
        {
            if(mob.session().confirm("Enter Y to DELETE, or N to modify (y/N)?","N"))
            {
                DVector set=(DVector)sets.elementAt(origLevelIndex,2);
                set.removeElementAt(origAbleIndex);
                return null;
            }
            level=(Integer)sets.elementAt(origLevelIndex,1);
        }
        else
            level=new Integer(1);
        level=new Integer(CMath.s_int(mob.session().prompt("Enter the level of this skill ("+level+"): ",""+level)));
        if(level.intValue()<=0)
        {
            mob.tell("Aborted.");
            return null;
        }
        Integer prof=null;
        Boolean secret=null;
        Boolean gained=null;
        String parms="";
        if(origLevelIndex<0)
        {
            prof=new Integer(0);
            secret=new Boolean(false);
            gained=new Boolean(false);
            parms="";
        }
        else
        {
            DVector set=(DVector)sets.elementAt(origLevelIndex,2);
            gained=(Boolean)set.elementAt(origAbleIndex,2);
            prof=(Integer)set.elementAt(origAbleIndex,3);
            secret=(Boolean)set.elementAt(origAbleIndex,4);
            parms=(String)set.elementAt(origAbleIndex,5);
            set.removeElementAt(origAbleIndex);
            origAbleIndex=-1;
        }
        
        int newlevelIndex=sets.indexOf(level);
        DVector levelSet=null;
        if(newlevelIndex<0)
        {
            newlevelIndex=sets.size();
            levelSet=new DVector(5);
            sets.addElement(level,levelSet);
        }
        else
            levelSet=(DVector)sets.elementAt(newlevelIndex,2);
        prof=new Integer(CMath.s_int(mob.session().prompt("Enter the (default) proficiency level ("+prof.toString()+"): ",prof.toString())));
        gained=new Boolean(mob.session().confirm("Is this skill automatically gained (Y/N)?",""+gained.toString()));
        secret=new Boolean(mob.session().confirm("Is this skill secret (N/y)?",secret.toString()));
        parms=mob.session().prompt("Enter any properties ("+parms+"): ",parms);
        levelSet.addElement(ableID,gained,prof,secret,parms);
        return sets;
    }
    
	protected void genClassAbilities(MOB mob, CharClass E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
        if((showFlag!=showNumber)&&(showFlag>-999))
        {
            mob.tell(showNumber+". Class Abilities: [...].");
            return;
        }
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(true))
		{
			StringBuffer parts=new StringBuffer("");
			int numAbles=CMath.s_int(E.getStat("NUMCABLE"));
            DVector levelSets=new DVector(2);
            int maxAbledLevel=Integer.MIN_VALUE;
			for(int v=0;v<numAbles;v++)
			{
				Ability A=CMClass.getAbility(E.getStat("GETCABLE"+v));
				if(A!=null)
				{
                    Boolean gain=new Boolean(CMath.s_bool(E.getStat("GETCABLEGAIN"+v)));
                    Integer defProf=new Integer(CMath.s_int(E.getStat("GETCABLEPROF"+v)));
                    Integer lvl=new Integer(CMath.s_int(E.getStat("GETCABLELVL"+v)));
                    Boolean secret=new Boolean(CMath.s_bool(E.getStat("GETCABLESECR"+v)));
                    String parm=E.getStat("GETCABLEPARM"+v);
                    int lvlIndex=levelSets.indexOf(lvl);
                    DVector set=null;
                    if(lvlIndex<0)
                    {
                        set=new DVector(5);
                        levelSets.addElement(lvl,set);
                        if(lvl.intValue()>maxAbledLevel)
                            maxAbledLevel=lvl.intValue();
                    }
                    else
                        set=(DVector)levelSets.elementAt(lvlIndex,2);
                    set.addElement(A.ID(),gain,defProf,secret,parm);
				}
			}
            String header=showNumber+". Class Abilities: ";
            String spaces=CMStrings.repeat(" ",2+(""+showNumber).length());
            parts.append("\n\r");
            parts.append(spaces+CMStrings.padRight("Lvl",3)+" "
                               +CMStrings.padRight("Skill",25)+" "
                               +CMStrings.padRight("Proff",5)+" "
                               +CMStrings.padRight("Gain",5)+" "
                               +CMStrings.padRight("Secret",6)+" "
                               +CMStrings.padRight("Parm",20)+"\n\r"
                               );
            for(int i=0;i<=maxAbledLevel;i++)
            {
                int index=levelSets.indexOf(new Integer(i));
                if(index<0) continue;
                DVector set=(DVector)levelSets.elementAt(index,2);
                for(int s=0;s<set.size();s++)
                {
                    String ID=(String)set.elementAt(s,1);
                    Boolean gain=(Boolean)set.elementAt(s,2);
                    Integer defProf=(Integer)set.elementAt(s,3);
                    Boolean secret=(Boolean)set.elementAt(s,4);
                    String parm=(String)set.elementAt(s,5);
                    parts.append(spaces+CMStrings.padRight(""+i,3)+" "
                                        +CMStrings.padRight(""+ID,25)+" "
                                        +CMStrings.padRight(defProf.toString(),5)+" "
                                        +CMStrings.padRight(gain.toString(),5)+" "
                                        +CMStrings.padRight(secret.toString(),6)+" "
                                        +CMStrings.padRight(parm,20)+"\n\r"
                                        );
                }
            }
                
			mob.session().wraplessPrintln(header+parts.toString());
			String newName=mob.session().prompt("Enter an ability name to add or remove (?)\n\r:","");
			if(newName.equalsIgnoreCase("?"))
				mob.tell(CMLib.lister().reallyList(CMClass.abilities(),-1).toString());
			else
			if(newName.length()>0)
			{
				int lvlIndex=-1;
                int ableIndex=-1;
                DVector myLevelSet=null;
                for(int s=0;s<levelSets.size();s++)
                {
                    DVector lvls=(DVector)levelSets.elementAt(s,2);
                    for(int l=0;l<lvls.size();l++)
                        if(CMLib.english().containsString(((String)lvls.elementAt(l,1)),newName))
                        {
                            lvlIndex=s;
                            ableIndex=l;
                            myLevelSet=lvls;
                            break;
                        }
                    if(lvlIndex>=0) break;
                }
				boolean updateList=false;
				if(ableIndex<0)
				{
					Ability A=CMClass.getAbility(newName);
					if(A==null)
						mob.tell("That is neither an existing ability name, nor a valid one to add.  Use ? for a list.");
					else
					{
                        // add new one here
                        if(genClassAbleMod(mob,levelSets,A.ID(),-1,-1)!=null)
                        {
    						mob.tell(A.ID()+" added.");
    						updateList=true;
                            numAbles++;
                        }
					}
				}
				else
				{
                    String aID=(String)myLevelSet.elementAt(ableIndex,1);
                    if(genClassAbleMod(mob,levelSets,aID,lvlIndex,ableIndex)!=null)
                        mob.tell(aID+" modified.");
                    else
                    {
                        mob.tell(aID+" removed.");
                        numAbles--;
                    }
                    
					updateList=true;
				}
				if(updateList)
				{
					if(numAbles>0)
						E.setStat("NUMCABLE",""+numAbles);
					else
						E.setStat("NUMCABLE","");
                    int dex=0;
                    for(int s=0;s<levelSets.size();s++)
                    {
                        Integer lvl=(Integer)levelSets.elementAt(s,1);
                        DVector lvls=(DVector)levelSets.elementAt(s,2);
                        for(int l=0;l<lvls.size();l++)
                        {
    						E.setStat("GETCABLE"+dex,lvls.elementAt(l,1).toString());
    						E.setStat("GETCABLELVL"+dex,lvl.toString());
                            E.setStat("GETCABLEGAIN"+dex,lvls.elementAt(l,2).toString());
    						E.setStat("GETCABLEPROF"+dex,lvls.elementAt(l,3).toString());
    						E.setStat("GETCABLESECR"+dex,lvls.elementAt(l,4).toString());
    						E.setStat("GETCABLEPARM"+dex,lvls.elementAt(l,5).toString());
                            dex++;
                        }
					}
				}
			}
			else
			{
				mob.tell("(no change)");
				return;
			}
		}
	}
	protected void genCulturalAbilities(MOB mob, Race E, int showNumber, int showFlag)
		throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(true))
		{
			StringBuffer parts=new StringBuffer("");
			int numResources=CMath.s_int(E.getStat("NUMCABLE"));
			Vector ables=new Vector();
			Vector data=new Vector();
			for(int v=0;v<numResources;v++)
			{
				Ability A=CMClass.getAbility(E.getStat("GETCABLE"+v));
				if(A!=null)
				{
					parts.append("("+A.ID()+"/"+E.getStat("GETCABLEPROF"+v)+"), ");
					ables.addElement(A);
					data.addElement(A.ID()+";"+E.getStat("GETCABLEPROF"+v));
				}
			}
			if(parts.toString().endsWith(", "))
			{parts.deleteCharAt(parts.length()-1);parts.deleteCharAt(parts.length()-1);}
			mob.tell(showNumber+". Cultural Abilities: "+parts.toString()+".");
			if((showFlag!=showNumber)&&(showFlag>-999)) return;
			String newName=mob.session().prompt("Enter an ability name to add or remove (?)\n\r:","");
			if(newName.equalsIgnoreCase("?"))
				mob.tell(CMLib.lister().reallyList(CMClass.abilities(),-1).toString());
			else
			if(newName.length()>0)
			{
				int partNum=-1;
				for(int i=0;i<ables.size();i++)
					if(CMLib.english().containsString(((Ability)ables.elementAt(i)).ID(),newName))
					{ partNum=i; break;}
				boolean updateList=false;
				if(partNum<0)
				{
					Ability A=CMClass.getAbility(newName);
					if(A==null)
						mob.tell("That is neither an existing ability name, nor a valid one to add.  Use ? for a list.");
					else
					{
						StringBuffer str=new StringBuffer(A.ID()+";");
						String prof=mob.session().prompt("Enter the default proficiency level (100): ","100");
						str.append((""+CMath.s_int(prof)));
						data.addElement(str.toString());
						ables.addElement(A);
						mob.tell(A.name()+" added.");
						updateList=true;
					}
				}
				else
				{
					Ability A=(Ability)ables.elementAt(partNum);
					ables.removeElementAt(partNum);
					data.removeElementAt(partNum);
					updateList=true;
					mob.tell(A.name()+" removed.");
				}
				if(updateList)
				{
					if(data.size()>0)
						E.setStat("NUMCABLE",""+data.size());
					else
						E.setStat("NUMCABLE","");
					for(int i=0;i<data.size();i++)
					{
						Vector V=CMParms.parseSemicolons((String)data.elementAt(i),false);
						E.setStat("GETCABLE"+i,((String)V.elementAt(0)));
						E.setStat("GETCABLEPROF"+i,((String)V.elementAt(1)));
					}
				}
			}
			else
			{
				mob.tell("(no change)");
				return;
			}
		}
	}
	protected void modifyGenClass(MOB mob, CharClass me)
		throws IOException
	{
		if(mob.isMonster())
			return;
		boolean ok=false;
		int showFlag=-1;
		if(CMProps.getIntVar(CMProps.SYSTEMI_EDITORTYPE)>0)
			showFlag=-999;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!ok))
		{
			int showNumber=0;

            genInt(mob,me,++showNumber,showFlag,"Number of Class Names: ","NUMNAME");
            int numNames=CMath.s_int(me.getStat("NUMNAME"));
            if(numNames<=1)
    			genText(mob,me,++showNumber,showFlag,"Class Name","NAME0");
            else
            for(int i=0;i<numNames;i++)
            {
                genText(mob,me,++showNumber,showFlag,"Class Name #"+i+": ","NAME"+i);
                if(i>0)
                while(!mob.session().killFlag())
                {
                    int oldNameLevel=CMath.s_int(me.getStat("NAMELEVEL"+i));
                    genInt(mob,me,++showNumber,showFlag,"Class Name #"+i+" class level: ","NAMELEVEL"+i);
                    int previousNameLevel=CMath.s_int(me.getStat("NAMELEVEL"+(i-1)));
                    int newNameLevel=CMath.s_int(me.getStat("NAMELEVEL"+i));
                    if((oldNameLevel!=newNameLevel)&&(newNameLevel<(previousNameLevel+1)))
                    {
                        mob.tell("This level may not be less than "+(previousNameLevel+1)+".");
                        me.setStat("NAMELEVEL"+i,""+(previousNameLevel+1));
                        showNumber--;
                    }
                    else
                        break;
                }
            }
			genText(mob,me,++showNumber,showFlag,"Base Class","BASE");
            genClassAvailability(mob,me,++showNumber,showFlag);
			genInt(mob,me,++showNumber,showFlag,"HP Con Divisor","HPDIV");
			genInt(mob,me,++showNumber,showFlag,"HP Die","HPDICE");
			genInt(mob,me,++showNumber,showFlag,"HP #Dice","HPDIE");
			genInt(mob,me,++showNumber,showFlag,"Mana Divisor","MANADIV");
			genInt(mob,me,++showNumber,showFlag,"Mana #Dice","MANADICE");
			genInt(mob,me,++showNumber,showFlag,"Mana Die","MANADIE");
			genInt(mob,me,++showNumber,showFlag,"Prac/Level","LVLPRAC");
			genInt(mob,me,++showNumber,showFlag,"Attack/Level","LVLATT");
			genAttackAttribute(mob,me,++showNumber,showFlag,"Attack Attribute","ATTATT");
			genInt(mob,me,++showNumber,showFlag,"Practices/1stLvl","FSTPRAC");
			genInt(mob,me,++showNumber,showFlag,"Trains/1stLvl","FSTTRAN");
			genInt(mob,me,++showNumber,showFlag,"Levels/Dmg Pt","LVLDAM");
			genInt(mob,me,++showNumber,showFlag,"Moves/Level","LVLMOVE");
			genArmorCode(mob,me,++showNumber,showFlag,"Armor Restr.","ARMOR");
            
            int armorMinorCode=CMath.s_int(me.getStat("ARMORMINOR"));
            boolean newSpells=CMLib.english().promptBool(mob,armorMinorCode>0,++showNumber,showFlag,"Armor restricts only spells");
            me.setStat("ARMORMINOR",""+(newSpells?CMMsg.TYP_CAST_SPELL:-1));
            
			genText(mob,me,++showNumber,showFlag,"Limitations","STRLMT");
			genText(mob,me,++showNumber,showFlag,"Bonuses","STRBON");
			genQualifications(mob,me,++showNumber,showFlag,"Qualifications","QUAL");
			genEStats(mob,me,++showNumber,showFlag);
			genAStats(mob,me,"ASTATS","CharStat Adjustments",++showNumber,showFlag);
			genAStats(mob,me,"CSTATS","CharStat Settings",++showNumber,showFlag);
			genAState(mob,me,"ASTATE","CharState Adjustments",++showNumber,showFlag);
			genAState(mob,me,"STARTASTATE","New Player CharState Adj.",++showNumber,showFlag);
			genClassFlags(mob,me,++showNumber,showFlag);
			genWeaponRestr(mob,me,++showNumber,showFlag,"Weapon Restr.","NUMWEP","GETWEP");
            genWeaponMaterials(mob,me,++showNumber,showFlag,"Weapon Materials","NUMWMAT","GETWMAT");
			genOutfit(mob,me,++showNumber,showFlag);
            genClassBuddy(mob,me,++showNumber,showFlag,"Stat-Modifying Class","STATCLASS");
            genClassBuddy(mob,me,++showNumber,showFlag,"Special Events Class","EVENTCLASS");
			genClassAbilities(mob,me,++showNumber,showFlag);
            genInt(mob,me,++showNumber,showFlag,"Number of Security Code Sets: ","NUMSSET");
            int numGroups=CMath.s_int(me.getStat("NUMSSET"));
            for(int i=0;i<numGroups;i++)
            {
                genText(mob,me,++showNumber,showFlag,"Security Codes in Set #"+i,"SSET"+i);
                while(!mob.session().killFlag())
                {
                    int oldGroupLevel=CMath.s_int(me.getStat("SSETLEVEL"+i));
                    genInt(mob,me,++showNumber,showFlag,"Class Level for Security Set #"+i+": ","SSETLEVEL"+i);
                    int previousGroupLevel=CMath.s_int(me.getStat("SSETLEVEL"+(i-1)));
                    int newGroupLevel=CMath.s_int(me.getStat("SSETLEVEL"+i));
                    if((oldGroupLevel!=newGroupLevel)
                    &&(i>0)
                    &&(newGroupLevel<(previousGroupLevel+1)))
                    {
                        mob.tell("This level may not be less than "+(previousGroupLevel+1)+".");
                        me.setStat("SSETLEVEL"+i,""+(previousGroupLevel+1));
                        showNumber--;
                    }
                    else
                        break;
                }
            }

			if(showFlag<-900){ ok=true; break;}
			if(showFlag>0){ showFlag=-1; continue;}
			showFlag=CMath.s_int(mob.session().prompt("Edit which? ",""));
			if(showFlag<=0)
			{
				showFlag=-1;
				ok=true;
			}
		}
	}

	protected void modifyGenAbility(MOB mob, Ability me)
	throws IOException
	{
		if(mob.isMonster())
			return;
		boolean ok=false;
		int showFlag=-1;
		if(CMProps.getIntVar(CMProps.SYSTEMI_EDITORTYPE)>0)
			showFlag=-999;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!ok))
		{
			int showNumber=0;
			// id is bad to change.. make them delete it.
		    //genText(mob,me,null,++showNumber,showFlag,"Enter the class","CLASS");
		    genText(mob,me,null,++showNumber,showFlag,"Enter an ability name to add or remove (?)\n\r:","NAME");
		    genText(mob,me,CMParms.toStringList(Ability.ACODE_DESCS)+","+CMParms.toStringList(Ability.DOMAIN_DESCS),++showNumber,showFlag,"Type, Domain (?)","CLASSIFICATION");
		    genText(mob,me,null,++showNumber,showFlag,"Command Words (comma sep)","TRIGSTR");
		    genText(mob,me,CMParms.toStringList(Ability.RANGE_CHOICES),++showNumber,showFlag,"Minimum Range (?)","MINRANGE");
		    genText(mob,me,CMParms.toStringList(Ability.RANGE_CHOICES),++showNumber,showFlag,"Maximum Range (?)","MAXRANGE");
		    genText(mob,me,null,++showNumber,showFlag,"Affect String","DISPLAY");
		    genBool(mob,me,++showNumber,showFlag,"Is Auto-invoking","AUTOINVOKE");
		    genText(mob,me,"0,"+CMParms.toStringList(Ability.FLAG_DESCS),++showNumber,showFlag,"Skill Flags (comma sep) (?)","FLAGS");
		    genInt(mob,me,"-1,x,"+Integer.MAX_VALUE+","+Integer.MAX_VALUE+"-(1 to 100)",++showNumber,showFlag,"Override Cost (?)","OVERRIDEMANA");
		    genText(mob,me,CMParms.toStringList(Ability.USAGE_DESCS),++showNumber,showFlag,"Cost Type (?)","USAGEMASK");
		    genText(mob,me,"0,"+CMParms.toStringList(Ability.CAN_DESCS),++showNumber,showFlag,"Can Affect (?)","CANAFFECTMASK");
		    genText(mob,me,"0,"+CMParms.toStringList(Ability.CAN_DESCS),++showNumber,showFlag,"Can Target (?)","CANTARGETMASK");
		    genText(mob,me,CMParms.toStringList(Ability.QUALITY_DESCS),++showNumber,showFlag,"Quality Code (?)","QUALITY");
		    genText(mob,me,"The parameters for this field are LIKE the parameters for this property:\n\r\n\r"+
                    CMLib.help().getHelpText("Prop_HereAdjuster",mob,true).toString(),++showNumber,showFlag,"Affect Adjustments (?)","HERESTATS");
		    genText(mob,me,CMLib.masking().maskHelp("\n","disallow"),++showNumber,showFlag,"Caster Mask (?)","CASTMASK");
		    genText(mob,me,CMLib.help().getHelpText("Scriptable",mob,true).toString(),++showNumber,showFlag,"Scriptable Parm (?)","SCRIPT");
		    genText(mob,me,CMLib.masking().maskHelp("\n","disallow"),++showNumber,showFlag,"Target Mask (?)","TARGETMASK");
		    genText(mob,me,null,++showNumber,showFlag,"Fizzle Message","FIZZLEMSG");
		    genText(mob,me,null,++showNumber,showFlag,"Auto-Cast Message","AUTOCASTMSG");
		    genText(mob,me,null,++showNumber,showFlag,"Normal-Cast Message","CASTMSG");
		    genText(mob,me,null,++showNumber,showFlag,"Post-Cast Message","POSTCASTMSG");
		    genText(mob,me,CMParms.toStringList(CMMsg.TYPE_DESCS),++showNumber,showFlag,"Attack-Type (?)","ATTACKCODE");
            genText(mob,me,"The parameters for this field are LIKE the parameters for this property:\n\r\n\r"+
                    CMLib.help().getHelpText("Prop_HereSpellCast",mob,true).toString(),++showNumber,showFlag,"Silent affects (?)","POSTCASTAFFECT");
            genText(mob,me,"The parameters for this field are LIKE the parameters for this property:\n\r\n\r"+
                    CMLib.help().getHelpText("Prop_HereSpellCast",mob,true).toString(),++showNumber,showFlag,"Extra castings (?)","POSTCASTABILITY");
            genText(mob,me,"Enter a damage or healing formula. Use +-*/()?. @x1=caster level, @x2=target level.  Formula evaluates >0 for damage, <0 for healing. Requires Can Target!",++showNumber,showFlag,"Damage/Healing Formula (?)","POSTCASTDAMAGE");
		    
			if(showFlag<-900){ ok=true; break;}
			if(showFlag>0){ showFlag=-1; continue;}
			showFlag=CMath.s_int(mob.session().prompt("Edit which? ",""));
			if(showFlag<=0)
			{
				showFlag=-1;
				ok=true;
			}
		}
	}

    boolean genText(MOB mob, DVector set, String[] choices, String help, int showNumber, int showFlag, String FieldDisp, String Field)
    throws IOException
    {
        int setDex=set.indexOf(Field);
        if(((showFlag>0)&&(showFlag!=showNumber))||(setDex<0)) return true;
        mob.tell(showNumber+". "+FieldDisp+": '"+((String)set.elementAt(setDex,2)+"'."));
        if((showFlag!=showNumber)&&(showFlag>-999)) return true;
        String newName=mob.session().prompt("Enter a new one\n\r:","");
        if(newName.trim().length()==0)
        {
            mob.tell("(no change)");
            return false;
        }
        if((newName.equalsIgnoreCase("?"))&&(help!=null))
        {
            if((mob.session()==null)||(mob.session().killFlag()))
                return false;
            mob.tell(help);
            return genText(mob,set,choices,help,showNumber,showFlag,FieldDisp,Field);
        }
        if(newName.equalsIgnoreCase("null")) newName="";
        if((choices==null)||(choices.length==0))
        {
            set.setElementAt(setDex,2,newName);
            return true;
        }
        boolean found=false;
        for(int s=0;s<choices.length;s++)
        {
            if(newName.equalsIgnoreCase(choices[s]))
            { newName=choices[s]; found=true; break;}
        }
        if(!found)
        {
            if((mob.session()==null)||(mob.session().killFlag()))
                return false;
            mob.tell(help);
            return genText(mob,set,choices,help,showNumber,showFlag,FieldDisp,Field);
        }
        set.setElementAt(setDex,2,newName);
        return true;
    }
    
    protected boolean modifyComponent(MOB mob, DVector components, int componentIndex)
    throws IOException
    {
        DVector decoded=CMLib.ableMapper().getAbilityComponentDecodedDVector(components,componentIndex);
        if(mob.isMonster()) return true;
        boolean ok=false;
        int showFlag=-1;
        if(CMProps.getIntVar(CMProps.SYSTEMI_EDITORTYPE)>0)
            showFlag=-999;
        String choices="Your choices are: ";
        String allComponents=CMParms.toStringList(RawMaterial.MATERIAL_DESCS)+","+CMParms.toStringList(RawMaterial.RESOURCE_DESCS);
        while((mob.session()!=null)&&(!mob.session().killFlag())&&(!ok))
        {
            int showNumber=0;
            genText(mob,decoded,(new String[]{"&&","||","X"}),choices+" &&, ||, X",++showNumber,showFlag,"Conjunction (X Deletes) (?)","ANDOR");
            if(((String)decoded.elementAt(0,2)).equalsIgnoreCase("X")) return false;
            genText(mob,decoded,(new String[]{"INVENTORY","HELD","WORN"}),choices+" INVENTORY, HELD, WORN",++showNumber,showFlag,"Component position (?)","DISPOSITION");
            genText(mob,decoded,(new String[]{"KEPT","CONSUMED"}),choices+" KEPT, CONSUMED",++showNumber,showFlag,"Component fate (?)","FATE");
            genText(mob,decoded,null,null,++showNumber,showFlag,"Amount of component","AMOUNT");
            genText(mob,decoded,null,allComponents,++showNumber,showFlag,"Type of component (?)","COMPONENTID");
            genText(mob,decoded,null,CMLib.masking().maskHelp("\n","disallow"),++showNumber,showFlag,"Component applies-to mask (?)","MASK");
            if(showFlag<-900){ ok=true; break;}
            if(showFlag>0){ showFlag=-1; continue;}
            showFlag=CMath.s_int(mob.session().prompt("Edit which? ",""));
            if(showFlag<=0)
            {
                showFlag=-1;
                ok=true;
            }
        }
        CMLib.ableMapper().setAbilityComponentCodedFromDecodedDVector(decoded,components,componentIndex);
        return true;
    }
    
    protected void modifyComponents(MOB mob, String componentID)
    throws IOException
    {
        if(mob.isMonster())
            return;
        boolean ok=false;
        int showFlag=-1;
        if(CMProps.getIntVar(CMProps.SYSTEMI_EDITORTYPE)>0)
            showFlag=-999;
        DVector codedDV=CMLib.ableMapper().getAbilityComponentDVector(componentID);
        if(codedDV!=null)
        while((mob.session()!=null)&&(!mob.session().killFlag())&&(!ok))
        {
            int showNumber=0;
            for(int v=0;v<codedDV.size();v++)
                if((mob.session()!=null)&&(!mob.session().killFlag()))
                {
                    showNumber++;
                    if((showFlag>0)&&(showFlag!=showNumber)) continue;
                    mob.tell(showNumber+": '"+CMLib.ableMapper().getAbilityComponentDesc(null,codedDV,v)+"'.");
                    if((showFlag!=showNumber)&&(showFlag>-999)) continue;
                    if(!modifyComponent(mob,codedDV,v))
                    {
                        codedDV.removeElementAt(v);
                        v--;
                    }
                }
            while((mob.session()!=null)&&(!mob.session().killFlag()))
            {
                showNumber++;
                mob.tell(showNumber+". Add new component requirement.");
                if((showFlag==showNumber)||(showFlag<=-999))
                {
                    CMLib.ableMapper().addBlankAbilityComponent(codedDV);
                    boolean success=modifyComponent(mob,codedDV,codedDV.size()-1);
                    if(!success)
                        codedDV.removeElementAt(codedDV.size()-1);
                    else
                    if(showFlag<=-999)
                        continue;
                }
                break;
            }
            if(showFlag<-900){ ok=true; break;}
            if(showFlag>0){ showFlag=-1; continue;}
            showFlag=CMath.s_int(mob.session().prompt("Edit which? ",""));
            if(showFlag<=0)
            {
                showFlag=-1;
                ok=true;
            }
        }
    }
    
    protected void modifyFaction(MOB mob, Faction me)
    throws IOException
    {
        if(mob.isMonster())
            return;
        boolean ok=false;
        int showFlag=-1;
        if(CMProps.getIntVar(CMProps.SYSTEMI_EDITORTYPE)>0)
            showFlag=-999;
        while((mob.session()!=null)&&(!mob.session().killFlag())&&(!ok))
        {
            int showNumber=0;
            // name
            me.setName(CMLib.english().promptText(mob,me.name(),++showNumber,showFlag,"Name"));

            // ranges
            ++showNumber;
            if(me.ranges().size()==0)
                me.ranges().addElement(me.newRange("0;100;Sample Range;SAMPLE;"));
            while((mob.session()!=null)&&(!mob.session().killFlag())&&(!((showFlag>0)&&(showFlag!=showNumber))))
            {
                StringBuffer list=new StringBuffer(showNumber+". Faction Division/Ranges List:\n\r");
                list.append(CMStrings.padRight("   Name",21)+CMStrings.padRight("Min",11)+CMStrings.padRight("Max",11)+CMStrings.padRight("Code",16)+CMStrings.padRight("Align",6)+"\n\r");
                for(int r=0;r<me.ranges().size();r++)
                {
                    Faction.FactionRange FR=(Faction.FactionRange)me.ranges().elementAt(r);
                    list.append(CMStrings.padRight("   "+FR.name(),20)+" ");
                    list.append(CMStrings.padRight(""+FR.low(),10)+" ");
                    list.append(CMStrings.padRight(""+FR.high(),10)+" ");
                    list.append(CMStrings.padRight(FR.codeName(),15)+" ");
                    list.append(CMStrings.padRight(Faction.ALIGN_NAMES[FR.alignEquiv()],5)+"\n\r");
                }
                mob.tell(list.toString());
                if((showFlag!=showNumber)&&(showFlag>-999)) break;
                String which=mob.session().prompt("Enter a name to add, remove, or modify:","");
                if(which.length()==0)
                    break;
                Faction.FactionRange FR=null;
                for(int r=0;r<me.ranges().size();r++)
                {
                    if(((Faction.FactionRange)me.ranges().elementAt(r)).name().equalsIgnoreCase(which))
                        FR=(Faction.FactionRange)me.ranges().elementAt(r);
                }
                if(FR==null)
                {
                    if(mob.session().confirm("Create a new range called '"+which+"' (y/N): ","N"))
                    {
                        FR=me.newRange("0;100;"+which+";CHANGEMYCODENAME;");
                        me.ranges().addElement(FR);
                    }
                }
                else
                if(mob.session().choose("Would you like to M)odify or D)elete this range (M/d): ","MD","M").toUpperCase().startsWith("D"))
                {
                    me.ranges().remove(FR);
                    mob.tell("Range deleted.");
                    FR=null;
                }
                if(FR!=null)
                {
                    String newName=mob.session().prompt("Enter a new name ("+FR.name()+")\n\r: "+FR.name());
                    boolean error99=false;
                    if(newName.length()==0)
                        error99=true;
                    else
                    for(int r=0;r<me.ranges().size();r++)
                    {
                        Faction.FactionRange FR3=(Faction.FactionRange)me.ranges().elementAt(r);
                        if(FR3.name().equalsIgnoreCase(FR.name())&&(FR3!=FR))
                        { mob.tell("A range already exists with that name!"); error99=true; break;}
                    }
                    if(error99)
                        mob.tell("(no change)");
                    else
                        FR.setName(newName);
                    newName=mob.session().prompt("Enter the low end of the range ("+FR.low()+")\n\r: ",""+FR.low());
                    if(!CMath.isInteger(newName))
                        mob.tell("(no change)");
                    else
                        FR.setLow(CMath.s_int(newName));
                    newName=mob.session().prompt("Enter the high end of the range ("+FR.high()+")\n\r: ",""+FR.high());
                    if((!CMath.isInteger(newName))||(CMath.s_int(newName)<FR.low()))
                        mob.tell("(no change)");
                    else
                        FR.setHigh(CMath.s_int(newName));
                    newName=mob.session().prompt("Enter a code-name ("+FR.codeName()+")\n\r: ",""+FR.codeName());
                    if(newName.trim().length()==0)
                        mob.tell("(no change)");
                    else
                    {
                    	Faction FC=CMLib.factions().getFactionByRangeCodeName(newName.toUpperCase().trim());
                    	if((FC!=null)&&(FC!=me))
                            mob.tell("That code name is already being used in another faction.  Value not accepted.");
                    	else
	                        FR.setCodeName(newName.toUpperCase().trim());
                    }
                    StringBuffer prompt=new StringBuffer("Select the 'virtue' (if any) of this range:\n\r");
                    StringBuffer choices=new StringBuffer("");
                    for(int r=0;r<Faction.ALIGN_NAMES.length;r++)
                    {
                        choices.append(""+r);
                        if(r==Faction.ALIGN_INDIFF)
                            prompt.append(r+") Not applicable\n\r");
                        else
                            prompt.append(r+") "+Faction.ALIGN_NAMES[r].toLowerCase()+"\n\r");
                    }
                    FR.setAlignEquiv(CMath.s_int(mob.session().choose(prompt.toString()+"Enter alignment equivalency or 0: ",choices.toString(),""+FR.alignEquiv())));
                }
            }


            // show in score
            me.setShowinscore(CMLib.english().promptBool(mob,me.showinscore(),++showNumber,showFlag,"Show in 'Score'"));

            // show in factions
            me.setShowinfactionscommand(CMLib.english().promptBool(mob,me.showinfactionscommand(),++showNumber,showFlag,"Show in 'Factions' command"));

            // show in special reports
            boolean alreadyReporter=false;
            for(Enumeration e=CMLib.factions().factionSet().elements();e.hasMoreElements();)
            {
                Faction F2=(Faction)e.nextElement();
                if(F2.showinspecialreported()) alreadyReporter=true;
            }
            if(!alreadyReporter)
                me.setShowinspecialreported(CMLib.english().promptBool(mob,me.showinspecialreported(),++showNumber,showFlag,"Show in Reports"));

            // show in editor
            me.setShowineditor(CMLib.english().promptBool(mob,me.showineditor(),++showNumber,showFlag,"Show in MOB Editor"));

            // auto defaults
            boolean error=true;
            me.setAutoDefaults(CMParms.parseSemicolons(CMLib.english().promptText(mob,CMParms.toSemicolonList(me.autoDefaults()),++showNumber,showFlag,"Optional automatic assigned values with zapper masks (semicolon delimited).\n\r    "),true));

            // non-auto defaults
            error=true;
            if(me.defaults().size()==0)
                me.defaults().addElement("0");
            ++showNumber;
            while(error&&(mob.session()!=null)&&(!mob.session().killFlag()))
            {
                error=false;
                String newDefaults=CMLib.english().promptText(mob,CMParms.toSemicolonList(me.defaults()),showNumber,showFlag,"Other default values with zapper masks (semicolon delimited).\n\r    ");
                if((showFlag!=showNumber)&&(showFlag>-999)) break;
                Vector V=CMParms.parseSemicolons(newDefaults,true);
                if(V.size()==0)
                {
                    mob.tell("This field may not be empty.");
                    error=true;
                }
                me.setDefaults(CMParms.parseSemicolons(newDefaults,true));
            }

            // choices and choice intro
            me.setChoices(CMParms.parseSemicolons(CMLib.english().promptText(mob,CMParms.toSemicolonList(me.choices()),++showNumber,showFlag,"Optional new player value choices (semicolon-delimited).\n\r    "),true));
            if(me.choices().size()>0)
                me.setChoiceIntro(CMLib.english().promptText(mob,me.choiceIntro(),++showNumber,showFlag,"Optional choices introduction text. Filename"));

            // rate modifier
            String newModifier=CMLib.english().promptText(mob,Math.round(me.rateModifier()*100.0)+"%",++showNumber,showFlag,"Rate modifier");
            if(newModifier.endsWith("%"))
                newModifier=newModifier.substring(0,newModifier.length()-1);
            if(CMath.isNumber(newModifier))
                me.setRateModifier(CMath.s_double(newModifier)/100.0);

            // experience flag
            boolean error2=true;
            ++showNumber;
            while(error2&&(mob.session()!=null)&&(!mob.session().killFlag())&&(!((showFlag>0)&&(showFlag!=showNumber))))
            {
                error2=false;
                StringBuffer nextPrompt=new StringBuffer("\n\r");
                int myval=-1;
                for(int i=0;i<Faction.EXPAFFECT_NAMES.length;i++)
                {
                    if(me.experienceFlag().equalsIgnoreCase(Faction.EXPAFFECT_NAMES[i]))
                        myval=i;
                    nextPrompt.append("  "+(i+1)+") "+CMStrings.capitalizeAndLower(Faction.EXPAFFECT_NAMES[i].toLowerCase())+"\n\r");
                }
                if(myval<0){ me.setExperienceFlag("NONE"); myval=0;}
                if((showFlag!=showNumber)&&(showFlag>-999))
                {
                    mob.tell(showNumber+". Affect on experience: "+Faction.EXPAFFECT_NAMES[myval]);
                    break;
                }
                String prompt="Affect on experience:  "+Faction.EXPAFFECT_NAMES[myval]+nextPrompt.toString()+"\n\rSelect a value: ";
                int mynewval=CMLib.english().promptInteger(mob,myval+1,showNumber,showFlag,prompt);
                if((showFlag!=showNumber)&&(showFlag>-999)) break;
                if((mynewval<=0)||(mynewval>Faction.EXPAFFECT_NAMES.length))
                {
                    mob.tell("That value is not valid.");
                    error2=true;
                }
                else
                    me.setExperienceFlag(Faction.EXPAFFECT_NAMES[mynewval-1]);
            }

            // factors by mask
            ++showNumber;
            while((mob.session()!=null)&&(!mob.session().killFlag())&&(!((showFlag>0)&&(showFlag!=showNumber))))
            {
                StringBuffer list=new StringBuffer(showNumber+". Faction change adjustment Factors with Zapper Masks:\n\r");
                list.append("    #) "+CMStrings.padRight("Zapper Mask",31)+CMStrings.padRight("Gain",6)+CMStrings.padRight("Loss",6)+"\n\r");
                StringBuffer choices=new StringBuffer("");
                for(int r=0;r<me.factors().size();r++)
                {
                    Vector factor=(Vector)me.factors().elementAt(r);
                    if(factor.size()!=3)
                        me.factors().removeElement(factor);
                    else
                    {
                        choices.append(((char)('A'+r)));
                        list.append("    "+(((char)('A'+r))+") "));
                        list.append(CMStrings.padRight((String)factor.elementAt(2),30)+" ");
                        list.append(CMStrings.padRight(""+Math.round(CMath.s_double((String)factor.elementAt(0))*100.0)+"%",5)+" ");
                        list.append(CMStrings.padRight(""+Math.round(CMath.s_double((String)factor.elementAt(1))*100.0)+"%",5)+"\n\r");
                    }
                }
                mob.tell(list.toString());
                if((showFlag!=showNumber)&&(showFlag>-999)) break;
                String which=mob.session().choose("Enter a # to remove, or modify, or enter 0 to Add:","0"+choices.toString(),"").trim().toUpperCase();
                int factorNum=choices.toString().indexOf(which);
                if((which.length()!=1)
                ||((!which.equalsIgnoreCase("0"))
                    &&((factorNum<0)||(factorNum>=me.factors().size()))))
                    break;
                Vector factor=null;
                if(!which.equalsIgnoreCase("0"))
                {
                    factor=(Vector)me.factors().elementAt(factorNum);
                    if(factor!=null)
                        if(mob.session().choose("Would you like to M)odify or D)elete this range (M/d): ","MD","M").toUpperCase().startsWith("D"))
                        {
                            me.factors().remove(factor);
                            mob.tell("Factor deleted.");
                            factor=null;
                        }
                }
                else
                {
                    factor=new Vector();
                    factor.addElement("1.0");
                    factor.addElement("1.0");
                    factor.addElement("");
                    me.factors().addElement(factor);
                }
                if(factor!=null)
                {
                    String mask=mob.session().prompt("Enter a new zapper mask ("+((String)factor.elementAt(2))+")\n\r: "+((String)factor.elementAt(2)));
                    double newHigh=CMath.s_double((String)factor.elementAt(0));
                    String newName=mob.session().prompt("Enter gain adjustment ("+Math.round(newHigh*100)+"%): "+Math.round(newHigh*100)+"".trim()+"%");
                    if(newName.endsWith("%"))
                        newName=newName.substring(0,newName.length()-1);
                    if(!CMath.isNumber(newName))
                        mob.tell("(no change)");
                    else
                        newHigh=CMath.s_double(newName)/100.0;

                    double newLow=CMath.s_double((String)factor.elementAt(1));
                    newName=mob.session().prompt("Enter loss adjustment ("+Math.round(newLow*100)+"%): "+Math.round(newLow*100)+"".trim()+"%");
                    if(newName.endsWith("%"))
                        newName=newName.substring(0,newName.length()-1);
                    if(!CMath.isNumber(newName))
                        mob.tell("(no change)");
                    else
                        newLow=CMath.s_double(newName)/100.0;
                    me.factors().removeElement(factor);
                    factor=new Vector();
                    factor.addElement(""+newHigh);
                    factor.addElement(""+newLow);
                    factor.addElement(""+mask);
                    me.factors().addElement(factor);
                }
            }

            // relations between factions
            ++showNumber;
            while((mob.session()!=null)&&(!mob.session().killFlag())&&(!((showFlag>0)&&(showFlag!=showNumber))))
            {
                StringBuffer list=new StringBuffer(showNumber+". Cross-Faction Relations:\n\r");
                list.append("    Faction"+CMStrings.padRight("",25)+"Percentage change\n\r");
                for(Enumeration e=me.relations().keys();e.hasMoreElements();)
                {
                    String key=(String)e.nextElement();
                    Double value=(Double)me.relations().get(key);
                    Faction F=CMLib.factions().getFaction(key);
                    if(F!=null)
                    {
                        list.append("    "+CMStrings.padRight(F.name(),31)+" ");
                        long lval=Math.round(value.doubleValue()*100.0);
                        list.append(lval+"%");
                        list.append("\n\r");
                    }
                }
                mob.tell(list.toString());
                if((showFlag!=showNumber)&&(showFlag>-999)) break;
                String which=mob.session().prompt("Enter a faction to add, remove, or modify relations:","");
                if(which.length()==0)
                    break;
                Faction theF=null;
                for(Enumeration e=me.relations().keys();e.hasMoreElements();)
                {
                    String key=(String)e.nextElement();
                    Faction F=CMLib.factions().getFaction(key);
                    if((F!=null)&&(F.name().equalsIgnoreCase(which)))
                        theF=F;
                }
                if(theF==null)
                {
                    Faction possibleF=CMLib.factions().getFaction(which);
                    if(possibleF==null) possibleF=CMLib.factions().getFactionByName(which);
                    if(possibleF==null)
                        mob.tell("'"+which+"' is not a valid faction.");
                    else
                    if(mob.session().confirm("Create a new relation for faction  '"+possibleF.name()+"' (y/N):","N"))
                    {
                        theF=possibleF;
                        me.relations().put(theF.factionID(),new Double(1.0));
                    }
                }
                else
                if(mob.session().choose("Would you like to M)odify or D)elete this relation (M/d): ","MD","M").toUpperCase().startsWith("D"))
                {
                    me.relations().remove(theF.factionID());
                    mob.tell("Relation deleted.");
                    theF=null;
                }
                if(theF!=null)
                {
                    long amount=Math.round(((Double)me.relations().get(theF.factionID())).doubleValue()*100.0);
                    String newName=mob.session().prompt("Enter a relation amount ("+amount+"%): ",""+amount+"%");
                    if(newName.endsWith("%")) newName=newName.substring(0,newName.length()-1);
                    if(!CMath.isInteger(newName))
                        mob.tell("(no change)");
                    else
                        amount=CMath.s_long(newName);
                    me.relations().remove(theF.factionID());
                    me.relations().put(theF.factionID(),new Double(amount/100.0));
                }
            }

            // faction change triggers
            ++showNumber;
            while((mob.session()!=null)&&(!mob.session().killFlag())&&(!((showFlag>0)&&(showFlag!=showNumber))))
            {
                StringBuffer list=new StringBuffer(showNumber+". Faction Change Triggers:\n\r");
                list.append("    "+CMStrings.padRight("Type",15)
                        +" "+CMStrings.padRight("Direction",10)
                        +" "+CMStrings.padRight("Factor",10)
                        +" "+CMStrings.padRight("Flags",20)
                        +" Mask\n\r");
                for(Enumeration e=me.Changes().elements();e.hasMoreElements();)
                {
                    Faction.FactionChangeEvent CE=(Faction.FactionChangeEvent)e.nextElement();
                    if(CE!=null)
                    {
                        list.append("    ");
                        list.append(CMStrings.padRight(CE.eventID(),15)+" ");
                        list.append(CMStrings.padRight(Faction.FactionChangeEvent.FACTION_DIRECTIONS[CE.direction()],10)+" ");
                        list.append(CMStrings.padRight(Math.round(CE.factor()*100.0)+"%",10)+" ");
                        list.append(CMStrings.padRight(CE.flagCache(),20)+" ");
                        list.append(CE.zapper()+"\n\r");
                    }
                }
                mob.tell(list.toString());
                if((showFlag!=showNumber)&&(showFlag>-999)) break;
                String which=mob.session().prompt("Select a trigger ID to add, remove, or modify (?):","");
                which=which.toUpperCase().trim();
                if(which.length()==0) break;
                if(which.equalsIgnoreCase("?"))
                {
                    mob.tell("Valid triggers: \n\r"+me.ALL_CHANGE_EVENT_TYPES());
                    continue;
                }
                Faction.FactionChangeEvent CE=(Faction.FactionChangeEvent)me.Changes().get(which);
                if(CE==null)
                {
                    CE=me.newChangeEvent();
                    if(!CE.setFilterID(which))
                    {
                        mob.tell("That ID is invalid.  Try '?'.");
                        continue;
                    }
                    else
                    if(!mob.session().confirm("Create a new trigger using ID '"+which+"' (y/N): ","N"))
                    {
                        CE=null;
                        break;
                    }
                    else
                        me.Changes().put(CE.eventID().toUpperCase(),CE);
                }
                else
                if(mob.session().choose("Would you like to M)odify or D)elete this trigger (M/d): ","MD","M").toUpperCase().startsWith("D"))
                {
                    me.Changes().remove(CE.eventID());
                    mob.tell("Trigger deleted.");
                    CE=null;
                }

                if(CE!=null)
                {
                    StringBuffer directions=new StringBuffer("Valid directions:\n\r");
                    StringBuffer cmds=new StringBuffer("");
                    for(int i=0;i<Faction.FactionChangeEvent.FACTION_DIRECTIONS.length;i++)
                    {
                        directions.append(((char)('A'+i))+") "+Faction.FactionChangeEvent.FACTION_DIRECTIONS[i]+"\n\r");
                        cmds.append((char)('A'+i));
                    }
                    String str=mob.session().choose(directions+"\n\rSelect a new direction ("+Faction.FactionChangeEvent.FACTION_DIRECTIONS[CE.direction()]+"): ",cmds.toString()+"\n\r","");
                    if((str.length()==0)||str.equals("\n")||str.equals("\r")||(cmds.toString().indexOf(str.charAt(0))<0))
                        mob.tell("(no change)");
                    else
                        CE.setDirection((cmds.toString().indexOf(str.charAt(0))));
                }
                if(CE!=null)
                {
                    if(CE.factor()==0.0) CE.setFactor(1.0);
                    int amount=(int)Math.round(CE.factor()*100.0);
                    String newName=mob.session().prompt("Enter the amount factor ("+amount+"%): ",""+amount+"%");
                    if(newName.endsWith("%")) newName=newName.substring(0,newName.length()-1);
                    if(!CMath.isInteger(newName))
                        mob.tell("(no change)");
                    else
                        CE.setFactor(new Double(CMath.s_int(newName)/100.0).doubleValue());
                }
                if(CE!=null)
                {
                    mob.tell("Valid flags include: "+CMParms.toStringList(Faction.FactionChangeEvent.VALID_FLAGS)+"\n\r");
                    String newFlags=mob.session().prompt("Enter new flag(s) ("+CE.flagCache()+"): "+CE.flagCache());
                    if((newFlags.length()==0)||(newFlags.equals(CE.flagCache())))
                        mob.tell("(no change)");
                    else
                        CE.setFlags(newFlags);
                }
                if(CE!=null)
                {
                    String newFlags=mob.session().prompt("Zapper mask ("+CE.zapper()+"): "+CE.zapper());
                    if((newFlags.length()==0)||(newFlags.equals(CE.zapper())))
                        mob.tell("(no change)");
                    else
                        CE.setZapper(newFlags);
                }
            }

            // Ability allowances
            ++showNumber;
            while((mob.session()!=null)&&(!mob.session().killFlag())&&(!((showFlag>0)&&(showFlag!=showNumber))))
            {
                if((showFlag>0)&&(showFlag!=showNumber)) break;
                StringBuffer list=new StringBuffer(showNumber+". Ability allowances:\n\r");
                list.append("    #) "
                        +CMStrings.padRight("Ability masks",40)
                        +" "+CMStrings.padRight("Low value",10)
                        +" "+CMStrings.padRight("High value",10)
                        +"\n\r");
                int num=0;
                StringBuffer choices=new StringBuffer("0\n\r");
                for(Enumeration e=me.abilityUsages().elements();e.hasMoreElements();)
                {
                    Faction.FactionAbilityUsage CA=(Faction.FactionAbilityUsage)e.nextElement();
                    if(CA!=null)
                    {
                        list.append("    "+((char)('A'+num)+") "));
                        list.append(CMStrings.padRight(CA.usageID(),40)+" ");
                        list.append(CMStrings.padRight(CA.low()+"",10)+" ");
                        list.append(CMStrings.padRight(CA.high()+"",10)+" ");
                        list.append("\n\r");
                        choices.append((char)('A'+num));
                        num++;
                    }
                }
                mob.tell(list.toString());
                if((showFlag!=showNumber)&&(showFlag>-999)) break;
                String which=mob.session().choose("Select an allowance to remove or modify, or enter 0 to Add:",choices.toString(),"");
                if(which.length()!=1)
                    break;
                which=which.toUpperCase().trim();
                Faction.FactionAbilityUsage CA=null;
                if(!which.equalsIgnoreCase("0"))
                {
                    num=(which.charAt(0)-'A');
                    if((num<0)||(num>=me.abilityUsages().size()))
                        break;
                    CA=(Faction.FactionAbilityUsage)me.abilityUsages().elementAt(num);
                    if(CA==null)
                    {
                        mob.tell("That allowance is invalid..");
                        continue;
                    }
                    if(mob.session().choose("Would you like to M)odify or D)elete this allowance (M/d): ","MD","M").toUpperCase().startsWith("D"))
                    {
                        me.abilityUsages().remove(CA);
                        mob.tell("Allowance deleted.");
                        CA=null;
                    }
                }
                else
                if(!mob.session().confirm("Create a new allowance (y/N): ","N"))
                {
                    CA=null;
                    continue;
                }
                else
                {
                    CA=me.newAbilityUsage();
                    me.abilityUsages().addElement(CA);
                }
                if(CA!=null)
                {
                    boolean cont=false;
                    while((!cont)&&(!mob.session().killFlag()))
                    {
                        String newFlags=mob.session().prompt("Ability determinate masks or ? ("+CA.usageID()+"): "+CA.usageID());
                        if(newFlags.equalsIgnoreCase("?"))
                        {
                            StringBuffer vals=new StringBuffer("Valid masks: \n\r");
                            for(int i=0;i<Ability.ACODE_DESCS.length;i++)
                                vals.append(Ability.ACODE_DESCS[i]+", ");
                            for(int i=0;i<Ability.DOMAIN_DESCS.length;i++)
                                vals.append(Ability.DOMAIN_DESCS[i]+", ");
                            for(int i=0;i< Ability.FLAG_DESCS.length;i++)
                                vals.append(Ability.FLAG_DESCS[i]+", ");
                            vals.append(" * Any ABILITY ID (skill/prayer/spell/etc)");
                            mob.tell(vals.toString());
                            cont=false;
                        }
                        else
                        {
                            cont=true;
                            if((newFlags.length()==0)||(newFlags.equals(CA.usageID())))
                                mob.tell("(no change)");
                            else
                            {
                                Vector unknowns=CA.setAbilityFlag(newFlags);
                                if(unknowns.size()>0)
                                    for(int i=unknowns.size()-1;i>=0;i--)
                                        if(CMClass.getAbility((String)unknowns.elementAt(i))!=null)
                                            unknowns.removeElementAt(i);
                                if(unknowns.size()>0)
                                {
                                    mob.tell("The following are unknown masks: '"+CMParms.toStringList(unknowns)+"'.  Please correct them.");
                                    cont=false;
                                }
                            }
                        }
                    }
                    String newName=mob.session().prompt("Enter the minimum value to use the ability ("+CA.low()+"): ",""+CA.low());
                    if((!CMath.isInteger(newName))||(CA.low()==CMath.s_int(newName)))
                        mob.tell("(no change)");
                    else
                        CA.setLow(CMath.s_int(newName));
                    newName=mob.session().prompt("Enter the maximum value to use the ability ("+CA.high()+"): ",""+CA.high());
                    if((!CMath.isInteger(newName))||(CA.high()==CMath.s_int(newName)))
                        mob.tell("(no change)");
                    else
                        CA.setHigh(CMath.s_int(newName));
                    if(CA.high()<CA.low()) CA.setHigh(CA.low());
                }
            }

            // calculate new max/min
            me.setMinimum(Integer.MAX_VALUE);
            me.setMaximum(Integer.MIN_VALUE);
            for(int r=0;r<me.ranges().size();r++)
            {
                Faction.FactionRange FR=(Faction.FactionRange)me.ranges().elementAt(r);
                if(FR.high()>me.maximum()) me.setMaximum(FR.high());
                if(FR.low()<me.minimum()) me.setMinimum(FR.low());
            }
            if(me.minimum()==Integer.MAX_VALUE) me.setMinimum(Integer.MIN_VALUE);
            if(me.maximum()==Integer.MIN_VALUE) me.setMaximum(Integer.MAX_VALUE);
            if(me.maximum()<me.minimum())
            {
                int oldMin=me.minimum();
                me.setMinimum(me.maximum());
                me.setMaximum(oldMin);
            }
            me.setMiddle(me.minimum()+(int)Math.round(CMath.div(me.maximum()-me.minimum(),2.0)));
            me.setDifference(CMath.abs(me.maximum()-me.minimum()));



            if(showFlag<-900){ ok=true; break;}
            if(showFlag>0){ showFlag=-1; continue;}
            showFlag=CMath.s_int(mob.session().prompt("Edit which? ",""));
            if(showFlag<=0)
            {
                showFlag=-1;
                ok=true;
            }
        }
        if((me.factionID().length()>0)&&(CMLib.factions().getFaction(me.factionID())!=null))
        {
            Vector oldV=Resources.getFileLineVector(Resources.getFileResource(me.factionID(),true));
            if(oldV.size()<10)
            {

            }
            boolean[] defined=new boolean[Faction.ALL_TAGS.length];
            for(int i=0;i<defined.length;i++) defined[i]=false;
            for(int v=0;v<oldV.size();v++)
            {
                String s=(String)oldV.elementAt(v);
                if(!(s.trim().startsWith("#")||s.trim().length()==0||(s.indexOf("=")<0)))
                {
                    String tag=s.substring(0,s.indexOf("=")).trim().toUpperCase();
                    int tagRef=CMLib.factions().isFactionTag(tag);
                    if(tagRef>=0) defined[tagRef]=true;
                }
            }
            boolean[] done=new boolean[Faction.ALL_TAGS.length];
            for(int i=0;i<done.length;i++) done[i]=false;
            int lastCommented=-1;
            String CR="\n\r";
            StringBuffer buf=new StringBuffer("");
            for(int v=0;v<oldV.size();v++)
            {
                String s=(String)oldV.elementAt(v);
                if(s.trim().length()==0)
                {
                    if((lastCommented>=0)&&(!done[lastCommented]))
                    {
                        done[lastCommented]=true;
                        buf.append(me.getINIDef(Faction.ALL_TAGS[lastCommented],CR)+CR);
                        lastCommented=-1;
                    }
                }
                else
                if(s.trim().startsWith("#")||(s.indexOf("=")<0))
                {
                    buf.append(s+CR);
                    int x=s.indexOf("=");
                    if(x>=0)
                    {
                        s=s.substring(0,x).trim();
                        int first=s.length()-1;
                        for(;first>=0;first--)
                            if(!Character.isLetterOrDigit(s.charAt(first)))
                                break;
                        first=CMLib.factions().isFactionTag(s.substring(first).trim().toUpperCase());
                        if(first>=0) lastCommented=first;
                    }
                }
                else
                {
                    String tag=s.substring(0,s.indexOf("=")).trim().toUpperCase();
                    int tagRef=CMLib.factions().isFactionTag(tag);
                    if(tagRef<0)
                        buf.append(s+CR);
                    else
                    if(!done[tagRef])
                    {
                        done[tagRef]=true;
                        buf.append(me.getINIDef(tag,CR)+CR);
                    }
                }
            }
            if((lastCommented>=0)&&(!done[lastCommented]))
                buf.append(me.getINIDef(Faction.ALL_TAGS[lastCommented],CR)+CR);
            Resources.removeResource(me.factionID());
            Resources.submitResource(me.factionID(),buf);
            if(!Resources.saveFileResource(me.factionID()))
                mob.tell("Faction File '"+me.factionID()+"' could not be modified.  Make sure it is not READ-ONLY.");
        }
    }

	protected void modifyGenRace(MOB mob, Race me)
		throws IOException
	{
		if(mob.isMonster())
			return;
		boolean ok=false;
		int showFlag=-1;
		if(CMProps.getIntVar(CMProps.SYSTEMI_EDITORTYPE)>0)
			showFlag=-999;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!ok))
		{
			int showNumber=0;
			genText(mob,me,++showNumber,showFlag,"Name","NAME");
			genCat(mob,me,++showNumber,showFlag);
			genInt(mob,me,++showNumber,showFlag,"Base Weight","BWEIGHT");
			genInt(mob,me,++showNumber,showFlag,"Weight Variance","VWEIGHT");
			genInt(mob,me,++showNumber,showFlag,"Base Male Height","MHEIGHT");
			genInt(mob,me,++showNumber,showFlag,"Base Female Height","FHEIGHT");
			genInt(mob,me,++showNumber,showFlag,"Height Variance","VHEIGHT");
			genRaceAvailability(mob,me,++showNumber,showFlag);
			genDisableFlags(mob,me,++showNumber,showFlag);
			genText(mob,me,++showNumber,showFlag,"Leaving text","LEAVE");
			genText(mob,me,++showNumber,showFlag,"Arriving text","ARRIVE");
			genRaceBuddy(mob,me,++showNumber,showFlag,"Health Race","HEALTHRACE");
			genRaceBuddy(mob,me,++showNumber,showFlag,"Event Race","EVENTRACE");
			genBodyParts(mob,me,++showNumber,showFlag);
			genRaceWearFlags(mob,me,++showNumber,showFlag);
			genAgingChart(mob,me,++showNumber,showFlag);
            genBool(mob,me,++showNumber,showFlag,"Never create corpse","BODYKILL");
			genEStats(mob,me,++showNumber,showFlag);
			genAStats(mob,me,"ASTATS","CharStat Adjustments",++showNumber,showFlag);
			genAStats(mob,me,"CSTATS","CharStat Settings",++showNumber,showFlag);
			genAState(mob,me,"ASTATE","CharState Adjustments",++showNumber,showFlag);
			genAState(mob,me,"STARTASTATE","New Player CharState Adj.",++showNumber,showFlag);
			genResources(mob,me,++showNumber,showFlag);
			genOutfit(mob,me,++showNumber,showFlag);
			genWeapon(mob,me,++showNumber,showFlag);
			genRaceBuddy(mob,me,++showNumber,showFlag,"Weapons Race","WEAPONRACE");
			genRacialAbilities(mob,me,++showNumber,showFlag);
			genCulturalAbilities(mob,me,++showNumber,showFlag);
			//genRacialEffects(mob,me,++showNumber,showFlag);
			if(showFlag<-900){ ok=true; break;}
			if(showFlag>0){ showFlag=-1; continue;}
			showFlag=CMath.s_int(mob.session().prompt("Edit which? ",""));
			if(showFlag<=0)
			{
				showFlag=-1;
				ok=true;
			}
		}
	}

	protected void modifyGenItem(MOB mob, Item me)
		throws IOException
	{
		boolean ok=false;
		int showFlag=-1;
		if(CMProps.getIntVar(CMProps.SYSTEMI_EDITORTYPE)>0)
			showFlag=-999;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!ok))
		{
			if(mob.isMonster())	return;
			int showNumber=0;
			genName(mob,me,++showNumber,showFlag);
			genDisplayText(mob,me,++showNumber,showFlag);
			genDescription(mob,me,++showNumber,showFlag);
			genLevel(mob,me,++showNumber,showFlag);
			genSecretIdentity(mob,me,++showNumber,showFlag);
			genMaterialCode(mob,me,++showNumber,showFlag);
			if(me instanceof ClanItem)
				genClanItem(mob,(ClanItem)me,++showNumber,showFlag);
			if(me instanceof ShipComponent)
			{
			    if(me instanceof ShipComponent.ShipPanel)
				    genPanelType(mob,(ShipComponent.ShipPanel)me,++showNumber,showFlag);
			}
            if(me instanceof PackagedItems)
                ((PackagedItems)me).setNumberOfItemsInPackage(CMLib.english().promptInteger(mob,((PackagedItems)me).numberOfItemsInPackage(),++showNumber,showFlag,"Number of items in the package"));
			genGettable(mob,me,++showNumber,showFlag);
			genReadable1(mob,me,++showNumber,showFlag);
			genReadable2(mob,me,++showNumber,showFlag);
			if(me instanceof Recipe) genRecipe(mob,(Recipe)me,++showNumber,showFlag);
			if(me instanceof Light)	genBurnout(mob,(Light)me,++showNumber,showFlag);
			genRejuv(mob,me,++showNumber,showFlag);
			if(me instanceof Coins)
			    genCoinStuff(mob,(Coins)me,++showNumber,showFlag);
			else
				genAbility(mob,me,++showNumber,showFlag);
			genUses(mob,me,++showNumber,showFlag);
			if(me instanceof Wand)
				genMaxUses(mob,(Wand)me,++showNumber,showFlag);
			genValue(mob,me,++showNumber,showFlag);
			genWeight(mob,me,++showNumber,showFlag);
			genDisposition(mob,me.baseEnvStats(),++showNumber,showFlag);
			genBehaviors(mob,me,++showNumber,showFlag);
			genAffects(mob,me,++showNumber,showFlag);
			if(me instanceof LandTitle)
				genTitleRoom(mob,(LandTitle)me,++showNumber,showFlag);
			genImage(mob,me,++showNumber,showFlag);
            for(int x=me.getSaveStatIndex();x<me.getStatCodes().length;x++)
                me.setStat(me.getStatCodes()[x],CMLib.english().promptText(mob,me.getStat(me.getStatCodes()[x]),++showNumber,showFlag,CMStrings.capitalizeAndLower(me.getStatCodes()[x])));
			if(showFlag<-900){ ok=true; break;}
			if(showFlag>0){ showFlag=-1; continue;}
			showFlag=CMath.s_int(mob.session().prompt("Edit which? ",""));
			if(showFlag<=0)
			{
				showFlag=-1;
				ok=true;
				me.recoverEnvStats();
				if(me.text().length()>=maxLength)
				{
					mob.tell("\n\rThe data entered exceeds the string limit of "+maxLength+" characters.  Please modify!");
					ok=false;
				}
			}
		}
	}

	protected void modifyGenFood(MOB mob, Food me)
		throws IOException
	{
		if(mob.isMonster())
			return;
		boolean ok=false;
		int showFlag=-1;
		if(CMProps.getIntVar(CMProps.SYSTEMI_EDITORTYPE)>0)
			showFlag=-999;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!ok))
		{
			int showNumber=0;
			genName(mob,me,++showNumber,showFlag);
			genDisplayText(mob,me,++showNumber,showFlag);
			genDescription(mob,me,++showNumber,showFlag);
			genSecretIdentity(mob,me,++showNumber,showFlag);
			genLevel(mob,me,++showNumber,showFlag);
			genValue(mob,me,++showNumber,showFlag);
			genRejuv(mob,me,++showNumber,showFlag);
			genWeight(mob,me,++showNumber,showFlag);
			genMaterialCode(mob,me,++showNumber,showFlag);
			genNourishment(mob,me,++showNumber,showFlag);
			genDisposition(mob,me.baseEnvStats(),++showNumber,showFlag);
			genGettable(mob,me,++showNumber,showFlag);
			genReadable1(mob,me,++showNumber,showFlag);
			genReadable2(mob,me,++showNumber,showFlag);
			if(me instanceof Light)	genBurnout(mob,(Light)me,++showNumber,showFlag);
			genBehaviors(mob,me,++showNumber,showFlag);
			genAffects(mob,me,++showNumber,showFlag);
			genImage(mob,me,++showNumber,showFlag);
            for(int x=me.getSaveStatIndex();x<me.getStatCodes().length;x++)
                me.setStat(me.getStatCodes()[x],CMLib.english().promptText(mob,me.getStat(me.getStatCodes()[x]),++showNumber,showFlag,CMStrings.capitalizeAndLower(me.getStatCodes()[x])));
			if(showFlag<-900){ ok=true; break;}
			if(showFlag>0){ showFlag=-1; continue;}
			showFlag=CMath.s_int(mob.session().prompt("Edit which? ",""));
			if(showFlag<=0)
			{
				showFlag=-1;
				ok=true;
				me.recoverEnvStats();
				if(me.text().length()>=maxLength)
				{
					mob.tell("\n\rThe data entered exceeds the string limit of "+maxLength+" characters.  Please modify!");
					ok=false;
				}
			}
		}
	}
	protected void modifyGenDrink(MOB mob, Drink me)
		throws IOException
	{
		if(mob.isMonster())
			return;
		boolean ok=false;
		int showFlag=-1;
		if(CMProps.getIntVar(CMProps.SYSTEMI_EDITORTYPE)>0)
			showFlag=-999;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!ok))
		{
			int showNumber=0;
			genName(mob,me,++showNumber,showFlag);
			genDisplayText(mob,me,++showNumber,showFlag);
			genDescription(mob,me,++showNumber,showFlag);
			genSecretIdentity(mob,(Item)me,++showNumber,showFlag);
			genValue(mob,(Item)me,++showNumber,showFlag);
			genLevel(mob,me,++showNumber,showFlag);
			genWeight(mob,me,++showNumber,showFlag);
			genRejuv(mob,me,++showNumber,showFlag);
			genThirstQuenched(mob,me,++showNumber,showFlag);
			genMaterialCode(mob,(Item)me,++showNumber,showFlag);
			genDrinkHeld(mob,me,++showNumber,showFlag);
			genGettable(mob,(Item)me,++showNumber,showFlag);
			genReadable1(mob,(Item)me,++showNumber,showFlag);
			genReadable2(mob,(Item)me,++showNumber,showFlag);
			if(me instanceof Light)	genBurnout(mob,(Light)me,++showNumber,showFlag);
			genBehaviors(mob,me,++showNumber,showFlag);
			genAffects(mob,me,++showNumber,showFlag);
			genDisposition(mob,me.baseEnvStats(),++showNumber,showFlag);
			if(me instanceof Container)
				genCapacity(mob,(Container)me,++showNumber,showFlag);
			if(me instanceof Perfume)
				((Perfume)me).setSmellList(CMLib.english().promptText(mob,((Perfume)me).getSmellList(),++showNumber,showFlag,"Smells list (; delimited)"));
			genImage(mob,me,++showNumber,showFlag);
            for(int x=me.getSaveStatIndex();x<me.getStatCodes().length;x++)
                me.setStat(me.getStatCodes()[x],CMLib.english().promptText(mob,me.getStat(me.getStatCodes()[x]),++showNumber,showFlag,CMStrings.capitalizeAndLower(me.getStatCodes()[x])));
			if(showFlag<-900){ ok=true; break;}
			if(showFlag>0){ showFlag=-1; continue;}
			showFlag=CMath.s_int(mob.session().prompt("Edit which? ",""));
			if(showFlag<=0)
			{
				showFlag=-1;
				ok=true;
				me.recoverEnvStats();
				if(me.text().length()>=maxLength)
				{
					mob.tell("\n\rThe data entered exceeds the string limit of "+maxLength+" characters.  Please modify!");
					ok=false;
				}
			}
		}
	}

	protected void modifyGenWallpaper(MOB mob, Item me)
		throws IOException
	{
		if(mob.isMonster())
			return;
		boolean ok=false;
		int showFlag=-1;
		if(CMProps.getIntVar(CMProps.SYSTEMI_EDITORTYPE)>0)
			showFlag=-999;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!ok))
		{
			int showNumber=0;
			genName(mob,me,++showNumber,showFlag);
			genDescription(mob,me,++showNumber,showFlag);
			genReadable1(mob,me,++showNumber,showFlag);
			genReadable2(mob,me,++showNumber,showFlag);
			if(me instanceof Light)	genBurnout(mob,(Light)me,++showNumber,showFlag);
            for(int x=me.getSaveStatIndex();x<me.getStatCodes().length;x++)
                me.setStat(me.getStatCodes()[x],CMLib.english().promptText(mob,me.getStat(me.getStatCodes()[x]),++showNumber,showFlag,CMStrings.capitalizeAndLower(me.getStatCodes()[x])));
			if(showFlag<-900){ ok=true; break;}
			if(showFlag>0){ showFlag=-1; continue;}
			showFlag=CMath.s_int(mob.session().prompt("Edit which? ",""));
			if(showFlag<=0)
			{
				showFlag=-1;
				ok=true;
				me.recoverEnvStats();
				if(me.text().length()>=maxLength)
				{
					mob.tell("\n\rThe data entered exceeds the string limit of "+maxLength+" characters.  Please modify!");
					ok=false;
				}
			}
		}
	}

	protected void modifyGenMap(MOB mob, com.planet_ink.coffee_mud.Items.interfaces.Map me)
		throws IOException
	{
		if(mob.isMonster())
			return;
		boolean ok=false;
		int showFlag=-1;
		if(CMProps.getIntVar(CMProps.SYSTEMI_EDITORTYPE)>0)
			showFlag=-999;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!ok))
		{
			int showNumber=0;
			genName(mob,me,++showNumber,showFlag);
			genDisplayText(mob,me,++showNumber,showFlag);
			genDescription(mob,me,++showNumber,showFlag);
			genLevel(mob,me,++showNumber,showFlag);
			genSecretIdentity(mob,me,++showNumber,showFlag);
			genGettable(mob,me,++showNumber,showFlag);
			genReadable1(mob,me,++showNumber,showFlag);
			genReadable2(mob,me,++showNumber,showFlag);
			genValue(mob,me,++showNumber,showFlag);
			genWeight(mob,me,++showNumber,showFlag);
			genRejuv(mob,me,++showNumber,showFlag);
			genMaterialCode(mob,me,++showNumber,showFlag);
			genDisposition(mob,me.baseEnvStats(),++showNumber,showFlag);
			genBehaviors(mob,me,++showNumber,showFlag);
			genAffects(mob,me,++showNumber,showFlag);
			genImage(mob,me,++showNumber,showFlag);
            for(int x=me.getSaveStatIndex();x<me.getStatCodes().length;x++)
                me.setStat(me.getStatCodes()[x],CMLib.english().promptText(mob,me.getStat(me.getStatCodes()[x]),++showNumber,showFlag,CMStrings.capitalizeAndLower(me.getStatCodes()[x])));
			if(showFlag<-900){ ok=true; break;}
			if(showFlag>0){ showFlag=-1; continue;}
			showFlag=CMath.s_int(mob.session().prompt("Edit which? ",""));
			if(showFlag<=0)
			{
				showFlag=-1;
				ok=true;
				me.recoverEnvStats();
				if(me.text().length()>=maxLength)
				{
					mob.tell("\n\rThe data entered exceeds the string limit of "+maxLength+" characters.  Please modify!");
					ok=false;
				}
			}
		}
	}

	protected void modifyGenContainer(MOB mob, Container me)
		throws IOException
	{
		if(mob.isMonster())
			return;
		boolean ok=false;
		int showFlag=-1;
		if(CMProps.getIntVar(CMProps.SYSTEMI_EDITORTYPE)>0)
			showFlag=-999;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!ok))
		{
			int showNumber=0;
			genName(mob,me,++showNumber,showFlag);
			genDisplayText(mob,me,++showNumber,showFlag);
			genDescription(mob,me,++showNumber,showFlag);
			genLevel(mob,me,++showNumber,showFlag);
			genRejuv(mob,me,++showNumber,showFlag);
			genCapacity(mob,me,++showNumber,showFlag);
			if(me instanceof ShipComponent)
			{
			    if(me instanceof ShipComponent.ShipPanel)
				    genPanelType(mob,(ShipComponent.ShipPanel)me,++showNumber,showFlag);
			}
			genLidsNLocks(mob,me,++showNumber,showFlag);
			genMaterialCode(mob,me,++showNumber,showFlag);
			genSecretIdentity(mob,me,++showNumber,showFlag);
			genValue(mob,me,++showNumber,showFlag);
			genUses(mob,me,++showNumber,showFlag);
			genWeight(mob,me,++showNumber,showFlag);
			genDisposition(mob,me.baseEnvStats(),++showNumber,showFlag);
			if(me instanceof DeadBody)
				genCorpseData(mob,(DeadBody)me,++showNumber,showFlag);
			if(me instanceof ClanItem)
				genClanItem(mob,(ClanItem)me,++showNumber,showFlag);
			genGettable(mob,me,++showNumber,showFlag);
			genReadable1(mob,me,++showNumber,showFlag);
			genReadable2(mob,me,++showNumber,showFlag);
			if(me instanceof Light)	genBurnout(mob,(Light)me,++showNumber,showFlag);
			genBehaviors(mob,me,++showNumber,showFlag);
			genAffects(mob,me,++showNumber,showFlag);
			if(me instanceof Rideable)
			{
				genRideable1(mob,(Rideable)me,++showNumber,showFlag);
				genRideable2(mob,(Rideable)me,++showNumber,showFlag);
			}
			if(me instanceof Exit)
			{
				genDoorName(mob,(Exit)me,++showNumber,showFlag);
				genClosedText(mob,(Exit)me,++showNumber,showFlag);
			}
			genImage(mob,me,++showNumber,showFlag);
            for(int x=me.getSaveStatIndex();x<me.getStatCodes().length;x++)
                me.setStat(me.getStatCodes()[x],CMLib.english().promptText(mob,me.getStat(me.getStatCodes()[x]),++showNumber,showFlag,CMStrings.capitalizeAndLower(me.getStatCodes()[x])));
			if(showFlag<-900){ ok=true; break;}
			if(showFlag>0){ showFlag=-1; continue;}
			showFlag=CMath.s_int(mob.session().prompt("Edit which? ",""));
			if(showFlag<=0)
			{
				showFlag=-1;
				ok=true;
				me.recoverEnvStats();
				if(me.text().length()>=maxLength)
				{
					mob.tell("\n\rThe data entered exceeds the string limit of "+maxLength+" characters.  Please modify!");
					ok=false;
				}
			}
		}
	}

	protected void modifyGenWeapon(MOB mob, Weapon me)
		throws IOException
	{
		if(mob.isMonster())
			return;
		boolean ok=false;
		int showFlag=-1;
		if(CMProps.getIntVar(CMProps.SYSTEMI_EDITORTYPE)>0)
			showFlag=-999;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!ok))
		{
			int showNumber=0;
			genName(mob,me,++showNumber,showFlag);
			genDisplayText(mob,me,++showNumber,showFlag);
			genDescription(mob,me,++showNumber,showFlag);
			genLevel(mob,me,++showNumber,showFlag);
			genAttack(mob,me,++showNumber,showFlag);
			genDamage(mob,me,++showNumber,showFlag);
			genMaterialCode(mob,me,++showNumber,showFlag);
			genWeaponType(mob,me,++showNumber,showFlag);
			genWeaponClassification(mob,me,++showNumber,showFlag);
			genWeaponRanges(mob,me,++showNumber,showFlag);
			if(me instanceof Wand)
			{
				genReadable1(mob,me,++showNumber,showFlag);
				genReadable2(mob,me,++showNumber,showFlag);
				genUses(mob,me,++showNumber,showFlag);
				genMaxUses(mob,(Wand)me,++showNumber,showFlag);
				if(me instanceof Light)	genBurnout(mob,(Light)me,++showNumber,showFlag);
			}
			else
				genWeaponAmmo(mob,me,++showNumber,showFlag);
			genRejuv(mob,me,++showNumber,showFlag);
			if((!me.requiresAmmunition())&&(!(me instanceof Wand)))
				genCondition(mob,me,++showNumber,showFlag);
			genAbility(mob,me,++showNumber,showFlag);
			genSecretIdentity(mob,me,++showNumber,showFlag);
			if(me instanceof ClanItem)
				genClanItem(mob,(ClanItem)me,++showNumber,showFlag);
			genGettable(mob,me,++showNumber,showFlag);
			genValue(mob,me,++showNumber,showFlag);
			genWeight(mob,me,++showNumber,showFlag);
			genDisposition(mob,me.baseEnvStats(),++showNumber,showFlag);
			genBehaviors(mob,me,++showNumber,showFlag);
			genAffects(mob,me,++showNumber,showFlag);
			genImage(mob,me,++showNumber,showFlag);
            for(int x=me.getSaveStatIndex();x<me.getStatCodes().length;x++)
                me.setStat(me.getStatCodes()[x],CMLib.english().promptText(mob,me.getStat(me.getStatCodes()[x]),++showNumber,showFlag,CMStrings.capitalizeAndLower(me.getStatCodes()[x])));
			if(showFlag<-900){ ok=true; break;}
			if(showFlag>0){ showFlag=-1; continue;}
			showFlag=CMath.s_int(mob.session().prompt("Edit which? ",""));
			if(showFlag<=0)
			{
				showFlag=-1;
				ok=true;
				me.recoverEnvStats();
				if(me.text().length()>=maxLength)
				{
					mob.tell("\n\rThe data entered exceeds the string limit of "+maxLength+" characters.  Please modify!");
					ok=false;
				}
			}
		}
	}
	protected void modifyGenArmor(MOB mob, Armor me)
		throws IOException
	{
		if(mob.isMonster())
			return;
		boolean ok=false;
		int showFlag=-1;
		if(CMProps.getIntVar(CMProps.SYSTEMI_EDITORTYPE)>0)
			showFlag=-999;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!ok))
		{
			int showNumber=0;
			genName(mob,me,++showNumber,showFlag);
			genDisplayText(mob,me,++showNumber,showFlag);
			genDescription(mob,me,++showNumber,showFlag);
			genLevel(mob,me,++showNumber,showFlag);
			genMaterialCode(mob,me,++showNumber,showFlag);
			genWornLocation(mob,me,++showNumber,showFlag);
			genLayer(mob,me,++showNumber,showFlag);
			genRejuv(mob,me,++showNumber,showFlag);
			genArmor(mob,me,++showNumber,showFlag);
			genCondition(mob,me,++showNumber,showFlag);
			genAbility(mob,me,++showNumber,showFlag);
			genSecretIdentity(mob,me,++showNumber,showFlag);
			if(me instanceof ClanItem)
				genClanItem(mob,(ClanItem)me,++showNumber,showFlag);
			genGettable(mob,me,++showNumber,showFlag);
			genCapacity(mob,me,++showNumber,showFlag);
			genLidsNLocks(mob,me,++showNumber,showFlag);
			genReadable1(mob,me,++showNumber,showFlag);
			genReadable2(mob,me,++showNumber,showFlag);
			if(me instanceof Light)	genBurnout(mob,(Light)me,++showNumber,showFlag);
			genValue(mob,me,++showNumber,showFlag);
			genWeight(mob,me,++showNumber,showFlag);
			genSize(mob,me,++showNumber,showFlag);
			genDisposition(mob,me.baseEnvStats(),++showNumber,showFlag);
			genBehaviors(mob,me,++showNumber,showFlag);
			genAffects(mob,me,++showNumber,showFlag);
			genImage(mob,me,++showNumber,showFlag);
            for(int x=me.getSaveStatIndex();x<me.getStatCodes().length;x++)
                me.setStat(me.getStatCodes()[x],CMLib.english().promptText(mob,me.getStat(me.getStatCodes()[x]),++showNumber,showFlag,CMStrings.capitalizeAndLower(me.getStatCodes()[x])));
			if(showFlag<-900){ ok=true; break;}
			if(showFlag>0){ showFlag=-1; continue;}
			showFlag=CMath.s_int(mob.session().prompt("Edit which? ",""));
			if(showFlag<=0)
			{
				showFlag=-1;
				ok=true;
				me.recoverEnvStats();
				if(me.text().length()>=maxLength)
				{
					mob.tell("\n\rThe data entered exceeds the string limit of "+maxLength+" characters.  Please modify!");
					ok=false;
				}
			}
		}
	}


	protected void modifyGenInstrument(MOB mob, MusicalInstrument me)
		throws IOException
	{
		if(mob.isMonster())
			return;
		boolean ok=false;
		int showFlag=-1;
		if(CMProps.getIntVar(CMProps.SYSTEMI_EDITORTYPE)>0)
			showFlag=-999;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!ok))
		{
			int showNumber=0;
			genName(mob,me,++showNumber,showFlag);
			genDisplayText(mob,me,++showNumber,showFlag);
			genDescription(mob,me,++showNumber,showFlag);
			genLevel(mob,me,++showNumber,showFlag);
			genMaterialCode(mob,me,++showNumber,showFlag);
			genWornLocation(mob,me,++showNumber,showFlag);
			genRejuv(mob,me,++showNumber,showFlag);
			genAbility(mob,me,++showNumber,showFlag);
			genSecretIdentity(mob,me,++showNumber,showFlag);
			genGettable(mob,me,++showNumber,showFlag);
			genInstrumentType(mob,me,++showNumber,showFlag);
			genValue(mob,me,++showNumber,showFlag);
			genWeight(mob,me,++showNumber,showFlag);
			genDisposition(mob,me.baseEnvStats(),++showNumber,showFlag);
			genBehaviors(mob,me,++showNumber,showFlag);
			genAffects(mob,me,++showNumber,showFlag);
			genImage(mob,me,++showNumber,showFlag);
            for(int x=me.getSaveStatIndex();x<me.getStatCodes().length;x++)
                me.setStat(me.getStatCodes()[x],CMLib.english().promptText(mob,me.getStat(me.getStatCodes()[x]),++showNumber,showFlag,CMStrings.capitalizeAndLower(me.getStatCodes()[x])));
			if(showFlag<-900){ ok=true; break;}
			if(showFlag>0){ showFlag=-1; continue;}
			showFlag=CMath.s_int(mob.session().prompt("Edit which? ",""));
			if(showFlag<=0)
			{
				showFlag=-1;
				ok=true;
				me.recoverEnvStats();
				if(me.text().length()>=maxLength)
				{
					mob.tell("\n\rThe data entered exceeds the string limit of "+maxLength+" characters.  Please modify!");
					ok=false;
				}
			}
		}
	}


	protected void modifyGenExit(MOB mob, Exit me)
		throws IOException
	{
		if(mob.isMonster())
			return;
		boolean ok=false;
		int showFlag=-1;
		if(CMProps.getIntVar(CMProps.SYSTEMI_EDITORTYPE)>0)
			showFlag=-999;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!ok))
		{
			int showNumber=0;
			genName(mob,me,++showNumber,showFlag);
			genDisplayText(mob,me,++showNumber,showFlag);
			genDescription(mob,me,++showNumber,showFlag);
			genLevel(mob,me,++showNumber,showFlag);
			genDoorsNLocks(mob,me,++showNumber,showFlag);
			if(me.hasADoor())
			{
				genClosedText(mob,me,++showNumber,showFlag);
				genDoorName(mob,me,++showNumber,showFlag);
				genOpenWord(mob,me,++showNumber,showFlag);
				genCloseWord(mob,me,++showNumber,showFlag);
			}
			genExitMisc(mob,me,++showNumber,showFlag);
			genDisposition(mob,me.baseEnvStats(),++showNumber,showFlag);
			genBehaviors(mob,me,++showNumber,showFlag);
			genAffects(mob,me,++showNumber,showFlag);
			genImage(mob,me,++showNumber,showFlag);
            for(int x=me.getSaveStatIndex();x<me.getStatCodes().length;x++)
                me.setStat(me.getStatCodes()[x],CMLib.english().promptText(mob,me.getStat(me.getStatCodes()[x]),++showNumber,showFlag,CMStrings.capitalizeAndLower(me.getStatCodes()[x])));
			if(showFlag<-900){ ok=true; break;}
			if(showFlag>0){ showFlag=-1; continue;}
			showFlag=CMath.s_int(mob.session().prompt("Edit which? ",""));
			if(showFlag<=0)
			{
				showFlag=-1;
				ok=true;
				me.recoverEnvStats();
				if(me.text().length()>=maxLength)
				{
					mob.tell("\n\rThe data entered exceeds the string limit of "+maxLength+" characters.  Please modify!");
					ok=false;
				}
			}
		}
	}


	protected void modifyGenMOB(MOB mob, MOB me)
		throws IOException
	{
		if(mob.isMonster())
			return;
		boolean ok=false;
		int showFlag=-1;
		if(CMProps.getIntVar(CMProps.SYSTEMI_EDITORTYPE)>0)
			showFlag=-999;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!ok))
		{
			int showNumber=0;
			genName(mob,me,++showNumber,showFlag);
			genDisplayText(mob,me,++showNumber,showFlag);
			genDescription(mob,me,++showNumber,showFlag);
			int oldLevel=me.baseEnvStats().level();
			genLevel(mob,me,++showNumber,showFlag);
			if((oldLevel<2)&&(me.baseEnvStats().level()>1))
				me.baseCharStats().getCurrentClass().fillOutMOB(me,me.baseEnvStats().level());
			genRejuv(mob,me,++showNumber,showFlag);
			genRace(mob,me,++showNumber,showFlag);
			Faction F=null;
			for(Enumeration e=CMLib.factions().factionSet().elements();e.hasMoreElements();)
			{
			    F=(Faction)e.nextElement();
			    if((!F.hasFaction(me))&&(F.findAutoDefault(me)!=Integer.MAX_VALUE))
			        mob.addFaction(F.factionID(),F.findAutoDefault(me));
			    if(F.showineditor())
				    genSpecialFaction(mob,me,++showNumber,showFlag,F);
			}
			genGender(mob,me,++showNumber,showFlag);
			genHeight(mob,me,++showNumber,showFlag);
			genWeight(mob,me,++showNumber,showFlag);
			genClan(mob,me,++showNumber,showFlag);
			genSpeed(mob,me,++showNumber,showFlag);
			if((oldLevel<2)&&(me.baseEnvStats().level()>1))
				me.baseEnvStats().setDamage((int)Math.round(CMath.div(me.baseEnvStats().damage(),me.baseEnvStats().speed())));
			genAttack(mob,me,++showNumber,showFlag);
			genDamage(mob,me,++showNumber,showFlag);
			genArmor(mob,me,++showNumber,showFlag);
			genHitPoints(mob,me,++showNumber,showFlag);
			genMoney(mob,me,++showNumber,showFlag);
			genAbilities(mob,me,++showNumber,showFlag);
			genBehaviors(mob,me,++showNumber,showFlag);
			genAffects(mob,me,++showNumber,showFlag);
			genDisposition(mob,me.baseEnvStats(),++showNumber,showFlag);
			genSensesMask(mob,me.baseEnvStats(),++showNumber,showFlag);
			if(me instanceof Rideable)
			{
				genRideable1(mob,(Rideable)me,++showNumber,showFlag);
				genRideable2(mob,(Rideable)me,++showNumber,showFlag);
			}
			if(me instanceof Deity)
			{
				genDeity1(mob,(Deity)me,++showNumber,showFlag);
				genDeity2(mob,(Deity)me,++showNumber,showFlag);
				genDeity3(mob,(Deity)me,++showNumber,showFlag);
				genDeity4(mob,(Deity)me,++showNumber,showFlag);
				genDeity5(mob,(Deity)me,++showNumber,showFlag);
				genDeity8(mob,(Deity)me,++showNumber,showFlag);
				genDeity9(mob,(Deity)me,++showNumber,showFlag);
				genDeity6(mob,(Deity)me,++showNumber,showFlag);
				genDeity0(mob,(Deity)me,++showNumber,showFlag);
				genDeity7(mob,(Deity)me,++showNumber,showFlag);
                genDeity11(mob,(Deity)me,++showNumber,showFlag);
			}
			genFaction(mob,me,++showNumber,showFlag);
			genTattoos(mob,me,++showNumber,showFlag);
			genExpertises(mob,me,++showNumber,showFlag);
			genImage(mob,me,++showNumber,showFlag);
            for(int x=me.getSaveStatIndex();x<me.getStatCodes().length;x++)
                me.setStat(me.getStatCodes()[x],CMLib.english().promptText(mob,me.getStat(me.getStatCodes()[x]),++showNumber,showFlag,CMStrings.capitalizeAndLower(me.getStatCodes()[x])));
			if(showFlag<-900){ ok=true; break;}
			if(showFlag>0){ showFlag=-1; continue;}
			showFlag=CMath.s_int(mob.session().prompt("Edit which? ",""));
			if(showFlag<=0)
			{
				showFlag=-1;
				ok=true;
				me.recoverCharStats();
				me.recoverMaxState();
				me.recoverEnvStats();
				me.resetToMaxState();
				if(me.text().length()>=maxLength)
				{
					mob.tell("\n\rThe data entered exceeds the string limit of "+maxLength+" characters.  Please modify!");
					ok=false;
				}
				me.setMiscText(me.text());
			}
		}

		mob.tell("\n\rNow don't forget to equip "+me.charStats().himher()+" with stuff before saving!\n\r");
	}

	protected void modifyPlayer(MOB mob, MOB me)
		throws IOException
	{
		if(mob.isMonster())
			return;
		boolean ok=false;
		int showFlag=-1;
		if(CMProps.getIntVar(CMProps.SYSTEMI_EDITORTYPE)>0)
			showFlag=-999;
		String oldName=me.Name();
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!ok))
		{
			int showNumber=0;
			genName(mob,me,++showNumber,showFlag);
			while((!me.Name().equals(oldName))&&(CMLib.database().DBUserSearch(null,me.Name())))
			{
				mob.tell("The name given cannot be chosen, as it is already being used.");
				genName(mob,me,showNumber,showFlag);
			}
			genPassword(mob,me,++showNumber,showFlag);

			genDescription(mob,me,++showNumber,showFlag);
			genLevel(mob,me,++showNumber,showFlag);
			genRace(mob,me,++showNumber,showFlag);
			genCharClass(mob,me,++showNumber,showFlag);
			genCharStats(mob,me,++showNumber,showFlag);
			Faction F=null;
			for(Enumeration e=CMLib.factions().factionSet().elements();e.hasMoreElements();)
			{
			    F=(Faction)e.nextElement();
			    if((!F.hasFaction(me))&&(F.findAutoDefault(me)!=Integer.MAX_VALUE))
			        mob.addFaction(F.factionID(),F.findAutoDefault(me));
			    if(F.showineditor())
				    genSpecialFaction(mob,me,++showNumber,showFlag,F);
			}
			genGender(mob,me,++showNumber,showFlag);
			genHeight(mob,me,++showNumber,showFlag);
			genWeight(mob,me,++showNumber,showFlag);
			genSpeed(mob,me,++showNumber,showFlag);
			genAttack(mob,me,++showNumber,showFlag);
			genDamage(mob,me,++showNumber,showFlag);
			genArmor(mob,me,++showNumber,showFlag);
			genHitPoints(mob,me,++showNumber,showFlag);
			genMoney(mob,me,++showNumber,showFlag);
            me.setTrains(CMLib.english().promptInteger(mob,me.getTrains(),++showNumber,showFlag,"Training Points"));
            me.setPractices(CMLib.english().promptInteger(mob,me.getPractices(),++showNumber,showFlag,"Practice Points"));
            me.setQuestPoint(CMLib.english().promptInteger(mob,me.getQuestPoint(),++showNumber,showFlag,"Quest Points"));
			genAbilities(mob,me,++showNumber,showFlag);
			genAffects(mob,me,++showNumber,showFlag);
			genBehaviors(mob,me,++showNumber,showFlag);
			genDisposition(mob,me.baseEnvStats(),++showNumber,showFlag);
			genSensesMask(mob,me.baseEnvStats(),++showNumber,showFlag);
			if(me instanceof Rideable)
			{
				genRideable1(mob,(Rideable)me,++showNumber,showFlag);
				genRideable2(mob,(Rideable)me,++showNumber,showFlag);
			}
			genFaction(mob,me,++showNumber,showFlag);
			genTattoos(mob,me,++showNumber,showFlag);
			genExpertises(mob,me,++showNumber,showFlag);
			genTitles(mob,me,++showNumber,showFlag);
			genEmail(mob,me,++showNumber,showFlag);
			genSecurity(mob,me,++showNumber,showFlag);
			genImage(mob,me,++showNumber,showFlag);
			genNotes(mob,me,++showNumber,showFlag);
            for(int x=me.getSaveStatIndex();x<me.getStatCodes().length;x++)
                me.setStat(me.getStatCodes()[x],CMLib.english().promptText(mob,me.getStat(me.getStatCodes()[x]),++showNumber,showFlag,CMStrings.capitalizeAndLower(me.getStatCodes()[x])));
            if(me.playerStats()!=null)
            for(int x=me.playerStats().getSaveStatIndex();x<me.playerStats().getStatCodes().length;x++)
                me.setStat(me.playerStats().getStatCodes()[x],CMLib.english().promptText(mob,me.playerStats().getStat(me.playerStats().getStatCodes()[x]),++showNumber,showFlag,CMStrings.capitalizeAndLower(me.playerStats().getStatCodes()[x])));
			if(showFlag<-900){ ok=true; break;}
			if(showFlag>0){ showFlag=-1; continue;}
			showFlag=CMath.s_int(mob.session().prompt("Edit which? ",""));
			if(showFlag<=0)
			{
				showFlag=-1;
				ok=true;
				me.recoverCharStats();
				me.recoverMaxState();
				me.recoverEnvStats();
				me.resetToMaxState();
				if(!oldName.equals(me.Name()))
				{
					MOB fakeMe=(MOB)me.copyOf();
					fakeMe.setName(oldName);
					CMLib.database().DBDeleteMOB(fakeMe);
					CMLib.database().DBCreateCharacter(me);
				}
				CMLib.database().DBUpdatePlayer(me);
				CMLib.database().DBUpdateFollowers(me);
			}
		}
	}

	
	protected void genClanStatus(MOB mob, Clan C, int showNumber, int showFlag)
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Clan Status: "+Clan.CLANSTATUS_DESC[C.getStatus()]);
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		switch(C.getStatus())
		{
		case Clan.CLANSTATUS_ACTIVE:
			C.setStatus(Clan.CLANSTATUS_PENDING);
			mob.tell("Clan '"+C.name()+"' has been changed from active to pending!");
			break;
		case Clan.CLANSTATUS_PENDING:
			C.setStatus(Clan.CLANSTATUS_ACTIVE);
			mob.tell("Clan '"+C.name()+"' has been changed from pending to active!");
			break;
		case Clan.CLANSTATUS_FADING:
			C.setStatus(Clan.CLANSTATUS_ACTIVE);
			mob.tell("Clan '"+C.name()+"' has been changed from fading to active!");
			break;
		default:
			mob.tell("Clan '"+C.name()+"' has not been changed!");
			break;
		}
	}
	
	protected void genClanGovt(MOB mob, Clan C, int showNumber, int showFlag)
	throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Government type: '"+C.typeName()+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		while((mob.session()!=null)&&(!mob.session().killFlag()))
		{
			String newName=mob.session().prompt("Enter a new one (?)\n\r:","");
			if(newName.trim().length()==0)
			{
				mob.tell("(no change)");
				return;
			}
			int newGovt=-1;
			StringBuffer gvts=new StringBuffer();
			for(int i=0;i<Clan.GVT_DESCS.length;i++)
			{
				gvts.append(Clan.GVT_DESCS[i]+", ");
				if(newName.equalsIgnoreCase(Clan.GVT_DESCS[i]))
					newGovt=i;
			}
			gvts=new StringBuffer(gvts.substring(0,gvts.length()-2));
			if(newGovt<0)
				mob.tell("That government type is invalid.  Valid types include: "+gvts.toString());
			else
			{
				C.setGovernment(newGovt);
				break;
			}
		}
	}
	
	protected void genClanRole(MOB mob, Clan C, int showNumber, int showFlag)
	throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		mob.tell(showNumber+". Clan (Role): '"+CMLib.clans().getRoleName(C.getGovernment(),C.getAutoPosition(),true,false)+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		while((mob.session()!=null)&&(!mob.session().killFlag()))
		{
			String newName=mob.session().prompt("Enter a new one (?)\n\r:","");
			if(newName.trim().length()==0)
			{
				mob.tell("(no change)");
				return;
			}
			int newRole=-1;
			StringBuffer roles=new StringBuffer();
			for(int i=0;i<Clan.ROL_DESCS[C.getGovernment()].length;i++)
			{
				roles.append(Clan.ROL_DESCS[C.getGovernment()][i]+", ");
				if(newName.equalsIgnoreCase(Clan.ROL_DESCS[C.getGovernment()][i]))
					newRole=Clan.POSORDER[i];
			}
			roles=new StringBuffer(roles.substring(0,roles.length()-2));
			if(newRole<0)
				mob.tell("That role is invalid.  Valid roles include: "+roles.toString());
			else
			{
				C.setAutoPosition(newRole);
				break;
			}
		}
	}
	
	protected void genClanClass(MOB mob, Clan C, int showNumber, int showFlag)
	throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return;
		CharClass CC=CMClass.getCharClass(C.getClanClass());
		if(CC==null)CC=CMClass.findCharClass(C.getClanClass());
		String clasName=(CC==null)?"NONE":CC.name();
		mob.tell(showNumber+". Clan Auto-Class: '"+clasName+"'.");
		if((showFlag!=showNumber)&&(showFlag>-999)) return;
		while((mob.session()!=null)&&(!mob.session().killFlag()))
		{
			String newName=mob.session().prompt("Enter a new one (?)\n\r:","");
			if(newName.trim().equalsIgnoreCase("none"))
			{
				C.setClanClass("");
				return;
			}
			else
			if(newName.trim().length()==0)
			{
				mob.tell("(no change)");
				return;
			}
			CharClass newC=null;
			StringBuffer clss=new StringBuffer();
			for(Enumeration e=CMClass.charClasses();e.hasMoreElements();)
			{
				CC=(CharClass)e.nextElement();
				clss.append(CC.name()+", ");
				if(newName.equalsIgnoreCase(CC.name())||(newName.equalsIgnoreCase(CC.ID())))
					newC=CC;
			}
			clss=new StringBuffer(clss.substring(0,clss.length()-2));
			if(newC==null)
				mob.tell("That class name is invalid.  Valid names include: "+clss.toString());
			else
			{
				C.setClanClass(newC.ID());
				break;
			}
		}
	}
	
	String genClanRoom(MOB mob, Clan C, String oldRoomID, String promptCode, int showNumber, int showFlag)
	throws IOException
	{
		if((showFlag>0)&&(showFlag!=showNumber)) return oldRoomID;
		mob.tell(showNumber+CMStrings.replaceAll(promptCode,"@x1",oldRoomID));
		if((showFlag!=showNumber)&&(showFlag>-999)) return oldRoomID;
		while((mob.session()!=null)&&(!mob.session().killFlag()))
		{
			String newName=mob.session().prompt("Enter a new one (null)\n\r:","");
			if(newName.trim().equalsIgnoreCase("null"))
				return "";
			else
			if(newName.trim().length()==0)
			{
				mob.tell("(no change)");
				return oldRoomID;
			}
			Room newRoom=CMLib.map().getRoom(newName);
			if((newRoom==null)
			||(CMLib.map().getExtendedRoomID(newRoom).length()==0)
			||(!CMLib.law().doesOwnThisProperty(C.clanID(),newRoom)))
				mob.tell("That is either not a valid room id, or that room is not owned by the clan.");
			else
				return CMLib.map().getExtendedRoomID(newRoom);
		}
		return oldRoomID;
	}
    
	protected void modifyClan(MOB mob, Clan C)
	throws IOException
	{
		if(mob.isMonster())
			return;
		boolean ok=false;
		int showFlag=-1;
		if(CMProps.getIntVar(CMProps.SYSTEMI_EDITORTYPE)>0)
			showFlag=-999;
		String oldName=C.ID();
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!ok))
		{
			mob.tell("*. Name: '"+C.name()+"'.");
			int showNumber=0;
			genClanGovt(mob,C,++showNumber,showFlag);
			C.setPremise(CMLib.english().promptText(mob,C.getPremise(),++showNumber,showFlag,"Clan Premise: ",true));
			C.setExp(CMLib.english().promptLong(mob,C.getExp(),++showNumber,showFlag,"Clan Experience: "));
			C.setTaxes(CMLib.english().promptDouble(mob,C.getTaxes(),++showNumber,showFlag,"Clan Tax Rate (X 100%): "));
			C.setMorgue(genClanRoom(mob,C,C.getMorgue(),". Morgue RoomID: '@x1'.",++showNumber,showFlag));
			C.setRecall(genClanRoom(mob,C,C.getRecall(),". Clan Home RoomID: '@x1'.",++showNumber,showFlag));
			C.setDonation(genClanRoom(mob,C,C.getDonation(),". Clan Donate RoomID: '@x1'.",++showNumber,showFlag));
			genClanAccept(mob,C,++showNumber,showFlag);
			genClanClass(mob,C,++showNumber,showFlag);
			genClanRole(mob,C,++showNumber,showFlag);
			genClanStatus(mob,C,++showNumber,showFlag);
			genClanMembers(mob,C,++showNumber,showFlag);
			/*setClanRelations, votes?*/
			if(showFlag<-900){ ok=true; break;}
			if(showFlag>0){ showFlag=-1; continue;}
			showFlag=CMath.s_int(mob.session().prompt("Edit which? ",""));
			if(showFlag<=0)
			{
				showFlag=-1;
				ok=true;
				if(!oldName.equals(C.ID()))
				{
					//cycle through everything changing the name
					CMLib.database().DBDeleteClan(C);
					CMLib.database().DBCreateClan(C);
				}
				C.update();
			}
		}
	}
	
	protected void modifyGenShopkeeper(MOB mob, ShopKeeper me)
		throws IOException
	{
		if(mob.isMonster())
			return;
		if(!(me instanceof MOB))
			return;
		MOB mme=(MOB)me;
		boolean ok=false;
		int showFlag=-1;
		if(CMProps.getIntVar(CMProps.SYSTEMI_EDITORTYPE)>0)
			showFlag=-999;
		while((mob.session()!=null)&&(!mob.session().killFlag())&&(!ok))
		{
			int showNumber=0;
			genName(mob,me,++showNumber,showFlag);
			genDisplayText(mob,me,++showNumber,showFlag);
			genDescription(mob,me,++showNumber,showFlag);
			int oldLevel=me.baseEnvStats().level();
			genLevel(mob,me,++showNumber,showFlag);
			if((oldLevel<2)&&(me.baseEnvStats().level()>1))
				mme.baseCharStats().getCurrentClass().fillOutMOB(mme,me.baseEnvStats().level());
			genRejuv(mob,me,++showNumber,showFlag);
			genRace(mob,mme,++showNumber,showFlag);
			genHeight(mob,me,++showNumber,showFlag);
			genWeight(mob,me,++showNumber,showFlag);
			Faction F=null;
			for(Enumeration e=CMLib.factions().factionSet().elements();e.hasMoreElements();)
			{
			    F=(Faction)e.nextElement();
			    if((!F.hasFaction((MOB)me))&&(F.findAutoDefault((MOB)me)!=Integer.MAX_VALUE))
			        mob.addFaction(F.factionID(),F.findAutoDefault((MOB)me));
			    if(F.showineditor())
				    genSpecialFaction(mob,(MOB)me,++showNumber,showFlag,F);
			}
			genGender(mob,mme,++showNumber,showFlag);
			genClan(mob,mme,++showNumber,showFlag);
			genSpeed(mob,me,++showNumber,showFlag);
			if((oldLevel<2)&&(me.baseEnvStats().level()>1))
				me.baseEnvStats().setDamage((int)Math.round(CMath.div(me.baseEnvStats().damage(),me.baseEnvStats().speed())));
			genAttack(mob,me,++showNumber,showFlag);
			genDamage(mob,me,++showNumber,showFlag);
			genArmor(mob,me,++showNumber,showFlag);
			if(me instanceof MOB)
				genHitPoints(mob,(MOB)me,++showNumber,showFlag);
			genMoney(mob,mme,++showNumber,showFlag);
			genAbilities(mob,mme,++showNumber,showFlag);
			genBehaviors(mob,me,++showNumber,showFlag);
			genAffects(mob,me,++showNumber,showFlag);
			genShopkeeper1(mob,me,++showNumber,showFlag);
			genShopkeeper2(mob,me,++showNumber,showFlag);
            genEconomics1(mob,me,++showNumber,showFlag);
            genEconomics5(mob,me,++showNumber,showFlag);
            genEconomics6(mob,me,++showNumber,showFlag);
			if(me instanceof Banker)
			{
				genBanker1(mob,(Banker)me,++showNumber,showFlag);
				genBanker2(mob,(Banker)me,++showNumber,showFlag);
				genBanker3(mob,(Banker)me,++showNumber,showFlag);
				genBanker4(mob,(Banker)me,++showNumber,showFlag);
			}
			else
            if(me instanceof PostOffice)
            {
                ((PostOffice)me).setPostalChain(CMLib.english().promptText(mob,((PostOffice)me).postalChain(),++showNumber,showFlag,"Postal chain"));
                ((PostOffice)me).setFeeForNewBox(CMLib.english().promptDouble(mob,((PostOffice)me).feeForNewBox(),++showNumber,showFlag,"Fee to open a new box"));
                ((PostOffice)me).setMinimumPostage(CMLib.english().promptDouble(mob,((PostOffice)me).minimumPostage(),++showNumber,showFlag,"Minimum postage cost"));
                ((PostOffice)me).setPostagePerPound(CMLib.english().promptDouble(mob,((PostOffice)me).postagePerPound(),++showNumber,showFlag,"Postage cost per pound after 1st pound"));
                ((PostOffice)me).setHoldFeePerPound(CMLib.english().promptDouble(mob,((PostOffice)me).holdFeePerPound(),++showNumber,showFlag,"Holding fee per pound per month"));
                ((PostOffice)me).setMaxMudMonthsHeld(CMLib.english().promptInteger(mob,((PostOffice)me).maxMudMonthsHeld(),++showNumber,showFlag,"Maximum number of months held"));
            }
            else
			{
                genEconomics2(mob,me,++showNumber,showFlag);
                genEconomics3(mob,me,++showNumber,showFlag);
                genEconomics4(mob,me,++showNumber,showFlag);
			}
			genDisposition(mob,me.baseEnvStats(),++showNumber,showFlag);
			genSensesMask(mob,me.baseEnvStats(),++showNumber,showFlag);
			genFaction(mob,mme,++showNumber,showFlag);
			genTattoos(mob,(MOB)me,++showNumber,showFlag);
			genExpertises(mob,(MOB)me,++showNumber,showFlag);
			genImage(mob,me,++showNumber,showFlag);
            for(int x=me.getSaveStatIndex();x<me.getStatCodes().length;x++)
                me.setStat(me.getStatCodes()[x],CMLib.english().promptText(mob,me.getStat(me.getStatCodes()[x]),++showNumber,showFlag,CMStrings.capitalizeAndLower(me.getStatCodes()[x])));
			if(showFlag<-900){ ok=true; break;}
			if(showFlag>0){ showFlag=-1; continue;}
			showFlag=CMath.s_int(mob.session().prompt("Edit which? ",""));
			if(showFlag<=0)
			{
				showFlag=-1;
				ok=true;
				mme.recoverCharStats();
				mme.recoverMaxState();
				me.recoverEnvStats();
				mme.resetToMaxState();
				if(me.text().length()>=maxLength)
				{
					mob.tell("\n\rThe data entered exceeds the string limit of "+maxLength+" characters.  Please modify!");
					ok=false;
				}
				me.setMiscText(me.text());
			}
		}
		mob.tell("\n\rNow don't forget to equip him with non-generic items before saving! If you DO add items to his list, be sure to come back here in case you've exceeded the string limit again.\n\r");
	}
}