public StringBuilder listLinkages(Session viewerS, MOB mob, String rest)
	{
		final StringBuilder buf=new StringBuilder("Links: \n\r");
		final List<List<Area>> areaLinkGroups=new Vector<List<Area>>();
		Vector<String> parms=CMParms.parse(rest.toUpperCase());
		boolean showSubStats = parms.contains("SUBSTATS");
		Enumeration<Area> a;
		if(parms.contains("WORLD"))
			a=CMLib.map().areas();
		else
			a=new XVector<Area>(mob.location().getArea()).elements();
		for(;a.hasMoreElements();)
		{
			final Area A=a.nextElement();
			buf.append("^H"+A.name()+"^N, "+A.numberOfProperIDedRooms()+" rooms, ");
			if(!A.getProperMap().hasMoreElements())
			{
				buf.append("\n\r");
				continue;
			}
			final List<List<Room>> linkedGroups=new Vector<List<Room>>();
			for(final Enumeration<Room> r=A.getCompleteMap();r.hasMoreElements();)
			{
				final Room R=r.nextElement();
				if(R.roomID().length()>0)
				{
					List<Room> myVec=null;
					List<Room> clearVec=null;
					for(int d=Directions.NUM_DIRECTIONS()-1;d>=0;d--)
					{
						final Room R2=R.rawDoors()[d];
						if(R2!=null)
						{
							for(int g=0;g<linkedGroups.size();g++)
							{
								final List<Room> G=linkedGroups.get(g);
								if(G.size()==0)
									clearVec=G;
								else
								if(G.contains(R2))
								{
									if(myVec==null)
									{
										myVec=G;
										myVec.add(R);
									}
									else
									if(myVec!=G)
									{
										for(int g2=0;g2<myVec.size();g2++)
											G.add(myVec.get(g2));
										myVec.clear();
										clearVec=myVec;
										myVec=G;
									}
								}
							}
						}
					}
					if(myVec==null)
					{
						if(clearVec!=null)
							clearVec.add(R);
						else
						{
							clearVec=new Vector<Room>();
							clearVec.add(R);
							linkedGroups.add(clearVec);
						}
					}
				}
				for(int g=linkedGroups.size()-1;g>=0;g--)
				{
					if((linkedGroups.get(g)).size()==0)
						linkedGroups.remove(g);
				}
			}
			final StringBuilder ext=new StringBuilder("links ");
			List<Area> myVec=null;
			List<Area> clearVec=null;
			for(final Enumeration<Room> r=A.getCompleteMap();r.hasMoreElements();)
			{
				final Room R=r.nextElement();
				if(R.roomID().length()>0)
				for(int d=Directions.NUM_DIRECTIONS()-1;d>=0;d--)
				{
					final Room R2=R.rawDoors()[d];
					if((R2!=null)&&(R2.getArea()!=R.getArea()))
					{
						ext.append("\n\r   "+CMLib.directions().getDirectionName(d)+": "+R2.getArea().name());
						if(showSubStats)
						{
							int[] areaStats = R2.getArea().getAreaIStats();
							ext.append(" (");
							ext.append(L("@x1 mobs, @x2 avg lvl, @x3 med lvl, @x4 avg align",
									""+areaStats[Area.Stats.POPULATION.ordinal()],
									""+areaStats[Area.Stats.AVG_LEVEL.ordinal()],
									""+areaStats[Area.Stats.MED_LEVEL.ordinal()],
									""+areaStats[Area.Stats.AVG_ALIGNMENT.ordinal()]));
							ext.append(") ");
						}
						else
							ext.append(" ("+R.roomID()+"/"+R2.roomID()+") ");
						for(int g=0;g<areaLinkGroups.size();g++)
						{
							final List<Area> G=areaLinkGroups.get(g);
							if(G.size()==0)
								clearVec=G;
							else
							if(G.contains(R2.getArea()))
							{
								if(myVec==null)
								{
									myVec=G;
									myVec.add(R.getArea());
								}
								else
								if(myVec!=G)
								{
									for(int g2=0;g2<myVec.size();g2++)
										G.add(myVec.get(g2));
									myVec.clear();
									clearVec=myVec;
									myVec=G;
								}
							}
						}
					}
				}
			}
			if(myVec==null)
			{
				if(clearVec!=null)
					clearVec.add(A);
				else
				{
					clearVec=new Vector<Area>();
					clearVec.add(A);
					areaLinkGroups.add(clearVec);
				}
			}
			int[] areaStats = A.getAreaIStats();
			if(areaStats[Area.Stats.POPULATION.ordinal()]>0)
			{
				buf.append(L("@x1 mobs, @x2 avg lvl, @x3 med lvl, @x4 avg align",
						""+areaStats[Area.Stats.POPULATION.ordinal()],
						""+areaStats[Area.Stats.AVG_LEVEL.ordinal()],
						""+areaStats[Area.Stats.MED_LEVEL.ordinal()],
						""+areaStats[Area.Stats.AVG_ALIGNMENT.ordinal()]));
			}
			if(linkedGroups.size()>0)
			{
				buf.append(", groups: "+linkedGroups.size()+" sizes: ");
				for(final List<Room> grp : linkedGroups)
					buf.append(grp.size()+" ");
			}
			buf.append("\t"+ext.toString()+"\n\r");
		}
		buf.append(L("There were @x1 area groups:",""+areaLinkGroups.size()));
		for(int g=areaLinkGroups.size()-1;g>=0;g--)
		{
			if(areaLinkGroups.get(g).size()==0)
				areaLinkGroups.remove(g);
		}
		final StringBuilder unlinkedGroups=new StringBuilder("");
		for(final List<Area> V : areaLinkGroups)
		{
			buf.append(V.size()+" ");
			if(V.size()<4)
			{
				for(int v=0;v<V.size();v++)
					unlinkedGroups.append(V.get(0).name()+"\t");
				unlinkedGroups.append("|\t");
			}

		}
		buf.append("\n\r");
		buf.append(L("Small Group Areas:\t@x1",unlinkedGroups.toString()));
		//Log.sysOut("Lister",buf.toString());
		return buf;
	}