@Override
	public void executeMsg(Environmental affecting, CMMsg msg)
	{
		super.executeMsg(affecting, msg);
		if(!(affecting instanceof Area))
			return;
		if(!theLawIsEnabled())
			return;

		final Area myArea=(Area)affecting;
		final Law laws=getLaws(affecting,false);
		if(!laws.lawIsActivated())
			return;
		if(msg.source()==null)
			return;
		if (lastAreaName == null) lastAreaName = myArea.Name();

		// the archons pardon
		if((msg.sourceMinor()==CMMsg.TYP_SPEAK)
		&&(msg.sourceMessage()!=null)
		&&(isAnUltimateAuthorityHere(msg.source(),laws)))
		{
			final int x=msg.sourceMessage().toUpperCase().indexOf("I HEREBY PARDON ");
			if(x>0)
			{
				int y=msg.sourceMessage().lastIndexOf('\'');
				if(y<x)
					y=msg.sourceMessage().lastIndexOf('`');
				String name=null;
				if(y>x)
					name=msg.sourceMessage().substring(x+16,y).trim();
				else
					name=msg.sourceMessage().substring(x+16).trim();
				if(name.length()>0)
				for(final LegalWarrant W : laws.warrants())
				{
					if((W.criminal()!=null)&&(CMLib.english().containsString(W.criminal().Name(),name)))
					{
						final Ability A=W.criminal().fetchEffect("Prisoner");
						if(A!=null)
							A.unInvoke();
						if(W.jail()!=W.criminal().location())
						{
							if(W.arrestingOfficer()!=null)
								dismissOfficer(W.arrestingOfficer());
							laws.warrants().remove(W);
						}
						else
						{
							W.setCrime("pardoned");
							W.setOffenses(0);
						}
					}
				}
			}
		}

		if((msg.sourceMinor()==CMMsg.TYP_DEATH)
		&&(msg.tool() instanceof MOB)
		&&(laws.basicCrimes().containsKey("MURDER"))
		&&((!msg.source().isMonster())
			||(!isTroubleMaker(msg.source()))
			||(this.isAnyKindOfOfficer(laws, msg.source()))))
		{
			final MOB criminal=(MOB)msg.tool();
			this.fillOutMurderWarrant(laws, myArea, criminal, msg.source());
			if(criminal.isMonster() && (isAnyKindOfOfficer(laws, msg.source())))
			{
				MOB leaderM = criminal.amUltimatelyFollowing();
				if((leaderM != null) && (leaderM != criminal) && (!leaderM.isMonster()))
					this.fillOutMurderWarrant(laws, myArea, leaderM, msg.source());
			}
			return;
		}

		if(isAnyKindOfOfficer(laws,msg.source())||(isTheJudge(laws,msg.source())))
		{
			if((msg.sourceMinor()==CMMsg.TYP_ENTER)
			&&(msg.target() instanceof Room))
			{
				final Room R=(Room)msg.target();
				MOB M=null;
				for(int m=0;m<R.numInhabitants();m++)
				{
					M=R.fetchInhabitant(m);
					if((M!=null)
					&&(M!=msg.source())
					&&(!isAnyKindOfOfficer(laws,M))
					&&(!isTheJudge(laws,M)))
						testEntryLaw(laws,myArea,M,R);
				}
			}
			return;
		}

		if((msg.source().isMonster())&&(!laws.arrestMobs()))
			return;

		if(!CMLib.flags().isAliveAwakeMobile(msg.source(),true))
			return;

		final Room R=msg.source().location();
		if(R==null)
			return;

		if((msg.tool() instanceof Ability)
		&&(msg.othersMessage()!=null)
		&&((laws.abilityCrimes().containsKey(msg.tool().ID().toUpperCase()))
			||(laws.abilityCrimes().containsKey(CMLib.flags().getAbilityType_((Ability)msg.tool())))
			||(laws.abilityCrimes().containsKey(CMLib.flags().getAbilityDomain((Ability)msg.tool())))))
		{
			String[] info=laws.abilityCrimes().get(msg.tool().ID().toUpperCase());
			if(info==null)
				info=laws.abilityCrimes().get(CMLib.flags().getAbilityType_((Ability)msg.tool()));
			if(info==null)
				info=laws.abilityCrimes().get(CMLib.flags().getAbilityDomain((Ability)msg.tool()));
			fillOutWarrant(msg.source(),
							laws,
							myArea,
							msg.target(),
							info[Law.BIT_CRIMELOCS],
							info[Law.BIT_CRIMEFLAGS],
							info[Law.BIT_CRIMENAME],
							info[Law.BIT_SENTENCE],
							info[Law.BIT_WARNMSG]);
		}

		for(final Enumeration<Ability> a=msg.source().effects();a.hasMoreElements();)
		{
			final Ability A=a.nextElement();
			if((A!=null)
			&&(!A.isAutoInvoked())
			&&((A.canBeUninvoked()||(!msg.source().isMonster())))
			&&((laws.abilityCrimes().containsKey("$"+A.ID().toUpperCase()))
				||(laws.abilityCrimes().containsKey("$"+CMLib.flags().getAbilityType_(A)))
				||(laws.abilityCrimes().containsKey("$"+CMLib.flags().getAbilityDomain(A)))))
			{
				String[] info=laws.abilityCrimes().get("$"+A.ID().toUpperCase());
				if(info==null)
					info=laws.abilityCrimes().get("$"+CMLib.flags().getAbilityType_(A));
				if(info==null)
					info=laws.abilityCrimes().get("$"+CMLib.flags().getAbilityDomain(A));
				fillOutWarrant(msg.source(),
								laws,
								myArea,
								null,
								info[Law.BIT_CRIMELOCS],
								info[Law.BIT_CRIMEFLAGS],
								info[Law.BIT_CRIMENAME],
								info[Law.BIT_SENTENCE],
								info[Law.BIT_WARNMSG]);
			}
		}

		if((CMath.bset(msg.targetMajor(),CMMsg.MASK_MALICIOUS))
		&&(msg.target() instanceof MOB)
		&&(!CMath.bset(msg.sourceMajor(),CMMsg.MASK_ALWAYS))
		&&((msg.tool()==null)
			||(msg.source().isMine(msg.tool()) 
				&& ((!(msg.tool() instanceof DiseaseAffect)) || (((DiseaseAffect)msg.tool()).isMalicious()))))
		&&(msg.target()!=msg.source())
		&&(!msg.target().name().equals(msg.source().name())))
		{
			if(isTheJudge(laws,(MOB)msg.target()))
			{
				if(!msg.source().isMonster())
				{
					for(int i=0;i<R.numInhabitants();i++)
					{
						final MOB M=R.fetchInhabitant(i);
						if((M!=null)
						&&(M!=msg.target())
						&&(M!=msg.source())
						&&(M.getVictim()!=msg.source())
						&&(isAnyKindOfOfficer(laws,M)))
						{
							if(msg.source().amFollowing()==M)
								msg.source().setFollowing(null);
							CMLib.commands().postSay(M,null,L("Ack! Treason! Die!"),false,false);
							M.setVictim(msg.source());
						}
					}
				}
			}
			else
			{
				boolean justResisting=false;
				boolean turnAbout=false;
				final boolean targetIsOfficer=isAnyKindOfOfficer(laws,(MOB)msg.target());
				final String[] assaultInfo=laws.basicCrimes().get("ASSAULT");
				final String[] murderInfo=laws.basicCrimes().get("MURDER");
				if((assaultInfo!=null)&&(murderInfo!=null))
				{
					for(final LegalWarrant W : laws.warrants())
					{
						if(targetIsOfficer
						&&(W.criminal()==msg.source())
						&&(W.arrestingOfficer()!=null)
						&&(W.criminal().location()!=null)
						&&(W.criminal().location().isInhabitant(W.arrestingOfficer())))
							justResisting=true;
						else
						if((!targetIsOfficer)
						&&(W.criminal()==msg.target())
						&&((W.victim()==msg.source())||((msg.source().amFollowing()!=null)&&(W.victim()==msg.source().amFollowing())))
						&&(W.crime().equals(assaultInfo[Law.BIT_CRIMENAME])||W.crime().equals(murderInfo[Law.BIT_CRIMENAME]))
						&&(isStillACrime(W,false)))
							turnAbout=true;
						else
						if((!targetIsOfficer)
						&&(W.victim()==msg.target())
						&&(W.criminal()==msg.source())
						&&(W.crime().equals(murderInfo[Law.BIT_CRIMENAME]))
						&&(isStillACrime(W,false)))
							turnAbout=true;
					}
				}
				if(justResisting)
				{
					if(laws.basicCrimes().containsKey("RESISTINGARREST"))
					{
						final String[] info=laws.basicCrimes().get("RESISTINGARREST");
						fillOutWarrant(msg.source(),
										laws,
										myArea,
										null,
										info[Law.BIT_CRIMELOCS],
										info[Law.BIT_CRIMEFLAGS],
										info[Law.BIT_CRIMENAME],
										info[Law.BIT_SENTENCE],
										info[Law.BIT_WARNMSG]);
					}
				}
				else
				if((!turnAbout)
				&&(assaultInfo!=null)
				&&((msg.source().isMonster())||(!isTroubleMaker((MOB)msg.target()))))
				{
					fillOutWarrant(msg.source(),
									laws,
									myArea,
									msg.target(),
									assaultInfo[Law.BIT_CRIMELOCS],
									assaultInfo[Law.BIT_CRIMEFLAGS],
									assaultInfo[Law.BIT_CRIMENAME],
									assaultInfo[Law.BIT_SENTENCE],
									assaultInfo[Law.BIT_WARNMSG]);
				}
			}
		}

		if((msg.othersCode()!=CMMsg.NO_EFFECT)
		   &&(msg.othersMessage()!=null))
		{
			if((msg.targetMinor()==CMMsg.TYP_GET)
			&&(msg.target() instanceof Item)
			&&(laws.bannedSubstances().size()>0))
			{
				final String rsc=RawMaterial.CODES.NAME(((Item)msg.target()).material()).toUpperCase();
				for(int i=0;i<laws.bannedSubstances().size();i++)
				{
					final List<String> V=laws.bannedSubstances().get(i);
					for(int v=0;v<V.size();v++)
					{
						if((CMLib.english().containsString(msg.target().name(),V.get(v)))
						||rsc.equalsIgnoreCase(V.get(v)))
						{
							final String[] info=laws.bannedBits().get(i);
							fillOutWarrant(msg.source(),
											laws,
											myArea,
											msg.target(),
											info[Law.BIT_CRIMELOCS],
											info[Law.BIT_CRIMEFLAGS],
											info[Law.BIT_CRIMENAME],
											info[Law.BIT_SENTENCE],
											info[Law.BIT_WARNMSG]);
						}
					}
				}

			}
			if(msg.sourceMinor()==CMMsg.TYP_ENTER)
				testEntryLaw(laws,myArea,msg.source(),R);

			for(int i=0;i<laws.otherCrimes().size();i++)
			{
				final List<String> V=laws.otherCrimes().get(i);
				for(int v=0;v<V.size();v++)
				{
					if(CMLib.english().containsString(msg.othersMessage(),V.get(v)))
					{
						final String[] info=laws.otherBits().get(i);
						fillOutWarrant(msg.source(),
										laws,
										myArea,
										msg.target(),
										info[Law.BIT_CRIMELOCS],
										info[Law.BIT_CRIMEFLAGS],
										info[Law.BIT_CRIMENAME],
										info[Law.BIT_SENTENCE],
										info[Law.BIT_WARNMSG]);
					}
				}
			}
		}
	}