public StringBuilder listRaces(Session viewerS, Enumeration<Race> these, String rest)
	{
		final List<String> parms=CMParms.parse(rest.toUpperCase());
		final boolean shortList=parms.contains("SHORT");
		if(shortList)
			parms.remove("SHORT");
		WikiFlag wiki = getWikiFlagRemoved(parms);
		final String restRest=CMParms.combine(parms).trim();
		final StringBuilder lines=new StringBuilder("");
		if(!these.hasMoreElements())
			return lines;
		int column=0;
		final int COL_LEN=CMLib.lister().fixColWidth(25.0,viewerS);
		if(shortList)
		{
			final Vector<String> raceNames=new Vector<String>();
			for(final Enumeration<Race> e=these;e.hasMoreElements();)
			{
				final Race R=e.nextElement();
				if((restRest.length()==0)
				||(CMLib.english().containsString(R.ID(), restRest))
				||(CMLib.english().containsString(R.name(), restRest))
				||(CMLib.english().containsString(R.racialCategory(), restRest)))
					raceNames.add(R.ID());
			}
			lines.append(CMParms.toListString(raceNames));
		}
		else
		for(final Enumeration<Race> e=these;e.hasMoreElements();)
		{
			final Race R=e.nextElement();
			if((restRest.length()==0)
			||(CMLib.english().containsString(R.ID(), restRest))
			||(CMLib.english().containsString(R.name(), restRest))
			||(CMLib.english().containsString(R.racialCategory(), restRest)))
			{
				if(wiki == WikiFlag.WIKILIST)
					lines.append("*[["+R.name()+"|"+R.name()+"]]\n\r");
				else
				if(wiki == WikiFlag.WIKIHELP)
				{
					String statAdj=R.getStatAdjDesc();
					if(R.getTrainAdjDesc().length()>0)
						statAdj+=((statAdj.length()>0)?", ":"")+R.getTrainAdjDesc();
					if(R.getPracAdjDesc().length()>0)
						statAdj+=((statAdj.length()>0)?", ":"")+R.getPracAdjDesc();
					String ableStr=R.getSensesChgDesc();
					if(R.getDispositionChgDesc().length()>0)
						ableStr+=((ableStr.length()>0)?", ":"")+R.getDispositionChgDesc();
					if(R.getAbilitiesDesc().length()>0)
						ableStr+=((ableStr.length()>0)?", ":"")+R.getAbilitiesDesc();
					String immunoStr="";
					for(String ableID : R.abilityImmunities())
					{
						final Ability A=CMClass.getAbilityPrototype(ableID);
						if(A!=null)
							immunoStr+=((immunoStr.length()>0)?", ":"")+A.name();
					}
					StringBuilder help=CMLib.help().getHelpText(R.ID(),null,false,true);
					if(help==null)
						help=CMLib.help().getHelpText(R.name(),null,false,true);
					if((help!=null)&&(help.toString().startsWith("<RACE>")))
						help=new StringBuilder(help.toString().substring(6));
					else
						help=new StringBuilder("");
					String eqStr="";
					if(R.outfit(null)!=null)
					{
						for(final Item I : R.outfit(null))
						{
							if(I!=null)
								eqStr+=((eqStr.length()>0)?", ":"")+I.Name();
						}
					}
					String qualClassesStr="";
					if(CMProps.isTheme(R.availabilityCode()) && ((R.availabilityCode()&Area.THEME_SKILLONLYMASK)==0))
					{
						for(final Enumeration<CharClass> c=CMClass.charClasses();c.hasMoreElements();)
						{
							final CharClass C=c.nextElement();
							if(((CMProps.isTheme(C.availabilityCode())))
							&&(C.isAllowedRace(R)))
							{
								qualClassesStr+="[["+C.name()+"("+C.baseClass()+")|"+C.name()+"]] ";
							}
						}
					}
					int maxAge=R.getAgingChart()[Race.AGE_ANCIENT];
					String lifeExpStr;
					if(maxAge>Integer.MAX_VALUE/2)
						lifeExpStr=L("Forever");
					else
						lifeExpStr=L("@x1 years",""+maxAge);
						
					lines.append("{{RaceTemplate"
							+ "|Name="+R.name()
							+ "|Description="+help
							+ "|Statadj="+statAdj
							+ "|BonusAbilities="+ableStr
							+ "|BonusLanguages="+R.getLanguagesDesc()
							+ "|Immunities="+immunoStr
							+ "|LifeExpectancy="+lifeExpStr
							+ "|Startingequipment="+eqStr
							+ "|Qualifyingclasses="+qualClassesStr
							+ "}}\n\r");
				}
				else
				{
					if(++column>3)
					{
						lines.append("\n\r");
						column=1;
					}
					lines.append(CMStrings.padRight(R.ID()
								+(R.isGeneric()?"*":"")
								+" ("+R.racialCategory()+")",COL_LEN));
				}
			}
		}
		lines.append("\n\r");
		return lines;
	}