public void listAreas(MOB mob, List<String> commands, Filterer<Area> filter)
	{
		if(mob==null)
			return;
		commands.remove(0);
		List<String> sortBys=null;
		List<String> colNames=null;
		WikiFlag wiki=getWikiFlagRemoved(commands);
		if(commands.size()>0)
		{
			List<String> addTos=null;
			while(commands.size()>0)
			{
				if(commands.get(0).toString().equalsIgnoreCase("sortby"))
				{
					commands.remove(0);
					sortBys=new Vector<String>();
					addTos=sortBys;
				}
				else
				if(commands.get(0).toString().equalsIgnoreCase("cols")||commands.get(0).toString().equalsIgnoreCase("columns"))
				{
					commands.remove(0);
					colNames=new Vector<String>();
					addTos=colNames;
				}
				else
				if(addTos!=null)
				{
					final String stat=commands.get(0).toString().toUpperCase().trim();
					final ListAreaStats ls=(ListAreaStats)CMath.s_valueOf(ListAreaStats.class, stat);
					final Area.Stats as=(Area.Stats)CMath.s_valueOf(Area.Stats.class, stat);
					if((ls==null)&&(as==null))
					{
						mob.tell(L("'@x1' is not recognized.  Try one of these: @x2, @x3",stat,CMParms.toListString(ListAreaStats.values()),CMParms.toListString(Area.Stats.values())));
						return;
					}
					addTos.add(stat);
					commands.remove(0);
				}
				else
				{
					mob.tell(L("'@x1' is not recognized.  Try 'columns' or 'sortby' followed by one or more of these: @x2, @x3",commands.get(0).toString(),CMParms.toListString(ListAreaStats.values()),CMParms.toListString(Area.Stats.values())));
					return;
				}
			}
		}
		final Vector<Triad<String,String,Integer>> columns=new Vector<Triad<String,String,Integer>>();
		if((colNames!=null)&&(colNames.size()>0))
		{
			for(final String newCol : colNames)
			{
				final ListAreaStats ls=(ListAreaStats)CMath.s_valueOf(ListAreaStats.class, newCol);
				final Area.Stats as=(Area.Stats)CMath.s_valueOf(Area.Stats.class, newCol);
				if(ls!=null)
					columns.add(new Triad<String,String,Integer>(ls.shortName,ls.name(),ls.len));
				else
				if(as!=null)
					columns.add(new Triad<String,String,Integer>(CMStrings.scrunchWord(CMStrings.capitalizeAndLower(newCol), 6),as.name(),Integer.valueOf(6)));
			}
		}
		else
		{
			//AREASTAT_DESCS
			columns.add(new Triad<String,String,Integer>(ListAreaStats.NAME.shortName,ListAreaStats.NAME.name(),ListAreaStats.NAME.len));
			columns.add(new Triad<String,String,Integer>(ListAreaStats.HIDDEN.shortName,ListAreaStats.HIDDEN.name(),ListAreaStats.HIDDEN.len));
			columns.add(new Triad<String,String,Integer>(ListAreaStats.ROOMS.shortName,ListAreaStats.ROOMS.name(),ListAreaStats.ROOMS.len));
			columns.add(new Triad<String,String,Integer>(ListAreaStats.STATE.shortName,ListAreaStats.STATE.name(),ListAreaStats.STATE.len));
			columns.add(new Triad<String,String,Integer>("Pop",Area.Stats.POPULATION.name(),Integer.valueOf(6)));
			columns.add(new Triad<String,String,Integer>("MedLv",Area.Stats.MED_LEVEL.name(),Integer.valueOf(6)));
		}

		final Session s=mob.session();
		final double wrap=(s==null)?78:s.getWrap();
		double totalCols=0;
		for(int i=0;i<columns.size();i++)
			totalCols+=columns.get(i).third.intValue();
		for(int i=0;i<columns.size();i++)
		{
			final double colVal=columns.get(i).third.intValue();
			final double pct=CMath.div(colVal,totalCols );
			final int newSize=(int)Math.round(Math.floor(CMath.mul(pct, wrap)));
			columns.get(i).third=Integer.valueOf(newSize);
		}

		final StringBuilder str=new StringBuilder("");
		for(final Triad<String,String,Integer> head : columns)
			str.append(CMStrings.padRight(head.first, head.third.intValue()));
		str.append("\n\r");
		final Triad<String,String,Integer> lastColomn=columns.get(columns.size()-1);
		Enumeration<Area> a;
		if(sortBys!=null)
		{
			final List<String> sortFields=sortBys;
			List<Area> sorted=new ArrayList<Area>();
			for(final Enumeration<Area> as=CMLib.map().areas();as.hasMoreElements();)
			{
				final Area A=as.nextElement();
				if((filter!=null)&&(!filter.passesFilter(A)))
					continue;
				sorted.add(A);
			}
			Collections.sort(sorted,new Comparator<Area>()
			{
				@SuppressWarnings({ "rawtypes", "unchecked" })
				@Override
				public int compare(Area arg0, Area arg1) 
				{
					for(String sortField : sortFields)
					{
						Comparable val0=getAreaStatFromSomewhere(arg0,sortField);
						Comparable val1=getAreaStatFromSomewhere(arg1,sortField);
						int comp=1;
						if((val0==null)&&(val1==null))
							comp=0;
						else
						if(val0==null)
							comp=-1;
						else
						if(val1==null)
							comp=1;
						else
							comp=val0.compareTo(val1);
						if(comp!=0)
							return comp;
					}
					return 0;
				}
			});
			if(sorted.size()>0)
				a=new IteratorEnumeration<Area>(sorted.iterator());
			else
				a=CMLib.map().areas();
		}
		else
			a=CMLib.map().areas();
		Faction theFaction=CMLib.factions().getFaction(CMLib.factions().AlignID());
		if(theFaction == null)
		{
			for(final Enumeration<Faction> e=CMLib.factions().factions();e.hasMoreElements();)
			{
				final Faction F=e.nextElement();
				if(F.showInSpecialReported())
					theFaction=F;
			}
		}
		for(;a.hasMoreElements();)
		{
			final Area A=a.nextElement();
			if((filter!=null)&&(!filter.passesFilter(A)))
				continue;
			if(wiki==WikiFlag.WIKILIST)
			{
				str.append("*[["+A.name()+"|"+A.name()+"]]");
			}
			else
			if(wiki==WikiFlag.WIKIHELP)
			{
				String currency = CMLib.beanCounter().getCurrency(A);
				if((currency==null)||(currency.trim().length()==0))
					currency="Gold coins (default)";
				else
					currency=CMStrings.capitalizeAndLower(currency);
				str.append("{{AreaTemplate"
						+ "|Name="+A.name()
						+ "|Description="+A.description()
						+ "|Author="+A.getAuthorID()
						+ "|Rooms="+A.getAreaIStats()[Area.Stats.VISITABLE_ROOMS.ordinal()]
						+ "|Population="+A.getAreaIStats()[Area.Stats.POPULATION.ordinal()]
						+ "|Currency="+currency
						+ "|LevelRange="+A.getAreaIStats()[Area.Stats.MIN_LEVEL.ordinal()]+"-"+A.getAreaIStats()[Area.Stats.MAX_LEVEL.ordinal()]
						+ "|MedianLevel="+A.getAreaIStats()[Area.Stats.MED_LEVEL.ordinal()]
						+ "|AvgAlign="+((theFaction!=null)?theFaction.fetchRangeName(A.getAreaIStats()[Area.Stats.AVG_ALIGNMENT.ordinal()]):"")
						+ "|MedAlignment="+((theFaction!=null)?theFaction.fetchRangeName(A.getAreaIStats()[Area.Stats.MED_ALIGNMENT.ordinal()]):""));
				for(Enumeration<String> f=A.areaBlurbFlags();f.hasMoreElements();)
				{
					String flag=f.nextElement();
					str.append("|"+flag+"="+A.getBlurbFlag(flag));
				}
				str.append("}} ");
			}
			else
			{
				for(final Triad<String,String,Integer> head : columns)
				{
					Object val =getAreaStatFromSomewhere(A,head.second);
					if(val==null)
						val="?";
					if(head==lastColomn)
						str.append(CMStrings.scrunchWord(val.toString(), head.third.intValue()-1));
					else
						str.append(CMStrings.padRight(CMStrings.scrunchWord(val.toString(), head.third.intValue()-1), head.third.intValue()));
				}
			}
			str.append("\n\r");
		}
		if(s!=null)
			s.colorOnlyPrint(str.toString(), true);
	}