<NME> StdRoom.java
<BEF> package com.planet_ink.coffee_mud.Locales;
import com.planet_ink.coffee_mud.Libraries.interfaces.*;
import com.planet_ink.coffee_mud.Libraries.interfaces.AchievementLibrary.Event;
import com.planet_ink.coffee_mud.core.interfaces.*;
import com.planet_ink.coffee_mud.core.interfaces.EachApplicable.ApplyAffectPhyStats;
import com.planet_ink.coffee_mud.core.interfaces.ItemPossessor.Expire;
import com.planet_ink.coffee_mud.core.interfaces.ItemPossessor.Move;
import com.planet_ink.coffee_mud.core.*;
import com.planet_ink.coffee_mud.core.collections.*;
import com.planet_ink.coffee_mud.Abilities.interfaces.*;
import com.planet_ink.coffee_mud.Areas.interfaces.*;
import com.planet_ink.coffee_mud.Behaviors.interfaces.*;
import com.planet_ink.coffee_mud.CharClasses.interfaces.*;
import com.planet_ink.coffee_mud.Commands.interfaces.*;
import com.planet_ink.coffee_mud.Common.interfaces.*;
import com.planet_ink.coffee_mud.Exits.interfaces.*;
import com.planet_ink.coffee_mud.Items.Basic.StdItem;
import com.planet_ink.coffee_mud.Items.interfaces.*;
import com.planet_ink.coffee_mud.Locales.interfaces.*;
import com.planet_ink.coffee_mud.MOBS.interfaces.*;
import com.planet_ink.coffee_mud.Races.interfaces.*;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
/*
   Copyright 2001-2022 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
   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 StdRoom implements Room
{
	@Override
	public String ID()
	{
		return "StdRoom";
	}

	protected String			_roomID				= "";
	protected String			name				= "the room";
	protected String			displayText			= L("Standard Room");
	protected String			rawImageName		= null;
	protected String			cachedImageName		= null;
	protected Object			description			= null;
	protected Area				myArea				= null;
	protected PhyStats			phyStats			= (PhyStats) CMClass.getCommon("DefaultPhyStats");
	protected PhyStats			basePhyStats		= (PhyStats) CMClass.getCommon("DefaultPhyStats");
	protected Exit[]			exits				= new Exit[Directions.NUM_DIRECTIONS()];
	protected Room[]			doors				= new Room[Directions.NUM_DIRECTIONS()];
	protected String[]			xtraValues			= null;
	protected boolean			mobility			= true;
	protected GridLocale		gridParent			= null;
	protected int				tickStatus			= Tickable.STATUS_NOT;
	protected long				expirationDate		= 0;
	protected int				atmosphere			= ATMOSPHERE_INHERIT;
	protected int				climask				= CLIMASK_INHERIT;
	protected int				myResource			= -1;
	protected long				lastResourceTime	= 0;
	protected boolean			amDestroyed			= false;
	protected boolean			skyedYet			= false;
	protected volatile short	combatTurnMobIndex	= 0;

	protected final AtomicInteger		roomRecoverMarker	= new AtomicInteger();
	protected SVector<Ability>			affects				= null;
	protected SVector<Behavior>			behaviors			= null;
	protected SVector<ScriptingEngine>	scripts				= null;
	protected SVector<MOB>				inhabitants			= new SVector<MOB>(1);
	protected SVector<Item>				contents			= new SVector<Item>(1);
	protected Room						me					= this;

	@SuppressWarnings("rawtypes")
	protected ApplyAffectPhyStats affectPhyStats 	= new ApplyAffectPhyStats<Physical>(this);
	// base move points and thirst points per round

	public StdRoom()
	{
		super();
		//CMClass.bumpCounter(this,CMClass.CMObjectType.LOCALE);//removed for mem & perf
		xtraValues=CMProps.getExtraStatCodesHolder(this);
		setMovementCost(2); // movement consumption
		setRoomSize(((domainType()&Room.INDOORS)>0)?1:10);
		recoverPhyStats();
	}

	/*
	protected void finalize()
	{
		CMClass.unbumpCounter(this, CMClass.CMObjectType.LOCALE);
	}// removed for mem & perf
	*/

	@Override
	public void initializeClass()
	{
	}

	@Override
	public CMObject newInstance()
	{
		try
		{
			return this.getClass().newInstance();
		}
		catch(final Exception e)
		{
			Log.errOut(ID(),e);
		}
		return new StdRoom();
	}

	@Override
	public String roomID()
	{
		return _roomID	;
	}

	@Override
	public String Name()
	{
		return name;
	}

	@Override
	public void setName(final String newName)
	{
		name=newName;
	}

	@Override
	public String name()
	{
		if(phyStats().newName()!=null)
			return phyStats().newName();
		return name;
	}

	@Override
	public String name(final MOB viewerMob)
	{
		return name();
	}

	@Override
	public String genericName()
	{
		final String domainName;
		if((domainType()&Room.INDOORS)==0)
			domainName=CMLib.english().startWithAorAn(Room.DOMAIN_OUTDOOR_DESCS[domainType()].toLowerCase());
		else
			domainName=CMLib.english().startWithAorAn(Room.DOMAIN_INDOORS_DESCS[CMath.unsetb(domainType(),Room.INDOORS)].toLowerCase());
		return L("@x1 place",domainName);

	}

	protected void setMovementCost(final int newCost)
	{
		basePhyStats().setWeight(newCost); // movement consumption
		recoverPhyStats();
	}

	protected int getMovementCost()
	{
		return phyStats().weight(); // movement consumption
	}

	protected void setRoomSize(final int newSize)
	{
		basePhyStats().setHeight(newSize);
		recoverPhyStats();
	}

	protected int getRoomSize()
	{
		return phyStats().height();
	}

	@Override
	public int getAtmosphereCode()
	{
		return atmosphere;
	}

	@Override
	public void setAtmosphere(final int resourceCode)
	{
		atmosphere=resourceCode;
	}

	@Override
	public int getAtmosphere()
	{
		if(getGridParent()!=null)
			return getGridParent().getAtmosphere();
		else
		if(getAtmosphereCode()!=ATMOSPHERE_INHERIT)
			return getAtmosphereCode();
		else
			return (myArea==null)?RawMaterial.RESOURCE_AIR:myArea.getAtmosphere();
	}

	@Override
	public String image()
	{
		if(cachedImageName==null)
		{
			if((rawImageName!=null)&&(rawImageName.length()>0))
				cachedImageName=rawImageName;
			else
				cachedImageName=CMLib.protocol().getDefaultMXPImage(this);
		}
		return cachedImageName;
	}

	@Override
	public String rawImage()
	{
		if(rawImageName==null)
			return "";
		return rawImageName;
	}

	@Override
	public void setImage(final String newImage)
	{
		if((newImage==null)||(newImage.trim().length()==0))
			rawImageName=null;
		else
			rawImageName=newImage;
		if((cachedImageName!=null)&&(!cachedImageName.equals(newImage)))
			cachedImageName=null;
	}

	@Override
	public boolean isGeneric()
	{
		return false;
	}

	@SuppressWarnings("rawtypes")
	protected void cloneFix(final Room R)
	{
		me=this;
		basePhyStats=(PhyStats)R.basePhyStats().copyOf();
		phyStats=(PhyStats)R.phyStats().copyOf();

		affectPhyStats = new ApplyAffectPhyStats(this);

		contents=new SVector<Item>();
		inhabitants=new SVector<MOB>();
		affects=null;
		behaviors=null;
		scripts=null;
		exits=new Exit[exits.length];
		Arrays.fill(exits, null);
		doors=new Room[doors.length];
		Arrays.fill(doors, null);
		for(int d=R.rawDoors().length-1;d>=0;d--)
		{
			if(R.getRawExit(d)!=null)
				exits[d]=(Exit)R.getRawExit(d).copyOf();
			if(R.rawDoors()[d]!=null)
				doors[d]=R.rawDoors()[d];
		}
		for(int i=0;i<R.numItems();i++)
		{
			final Item I2=R.getItem(i);
			if(I2!=null)
			{
				final Item I=(Item)I2.copyOf();
				I.setOwner(this);
				contents.addElement(I);
			}
		}
		for(int i=0;i<numItems();i++)
		{
			final Item I2=getItem(i);
			if((I2!=null)
			&&(I2.container()!=null)
			&&(!isContent(I2.container())))
			{
				for(int ii=0;ii<R.numItems();ii++)
				{
					if((R.getItem(ii)==I2.container())&&(ii<numItems()))
					{
						I2.setContainer((Container)getItem(ii));
						break;
					}
				}
			}
		}
		for(final Enumeration<MOB> m=R.inhabitants();m.hasMoreElements();)
		{
			final MOB M2=m.nextElement();
			if(M2.isSavable())
			{
				final MOB M=(MOB)M2.copyOf();
				if(M.getStartRoom()==R)
					M.setStartRoom(this);
				M.setLocation(this);
				inhabitants.addElement(M);
			}
		}
		for(final Enumeration<Ability> a=R.effects();a.hasMoreElements();)
		{
			final Ability A=a.nextElement();
			if(!A.canBeUninvoked())
				addEffect((Ability)A.copyOf());
		}
		for(final Enumeration<Behavior> e=R.behaviors();e.hasMoreElements();)
		{
			final Behavior B=e.nextElement();
			addBehavior((Behavior)B.copyOf());
		}
		for(final Enumeration<ScriptingEngine> e=R.scripts();e.hasMoreElements();)
		{
			final ScriptingEngine SE=e.nextElement();
			addScript((ScriptingEngine)SE.copyOf());
		}
	}

	@Override
	public CMObject copyOf()
	{
		try
		{
			final StdRoom R=(StdRoom)this.clone();
			//CMClass.bumpCounter(R,CMClass.CMObjectType.LOCALE);//removed for mem & perf
			R.xtraValues=(xtraValues==null)?null:(String[])xtraValues.clone();
			R.cloneFix(this);
			return R;

		}
		catch(final CloneNotSupportedException e)
		{
			return this.newInstance();
		}
	}

	@Override
	public int domainType()
	{
		return Room.DOMAIN_OUTDOORS_CITY;
	}

	@Override
	public int getClimateTypeCode()
	{
		return climask;
	}

	@Override
	public void setClimateType(final int climask)
	{
		this.climask=climask;
	}

	@Override
	public int getClimateType()
	{
		if(getGridParent()!=null)
			return getGridParent().getClimateType();
		else
		if(getClimateTypeCode()!=CLIMASK_INHERIT)
			return getClimateTypeCode();
		else
			return (myArea==null)?CLIMASK_NORMAL:myArea.getClimateType();
	}

	@Override
	public long expirationDate()
	{
		return expirationDate;
	}

	@Override
	public void setExpirationDate(final long time)
	{
		expirationDate=time;
	}

	@Override
	public void setRawExit(final int direction, final Exit to)
	{
		if((direction<0)||(direction>=exits.length))
			return;
		final Exit E=exits[direction];
		if(E==to)
			return;
		if(E!=null)
			E.exitUsage((short)-1);
		if(to !=null )
		{
			to.exitUsage((short)1);
			exits[direction]=to;
		}
		else
			exits[direction]=null;

		/**
		 * cant be done
		 *
		if((E!=null)&&(E.exitUsage((short)0)==0))
			E.destroy();
		 */
	}

	@Override
	public String displayText()
	{
		return displayText;
	}

	@Override
	public void setDisplayText(final String newDisplayText)
	{
		displayText=newDisplayText;
	}

	@Override
	public String description()
	{
		if(description == null)
		{
			if(CMProps.getBoolVar(CMProps.Bool.ROOMDNOCACHE)&&(roomID().trim().length()>0))
			{
				final String txt=CMLib.database().DBReadRoomDesc(roomID());
				if(txt==null)
				{
					Log.errOut("Unable to recover description for "+roomID()+".");
					return "";
				}
				return txt;
			}
			return "";
		}
		else
		if(description instanceof byte[])
		{
			final byte[] descriptionBytes=(byte[])description;
			if(CMProps.getBoolVar(CMProps.Bool.ROOMDCOMPRESS))
				return CMLib.encoder().decompressString(descriptionBytes);
			return CMStrings.bytesToStr(descriptionBytes);
		}
		else
			return ((String)description);
	}

	@Override
	public void setDescription(final String newDescription)
	{
		if(newDescription.length()==0)
			description=null;
		else
		if(CMProps.getBoolVar(CMProps.Bool.ROOMDCOMPRESS))
			description=CMLib.encoder().compressString(newDescription);
		else
			description=newDescription;
	}

	@Override
	public String text()
	{
		return CMLib.coffeeMaker().getEnvironmentalMiscTextXML(this,true);
	}

	@Override
	public String miscTextFormat()
	{
		return CMParms.FORMAT_UNDEFINED;
	}

	@Override
	public void setMiscText(final String newMiscText)
	{
		if(newMiscText.trim().length()>0)
			CMLib.coffeeMaker().unpackEnvironmentalMiscTextXML(this,newMiscText,true);
	}

	@Override
	public void setRoomID(final String newID)
	{
		if((_roomID!=null)&&(!_roomID.equals(newID)))
		{
			_roomID=newID;
			if(myArea!=null)
			{
				// force the re-sort
				myArea.delProperRoom(this);
				myArea.addProperRoom(this);
			}
		}
		else
			_roomID=newID;
	}

	@Override
	public Area getArea()
	{
		if(myArea==null)
			return CMClass.randomArea();
		return myArea;
	}

	@Override
	public void setArea(final Area newArea)
	{
		if(newArea!=myArea)
		{
			if(myArea!=null)
				myArea.delProperRoom(this);
			myArea=newArea;
			if(myArea!=null)
				myArea.addProperRoom(this);
		}
	}

	@Override
	public void setGridParent(final GridLocale room)
	{
		gridParent=room;
	}

	@Override
	public GridLocale getGridParent()
	{
		return gridParent;
	}

	@Override
	public void giveASky(final int depth)
	{
		if(skyedYet)
			return;
		if(depth>1000)
			return;

		final Area A=getArea();
		if(A==null)
			return;
		skyedYet=true;
		if((roomID().length()==0)
		&&(getGridParent()!=null)
		&&(getGridParent().roomID().length()==0))
			return;

		if((rawDoors()[Directions.UP]==null)
		&&((domainType()&Room.INDOORS)==0)
		&&(domainType()!=Room.DOMAIN_OUTDOORS_UNDERWATER)
		&&(domainType()!=Room.DOMAIN_OUTDOORS_AIR)
		&&(CMProps.getIntVar(CMProps.Int.SKYSIZE)!=0))
		{
			Exit upE=null;
			final Exit dnE=CMClass.getExit("StdOpenDoorway");
			if(CMProps.getIntVar(CMProps.Int.SKYSIZE)>0)
				upE=dnE;
			else
				upE=CMClass.getExit("UnseenWalkway");

			final GridLocale sky=(GridLocale)CMClass.getLocale("EndlessThinSky");
			sky.setRoomID("");
			sky.setArea(getArea());
			rawDoors()[Directions.UP]=sky;
			setRawExit(Directions.UP,upE);
			sky.rawDoors()[Directions.DOWN]=this;
			sky.setRawExit(Directions.DOWN,dnE);

			if(!(getArea() instanceof Boardable))
			{
				for(int d=rawDoors().length-1;d>=0;d--)
				{
					if((d!=Directions.UP)
					&&(d!=Directions.DOWN))
					{
						Room thatRoom=rawDoors()[d];
						if((thatRoom!=null)&&(getRawExit(d)!=null))
						{
							thatRoom=CMLib.map().getRoom(thatRoom);
							if(thatRoom != null)
							{
								thatRoom.giveASky(depth+1);
								final Room thatSky=thatRoom.rawDoors()[Directions.UP];
								if((thatSky!=null)
								&&(thatSky.roomID().length()==0)
								&&((thatSky instanceof EndlessThinSky)||(thatSky instanceof EndlessSky)))
								{
									Exit xo=getRawExit(d);
									if(xo!=null)
									{
										if(xo.hasADoor())
											xo=dnE;
										sky.rawDoors()[d]=thatSky;
										sky.setRawExit(d,xo);
									}
									final int opDir=Directions.getOpDirectionCode(d);
									xo=thatRoom.getRawExit(opDir);
									if(xo!=null)
									{
										if(xo.hasADoor())
											xo=dnE;
										thatSky.rawDoors()[opDir]=sky;
										thatSky.setRawExit(opDir,xo);
									}
									((GridLocale)thatSky).clearGrid(null);
								}
							}
						}
					}
				}
			}
			sky.clearGrid(null);
		}
	}

	@Override
	public List<Room> getSky()
	{
		final List<Room> skys = new Vector<Room>(1);
		if(!skyedYet)
			return skys;
		final Room skyGridRoom=rawDoors()[Directions.UP];
		if(skyGridRoom!=null)
		{
			if(((skyGridRoom.roomID()==null)||(skyGridRoom.roomID().length()==0))
			&&((skyGridRoom instanceof EndlessSky)||(skyGridRoom instanceof EndlessThinSky)))
				skys.add(skyGridRoom);
		}
		return skys;
	}

	@Override
	public void clearSky()
	{
		if(!skyedYet)
			return;
		final Room skyGridRoom=rawDoors()[Directions.UP];
		if(skyGridRoom!=null)
		{
			if(((skyGridRoom.roomID()==null)||(skyGridRoom.roomID().length()==0))
			&&((skyGridRoom instanceof EndlessSky)||(skyGridRoom instanceof EndlessThinSky)))
			{
				((GridLocale)skyGridRoom).clearGrid(null);
				rawDoors()[Directions.UP]=null;
				setRawExit(Directions.UP,null);
				for(int d=0;d<skyGridRoom.rawDoors().length;d++)
				{
					final Room thatSky=skyGridRoom.rawDoors()[d];
					final int opDir=Directions.getOpDirectionCode(d);
					if((thatSky!=null)&&(thatSky.rawDoors()[opDir]==skyGridRoom))
					{
						thatSky.rawDoors()[opDir]=null;
						thatSky.setRawExit(opDir, null);
					}
					skyGridRoom.rawDoors()[d]=null;
					skyGridRoom.setRawExit(d,null);
				}
				CMLib.map().emptyRoom(skyGridRoom,null,true);
				skyGridRoom.destroy();
				skyedYet=false;
			}
		}
		else
			skyedYet=false;
	}

	@Override
	public List<Integer> resourceChoices()
	{
		return null;
	}

	@Override
	public void setResource(final int resourceCode)
	{
		myResource=resourceCode;
		lastResourceTime= (resourceCode>=0) ? lastResourceTime=System.currentTimeMillis() : 0;
	}

	@Override
	public int myResource()
	{
		if(lastResourceTime!=0)
		{
			if(lastResourceTime<(System.currentTimeMillis()-(30*TimeManager.MILI_MINUTE)))
				setResource(-1);
		}
		if(myResource<0)
		{
			if(resourceChoices()==null)
				setResource(-1);
			else
			{
				final List<Integer> preferredChoices=new ArrayList<Integer>();
				for(int d=0;d<Directions.NUM_DIRECTIONS();d++)
				{
					final Room R=rawDoors()[d];
					if((R!=null)
					&&(R.ID().equals(ID()))
					&&(R.resourceChoices()==resourceChoices())
					&&(R instanceof StdRoom)
					gridParent.executeMsg(myHost,msg);
				else
				if((roomID().length()>0)
				&&(CMSecurity.isSaveFlag("ROOMMOBS")
					||CMSecurity.isSaveFlag("ROOMITEMS")
					||CMSecurity.isSaveFlag("ROOMSHOPS")))
					{
						myResource = choice.intValue();
						return myResource;
					}
				}
				int totalChance=0;
				for(int i=0;i<resourceChoices().size();i++)
				{
					final int resource=resourceChoices().get(i).intValue();
					totalChance+=RawMaterial.CODES.FREQUENCY(resource);
				}
				setResource(-1);
				final int theRoll=CMLib.dice().roll(1,totalChance,0);
				totalChance=0;
				for(int i=0;i<resourceChoices().size();i++)
				{
					final int resource=resourceChoices().get(i).intValue();
					totalChance+=RawMaterial.CODES.FREQUENCY(resource);
					if(theRoll<=totalChance)
					{
						setResource(resource);
						break;
					}
				}
			}
		}
		return myResource;
	}

	@Override
	public void toggleMobility(final boolean onoff)
	{
		mobility=onoff;
	}

	@Override
	public boolean getMobility()
	{
		return mobility;
	}

	@Override
	public boolean okMessage(final Environmental myHost, final CMMsg msg)
	{
		if(!getArea().okMessage(this,msg))
			return false;

		if(msg.amITarget(this))
		{
			final MOB mob=msg.source();
			switch(msg.targetMinor())
			{
			case CMMsg.TYP_EXPIRE:
			{
				if((gridParent!=null)&&(!gridParent.okMessage(myHost,msg)))
					return false;
				if(!CMLib.map().isClearableRoom(this))
					return false;
				for(int d=Directions.NUM_DIRECTIONS()-1;d>=0;d--)
				{
					final Room R2=rawDoors()[d];
					if((R2!=null)&&(!CMLib.map().isClearableRoom(R2)))
						return false;
				}
				break;
			}
			case CMMsg.TYP_LEAVE:
				if((!CMLib.flags().allowsMovement(this))||(!getMobility()))
					return false;
				break;
			case CMMsg.TYP_FLEE:
			case CMMsg.TYP_ENTER:
				if((!CMLib.flags().allowsMovement(this))||(!getMobility()))
					return false;
				if(!mob.isMonster())
				{
					final Room R=mob.location();
					if((R!=null)&&(R.getArea()!=getArea()))
					{
						CMLib.factions().updatePlayerFactions(mob,this,false);
						CMLib.achievements().possiblyBumpAchievement(mob, Event.AREAVISIT, 1, new Object[] {getArea(), this});
					}
					giveASky(0);
				}
				break;
			case CMMsg.TYP_AREAAFFECT:
				// obsolete with the area objects
				break;
			case CMMsg.TYP_CAST_SPELL:
			case CMMsg.TYP_DELICATE_HANDS_ACT:
			case CMMsg.TYP_NOISYMOVEMENT:
			case CMMsg.TYP_OK_ACTION:
			case CMMsg.TYP_JUSTICE:
			case CMMsg.TYP_OK_VISUAL:
			case CMMsg.TYP_SNIFF:
				break;
			case CMMsg.TYP_LIST:
			case CMMsg.TYP_BUY:
			case CMMsg.TYP_BID:
			case CMMsg.TYP_SELL:
			case CMMsg.TYP_VIEW:
			case CMMsg.TYP_VALUE:
				if(CMLib.coffeeShops().getShopKeeper(this)==null)
				{
					mob.tell(L("You can't shop here."));
					return false;
				}
				break;
			case CMMsg.TYP_SPEAK:
				break;
			case CMMsg.TYP_DIG:
				if(CMLib.map().getExtendedRoomID(this).length()==0)
				{
					mob.tell(L("You can't really dig here."));
					return false;
				}
				switch(this.domainType())
				{
				case Room.DOMAIN_OUTDOORS_DESERT:
				case Room.DOMAIN_OUTDOORS_HILLS:
				case Room.DOMAIN_OUTDOORS_JUNGLE:
				case Room.DOMAIN_OUTDOORS_PLAINS:
				case Room.DOMAIN_OUTDOORS_SWAMP:
				case Room.DOMAIN_OUTDOORS_WOODS:
					break;
				case Room.DOMAIN_OUTDOORS_WATERSURFACE:
				case Room.DOMAIN_OUTDOORS_UNDERWATER:
				{
					if(getRoomInDir(Directions.DOWN)==null)
						break;
				}
				//$FALL-THROUGH$
				default:
					mob.tell(L("You can't really dig here."));
					return false;
				}
				break;
			default:
				if(((msg.targetMajor(CMMsg.MASK_HANDS))||(msg.targetMajor(CMMsg.MASK_MOUTH)))
				&&(!CMath.bset(msg.targetMajor(), CMMsg.MASK_MAGIC))
				&&(!(msg.tool() instanceof Ability))
				&&(msg.targetMinor()!=CMMsg.TYP_THROW)
				&&(isInhabitant(msg.source())))
				{
					mob.tell(L("You can't do that here."));
					return false;
				}
				break;
			}
		}

		if(isInhabitant(msg.source()))
		{
			if(!msg.source().okMessage(this,msg))
				return false;
		}
		for(final Enumeration<MOB> m=inhabitants();m.hasMoreElements();)
		{
			final MOB M=m.nextElement();
			if((M!=msg.source())
			&&(!M.okMessage(this,msg)))
				return false;
		}
		for(final Enumeration<Item> i=items();i.hasMoreElements();)
		{
			final Item I=i.nextElement();
			if(!I.okMessage(this,msg))
				return false;
		}
		for(final Enumeration<Ability> a=effects();a.hasMoreElements();)
		{
			final Ability A=a.nextElement();
			if(!A.okMessage(this,msg))
				return false;
		}
		for(final Enumeration<Behavior> b=behaviors();b.hasMoreElements();)
		{
			final Behavior B=b.nextElement();
			if(!B.okMessage(this,msg))
				return false;
		}
		for(final Enumeration<ScriptingEngine> s=scripts();s.hasMoreElements();)
		{
			final ScriptingEngine S=s.nextElement();
			if(!S.okMessage(this,msg))
				return false;
		}

		for(int d=Directions.NUM_DIRECTIONS()-1;d>=0;d--)
		{
			final Exit thisExit=getRawExit(d);
			if(thisExit!=null)
			{
				if(!thisExit.okMessage(this,msg))
					return false;
			}
		}
		return true;
	}

	@Override
	public void executeMsg(final Environmental myHost, final CMMsg msg)
	{
		getArea().executeMsg(this,msg);

		if(msg.amITarget(this))
		{
			final MOB mob=msg.source();
			switch(msg.targetMinor())
			{
			case CMMsg.TYP_LEAVE:
			{
				if(!CMath.bset(msg.targetMajor(),CMMsg.MASK_OPTIMIZE))
					recoverRoomStats();
				break;
			}
			case CMMsg.TYP_FLEE:
			{
				if(!CMath.bset(msg.targetMajor(),CMMsg.MASK_OPTIMIZE))
					recoverRoomStats();
				break;
			}
			case CMMsg.TYP_ENTER:
			case CMMsg.TYP_RECALL:
			{
				if(!CMath.bset(msg.targetMajor(),CMMsg.MASK_OPTIMIZE))
					recoverRoomStats();
				if((msg.source().playerStats()!=null)
				&&(msg.source().soulMate()==null))
				{
					if(msg.source().playerStats().addRoomVisit(this))
						CMLib.players().bumpPrideStat(msg.source(),AccountStats.PrideStat.ROOMS_EXPLORED, 1);
				}
				break;
			}
			case CMMsg.TYP_LOOK_EXITS:
				if(msg.value()==CMMsg.MASK_OPTIMIZE)
					CMLib.commands().lookAtExitsShort(this, msg.source());
				else
					CMLib.commands().lookAtExits(this, msg.source());
				break;
			case CMMsg.TYP_LOOK:
			case CMMsg.TYP_EXAMINE:
				CMLib.commands().handleBeingLookedAt(msg);
				break;
			case CMMsg.TYP_SNIFF:
				CMLib.commands().handleBeingSniffed(msg);
				break;
			case CMMsg.TYP_READ:
				if(CMLib.flags().canBeSeenBy(this,mob))
					mob.tell(L("There is nothing written here."));
				else
					mob.tell(L("You can't see that!"));
				break;
			case CMMsg.TYP_AREAAFFECT:
				// obsolete with the area objects
				break;
			case CMMsg.TYP_DIG:
				if(findItem("HoleInTheGround")==null)
					addItem(CMClass.getBasicItem("HoleInTheGround"));
				break;
			default:
				break;
			}
		}

		if((msg.othersMinor() == CMMsg.TYP_GRAVITY)
		&&(msg.targetMinor() == CMMsg.NO_EFFECT)
		&&(numInhabitants()>0))
		{
			final CMMsg gmsg = (CMMsg)msg.copyOf();
			gmsg.setTargetCode(msg.othersCode());
			gmsg.setOthersCode(CMMsg.NO_EFFECT);
			final Room me=this;
			eachInhabitant(new EachApplicable<MOB>()
			{
				final Room R=me;
				@Override
				public void apply(final MOB M)
				{
					gmsg.setTarget(M);
					if(R.okMessage(M, gmsg))
						R.send(M, gmsg);
				}
			});
		}

		if(numItems()>0)
		{
			eachItem(new EachApplicable<Item>()
			{
				@Override
				public final void apply(final Item I)
				{
					I.executeMsg(me, msg);
				}
			});
		}

		for(int d=Directions.NUM_DIRECTIONS()-1;d>=0;d--)
		{
			final Exit E=getRawExit(d);
			if(E!=null)
				E.executeMsg(this,msg);
		}

		if(numBehaviors()>0)
		{
			eachBehavior(new EachApplicable<Behavior>()
			{
				@Override
				public final void apply(final Behavior B)
				{
					B.executeMsg(me, msg);
				}
			});
		}
		if(numScripts()>0)
		{
			eachScript(new EachApplicable<ScriptingEngine>()
			{
				@Override
				public final void apply(final ScriptingEngine S)
				{
					S.executeMsg(me, msg);
				}
			});
		}
		if(numEffects()>0)
		{
			eachEffect(new EachApplicable<Ability>()
			{
				@Override
				public final void apply(final Ability A)
				{
					A.executeMsg(me,msg);
				}
			});
		}

		if(msg.sourceMinor()==CMMsg.TYP_SHUTDOWN)
		{
			try
			{
				if(CMSecurity.isSaveFlag(CMSecurity.SaveFlag.ROOMMOBS))
				{
					if(roomID().length()==0)
					{
						eachInhabitant(new EachApplicable<MOB>()
						{
							@Override
							public final void apply(final MOB M)
							{
								if((M.isSavable())
								&&(M.getStartRoom()!=me)
								&&(M.getStartRoom()!=null)
								&&(M.getStartRoom().roomID().length()>0))
									M.getStartRoom().bringMobHere(M,false);
							}
						});
					}
				}
				else
				if(CMSecurity.isSaveFlag(CMSecurity.SaveFlag.ROOMSHOPS))
				{
					eachInhabitant(new EachApplicable<MOB>()
					{
						@Override
						public final void apply(final MOB M)
						{
							if((M instanceof ShopKeeper)
							&&(M.isSavable())
							&&(M.getStartRoom()!=me)
							&&(M.getStartRoom()!=null))
								M.getStartRoom().bringMobHere(M,false);
						}
					});
				}
			}
			catch(final NoSuchElementException e)
			{
			}
		}

		if(msg.amITarget(this)&&(msg.targetMinor()==CMMsg.TYP_EXPIRE))
		{
			synchronized(CMClass.getSync(("SYNC"+roomID())))
			{
				final LinkedList<DeadBody> deadBodies=new LinkedList<DeadBody>();
				eachItem(new EachApplicable<Item>()
				{
					@Override
					public final void apply(final Item I)
					{
						if((I instanceof DeadBody)
						&&(((DeadBody)I).isPlayerCorpse()))
							deadBodies.add((DeadBody)I);
					}
				});
				for(final DeadBody D : deadBodies)
				{
					MOB M=CMLib.players().getLoadPlayer(D.getMobName());
					if(M==null)
						M=D.getSavedMOB();
					if((M!=null)&&(M.getStartRoom()!=null))
					{
						final Room startRoom=CMLib.map().getRoom(M.getStartRoom());
						M.tell(L("Your corpse has been moved to @x1",startRoom.displayText()));
						startRoom.moveItemTo(D);
					}
				}
				if(gridParent!=null)
					gridParent.executeMsg(myHost,msg);
				else
				if((roomID().length()>0)
				&&((getArea()==null)||(!CMath.bset(getArea().flags(), Area.FLAG_INSTANCE_CHILD)))
				&&(CMSecurity.isSaveFlag(CMSecurity.SaveFlag.ROOMMOBS)
					||CMSecurity.isSaveFlag(CMSecurity.SaveFlag.ROOMITEMS)
					||CMSecurity.isSaveFlag(CMSecurity.SaveFlag.ROOMSHOPS)))
				{
					final ArrayList<MOB> shopmobs=new ArrayList<MOB>(1);
					final ArrayList<Item> bodies=new ArrayList<Item>(1);
					if(CMSecurity.isSaveFlag(CMSecurity.SaveFlag.ROOMMOBS))
					{
						eachInhabitant(new EachApplicable<MOB>()
						{
							@Override
							public final void apply(final MOB M)
							{
								if(M.isSavable())
								{
									M.setStartRoom(me);
									M.text(); // this permanizes his current state
								}
							}
						});
						CMLib.database().DBUpdateMOBs(this);
					}
					else
					if(CMSecurity.isSaveFlag(CMSecurity.SaveFlag.ROOMSHOPS))
					{
						eachInhabitant(new EachApplicable<MOB>()
						{
							@Override
							public final void apply(final MOB M)
							{
								if((M.isSavable())
								&&(M instanceof ShopKeeper)
								&&(M.getStartRoom()==me))
									shopmobs.add(M);
							}
						});
						if(!shopmobs.isEmpty())
							CMLib.database().DBUpdateTheseMOBs(this,shopmobs);
					}
					if(CMSecurity.isSaveFlag(CMSecurity.SaveFlag.ROOMITEMS))
					{
						eachItem(new EachApplicable<Item>()
						{
							@Override public final void apply(final Item I)
							{
								if(I instanceof DeadBody)
									bodies.add(I);
							}
						});
						for(int i=0;i<bodies.size();i++)
							bodies.get(i).destroy();
						CMLib.database().DBUpdateItems(this);
					}
				}
				final Area A=getArea();
				final String roomID=roomID();
				setGridParent(null);
				if(!CMProps.getBoolVar(CMProps.Bool.MUDSHUTTINGDOWN))
				{
					CMLib.map().emptyRoom(this,null,true);
					destroy();
					if(roomID.length()>0)
						A.addProperRoomnumber(roomID);
				}
			}
		}
	}

	@Override
	public void startItemRejuv()
	{
		eachItem(new EachApplicable<Item>()
		{
			@Override
			public final void apply(final Item item)
			{
				if(item.container()==null)
				{
					final ItemTicker I=(ItemTicker)CMClass.getAbility("ItemRejuv");
					I.unloadIfNecessary(item);
					if((item.phyStats().rejuv()!=PhyStats.NO_REJUV)
					&&(item.phyStats().rejuv()>0))
						I.loadMeUp(item,me);
				}
			}
		});
	}

	@Override
	public int getTickStatus()
	{
		return tickStatus;
	}

	@Override
	public boolean tick(final Tickable ticking, final int tickID)
	{
		tickStatus=Tickable.STATUS_START;
		if((myArea != null) && (myArea.amDestroyed()))
		{
			Log.errOut("Destroying "+CMLib.map().getExtendedRoomID(this)+" because of destroyed area.");
			destroy();
			return false;
		}
		if(tickID==Tickable.TICKID_ROOM_BEHAVIOR)
		{
			if((numBehaviors()<=0)&&(numScripts()<=0))
				return false;
			tickStatus=Tickable.STATUS_BEHAVIOR;
			eachBehavior(new EachApplicable<Behavior>()
			{
				@Override
				public final void apply(final Behavior B)
				{
					B.tick(ticking, tickID);
				}
			});
			tickStatus=Tickable.STATUS_SCRIPT;
			eachScript(new EachApplicable<ScriptingEngine>()
			{
				@Override
				public final void apply(final ScriptingEngine S)
				{
					S.tick(ticking, tickID);
				}
			});
		}
		else
		{
			tickStatus=Tickable.STATUS_AFFECT;
			if(numEffects()>0)
			{
				eachEffect(new EachApplicable<Ability>()
				{
					@Override
					public final void apply(final Ability A)
					{
						if(!A.tick(ticking,tickID))
							A.unInvoke();
					}
				});
			}
		}
		tickStatus=Tickable.STATUS_NOT;
		return !amDestroyed();
	}

	@Override
	public PhyStats phyStats()
	{
		return phyStats;
	}

	@Override
	public PhyStats basePhyStats()
	{
		return basePhyStats;
	}

	@SuppressWarnings("unchecked")
	@Override
	public void recoverPhyStats()
	{
		basePhyStats.copyInto(phyStats);
		final Area myArea=getArea();
		if(myArea!=null)
			myArea.affectPhyStats(this,phyStats());

		eachEffect(affectPhyStats);
		eachItem(affectPhyStats);
		eachInhabitant(affectPhyStats);
	}

	private final static EachApplicable<Item> recoverRoomStatsItemApplicable=new EachApplicable.ApplyRecoverPhyStats<Item>();

	private final static EachApplicable<MOB> recoverRoomStatsInhabitantApplicable=new EachApplicable<MOB>()
	{
		@Override
		public final void apply(final MOB M)
		{
			M.recoverCharStats();
			M.recoverPhyStats();
			M.recoverMaxState();
		}
	};

	private void reallyRecoverRoomStats()
	{
		recoverPhyStats();
		eachInhabitant(recoverRoomStatsInhabitantApplicable);
		for(final Exit X : exits)
		{
			if(X!=null)
				X.recoverPhyStats();
		}
		eachItem(recoverRoomStatsItemApplicable);
	}

	@Override
	public void recoverRoomStats()
	{
		if(roomRecoverMarker.addAndGet(1)!=1)
			return;
		try
		{
			reallyRecoverRoomStats();
			if(roomRecoverMarker.addAndGet(-1)>0)
				reallyRecoverRoomStats();
		}
		finally
		{
			roomRecoverMarker.set(0);
		}
	}

	@Override
	public void setBasePhyStats(final PhyStats newStats)
	{
		basePhyStats=(PhyStats)newStats.copyOf();
	}

	private final static int phyStatsMaskOut = ~(PhyStats.IS_DARK|PhyStats.IS_LIGHTSOURCE|PhyStats.IS_SLEEPING|PhyStats.IS_HIDDEN|PhyStats.IS_SWIMMING|PhyStats.IS_NOT_SEEN);

	@Override
	public void affectPhyStats(final Physical affected, final PhyStats affectableStats)
	{
		getArea().affectPhyStats(affected,affectableStats);
		final int disposition=phyStats().disposition() & phyStatsMaskOut;
		if(disposition>0)
			affectableStats.setDisposition(affectableStats.disposition()|disposition);
		eachEffect(new EachApplicable<Ability>()
		{
			@Override
			public final void apply(final Ability A)
			{
				if(A.bubbleAffect())
					A.affectPhyStats(affected,affectableStats);
			}
		});
	}

	@Override
	public void affectCharStats(final MOB affectedMob, final CharStats affectableStats)
	{
		getArea().affectCharStats(affectedMob,affectableStats);
		eachEffect(new EachApplicable<Ability>()
		{
			@Override
			public final void apply(final Ability A)
			{
				if(A.bubbleAffect())
					A.affectCharStats(affectedMob,affectableStats);
			}
		});
	}

	@Override
	public void affectCharState(final MOB affectedMob, final CharState affectableMaxState)
	{
		getArea().affectCharState(affectedMob,affectableMaxState);
		eachEffect(new EachApplicable<Ability>()
		{
			@Override
			public final void apply(final Ability A)
			{
				if(A.bubbleAffect())
					A.affectCharState(affectedMob,affectableMaxState);
			}
		});
	}

	@Override
	public int compareTo(final CMObject o)
	{
		return CMClass.classID(this).compareToIgnoreCase(CMClass.classID(o));
	}

	@Override
	public String displayText(final MOB mob)
	{
		return CMLib.commands().parseVaries(mob,getArea(),this,displayText());
	}

	@Override
	public String description(final MOB mob)
	{
		return CMLib.commands().parseVaries(mob,getArea(),this,description());
	}

	@Override
	public void bringMobHere(final MOB mob, final boolean andFollowers)
	{
		if(mob==null)
			return;
		final Room oldRoom=mob.location();
		if(oldRoom!=null)
			oldRoom.delInhabitant(mob);
		if(!isInhabitant(mob))
			addInhabitant(mob);
		mob.setLocation(this);

		if((andFollowers)&&(oldRoom!=null))
		{
			for(final Enumeration<Pair<MOB,Short>> f=mob.followers();f.hasMoreElements();)
			{
				final MOB folM=f.nextElement().first;
				if((folM.location()==oldRoom)
				&&(folM != mob)
				&&(oldRoom != this))
					bringMobHere(folM,true);
			}
		}
		final Rideable RI=mob.riding();
		if((RI!=null)&&(CMLib.map().roomLocation(RI)==oldRoom))
		{
			if((RI.isMobileRideBasis())
			&&((!(RI instanceof Item))||(!CMLib.flags().isMobile(RI))))
			{
				if(RI instanceof MOB)
					bringMobHere((MOB)RI,andFollowers);
				else
				if(RI instanceof Item)
				{
					if(andFollowers)
						moveItemTo((Item)RI,ItemPossessor.Expire.Player_Drop,Move.Followers);
					else
						moveItemTo((Item)RI,ItemPossessor.Expire.Player_Drop);
				}
				// refuse is good for above, since mostly moving player stuff around
			}
			else
				mob.setRiding(null);
		}
		if((oldRoom!=null)
		&&(mob instanceof Rideable)
		&&(oldRoom!=this))
		{
			for(final Enumeration<Rider> r=((Rideable)mob).riders();r.hasMoreElements();)
			{
				final Rider RR=r.nextElement();
				if(CMLib.map().roomLocation(RR)==oldRoom)
				{
					if(((Rideable)mob).isMobileRideBasis())
					{
						if((RR instanceof MOB)
						&&(andFollowers)
						&&(RR!=mob))
							bringMobHere((MOB)RR,andFollowers);
						else
						if(RR instanceof Item)
						{
							if(andFollowers)
								moveItemTo((Item)RR,ItemPossessor.Expire.Player_Drop,Move.Followers);
							else
								moveItemTo((Item)RR,ItemPossessor.Expire.Player_Drop);
							// refuse is good for above, since mostly moving player stuff around
						}
					}
					else
						RR.setRiding(null);
				}
			}
		}
		if(oldRoom!=null)
			oldRoom.recoverRoomStats();
		recoverRoomStats();
	}

	@Override
	public void moveItemTo(final Item container)
	{
		moveItemTo(container, Expire.Never);
	}

	@Override
	public void moveItemTo(final Item item, final Expire expire, final Move... moveFlags)
	{
		if(item==null)
			return;
		final ItemPossessor o;
		synchronized(item)
		{
			o=item.owner();
		}
		if(o==null)
			return;

		List<Item> V=new ArrayList<Item>();
		if(item instanceof Container)
			V=((Container)item).getDeepContents();
		o.delItem(item);
		if(o.isContent(item))
			o.delItem(item);

		addItem(item, expire);
		for(int v=0;v<V.size();v++)
		{
			final Item i2=V.get(v);
			o.delItem(i2);
			if(o.isContent(i2))
				o.delItem(i2);
			addItem(i2);
		}
		item.setContainer(null);

		final Rideable RI=item.riding();
		if((RI!=null)&&(o instanceof Room)&&(CMLib.map().roomLocation(RI)==o))
		{
			if((RI.isMobileRideBasis())
			&&((!(RI instanceof Item))||(!CMLib.flags().isMobile(RI))))
			{
				if(RI instanceof MOB)
					bringMobHere((MOB)RI,true);
				else
				if(RI instanceof Item)
					moveItemTo((Item)RI,null,ItemPossessor.Move.Followers);
			}
			else
				item.setRiding(null);
		}
		if(CMParms.contains(moveFlags, Move.Followers)
		&&(o instanceof Room)
		&&(item instanceof Rideable)
		&&(o!=this))
		{
			Rider RR=null;
			for(int r=0;r<((Rideable)item).numRiders();r++)
			{
				RR=((Rideable)item).fetchRider(r);
				if(CMLib.map().roomLocation(RR)==o)
				{
					if((((Rideable)item).isMobileRideBasis())
					&&(!CMLib.flags().isMobile(item)))
					{
						if(RR instanceof MOB)
							bringMobHere((MOB)RR,true);
						else
						if(RR instanceof Item)
							moveItemTo((Item)RR,ItemPossessor.Expire.Player_Drop,ItemPossessor.Move.Followers);
					}
					else
						RR.setRiding(null);
				}
			}
		}

		if(!CMParms.contains(moveFlags, Move.Optimize))
		{
			if(o instanceof Room)
				((Room)o).recoverRoomStats();
			else
			if(o instanceof MOB)
			{
				((MOB)o).recoverCharStats();
				((MOB)o).recoverPhyStats();
				((MOB)o).recoverMaxState();
			}
			recoverRoomStats();
		}
	}

	@Override
	public int getReverseDir(final int direction)
	{
		if((direction<0)||(direction>=Directions.NUM_DIRECTIONS()))
			return -1;
		final Room opRoom=getRoomInDir(direction);
		if(opRoom!=null)
		{
			if(direction == Directions.GATE)
				return direction;
			final int formalOpDir=Directions.getOpDirectionCode(direction);
			if(opRoom.rawDoors()[formalOpDir]==this)
				return formalOpDir;
			if(opRoom.getRoomInDir(formalOpDir)==this)
				return formalOpDir;
			for(int d=0;d<Directions.NUM_DIRECTIONS();d++)
			{
				if(opRoom.rawDoors()[d]==this)
					return d;
			}
			return formalOpDir;
		}
		return -1;
	}

	@Override
	public Exit getReverseExit(final int direction)
	{
		final int opDir=getReverseDir(direction);
		if((opDir<0)||(opDir>=Directions.NUM_DIRECTIONS()))
			return null;
		final Room opRoom=getRoomInDir(direction);
		if(opRoom!=null)
			return opRoom.getExitInDir(opDir);
		return null;
	}

	@Override
	public Exit getPairedExit(final int direction)
	{
		final Exit opExit=getReverseExit(direction);
		final Exit myExit=getExitInDir(direction);
		if((myExit==null)||(opExit==null))
			return null;
		if(myExit.hasADoor()!=opExit.hasADoor())
			return null;
		return opExit;
	}

	@Override
	public Room prepareRoomInDir(final Room R, final int direction)
	{
		if(amDestroyed)
		{
			if(roomID().length()>0)
			{
				final Room thinMeR=CMClass.getLocale("ThinRoom");
				thinMeR.setRoomID(roomID());
				thinMeR.setArea(myArea);
				if(R.rawDoors()[direction]==this)
					R.rawDoors()[direction]=thinMeR;
				return thinMeR.prepareRoomInDir(R,direction);
			}
			return null;
		}
		if(expirationDate()!=0)
			setExpirationDate(System.currentTimeMillis()+WorldMap.ROOM_EXPIRATION_MILLIS);
		return this;
	}

	@Override
	public Room getRoomInDir(final int direction)
	{
		if((direction<0)||(direction>=doors.length)||(amDestroyed))
			return null;
		Room nextRoom=rawDoors()[direction];
		if(gridParent!=null)
			nextRoom=gridParent.prepareGridLocale(this,nextRoom,direction);
		if(nextRoom!=null)
		{
			nextRoom=nextRoom.prepareRoomInDir(this,direction);
			if((nextRoom!=null)&&(nextRoom.amDestroyed()))
				return null;
		}
		return nextRoom;
	}

	@Override
	public Exit getExitInDir(final int direction)
	{
		if((direction<0)||(direction>=exits.length))
			return null;
		if((gridParent!=null)&&(getRawExit(direction)==null))
			getRoomInDir(direction);
		return getRawExit(direction);
	}

	protected void sendAndExec(final MOB source, final CMMsg msg)
	{
		if((Log.debugChannelOn())&&(CMSecurity.isDebugging(CMSecurity.DbgFlag.MESSAGES)))
			Log.debugOut("StdRoom",msg.source().ID()+":"+msg.sourceCode()+":"+msg.sourceMessage()+"/"+((msg.target()!=null)?msg.target().ID():"null")+":"+msg.targetCode()+":"+msg.targetMessage()+"/"+((msg.tool()!=null)?msg.tool().ID():"null")+"/"+msg.othersCode()+":"+msg.othersMessage());
		for(final MOB otherMOB : inhabitants)
		{
			if(otherMOB!=source)
				otherMOB.executeMsg(otherMOB,msg);
		}
		executeMsg(source,msg);
		CMLib.commands().monitorGlobalMessage(this, msg);
	}

	protected void sendTrailermsgs(final MOB source, final CMMsg msg, final int depth, final boolean includeSource)
	{
		// now handle trailer msgs
		if(depth<3)
		{
			if(msg.trailerMsgs()!=null)
			{
				for(final CMMsg msg2 : msg.trailerMsgs())
				{
					if((msg!=msg2)
					&&((msg2.target()==null)
					   ||(!(msg2.target() instanceof MOB))
					   ||((!((MOB)msg2.target()).amDead())||(msg2.sourceMinor()==CMMsg.TYP_DEATH)))
					&&(okMessage(source,msg2)))
					{
						if(includeSource)
							source.executeMsg(source,msg2);
						sendAndExec(source,msg2);
						sendTrailermsgs(source, msg2, depth+1, includeSource);
					}
				}
			}
			final List<Runnable> trails=msg.trailerRunnables();
			if((trails!=null)
			&&(trails.size()>0))
			{
				for(final Runnable r : trails)
					CMLib.threads().executeRunnable(r);
			}
		}
	}

	@Override
	public void send(final MOB source, final CMMsg msg)
	{
		source.executeMsg(source,msg);
		sendAndExec(source,msg);
		sendTrailermsgs(source, msg, 0, true);
	}

	@Override
	public void sendOthers(final MOB source, final CMMsg msg)
	{
		sendAndExec(source,msg);
		sendTrailermsgs(source, msg, 0, false);
	}

	@Override
	public void showHappens(final int allCode, final String allMessage)
	{
		final MOB everywhereMOB=CMLib.map().getFactoryMOB(this);
		final CMMsg msg=CMClass.getMsg(everywhereMOB,null,null,allCode,allCode,allCode,allMessage);
		sendOthers(everywhereMOB,msg);
		everywhereMOB.destroy();
	}

	@Override
	public void showHappens(final int allCode, final Environmental like, final String allMessage)
	{
		final MOB everywhereMOB=CMClass.getFactoryMOB();
		everywhereMOB.setName(like.name());
		if(like instanceof Physical)
			everywhereMOB.setBasePhyStats(((Physical)like).phyStats());
		everywhereMOB.setLocation(this);
		everywhereMOB.recoverPhyStats();
		final CMMsg msg=CMClass.getMsg(everywhereMOB,null,null,allCode,allCode,allCode,allMessage);
		send(everywhereMOB,msg);
		everywhereMOB.destroy();
	}

	@Override
	public boolean show(final MOB source, final Environmental target, final int allCode, final String allMessage)
	{
		final CMMsg msg=CMClass.getMsg(source,target,null,allCode,allCode,allCode,allMessage);
		if((!CMath.bset(allCode,CMMsg.MASK_ALWAYS))&&(!okMessage(source,msg)))
			return false;
		send(source,msg);
		return true;
	}

	@Override
	public boolean show(final MOB source, final Environmental target, final Environmental tool, final int allCode, final String allMessage)
	{
		final CMMsg msg=CMClass.getMsg(source,target,tool,allCode,allCode,allCode,allMessage);
		if((!CMath.bset(allCode,CMMsg.MASK_ALWAYS))&&(!okMessage(source,msg)))
			return false;
		send(source,msg);
		return true;
	}

	@Override
	public boolean show(final MOB source,
						final Environmental target,
						final Environmental tool,
						final int srcCode,
						final int tarCode,
						final int othCode,
						final String allMessage)
	{
		final CMMsg msg=CMClass.getMsg(source,target,tool,srcCode,tarCode,othCode,allMessage);
		if((!CMath.bset(srcCode,CMMsg.MASK_ALWAYS))&&(!okMessage(source,msg)))
			return false;
		send(source,msg);
		return true;
	}

	@Override
	public boolean show(final MOB source,
						final Environmental target,
						final Environmental tool,
						final int allCode,
						final String srcMessage,
						final String tarMessage,
						final String othMessage)
	{
		final CMMsg msg=CMClass.getMsg(source,target,tool,allCode,srcMessage,allCode,tarMessage,allCode,othMessage);
		if((!CMath.bset(allCode,CMMsg.MASK_ALWAYS))&&(!okMessage(source,msg)))
			return false;
		send(source,msg);
		return true;
	}

	@Override
	public boolean show(final MOB source,
						final Environmental target,
						final Environmental tool,
						final int srcCode,
						final String srcMessage,
						final int tarCode,
						final String tarMessage,
						final int othCode,
						final String othMessage)
	{
		final CMMsg msg=CMClass.getMsg(source,target,tool,srcCode,srcMessage,tarCode,tarMessage,othCode,othMessage);
		if((!CMath.bset(srcCode,CMMsg.MASK_ALWAYS))&&(!okMessage(source,msg)))
			return false;
		send(source,msg);
		return true;
	}

	@Override
	public boolean showOthers(final MOB source,
							  final Environmental target,
							  final int allCode,
							  final String allMessage)
	{
		final CMMsg msg=CMClass.getMsg(source,target,null,allCode,allCode,allCode,allMessage);
		if((!CMath.bset(allCode,CMMsg.MASK_ALWAYS))&&(!okMessage(source,msg)))
			return false;
		sendAndExec(source,msg);
		sendTrailermsgs(source, msg, 0, false);
		return true;
	}

	@Override
	public boolean showOthers(final MOB source,
							  final Environmental target,
							  final Environmental tool,
							  final int allCode,
							  final String allMessage)
	{
		final CMMsg msg=CMClass.getMsg(source,target,tool,allCode,allCode,allCode,allMessage);
		if((!CMath.bset(allCode,CMMsg.MASK_ALWAYS))&&(!okMessage(source,msg)))
			return false;
		sendAndExec(source,msg);
		sendTrailermsgs(source, msg, 0, false);
		return true;
	}

	@Override
	public boolean showSource(final MOB source,
							  final Environmental target,
							  final int allCode,
							  final String allMessage)
	{
		final CMMsg msg=CMClass.getMsg(source,target,null,allCode,allCode,allCode,allMessage);
		if((!CMath.bset(allCode,CMMsg.MASK_ALWAYS))&&(!okMessage(source,msg)))
			return false;
		source.executeMsg(source,msg);
		return true;
	}

	@Override
	public boolean showSource(final MOB source,
							  final Environmental target,
							  final Environmental tool,
							  final int allCode,
							  final String allMessage)
	{
		final CMMsg msg=CMClass.getMsg(source,target,tool,allCode,allCode,allCode,allMessage);
		if((!CMath.bset(allCode,CMMsg.MASK_ALWAYS))&&(!okMessage(source,msg)))
			return false;
		source.executeMsg(source,msg);
		return true;
	}

	@Override
	public Exit getRawExit(final int dir)
	{
		if(dir<exits.length)
			return exits[dir];
		return null;
	}

	@Override
	public Room[] rawDoors()
	{
		return doors;
	}

	@Override
	public boolean isSavable()
	{
		return ((roomID().length()>0)
				&&((getArea()==null)
					|| (!CMath.bset(getArea().flags(),Area.FLAG_INSTANCE_CHILD)))
				&&(CMLib.flags().isSavable(this)));
	}

	@Override
	public void setSavable(final boolean truefalse)
	{
		CMLib.flags().setSavable(this, truefalse);
	}

	@Override
	public void destroy()
	{
		if((phyStats().sensesMask()&PhyStats.SENSE_UNDESTROYABLE)>0)
			return;
		CMLib.map().registerWorldObjectDestroyed(getArea(),this,this);
		delAllEffects(true);
		delAllInhabitants(true);
		delAllBehaviors();
		delAllScripts();
		CMLib.threads().deleteTick(this,-1);
		delAllItems(true);
		if(this instanceof GridLocale)
			((GridLocale)this).clearGrid(null);
		clearSky();
		if((roomID().length()==0)&&(rawDoors()!=null))
		{
			Room roomDir=null;
			for(int d=rawDoors().length-1;d>=0;d--)
			{
				roomDir=rawDoors()[d];
				if((roomDir!=null)&&(roomDir.rawDoors()!=null))
				{
					for(int d2=roomDir.rawDoors().length-1;d2>=0;d2--)
					{
						if(roomDir.rawDoors()[d2]==this)
						{
							roomDir.rawDoors()[d2]=null;
							roomDir.setRawExit(d2,null);
						}
					}
				}
			}
		}
		rawImageName=null;
		cachedImageName=null;
		setArea(null); // this actually deletes the room from the cache map
		basePhyStats=(PhyStats)CMClass.getCommon("DefaultPhyStats");
		phyStats=basePhyStats;
		for(int d=Directions.NUM_DIRECTIONS()-1;d>=0;d--)
			setRawExit(d,null);
		Arrays.fill(exits, null);
		Arrays.fill(doors, null);
		affects=null;
		behaviors=null;
		scripts=null;
		contents.setSize(0);
		inhabitants.setSize(0);
		gridParent=null;
		amDestroyed=true;
	}

	@Override
	public final boolean amDestroyed()
	{
		return amDestroyed;
	}

	@Override
	public int getCombatTurnMobIndex()
	{
		return combatTurnMobIndex;
	}

	@Override
	public void setCombatTurnMobIndex(final int index)
	{
		combatTurnMobIndex = (short)index;
	}

	@Override
	public boolean isHere(final Environmental E)
	{
		if(E instanceof Item)
			return isContent((Item)E);
		else
		if(E instanceof MOB)
			return isInhabitant((MOB)E);
		else
		if(E instanceof Exit)
		{
			for(int d=Directions.NUM_DIRECTIONS()-1;d>=0;d--)
			{
				if(getRawExit(d)==E)
					return true;
			}
		}
		else
		if(E instanceof Room)
		{
			if (E == this)
				return true;
			if (E instanceof Room)
			{
				if (CMLib.map().getExtendedRoomID(this).equals(CMLib.map().getExtendedRoomID((Room) E)))
					return true;
			}
			return false;
		}
		else
		if(E instanceof Ability)
			return fetchEffect(E.ID())!=null;
		else
		if(E instanceof Behavior)
			return fetchBehavior(E.ID())!=null;
		return false;
	}

	@Override
	public MOB fetchRandomInhabitant()
	{
		if(inhabitants.isEmpty())
			return null;
		return fetchInhabitant(CMLib.dice().roll(1,numInhabitants(),-1));
	}

	@Override
	public MOB fetchInhabitant(final String inhabitantID)
	{
		if(inhabitants.isEmpty())
			return null;
		MOB mob=(MOB)CMLib.english().fetchEnvironmental(inhabitants,inhabitantID,true);
		if(mob==null)
			mob=(MOB)CMLib.english().fetchEnvironmental(inhabitants,inhabitantID, false);
		return mob;
	}

	@Override
	public MOB fetchInhabitantExact(final String inhabitantID)
	{
		if(inhabitants.isEmpty())
			return null;
		return (MOB)CMLib.english().fetchEnvironmental(inhabitants,inhabitantID,true);
	}

	private static final ReadOnlyVector<MOB> emptyMOBV=new ReadOnlyVector<MOB>(1);

	@SuppressWarnings("unchecked")

	@Override
	public List<MOB> fetchInhabitants(final String inhabitantID)
	{
		if(inhabitants.isEmpty())
			return emptyMOBV;
		@SuppressWarnings("rawtypes")
		List inhabs=CMLib.english().fetchEnvironmentals(inhabitants,inhabitantID,true);
		if(inhabs.isEmpty())
			inhabs=CMLib.english().fetchEnvironmentals(inhabitants,inhabitantID, false);
		return inhabs;
	}

	@Override
	public void addInhabitant(final MOB mob)
	{
		inhabitants.addElement(mob);
	}

	@Override
	public Enumeration<MOB> inhabitants()
	{
		return inhabitants.elements();
	}

	@Override
	public int numInhabitants()
	{
		return inhabitants.size();
	}

	@Override
	public int numPCInhabitants()
	{
		final Set<MOB> playerInhabitants=CMLib.players().getPlayersHere(this);
		if(playerInhabitants.isEmpty())
			return 0;
		int num=0;
		for(final MOB M : playerInhabitants)
		{
			if((M!=null)&&(M.session()!=null))
				num++;
		}
		return num;
	}

	@Override
	public boolean isInhabitant(final MOB mob)
	{
		return inhabitants.contains(mob);
	}

	@Override
	public MOB fetchInhabitant(final int i)
	{
		try
		{
			return inhabitants.elementAt(i);
		}
		catch(final java.lang.ArrayIndexOutOfBoundsException x)
		{
		}
		return null;
	}

	@Override
	public void eachInhabitant(final EachApplicable<MOB> applier)
	{
		final List<MOB> inhabitants=this.inhabitants;
		if((inhabitants!=null)&&(!inhabitants.isEmpty()))
		{
			try
			{
				for(int a=0;a<inhabitants.size();a++)
				{
					final MOB M=inhabitants.get(a);
					if(M!=null)
						applier.apply(M);
				}
			}
			catch(final ArrayIndexOutOfBoundsException e)
			{
			}
		}
	}

	@Override
	public void delInhabitant(final MOB mob)
	{
		inhabitants.removeElement(mob);
	}

	@Override
	public void delAllInhabitants(final boolean destroy)
	{
		try
		{
			for(int i=numInhabitants()-1;i>=0;i--)
			{
				final MOB M=fetchInhabitant(i);
				if(M!=null)
				{
					if(destroy || (M.location()==this))
						M.setLocation(null);
					if(destroy)
						M.destroy();
				}
			}
			inhabitants.clear();
		}
		catch(final Exception e)
		{
		}
	}

	@Override
	public Exit fetchExit(final String itemID)
	{
		final int dir=CMLib.directions().getGoodDirectionCode(itemID);
		Exit E=null;
		if(dir >= 0)
			E=getExitInDir(dir);
		final List<Exit> exitList=Arrays.asList(exits);
		if(E==null)
			E=CMLib.english().fetchExit(exitList, itemID, true);
		if(E==null)
			E=CMLib.english().fetchExit(exitList, itemID, false);
		if(contents.isEmpty())
			return E;
		if(E==null)
			E=CMLib.english().fetchExit(contents, itemID, true);
		if(E==null)
			E=CMLib.english().fetchExit(contents, itemID, false);
		return E;
	}

	@Override
	public Item findItem(final String itemID)
	{
		if(contents.isEmpty())
			return null;
		Item item=(Item)CMLib.english().fetchEnvironmental(contents,itemID,true);
		if(item==null)
			item=(Item)CMLib.english().fetchEnvironmental(contents,itemID,false);
		return item;
	}

	@Override
	public Enumeration<Item> items()
	{
		return contents.elements();
	}

	@Override
	public Enumeration<Item> itemsRecursive()
	{
		return new MultiEnumeration<Item>()
			.addEnumeration(items())
			.addEnumeration(new Enumeration<Item>()
			{
				private final Enumeration<MOB> curMobEnumeration = inhabitants();
				private volatile Enumeration<Item> curItemEnumeration;

				@Override
				public boolean hasMoreElements()
				{
					boolean hasMore = (curItemEnumeration!=null)&&(curItemEnumeration.hasMoreElements());
					while(!hasMore)
					{
						if((curMobEnumeration == null)||(!curMobEnumeration.hasMoreElements()))
							return false;
						curItemEnumeration=curMobEnumeration.nextElement().items();
						hasMore = (curItemEnumeration!=null)&&(curItemEnumeration.hasMoreElements());
					}
					return hasMore;
				}

				@Override
				public Item nextElement()
				{
					if(!hasMoreElements())
						throw new NoSuchElementException();
					return curItemEnumeration.nextElement();
				}
			});
	}


	@Override
	public Item findItem(final Item goodLocation, final String itemID)
	{
		if(contents.isEmpty())
			return null;
		Item item=CMLib.english().fetchAvailableItem(contents,itemID,goodLocation,Wearable.FILTER_ANY,true);
		if(item==null)
			item=CMLib.english().fetchAvailableItem(contents,itemID,goodLocation,Wearable.FILTER_ANY,false);
		return item;
	}

	@Override
	public List<Item> findItems(final Item goodLocation, final String itemID)
	{
		if(contents.isEmpty())
			return new Vector<Item>(1);
		List<Item> items=CMLib.english().fetchAvailableItems(contents,itemID,goodLocation,Wearable.FILTER_ANY,true);
		if(items.isEmpty())
			items=CMLib.english().fetchAvailableItems(contents,itemID,goodLocation,Wearable.FILTER_ANY,false);
		return items;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public List<Item> findItems(final String itemID)
	{
		if(contents.isEmpty())
			return new Vector<Item>(1);
		List items=CMLib.english().fetchEnvironmentals(contents,itemID,true);
		if(items.isEmpty())
			items=CMLib.english().fetchEnvironmentals(contents,itemID, false);
		return items;
	}

	@Override
	public void addItem(final Item item, Expire expire)
	{
		if(expire == null)
		{
			expire=Expire.Never;
		}
		int numMins = 0;
		switch(expire)
		{
		case Monster_EQ:
			addItem(item);
			numMins = CMProps.getIntVar(CMProps.Int.EXPIRE_MONSTER_EQ);
			break;
		case Monster_Body:
			insertItemUpTop(item);
			numMins = CMProps.getIntVar(CMProps.Int.EXPIRE_MONSTER_BODY);
			break;
		case Player_Body:
			insertItemUpTop(item);
			numMins = CMProps.getIntVar(CMProps.Int.EXPIRE_PLAYER_BODY);
			break;
		case Player_Drop:
			addItem(item);
			numMins = CMProps.getIntVar(CMProps.Int.EXPIRE_PLAYER_DROP);
			break;
		case Resource:
			addItem(item);
			numMins = CMProps.getIntVar(CMProps.Int.EXPIRE_RESOURCE);
			break;
		case Never:
			addItem(item);
			break;
		case Inheret:
			addItem(item);
			return;
		}
		if(numMins==0)
			item.setExpirationDate(0);
		else
			item.setExpirationDate(System.currentTimeMillis()+(numMins * TimeManager.MILI_MINUTE));
	}

	protected void insertItemUpTop(final Item item)
	{
		if((item!=null)&&(!item.amDestroyed()))
		{
			item.setOwner(this);
			if(!contents.isEmpty())
				contents.add(0,item);
			else
				contents.add(item);
			item.recoverPhyStats();
		}
	}

	@Override
	public void addItem(final Item item)
	{
		if((item!=null)&&(!item.amDestroyed()))
		{
			item.setOwner(this);
			contents.addElement(item);
			item.recoverPhyStats();
		}
	}

	@Override
	public void delItem(final Item item)
	{
		contents.removeElement(item);
		item.recoverPhyStats();
	}

	@Override
	public void delAllItems(final boolean destroy)
	{
		if((destroy)
		&&(numItems()>0))
		{
			final List<Item> delThese = new LinkedList<Item>();
			delThese.addAll(contents);
			contents.clear();
			for(final Item I : delThese)
			{
				if(I!=null)
				{
					// since were deleting you AND all your peers, no need for Item to do it.
					I.setOwner(null);
					I.destroy();
				}
			}
		}
		contents.clear();
	}

	@Override
	public int numItems()
	{
		return contents.size();
	}

	@Override
	public boolean isContent(final Item item)
	{
		return contents.contains(item);
	}

	@Override
	public Item getItem(final int i)
	{
		try
		{
			return contents.elementAt(i);
		}
		catch(final java.lang.ArrayIndexOutOfBoundsException x)
		{
		}
		return null;
	}

	@Override
	public void eachItem(final EachApplicable<Item> applier)
	{
		final List<Item> contents=this.contents;
		if((contents!=null)&&(!contents.isEmpty()))
		{
			try
			{
				for(int a=0;a<contents.size();a++)
				{
					final Item I=contents.get(a);
					if(I!=null)
						applier.apply(I);
				}
			}
			catch(final ArrayIndexOutOfBoundsException e)
			{
			}
		}
	}

	@Override
	public Item getRandomItem()
	{
		if(numItems()==0)
			return null;
		return getItem(CMLib.dice().roll(1,numItems(),-1));
	}

	@Override
	public String getContextName(final Environmental E)
	{
		if(E instanceof Exit)
		{
			for(int e=0;e<exits.length;e++)
			{
				if(exits[e]==E)
					return CMLib.directions().getDirectionName(e, CMLib.flags().getDirType(this));
			}
			return E.Name();
		}
		else
		if(E instanceof MOB)
		{
			final String ctxName=CMLib.english().getContextName(inhabitants,E);
			if(ctxName!=null)
				return ctxName;
		}
		else
		if(E instanceof Item)
		{
			final String ctxName=CMLib.english().getContextName(contents,E);
			if(ctxName!=null)
				return ctxName;
		}
		else
		if(E!=null)
			return E.name();
		return "nothing";
	}

	@Override
	public PhysicalAgent fetchFromMOBRoomItemExit(final MOB mob, final Item goodLocation, String thingName, final Filterer<Environmental> filter)
	{
		PhysicalAgent found=null;
		String newThingName=CMLib.lang().preItemParser(thingName);
		if(newThingName!=null)
			thingName=newThingName;
		final boolean mineOnly=(mob!=null)&&(thingName.toUpperCase().trim().startsWith("MY "));
		if(mineOnly)
			thingName=thingName.trim().substring(3).trim();
		if((mob!=null)&&((filter!=Wearable.FILTER_WORNONLY)))
		{
			found=mob.fetchItem(goodLocation, new Filterer<Environmental>()
			{
				@Override
				public boolean passesFilter(final Environmental obj)
				{
					return filter.passesFilter(obj) && Wearable.FILTER_UNWORNONLY.passesFilter(obj);
				}
			}, thingName);
		}
		if((found==null)&&(!mineOnly))
		{
			found=(Exit)CMLib.english().fetchEnvironmental(Arrays.asList(exits),thingName,true);
			if(found==null)
				found=CMLib.english().fetchAvailableItem(contents,thingName,goodLocation,filter,true);
			if(found==null)
				found=(Exit)CMLib.english().fetchEnvironmental(Arrays.asList(exits),thingName,false);
			if(found==null)
				found=CMLib.english().fetchAvailableItem(contents,thingName,goodLocation,filter,false);

			if((found instanceof Item)  // the smurfy well/gate exception
			&&(goodLocation==null)
			&&(found.displayText().length()==0)
			&&(thingName.indexOf('.')<0))
			{
				PhysicalAgent visibleItem=null;
				visibleItem=(Exit)CMLib.english().fetchEnvironmental(Arrays.asList(exits),thingName,false);
				if(visibleItem==null)
					visibleItem=fetchFromMOBRoomItemExit(null,null,thingName+".2",filter);
				if(visibleItem!=null)
					found=visibleItem;
			}

			if((found!=null)&&(CMLib.flags().canBeSeenBy(found,mob)))
				return found;
			while((found!=null)&&(!CMLib.flags().canBeSeenBy(found,mob)))
			{
				newThingName=CMLib.english().bumpDotContextNumber(thingName,1);
				if(!newThingName.equals(thingName))
				{
					thingName=newThingName;
					found=fetchFromRoomFavorItems(goodLocation, thingName);
				}
				else
					found=null;
			}
		}
		if((mob!=null)&&(found==null)&&((filter!=Wearable.FILTER_UNWORNONLY)))
		{
			found=mob.fetchItem(null, new Filterer<Environmental>()
			{
				@Override
				public boolean passesFilter(final Environmental obj)
				{
					return filter.passesFilter(obj) && Wearable.FILTER_WORNONLY.passesFilter(obj);
				}
			}, thingName);
		}
		if(found==null)
		{
			newThingName=CMLib.lang().failedItemParser(thingName);
			if(newThingName!=null)
				return fetchFromMOBRoomItemExit(mob,goodLocation,newThingName,filter);
		}
		return found;
	}

	@Override
	public PhysicalAgent fetchFromRoomFavorItems(final Item goodLocation, String thingName)
	{
		// def was Wearable.FILTER_UNWORNONLY;
		String newThingName=CMLib.lang().preItemParser(thingName);
		if(newThingName!=null)
			thingName=newThingName;
		PhysicalAgent found=null;
		final int[] contextNumber=new int[]{0};
		if(!contents.isEmpty())
			found=(PhysicalAgent)CMLib.english().fetchAvailable(contents,thingName,goodLocation,Wearable.FILTER_ANY,true,contextNumber);
		if(found==null)
			found=(PhysicalAgent)CMLib.english().fetchAvailable(Arrays.asList(exits),thingName,goodLocation,Wearable.FILTER_ANY,true,contextNumber);
		if((found==null)&&(!inhabitants.isEmpty()))
			found=(PhysicalAgent)CMLib.english().fetchAvailable(inhabitants,thingName,goodLocation,Wearable.FILTER_ANY,true,contextNumber);
		contextNumber[0]=0;
		if((found==null)&&(!contents.isEmpty()))
			found=(PhysicalAgent)CMLib.english().fetchAvailable(contents,thingName,goodLocation,Wearable.FILTER_ANY,false,contextNumber);
		if(found==null)
			found=(PhysicalAgent)CMLib.english().fetchAvailable(Arrays.asList(exits),thingName,goodLocation,Wearable.FILTER_ANY,false,contextNumber);
		if((found==null)&&(!inhabitants.isEmpty()))
			found=(PhysicalAgent)CMLib.english().fetchAvailable(inhabitants,thingName,goodLocation,Wearable.FILTER_ANY,false,contextNumber);

		if((found!=null) // the smurfy well exception
		&&(found instanceof Item)
		&&(goodLocation==null)
		&&(found.displayText().length()==0)
		&&(thingName.indexOf('.')<0))
		{
			final PhysicalAgent visibleItem=fetchFromRoomFavorItems(null,thingName+".2");
			if(visibleItem!=null)
				found=visibleItem;
		}
		if(found==null)
		{
			newThingName=CMLib.lang().failedItemParser(thingName);
			if(newThingName!=null)
				return fetchFromRoomFavorItems(goodLocation,newThingName);
		}
		return found;
	}

	@Override
	public PhysicalAgent fetchFromRoomFavorExits(String thingName)
	{
		String newThingName=CMLib.lang().preItemParser(thingName);
		if(newThingName!=null)
			thingName=newThingName;
		final Item goodLocation=null;
		PhysicalAgent found=null;
		final int dirCode = CMLib.directions().getGoodDirectionCode(thingName);
		final int[] contextNumber=new int[]{0};
		if(dirCode>=0)
			found=getRoomInDir(dirCode);
		if(found==null)
			found=(PhysicalAgent)CMLib.english().fetchAvailable(Arrays.asList(exits),thingName,goodLocation,Wearable.FILTER_ANY,true,contextNumber);
		if((found==null)&&(!contents.isEmpty()))
			found=(PhysicalAgent)CMLib.english().fetchAvailable(contents,thingName,goodLocation,Wearable.FILTER_ANY,true,contextNumber);
		if((found==null)&&(!inhabitants.isEmpty()))
			found=(PhysicalAgent)CMLib.english().fetchAvailable(inhabitants,thingName,goodLocation,Wearable.FILTER_ANY,true,contextNumber);
		contextNumber[0]=0;
		if(found==null)
			found=(PhysicalAgent)CMLib.english().fetchAvailable(Arrays.asList(exits),thingName,goodLocation,Wearable.FILTER_ANY,false,contextNumber);
		if((found==null)&&(!contents.isEmpty()))
			found=(PhysicalAgent)CMLib.english().fetchAvailable(contents,thingName,goodLocation,Wearable.FILTER_ANY,false,contextNumber);
		if((found==null)&&(!inhabitants.isEmpty()))
			found=(PhysicalAgent)CMLib.english().fetchAvailable(inhabitants,thingName,goodLocation,Wearable.FILTER_ANY,false,contextNumber);
		if(found==null)
		{
			newThingName=CMLib.lang().failedItemParser(thingName);
			if(newThingName!=null)
				return fetchFromRoomFavorMOBs(goodLocation,newThingName);
		}
		return found;
	}

	@Override
	public PhysicalAgent fetchFromRoomFavorMOBs(final Item goodLocation, String thingName)
	{
		// def was Wearable.FILTER_UNWORNONLY;
		String newThingName=CMLib.lang().preItemParser(thingName);
		if(newThingName!=null)
			thingName=newThingName;
		final int[] contextNumber = new int[]{0};
		PhysicalAgent found=null;
		if(!inhabitants.isEmpty())
			found=(PhysicalAgent)CMLib.english().fetchAvailable(inhabitants,thingName,goodLocation,Wearable.FILTER_ANY,true,contextNumber);
		if((found==null)&&(!contents.isEmpty()))
			found=(PhysicalAgent)CMLib.english().fetchAvailable(contents,thingName,goodLocation,Wearable.FILTER_ANY,true,contextNumber);
		if(found==null)
			found=(PhysicalAgent)CMLib.english().fetchAvailable(Arrays.asList(exits),thingName,goodLocation,Wearable.FILTER_ANY,true,contextNumber);
		contextNumber[0]=0;
		if((found==null)&&(!inhabitants.isEmpty()))
			found=(PhysicalAgent)CMLib.english().fetchAvailable(inhabitants,thingName,goodLocation,Wearable.FILTER_ANY,false,contextNumber);
		if((found==null)&&(!contents.isEmpty()))
			found=(PhysicalAgent)CMLib.english().fetchAvailable(contents,thingName,goodLocation,Wearable.FILTER_ANY,false,contextNumber);
		if(found==null)
			found=(PhysicalAgent)CMLib.english().fetchAvailable(Arrays.asList(exits),thingName,goodLocation,Wearable.FILTER_ANY,false,contextNumber);
		if(found==null)
		{
			newThingName=CMLib.lang().failedItemParser(thingName);
			if(newThingName!=null)
				return fetchFromRoomFavorMOBs(goodLocation,newThingName);
		}
		return found;
	}

	@Override
	public PhysicalAgent fetchFromMOBRoomFavorsItems(final MOB mob, final Item goodLocation, final String thingName, final Filterer<Environmental> filter)
	{
		return fetchFromMOBRoom(mob,goodLocation,thingName,filter,true);
	}

	@Override
	public PhysicalAgent fetchFromMOBRoomFavorsMOBs(final MOB mob, final Item goodLocation, final String thingName, final Filterer<Environmental> filter)
	{
		return fetchFromMOBRoom(mob,goodLocation,thingName,filter,false);
	}

	private PhysicalAgent fetchFromMOBRoom(final MOB mob, final Item goodLocation, String thingName, final Filterer<Environmental> filter, final boolean favorItems)
	{
		PhysicalAgent found=null;
		String newThingName=CMLib.lang().preItemParser(thingName);
		if(newThingName!=null)
			thingName=newThingName;
		final boolean mineOnly=(mob!=null)&&(thingName.toUpperCase().trim().startsWith("MY "));
		if(mineOnly)
			thingName=thingName.trim().substring(3).trim();
		if((mob!=null)&&(favorItems)&&(filter!=Wearable.FILTER_WORNONLY))
		{
			final Filterer<Environmental> mobCheckFilter = new Filterer<Environmental>()
			{
				@Override
				public boolean passesFilter(final Environmental obj)
				{
					return filter.passesFilter(obj) && Wearable.FILTER_UNWORNONLY.passesFilter(obj);
				}
			};
			found=mob.fetchItem(goodLocation, mobCheckFilter, thingName);
			if(found == null) // smurfy well exception -- see below -- this is under favorItems and !wornonly
			{
				// this ugliness allows you do use dot syntax on things on the ground when you have SOME stuff in inventory, but not much
				final int dotNumber=CMLib.english().getContextDotNumber(thingName);
				if(dotNumber > 1)
				{
					String testThingName =  CMLib.english().bumpDotContextNumber(thingName, -(dotNumber-1));
					int numMobHas = 0;
					for(int i=1;i<=dotNumber;i++)
					{
						if(mob.fetchItem(goodLocation, mobCheckFilter, testThingName)==null)
							break;
						numMobHas++;
						testThingName =  CMLib.english().bumpDotContextNumber(testThingName, 1);
					}
					if(dotNumber > numMobHas)
					{
						final int curDotNumber=numMobHas+1;
						final int delta = -(curDotNumber-1) + (dotNumber-numMobHas-1);
						testThingName =  CMLib.english().bumpDotContextNumber(testThingName, delta);
						found = fetchFromRoomFavorItems(goodLocation, testThingName);
						if((found != null)
						&&((filter==null)||(filter.passesFilter(found))))
							return found;
					}
				}
			}
		}
		if((found==null)&&(!mineOnly))
		{
			if(favorItems)
				found=fetchFromRoomFavorItems(goodLocation, thingName);
			else
				found=fetchFromRoomFavorMOBs(goodLocation, thingName);
			if((found!=null)
			&&(CMLib.flags().canBeSeenBy(found,mob)))
				return found;
			while((found!=null)&&(!CMLib.flags().canBeSeenBy(found,mob)))
			{
				newThingName=CMLib.english().bumpDotContextNumber(thingName,1);
				if(!newThingName.equals(thingName))
				{
					thingName=newThingName;
					if(favorItems)
						found=fetchFromRoomFavorItems(goodLocation, thingName);
					else
						found=fetchFromRoomFavorMOBs(goodLocation, thingName);
				}
				else
					found=null;
			}
		}
		if((mob!=null)&&(!favorItems)&&(filter!=Wearable.FILTER_WORNONLY))
		{
			found=mob.fetchItem(goodLocation, new Filterer<Environmental>()
			{
				@Override
				public boolean passesFilter(final Environmental obj)
				{
					return filter.passesFilter(obj) && Wearable.FILTER_UNWORNONLY.passesFilter(obj);
				}
			}, thingName);
		}
		if((mob!=null)&&(found==null)&&(filter!=Wearable.FILTER_UNWORNONLY))
		{
			found=mob.fetchItem(null, new Filterer<Environmental>()
			{
				@Override
				public boolean passesFilter(final Environmental obj)
				{
					return filter.passesFilter(obj) && Wearable.FILTER_WORNONLY.passesFilter(obj);
				}
			}, thingName);
		}
		if((mob!=null)&&(found==null))
			found=mob.fetchItem(goodLocation,filter,thingName);
		if(found==null)
		{
			final Directions.DirType dirType=CMLib.flags().getDirType(this);
			for(int d=0;d<exits.length;d++)
			{
				if((exits[d]!=null)
				&&(thingName.equalsIgnoreCase(CMLib.directions().getDirectionName(d,dirType))))
					return getExitInDir(d);
			}
		}
		if(found==null)
		{
			newThingName=CMLib.lang().failedItemParser(thingName);
			if(newThingName!=null)
				return fetchFromMOBRoom(mob,goodLocation,newThingName,filter,favorItems);
		}
		return found;
	}

	@Override
	public int pointsPerMove()
	{
		return getArea().getClimateObj().adjustMovement(getMovementCost(),this);
	}

	protected int baseThirst()
	{
		return 1;
	}

	@Override
	public int thirstPerRound()
	{
		final int derivedClimate=getClimateType();
		int adjustment=0;
		if(CMath.bset(derivedClimate, Places.CLIMASK_HOT))
			adjustment+=1;
		if(CMath.bset(derivedClimate, Places.CLIMASK_WET))
			adjustment-=1;
		if(CMath.bset(derivedClimate, Places.CLIMASK_DRY))
			adjustment+=1;
		if(CMath.bset(derivedClimate, Places.CLIMASK_WINDY))
			adjustment+=1;
		if(getArea().getClimateObj()!=null)
			return getArea().getClimateObj().adjustWaterConsumption(baseThirst()+adjustment,this);
		return 0;
	}

	@Override
	public int minRange()
	{
		return Integer.MIN_VALUE;
	}

	@Override
	public int maxRange()
	{
		return phyStats().height();
	}

	@Override
	public void addEffect(final Ability to)
	{
		if(to==null)
			return;
		if(fetchEffect(to.ID())!=null)
			return;
		if(affects==null)
			affects=new SVector<Ability>(1);
		if(affects.contains(to))
			return;
		affects.addElement(to);
		to.setAffectedOne(this);
	}

	@Override
	public void addNonUninvokableEffect(final Ability to)
	{
		if(to==null)
			return;
		if(fetchEffect(to.ID())!=null)
			return;
		if(affects==null)
			affects=new SVector<Ability>(1);
		to.makeNonUninvokable();
		to.makeLongLasting();
		affects.addElement(to);
		to.setAffectedOne(this);
	}

	@Override
	public void delEffect(final Ability to)
	{
		if(affects==null)
			return;
		if(affects.remove(to))
		{
			to.setAffectedOne(null);
			if(affects.isEmpty())
				affects=new SVector<Ability>(1);
		}
	}

	@Override
	public void eachEffect(final EachApplicable<Ability> applier)
	{
		final List<Ability> affects=this.affects;
		if((affects!=null)&&(!affects.isEmpty()))
		try
		{
			for(int a=0;a<affects.size();a++)
			{
				final Ability A=affects.get(a);
				if(A!=null)
					applier.apply(A);
			}
		}
		catch(final ArrayIndexOutOfBoundsException e)
		{
		}
	}

	@Override
	public void delAllEffects(final boolean unInvoke)
	{
		if(affects==null)
			return;
		for(int a=numEffects()-1;a>=0;a--)
		{
			final Ability A=fetchEffect(a);
			if(A!=null)
			{
				if(unInvoke)
					A.unInvoke();
				A.setAffectedOne(null);
			}
		}
		affects=new SVector<Ability>(1);
	}

	@Override
	public int numEffects()
	{
		if(affects==null)
			return 0;
		return affects.size();
	}

	@SuppressWarnings("unchecked")

	@Override
	public Enumeration<Ability> effects()
	{
		return (affects==null)?EmptyEnumeration.INSTANCE:affects.elements();
	}

	@Override
	public Ability fetchEffect(final int index)
	{
		if(affects==null)
			return null;
		try
		{
			return affects.elementAt(index);
		}
		catch(final java.lang.ArrayIndexOutOfBoundsException x)
		{
		}
		return null;
	}

	@Override
	public Ability fetchEffect(final String ID)
	{
		if(affects==null)
			return null;
		for(final Enumeration<Ability> a=effects();a.hasMoreElements();)
		{
			final Ability A=a.nextElement();
			if(A.ID().equals(ID))
				return A;
		}
		return null;
	}

	/** Manipulation of Behavior objects, which includes
	 * movement, speech, spellcasting, etc, etc.*/
	@Override
	public void addBehavior(final Behavior to)
	{
		if(to==null)
			return;
		if(behaviors==null)
			behaviors=new SVector<Behavior>(1);
		for(final Behavior B : behaviors)
		{
			if(B.ID().equals(to.ID()))
				return;
		}
		if(behaviors.isEmpty())
			CMLib.threads().startTickDown(this,Tickable.TICKID_ROOM_BEHAVIOR,1);
		to.startBehavior(this);
		behaviors.addElement(to);
	}

	@Override
	public void delBehavior(final Behavior to)
	{
		if(behaviors==null)
			return;
		if(behaviors.remove(to))
		{
			to.endBehavior(this);
			if(behaviors.isEmpty())
				behaviors=new SVector<Behavior>(1);
			if(((behaviors==null)||(behaviors.isEmpty()))&&((scripts==null)||(scripts.isEmpty())))
				CMLib.threads().deleteTick(this,Tickable.TICKID_ROOM_BEHAVIOR);
		}
	}

	@Override
	public void delAllBehaviors()
	{
		final boolean didSomething=(behaviors!=null)&&(!behaviors.isEmpty());
		if(didSomething)
			behaviors.clear();
		behaviors=null;
		if(didSomething && ((scripts==null)||(scripts.isEmpty())))
			CMLib.threads().deleteTick(this,Tickable.TICKID_ROOM_BEHAVIOR);
	}

	@Override
	public int numBehaviors()
	{
		if(behaviors==null)
			return 0;
		return behaviors.size();
	}

	@SuppressWarnings("unchecked")

	@Override
	public Enumeration<Behavior> behaviors()
	{
		return (behaviors==null)?EmptyEnumeration.INSTANCE:behaviors.elements();
	}

	@Override
	public Behavior fetchBehavior(final int index)
	{
		if(behaviors==null)
			return null;
		try
		{
			return behaviors.elementAt(index);
		}
		catch(final java.lang.ArrayIndexOutOfBoundsException x)
		{
		}
		return null;
	}

	@Override
	public Behavior fetchBehavior(final String ID)
	{
		if(behaviors==null)
			return null;
		for(final Behavior B : behaviors)
		{
			if(B.ID().equalsIgnoreCase(ID))
				return B;
		}
		return null;
	}

	@Override
	public void eachBehavior(final EachApplicable<Behavior> applier)
	{
		final List<Behavior> behaviors=this.behaviors;
		if((behaviors!=null)&&(!behaviors.isEmpty()))
		try
		{
			for(int a=0;a<behaviors.size();a++)
			{
				final Behavior B=behaviors.get(a);
				if(B!=null)
					applier.apply(B);
			}
		}
		catch(final ArrayIndexOutOfBoundsException e)
		{
		}
	}

	/** Manipulation of the scripts list */
	@Override
	public void addScript(final ScriptingEngine S)
	{
		if(scripts==null)
			scripts=new SVector<ScriptingEngine>(1);
		if(S==null)
			return;
		if(!scripts.contains(S))
		{
			for(final Enumeration<ScriptingEngine> s2=scripts();s2.hasMoreElements();)
			{
				final ScriptingEngine S2=s2.nextElement();
				if(S2.getScript().equalsIgnoreCase(S.getScript()))
					return;
			}
			if(scripts.isEmpty())
				CMLib.threads().startTickDown(this,Tickable.TICKID_ROOM_BEHAVIOR,1);
			scripts.addElement(S);
		}
	}

	@Override
	public void delScript(final ScriptingEngine S)
	{
		if(scripts!=null)
		{
			if(scripts.remove(S))
			{
				if(scripts.isEmpty())
					scripts=new SVector<ScriptingEngine>(1);
				if(((behaviors==null)||(behaviors.isEmpty()))&&((scripts==null)||(scripts.isEmpty())))
					CMLib.threads().deleteTick(this,Tickable.TICKID_ROOM_BEHAVIOR);
			}
		}
	}

	@Override
	public void delAllScripts()
	{
		final boolean didSomething=(scripts!=null)&&(!scripts.isEmpty());
		if(didSomething)
			scripts.clear();
		scripts=null;
		if(didSomething && ((behaviors==null)||(behaviors.isEmpty())))
			CMLib.threads().deleteTick(this,Tickable.TICKID_ROOM_BEHAVIOR);
	}

	@Override
	public int numScripts()
	{
		return (scripts==null)?0:scripts.size();
	}

	@SuppressWarnings("unchecked")

	@Override
	public Enumeration<ScriptingEngine> scripts()
	{
		return (scripts==null)?EmptyEnumeration.INSTANCE:scripts.elements();
	}

	@Override
	public ScriptingEngine fetchScript(final int x)
	{
		try
		{
			return scripts.elementAt(x);
		}
		catch (final Exception e)
		{
		}
		return null;
	}

	@Override
	public void eachScript(final EachApplicable<ScriptingEngine> applier)
	{
		final List<ScriptingEngine> scripts=this.scripts;
		if((scripts!=null)&&(!scripts.isEmpty()))
		try
		{
			for(int a=0;a<scripts.size();a++)
			{
				final ScriptingEngine S=scripts.get(a);
				if(S!=null)
					applier.apply(S);
			}
		}
		catch(final ArrayIndexOutOfBoundsException e)
		{
		}
	}

	@Override
	public String L(final String str, final String... xs)
	{
		return CMLib.lang().fullSessionTranslation(str, xs);
	}

	@Override
	public int getSaveStatIndex()
	{
		return (xtraValues == null) ? getStatCodes().length : getStatCodes().length - xtraValues.length;
	}

	protected static final String[]	STDCODES	= { "CLASS", "DISPLAY", "DESCRIPTION", "TEXT", "AFFBEHAV", "IMAGE", "CLIMATE", "ATMOSPHERE", "ROOMID" };
	private static String[]			codes		= null;

	@Override
	public String[] getStatCodes()
	{
		if (codes == null)
			codes = CMProps.getStatCodesList(STDCODES, this);
		return codes;
	}

	@Override
	public boolean isStat(final String code)
	{
		return CMParms.indexOf(getStatCodes(), code.toUpperCase().trim()) >= 0;
	}

	protected int getCodeNum(final String code)
	{
		return CMParms.indexOf(codes, code.toUpperCase());
	}

	@Override
	public String getStat(final String code)
	{
		switch (getCodeNum(code))
		{
		case 0:
			return CMClass.classID(this);
		case 1:
			return displayText();
		case 2:
			return description();
		case 3:
			return text();
		case 4:
			return CMLib.coffeeMaker().getExtraEnvironmentalXML(this);
		case 5:
			return rawImage();
		case 6:
			return "" + getClimateTypeCode();
		case 7:
			return "" + getAtmosphereCode();
		case 8:
			return ""+CMLib.map().getExtendedRoomID(this);
		default:
			return CMProps.getStatCodeExtensionValue(getStatCodes(), xtraValues, code);
		}
	}

	@Override
	public void setStat(final String code, final String val)
	{
		switch (getCodeNum(code))
		{
		case 0:
			return;
		case 1:
			setDisplayText(val);
			break;
		case 2:
			setDescription(val);
			break;
		case 3:
			setMiscText(val);
			break;
		case 4:
		{
			delAllEffects(true);
			delAllBehaviors();
			CMLib.coffeeMaker().unpackExtraEnvironmentalXML(this, CMLib.xml().parseAllXML(val));
			break;
		}
		case 5:
			setImage(val);
			break;
		case 6:
			setClimateType((CMath.s_int(val) < 0) ? -1 : CMath.s_parseBitIntExpression(Places.CLIMATE_DESCS, val));
			break;
		case 7:
		{
			if (CMath.isMathExpression(val))
				setAtmosphere(CMath.s_parseIntExpression(val));
			final int matCode = RawMaterial.CODES.FIND_IgnoreCase(val);
			if (matCode >= 0)
				setAtmosphere(matCode);
			break;
		}
		case 8:
			this.setRoomID(val);
			break;
		default:
			CMProps.setStatCodeExtensionValue(getStatCodes(), xtraValues, code, val);
			break;
		}
	}

	@Override
	public boolean sameAs(final Environmental E)
	{
		if (!(E instanceof StdRoom))
			return false;
		final String[] codes = getStatCodes();
		for (int i = 0; i < codes.length; i++)
		{
			if((!E.getStat(codes[i]).equals(getStat(codes[i])))
			&&(!codes[i].equals("ROOMID"))
			&&(!codes[i].equals("ATMOSPHERE")))
				return false;
		}
		return true;
	}
}

<MSG> 

git-svn-id: svn://192.168.1.10/public/CoffeeMud@8968 0d6f1817-ed0e-0410-87c9-987e46238f29

<DFF> @@ -708,6 +708,7 @@ public class StdRoom implements Room
 					gridParent.executeMsg(myHost,msg);
 				else
 				if((roomID().length()>0)
+				&&((getArea()==null)||(!CMath.bset(getArea().flags(), Area.FLAG_INSTANCE_CHILD)))
 				&&(CMSecurity.isSaveFlag("ROOMMOBS")
 					||CMSecurity.isSaveFlag("ROOMITEMS")
 					||CMSecurity.isSaveFlag("ROOMSHOPS")))

{'commit': 'diff --git a/com/planet_ink/coffee_mud/Locales/StdRoom.java b/com/planet_ink/coffee_mud/Locales/StdRoom.java\nindex a1b8efae4d..b3659f4b04 100644\n--- a/com/planet_ink/coffee_mud/Locales/StdRoom.java\n+++ b/com/planet_ink/coffee_mud/Locales/StdRoom.java\n@@ -708,6 +708,7 @@ public class StdRoom implements Room\n \t\t\t\t\tgridParent.executeMsg(myHost,msg);\r\n \t\t\t\telse\r\n \t\t\t\tif((roomID().length()>0)\r\n+\t\t\t\t&&((getArea()==null)||(!CMath.bset(getArea().flags(), Area.FLAG_INSTANCE_CHILD)))\r\n \t\t\t\t&&(CMSecurity.isSaveFlag("ROOMMOBS")\r\n \t\t\t\t\t||CMSecurity.isSaveFlag("ROOMITEMS")\r\n \t\t\t\t\t||CMSecurity.isSaveFlag("ROOMSHOPS")))\r\n', 'commit_subject': '', 'repo_name': 'bozimmerman/CoffeeMud', 'committer': {'name': 'bozimmerman', 'email': 'dc45fe023482b3b890b5e574e53c1d051f45b1ef@zimmers.net', 'time_sec': '1300080950', 'tz_offset': '0', 'date': {'seconds': '1300080950'}}, 'commit_tree': '6254a50437f30232538eaa6f3e162c79b5abf678', 'commit_message': '\n\ngit-svn-id: svn://192.168.1.10/public/CoffeeMud@8968 0d6f1817-ed0e-0410-87c9-987e46238f29\n', 'language_name': 'JavaScript', 'license': 'apache-2.0', 'hunks': '@@ -708,6 +708,7 @@ public class StdRoom implements Room\n \t\t\t\t\tgridParent.executeMsg(myHost,msg);\r\n \t\t\t\telse\r\n \t\t\t\tif((roomID().length()>0)\r\n+\t\t\t\t&&((getArea()==null)||(!CMath.bset(getArea().flags(), Area.FLAG_INSTANCE_CHILD)))\r\n \t\t\t\t&&(CMSecurity.isSaveFlag("ROOMMOBS")\r\n \t\t\t\t\t||CMSecurity.isSaveFlag("ROOMITEMS")\r\n \t\t\t\t\t||CMSecurity.isSaveFlag("ROOMSHOPS")))\r\n', 'addition_count': 1, 'deletion_count': 0, 'src_file': 'a/com/planet_ink/coffee_mud/Locales/StdRoom.java', 'tgt_file': 'b/com/planet_ink/coffee_mud/Locales/StdRoom.java', 'file_extension': '.java', 'before_file': 'package com.planet_ink.coffee_mud.Locales;\nimport com.planet_ink.coffee_mud.Libraries.interfaces.*;\nimport com.planet_ink.coffee_mud.Libraries.interfaces.AchievementLibrary.Event;\nimport com.planet_ink.coffee_mud.core.interfaces.*;\nimport com.planet_ink.coffee_mud.core.interfaces.EachApplicable.ApplyAffectPhyStats;\nimport com.planet_ink.coffee_mud.core.interfaces.ItemPossessor.Expire;\nimport com.planet_ink.coffee_mud.core.interfaces.ItemPossessor.Move;\nimport com.planet_ink.coffee_mud.core.*;\nimport com.planet_ink.coffee_mud.core.collections.*;\nimport com.planet_ink.coffee_mud.Abilities.interfaces.*;\nimport com.planet_ink.coffee_mud.Areas.interfaces.*;\nimport com.planet_ink.coffee_mud.Behaviors.interfaces.*;\nimport com.planet_ink.coffee_mud.CharClasses.interfaces.*;\nimport com.planet_ink.coffee_mud.Commands.interfaces.*;\nimport com.planet_ink.coffee_mud.Common.interfaces.*;\nimport com.planet_ink.coffee_mud.Exits.interfaces.*;\nimport com.planet_ink.coffee_mud.Items.Basic.StdItem;\nimport com.planet_ink.coffee_mud.Items.interfaces.*;\nimport com.planet_ink.coffee_mud.Locales.interfaces.*;\nimport com.planet_ink.coffee_mud.MOBS.interfaces.*;\nimport com.planet_ink.coffee_mud.Races.interfaces.*;\n\nimport java.util.*;\nimport java.util.concurrent.atomic.AtomicInteger;\n/*\n   Copyright 2001-2022 Bo Zimmerman\n\n   Licensed under the Apache License, Version 2.0 (the "License");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n\t   http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n*/\npublic class StdRoom implements Room\n{\n\t@Override\n\tpublic String ID()\n\t{\n\t\treturn "StdRoom";\n\t}\n\n\tprotected String\t\t\t_roomID\t\t\t\t= "";\n\tprotected String\t\t\tname\t\t\t\t= "the room";\n\tprotected String\t\t\tdisplayText\t\t\t= L("Standard Room");\n\tprotected String\t\t\trawImageName\t\t= null;\n\tprotected String\t\t\tcachedImageName\t\t= null;\n\tprotected Object\t\t\tdescription\t\t\t= null;\n\tprotected Area\t\t\t\tmyArea\t\t\t\t= null;\n\tprotected PhyStats\t\t\tphyStats\t\t\t= (PhyStats) CMClass.getCommon("DefaultPhyStats");\n\tprotected PhyStats\t\t\tbasePhyStats\t\t= (PhyStats) CMClass.getCommon("DefaultPhyStats");\n\tprotected Exit[]\t\t\texits\t\t\t\t= new Exit[Directions.NUM_DIRECTIONS()];\n\tprotected Room[]\t\t\tdoors\t\t\t\t= new Room[Directions.NUM_DIRECTIONS()];\n\tprotected String[]\t\t\txtraValues\t\t\t= null;\n\tprotected boolean\t\t\tmobility\t\t\t= true;\n\tprotected GridLocale\t\tgridParent\t\t\t= null;\n\tprotected int\t\t\t\ttickStatus\t\t\t= Tickable.STATUS_NOT;\n\tprotected long\t\t\t\texpirationDate\t\t= 0;\n\tprotected int\t\t\t\tatmosphere\t\t\t= ATMOSPHERE_INHERIT;\n\tprotected int\t\t\t\tclimask\t\t\t\t= CLIMASK_INHERIT;\n\tprotected int\t\t\t\tmyResource\t\t\t= -1;\n\tprotected long\t\t\t\tlastResourceTime\t= 0;\n\tprotected boolean\t\t\tamDestroyed\t\t\t= false;\n\tprotected boolean\t\t\tskyedYet\t\t\t= false;\n\tprotected volatile short\tcombatTurnMobIndex\t= 0;\n\n\tprotected final AtomicInteger\t\troomRecoverMarker\t= new AtomicInteger();\n\tprotected SVector<Ability>\t\t\taffects\t\t\t\t= null;\n\tprotected SVector<Behavior>\t\t\tbehaviors\t\t\t= null;\n\tprotected SVector<ScriptingEngine>\tscripts\t\t\t\t= null;\n\tprotected SVector<MOB>\t\t\t\tinhabitants\t\t\t= new SVector<MOB>(1);\n\tprotected SVector<Item>\t\t\t\tcontents\t\t\t= new SVector<Item>(1);\n\tprotected Room\t\t\t\t\t\tme\t\t\t\t\t= this;\n\n\t@SuppressWarnings("rawtypes")\n\tprotected ApplyAffectPhyStats affectPhyStats \t= new ApplyAffectPhyStats<Physical>(this);\n\t// base move points and thirst points per round\n\n\tpublic StdRoom()\n\t{\n\t\tsuper();\n\t\t//CMClass.bumpCounter(this,CMClass.CMObjectType.LOCALE);//removed for mem & perf\n\t\txtraValues=CMProps.getExtraStatCodesHolder(this);\n\t\tsetMovementCost(2); // movement consumption\n\t\tsetRoomSize(((domainType()&Room.INDOORS)>0)?1:10);\n\t\trecoverPhyStats();\n\t}\n\n\t/*\n\tprotected void finalize()\n\t{\n\t\tCMClass.unbumpCounter(this, CMClass.CMObjectType.LOCALE);\n\t}// removed for mem & perf\n\t*/\n\n\t@Override\n\tpublic void initializeClass()\n\t{\n\t}\n\n\t@Override\n\tpublic CMObject newInstance()\n\t{\n\t\ttry\n\t\t{\n\t\t\treturn this.getClass().newInstance();\n\t\t}\n\t\tcatch(final Exception e)\n\t\t{\n\t\t\tLog.errOut(ID(),e);\n\t\t}\n\t\treturn new StdRoom();\n\t}\n\n\t@Override\n\tpublic String roomID()\n\t{\n\t\treturn _roomID\t;\n\t}\n\n\t@Override\n\tpublic String Name()\n\t{\n\t\treturn name;\n\t}\n\n\t@Override\n\tpublic void setName(final String newName)\n\t{\n\t\tname=newName;\n\t}\n\n\t@Override\n\tpublic String name()\n\t{\n\t\tif(phyStats().newName()!=null)\n\t\t\treturn phyStats().newName();\n\t\treturn name;\n\t}\n\n\t@Override\n\tpublic String name(final MOB viewerMob)\n\t{\n\t\treturn name();\n\t}\n\n\t@Override\n\tpublic String genericName()\n\t{\n\t\tfinal String domainName;\n\t\tif((domainType()&Room.INDOORS)==0)\n\t\t\tdomainName=CMLib.english().startWithAorAn(Room.DOMAIN_OUTDOOR_DESCS[domainType()].toLowerCase());\n\t\telse\n\t\t\tdomainName=CMLib.english().startWithAorAn(Room.DOMAIN_INDOORS_DESCS[CMath.unsetb(domainType(),Room.INDOORS)].toLowerCase());\n\t\treturn L("@x1 place",domainName);\n\n\t}\n\n\tprotected void setMovementCost(final int newCost)\n\t{\n\t\tbasePhyStats().setWeight(newCost); // movement consumption\n\t\trecoverPhyStats();\n\t}\n\n\tprotected int getMovementCost()\n\t{\n\t\treturn phyStats().weight(); // movement consumption\n\t}\n\n\tprotected void setRoomSize(final int newSize)\n\t{\n\t\tbasePhyStats().setHeight(newSize);\n\t\trecoverPhyStats();\n\t}\n\n\tprotected int getRoomSize()\n\t{\n\t\treturn phyStats().height();\n\t}\n\n\t@Override\n\tpublic int getAtmosphereCode()\n\t{\n\t\treturn atmosphere;\n\t}\n\n\t@Override\n\tpublic void setAtmosphere(final int resourceCode)\n\t{\n\t\tatmosphere=resourceCode;\n\t}\n\n\t@Override\n\tpublic int getAtmosphere()\n\t{\n\t\tif(getGridParent()!=null)\n\t\t\treturn getGridParent().getAtmosphere();\n\t\telse\n\t\tif(getAtmosphereCode()!=ATMOSPHERE_INHERIT)\n\t\t\treturn getAtmosphereCode();\n\t\telse\n\t\t\treturn (myArea==null)?RawMaterial.RESOURCE_AIR:myArea.getAtmosphere();\n\t}\n\n\t@Override\n\tpublic String image()\n\t{\n\t\tif(cachedImageName==null)\n\t\t{\n\t\t\tif((rawImageName!=null)&&(rawImageName.length()>0))\n\t\t\t\tcachedImageName=rawImageName;\n\t\t\telse\n\t\t\t\tcachedImageName=CMLib.protocol().getDefaultMXPImage(this);\n\t\t}\n\t\treturn cachedImageName;\n\t}\n\n\t@Override\n\tpublic String rawImage()\n\t{\n\t\tif(rawImageName==null)\n\t\t\treturn "";\n\t\treturn rawImageName;\n\t}\n\n\t@Override\n\tpublic void setImage(final String newImage)\n\t{\n\t\tif((newImage==null)||(newImage.trim().length()==0))\n\t\t\trawImageName=null;\n\t\telse\n\t\t\trawImageName=newImage;\n\t\tif((cachedImageName!=null)&&(!cachedImageName.equals(newImage)))\n\t\t\tcachedImageName=null;\n\t}\n\n\t@Override\n\tpublic boolean isGeneric()\n\t{\n\t\treturn false;\n\t}\n\n\t@SuppressWarnings("rawtypes")\n\tprotected void cloneFix(final Room R)\n\t{\n\t\tme=this;\n\t\tbasePhyStats=(PhyStats)R.basePhyStats().copyOf();\n\t\tphyStats=(PhyStats)R.phyStats().copyOf();\n\n\t\taffectPhyStats = new ApplyAffectPhyStats(this);\n\n\t\tcontents=new SVector<Item>();\n\t\tinhabitants=new SVector<MOB>();\n\t\taffects=null;\n\t\tbehaviors=null;\n\t\tscripts=null;\n\t\texits=new Exit[exits.length];\n\t\tArrays.fill(exits, null);\n\t\tdoors=new Room[doors.length];\n\t\tArrays.fill(doors, null);\n\t\tfor(int d=R.rawDoors().length-1;d>=0;d--)\n\t\t{\n\t\t\tif(R.getRawExit(d)!=null)\n\t\t\t\texits[d]=(Exit)R.getRawExit(d).copyOf();\n\t\t\tif(R.rawDoors()[d]!=null)\n\t\t\t\tdoors[d]=R.rawDoors()[d];\n\t\t}\n\t\tfor(int i=0;i<R.numItems();i++)\n\t\t{\n\t\t\tfinal Item I2=R.getItem(i);\n\t\t\tif(I2!=null)\n\t\t\t{\n\t\t\t\tfinal Item I=(Item)I2.copyOf();\n\t\t\t\tI.setOwner(this);\n\t\t\t\tcontents.addElement(I);\n\t\t\t}\n\t\t}\n\t\tfor(int i=0;i<numItems();i++)\n\t\t{\n\t\t\tfinal Item I2=getItem(i);\n\t\t\tif((I2!=null)\n\t\t\t&&(I2.container()!=null)\n\t\t\t&&(!isContent(I2.container())))\n\t\t\t{\n\t\t\t\tfor(int ii=0;ii<R.numItems();ii++)\n\t\t\t\t{\n\t\t\t\t\tif((R.getItem(ii)==I2.container())&&(ii<numItems()))\n\t\t\t\t\t{\n\t\t\t\t\t\tI2.setContainer((Container)getItem(ii));\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor(final Enumeration<MOB> m=R.inhabitants();m.hasMoreElements();)\n\t\t{\n\t\t\tfinal MOB M2=m.nextElement();\n\t\t\tif(M2.isSavable())\n\t\t\t{\n\t\t\t\tfinal MOB M=(MOB)M2.copyOf();\n\t\t\t\tif(M.getStartRoom()==R)\n\t\t\t\t\tM.setStartRoom(this);\n\t\t\t\tM.setLocation(this);\n\t\t\t\tinhabitants.addElement(M);\n\t\t\t}\n\t\t}\n\t\tfor(final Enumeration<Ability> a=R.effects();a.hasMoreElements();)\n\t\t{\n\t\t\tfinal Ability A=a.nextElement();\n\t\t\tif(!A.canBeUninvoked())\n\t\t\t\taddEffect((Ability)A.copyOf());\n\t\t}\n\t\tfor(final Enumeration<Behavior> e=R.behaviors();e.hasMoreElements();)\n\t\t{\n\t\t\tfinal Behavior B=e.nextElement();\n\t\t\taddBehavior((Behavior)B.copyOf());\n\t\t}\n\t\tfor(final Enumeration<ScriptingEngine> e=R.scripts();e.hasMoreElements();)\n\t\t{\n\t\t\tfinal ScriptingEngine SE=e.nextElement();\n\t\t\taddScript((ScriptingEngine)SE.copyOf());\n\t\t}\n\t}\n\n\t@Override\n\tpublic CMObject copyOf()\n\t{\n\t\ttry\n\t\t{\n\t\t\tfinal StdRoom R=(StdRoom)this.clone();\n\t\t\t//CMClass.bumpCounter(R,CMClass.CMObjectType.LOCALE);//removed for mem & perf\n\t\t\tR.xtraValues=(xtraValues==null)?null:(String[])xtraValues.clone();\n\t\t\tR.cloneFix(this);\n\t\t\treturn R;\n\n\t\t}\n\t\tcatch(final CloneNotSupportedException e)\n\t\t{\n\t\t\treturn this.newInstance();\n\t\t}\n\t}\n\n\t@Override\n\tpublic int domainType()\n\t{\n\t\treturn Room.DOMAIN_OUTDOORS_CITY;\n\t}\n\n\t@Override\n\tpublic int getClimateTypeCode()\n\t{\n\t\treturn climask;\n\t}\n\n\t@Override\n\tpublic void setClimateType(final int climask)\n\t{\n\t\tthis.climask=climask;\n\t}\n\n\t@Override\n\tpublic int getClimateType()\n\t{\n\t\tif(getGridParent()!=null)\n\t\t\treturn getGridParent().getClimateType();\n\t\telse\n\t\tif(getClimateTypeCode()!=CLIMASK_INHERIT)\n\t\t\treturn getClimateTypeCode();\n\t\telse\n\t\t\treturn (myArea==null)?CLIMASK_NORMAL:myArea.getClimateType();\n\t}\n\n\t@Override\n\tpublic long expirationDate()\n\t{\n\t\treturn expirationDate;\n\t}\n\n\t@Override\n\tpublic void setExpirationDate(final long time)\n\t{\n\t\texpirationDate=time;\n\t}\n\n\t@Override\n\tpublic void setRawExit(final int direction, final Exit to)\n\t{\n\t\tif((direction<0)||(direction>=exits.length))\n\t\t\treturn;\n\t\tfinal Exit E=exits[direction];\n\t\tif(E==to)\n\t\t\treturn;\n\t\tif(E!=null)\n\t\t\tE.exitUsage((short)-1);\n\t\tif(to !=null )\n\t\t{\n\t\t\tto.exitUsage((short)1);\n\t\t\texits[direction]=to;\n\t\t}\n\t\telse\n\t\t\texits[direction]=null;\n\n\t\t/**\n\t\t * cant be done\n\t\t *\n\t\tif((E!=null)&&(E.exitUsage((short)0)==0))\n\t\t\tE.destroy();\n\t\t */\n\t}\n\n\t@Override\n\tpublic String displayText()\n\t{\n\t\treturn displayText;\n\t}\n\n\t@Override\n\tpublic void setDisplayText(final String newDisplayText)\n\t{\n\t\tdisplayText=newDisplayText;\n\t}\n\n\t@Override\n\tpublic String description()\n\t{\n\t\tif(description == null)\n\t\t{\n\t\t\tif(CMProps.getBoolVar(CMProps.Bool.ROOMDNOCACHE)&&(roomID().trim().length()>0))\n\t\t\t{\n\t\t\t\tfinal String txt=CMLib.database().DBReadRoomDesc(roomID());\n\t\t\t\tif(txt==null)\n\t\t\t\t{\n\t\t\t\t\tLog.errOut("Unable to recover description for "+roomID()+".");\n\t\t\t\t\treturn "";\n\t\t\t\t}\n\t\t\t\treturn txt;\n\t\t\t}\n\t\t\treturn "";\n\t\t}\n\t\telse\n\t\tif(description instanceof byte[])\n\t\t{\n\t\t\tfinal byte[] descriptionBytes=(byte[])description;\n\t\t\tif(CMProps.getBoolVar(CMProps.Bool.ROOMDCOMPRESS))\n\t\t\t\treturn CMLib.encoder().decompressString(descriptionBytes);\n\t\t\treturn CMStrings.bytesToStr(descriptionBytes);\n\t\t}\n\t\telse\n\t\t\treturn ((String)description);\n\t}\n\n\t@Override\n\tpublic void setDescription(final String newDescription)\n\t{\n\t\tif(newDescription.length()==0)\n\t\t\tdescription=null;\n\t\telse\n\t\tif(CMProps.getBoolVar(CMProps.Bool.ROOMDCOMPRESS))\n\t\t\tdescription=CMLib.encoder().compressString(newDescription);\n\t\telse\n\t\t\tdescription=newDescription;\n\t}\n\n\t@Override\n\tpublic String text()\n\t{\n\t\treturn CMLib.coffeeMaker().getEnvironmentalMiscTextXML(this,true);\n\t}\n\n\t@Override\n\tpublic String miscTextFormat()\n\t{\n\t\treturn CMParms.FORMAT_UNDEFINED;\n\t}\n\n\t@Override\n\tpublic void setMiscText(final String newMiscText)\n\t{\n\t\tif(newMiscText.trim().length()>0)\n\t\t\tCMLib.coffeeMaker().unpackEnvironmentalMiscTextXML(this,newMiscText,true);\n\t}\n\n\t@Override\n\tpublic void setRoomID(final String newID)\n\t{\n\t\tif((_roomID!=null)&&(!_roomID.equals(newID)))\n\t\t{\n\t\t\t_roomID=newID;\n\t\t\tif(myArea!=null)\n\t\t\t{\n\t\t\t\t// force the re-sort\n\t\t\t\tmyArea.delProperRoom(this);\n\t\t\t\tmyArea.addProperRoom(this);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t\t_roomID=newID;\n\t}\n\n\t@Override\n\tpublic Area getArea()\n\t{\n\t\tif(myArea==null)\n\t\t\treturn CMClass.randomArea();\n\t\treturn myArea;\n\t}\n\n\t@Override\n\tpublic void setArea(final Area newArea)\n\t{\n\t\tif(newArea!=myArea)\n\t\t{\n\t\t\tif(myArea!=null)\n\t\t\t\tmyArea.delProperRoom(this);\n\t\t\tmyArea=newArea;\n\t\t\tif(myArea!=null)\n\t\t\t\tmyArea.addProperRoom(this);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setGridParent(final GridLocale room)\n\t{\n\t\tgridParent=room;\n\t}\n\n\t@Override\n\tpublic GridLocale getGridParent()\n\t{\n\t\treturn gridParent;\n\t}\n\n\t@Override\n\tpublic void giveASky(final int depth)\n\t{\n\t\tif(skyedYet)\n\t\t\treturn;\n\t\tif(depth>1000)\n\t\t\treturn;\n\n\t\tfinal Area A=getArea();\n\t\tif(A==null)\n\t\t\treturn;\n\t\tskyedYet=true;\n\t\tif((roomID().length()==0)\n\t\t&&(getGridParent()!=null)\n\t\t&&(getGridParent().roomID().length()==0))\n\t\t\treturn;\n\n\t\tif((rawDoors()[Directions.UP]==null)\n\t\t&&((domainType()&Room.INDOORS)==0)\n\t\t&&(domainType()!=Room.DOMAIN_OUTDOORS_UNDERWATER)\n\t\t&&(domainType()!=Room.DOMAIN_OUTDOORS_AIR)\n\t\t&&(CMProps.getIntVar(CMProps.Int.SKYSIZE)!=0))\n\t\t{\n\t\t\tExit upE=null;\n\t\t\tfinal Exit dnE=CMClass.getExit("StdOpenDoorway");\n\t\t\tif(CMProps.getIntVar(CMProps.Int.SKYSIZE)>0)\n\t\t\t\tupE=dnE;\n\t\t\telse\n\t\t\t\tupE=CMClass.getExit("UnseenWalkway");\n\n\t\t\tfinal GridLocale sky=(GridLocale)CMClass.getLocale("EndlessThinSky");\n\t\t\tsky.setRoomID("");\n\t\t\tsky.setArea(getArea());\n\t\t\trawDoors()[Directions.UP]=sky;\n\t\t\tsetRawExit(Directions.UP,upE);\n\t\t\tsky.rawDoors()[Directions.DOWN]=this;\n\t\t\tsky.setRawExit(Directions.DOWN,dnE);\n\n\t\t\tif(!(getArea() instanceof Boardable))\n\t\t\t{\n\t\t\t\tfor(int d=rawDoors().length-1;d>=0;d--)\n\t\t\t\t{\n\t\t\t\t\tif((d!=Directions.UP)\n\t\t\t\t\t&&(d!=Directions.DOWN))\n\t\t\t\t\t{\n\t\t\t\t\t\tRoom thatRoom=rawDoors()[d];\n\t\t\t\t\t\tif((thatRoom!=null)&&(getRawExit(d)!=null))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tthatRoom=CMLib.map().getRoom(thatRoom);\n\t\t\t\t\t\t\tif(thatRoom != null)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tthatRoom.giveASky(depth+1);\n\t\t\t\t\t\t\t\tfinal Room thatSky=thatRoom.rawDoors()[Directions.UP];\n\t\t\t\t\t\t\t\tif((thatSky!=null)\n\t\t\t\t\t\t\t\t&&(thatSky.roomID().length()==0)\n\t\t\t\t\t\t\t\t&&((thatSky instanceof EndlessThinSky)||(thatSky instanceof EndlessSky)))\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tExit xo=getRawExit(d);\n\t\t\t\t\t\t\t\t\tif(xo!=null)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tif(xo.hasADoor())\n\t\t\t\t\t\t\t\t\t\t\txo=dnE;\n\t\t\t\t\t\t\t\t\t\tsky.rawDoors()[d]=thatSky;\n\t\t\t\t\t\t\t\t\t\tsky.setRawExit(d,xo);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tfinal int opDir=Directions.getOpDirectionCode(d);\n\t\t\t\t\t\t\t\t\txo=thatRoom.getRawExit(opDir);\n\t\t\t\t\t\t\t\t\tif(xo!=null)\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tif(xo.hasADoor())\n\t\t\t\t\t\t\t\t\t\t\txo=dnE;\n\t\t\t\t\t\t\t\t\t\tthatSky.rawDoors()[opDir]=sky;\n\t\t\t\t\t\t\t\t\t\tthatSky.setRawExit(opDir,xo);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t((GridLocale)thatSky).clearGrid(null);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tsky.clearGrid(null);\n\t\t}\n\t}\n\n\t@Override\n\tpublic List<Room> getSky()\n\t{\n\t\tfinal List<Room> skys = new Vector<Room>(1);\n\t\tif(!skyedYet)\n\t\t\treturn skys;\n\t\tfinal Room skyGridRoom=rawDoors()[Directions.UP];\n\t\tif(skyGridRoom!=null)\n\t\t{\n\t\t\tif(((skyGridRoom.roomID()==null)||(skyGridRoom.roomID().length()==0))\n\t\t\t&&((skyGridRoom instanceof EndlessSky)||(skyGridRoom instanceof EndlessThinSky)))\n\t\t\t\tskys.add(skyGridRoom);\n\t\t}\n\t\treturn skys;\n\t}\n\n\t@Override\n\tpublic void clearSky()\n\t{\n\t\tif(!skyedYet)\n\t\t\treturn;\n\t\tfinal Room skyGridRoom=rawDoors()[Directions.UP];\n\t\tif(skyGridRoom!=null)\n\t\t{\n\t\t\tif(((skyGridRoom.roomID()==null)||(skyGridRoom.roomID().length()==0))\n\t\t\t&&((skyGridRoom instanceof EndlessSky)||(skyGridRoom instanceof EndlessThinSky)))\n\t\t\t{\n\t\t\t\t((GridLocale)skyGridRoom).clearGrid(null);\n\t\t\t\trawDoors()[Directions.UP]=null;\n\t\t\t\tsetRawExit(Directions.UP,null);\n\t\t\t\tfor(int d=0;d<skyGridRoom.rawDoors().length;d++)\n\t\t\t\t{\n\t\t\t\t\tfinal Room thatSky=skyGridRoom.rawDoors()[d];\n\t\t\t\t\tfinal int opDir=Directions.getOpDirectionCode(d);\n\t\t\t\t\tif((thatSky!=null)&&(thatSky.rawDoors()[opDir]==skyGridRoom))\n\t\t\t\t\t{\n\t\t\t\t\t\tthatSky.rawDoors()[opDir]=null;\n\t\t\t\t\t\tthatSky.setRawExit(opDir, null);\n\t\t\t\t\t}\n\t\t\t\t\tskyGridRoom.rawDoors()[d]=null;\n\t\t\t\t\tskyGridRoom.setRawExit(d,null);\n\t\t\t\t}\n\t\t\t\tCMLib.map().emptyRoom(skyGridRoom,null,true);\n\t\t\t\tskyGridRoom.destroy();\n\t\t\t\tskyedYet=false;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t\tskyedYet=false;\n\t}\n\n\t@Override\n\tpublic List<Integer> resourceChoices()\n\t{\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void setResource(final int resourceCode)\n\t{\n\t\tmyResource=resourceCode;\n\t\tlastResourceTime= (resourceCode>=0) ? lastResourceTime=System.currentTimeMillis() : 0;\n\t}\n\n\t@Override\n\tpublic int myResource()\n\t{\n\t\tif(lastResourceTime!=0)\n\t\t{\n\t\t\tif(lastResourceTime<(System.currentTimeMillis()-(30*TimeManager.MILI_MINUTE)))\n\t\t\t\tsetResource(-1);\n\t\t}\n\t\tif(myResource<0)\n\t\t{\n\t\t\tif(resourceChoices()==null)\n\t\t\t\tsetResource(-1);\n\t\t\telse\n\t\t\t{\n\t\t\t\tfinal List<Integer> preferredChoices=new ArrayList<Integer>();\n\t\t\t\tfor(int d=0;d<Directions.NUM_DIRECTIONS();d++)\n\t\t\t\t{\n\t\t\t\t\tfinal Room R=rawDoors()[d];\n\t\t\t\t\tif((R!=null)\n\t\t\t\t\t&&(R.ID().equals(ID()))\n\t\t\t\t\t&&(R.resourceChoices()==resourceChoices())\n\t\t\t\t\t&&(R instanceof StdRoom)\n\t\t\t\t\tgridParent.executeMsg(myHost,msg);\r\n\t\t\t\telse\r\n\t\t\t\tif((roomID().length()>0)\r\n\t\t\t\t&&(CMSecurity.isSaveFlag("ROOMMOBS")\r\n\t\t\t\t\t||CMSecurity.isSaveFlag("ROOMITEMS")\r\n\t\t\t\t\t||CMSecurity.isSaveFlag("ROOMSHOPS")))\r\n\t\t\t\t\t{\n\t\t\t\t\t\tmyResource = choice.intValue();\n\t\t\t\t\t\treturn myResource;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tint totalChance=0;\n\t\t\t\tfor(int i=0;i<resourceChoices().size();i++)\n\t\t\t\t{\n\t\t\t\t\tfinal int resource=resourceChoices().get(i).intValue();\n\t\t\t\t\ttotalChance+=RawMaterial.CODES.FREQUENCY(resource);\n\t\t\t\t}\n\t\t\t\tsetResource(-1);\n\t\t\t\tfinal int theRoll=CMLib.dice().roll(1,totalChance,0);\n\t\t\t\ttotalChance=0;\n\t\t\t\tfor(int i=0;i<resourceChoices().size();i++)\n\t\t\t\t{\n\t\t\t\t\tfinal int resource=resourceChoices().get(i).intValue();\n\t\t\t\t\ttotalChance+=RawMaterial.CODES.FREQUENCY(resource);\n\t\t\t\t\tif(theRoll<=totalChance)\n\t\t\t\t\t{\n\t\t\t\t\t\tsetResource(resource);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn myResource;\n\t}\n\n\t@Override\n\tpublic void toggleMobility(final boolean onoff)\n\t{\n\t\tmobility=onoff;\n\t}\n\n\t@Override\n\tpublic boolean getMobility()\n\t{\n\t\treturn mobility;\n\t}\n\n\t@Override\n\tpublic boolean okMessage(final Environmental myHost, final CMMsg msg)\n\t{\n\t\tif(!getArea().okMessage(this,msg))\n\t\t\treturn false;\n\n\t\tif(msg.amITarget(this))\n\t\t{\n\t\t\tfinal MOB mob=msg.source();\n\t\t\tswitch(msg.targetMinor())\n\t\t\t{\n\t\t\tcase CMMsg.TYP_EXPIRE:\n\t\t\t{\n\t\t\t\tif((gridParent!=null)&&(!gridParent.okMessage(myHost,msg)))\n\t\t\t\t\treturn false;\n\t\t\t\tif(!CMLib.map().isClearableRoom(this))\n\t\t\t\t\treturn false;\n\t\t\t\tfor(int d=Directions.NUM_DIRECTIONS()-1;d>=0;d--)\n\t\t\t\t{\n\t\t\t\t\tfinal Room R2=rawDoors()[d];\n\t\t\t\t\tif((R2!=null)&&(!CMLib.map().isClearableRoom(R2)))\n\t\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase CMMsg.TYP_LEAVE:\n\t\t\t\tif((!CMLib.flags().allowsMovement(this))||(!getMobility()))\n\t\t\t\t\treturn false;\n\t\t\t\tbreak;\n\t\t\tcase CMMsg.TYP_FLEE:\n\t\t\tcase CMMsg.TYP_ENTER:\n\t\t\t\tif((!CMLib.flags().allowsMovement(this))||(!getMobility()))\n\t\t\t\t\treturn false;\n\t\t\t\tif(!mob.isMonster())\n\t\t\t\t{\n\t\t\t\t\tfinal Room R=mob.location();\n\t\t\t\t\tif((R!=null)&&(R.getArea()!=getArea()))\n\t\t\t\t\t{\n\t\t\t\t\t\tCMLib.factions().updatePlayerFactions(mob,this,false);\n\t\t\t\t\t\tCMLib.achievements().possiblyBumpAchievement(mob, Event.AREAVISIT, 1, new Object[] {getArea(), this});\n\t\t\t\t\t}\n\t\t\t\t\tgiveASky(0);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase CMMsg.TYP_AREAAFFECT:\n\t\t\t\t// obsolete with the area objects\n\t\t\t\tbreak;\n\t\t\tcase CMMsg.TYP_CAST_SPELL:\n\t\t\tcase CMMsg.TYP_DELICATE_HANDS_ACT:\n\t\t\tcase CMMsg.TYP_NOISYMOVEMENT:\n\t\t\tcase CMMsg.TYP_OK_ACTION:\n\t\t\tcase CMMsg.TYP_JUSTICE:\n\t\t\tcase CMMsg.TYP_OK_VISUAL:\n\t\t\tcase CMMsg.TYP_SNIFF:\n\t\t\t\tbreak;\n\t\t\tcase CMMsg.TYP_LIST:\n\t\t\tcase CMMsg.TYP_BUY:\n\t\t\tcase CMMsg.TYP_BID:\n\t\t\tcase CMMsg.TYP_SELL:\n\t\t\tcase CMMsg.TYP_VIEW:\n\t\t\tcase CMMsg.TYP_VALUE:\n\t\t\t\tif(CMLib.coffeeShops().getShopKeeper(this)==null)\n\t\t\t\t{\n\t\t\t\t\tmob.tell(L("You can\'t shop here."));\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase CMMsg.TYP_SPEAK:\n\t\t\t\tbreak;\n\t\t\tcase CMMsg.TYP_DIG:\n\t\t\t\tif(CMLib.map().getExtendedRoomID(this).length()==0)\n\t\t\t\t{\n\t\t\t\t\tmob.tell(L("You can\'t really dig here."));\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tswitch(this.domainType())\n\t\t\t\t{\n\t\t\t\tcase Room.DOMAIN_OUTDOORS_DESERT:\n\t\t\t\tcase Room.DOMAIN_OUTDOORS_HILLS:\n\t\t\t\tcase Room.DOMAIN_OUTDOORS_JUNGLE:\n\t\t\t\tcase Room.DOMAIN_OUTDOORS_PLAINS:\n\t\t\t\tcase Room.DOMAIN_OUTDOORS_SWAMP:\n\t\t\t\tcase Room.DOMAIN_OUTDOORS_WOODS:\n\t\t\t\t\tbreak;\n\t\t\t\tcase Room.DOMAIN_OUTDOORS_WATERSURFACE:\n\t\t\t\tcase Room.DOMAIN_OUTDOORS_UNDERWATER:\n\t\t\t\t{\n\t\t\t\t\tif(getRoomInDir(Directions.DOWN)==null)\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\t//$FALL-THROUGH$\n\t\t\t\tdefault:\n\t\t\t\t\tmob.tell(L("You can\'t really dig here."));\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tif(((msg.targetMajor(CMMsg.MASK_HANDS))||(msg.targetMajor(CMMsg.MASK_MOUTH)))\n\t\t\t\t&&(!CMath.bset(msg.targetMajor(), CMMsg.MASK_MAGIC))\n\t\t\t\t&&(!(msg.tool() instanceof Ability))\n\t\t\t\t&&(msg.targetMinor()!=CMMsg.TYP_THROW)\n\t\t\t\t&&(isInhabitant(msg.source())))\n\t\t\t\t{\n\t\t\t\t\tmob.tell(L("You can\'t do that here."));\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif(isInhabitant(msg.source()))\n\t\t{\n\t\t\tif(!msg.source().okMessage(this,msg))\n\t\t\t\treturn false;\n\t\t}\n\t\tfor(final Enumeration<MOB> m=inhabitants();m.hasMoreElements();)\n\t\t{\n\t\t\tfinal MOB M=m.nextElement();\n\t\t\tif((M!=msg.source())\n\t\t\t&&(!M.okMessage(this,msg)))\n\t\t\t\treturn false;\n\t\t}\n\t\tfor(final Enumeration<Item> i=items();i.hasMoreElements();)\n\t\t{\n\t\t\tfinal Item I=i.nextElement();\n\t\t\tif(!I.okMessage(this,msg))\n\t\t\t\treturn false;\n\t\t}\n\t\tfor(final Enumeration<Ability> a=effects();a.hasMoreElements();)\n\t\t{\n\t\t\tfinal Ability A=a.nextElement();\n\t\t\tif(!A.okMessage(this,msg))\n\t\t\t\treturn false;\n\t\t}\n\t\tfor(final Enumeration<Behavior> b=behaviors();b.hasMoreElements();)\n\t\t{\n\t\t\tfinal Behavior B=b.nextElement();\n\t\t\tif(!B.okMessage(this,msg))\n\t\t\t\treturn false;\n\t\t}\n\t\tfor(final Enumeration<ScriptingEngine> s=scripts();s.hasMoreElements();)\n\t\t{\n\t\t\tfinal ScriptingEngine S=s.nextElement();\n\t\t\tif(!S.okMessage(this,msg))\n\t\t\t\treturn false;\n\t\t}\n\n\t\tfor(int d=Directions.NUM_DIRECTIONS()-1;d>=0;d--)\n\t\t{\n\t\t\tfinal Exit thisExit=getRawExit(d);\n\t\t\tif(thisExit!=null)\n\t\t\t{\n\t\t\t\tif(!thisExit.okMessage(this,msg))\n\t\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic void executeMsg(final Environmental myHost, final CMMsg msg)\n\t{\n\t\tgetArea().executeMsg(this,msg);\n\n\t\tif(msg.amITarget(this))\n\t\t{\n\t\t\tfinal MOB mob=msg.source();\n\t\t\tswitch(msg.targetMinor())\n\t\t\t{\n\t\t\tcase CMMsg.TYP_LEAVE:\n\t\t\t{\n\t\t\t\tif(!CMath.bset(msg.targetMajor(),CMMsg.MASK_OPTIMIZE))\n\t\t\t\t\trecoverRoomStats();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase CMMsg.TYP_FLEE:\n\t\t\t{\n\t\t\t\tif(!CMath.bset(msg.targetMajor(),CMMsg.MASK_OPTIMIZE))\n\t\t\t\t\trecoverRoomStats();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase CMMsg.TYP_ENTER:\n\t\t\tcase CMMsg.TYP_RECALL:\n\t\t\t{\n\t\t\t\tif(!CMath.bset(msg.targetMajor(),CMMsg.MASK_OPTIMIZE))\n\t\t\t\t\trecoverRoomStats();\n\t\t\t\tif((msg.source().playerStats()!=null)\n\t\t\t\t&&(msg.source().soulMate()==null))\n\t\t\t\t{\n\t\t\t\t\tif(msg.source().playerStats().addRoomVisit(this))\n\t\t\t\t\t\tCMLib.players().bumpPrideStat(msg.source(),AccountStats.PrideStat.ROOMS_EXPLORED, 1);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase CMMsg.TYP_LOOK_EXITS:\n\t\t\t\tif(msg.value()==CMMsg.MASK_OPTIMIZE)\n\t\t\t\t\tCMLib.commands().lookAtExitsShort(this, msg.source());\n\t\t\t\telse\n\t\t\t\t\tCMLib.commands().lookAtExits(this, msg.source());\n\t\t\t\tbreak;\n\t\t\tcase CMMsg.TYP_LOOK:\n\t\t\tcase CMMsg.TYP_EXAMINE:\n\t\t\t\tCMLib.commands().handleBeingLookedAt(msg);\n\t\t\t\tbreak;\n\t\t\tcase CMMsg.TYP_SNIFF:\n\t\t\t\tCMLib.commands().handleBeingSniffed(msg);\n\t\t\t\tbreak;\n\t\t\tcase CMMsg.TYP_READ:\n\t\t\t\tif(CMLib.flags().canBeSeenBy(this,mob))\n\t\t\t\t\tmob.tell(L("There is nothing written here."));\n\t\t\t\telse\n\t\t\t\t\tmob.tell(L("You can\'t see that!"));\n\t\t\t\tbreak;\n\t\t\tcase CMMsg.TYP_AREAAFFECT:\n\t\t\t\t// obsolete with the area objects\n\t\t\t\tbreak;\n\t\t\tcase CMMsg.TYP_DIG:\n\t\t\t\tif(findItem("HoleInTheGround")==null)\n\t\t\t\t\taddItem(CMClass.getBasicItem("HoleInTheGround"));\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif((msg.othersMinor() == CMMsg.TYP_GRAVITY)\n\t\t&&(msg.targetMinor() == CMMsg.NO_EFFECT)\n\t\t&&(numInhabitants()>0))\n\t\t{\n\t\t\tfinal CMMsg gmsg = (CMMsg)msg.copyOf();\n\t\t\tgmsg.setTargetCode(msg.othersCode());\n\t\t\tgmsg.setOthersCode(CMMsg.NO_EFFECT);\n\t\t\tfinal Room me=this;\n\t\t\teachInhabitant(new EachApplicable<MOB>()\n\t\t\t{\n\t\t\t\tfinal Room R=me;\n\t\t\t\t@Override\n\t\t\t\tpublic void apply(final MOB M)\n\t\t\t\t{\n\t\t\t\t\tgmsg.setTarget(M);\n\t\t\t\t\tif(R.okMessage(M, gmsg))\n\t\t\t\t\t\tR.send(M, gmsg);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tif(numItems()>0)\n\t\t{\n\t\t\teachItem(new EachApplicable<Item>()\n\t\t\t{\n\t\t\t\t@Override\n\t\t\t\tpublic final void apply(final Item I)\n\t\t\t\t{\n\t\t\t\t\tI.executeMsg(me, msg);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tfor(int d=Directions.NUM_DIRECTIONS()-1;d>=0;d--)\n\t\t{\n\t\t\tfinal Exit E=getRawExit(d);\n\t\t\tif(E!=null)\n\t\t\t\tE.executeMsg(this,msg);\n\t\t}\n\n\t\tif(numBehaviors()>0)\n\t\t{\n\t\t\teachBehavior(new EachApplicable<Behavior>()\n\t\t\t{\n\t\t\t\t@Override\n\t\t\t\tpublic final void apply(final Behavior B)\n\t\t\t\t{\n\t\t\t\t\tB.executeMsg(me, msg);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\tif(numScripts()>0)\n\t\t{\n\t\t\teachScript(new EachApplicable<ScriptingEngine>()\n\t\t\t{\n\t\t\t\t@Override\n\t\t\t\tpublic final void apply(final ScriptingEngine S)\n\t\t\t\t{\n\t\t\t\t\tS.executeMsg(me, msg);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\tif(numEffects()>0)\n\t\t{\n\t\t\teachEffect(new EachApplicable<Ability>()\n\t\t\t{\n\t\t\t\t@Override\n\t\t\t\tpublic final void apply(final Ability A)\n\t\t\t\t{\n\t\t\t\t\tA.executeMsg(me,msg);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tif(msg.sourceMinor()==CMMsg.TYP_SHUTDOWN)\n\t\t{\n\t\t\ttry\n\t\t\t{\n\t\t\t\tif(CMSecurity.isSaveFlag(CMSecurity.SaveFlag.ROOMMOBS))\n\t\t\t\t{\n\t\t\t\t\tif(roomID().length()==0)\n\t\t\t\t\t{\n\t\t\t\t\t\teachInhabitant(new EachApplicable<MOB>()\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t@Override\n\t\t\t\t\t\t\tpublic final void apply(final MOB M)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif((M.isSavable())\n\t\t\t\t\t\t\t\t&&(M.getStartRoom()!=me)\n\t\t\t\t\t\t\t\t&&(M.getStartRoom()!=null)\n\t\t\t\t\t\t\t\t&&(M.getStartRoom().roomID().length()>0))\n\t\t\t\t\t\t\t\t\tM.getStartRoom().bringMobHere(M,false);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\tif(CMSecurity.isSaveFlag(CMSecurity.SaveFlag.ROOMSHOPS))\n\t\t\t\t{\n\t\t\t\t\teachInhabitant(new EachApplicable<MOB>()\n\t\t\t\t\t{\n\t\t\t\t\t\t@Override\n\t\t\t\t\t\tpublic final void apply(final MOB M)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif((M instanceof ShopKeeper)\n\t\t\t\t\t\t\t&&(M.isSavable())\n\t\t\t\t\t\t\t&&(M.getStartRoom()!=me)\n\t\t\t\t\t\t\t&&(M.getStartRoom()!=null))\n\t\t\t\t\t\t\t\tM.getStartRoom().bringMobHere(M,false);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch(final NoSuchElementException e)\n\t\t\t{\n\t\t\t}\n\t\t}\n\n\t\tif(msg.amITarget(this)&&(msg.targetMinor()==CMMsg.TYP_EXPIRE))\n\t\t{\n\t\t\tsynchronized(CMClass.getSync(("SYNC"+roomID())))\n\t\t\t{\n\t\t\t\tfinal LinkedList<DeadBody> deadBodies=new LinkedList<DeadBody>();\n\t\t\t\teachItem(new EachApplicable<Item>()\n\t\t\t\t{\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic final void apply(final Item I)\n\t\t\t\t\t{\n\t\t\t\t\t\tif((I instanceof DeadBody)\n\t\t\t\t\t\t&&(((DeadBody)I).isPlayerCorpse()))\n\t\t\t\t\t\t\tdeadBodies.add((DeadBody)I);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tfor(final DeadBody D : deadBodies)\n\t\t\t\t{\n\t\t\t\t\tMOB M=CMLib.players().getLoadPlayer(D.getMobName());\n\t\t\t\t\tif(M==null)\n\t\t\t\t\t\tM=D.getSavedMOB();\n\t\t\t\t\tif((M!=null)&&(M.getStartRoom()!=null))\n\t\t\t\t\t{\n\t\t\t\t\t\tfinal Room startRoom=CMLib.map().getRoom(M.getStartRoom());\n\t\t\t\t\t\tM.tell(L("Your corpse has been moved to @x1",startRoom.displayText()));\n\t\t\t\t\t\tstartRoom.moveItemTo(D);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(gridParent!=null)\n\t\t\t\t\tgridParent.executeMsg(myHost,msg);\n\t\t\t\telse\n\t\t\t\tif((roomID().length()>0)\n\t\t\t\t&&((getArea()==null)||(!CMath.bset(getArea().flags(), Area.FLAG_INSTANCE_CHILD)))\n\t\t\t\t&&(CMSecurity.isSaveFlag(CMSecurity.SaveFlag.ROOMMOBS)\n\t\t\t\t\t||CMSecurity.isSaveFlag(CMSecurity.SaveFlag.ROOMITEMS)\n\t\t\t\t\t||CMSecurity.isSaveFlag(CMSecurity.SaveFlag.ROOMSHOPS)))\n\t\t\t\t{\n\t\t\t\t\tfinal ArrayList<MOB> shopmobs=new ArrayList<MOB>(1);\n\t\t\t\t\tfinal ArrayList<Item> bodies=new ArrayList<Item>(1);\n\t\t\t\t\tif(CMSecurity.isSaveFlag(CMSecurity.SaveFlag.ROOMMOBS))\n\t\t\t\t\t{\n\t\t\t\t\t\teachInhabitant(new EachApplicable<MOB>()\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t@Override\n\t\t\t\t\t\t\tpublic final void apply(final MOB M)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif(M.isSavable())\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tM.setStartRoom(me);\n\t\t\t\t\t\t\t\t\tM.text(); // this permanizes his current state\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t\tCMLib.database().DBUpdateMOBs(this);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\tif(CMSecurity.isSaveFlag(CMSecurity.SaveFlag.ROOMSHOPS))\n\t\t\t\t\t{\n\t\t\t\t\t\teachInhabitant(new EachApplicable<MOB>()\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t@Override\n\t\t\t\t\t\t\tpublic final void apply(final MOB M)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif((M.isSavable())\n\t\t\t\t\t\t\t\t&&(M instanceof ShopKeeper)\n\t\t\t\t\t\t\t\t&&(M.getStartRoom()==me))\n\t\t\t\t\t\t\t\t\tshopmobs.add(M);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif(!shopmobs.isEmpty())\n\t\t\t\t\t\t\tCMLib.database().DBUpdateTheseMOBs(this,shopmobs);\n\t\t\t\t\t}\n\t\t\t\t\tif(CMSecurity.isSaveFlag(CMSecurity.SaveFlag.ROOMITEMS))\n\t\t\t\t\t{\n\t\t\t\t\t\teachItem(new EachApplicable<Item>()\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t@Override public final void apply(final Item I)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tif(I instanceof DeadBody)\n\t\t\t\t\t\t\t\t\tbodies.add(I);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t\tfor(int i=0;i<bodies.size();i++)\n\t\t\t\t\t\t\tbodies.get(i).destroy();\n\t\t\t\t\t\tCMLib.database().DBUpdateItems(this);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfinal Area A=getArea();\n\t\t\t\tfinal String roomID=roomID();\n\t\t\t\tsetGridParent(null);\n\t\t\t\tif(!CMProps.getBoolVar(CMProps.Bool.MUDSHUTTINGDOWN))\n\t\t\t\t{\n\t\t\t\t\tCMLib.map().emptyRoom(this,null,true);\n\t\t\t\t\tdestroy();\n\t\t\t\t\tif(roomID.length()>0)\n\t\t\t\t\t\tA.addProperRoomnumber(roomID);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void startItemRejuv()\n\t{\n\t\teachItem(new EachApplicable<Item>()\n\t\t{\n\t\t\t@Override\n\t\t\tpublic final void apply(final Item item)\n\t\t\t{\n\t\t\t\tif(item.container()==null)\n\t\t\t\t{\n\t\t\t\t\tfinal ItemTicker I=(ItemTicker)CMClass.getAbility("ItemRejuv");\n\t\t\t\t\tI.unloadIfNecessary(item);\n\t\t\t\t\tif((item.phyStats().rejuv()!=PhyStats.NO_REJUV)\n\t\t\t\t\t&&(item.phyStats().rejuv()>0))\n\t\t\t\t\t\tI.loadMeUp(item,me);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\t@Override\n\tpublic int getTickStatus()\n\t{\n\t\treturn tickStatus;\n\t}\n\n\t@Override\n\tpublic boolean tick(final Tickable ticking, final int tickID)\n\t{\n\t\ttickStatus=Tickable.STATUS_START;\n\t\tif((myArea != null) && (myArea.amDestroyed()))\n\t\t{\n\t\t\tLog.errOut("Destroying "+CMLib.map().getExtendedRoomID(this)+" because of destroyed area.");\n\t\t\tdestroy();\n\t\t\treturn false;\n\t\t}\n\t\tif(tickID==Tickable.TICKID_ROOM_BEHAVIOR)\n\t\t{\n\t\t\tif((numBehaviors()<=0)&&(numScripts()<=0))\n\t\t\t\treturn false;\n\t\t\ttickStatus=Tickable.STATUS_BEHAVIOR;\n\t\t\teachBehavior(new EachApplicable<Behavior>()\n\t\t\t{\n\t\t\t\t@Override\n\t\t\t\tpublic final void apply(final Behavior B)\n\t\t\t\t{\n\t\t\t\t\tB.tick(ticking, tickID);\n\t\t\t\t}\n\t\t\t});\n\t\t\ttickStatus=Tickable.STATUS_SCRIPT;\n\t\t\teachScript(new EachApplicable<ScriptingEngine>()\n\t\t\t{\n\t\t\t\t@Override\n\t\t\t\tpublic final void apply(final ScriptingEngine S)\n\t\t\t\t{\n\t\t\t\t\tS.tick(ticking, tickID);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\telse\n\t\t{\n\t\t\ttickStatus=Tickable.STATUS_AFFECT;\n\t\t\tif(numEffects()>0)\n\t\t\t{\n\t\t\t\teachEffect(new EachApplicable<Ability>()\n\t\t\t\t{\n\t\t\t\t\t@Override\n\t\t\t\t\tpublic final void apply(final Ability A)\n\t\t\t\t\t{\n\t\t\t\t\t\tif(!A.tick(ticking,tickID))\n\t\t\t\t\t\t\tA.unInvoke();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\ttickStatus=Tickable.STATUS_NOT;\n\t\treturn !amDestroyed();\n\t}\n\n\t@Override\n\tpublic PhyStats phyStats()\n\t{\n\t\treturn phyStats;\n\t}\n\n\t@Override\n\tpublic PhyStats basePhyStats()\n\t{\n\t\treturn basePhyStats;\n\t}\n\n\t@SuppressWarnings("unchecked")\n\t@Override\n\tpublic void recoverPhyStats()\n\t{\n\t\tbasePhyStats.copyInto(phyStats);\n\t\tfinal Area myArea=getArea();\n\t\tif(myArea!=null)\n\t\t\tmyArea.affectPhyStats(this,phyStats());\n\n\t\teachEffect(affectPhyStats);\n\t\teachItem(affectPhyStats);\n\t\teachInhabitant(affectPhyStats);\n\t}\n\n\tprivate final static EachApplicable<Item> recoverRoomStatsItemApplicable=new EachApplicable.ApplyRecoverPhyStats<Item>();\n\n\tprivate final static EachApplicable<MOB> recoverRoomStatsInhabitantApplicable=new EachApplicable<MOB>()\n\t{\n\t\t@Override\n\t\tpublic final void apply(final MOB M)\n\t\t{\n\t\t\tM.recoverCharStats();\n\t\t\tM.recoverPhyStats();\n\t\t\tM.recoverMaxState();\n\t\t}\n\t};\n\n\tprivate void reallyRecoverRoomStats()\n\t{\n\t\trecoverPhyStats();\n\t\teachInhabitant(recoverRoomStatsInhabitantApplicable);\n\t\tfor(final Exit X : exits)\n\t\t{\n\t\t\tif(X!=null)\n\t\t\t\tX.recoverPhyStats();\n\t\t}\n\t\teachItem(recoverRoomStatsItemApplicable);\n\t}\n\n\t@Override\n\tpublic void recoverRoomStats()\n\t{\n\t\tif(roomRecoverMarker.addAndGet(1)!=1)\n\t\t\treturn;\n\t\ttry\n\t\t{\n\t\t\treallyRecoverRoomStats();\n\t\t\tif(roomRecoverMarker.addAndGet(-1)>0)\n\t\t\t\treallyRecoverRoomStats();\n\t\t}\n\t\tfinally\n\t\t{\n\t\t\troomRecoverMarker.set(0);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setBasePhyStats(final PhyStats newStats)\n\t{\n\t\tbasePhyStats=(PhyStats)newStats.copyOf();\n\t}\n\n\tprivate final static int phyStatsMaskOut = ~(PhyStats.IS_DARK|PhyStats.IS_LIGHTSOURCE|PhyStats.IS_SLEEPING|PhyStats.IS_HIDDEN|PhyStats.IS_SWIMMING|PhyStats.IS_NOT_SEEN);\n\n\t@Override\n\tpublic void affectPhyStats(final Physical affected, final PhyStats affectableStats)\n\t{\n\t\tgetArea().affectPhyStats(affected,affectableStats);\n\t\tfinal int disposition=phyStats().disposition() & phyStatsMaskOut;\n\t\tif(disposition>0)\n\t\t\taffectableStats.setDisposition(affectableStats.disposition()|disposition);\n\t\teachEffect(new EachApplicable<Ability>()\n\t\t{\n\t\t\t@Override\n\t\t\tpublic final void apply(final Ability A)\n\t\t\t{\n\t\t\t\tif(A.bubbleAffect())\n\t\t\t\t\tA.affectPhyStats(affected,affectableStats);\n\t\t\t}\n\t\t});\n\t}\n\n\t@Override\n\tpublic void affectCharStats(final MOB affectedMob, final CharStats affectableStats)\n\t{\n\t\tgetArea().affectCharStats(affectedMob,affectableStats);\n\t\teachEffect(new EachApplicable<Ability>()\n\t\t{\n\t\t\t@Override\n\t\t\tpublic final void apply(final Ability A)\n\t\t\t{\n\t\t\t\tif(A.bubbleAffect())\n\t\t\t\t\tA.affectCharStats(affectedMob,affectableStats);\n\t\t\t}\n\t\t});\n\t}\n\n\t@Override\n\tpublic void affectCharState(final MOB affectedMob, final CharState affectableMaxState)\n\t{\n\t\tgetArea().affectCharState(affectedMob,affectableMaxState);\n\t\teachEffect(new EachApplicable<Ability>()\n\t\t{\n\t\t\t@Override\n\t\t\tpublic final void apply(final Ability A)\n\t\t\t{\n\t\t\t\tif(A.bubbleAffect())\n\t\t\t\t\tA.affectCharState(affectedMob,affectableMaxState);\n\t\t\t}\n\t\t});\n\t}\n\n\t@Override\n\tpublic int compareTo(final CMObject o)\n\t{\n\t\treturn CMClass.classID(this).compareToIgnoreCase(CMClass.classID(o));\n\t}\n\n\t@Override\n\tpublic String displayText(final MOB mob)\n\t{\n\t\treturn CMLib.commands().parseVaries(mob,getArea(),this,displayText());\n\t}\n\n\t@Override\n\tpublic String description(final MOB mob)\n\t{\n\t\treturn CMLib.commands().parseVaries(mob,getArea(),this,description());\n\t}\n\n\t@Override\n\tpublic void bringMobHere(final MOB mob, final boolean andFollowers)\n\t{\n\t\tif(mob==null)\n\t\t\treturn;\n\t\tfinal Room oldRoom=mob.location();\n\t\tif(oldRoom!=null)\n\t\t\toldRoom.delInhabitant(mob);\n\t\tif(!isInhabitant(mob))\n\t\t\taddInhabitant(mob);\n\t\tmob.setLocation(this);\n\n\t\tif((andFollowers)&&(oldRoom!=null))\n\t\t{\n\t\t\tfor(final Enumeration<Pair<MOB,Short>> f=mob.followers();f.hasMoreElements();)\n\t\t\t{\n\t\t\t\tfinal MOB folM=f.nextElement().first;\n\t\t\t\tif((folM.location()==oldRoom)\n\t\t\t\t&&(folM != mob)\n\t\t\t\t&&(oldRoom != this))\n\t\t\t\t\tbringMobHere(folM,true);\n\t\t\t}\n\t\t}\n\t\tfinal Rideable RI=mob.riding();\n\t\tif((RI!=null)&&(CMLib.map().roomLocation(RI)==oldRoom))\n\t\t{\n\t\t\tif((RI.isMobileRideBasis())\n\t\t\t&&((!(RI instanceof Item))||(!CMLib.flags().isMobile(RI))))\n\t\t\t{\n\t\t\t\tif(RI instanceof MOB)\n\t\t\t\t\tbringMobHere((MOB)RI,andFollowers);\n\t\t\t\telse\n\t\t\t\tif(RI instanceof Item)\n\t\t\t\t{\n\t\t\t\t\tif(andFollowers)\n\t\t\t\t\t\tmoveItemTo((Item)RI,ItemPossessor.Expire.Player_Drop,Move.Followers);\n\t\t\t\t\telse\n\t\t\t\t\t\tmoveItemTo((Item)RI,ItemPossessor.Expire.Player_Drop);\n\t\t\t\t}\n\t\t\t\t// refuse is good for above, since mostly moving player stuff around\n\t\t\t}\n\t\t\telse\n\t\t\t\tmob.setRiding(null);\n\t\t}\n\t\tif((oldRoom!=null)\n\t\t&&(mob instanceof Rideable)\n\t\t&&(oldRoom!=this))\n\t\t{\n\t\t\tfor(final Enumeration<Rider> r=((Rideable)mob).riders();r.hasMoreElements();)\n\t\t\t{\n\t\t\t\tfinal Rider RR=r.nextElement();\n\t\t\t\tif(CMLib.map().roomLocation(RR)==oldRoom)\n\t\t\t\t{\n\t\t\t\t\tif(((Rideable)mob).isMobileRideBasis())\n\t\t\t\t\t{\n\t\t\t\t\t\tif((RR instanceof MOB)\n\t\t\t\t\t\t&&(andFollowers)\n\t\t\t\t\t\t&&(RR!=mob))\n\t\t\t\t\t\t\tbringMobHere((MOB)RR,andFollowers);\n\t\t\t\t\t\telse\n\t\t\t\t\t\tif(RR instanceof Item)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif(andFollowers)\n\t\t\t\t\t\t\t\tmoveItemTo((Item)RR,ItemPossessor.Expire.Player_Drop,Move.Followers);\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tmoveItemTo((Item)RR,ItemPossessor.Expire.Player_Drop);\n\t\t\t\t\t\t\t// refuse is good for above, since mostly moving player stuff around\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tRR.setRiding(null);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif(oldRoom!=null)\n\t\t\toldRoom.recoverRoomStats();\n\t\trecoverRoomStats();\n\t}\n\n\t@Override\n\tpublic void moveItemTo(final Item container)\n\t{\n\t\tmoveItemTo(container, Expire.Never);\n\t}\n\n\t@Override\n\tpublic void moveItemTo(final Item item, final Expire expire, final Move... moveFlags)\n\t{\n\t\tif(item==null)\n\t\t\treturn;\n\t\tfinal ItemPossessor o;\n\t\tsynchronized(item)\n\t\t{\n\t\t\to=item.owner();\n\t\t}\n\t\tif(o==null)\n\t\t\treturn;\n\n\t\tList<Item> V=new ArrayList<Item>();\n\t\tif(item instanceof Container)\n\t\t\tV=((Container)item).getDeepContents();\n\t\to.delItem(item);\n\t\tif(o.isContent(item))\n\t\t\to.delItem(item);\n\n\t\taddItem(item, expire);\n\t\tfor(int v=0;v<V.size();v++)\n\t\t{\n\t\t\tfinal Item i2=V.get(v);\n\t\t\to.delItem(i2);\n\t\t\tif(o.isContent(i2))\n\t\t\t\to.delItem(i2);\n\t\t\taddItem(i2);\n\t\t}\n\t\titem.setContainer(null);\n\n\t\tfinal Rideable RI=item.riding();\n\t\tif((RI!=null)&&(o instanceof Room)&&(CMLib.map().roomLocation(RI)==o))\n\t\t{\n\t\t\tif((RI.isMobileRideBasis())\n\t\t\t&&((!(RI instanceof Item))||(!CMLib.flags().isMobile(RI))))\n\t\t\t{\n\t\t\t\tif(RI instanceof MOB)\n\t\t\t\t\tbringMobHere((MOB)RI,true);\n\t\t\t\telse\n\t\t\t\tif(RI instanceof Item)\n\t\t\t\t\tmoveItemTo((Item)RI,null,ItemPossessor.Move.Followers);\n\t\t\t}\n\t\t\telse\n\t\t\t\titem.setRiding(null);\n\t\t}\n\t\tif(CMParms.contains(moveFlags, Move.Followers)\n\t\t&&(o instanceof Room)\n\t\t&&(item instanceof Rideable)\n\t\t&&(o!=this))\n\t\t{\n\t\t\tRider RR=null;\n\t\t\tfor(int r=0;r<((Rideable)item).numRiders();r++)\n\t\t\t{\n\t\t\t\tRR=((Rideable)item).fetchRider(r);\n\t\t\t\tif(CMLib.map().roomLocation(RR)==o)\n\t\t\t\t{\n\t\t\t\t\tif((((Rideable)item).isMobileRideBasis())\n\t\t\t\t\t&&(!CMLib.flags().isMobile(item)))\n\t\t\t\t\t{\n\t\t\t\t\t\tif(RR instanceof MOB)\n\t\t\t\t\t\t\tbringMobHere((MOB)RR,true);\n\t\t\t\t\t\telse\n\t\t\t\t\t\tif(RR instanceof Item)\n\t\t\t\t\t\t\tmoveItemTo((Item)RR,ItemPossessor.Expire.Player_Drop,ItemPossessor.Move.Followers);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t\tRR.setRiding(null);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif(!CMParms.contains(moveFlags, Move.Optimize))\n\t\t{\n\t\t\tif(o instanceof Room)\n\t\t\t\t((Room)o).recoverRoomStats();\n\t\t\telse\n\t\t\tif(o instanceof MOB)\n\t\t\t{\n\t\t\t\t((MOB)o).recoverCharStats();\n\t\t\t\t((MOB)o).recoverPhyStats();\n\t\t\t\t((MOB)o).recoverMaxState();\n\t\t\t}\n\t\t\trecoverRoomStats();\n\t\t}\n\t}\n\n\t@Override\n\tpublic int getReverseDir(final int direction)\n\t{\n\t\tif((direction<0)||(direction>=Directions.NUM_DIRECTIONS()))\n\t\t\treturn -1;\n\t\tfinal Room opRoom=getRoomInDir(direction);\n\t\tif(opRoom!=null)\n\t\t{\n\t\t\tif(direction == Directions.GATE)\n\t\t\t\treturn direction;\n\t\t\tfinal int formalOpDir=Directions.getOpDirectionCode(direction);\n\t\t\tif(opRoom.rawDoors()[formalOpDir]==this)\n\t\t\t\treturn formalOpDir;\n\t\t\tif(opRoom.getRoomInDir(formalOpDir)==this)\n\t\t\t\treturn formalOpDir;\n\t\t\tfor(int d=0;d<Directions.NUM_DIRECTIONS();d++)\n\t\t\t{\n\t\t\t\tif(opRoom.rawDoors()[d]==this)\n\t\t\t\t\treturn d;\n\t\t\t}\n\t\t\treturn formalOpDir;\n\t\t}\n\t\treturn -1;\n\t}\n\n\t@Override\n\tpublic Exit getReverseExit(final int direction)\n\t{\n\t\tfinal int opDir=getReverseDir(direction);\n\t\tif((opDir<0)||(opDir>=Directions.NUM_DIRECTIONS()))\n\t\t\treturn null;\n\t\tfinal Room opRoom=getRoomInDir(direction);\n\t\tif(opRoom!=null)\n\t\t\treturn opRoom.getExitInDir(opDir);\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Exit getPairedExit(final int direction)\n\t{\n\t\tfinal Exit opExit=getReverseExit(direction);\n\t\tfinal Exit myExit=getExitInDir(direction);\n\t\tif((myExit==null)||(opExit==null))\n\t\t\treturn null;\n\t\tif(myExit.hasADoor()!=opExit.hasADoor())\n\t\t\treturn null;\n\t\treturn opExit;\n\t}\n\n\t@Override\n\tpublic Room prepareRoomInDir(final Room R, final int direction)\n\t{\n\t\tif(amDestroyed)\n\t\t{\n\t\t\tif(roomID().length()>0)\n\t\t\t{\n\t\t\t\tfinal Room thinMeR=CMClass.getLocale("ThinRoom");\n\t\t\t\tthinMeR.setRoomID(roomID());\n\t\t\t\tthinMeR.setArea(myArea);\n\t\t\t\tif(R.rawDoors()[direction]==this)\n\t\t\t\t\tR.rawDoors()[direction]=thinMeR;\n\t\t\t\treturn thinMeR.prepareRoomInDir(R,direction);\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t\tif(expirationDate()!=0)\n\t\t\tsetExpirationDate(System.currentTimeMillis()+WorldMap.ROOM_EXPIRATION_MILLIS);\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic Room getRoomInDir(final int direction)\n\t{\n\t\tif((direction<0)||(direction>=doors.length)||(amDestroyed))\n\t\t\treturn null;\n\t\tRoom nextRoom=rawDoors()[direction];\n\t\tif(gridParent!=null)\n\t\t\tnextRoom=gridParent.prepareGridLocale(this,nextRoom,direction);\n\t\tif(nextRoom!=null)\n\t\t{\n\t\t\tnextRoom=nextRoom.prepareRoomInDir(this,direction);\n\t\t\tif((nextRoom!=null)&&(nextRoom.amDestroyed()))\n\t\t\t\treturn null;\n\t\t}\n\t\treturn nextRoom;\n\t}\n\n\t@Override\n\tpublic Exit getExitInDir(final int direction)\n\t{\n\t\tif((direction<0)||(direction>=exits.length))\n\t\t\treturn null;\n\t\tif((gridParent!=null)&&(getRawExit(direction)==null))\n\t\t\tgetRoomInDir(direction);\n\t\treturn getRawExit(direction);\n\t}\n\n\tprotected void sendAndExec(final MOB source, final CMMsg msg)\n\t{\n\t\tif((Log.debugChannelOn())&&(CMSecurity.isDebugging(CMSecurity.DbgFlag.MESSAGES)))\n\t\t\tLog.debugOut("StdRoom",msg.source().ID()+":"+msg.sourceCode()+":"+msg.sourceMessage()+"/"+((msg.target()!=null)?msg.target().ID():"null")+":"+msg.targetCode()+":"+msg.targetMessage()+"/"+((msg.tool()!=null)?msg.tool().ID():"null")+"/"+msg.othersCode()+":"+msg.othersMessage());\n\t\tfor(final MOB otherMOB : inhabitants)\n\t\t{\n\t\t\tif(otherMOB!=source)\n\t\t\t\totherMOB.executeMsg(otherMOB,msg);\n\t\t}\n\t\texecuteMsg(source,msg);\n\t\tCMLib.commands().monitorGlobalMessage(this, msg);\n\t}\n\n\tprotected void sendTrailermsgs(final MOB source, final CMMsg msg, final int depth, final boolean includeSource)\n\t{\n\t\t// now handle trailer msgs\n\t\tif(depth<3)\n\t\t{\n\t\t\tif(msg.trailerMsgs()!=null)\n\t\t\t{\n\t\t\t\tfor(final CMMsg msg2 : msg.trailerMsgs())\n\t\t\t\t{\n\t\t\t\t\tif((msg!=msg2)\n\t\t\t\t\t&&((msg2.target()==null)\n\t\t\t\t\t   ||(!(msg2.target() instanceof MOB))\n\t\t\t\t\t   ||((!((MOB)msg2.target()).amDead())||(msg2.sourceMinor()==CMMsg.TYP_DEATH)))\n\t\t\t\t\t&&(okMessage(source,msg2)))\n\t\t\t\t\t{\n\t\t\t\t\t\tif(includeSource)\n\t\t\t\t\t\t\tsource.executeMsg(source,msg2);\n\t\t\t\t\t\tsendAndExec(source,msg2);\n\t\t\t\t\t\tsendTrailermsgs(source, msg2, depth+1, includeSource);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfinal List<Runnable> trails=msg.trailerRunnables();\n\t\t\tif((trails!=null)\n\t\t\t&&(trails.size()>0))\n\t\t\t{\n\t\t\t\tfor(final Runnable r : trails)\n\t\t\t\t\tCMLib.threads().executeRunnable(r);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void send(final MOB source, final CMMsg msg)\n\t{\n\t\tsource.executeMsg(source,msg);\n\t\tsendAndExec(source,msg);\n\t\tsendTrailermsgs(source, msg, 0, true);\n\t}\n\n\t@Override\n\tpublic void sendOthers(final MOB source, final CMMsg msg)\n\t{\n\t\tsendAndExec(source,msg);\n\t\tsendTrailermsgs(source, msg, 0, false);\n\t}\n\n\t@Override\n\tpublic void showHappens(final int allCode, final String allMessage)\n\t{\n\t\tfinal MOB everywhereMOB=CMLib.map().getFactoryMOB(this);\n\t\tfinal CMMsg msg=CMClass.getMsg(everywhereMOB,null,null,allCode,allCode,allCode,allMessage);\n\t\tsendOthers(everywhereMOB,msg);\n\t\teverywhereMOB.destroy();\n\t}\n\n\t@Override\n\tpublic void showHappens(final int allCode, final Environmental like, final String allMessage)\n\t{\n\t\tfinal MOB everywhereMOB=CMClass.getFactoryMOB();\n\t\teverywhereMOB.setName(like.name());\n\t\tif(like instanceof Physical)\n\t\t\teverywhereMOB.setBasePhyStats(((Physical)like).phyStats());\n\t\teverywhereMOB.setLocation(this);\n\t\teverywhereMOB.recoverPhyStats();\n\t\tfinal CMMsg msg=CMClass.getMsg(everywhereMOB,null,null,allCode,allCode,allCode,allMessage);\n\t\tsend(everywhereMOB,msg);\n\t\teverywhereMOB.destroy();\n\t}\n\n\t@Override\n\tpublic boolean show(final MOB source, final Environmental target, final int allCode, final String allMessage)\n\t{\n\t\tfinal CMMsg msg=CMClass.getMsg(source,target,null,allCode,allCode,allCode,allMessage);\n\t\tif((!CMath.bset(allCode,CMMsg.MASK_ALWAYS))&&(!okMessage(source,msg)))\n\t\t\treturn false;\n\t\tsend(source,msg);\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean show(final MOB source, final Environmental target, final Environmental tool, final int allCode, final String allMessage)\n\t{\n\t\tfinal CMMsg msg=CMClass.getMsg(source,target,tool,allCode,allCode,allCode,allMessage);\n\t\tif((!CMath.bset(allCode,CMMsg.MASK_ALWAYS))&&(!okMessage(source,msg)))\n\t\t\treturn false;\n\t\tsend(source,msg);\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean show(final MOB source,\n\t\t\t\t\t\tfinal Environmental target,\n\t\t\t\t\t\tfinal Environmental tool,\n\t\t\t\t\t\tfinal int srcCode,\n\t\t\t\t\t\tfinal int tarCode,\n\t\t\t\t\t\tfinal int othCode,\n\t\t\t\t\t\tfinal String allMessage)\n\t{\n\t\tfinal CMMsg msg=CMClass.getMsg(source,target,tool,srcCode,tarCode,othCode,allMessage);\n\t\tif((!CMath.bset(srcCode,CMMsg.MASK_ALWAYS))&&(!okMessage(source,msg)))\n\t\t\treturn false;\n\t\tsend(source,msg);\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean show(final MOB source,\n\t\t\t\t\t\tfinal Environmental target,\n\t\t\t\t\t\tfinal Environmental tool,\n\t\t\t\t\t\tfinal int allCode,\n\t\t\t\t\t\tfinal String srcMessage,\n\t\t\t\t\t\tfinal String tarMessage,\n\t\t\t\t\t\tfinal String othMessage)\n\t{\n\t\tfinal CMMsg msg=CMClass.getMsg(source,target,tool,allCode,srcMessage,allCode,tarMessage,allCode,othMessage);\n\t\tif((!CMath.bset(allCode,CMMsg.MASK_ALWAYS))&&(!okMessage(source,msg)))\n\t\t\treturn false;\n\t\tsend(source,msg);\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean show(final MOB source,\n\t\t\t\t\t\tfinal Environmental target,\n\t\t\t\t\t\tfinal Environmental tool,\n\t\t\t\t\t\tfinal int srcCode,\n\t\t\t\t\t\tfinal String srcMessage,\n\t\t\t\t\t\tfinal int tarCode,\n\t\t\t\t\t\tfinal String tarMessage,\n\t\t\t\t\t\tfinal int othCode,\n\t\t\t\t\t\tfinal String othMessage)\n\t{\n\t\tfinal CMMsg msg=CMClass.getMsg(source,target,tool,srcCode,srcMessage,tarCode,tarMessage,othCode,othMessage);\n\t\tif((!CMath.bset(srcCode,CMMsg.MASK_ALWAYS))&&(!okMessage(source,msg)))\n\t\t\treturn false;\n\t\tsend(source,msg);\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean showOthers(final MOB source,\n\t\t\t\t\t\t\t  final Environmental target,\n\t\t\t\t\t\t\t  final int allCode,\n\t\t\t\t\t\t\t  final String allMessage)\n\t{\n\t\tfinal CMMsg msg=CMClass.getMsg(source,target,null,allCode,allCode,allCode,allMessage);\n\t\tif((!CMath.bset(allCode,CMMsg.MASK_ALWAYS))&&(!okMessage(source,msg)))\n\t\t\treturn false;\n\t\tsendAndExec(source,msg);\n\t\tsendTrailermsgs(source, msg, 0, false);\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean showOthers(final MOB source,\n\t\t\t\t\t\t\t  final Environmental target,\n\t\t\t\t\t\t\t  final Environmental tool,\n\t\t\t\t\t\t\t  final int allCode,\n\t\t\t\t\t\t\t  final String allMessage)\n\t{\n\t\tfinal CMMsg msg=CMClass.getMsg(source,target,tool,allCode,allCode,allCode,allMessage);\n\t\tif((!CMath.bset(allCode,CMMsg.MASK_ALWAYS))&&(!okMessage(source,msg)))\n\t\t\treturn false;\n\t\tsendAndExec(source,msg);\n\t\tsendTrailermsgs(source, msg, 0, false);\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean showSource(final MOB source,\n\t\t\t\t\t\t\t  final Environmental target,\n\t\t\t\t\t\t\t  final int allCode,\n\t\t\t\t\t\t\t  final String allMessage)\n\t{\n\t\tfinal CMMsg msg=CMClass.getMsg(source,target,null,allCode,allCode,allCode,allMessage);\n\t\tif((!CMath.bset(allCode,CMMsg.MASK_ALWAYS))&&(!okMessage(source,msg)))\n\t\t\treturn false;\n\t\tsource.executeMsg(source,msg);\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic boolean showSource(final MOB source,\n\t\t\t\t\t\t\t  final Environmental target,\n\t\t\t\t\t\t\t  final Environmental tool,\n\t\t\t\t\t\t\t  final int allCode,\n\t\t\t\t\t\t\t  final String allMessage)\n\t{\n\t\tfinal CMMsg msg=CMClass.getMsg(source,target,tool,allCode,allCode,allCode,allMessage);\n\t\tif((!CMath.bset(allCode,CMMsg.MASK_ALWAYS))&&(!okMessage(source,msg)))\n\t\t\treturn false;\n\t\tsource.executeMsg(source,msg);\n\t\treturn true;\n\t}\n\n\t@Override\n\tpublic Exit getRawExit(final int dir)\n\t{\n\t\tif(dir<exits.length)\n\t\t\treturn exits[dir];\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Room[] rawDoors()\n\t{\n\t\treturn doors;\n\t}\n\n\t@Override\n\tpublic boolean isSavable()\n\t{\n\t\treturn ((roomID().length()>0)\n\t\t\t\t&&((getArea()==null)\n\t\t\t\t\t|| (!CMath.bset(getArea().flags(),Area.FLAG_INSTANCE_CHILD)))\n\t\t\t\t&&(CMLib.flags().isSavable(this)));\n\t}\n\n\t@Override\n\tpublic void setSavable(final boolean truefalse)\n\t{\n\t\tCMLib.flags().setSavable(this, truefalse);\n\t}\n\n\t@Override\n\tpublic void destroy()\n\t{\n\t\tif((phyStats().sensesMask()&PhyStats.SENSE_UNDESTROYABLE)>0)\n\t\t\treturn;\n\t\tCMLib.map().registerWorldObjectDestroyed(getArea(),this,this);\n\t\tdelAllEffects(true);\n\t\tdelAllInhabitants(true);\n\t\tdelAllBehaviors();\n\t\tdelAllScripts();\n\t\tCMLib.threads().deleteTick(this,-1);\n\t\tdelAllItems(true);\n\t\tif(this instanceof GridLocale)\n\t\t\t((GridLocale)this).clearGrid(null);\n\t\tclearSky();\n\t\tif((roomID().length()==0)&&(rawDoors()!=null))\n\t\t{\n\t\t\tRoom roomDir=null;\n\t\t\tfor(int d=rawDoors().length-1;d>=0;d--)\n\t\t\t{\n\t\t\t\troomDir=rawDoors()[d];\n\t\t\t\tif((roomDir!=null)&&(roomDir.rawDoors()!=null))\n\t\t\t\t{\n\t\t\t\t\tfor(int d2=roomDir.rawDoors().length-1;d2>=0;d2--)\n\t\t\t\t\t{\n\t\t\t\t\t\tif(roomDir.rawDoors()[d2]==this)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\troomDir.rawDoors()[d2]=null;\n\t\t\t\t\t\t\troomDir.setRawExit(d2,null);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\trawImageName=null;\n\t\tcachedImageName=null;\n\t\tsetArea(null); // this actually deletes the room from the cache map\n\t\tbasePhyStats=(PhyStats)CMClass.getCommon("DefaultPhyStats");\n\t\tphyStats=basePhyStats;\n\t\tfor(int d=Directions.NUM_DIRECTIONS()-1;d>=0;d--)\n\t\t\tsetRawExit(d,null);\n\t\tArrays.fill(exits, null);\n\t\tArrays.fill(doors, null);\n\t\taffects=null;\n\t\tbehaviors=null;\n\t\tscripts=null;\n\t\tcontents.setSize(0);\n\t\tinhabitants.setSize(0);\n\t\tgridParent=null;\n\t\tamDestroyed=true;\n\t}\n\n\t@Override\n\tpublic final boolean amDestroyed()\n\t{\n\t\treturn amDestroyed;\n\t}\n\n\t@Override\n\tpublic int getCombatTurnMobIndex()\n\t{\n\t\treturn combatTurnMobIndex;\n\t}\n\n\t@Override\n\tpublic void setCombatTurnMobIndex(final int index)\n\t{\n\t\tcombatTurnMobIndex = (short)index;\n\t}\n\n\t@Override\n\tpublic boolean isHere(final Environmental E)\n\t{\n\t\tif(E instanceof Item)\n\t\t\treturn isContent((Item)E);\n\t\telse\n\t\tif(E instanceof MOB)\n\t\t\treturn isInhabitant((MOB)E);\n\t\telse\n\t\tif(E instanceof Exit)\n\t\t{\n\t\t\tfor(int d=Directions.NUM_DIRECTIONS()-1;d>=0;d--)\n\t\t\t{\n\t\t\t\tif(getRawExit(d)==E)\n\t\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\telse\n\t\tif(E instanceof Room)\n\t\t{\n\t\t\tif (E == this)\n\t\t\t\treturn true;\n\t\t\tif (E instanceof Room)\n\t\t\t{\n\t\t\t\tif (CMLib.map().getExtendedRoomID(this).equals(CMLib.map().getExtendedRoomID((Room) E)))\n\t\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t\telse\n\t\tif(E instanceof Ability)\n\t\t\treturn fetchEffect(E.ID())!=null;\n\t\telse\n\t\tif(E instanceof Behavior)\n\t\t\treturn fetchBehavior(E.ID())!=null;\n\t\treturn false;\n\t}\n\n\t@Override\n\tpublic MOB fetchRandomInhabitant()\n\t{\n\t\tif(inhabitants.isEmpty())\n\t\t\treturn null;\n\t\treturn fetchInhabitant(CMLib.dice().roll(1,numInhabitants(),-1));\n\t}\n\n\t@Override\n\tpublic MOB fetchInhabitant(final String inhabitantID)\n\t{\n\t\tif(inhabitants.isEmpty())\n\t\t\treturn null;\n\t\tMOB mob=(MOB)CMLib.english().fetchEnvironmental(inhabitants,inhabitantID,true);\n\t\tif(mob==null)\n\t\t\tmob=(MOB)CMLib.english().fetchEnvironmental(inhabitants,inhabitantID, false);\n\t\treturn mob;\n\t}\n\n\t@Override\n\tpublic MOB fetchInhabitantExact(final String inhabitantID)\n\t{\n\t\tif(inhabitants.isEmpty())\n\t\t\treturn null;\n\t\treturn (MOB)CMLib.english().fetchEnvironmental(inhabitants,inhabitantID,true);\n\t}\n\n\tprivate static final ReadOnlyVector<MOB> emptyMOBV=new ReadOnlyVector<MOB>(1);\n\n\t@SuppressWarnings("unchecked")\n\n\t@Override\n\tpublic List<MOB> fetchInhabitants(final String inhabitantID)\n\t{\n\t\tif(inhabitants.isEmpty())\n\t\t\treturn emptyMOBV;\n\t\t@SuppressWarnings("rawtypes")\n\t\tList inhabs=CMLib.english().fetchEnvironmentals(inhabitants,inhabitantID,true);\n\t\tif(inhabs.isEmpty())\n\t\t\tinhabs=CMLib.english().fetchEnvironmentals(inhabitants,inhabitantID, false);\n\t\treturn inhabs;\n\t}\n\n\t@Override\n\tpublic void addInhabitant(final MOB mob)\n\t{\n\t\tinhabitants.addElement(mob);\n\t}\n\n\t@Override\n\tpublic Enumeration<MOB> inhabitants()\n\t{\n\t\treturn inhabitants.elements();\n\t}\n\n\t@Override\n\tpublic int numInhabitants()\n\t{\n\t\treturn inhabitants.size();\n\t}\n\n\t@Override\n\tpublic int numPCInhabitants()\n\t{\n\t\tfinal Set<MOB> playerInhabitants=CMLib.players().getPlayersHere(this);\n\t\tif(playerInhabitants.isEmpty())\n\t\t\treturn 0;\n\t\tint num=0;\n\t\tfor(final MOB M : playerInhabitants)\n\t\t{\n\t\t\tif((M!=null)&&(M.session()!=null))\n\t\t\t\tnum++;\n\t\t}\n\t\treturn num;\n\t}\n\n\t@Override\n\tpublic boolean isInhabitant(final MOB mob)\n\t{\n\t\treturn inhabitants.contains(mob);\n\t}\n\n\t@Override\n\tpublic MOB fetchInhabitant(final int i)\n\t{\n\t\ttry\n\t\t{\n\t\t\treturn inhabitants.elementAt(i);\n\t\t}\n\t\tcatch(final java.lang.ArrayIndexOutOfBoundsException x)\n\t\t{\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void eachInhabitant(final EachApplicable<MOB> applier)\n\t{\n\t\tfinal List<MOB> inhabitants=this.inhabitants;\n\t\tif((inhabitants!=null)&&(!inhabitants.isEmpty()))\n\t\t{\n\t\t\ttry\n\t\t\t{\n\t\t\t\tfor(int a=0;a<inhabitants.size();a++)\n\t\t\t\t{\n\t\t\t\t\tfinal MOB M=inhabitants.get(a);\n\t\t\t\t\tif(M!=null)\n\t\t\t\t\t\tapplier.apply(M);\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch(final ArrayIndexOutOfBoundsException e)\n\t\t\t{\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void delInhabitant(final MOB mob)\n\t{\n\t\tinhabitants.removeElement(mob);\n\t}\n\n\t@Override\n\tpublic void delAllInhabitants(final boolean destroy)\n\t{\n\t\ttry\n\t\t{\n\t\t\tfor(int i=numInhabitants()-1;i>=0;i--)\n\t\t\t{\n\t\t\t\tfinal MOB M=fetchInhabitant(i);\n\t\t\t\tif(M!=null)\n\t\t\t\t{\n\t\t\t\t\tif(destroy || (M.location()==this))\n\t\t\t\t\t\tM.setLocation(null);\n\t\t\t\t\tif(destroy)\n\t\t\t\t\t\tM.destroy();\n\t\t\t\t}\n\t\t\t}\n\t\t\tinhabitants.clear();\n\t\t}\n\t\tcatch(final Exception e)\n\t\t{\n\t\t}\n\t}\n\n\t@Override\n\tpublic Exit fetchExit(final String itemID)\n\t{\n\t\tfinal int dir=CMLib.directions().getGoodDirectionCode(itemID);\n\t\tExit E=null;\n\t\tif(dir >= 0)\n\t\t\tE=getExitInDir(dir);\n\t\tfinal List<Exit> exitList=Arrays.asList(exits);\n\t\tif(E==null)\n\t\t\tE=CMLib.english().fetchExit(exitList, itemID, true);\n\t\tif(E==null)\n\t\t\tE=CMLib.english().fetchExit(exitList, itemID, false);\n\t\tif(contents.isEmpty())\n\t\t\treturn E;\n\t\tif(E==null)\n\t\t\tE=CMLib.english().fetchExit(contents, itemID, true);\n\t\tif(E==null)\n\t\t\tE=CMLib.english().fetchExit(contents, itemID, false);\n\t\treturn E;\n\t}\n\n\t@Override\n\tpublic Item findItem(final String itemID)\n\t{\n\t\tif(contents.isEmpty())\n\t\t\treturn null;\n\t\tItem item=(Item)CMLib.english().fetchEnvironmental(contents,itemID,true);\n\t\tif(item==null)\n\t\t\titem=(Item)CMLib.english().fetchEnvironmental(contents,itemID,false);\n\t\treturn item;\n\t}\n\n\t@Override\n\tpublic Enumeration<Item> items()\n\t{\n\t\treturn contents.elements();\n\t}\n\n\t@Override\n\tpublic Enumeration<Item> itemsRecursive()\n\t{\n\t\treturn new MultiEnumeration<Item>()\n\t\t\t.addEnumeration(items())\n\t\t\t.addEnumeration(new Enumeration<Item>()\n\t\t\t{\n\t\t\t\tprivate final Enumeration<MOB> curMobEnumeration = inhabitants();\n\t\t\t\tprivate volatile Enumeration<Item> curItemEnumeration;\n\n\t\t\t\t@Override\n\t\t\t\tpublic boolean hasMoreElements()\n\t\t\t\t{\n\t\t\t\t\tboolean hasMore = (curItemEnumeration!=null)&&(curItemEnumeration.hasMoreElements());\n\t\t\t\t\twhile(!hasMore)\n\t\t\t\t\t{\n\t\t\t\t\t\tif((curMobEnumeration == null)||(!curMobEnumeration.hasMoreElements()))\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\tcurItemEnumeration=curMobEnumeration.nextElement().items();\n\t\t\t\t\t\thasMore = (curItemEnumeration!=null)&&(curItemEnumeration.hasMoreElements());\n\t\t\t\t\t}\n\t\t\t\t\treturn hasMore;\n\t\t\t\t}\n\n\t\t\t\t@Override\n\t\t\t\tpublic Item nextElement()\n\t\t\t\t{\n\t\t\t\t\tif(!hasMoreElements())\n\t\t\t\t\t\tthrow new NoSuchElementException();\n\t\t\t\t\treturn curItemEnumeration.nextElement();\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\n\t@Override\n\tpublic Item findItem(final Item goodLocation, final String itemID)\n\t{\n\t\tif(contents.isEmpty())\n\t\t\treturn null;\n\t\tItem item=CMLib.english().fetchAvailableItem(contents,itemID,goodLocation,Wearable.FILTER_ANY,true);\n\t\tif(item==null)\n\t\t\titem=CMLib.english().fetchAvailableItem(contents,itemID,goodLocation,Wearable.FILTER_ANY,false);\n\t\treturn item;\n\t}\n\n\t@Override\n\tpublic List<Item> findItems(final Item goodLocation, final String itemID)\n\t{\n\t\tif(contents.isEmpty())\n\t\t\treturn new Vector<Item>(1);\n\t\tList<Item> items=CMLib.english().fetchAvailableItems(contents,itemID,goodLocation,Wearable.FILTER_ANY,true);\n\t\tif(items.isEmpty())\n\t\t\titems=CMLib.english().fetchAvailableItems(contents,itemID,goodLocation,Wearable.FILTER_ANY,false);\n\t\treturn items;\n\t}\n\n\t@SuppressWarnings({ "rawtypes", "unchecked" })\n\t@Override\n\tpublic List<Item> findItems(final String itemID)\n\t{\n\t\tif(contents.isEmpty())\n\t\t\treturn new Vector<Item>(1);\n\t\tList items=CMLib.english().fetchEnvironmentals(contents,itemID,true);\n\t\tif(items.isEmpty())\n\t\t\titems=CMLib.english().fetchEnvironmentals(contents,itemID, false);\n\t\treturn items;\n\t}\n\n\t@Override\n\tpublic void addItem(final Item item, Expire expire)\n\t{\n\t\tif(expire == null)\n\t\t{\n\t\t\texpire=Expire.Never;\n\t\t}\n\t\tint numMins = 0;\n\t\tswitch(expire)\n\t\t{\n\t\tcase Monster_EQ:\n\t\t\taddItem(item);\n\t\t\tnumMins = CMProps.getIntVar(CMProps.Int.EXPIRE_MONSTER_EQ);\n\t\t\tbreak;\n\t\tcase Monster_Body:\n\t\t\tinsertItemUpTop(item);\n\t\t\tnumMins = CMProps.getIntVar(CMProps.Int.EXPIRE_MONSTER_BODY);\n\t\t\tbreak;\n\t\tcase Player_Body:\n\t\t\tinsertItemUpTop(item);\n\t\t\tnumMins = CMProps.getIntVar(CMProps.Int.EXPIRE_PLAYER_BODY);\n\t\t\tbreak;\n\t\tcase Player_Drop:\n\t\t\taddItem(item);\n\t\t\tnumMins = CMProps.getIntVar(CMProps.Int.EXPIRE_PLAYER_DROP);\n\t\t\tbreak;\n\t\tcase Resource:\n\t\t\taddItem(item);\n\t\t\tnumMins = CMProps.getIntVar(CMProps.Int.EXPIRE_RESOURCE);\n\t\t\tbreak;\n\t\tcase Never:\n\t\t\taddItem(item);\n\t\t\tbreak;\n\t\tcase Inheret:\n\t\t\taddItem(item);\n\t\t\treturn;\n\t\t}\n\t\tif(numMins==0)\n\t\t\titem.setExpirationDate(0);\n\t\telse\n\t\t\titem.setExpirationDate(System.currentTimeMillis()+(numMins * TimeManager.MILI_MINUTE));\n\t}\n\n\tprotected void insertItemUpTop(final Item item)\n\t{\n\t\tif((item!=null)&&(!item.amDestroyed()))\n\t\t{\n\t\t\titem.setOwner(this);\n\t\t\tif(!contents.isEmpty())\n\t\t\t\tcontents.add(0,item);\n\t\t\telse\n\t\t\t\tcontents.add(item);\n\t\t\titem.recoverPhyStats();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void addItem(final Item item)\n\t{\n\t\tif((item!=null)&&(!item.amDestroyed()))\n\t\t{\n\t\t\titem.setOwner(this);\n\t\t\tcontents.addElement(item);\n\t\t\titem.recoverPhyStats();\n\t\t}\n\t}\n\n\t@Override\n\tpublic void delItem(final Item item)\n\t{\n\t\tcontents.removeElement(item);\n\t\titem.recoverPhyStats();\n\t}\n\n\t@Override\n\tpublic void delAllItems(final boolean destroy)\n\t{\n\t\tif((destroy)\n\t\t&&(numItems()>0))\n\t\t{\n\t\t\tfinal List<Item> delThese = new LinkedList<Item>();\n\t\t\tdelThese.addAll(contents);\n\t\t\tcontents.clear();\n\t\t\tfor(final Item I : delThese)\n\t\t\t{\n\t\t\t\tif(I!=null)\n\t\t\t\t{\n\t\t\t\t\t// since were deleting you AND all your peers, no need for Item to do it.\n\t\t\t\t\tI.setOwner(null);\n\t\t\t\t\tI.destroy();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tcontents.clear();\n\t}\n\n\t@Override\n\tpublic int numItems()\n\t{\n\t\treturn contents.size();\n\t}\n\n\t@Override\n\tpublic boolean isContent(final Item item)\n\t{\n\t\treturn contents.contains(item);\n\t}\n\n\t@Override\n\tpublic Item getItem(final int i)\n\t{\n\t\ttry\n\t\t{\n\t\t\treturn contents.elementAt(i);\n\t\t}\n\t\tcatch(final java.lang.ArrayIndexOutOfBoundsException x)\n\t\t{\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void eachItem(final EachApplicable<Item> applier)\n\t{\n\t\tfinal List<Item> contents=this.contents;\n\t\tif((contents!=null)&&(!contents.isEmpty()))\n\t\t{\n\t\t\ttry\n\t\t\t{\n\t\t\t\tfor(int a=0;a<contents.size();a++)\n\t\t\t\t{\n\t\t\t\t\tfinal Item I=contents.get(a);\n\t\t\t\t\tif(I!=null)\n\t\t\t\t\t\tapplier.apply(I);\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch(final ArrayIndexOutOfBoundsException e)\n\t\t\t{\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic Item getRandomItem()\n\t{\n\t\tif(numItems()==0)\n\t\t\treturn null;\n\t\treturn getItem(CMLib.dice().roll(1,numItems(),-1));\n\t}\n\n\t@Override\n\tpublic String getContextName(final Environmental E)\n\t{\n\t\tif(E instanceof Exit)\n\t\t{\n\t\t\tfor(int e=0;e<exits.length;e++)\n\t\t\t{\n\t\t\t\tif(exits[e]==E)\n\t\t\t\t\treturn CMLib.directions().getDirectionName(e, CMLib.flags().getDirType(this));\n\t\t\t}\n\t\t\treturn E.Name();\n\t\t}\n\t\telse\n\t\tif(E instanceof MOB)\n\t\t{\n\t\t\tfinal String ctxName=CMLib.english().getContextName(inhabitants,E);\n\t\t\tif(ctxName!=null)\n\t\t\t\treturn ctxName;\n\t\t}\n\t\telse\n\t\tif(E instanceof Item)\n\t\t{\n\t\t\tfinal String ctxName=CMLib.english().getContextName(contents,E);\n\t\t\tif(ctxName!=null)\n\t\t\t\treturn ctxName;\n\t\t}\n\t\telse\n\t\tif(E!=null)\n\t\t\treturn E.name();\n\t\treturn "nothing";\n\t}\n\n\t@Override\n\tpublic PhysicalAgent fetchFromMOBRoomItemExit(final MOB mob, final Item goodLocation, String thingName, final Filterer<Environmental> filter)\n\t{\n\t\tPhysicalAgent found=null;\n\t\tString newThingName=CMLib.lang().preItemParser(thingName);\n\t\tif(newThingName!=null)\n\t\t\tthingName=newThingName;\n\t\tfinal boolean mineOnly=(mob!=null)&&(thingName.toUpperCase().trim().startsWith("MY "));\n\t\tif(mineOnly)\n\t\t\tthingName=thingName.trim().substring(3).trim();\n\t\tif((mob!=null)&&((filter!=Wearable.FILTER_WORNONLY)))\n\t\t{\n\t\t\tfound=mob.fetchItem(goodLocation, new Filterer<Environmental>()\n\t\t\t{\n\t\t\t\t@Override\n\t\t\t\tpublic boolean passesFilter(final Environmental obj)\n\t\t\t\t{\n\t\t\t\t\treturn filter.passesFilter(obj) && Wearable.FILTER_UNWORNONLY.passesFilter(obj);\n\t\t\t\t}\n\t\t\t}, thingName);\n\t\t}\n\t\tif((found==null)&&(!mineOnly))\n\t\t{\n\t\t\tfound=(Exit)CMLib.english().fetchEnvironmental(Arrays.asList(exits),thingName,true);\n\t\t\tif(found==null)\n\t\t\t\tfound=CMLib.english().fetchAvailableItem(contents,thingName,goodLocation,filter,true);\n\t\t\tif(found==null)\n\t\t\t\tfound=(Exit)CMLib.english().fetchEnvironmental(Arrays.asList(exits),thingName,false);\n\t\t\tif(found==null)\n\t\t\t\tfound=CMLib.english().fetchAvailableItem(contents,thingName,goodLocation,filter,false);\n\n\t\t\tif((found instanceof Item)  // the smurfy well/gate exception\n\t\t\t&&(goodLocation==null)\n\t\t\t&&(found.displayText().length()==0)\n\t\t\t&&(thingName.indexOf(\'.\')<0))\n\t\t\t{\n\t\t\t\tPhysicalAgent visibleItem=null;\n\t\t\t\tvisibleItem=(Exit)CMLib.english().fetchEnvironmental(Arrays.asList(exits),thingName,false);\n\t\t\t\tif(visibleItem==null)\n\t\t\t\t\tvisibleItem=fetchFromMOBRoomItemExit(null,null,thingName+".2",filter);\n\t\t\t\tif(visibleItem!=null)\n\t\t\t\t\tfound=visibleItem;\n\t\t\t}\n\n\t\t\tif((found!=null)&&(CMLib.flags().canBeSeenBy(found,mob)))\n\t\t\t\treturn found;\n\t\t\twhile((found!=null)&&(!CMLib.flags().canBeSeenBy(found,mob)))\n\t\t\t{\n\t\t\t\tnewThingName=CMLib.english().bumpDotContextNumber(thingName,1);\n\t\t\t\tif(!newThingName.equals(thingName))\n\t\t\t\t{\n\t\t\t\t\tthingName=newThingName;\n\t\t\t\t\tfound=fetchFromRoomFavorItems(goodLocation, thingName);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tfound=null;\n\t\t\t}\n\t\t}\n\t\tif((mob!=null)&&(found==null)&&((filter!=Wearable.FILTER_UNWORNONLY)))\n\t\t{\n\t\t\tfound=mob.fetchItem(null, new Filterer<Environmental>()\n\t\t\t{\n\t\t\t\t@Override\n\t\t\t\tpublic boolean passesFilter(final Environmental obj)\n\t\t\t\t{\n\t\t\t\t\treturn filter.passesFilter(obj) && Wearable.FILTER_WORNONLY.passesFilter(obj);\n\t\t\t\t}\n\t\t\t}, thingName);\n\t\t}\n\t\tif(found==null)\n\t\t{\n\t\t\tnewThingName=CMLib.lang().failedItemParser(thingName);\n\t\t\tif(newThingName!=null)\n\t\t\t\treturn fetchFromMOBRoomItemExit(mob,goodLocation,newThingName,filter);\n\t\t}\n\t\treturn found;\n\t}\n\n\t@Override\n\tpublic PhysicalAgent fetchFromRoomFavorItems(final Item goodLocation, String thingName)\n\t{\n\t\t// def was Wearable.FILTER_UNWORNONLY;\n\t\tString newThingName=CMLib.lang().preItemParser(thingName);\n\t\tif(newThingName!=null)\n\t\t\tthingName=newThingName;\n\t\tPhysicalAgent found=null;\n\t\tfinal int[] contextNumber=new int[]{0};\n\t\tif(!contents.isEmpty())\n\t\t\tfound=(PhysicalAgent)CMLib.english().fetchAvailable(contents,thingName,goodLocation,Wearable.FILTER_ANY,true,contextNumber);\n\t\tif(found==null)\n\t\t\tfound=(PhysicalAgent)CMLib.english().fetchAvailable(Arrays.asList(exits),thingName,goodLocation,Wearable.FILTER_ANY,true,contextNumber);\n\t\tif((found==null)&&(!inhabitants.isEmpty()))\n\t\t\tfound=(PhysicalAgent)CMLib.english().fetchAvailable(inhabitants,thingName,goodLocation,Wearable.FILTER_ANY,true,contextNumber);\n\t\tcontextNumber[0]=0;\n\t\tif((found==null)&&(!contents.isEmpty()))\n\t\t\tfound=(PhysicalAgent)CMLib.english().fetchAvailable(contents,thingName,goodLocation,Wearable.FILTER_ANY,false,contextNumber);\n\t\tif(found==null)\n\t\t\tfound=(PhysicalAgent)CMLib.english().fetchAvailable(Arrays.asList(exits),thingName,goodLocation,Wearable.FILTER_ANY,false,contextNumber);\n\t\tif((found==null)&&(!inhabitants.isEmpty()))\n\t\t\tfound=(PhysicalAgent)CMLib.english().fetchAvailable(inhabitants,thingName,goodLocation,Wearable.FILTER_ANY,false,contextNumber);\n\n\t\tif((found!=null) // the smurfy well exception\n\t\t&&(found instanceof Item)\n\t\t&&(goodLocation==null)\n\t\t&&(found.displayText().length()==0)\n\t\t&&(thingName.indexOf(\'.\')<0))\n\t\t{\n\t\t\tfinal PhysicalAgent visibleItem=fetchFromRoomFavorItems(null,thingName+".2");\n\t\t\tif(visibleItem!=null)\n\t\t\t\tfound=visibleItem;\n\t\t}\n\t\tif(found==null)\n\t\t{\n\t\t\tnewThingName=CMLib.lang().failedItemParser(thingName);\n\t\t\tif(newThingName!=null)\n\t\t\t\treturn fetchFromRoomFavorItems(goodLocation,newThingName);\n\t\t}\n\t\treturn found;\n\t}\n\n\t@Override\n\tpublic PhysicalAgent fetchFromRoomFavorExits(String thingName)\n\t{\n\t\tString newThingName=CMLib.lang().preItemParser(thingName);\n\t\tif(newThingName!=null)\n\t\t\tthingName=newThingName;\n\t\tfinal Item goodLocation=null;\n\t\tPhysicalAgent found=null;\n\t\tfinal int dirCode = CMLib.directions().getGoodDirectionCode(thingName);\n\t\tfinal int[] contextNumber=new int[]{0};\n\t\tif(dirCode>=0)\n\t\t\tfound=getRoomInDir(dirCode);\n\t\tif(found==null)\n\t\t\tfound=(PhysicalAgent)CMLib.english().fetchAvailable(Arrays.asList(exits),thingName,goodLocation,Wearable.FILTER_ANY,true,contextNumber);\n\t\tif((found==null)&&(!contents.isEmpty()))\n\t\t\tfound=(PhysicalAgent)CMLib.english().fetchAvailable(contents,thingName,goodLocation,Wearable.FILTER_ANY,true,contextNumber);\n\t\tif((found==null)&&(!inhabitants.isEmpty()))\n\t\t\tfound=(PhysicalAgent)CMLib.english().fetchAvailable(inhabitants,thingName,goodLocation,Wearable.FILTER_ANY,true,contextNumber);\n\t\tcontextNumber[0]=0;\n\t\tif(found==null)\n\t\t\tfound=(PhysicalAgent)CMLib.english().fetchAvailable(Arrays.asList(exits),thingName,goodLocation,Wearable.FILTER_ANY,false,contextNumber);\n\t\tif((found==null)&&(!contents.isEmpty()))\n\t\t\tfound=(PhysicalAgent)CMLib.english().fetchAvailable(contents,thingName,goodLocation,Wearable.FILTER_ANY,false,contextNumber);\n\t\tif((found==null)&&(!inhabitants.isEmpty()))\n\t\t\tfound=(PhysicalAgent)CMLib.english().fetchAvailable(inhabitants,thingName,goodLocation,Wearable.FILTER_ANY,false,contextNumber);\n\t\tif(found==null)\n\t\t{\n\t\t\tnewThingName=CMLib.lang().failedItemParser(thingName);\n\t\t\tif(newThingName!=null)\n\t\t\t\treturn fetchFromRoomFavorMOBs(goodLocation,newThingName);\n\t\t}\n\t\treturn found;\n\t}\n\n\t@Override\n\tpublic PhysicalAgent fetchFromRoomFavorMOBs(final Item goodLocation, String thingName)\n\t{\n\t\t// def was Wearable.FILTER_UNWORNONLY;\n\t\tString newThingName=CMLib.lang().preItemParser(thingName);\n\t\tif(newThingName!=null)\n\t\t\tthingName=newThingName;\n\t\tfinal int[] contextNumber = new int[]{0};\n\t\tPhysicalAgent found=null;\n\t\tif(!inhabitants.isEmpty())\n\t\t\tfound=(PhysicalAgent)CMLib.english().fetchAvailable(inhabitants,thingName,goodLocation,Wearable.FILTER_ANY,true,contextNumber);\n\t\tif((found==null)&&(!contents.isEmpty()))\n\t\t\tfound=(PhysicalAgent)CMLib.english().fetchAvailable(contents,thingName,goodLocation,Wearable.FILTER_ANY,true,contextNumber);\n\t\tif(found==null)\n\t\t\tfound=(PhysicalAgent)CMLib.english().fetchAvailable(Arrays.asList(exits),thingName,goodLocation,Wearable.FILTER_ANY,true,contextNumber);\n\t\tcontextNumber[0]=0;\n\t\tif((found==null)&&(!inhabitants.isEmpty()))\n\t\t\tfound=(PhysicalAgent)CMLib.english().fetchAvailable(inhabitants,thingName,goodLocation,Wearable.FILTER_ANY,false,contextNumber);\n\t\tif((found==null)&&(!contents.isEmpty()))\n\t\t\tfound=(PhysicalAgent)CMLib.english().fetchAvailable(contents,thingName,goodLocation,Wearable.FILTER_ANY,false,contextNumber);\n\t\tif(found==null)\n\t\t\tfound=(PhysicalAgent)CMLib.english().fetchAvailable(Arrays.asList(exits),thingName,goodLocation,Wearable.FILTER_ANY,false,contextNumber);\n\t\tif(found==null)\n\t\t{\n\t\t\tnewThingName=CMLib.lang().failedItemParser(thingName);\n\t\t\tif(newThingName!=null)\n\t\t\t\treturn fetchFromRoomFavorMOBs(goodLocation,newThingName);\n\t\t}\n\t\treturn found;\n\t}\n\n\t@Override\n\tpublic PhysicalAgent fetchFromMOBRoomFavorsItems(final MOB mob, final Item goodLocation, final String thingName, final Filterer<Environmental> filter)\n\t{\n\t\treturn fetchFromMOBRoom(mob,goodLocation,thingName,filter,true);\n\t}\n\n\t@Override\n\tpublic PhysicalAgent fetchFromMOBRoomFavorsMOBs(final MOB mob, final Item goodLocation, final String thingName, final Filterer<Environmental> filter)\n\t{\n\t\treturn fetchFromMOBRoom(mob,goodLocation,thingName,filter,false);\n\t}\n\n\tprivate PhysicalAgent fetchFromMOBRoom(final MOB mob, final Item goodLocation, String thingName, final Filterer<Environmental> filter, final boolean favorItems)\n\t{\n\t\tPhysicalAgent found=null;\n\t\tString newThingName=CMLib.lang().preItemParser(thingName);\n\t\tif(newThingName!=null)\n\t\t\tthingName=newThingName;\n\t\tfinal boolean mineOnly=(mob!=null)&&(thingName.toUpperCase().trim().startsWith("MY "));\n\t\tif(mineOnly)\n\t\t\tthingName=thingName.trim().substring(3).trim();\n\t\tif((mob!=null)&&(favorItems)&&(filter!=Wearable.FILTER_WORNONLY))\n\t\t{\n\t\t\tfinal Filterer<Environmental> mobCheckFilter = new Filterer<Environmental>()\n\t\t\t{\n\t\t\t\t@Override\n\t\t\t\tpublic boolean passesFilter(final Environmental obj)\n\t\t\t\t{\n\t\t\t\t\treturn filter.passesFilter(obj) && Wearable.FILTER_UNWORNONLY.passesFilter(obj);\n\t\t\t\t}\n\t\t\t};\n\t\t\tfound=mob.fetchItem(goodLocation, mobCheckFilter, thingName);\n\t\t\tif(found == null) // smurfy well exception -- see below -- this is under favorItems and !wornonly\n\t\t\t{\n\t\t\t\t// this ugliness allows you do use dot syntax on things on the ground when you have SOME stuff in inventory, but not much\n\t\t\t\tfinal int dotNumber=CMLib.english().getContextDotNumber(thingName);\n\t\t\t\tif(dotNumber > 1)\n\t\t\t\t{\n\t\t\t\t\tString testThingName =  CMLib.english().bumpDotContextNumber(thingName, -(dotNumber-1));\n\t\t\t\t\tint numMobHas = 0;\n\t\t\t\t\tfor(int i=1;i<=dotNumber;i++)\n\t\t\t\t\t{\n\t\t\t\t\t\tif(mob.fetchItem(goodLocation, mobCheckFilter, testThingName)==null)\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tnumMobHas++;\n\t\t\t\t\t\ttestThingName =  CMLib.english().bumpDotContextNumber(testThingName, 1);\n\t\t\t\t\t}\n\t\t\t\t\tif(dotNumber > numMobHas)\n\t\t\t\t\t{\n\t\t\t\t\t\tfinal int curDotNumber=numMobHas+1;\n\t\t\t\t\t\tfinal int delta = -(curDotNumber-1) + (dotNumber-numMobHas-1);\n\t\t\t\t\t\ttestThingName =  CMLib.english().bumpDotContextNumber(testThingName, delta);\n\t\t\t\t\t\tfound = fetchFromRoomFavorItems(goodLocation, testThingName);\n\t\t\t\t\t\tif((found != null)\n\t\t\t\t\t\t&&((filter==null)||(filter.passesFilter(found))))\n\t\t\t\t\t\t\treturn found;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif((found==null)&&(!mineOnly))\n\t\t{\n\t\t\tif(favorItems)\n\t\t\t\tfound=fetchFromRoomFavorItems(goodLocation, thingName);\n\t\t\telse\n\t\t\t\tfound=fetchFromRoomFavorMOBs(goodLocation, thingName);\n\t\t\tif((found!=null)\n\t\t\t&&(CMLib.flags().canBeSeenBy(found,mob)))\n\t\t\t\treturn found;\n\t\t\twhile((found!=null)&&(!CMLib.flags().canBeSeenBy(found,mob)))\n\t\t\t{\n\t\t\t\tnewThingName=CMLib.english().bumpDotContextNumber(thingName,1);\n\t\t\t\tif(!newThingName.equals(thingName))\n\t\t\t\t{\n\t\t\t\t\tthingName=newThingName;\n\t\t\t\t\tif(favorItems)\n\t\t\t\t\t\tfound=fetchFromRoomFavorItems(goodLocation, thingName);\n\t\t\t\t\telse\n\t\t\t\t\t\tfound=fetchFromRoomFavorMOBs(goodLocation, thingName);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t\tfound=null;\n\t\t\t}\n\t\t}\n\t\tif((mob!=null)&&(!favorItems)&&(filter!=Wearable.FILTER_WORNONLY))\n\t\t{\n\t\t\tfound=mob.fetchItem(goodLocation, new Filterer<Environmental>()\n\t\t\t{\n\t\t\t\t@Override\n\t\t\t\tpublic boolean passesFilter(final Environmental obj)\n\t\t\t\t{\n\t\t\t\t\treturn filter.passesFilter(obj) && Wearable.FILTER_UNWORNONLY.passesFilter(obj);\n\t\t\t\t}\n\t\t\t}, thingName);\n\t\t}\n\t\tif((mob!=null)&&(found==null)&&(filter!=Wearable.FILTER_UNWORNONLY))\n\t\t{\n\t\t\tfound=mob.fetchItem(null, new Filterer<Environmental>()\n\t\t\t{\n\t\t\t\t@Override\n\t\t\t\tpublic boolean passesFilter(final Environmental obj)\n\t\t\t\t{\n\t\t\t\t\treturn filter.passesFilter(obj) && Wearable.FILTER_WORNONLY.passesFilter(obj);\n\t\t\t\t}\n\t\t\t}, thingName);\n\t\t}\n\t\tif((mob!=null)&&(found==null))\n\t\t\tfound=mob.fetchItem(goodLocation,filter,thingName);\n\t\tif(found==null)\n\t\t{\n\t\t\tfinal Directions.DirType dirType=CMLib.flags().getDirType(this);\n\t\t\tfor(int d=0;d<exits.length;d++)\n\t\t\t{\n\t\t\t\tif((exits[d]!=null)\n\t\t\t\t&&(thingName.equalsIgnoreCase(CMLib.directions().getDirectionName(d,dirType))))\n\t\t\t\t\treturn getExitInDir(d);\n\t\t\t}\n\t\t}\n\t\tif(found==null)\n\t\t{\n\t\t\tnewThingName=CMLib.lang().failedItemParser(thingName);\n\t\t\tif(newThingName!=null)\n\t\t\t\treturn fetchFromMOBRoom(mob,goodLocation,newThingName,filter,favorItems);\n\t\t}\n\t\treturn found;\n\t}\n\n\t@Override\n\tpublic int pointsPerMove()\n\t{\n\t\treturn getArea().getClimateObj().adjustMovement(getMovementCost(),this);\n\t}\n\n\tprotected int baseThirst()\n\t{\n\t\treturn 1;\n\t}\n\n\t@Override\n\tpublic int thirstPerRound()\n\t{\n\t\tfinal int derivedClimate=getClimateType();\n\t\tint adjustment=0;\n\t\tif(CMath.bset(derivedClimate, Places.CLIMASK_HOT))\n\t\t\tadjustment+=1;\n\t\tif(CMath.bset(derivedClimate, Places.CLIMASK_WET))\n\t\t\tadjustment-=1;\n\t\tif(CMath.bset(derivedClimate, Places.CLIMASK_DRY))\n\t\t\tadjustment+=1;\n\t\tif(CMath.bset(derivedClimate, Places.CLIMASK_WINDY))\n\t\t\tadjustment+=1;\n\t\tif(getArea().getClimateObj()!=null)\n\t\t\treturn getArea().getClimateObj().adjustWaterConsumption(baseThirst()+adjustment,this);\n\t\treturn 0;\n\t}\n\n\t@Override\n\tpublic int minRange()\n\t{\n\t\treturn Integer.MIN_VALUE;\n\t}\n\n\t@Override\n\tpublic int maxRange()\n\t{\n\t\treturn phyStats().height();\n\t}\n\n\t@Override\n\tpublic void addEffect(final Ability to)\n\t{\n\t\tif(to==null)\n\t\t\treturn;\n\t\tif(fetchEffect(to.ID())!=null)\n\t\t\treturn;\n\t\tif(affects==null)\n\t\t\taffects=new SVector<Ability>(1);\n\t\tif(affects.contains(to))\n\t\t\treturn;\n\t\taffects.addElement(to);\n\t\tto.setAffectedOne(this);\n\t}\n\n\t@Override\n\tpublic void addNonUninvokableEffect(final Ability to)\n\t{\n\t\tif(to==null)\n\t\t\treturn;\n\t\tif(fetchEffect(to.ID())!=null)\n\t\t\treturn;\n\t\tif(affects==null)\n\t\t\taffects=new SVector<Ability>(1);\n\t\tto.makeNonUninvokable();\n\t\tto.makeLongLasting();\n\t\taffects.addElement(to);\n\t\tto.setAffectedOne(this);\n\t}\n\n\t@Override\n\tpublic void delEffect(final Ability to)\n\t{\n\t\tif(affects==null)\n\t\t\treturn;\n\t\tif(affects.remove(to))\n\t\t{\n\t\t\tto.setAffectedOne(null);\n\t\t\tif(affects.isEmpty())\n\t\t\t\taffects=new SVector<Ability>(1);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void eachEffect(final EachApplicable<Ability> applier)\n\t{\n\t\tfinal List<Ability> affects=this.affects;\n\t\tif((affects!=null)&&(!affects.isEmpty()))\n\t\ttry\n\t\t{\n\t\t\tfor(int a=0;a<affects.size();a++)\n\t\t\t{\n\t\t\t\tfinal Ability A=affects.get(a);\n\t\t\t\tif(A!=null)\n\t\t\t\t\tapplier.apply(A);\n\t\t\t}\n\t\t}\n\t\tcatch(final ArrayIndexOutOfBoundsException e)\n\t\t{\n\t\t}\n\t}\n\n\t@Override\n\tpublic void delAllEffects(final boolean unInvoke)\n\t{\n\t\tif(affects==null)\n\t\t\treturn;\n\t\tfor(int a=numEffects()-1;a>=0;a--)\n\t\t{\n\t\t\tfinal Ability A=fetchEffect(a);\n\t\t\tif(A!=null)\n\t\t\t{\n\t\t\t\tif(unInvoke)\n\t\t\t\t\tA.unInvoke();\n\t\t\t\tA.setAffectedOne(null);\n\t\t\t}\n\t\t}\n\t\taffects=new SVector<Ability>(1);\n\t}\n\n\t@Override\n\tpublic int numEffects()\n\t{\n\t\tif(affects==null)\n\t\t\treturn 0;\n\t\treturn affects.size();\n\t}\n\n\t@SuppressWarnings("unchecked")\n\n\t@Override\n\tpublic Enumeration<Ability> effects()\n\t{\n\t\treturn (affects==null)?EmptyEnumeration.INSTANCE:affects.elements();\n\t}\n\n\t@Override\n\tpublic Ability fetchEffect(final int index)\n\t{\n\t\tif(affects==null)\n\t\t\treturn null;\n\t\ttry\n\t\t{\n\t\t\treturn affects.elementAt(index);\n\t\t}\n\t\tcatch(final java.lang.ArrayIndexOutOfBoundsException x)\n\t\t{\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Ability fetchEffect(final String ID)\n\t{\n\t\tif(affects==null)\n\t\t\treturn null;\n\t\tfor(final Enumeration<Ability> a=effects();a.hasMoreElements();)\n\t\t{\n\t\t\tfinal Ability A=a.nextElement();\n\t\t\tif(A.ID().equals(ID))\n\t\t\t\treturn A;\n\t\t}\n\t\treturn null;\n\t}\n\n\t/** Manipulation of Behavior objects, which includes\n\t * movement, speech, spellcasting, etc, etc.*/\n\t@Override\n\tpublic void addBehavior(final Behavior to)\n\t{\n\t\tif(to==null)\n\t\t\treturn;\n\t\tif(behaviors==null)\n\t\t\tbehaviors=new SVector<Behavior>(1);\n\t\tfor(final Behavior B : behaviors)\n\t\t{\n\t\t\tif(B.ID().equals(to.ID()))\n\t\t\t\treturn;\n\t\t}\n\t\tif(behaviors.isEmpty())\n\t\t\tCMLib.threads().startTickDown(this,Tickable.TICKID_ROOM_BEHAVIOR,1);\n\t\tto.startBehavior(this);\n\t\tbehaviors.addElement(to);\n\t}\n\n\t@Override\n\tpublic void delBehavior(final Behavior to)\n\t{\n\t\tif(behaviors==null)\n\t\t\treturn;\n\t\tif(behaviors.remove(to))\n\t\t{\n\t\t\tto.endBehavior(this);\n\t\t\tif(behaviors.isEmpty())\n\t\t\t\tbehaviors=new SVector<Behavior>(1);\n\t\t\tif(((behaviors==null)||(behaviors.isEmpty()))&&((scripts==null)||(scripts.isEmpty())))\n\t\t\t\tCMLib.threads().deleteTick(this,Tickable.TICKID_ROOM_BEHAVIOR);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void delAllBehaviors()\n\t{\n\t\tfinal boolean didSomething=(behaviors!=null)&&(!behaviors.isEmpty());\n\t\tif(didSomething)\n\t\t\tbehaviors.clear();\n\t\tbehaviors=null;\n\t\tif(didSomething && ((scripts==null)||(scripts.isEmpty())))\n\t\t\tCMLib.threads().deleteTick(this,Tickable.TICKID_ROOM_BEHAVIOR);\n\t}\n\n\t@Override\n\tpublic int numBehaviors()\n\t{\n\t\tif(behaviors==null)\n\t\t\treturn 0;\n\t\treturn behaviors.size();\n\t}\n\n\t@SuppressWarnings("unchecked")\n\n\t@Override\n\tpublic Enumeration<Behavior> behaviors()\n\t{\n\t\treturn (behaviors==null)?EmptyEnumeration.INSTANCE:behaviors.elements();\n\t}\n\n\t@Override\n\tpublic Behavior fetchBehavior(final int index)\n\t{\n\t\tif(behaviors==null)\n\t\t\treturn null;\n\t\ttry\n\t\t{\n\t\t\treturn behaviors.elementAt(index);\n\t\t}\n\t\tcatch(final java.lang.ArrayIndexOutOfBoundsException x)\n\t\t{\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic Behavior fetchBehavior(final String ID)\n\t{\n\t\tif(behaviors==null)\n\t\t\treturn null;\n\t\tfor(final Behavior B : behaviors)\n\t\t{\n\t\t\tif(B.ID().equalsIgnoreCase(ID))\n\t\t\t\treturn B;\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void eachBehavior(final EachApplicable<Behavior> applier)\n\t{\n\t\tfinal List<Behavior> behaviors=this.behaviors;\n\t\tif((behaviors!=null)&&(!behaviors.isEmpty()))\n\t\ttry\n\t\t{\n\t\t\tfor(int a=0;a<behaviors.size();a++)\n\t\t\t{\n\t\t\t\tfinal Behavior B=behaviors.get(a);\n\t\t\t\tif(B!=null)\n\t\t\t\t\tapplier.apply(B);\n\t\t\t}\n\t\t}\n\t\tcatch(final ArrayIndexOutOfBoundsException e)\n\t\t{\n\t\t}\n\t}\n\n\t/** Manipulation of the scripts list */\n\t@Override\n\tpublic void addScript(final ScriptingEngine S)\n\t{\n\t\tif(scripts==null)\n\t\t\tscripts=new SVector<ScriptingEngine>(1);\n\t\tif(S==null)\n\t\t\treturn;\n\t\tif(!scripts.contains(S))\n\t\t{\n\t\t\tfor(final Enumeration<ScriptingEngine> s2=scripts();s2.hasMoreElements();)\n\t\t\t{\n\t\t\t\tfinal ScriptingEngine S2=s2.nextElement();\n\t\t\t\tif(S2.getScript().equalsIgnoreCase(S.getScript()))\n\t\t\t\t\treturn;\n\t\t\t}\n\t\t\tif(scripts.isEmpty())\n\t\t\t\tCMLib.threads().startTickDown(this,Tickable.TICKID_ROOM_BEHAVIOR,1);\n\t\t\tscripts.addElement(S);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void delScript(final ScriptingEngine S)\n\t{\n\t\tif(scripts!=null)\n\t\t{\n\t\t\tif(scripts.remove(S))\n\t\t\t{\n\t\t\t\tif(scripts.isEmpty())\n\t\t\t\t\tscripts=new SVector<ScriptingEngine>(1);\n\t\t\t\tif(((behaviors==null)||(behaviors.isEmpty()))&&((scripts==null)||(scripts.isEmpty())))\n\t\t\t\t\tCMLib.threads().deleteTick(this,Tickable.TICKID_ROOM_BEHAVIOR);\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void delAllScripts()\n\t{\n\t\tfinal boolean didSomething=(scripts!=null)&&(!scripts.isEmpty());\n\t\tif(didSomething)\n\t\t\tscripts.clear();\n\t\tscripts=null;\n\t\tif(didSomething && ((behaviors==null)||(behaviors.isEmpty())))\n\t\t\tCMLib.threads().deleteTick(this,Tickable.TICKID_ROOM_BEHAVIOR);\n\t}\n\n\t@Override\n\tpublic int numScripts()\n\t{\n\t\treturn (scripts==null)?0:scripts.size();\n\t}\n\n\t@SuppressWarnings("unchecked")\n\n\t@Override\n\tpublic Enumeration<ScriptingEngine> scripts()\n\t{\n\t\treturn (scripts==null)?EmptyEnumeration.INSTANCE:scripts.elements();\n\t}\n\n\t@Override\n\tpublic ScriptingEngine fetchScript(final int x)\n\t{\n\t\ttry\n\t\t{\n\t\t\treturn scripts.elementAt(x);\n\t\t}\n\t\tcatch (final Exception e)\n\t\t{\n\t\t}\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void eachScript(final EachApplicable<ScriptingEngine> applier)\n\t{\n\t\tfinal List<ScriptingEngine> scripts=this.scripts;\n\t\tif((scripts!=null)&&(!scripts.isEmpty()))\n\t\ttry\n\t\t{\n\t\t\tfor(int a=0;a<scripts.size();a++)\n\t\t\t{\n\t\t\t\tfinal ScriptingEngine S=scripts.get(a);\n\t\t\t\tif(S!=null)\n\t\t\t\t\tapplier.apply(S);\n\t\t\t}\n\t\t}\n\t\tcatch(final ArrayIndexOutOfBoundsException e)\n\t\t{\n\t\t}\n\t}\n\n\t@Override\n\tpublic String L(final String str, final String... xs)\n\t{\n\t\treturn CMLib.lang().fullSessionTranslation(str, xs);\n\t}\n\n\t@Override\n\tpublic int getSaveStatIndex()\n\t{\n\t\treturn (xtraValues == null) ? getStatCodes().length : getStatCodes().length - xtraValues.length;\n\t}\n\n\tprotected static final String[]\tSTDCODES\t= { "CLASS", "DISPLAY", "DESCRIPTION", "TEXT", "AFFBEHAV", "IMAGE", "CLIMATE", "ATMOSPHERE", "ROOMID" };\n\tprivate static String[]\t\t\tcodes\t\t= null;\n\n\t@Override\n\tpublic String[] getStatCodes()\n\t{\n\t\tif (codes == null)\n\t\t\tcodes = CMProps.getStatCodesList(STDCODES, this);\n\t\treturn codes;\n\t}\n\n\t@Override\n\tpublic boolean isStat(final String code)\n\t{\n\t\treturn CMParms.indexOf(getStatCodes(), code.toUpperCase().trim()) >= 0;\n\t}\n\n\tprotected int getCodeNum(final String code)\n\t{\n\t\treturn CMParms.indexOf(codes, code.toUpperCase());\n\t}\n\n\t@Override\n\tpublic String getStat(final String code)\n\t{\n\t\tswitch (getCodeNum(code))\n\t\t{\n\t\tcase 0:\n\t\t\treturn CMClass.classID(this);\n\t\tcase 1:\n\t\t\treturn displayText();\n\t\tcase 2:\n\t\t\treturn description();\n\t\tcase 3:\n\t\t\treturn text();\n\t\tcase 4:\n\t\t\treturn CMLib.coffeeMaker().getExtraEnvironmentalXML(this);\n\t\tcase 5:\n\t\t\treturn rawImage();\n\t\tcase 6:\n\t\t\treturn "" + getClimateTypeCode();\n\t\tcase 7:\n\t\t\treturn "" + getAtmosphereCode();\n\t\tcase 8:\n\t\t\treturn ""+CMLib.map().getExtendedRoomID(this);\n\t\tdefault:\n\t\t\treturn CMProps.getStatCodeExtensionValue(getStatCodes(), xtraValues, code);\n\t\t}\n\t}\n\n\t@Override\n\tpublic void setStat(final String code, final String val)\n\t{\n\t\tswitch (getCodeNum(code))\n\t\t{\n\t\tcase 0:\n\t\t\treturn;\n\t\tcase 1:\n\t\t\tsetDisplayText(val);\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tsetDescription(val);\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tsetMiscText(val);\n\t\t\tbreak;\n\t\tcase 4:\n\t\t{\n\t\t\tdelAllEffects(true);\n\t\t\tdelAllBehaviors();\n\t\t\tCMLib.coffeeMaker().unpackExtraEnvironmentalXML(this, CMLib.xml().parseAllXML(val));\n\t\t\tbreak;\n\t\t}\n\t\tcase 5:\n\t\t\tsetImage(val);\n\t\t\tbreak;\n\t\tcase 6:\n\t\t\tsetClimateType((CMath.s_int(val) < 0) ? -1 : CMath.s_parseBitIntExpression(Places.CLIMATE_DESCS, val));\n\t\t\tbreak;\n\t\tcase 7:\n\t\t{\n\t\t\tif (CMath.isMathExpression(val))\n\t\t\t\tsetAtmosphere(CMath.s_parseIntExpression(val));\n\t\t\tfinal int matCode = RawMaterial.CODES.FIND_IgnoreCase(val);\n\t\t\tif (matCode >= 0)\n\t\t\t\tsetAtmosphere(matCode);\n\t\t\tbreak;\n\t\t}\n\t\tcase 8:\n\t\t\tthis.setRoomID(val);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tCMProps.setStatCodeExtensionValue(getStatCodes(), xtraValues, code, val);\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t@Override\n\tpublic boolean sameAs(final Environmental E)\n\t{\n\t\tif (!(E instanceof StdRoom))\n\t\t\treturn false;\n\t\tfinal String[] codes = getStatCodes();\n\t\tfor (int i = 0; i < codes.length; i++)\n\t\t{\n\t\t\tif((!E.getStat(codes[i]).equals(getStat(codes[i])))\n\t\t\t&&(!codes[i].equals("ROOMID"))\n\t\t\t&&(!codes[i].equals("ATMOSPHERE")))\n\t\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n}\n', 'message': '\n\ngit-svn-id: svn://192.168.1.10/public/CoffeeMud@8968 0d6f1817-ed0e-0410-87c9-987e46238f29\n', 'author_name': 'bozimmerman', 'lang': 'java'}