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

/*
   Copyright 2003-2016 Bo Zimmerman

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

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

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

public class WaterCurrents extends ActiveTicker
{
	@Override
	public String ID()
	{
		return "WaterCurrents";
	}

	@Override
	protected int canImproveCode()
	{
		return Behavior.CAN_ROOMS | Behavior.CAN_AREAS;
	}

	protected String	dirs	= "";
	protected boolean	doBoats = false;

	public WaterCurrents()
	{
		super();
		minTicks=3;maxTicks=5;chance=75;
		tickReset();
	}

	@Override
	public String accountForYourself()
	{
		return "water current moving";
	}

	@Override
	public void setParms(String newParms)
	{
		super.setParms(newParms);
		final Vector<String> V=CMParms.parse(newParms);
		dirs="";
		for(int v=0;v<V.size();v++)
		{
			final String str=V.get(v);
			if(str.equalsIgnoreCase("BOATS"))
				this.doBoats=true;
			else
			{
				final int dir=Directions.getGoodDirectionCode(str);
				if(dir>=0)
					dirs=dirs+Directions.getDirectionChar(dir);
			}
		}
		if(dirs.length()==0)
			dirs="NE";
	}
	
	public void applyCurrents(Room R, Vector<Physical> done)
	{
		final Vector<Physical> todo=new Vector<Physical>();
		if((R!=null)&&(R.numInhabitants()>0))
		{
			MOB M=null;
			for(int m=0;m<R.numInhabitants();m++)
			{
				M=R.fetchInhabitant(m);
				if((M!=null)
				&&(!M.isMonster())
				&&(M.riding()==null)
				&&(!CMLib.flags().isInFlight(M))
				&&((!(M instanceof Rideable))||(((Rideable)M).numRiders()==0))
				&&(!M.isInCombat())
				&&(!CMLib.flags().isMobile(M))
				&&(!done.contains(M)))
				{
					todo.addElement(M);
					done.addElement(M);
				}
			}
		}
		if((R!=null)&&(R.numItems()>0))
		{
			Item I=null;
			for(int i=0;i<R.numItems();i++)
			{
				I=R.getItem(i);
				if((I!=null)
				&&(I.container()==null)
				&&((!(I instanceof Rideable))
					||(((Rideable)I).rideBasis()!=Rideable.RIDEABLE_WATER)
					||(((Rideable)I).numRiders()==0)
					||(doBoats))
				&&(!CMLib.flags().isInFlight(I))
				&&(!CMLib.flags().isMobile(I))
				&&((!(I instanceof Exit))||(doBoats))
				&&(!done.contains(I)))
				{
					todo.addElement(I);
					done.addElement(I);
				}
			}
		}
		if((todo.size()>0)&&(R!=null))
		{
			int dir=-1;
			Room R2=null;
			for(int dl=0;dl<dirs.length();dl++)
			{
				dir=Directions.getDirectionCode(""+dirs.charAt(dl));
				if(dir>=0)
				{
					R2=R.getRoomInDir(dir);
					if(R2!=null)
					{
						if((R.getExitInDir(dir)!=null)
						&&(R.getExitInDir(dir).isOpen())
						&&((R2.domainType()==R.domainType())
							||(CMLib.flags().isWateryRoom(R2))))
								break;
						R2=null;
					}
				}
			}
			if(R2!=null)
			{
				MOB M=null;
				Item I=null;
				MOB srcM=CMClass.getFactoryMOB("the water", 1, R2);
				for(int m=0;m<todo.size();m++)
				{
					if(todo.elementAt(m) instanceof MOB)
					{
						M=(MOB)todo.elementAt(m);
						final CMMsg themsg=CMClass.getMsg(srcM,M,new AWaterCurrent(),CMMsg.MSG_OK_ACTION,L("<T-NAME> <T-IS-ARE> swept @x1 by the current.",
								Directions.getDirectionName(dir).toLowerCase()));
						if(R.okMessage(M,themsg))
						{
							R.send(M,themsg);
							R2.bringMobHere(M,false);
							R2.showOthers(srcM,M,new AWaterCurrent(),CMMsg.MSG_OK_ACTION,L("<T-NAME> <T-IS-ARE> swept in from @x1 by the current.",
									Directions.getFromCompassDirectionName(Directions.getOpDirectionCode(dir)).toLowerCase()));
							CMLib.commands().postLook(M,true);
						}
					}
					else
					if(todo.elementAt(m) instanceof Item)
					{
						I=(Item)todo.elementAt(m);
						if(R.show(srcM,I,new AWaterCurrent(),CMMsg.MSG_OK_ACTION,L("@x1 is swept @x2 by the current.",
								I.name(),Directions.getDirectionName(dir).toLowerCase())))
						{
							if(I instanceof BoardableShip)
							{
								for(Enumeration<Room> r = ((BoardableShip)I).getShipArea().getProperMap();r.hasMoreElements();)
								{
									final Room R3=r.nextElement();
									if((R3!=null)&&((R3.domainType()&Room.INDOORS)==0))
										R3.showHappens(CMMsg.MSG_OK_ACTION, L("@x1 is swept @x2 by the current.",I.name(),Directions.getDirectionName(dir).toLowerCase()));
								}
							}
							R2.moveItemTo(I,ItemPossessor.Expire.Player_Drop);
							R2.showOthers(srcM,I,new AWaterCurrent(),CMMsg.MSG_OK_ACTION,L("@x1 is swept in from @x2 by the current.",
									I.name(),Directions.getFromCompassDirectionName(Directions.getOpDirectionCode(dir)).toLowerCase()));
						}
					}
				}
				srcM.destroy();
			}
		}
	}

	@Override
	public boolean tick(Tickable ticking, int tickID)
	{
		super.tick(ticking,tickID);
		if(canAct(ticking,tickID))
		{
			final Vector<Physical> sweeps=new Vector<Physical>();
			if(ticking instanceof Room)
			{
				final Room R=(Room)ticking;
				applyCurrents(R,sweeps);
				final Room below=R.rawDoors()[Directions.DOWN];
				if((below!=null)
				&&(below.roomID().length()==0)
				&&(below instanceof GridLocale)
				&&((below.domainType()==Room.DOMAIN_INDOORS_UNDERWATER)
				   ||(below.domainType()==Room.DOMAIN_OUTDOORS_UNDERWATER)))
				{
					for (final Room R2 : ((GridLocale)below).getAllRooms())
					{
						applyCurrents(R2,sweeps);
					}
				}
			}
			else
			if(ticking instanceof Area)
			{
				for(final Enumeration<Room> r=((Area)ticking).getMetroMap();r.hasMoreElements();)
				{
					final Room R=r.nextElement();
					if(CMLib.flags().isWateryRoom(R))
						applyCurrents(R,sweeps);
				}
			}
		}
		return true;
	}
	protected static final String[] empty={};
	protected static final String[] CODES={"CLASS","TEXT"};
	
	protected static class AWaterCurrent implements Ability, Cloneable
	{
		public AWaterCurrent()
		{
			super();
			// CMClass.bumpCounter(this,CMClass.CMObjectType.ABILITY);//removed
			// for mem & perf
		}

		@Override
		public String ID()
		{
			return "AWaterCurrent";
		}

		@Override
		public String name()
		{
			return "a water current";
		}

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

		@Override
		public String description()
		{
			return "";
		}

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

		protected boolean	savable		= true;
		protected String	miscText	= "";
		protected Physical	affected	= null;

		protected int canAffectCode()
		{
			return 0;
		}

		protected int canTargetCode()
		{
			return 0;
		}

		@Override
		public boolean canTarget(int can_code)
		{
			return false;
		}

		@Override
		public boolean canAffect(int can_code)
		{
			return false;
		}

		@Override
		public double castingTime(final MOB mob, final List<String> cmds)
		{
			return 0.0;
		}

		@Override
		public double combatCastingTime(final MOB mob, final List<String> cmds)
		{
			return 0.0;
		}

		@Override
		public double checkedCastingCost(final MOB mob, final List<String> cmds)
		{
			return 0.0;
		}

		@Override
		public void initializeClass()
		{
		}

		@Override
		public int abilityCode()
		{
			return 0;
		}

		@Override
		public void setAbilityCode(int newCode)
		{
		}

		@Override
		public int adjustedLevel(MOB mob, int asLevel)
		{
			return -1;
		}

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

		@Override
		public ExpertiseLibrary.SkillCost getTrainingCost(MOB mob)
		{
			return CMLib.expertises().createNewSkillCost(ExpertiseLibrary.CostType.TRAIN, Double.valueOf(1.0));
		}

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

		@Override
		public long flags()
		{
			return Ability.FLAG_TRANSPORTING;
		}

		@Override
		public int getTickStatus()
		{
			return Tickable.STATUS_NOT;
		}

		@Override
		public int usageType()
		{
			return 0;
		}

		// protected void finalize(){
		// CMClass.unbumpCounter(this,CMClass.CMObjectType.ABILITY); }//removed
		// for mem & perf
		@Override
		public long expirationDate()
		{
			return 0;
		}

		@Override
		public void setExpirationDate(long time)
		{
		}

		@Override
		public void setName(String newName)
		{
		}

		@Override
		public void setDescription(String newDescription)
		{
		}

		@Override
		public void setDisplayText(String newDisplayText)
		{
		}

		@Override
		public String image()
		{
			return "";
		}

		@Override
		public String rawImage()
		{
			return "";
		}

		@Override
		public void setImage(String newImage)
		{
		}

		@Override
		public MOB invoker()
		{
			return null;
		}

		@Override
		public void setInvoker(MOB mob)
		{
		}

		@Override
		public String[] triggerStrings()
		{
			return empty;
		}

		@Override
		public boolean preInvoke(MOB mob, List<String> commands, Physical givenTarget, boolean auto, int asLevel, int secondsElapsed, double actionsRemaining)
		{
			return true;
		}

		@Override
		public boolean invoke(MOB mob, List<String> commands, Physical target, boolean auto, int asLevel)
		{
			return false;
		}

		@Override
		public boolean invoke(MOB mob, Physical target, boolean auto, int asLevel)
		{
			return false;
		}

		@Override
		public boolean autoInvocation(MOB mob, boolean force)
		{
			return false;
		}

		@Override
		public void unInvoke()
		{
		}

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

		@Override
		public boolean isAutoInvoked()
		{
			return true;
		}

		@Override
		public boolean isNowAnAutoEffect()
		{
			return true;
		}

		@Override
		public List<String> externalFiles()
		{
			return null;
		}

		@Override
		public boolean canBeTaughtBy(MOB teacher, MOB student)
		{
			return false;
		}

		@Override
		public boolean canBePracticedBy(MOB teacher, MOB student)
		{
			return false;
		}

		@Override
		public boolean canBeLearnedBy(MOB teacher, MOB student)
		{
			return false;
		}

		@Override
		public void teach(MOB teacher, MOB student)
		{
		}

		@Override
		public void practice(MOB teacher, MOB student)
		{
		}

		@Override
		public int maxRange()
		{
			return Integer.MAX_VALUE;
		}

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

		@Override
		public void startTickDown(MOB invokerMOB, Physical affected, int tickTime)
		{
			if (affected.fetchEffect(ID()) == null)
				affected.addEffect(this);
		}

		@Override
		public int proficiency()
		{
			return 0;
		}

		@Override
		public void setProficiency(int newProficiency)
		{
		}

		@Override
		public boolean proficiencyCheck(MOB mob, int adjustment, boolean auto)
		{
			return false;
		}

		@Override
		public void helpProficiency(MOB mob, int adjustment)
		{
		}

		@Override
		public Physical affecting()
		{
			return affected;
		}

		@Override
		public void setAffectedOne(Physical P)
		{
			affected = P;
		}

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

		@Override
		public int abstractQuality()
		{
			return Ability.QUALITY_INDIFFERENT;
		}

		@Override
		public int enchantQuality()
		{
			return Ability.QUALITY_INDIFFERENT;
		}

		@Override
		public int castingQuality(MOB mob, Physical target)
		{
			return Ability.QUALITY_INDIFFERENT;
		}

		@Override
		public int classificationCode()
		{
			return Ability.ACODE_PROPERTY;
		}

		@Override
		public boolean isSavable()
		{
			return savable;
		}

		@Override
		public void setSavable(boolean truefalse)
		{
			savable = truefalse;
		}

		protected boolean	amDestroyed	= false;

		@Override
		public void destroy()
		{
			amDestroyed = true;
		}

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

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

		@Override
		public int getSaveStatIndex()
		{
			return getStatCodes().length;
		}

		@Override
		public String[] getStatCodes()
		{
			return CODES;
		}

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

		protected int getCodeNum(String code)
		{
			for(int i=0;i<CODES.length;i++)
			{
				if(code.equalsIgnoreCase(CODES[i]))
					return i;
			}
			return -1;
		}

		@Override
		public String getStat(String code)
		{
			switch(getCodeNum(code))
			{
			case 0:
				return ID();
			case 1:
				return text();
			}
			return "";
		}

		@Override
		public void setStat(String code, String val)
		{
			switch(getCodeNum(code))
			{
			case 0:
				return;
			case 1:
				setMiscText(val);
				break;
			}
		}
		
		@Override
		public boolean sameAs(Environmental E)
		{
			if(!(E instanceof AWaterCurrent))
				return false;
			final String[] codes=getStatCodes();
			for(int i=0;i<codes.length;i++)
			{
				if(!E.getStat(codes[i]).equals(getStat(codes[i])))
					return false;
			}
			return true;
		}

		protected void cloneFix(Ability E)
		{
		}

		@Override
		public CMObject copyOf()
		{
			try
			{
				final AWaterCurrent E=(AWaterCurrent)this.clone();
				//CMClass.bumpCounter(E,CMClass.CMObjectType.ABILITY);//removed for mem & perf
				E.cloneFix(this);
				return E;

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

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

		@Override
		public void setMiscText(String newMiscText)
		{
			miscText = newMiscText;
		}

		@Override
		public String text()
		{
			return miscText;
		}

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

		@Override
		public boolean appropriateToMyFactions(MOB mob)
		{
			return true;
		}

		@Override
		public String accountForYourself()
		{
			return "";
		}

		@Override
		public String requirements(MOB mob)
		{
			return "";
		}

		@Override
		public boolean canAffect(Physical P)
		{
			if((P==null)&&(canAffectCode()==0))
				return true;
			if(P==null)
				return false;
			if((P instanceof MOB)&&((canAffectCode()&Ability.CAN_MOBS)>0))
				return true;
			if((P instanceof Item)&&((canAffectCode()&Ability.CAN_ITEMS)>0))
				return true;
			if((P instanceof Exit)&&((canAffectCode()&Ability.CAN_EXITS)>0))
				return true;
			if((P instanceof Room)&&((canAffectCode()&Ability.CAN_ROOMS)>0))
				return true;
			if((P instanceof Area)&&((canAffectCode()&Ability.CAN_AREAS)>0))
				return true;
			return false;
		}

		@Override
		public boolean canTarget(Physical P)
		{
			return false;
		}

		@Override
		public void affectPhyStats(Physical affected, PhyStats affectableStats)
		{
		}

		@Override
		public void affectCharStats(MOB affectedMob, CharStats affectableStats)
		{
		}

		@Override
		public void affectCharState(MOB affectedMob, CharState affectableMaxState)
		{
		}

		@Override
		public void executeMsg(final Environmental myHost, final CMMsg msg)
		{
			return;
		}

		@Override
		public boolean okMessage(final Environmental myHost, final CMMsg msg)
		{
			return true;
		}

		@Override
		public boolean tick(Tickable ticking, int tickID)
		{
			return true;
		}

		@Override
		public void makeLongLasting()
		{
		}

		@Override
		public void makeNonUninvokable()
		{
		}

		protected static final int[]	cost	= new int[3];

		@Override
		public int[] usageCost(MOB mob, boolean ignoreClassOverride)
		{
			return cost;
		}

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