@Override
	public boolean okMessage(final Environmental myHost, final CMMsg msg)
	{
		switch(msg.sourceMinor())
		{
		case CMMsg.TYP_HUH:
		case CMMsg.TYP_COMMANDFAIL:
		case CMMsg.TYP_COMMAND:
			break;
		default:
			if(!confirmAreaMessage(msg, true))
				return false;
			break;
		}
		
		if((msg.target() == this)
		&&(msg.tool()!=null)
		&&(msg.tool().ID().equals("AWaterCurrent")))
		{
			if(anchorDown)
				return false;
		}
		else
		if((msg.sourceMinor()==CMMsg.TYP_HUH)
		&&(msg.targetMessage()!=null)
		&&(area == CMLib.map().areaLocation(msg.source())))
		{
			final List<String> cmds=CMParms.parse(msg.targetMessage());
			if(cmds.size()==0)
				return true;
			final String word=cmds.get(0).toUpperCase();
			final String secondWord=(cmds.size()>1) ? cmds.get(1).toUpperCase() : "";
			SailingCommand cmd = (SailingCommand)CMath.s_valueOf(SailingCommand.class, word);
			if((cmd == null)&&(secondWord.length()>0))
				cmd = (SailingCommand)CMath.s_valueOf(SailingCommand.class, word+"_"+secondWord);
			if(cmd != null)
			{
				switch(cmd)
				{
				case TARGET:
				{
					if(cmds.size()==1)
					{
						msg.source().tell(L("You must specify another ship to target."));
						return false;
					}
					final Room thisRoom = (Room)owner();
					if(thisRoom==null)
					{
						msg.source().tell(L("This ship is nowhere to be found!"));
						return false;
					}
					String rest = CMParms.combine(cmds,1);
					Boolean result = startAttack(msg.source(),thisRoom,rest);
					if(result  == Boolean.TRUE)
					{
						if(this.targetedShip != null)
							msg.source().tell(L("You are now targeting @x1.",this.targetedShip.Name()));
						msg.source().tell(getTargetedShipInfo());
					}
					else
					if(result  == Boolean.FALSE)
						return false;
					else
					{
						msg.source().tell(L("You don't see '@x1' here to target",rest));
						return false;
					}
					break;
				}
				case TENDER:
				{
					if(cmds.size()==1)
					{
						msg.source().tell(L("You must specify another ship to offer aboard."));
						return false;
					}
					final Room thisRoom = (Room)owner();
					if(thisRoom==null)
					{
						msg.source().tell(L("This ship is nowhere to be found!"));
						return false;
					}
					if(this.targetedShip!=null)
					{
						msg.source().tell(L("Not while you are in combat!"));
						return false;
					}
					String rest = CMParms.combine(cmds,1);
					final Item I=thisRoom.findItem(rest);
					if((I instanceof GenSailingShip)&&(I!=this)&&(CMLib.flags().canBeSeenBy(I, msg.source())))
					{
						GenSailingShip otherShip = (GenSailingShip)I;
						if(otherShip.targetedShip != null)
						{
							msg.source().tell(L("Not while @x1 is in in combat!",otherShip.Name()));
							return false;
						}
						final MOB mob = CMClass.getFactoryMOB(name(),phyStats().level(),thisRoom);
						try
						{
							mob.setRiding(this);
							mob.basePhyStats().setDisposition(mob.basePhyStats().disposition()|PhyStats.IS_SWIMMING);
							mob.phyStats().setDisposition(mob.phyStats().disposition()|PhyStats.IS_SWIMMING);
							if(otherShip.tenderShip == this)
							{
								if(thisRoom.show(mob, otherShip, CMMsg.MSG_NOISYMOVEMENT, L("<S-NAME> connect(s) her gangplank with <T-NAME>")))
								{
									this.tenderShip = otherShip;
									final BoardableShip myArea=(BoardableShip)this.getShipArea();
									final BoardableShip hisArea=(BoardableShip)otherShip.getShipArea();
									
									final Room hisExitRoom = hisArea.unDock(false);
									final Room myExitRoom = myArea.unDock(false);
									myArea.dockHere(hisExitRoom);
									hisArea.dockHere(myExitRoom);
								}
							}
							else
							{
								if(thisRoom.show(mob, otherShip, CMMsg.MSG_NOISYMOVEMENT, L("<S-NAME> extend(s) her gangplank toward(s) <T-NAME>")))
									this.tenderShip = otherShip;
							}
						}
						finally
						{
							mob.destroy();
						}
					}
					else
					{
						msg.source().tell(L("You don't see the ship '@x1' here to board",rest));
						return false;
					}
					break;
				}
				case SINK:
				{
					if(!CMSecurity.isAllowedEverywhere(msg.source(), CMSecurity.SecFlag.CMDROOMS))
						return true;
					CMMsg damageMsg=CMClass.getMsg(msg.source(), this, CMMsg.MSG_DAMAGE, "SINK!!!");
					damageMsg.setValue(99999);
					this.executeMsg(this, damageMsg);
					return false;
				}
				case AIM:
				{
					final Room thisRoom = (Room)owner();
					if(thisRoom==null)
					{
						msg.source().tell(L("This ship is nowhere to be found!"));
						return false;
					}
					if((!this.amInTacticalMode())
					||(this.targetedShip==null)
					||(!thisRoom.isContent((Item)this.targetedShip)))
					{
						msg.source().tell(L("You ship must be targeting an enemy to aim weapons."));
						return false;
					}
					if(cmds.size()<3)
					{
						msg.source().tell(L("Aim what weapon how far ahead?"));
						msg.source().tell(getTargetedShipInfo());
						return false;
					}
					String leadStr = cmds.remove(cmds.size()-1);
					String weaponStr = CMParms.combine(cmds,1);
					final Room mobR=msg.source().location();
					if((!CMath.isInteger(leadStr))||(CMath.s_int(leadStr)<0))
					{
						if(this.targetedShip!=null)
							msg.source().tell(L("'@x1' is not a valid distance ahead of @x2 to fire.",leadStr,this.targetedShip.name()));
						else
							msg.source().tell(L("'@x1' is not a valid distance.",leadStr));
						return false;
					}
					if(mobR!=null)
					{
						Item I=mobR.findItem(null, weaponStr);
						if((I==null)||(!CMLib.flags().canBeSeenBy(I,msg.source())))
						{
							msg.source().tell(L("You don't see any seige weapon called '@x1' here.",leadStr));
							return false;
						}
						if(!CMLib.combat().isAShipSiegeWeapon(I))
						{
							msg.source().tell(L("@x1 is not a useable siege weapon.",leadStr));
							return false;
						}
						AmmunitionWeapon weapon=(AmmunitionWeapon)I;
						int distance = weapon.maxRange();
						int[] targetCoords = new int[2];
						int leadAmt=0;
						if(this.targetedShip instanceof GenSailingShip)
						{
							targetCoords = ((GenSailingShip)this.targetedShip).getMyCoords();
							int direction = ((GenSailingShip)this.targetedShip).directionFacing;
							if(targetCoords == null)
							{
								msg.source().tell(L("You ship must be targeting an enemy to aim weapons."));
								return false;
							}
							distance = this.getTacticalDistance(this.targetedShip);
							leadAmt = CMath.s_int(leadStr);
							for(int i=0;i<leadAmt;i++)
								targetCoords = Directions.adjustXYByDirections(targetCoords[0], targetCoords[1], direction);
						}
						if((weapon.maxRange() < distance)||(weapon.minRange() > distance))
						{
							msg.source().tell(L("Your target is presently at distance of @x1, but this weapons range is @x2 to @x3.",
												""+distance,""+weapon.minRange(),""+weapon.maxRange()));
							return false;
						}
						if(weapon.requiresAmmunition() 
						&& (weapon.ammunitionCapacity() > 0)
						&& (weapon.ammunitionRemaining() == 0))
						{
							msg.source().tell(L("@x1 needs to be LOADed first.",weapon.Name()));
							return false;
						}
						String timeToFire=""+(CMLib.threads().msToNextTick((Tickable)CMLib.combat(), Tickable.TICKID_SUPPORT|Tickable.TICKID_SOLITARYMASK) / 1000);
						String msgStr=L("<S-NAME> aim(s) <O-NAME> at <T-NAME> (@x1).",""+leadAmt);
						if(msg.source().isMonster() && aimings.contains(weapon))
						{
							msg.source().tell(L("@x1 is already aimed.",weapon.Name()));
							return false;
						}
						CMMsg msg2=CMClass.getMsg(msg.source(), targetedShip, weapon, CMMsg.MSG_NOISYMOVEMENT, msgStr);
						if(mobR.okMessage(msg.source(), msg2))
						{
							this.aimings.removeFirst(weapon);
							this.aimings.add(new Pair<Weapon,int[]>(weapon,targetCoords));
							mobR.send(msg.source(), msg2);
							msg.source().tell(L("@x1 is now aimed and will be fired in @x2 seconds.",I.name(),timeToFire));
						}
					}
					return false;
				}
				case WEIGH_ANCHOR:
				case RAISE_ANCHOR:
				{
					if(!securityCheck(msg.source()))
					{
						msg.source().tell(L("The captain does not permit you."));
						return false;
					}
					if(safetyMove())
					{
						msg.source().tell(L("The ship has moved!"));
						return false;
					}
					final Room R=CMLib.map().roomLocation(this);
					if(!anchorDown)
						msg.source().tell(L("The anchor is already up."));
					else
					if(R!=null)
					{
						CMMsg msg2=CMClass.getMsg(msg.source(), this, null, CMMsg.MSG_NOISYMOVEMENT, L("<S-NAME> raise(s) anchor on <T-NAME>."));
						if((R.okMessage(msg.source(), msg2) && this.okAreaMessage(msg2, true)))
						{
							R.send(msg.source(), msg2);
							anchorDown=false;
						}
					}
					return false;
				}
				case LOWER_ANCHOR:
				{
					if(!securityCheck(msg.source()))
					{
						msg.source().tell(L("The captain does not permit you."));
						return false;
					}
					if(safetyMove())
					{
						msg.source().tell(L("The ship has moved!"));
						return false;
					}
					final Room R=CMLib.map().roomLocation(this);
					if(anchorDown)
						msg.source().tell(L("The anchor is already down."));
					else
					if(R!=null)
					{
						CMMsg msg2=CMClass.getMsg(msg.source(), this, null, CMMsg.MSG_NOISYMOVEMENT, L("<S-NAME> lower(s) anchor on <T-NAME>."));
						if((R.okMessage(msg.source(), msg2) && this.okAreaMessage(msg2, true)))
						{
							R.send(msg.source(), msg2);
							this.sendAreaMessage(msg2, true);
							anchorDown=true;
						}
					}
					return false;
				}
				case STEER:
				{
					if(!securityCheck(msg.source()))
					{
						msg.source().tell(L("The captain does not permit you."));
						return false;
					}
					if(CMLib.flags().isFalling(this) || ((this.subjectToWearAndTear() && (usesRemaining()<=0))))
					{
						msg.source().tell(L("The ship won't seem to move!"));
						return false;
					}
					if(safetyMove())
					{
						msg.source().tell(L("The ship has moved!"));
						return false;
					}
					if((courseDirection >=0)||(courseDirections.size()>0))
					{
						if(!this.amInTacticalMode())
							msg.source().tell(L("Your previous course has been cancelled."));
						courseDirection = -1;
						courseDirections.clear();
					}
					int dir=CMLib.directions().getCompassDirectionCode(secondWord);
					if(dir<0)
					{
						msg.source().tell(L("Steer the ship which direction?"));
						return false;
					}
					final Room R=CMLib.map().roomLocation(this);
					if((R==null)||(msg.source().location()==null))
					{
						msg.source().tell(L("You are nowhere, so you won`t be moving anywhere."));
						return false;
					}
					if(((msg.source().location().domainType()&Room.INDOORS)==Room.INDOORS)
					&&(msg.source().isPlayer()))
					{
						msg.source().tell(L("You must be on deck to steer your ship."));
						return false;
					}
					final String dirName = CMLib.directions().getDirectionName(dir);
					if(!this.amInTacticalMode())
					{
						final Room targetRoom=R.getRoomInDir(dir);
						final Exit targetExit=R.getExitInDir(dir);
						if((targetRoom==null)||(targetExit==null)||(!targetExit.isOpen()))
						{
							msg.source().tell(L("There doesn't look to be anything in that direction."));
							return false;
						}
					}
					else
					{
						directionFacing = getDirectionFacing(dir);
						if(dir == this.directionFacing)
						{
							msg.source().tell(L("Your ship is already sailing @x1.",dirName));
							return false;
						}
					}
					if(anchorDown)
					{
						msg.source().tell(L("The anchor is down, so you won`t be moving anywhere."));
						return false;
					}
					break;
				}
				case SAIL:
				{
					if(!securityCheck(msg.source()))
					{
						msg.source().tell(L("The captain does not permit you."));
						return false;
					}
					if(CMLib.flags().isFalling(this) || ((this.subjectToWearAndTear() && (usesRemaining()<=0))))
					{
						msg.source().tell(L("The ship won't seem to move!"));
						return false;
					}
					if(safetyMove())
					{
						msg.source().tell(L("The ship has moved!"));
						return false;
					}
					if((courseDirection >=0)||(courseDirections.size()>0))
					{
						if(!this.amInTacticalMode())
							msg.source().tell(L("Your previous course has been cancelled."));
						courseDirection = -1;
						courseDirections.clear();
					}
					final Room R=CMLib.map().roomLocation(this);
					if((R==null)||(msg.source().location()==null))
					{
						msg.source().tell(L("You are nowhere, so you won`t be moving anywhere."));
						return false;
					}
					if(((msg.source().location().domainType()&Room.INDOORS)==Room.INDOORS)
					&&(msg.source().isPlayer()))
					{
						msg.source().tell(L("You must be on deck to sail your ship."));
						return false;
					}
					int dir=CMLib.directions().getCompassDirectionCode(secondWord);
					if(dir<0)
					{
						msg.source().tell(L("Sail the ship which direction?"));
						return false;
					}
					if(!this.amInTacticalMode())
					{
						final Room targetRoom=R.getRoomInDir(dir);
						final Exit targetExit=R.getExitInDir(dir);
						if((targetRoom==null)||(targetExit==null)||(!targetExit.isOpen()))
						{
							msg.source().tell(L("There doesn't look to be anything in that direction."));
							return false;
						}
					}
					else
					{
						String dirName = CMLib.directions().getDirectionName(directionFacing);
						directionFacing = getDirectionFacing(dir);
						if(dir != this.directionFacing)
						{
							msg.source().tell(L("When in tactical mode, your ship can only SAIL @x1.  Use COURSE for more complex maneuvers, or STEER.",dirName));
							return false;
						}
					}
					if(anchorDown)
					{
						msg.source().tell(L("The anchor is down, so you won`t be moving anywhere."));
						return false;
					}
					break;
				}
				case COURSE:
				case SET_COURSE:
				{
					if(!securityCheck(msg.source()))
					{
						msg.source().tell(L("The captain does not permit you."));
						return false;
					}
					if(CMLib.flags().isFalling(this) || ((this.subjectToWearAndTear() && (usesRemaining()<=0))))
					{
						msg.source().tell(L("The ship won't seem to move!"));
						return false;
					}
					if(safetyMove())
					{
						msg.source().tell(L("The ship has moved!"));
						return false;
					}
					if((courseDirection >=0)||(courseDirections.size()>0))
					{
						if(!this.amInTacticalMode())
							msg.source().tell(L("Your previous course has been cancelled."));
						courseDirection = -1;
						courseDirections.clear();
					}
					final Room R=CMLib.map().roomLocation(this);
					if((R==null)||(msg.source().location()==null))
					{
						msg.source().tell(L("You are nowhere, so you won`t be moving anywhere."));
						return false;
					}
					if(((msg.source().location().domainType()&Room.INDOORS)==Room.INDOORS)
					&&(msg.source().isPlayer()))
					{
						msg.source().tell(L("You must be on deck to steer your ship."));
						return false;
					}
					int dirIndex = 1;
					if(word.equals("SET"))
						dirIndex = 2;
					int firstDir = -1;
					this.courseDirections.clear();
					if(amInTacticalMode())
					{
						final int speed=getShipSpeed();
						final String dirFacingName = CMLib.directions().getDirectionName(directionFacing);
						if(dirIndex >= cmds.size())
						{
							msg.source().tell(L("Your ship is currently sailing @x1. To set a course, you must specify up to @x2 directions of travel, "
												+ "of which only the last may be something other than @x3.",dirFacingName,""+speed,dirFacingName));
							return false;
						}
						List<String> dirNames = new ArrayList<String>();
						final int[] coordinates = Arrays.copyOf(getMyCoords(),2);
						int otherDir = -1;
						for(;dirIndex<cmds.size();dirIndex++)
						{
							final String dirWord=cmds.get(dirIndex);
							int dir=CMLib.directions().getCompassDirectionCode(dirWord);
							if(dir<0)
							{
								msg.source().tell(L("@x1 is not a valid direction.",dirWord));
								return false;
							}
							if((otherDir < 0) && (dir == directionFacing))
							{
								Directions.adjustXYByDirections(coordinates[0], coordinates[1], dir);
								final Room targetRoom=R.getRoomInDir(dir);
								final Exit targetExit=R.getExitInDir(dir);
								if((targetRoom==null)||(targetExit==null)||(!targetExit.isOpen()))
								{
									if(getLowestTacticalDistanceFromThis() >= R.maxRange())
									{
										msg.source().tell(L("There doesn't look to be anywhere you can sail in that direction."));
										return false;
									}
								}
							}
							if(this.courseDirections.size() >= speed)
							{
								msg.source().tell(L("Your course may not exceed your tactical speed, which is @x1 moves.", ""+speed));
								return false;
							}
							if(otherDir > 0)
							{
								msg.source().tell(L("Your course includes a change of direction, from @x1 to @x2.  "
												+ "In tactical maneuvers, a changes of direction must be at the end of the course settings.", 
												dirFacingName,CMLib.directions().getDirectionName(otherDir)));
								return false;
							}
							else
							if(dir != directionFacing)
								otherDir = dir;
							dirNames.add(CMLib.directions().getDirectionName(dir).toLowerCase());
							this.courseDirections.add(Integer.valueOf(dir));
						}
						if(this.courseDirections.size()>0)
							this.courseDirection = this.courseDirections.remove(0).intValue();
						if((this.courseDirections.size()==0)||(this.courseDirections.get(this.courseDirections.size()-1).intValue()>=0))
							this.courseDirections.add(Integer.valueOf(-1));
						
						this.announceActionToDeck(msg.source(),L("<S-NAME> order(s) a course setting of @x1.",CMLib.english().toEnglishStringList(dirNames.toArray(new String[0]))));
					}
					else
					{
						if(dirIndex >= cmds.size())
						{
							msg.source().tell(L("To set a course, you must specify some directions of travel, separated by spaces."));
							return false;
						}
						for(;dirIndex<cmds.size();dirIndex++)
						{
							final String dirWord=cmds.get(dirIndex);
							int dir=CMLib.directions().getCompassDirectionCode(dirWord);
							if(dir<0)
							{
								msg.source().tell(L("@x1 is not a valid direction.",dirWord));
								return false;
							}
							if(firstDir < 0)
								firstDir = dir;
							else
								this.courseDirections.add(Integer.valueOf(dir));
						}
						final Room targetRoom=R.getRoomInDir(firstDir);
						final Exit targetExit=R.getExitInDir(firstDir);
						if((targetRoom==null)||(targetExit==null)||(!targetExit.isOpen()))
						{
							this.courseDirection=-1;
							this.courseDirections.clear();
							msg.source().tell(L("There doesn't look to be anything in that direction."));
							return false;
						}
						if((this.courseDirections.size()==0)||(this.courseDirections.get(this.courseDirections.size()-1).intValue()>=0))
							this.courseDirections.add(Integer.valueOf(-1));
						steer(msg.source(),R, firstDir);
					}
					if(anchorDown)
						msg.source().tell(L("The anchor is down, so you won`t be moving anywhere."));
					return false;
				}
				}
			}
			if(cmd != null)
			{
				cmds.add(0, "METAMSGCOMMAND");
				double speed=getShipSpeed();
				if(speed == 0)
					speed=0;
				else
					speed = msg.source().phyStats().speed() / speed;
				msg.source().enqueCommand(cmds, MUDCmdProcessor.METAFLAG_ASMESSAGE, speed);
				return false;
			}
		}
		else
		if((msg.sourceMinor()==CMMsg.TYP_COMMAND)
		&&(msg.sourceMessage()!=null)
		&&(area == CMLib.map().areaLocation(msg.source())))
		{
			final List<String> cmds=CMParms.parse(msg.sourceMessage());
			if(cmds.size()==0)
				return true;
			final String word=cmds.get(0).toUpperCase();
			final String secondWord=(cmds.size()>1) ? cmds.get(1).toUpperCase() : "";
			SailingCommand cmd = (SailingCommand)CMath.s_valueOf(SailingCommand.class, word);
			if((cmd == null)&&(secondWord.length()>0))
				cmd = (SailingCommand)CMath.s_valueOf(SailingCommand.class, word+"_"+secondWord);
			if(cmd == null)
				return true;
			switch(cmd)
			{
			case SAIL:
			{
				int dir=CMLib.directions().getCompassDirectionCode(secondWord);
				if(dir<0)
					return false;
				final Room R=CMLib.map().roomLocation(this);
				if(R==null)
					return false;
				if(!this.amInTacticalMode())
				{
					this.courseDirections.clear(); // sail eliminates a course
					this.courseDirections.add(Integer.valueOf(-1));
					this.beginSail(msg.source(), R, dir);
				}
				else
				{
					if(this.courseDirections.size()>0)
						msg.source().tell(L("Your prior course has been overridden."));
					this.courseDirections.clear();
					this.courseDirections.add(Integer.valueOf(-1));
					this.courseDirection = dir;
					this.announceActionToDeck(msg.source(),L("<S-NAME> start(s) sailing @x1.",CMLib.directions().getDirectionName(dir)));
				}
				return false;
			}
			case STEER:
			{
				int dir=CMLib.directions().getCompassDirectionCode(secondWord);
				if(dir<0)
					return false;
				final Room R=CMLib.map().roomLocation(this);
				if(R==null)
					return false;
				if(!this.amInTacticalMode())
				{
					steer(msg.source(),R, dir);
				}
				else
				{
					if(this.courseDirections.size()>0)
						msg.source().tell(L("Your prior tactical course has been overridden."));
					this.courseDirections.clear();
					this.courseDirections.add(Integer.valueOf(-1));
					this.courseDirection = dir;
					this.announceActionToDeck(msg.source(),L("<S-NAME> start(s) steering the ship @x1.",CMLib.directions().getDirectionName(dir)));
				}
				return false;
			}
			default:
				// already done...
				return false;
			}
		}
		else
		if((msg.targetMinor()==CMMsg.TYP_SIT)
		&&(msg.target()==this)
		&&(msg.source().location()==owner())
		&&(CMLib.flags().isWateryRoom(msg.source().location()))
		&&(!CMLib.flags().isFlying(msg.source()))
		&&(!CMLib.law().doesHavePriviledgesHere(msg.source(), super.getDestinationRoom(msg.source().location()))))
		{
			final Rideable ride=msg.source().riding();
			if(ticksSinceMove < 2)
			{
				if(ride == null)
					msg.source().tell(CMLib.lang().L("You'll need some assistance to board a ship from the water."));
				else
					msg.source().tell(msg.source(),this,ride,CMLib.lang().L("<S-NAME> chase(s) <T-NAME> around in <O-NAME>."));
				return false;
			}
			else
			if(ride == null)
			{
				msg.source().tell(CMLib.lang().L("You'll need some assistance to board a ship from the water."));
				return false;
			}
			else
			if(!CMLib.flags().isClimbing(msg.source()))
			{
				msg.source().tell(CMLib.lang().L("You'll need some assistance to board a ship from @x1, such as some means to climb up.",ride.name(msg.source())));
				return false;
			}
			else
				msg.source().setRiding(null); // if you're climbing, you're not riding any more
		}
		else
		if((msg.sourceMinor()==CMMsg.TYP_COMMANDFAIL)
		&&(msg.targetMessage()!=null)
		&&(msg.targetMessage().length()>0))
		{
			switch(Character.toUpperCase(msg.targetMessage().charAt(0)))
			{
			case 'A':
			{
				List<String> parsedFail = CMParms.parse(msg.targetMessage());
				String cmd=parsedFail.get(0).toUpperCase();
				if(("ATTACK".startsWith(cmd))&&(owner() instanceof Room))
				{
					final Room thisRoom = (Room)owner();
					String rest = CMParms.combine(parsedFail,1);
					if(!securityCheck(msg.source()))
					{
						msg.source().tell(L("The captain does not permit you."));
						return false;
					}
					Boolean result = startAttack(msg.source(),thisRoom,rest);
					if(result == Boolean.FALSE)
						return false;
					else
					if(result == Boolean.TRUE)
					{
						msg.source().tell(getTargetedShipInfo());
						return false;
					}
				}
				break;
			}
			case 'E':
			case 'L':
			{
				List<String> parsedFail = CMParms.parse(msg.targetMessage());
				String cmd=parsedFail.get(0).toUpperCase();
				if(("LOOK".startsWith(cmd)||"LLOOK".startsWith(cmd)||"EXAMINE".startsWith(cmd))
				&&(owner() instanceof Room))
				{
					final int msgType = "EXAMINE".startsWith(cmd) ? CMMsg.MSG_EXAMINE : CMMsg.MSG_LOOK;
					final Room R = (Room)owner();
					String rest = CMParms.combine(parsedFail,1);
					final Item I = R.findItem(null, rest);
					if((I instanceof GenSailingShip)
					||((I instanceof Rideable)&&(((Rideable)I).rideBasis()==Rideable.RIDEABLE_WATER)))
					{
						final CMMsg lookMsg=CMClass.getMsg(msg.source(),I,null,msgType,null,msgType,null,msgType,null);
						if(R.okMessage(msg.source(),lookMsg))
						{
							R.send(msg.source(),lookMsg);
							return false;
						}
					}
				}
				break;
			}
			case 'T': // throwing things to another ship, like a grapple
			{
				List<String> parsedFail = CMParms.parse(msg.targetMessage());
				String cmd=parsedFail.get(0).toUpperCase();
				if(("THROW".startsWith(cmd))
				&&(owner() instanceof Room)
				&&(msg.source().location()!=null)
				&&((msg.source().location().domainType()&Room.INDOORS)==0)
				&&(parsedFail.size()>2))
				{
					parsedFail.remove(0);
					final MOB mob=msg.source();
					final Room R = (Room)owner();
					String str=parsedFail.get(parsedFail.size()-1);
					parsedFail.remove(str);
					final String what=CMParms.combine(parsedFail,0);
					Item item=mob.fetchItem(null,Wearable.FILTER_WORNONLY,what);
					if(item==null)
						item=mob.findItem(null,what);
					if((item!=null)
					&&(CMLib.flags().canBeSeenBy(item,mob))
					&&((item.amWearingAt(Wearable.WORN_HELD))||(item.amWearingAt(Wearable.WORN_WIELD))))
					{
						str=str.toLowerCase();
						if(str.equals("water")||str.equals("overboard")||CMLib.english().containsString(R.displayText(), str))
						{
							final Room target=R;
							final CMMsg msg2=CMClass.getMsg(mob,target,item,CMMsg.MSG_THROW,L("<S-NAME> throw(s) <O-NAME> overboard."));
							final CMMsg msg3=CMClass.getMsg(mob,target,item,CMMsg.MSG_THROW,L("<O-NAME> fl(ys) in from overboard."));
							if(mob.location().okMessage(mob,msg2)&&target.okMessage(mob,msg3))
							{
								mob.location().send(mob,msg2);
								target.sendOthers(mob,msg3);
							}
							return false;
						}
							
						final Item I = R.findItem(null, str);
						if(I!=this)
						{
							if((I instanceof GenSailingShip)
							||((I instanceof Rideable)&&(((Rideable)I).rideBasis()==Rideable.RIDEABLE_WATER)))
							{
								if((!amInTacticalMode())
								||(I.maxRange() < getTacticalDistance(I)))
								{
									msg.source().tell(L("You can't throw @x1 at @x2, it's too far away!",item.name(msg.source()),I.name(msg.source())));
									return false;
								}
								else
								if(getMyCoords()!=null)
								{
									final int[] targetCoords = ((GenSailingShip)I).getMyCoords();
									if(targetCoords!=null)
									{
										int dir = Directions.getRelativeDirection(getMyCoords(), targetCoords);
										final String inDir=CMLib.directions().getShipInDirectionName(dir);
										final String fromDir=CMLib.directions().getFromShipDirectionName(Directions.getOpDirectionCode(dir));
										Room target = ((GenSailingShip)I).getRandomDeckRoom();
										if(target == null)
											target=R;
										final CMMsg msg2=CMClass.getMsg(mob,target,item,CMMsg.MSG_THROW,L("<S-NAME> throw(s) <O-NAME> @x1.",inDir.toLowerCase()));
										final CMMsg msg3=CMClass.getMsg(mob,target,item,CMMsg.MSG_THROW,L("<O-NAME> fl(ys) in from @x1.",fromDir.toLowerCase()));
										if(mob.location().okMessage(mob,msg2)&&target.okMessage(mob,msg3))
										{
											mob.location().send(mob,msg2);
											target.sendOthers(mob,msg3);
										}
										return false;
									}
									else
									{
										msg.source().tell(L("You can't throw @x1 at @x2, it's too far away!",item.name(msg.source()),I.name(msg.source())));
										return false;
									}
								}
								else
								{
									msg.source().tell(L("You can't throw @x1 at @x2, it's too far away!",item.name(msg.source()),I.name(msg.source())));
									return false;
								}
							}
						}
					}
				}
				break;
			}
			}
		}
		else
		if((msg.targetMinor()==CMMsg.TYP_LEAVE)
		&&(msg.target() instanceof Room)
		&&(msg.target() == owner()))
		{
			if((msg.source().riding() != null)
			&&(this.targetedShip == msg.source().riding())
			&&(CMLib.flags().isWaterWorthy(msg.source().riding())))
			{
				msg.source().tell(L("Your small vessel can not get away during combat."));
				return false;
			}
			if(msg.tool() instanceof Exit)
			{
				final Room R=msg.source().location();
				int dir=CMLib.map().getExitDir(R,(Exit)msg.tool());
				if((dir >= 0)
				&&(R.getRoomInDir(dir)!=null)
				&&(R.getRoomInDir(dir).getArea()==this.getShipArea())
				&&(msg.othersMessage()!=null)
				&&(msg.othersMessage().indexOf("<S-NAME>")>=0)
				&&(msg.othersMessage().indexOf(L(CMLib.flags().getPresentDispositionVerb(msg.source(),CMFlagLibrary.ComingOrGoing.LEAVES)))>=0))
					msg.setOthersMessage(L("<S-NAME> board(s) @x1.",Name()));
			}
			
		}
		else
		if((msg.targetMinor()==CMMsg.TYP_ENTER)
		&&(msg.target() == owner())
		&&(msg.source().location()!=null)
		&&(msg.source().location().getArea()==this.getShipArea())
		&&(msg.tool() instanceof Exit)
		&&(msg.othersMessage()!=null)
		&&(msg.othersMessage().indexOf("<S-NAME>")>=0)
		&&(msg.othersMessage().indexOf(L(CMLib.flags().getPresentDispositionVerb(msg.source(),CMFlagLibrary.ComingOrGoing.ARRIVES)))>=0))
			msg.setOthersMessage(L("<S-NAME> disembark(s) @x1.",Name()));
		if(!super.okMessage(myHost, msg))
			return false;
		return true;
	}