// ====||| String Object additions |||==========================================================
String.prototype.link = function(sCode) {return "<a class='Link' href=\"javascript:" + sCode + "\">" + this + "</a>";}
String.prototype.red = function(sTitle) {var retVal = "<span style='cursor:default;color:red;'"; if (sTitle) retVal += " title='" + sTitle + "'"; retVal += ">" + this + "</span>"; return retVal;}

// ====||| Faction Object |||==========================================================
function Faction(iIndex, sData) {
	if (!sData || sData.indexOf(",") < 0) return;
	this._index = iIndex;
		this.Name = eval(sData.split(",")[0]);
		this.Code = eval(sData.split(",")[1]);
		this.Icon = eval(sData.split(",")[2]);
		this.Selected = eval(sData.split(",")[3]);
}
new Faction();
Faction.prototype.getIndex = function() {return this._index;}
Faction.prototype.isSelected = faction_isSelected;

// ====||| Map Object |||===========================================================
function Map(iIndex, sData) {
	if (!sData || sData.indexOf(",") < 0) return;
	this._index = iIndex;
	this.Name = eval(sData.split(",")[0]);
	this.Epic = eval(sData.split(",")[1]);
}
new Map();
Map.prototype.getIndex = function() {return this._index;}

// ====||| Mini Object |||==========================================================
function Mini(iIndex, sData) {
	if (!sData || sData.indexOf(",") < 0) return;
	this._index = iIndex;
	this._data = sData.split(",");
	for (var i = 0; i < this._data.length; i++) {
		this._data[i] = eval(this._data[i]);
		if (i == C_FACTION) this._data[i] = aFactionData[this._data[i]];
		if (i == C_RARITY) this._data[i] = aRarityData.getRarityByCode(this._data[i]);
		if (i == C_SET) this._data[i] = aSetData.getSetByCode(this._data[i]);
		if (i == C_SIZE) this._data[i] = aSizeData.getSizeByCode(this._data[i]);
	}
}
new Mini();
Mini.prototype.clone = function() {
	var oRetVal = new Mini();
	oRetVal._index = this._index;
	oRetVal._data = this._data;
	return oRetVal;
}

//Commanders, Followers and Leaders, Minions, Mobs
Mini.prototype.canAdd = function(oMini) {if (!oMini) return false; if (this.hasWarbandBuilding()) if (eval(this._data[C_RESERVED1])) return this.canCommand(oMini); return false;}
Mini.prototype.canCommand = mini_canCommand;
Mini.prototype.canEnvoy = function(oMini) {return oMini && this.isEnvoy() && oMini.isPsionic() && this.getFaction() != oMini.getFaction();}
Mini.prototype.canLead = function(oMini) {if (!oMini || !this.hasMinions()) return false; return eval(this._data[C_RESERVED2]);}
Mini.prototype.canMob = function(oMini) {return oMini && this.isMob() && this.getIndex() == oMini.getIndex() && this.isEpic() == oMini.isEpic();}
Mini.prototype.getCommanderRating = function() {return this.isCommander()? this._data[C_COMMANDERRATING] : -1;}
Mini.prototype.getMaxMinions = function() {return this._data[C_RESERVED1];}
Mini.prototype.getMinionsCost = function() {if (!this.Minions) return 0; var retVal = 0; for (var i = 0; i < this.Minions.length; i++) retVal += this.Minions[i].getCost(); return retVal;}
Mini.prototype.getMinionsCount = function() {if (!this.Minions) return 0; return this.Minions.length;}
Mini.prototype.getMinionsEffect = function(bShort) {return this.hasMinions()? bShort? this._data[C_RESERVED3] : unescape(this._data[C_RESERVED4]) : "";}
Mini.prototype.getMobCount = function() {return parseInt(this._data[C_CONSTRUCTIONSPECIAL1].substring(4));}
Mini.prototype.getWarbandBuildingEffect = function(bShort) {return this.hasWarbandBuilding()? bShort? this._data[C_RESERVED3] : unescape(this._data[C_RESERVED4]) : "";}
Mini.prototype.hasMinions = function() {return this._data[C_CONSTRUCTIONSPECIAL]? -1 < this._data[C_CONSTRUCTIONSPECIAL].indexOf("M") : false;}
Mini.prototype.hasWarbandBuilding = function() {return this._data[C_COMMANDERTYPE]? -1 < this._data[C_COMMANDERTYPE].indexOf("W") : false;}
Mini.prototype.isCommander = function() {return this._data[C_COMMANDERTYPE]? -1 < this._data[C_COMMANDERTYPE].indexOf("C") : false;}
Mini.prototype.isDomineering = function() {return this._data[C_COMMANDERTYPE]? -1 < this._data[C_COMMANDERTYPE].indexOf("D") : false;}
Mini.prototype.isMob = function() {return this._data[C_CONSTRUCTIONSPECIAL1] && this._data[C_CONSTRUCTIONSPECIAL1].indexOf("Mob ") == 0;}
Mini.prototype.isMount = function() {return this._data[C_CONSTRUCTIONSPECIAL] && -1 < this._data[C_CONSTRUCTIONSPECIAL].indexOf("X");}
Mini.prototype.isEnvoy = function() {return this._data[C_CONSTRUCTIONSPECIAL1] == "Psionic Envoy";}
Mini.prototype.isSubCommander = function(type) {return this._data[C_COMMANDERTYPE]? -1 < this._data[C_COMMANDERTYPE].indexOf(type? type : "S") : false;}

//Factions
Mini.prototype.getFaction = function() {return this._data[C_FACTION];} //Object
Mini.prototype.hasFaction = mini_hasFaction;

//Beasts and Masters
Mini.prototype.getDifficultRating = function() {return this._data[C_DIFFICULTRATING]? this._data[C_DIFFICULTRATING] : 0;}
Mini.prototype.getMasterRating = function() {return this._data[C_MASTERRATING]? this._data[C_MASTERRATING] : 0;}
Mini.prototype.isDifficult = function() {return this._data[C_DIFFICULTRATING]? 0 < parseInt(this._data[C_DIFFICULTRATING]) : false;}
Mini.prototype.isWild = function() {return this._data[C_CONSTRUCTIONSPECIAL]? -1 < this._data[C_CONSTRUCTIONSPECIAL].indexOf("W") : false;}
Mini.prototype.isBeast = function() {return this.hasType("Animal") || this.hasType("Magical Beast");}
Mini.prototype.isDemon = function() {return this.hasType("Outsider") && (this.hasFaction(C_LE) || this.hasFaction(C_CE));}
Mini.prototype.isWolf = function() {return this.hasType("Animal") && this.hasInName("Wolf");}
Mini.prototype.getMountRider = function(bShort) {return bShort? this._data[C_RESERVED2] : "Can have a " + aSizeData[this.getSize().getIndex()-1].Name + " or smaller " + this._data[C_RESERVED2] + " creature as a rider";}

Mini.prototype.isMaster = function(type) {return this._data[C_MASTERTYPE]? -1 < this._data[C_MASTERTYPE].indexOf(type) : false;}
Mini.prototype.isBeastmaster = function() {return this.isMaster("B");}
Mini.prototype.isDemonmaster = function() {return this.isMaster("De");}
Mini.prototype.isDisplacermaster = function() {return this.isMaster("Di");}
Mini.prototype.isDragonmaster = function() {return this.isMaster("Dr");}
Mini.prototype.isElementalmaster = function() {return this.isMaster("E");}
Mini.prototype.isFireElementalMaster = function() {return this.isMaster("F");}
Mini.prototype.isGiantmaster = function() {return this.isMaster("G");}
Mini.prototype.isHyenamaster = function() {return this.isMaster("H");}
Mini.prototype.isPlantmaster = function() {return this.isMaster("P");}
Mini.prototype.isSlaadmaster = function() {return this.isMaster("Sl");}
Mini.prototype.isSpidermaster = function() {return this.isMaster("Sp");}

//Sizes
Mini.prototype.getSize = function() {return this._data[C_SIZE];} //Object
Mini.prototype.isSize = function(sSize) {return (this._data[C_SIZE].Code == sSize);}

//Type
Mini.prototype.getSubType = mini_getSubType;
Mini.prototype.getType = function() {return this._data[C_TYPE];}
Mini.prototype.hasSubType = mini_hasSubType;
Mini.prototype.hasType = function(sType) {return this._data[C_TYPE] == sType || this.hasSubType(sType);}

//Other
Mini.prototype.getIndex = function() {return this._index;}
Mini.prototype.getCollectorNumber = function() {return this._data[C_COLLECTORNO];}
Mini.prototype.getCost = function() {return this._data[C_COST];}
Mini.prototype.getLevel = function() {return this._data[C_LEVEL];}
Mini.prototype.getName = function() {return unescape(this._data[C_NAME]);}
Mini.prototype.getRarity = function() {return this._data[C_RARITY];} //Object
Mini.prototype.getSet = function() {return this._data[C_SET];} //Object
Mini.prototype.getNotes = mini_getNotes;
Mini.prototype.hasNotes = function(bIsMinion) {return (this._data[C_CONSTRUCTIONSPECIAL1] || this.isAttendant() || this.isBeastmaster() || this.isDemonmaster() || this.isDisplacermaster() || this.isDragonmaster() || this.isFireElementalMaster() || this.isHyenamaster() || this.isMount() || this.isPlantmaster() || this.isSlaadmaster() || this.isSpidermaster() || this.isDifficult() || this.isWild() || this.isIndependent() || this.requiresCommander() || this.requiresDwarfCommander() || this.isUnique() || this.hasMinions() || this.hasWarbandBuilding());}
Mini.prototype.isAttendant = function() {return this._data[C_CONSTRUCTIONSPECIAL]? -1 < this._data[C_CONSTRUCTIONSPECIAL].indexOf("A") : false;}
Mini.prototype.isEpic = function() {return this._data[C_CONSTRUCTIONSPECIAL]? -1 < this._data[C_CONSTRUCTIONSPECIAL].indexOf("E") : false;}
Mini.prototype.isImmuneFire = function() {return this._data[C_CONSTRUCTIONSPECIAL2]? -1 < this._data[C_CONSTRUCTIONSPECIAL2].indexOf("ImmF") : false;}
Mini.prototype.isIndependent = function() {return this._data[C_CONSTRUCTIONSPECIAL]? -1 < this._data[C_CONSTRUCTIONSPECIAL].indexOf("I") : false;}
Mini.prototype.isPsionic = function() {return this._data[C_CONSTRUCTIONSPECIAL]? -1 < this._data[C_CONSTRUCTIONSPECIAL].indexOf("P") : false;}
Mini.prototype.isSpellcaster = function() {return this._data[C_CONSTRUCTIONSPECIAL]? -1 < this._data[C_CONSTRUCTIONSPECIAL].indexOf("P") || -1 < this._data[C_CONSTRUCTIONSPECIAL].indexOf("S") : false;}
Mini.prototype.isUnique = function() {return this._data[C_CONSTRUCTIONSPECIAL]? -1 < this._data[C_CONSTRUCTIONSPECIAL].indexOf("U") : false;}
Mini.prototype.hasInName = function(sWord) {
	var aName = this._data[C_NAME].replace("-", " ").replace("%2C", "").replace("%27", "").split(" ");
	for (var i = 0; i < aName.length; i++) {
		if (aName[i] == sWord) return true;
		if (aName[i].substring(0, sWord.length) == sWord) return true;
		if (aName[i].substring(aName[i].length - sWord.length) == sWord) return true;
	}
	return false;
}
Mini.prototype.requiresCommander = function() {return this._data[C_CONSTRUCTIONSPECIAL]? -1 < this._data[C_CONSTRUCTIONSPECIAL].indexOf("R") : false;}
Mini.prototype.requiresDwarfCommander = function() {return this._data[C_CONSTRUCTIONSPECIAL]? -1 < this._data[C_CONSTRUCTIONSPECIAL].indexOf("D") : false;}

// ====||| Rarity Object |||==========================================================
function Rarity(iIndex, sData) {
	if (!sData || sData.indexOf(",") < 0) return;
	this._index = iIndex;
	this._data = sData.split(",");
		this.Name = eval(this._data[0]);
		this.Code = eval(this._data[1]);
		this.Selected = true;
}
new Rarity();
Rarity.prototype.getIndex = function() {return this._index;}

// ====||| Set Object |||==========================================================
function Set(iIndex, sData) {
	if (!sData || sData.indexOf(",") < 0) return;
	this._index = iIndex;
	this._data = sData.split(",");
		this.Name = eval(this._data[0]);
		this.Code = eval(this._data[1]);
		this.StartIndex = eval(this._data[2]);
		this.MiniCount = eval(this._data[3]);
		this.Active = eval(this._data[4]);
		this.Selected = eval(this._data[5]);
}
new Set();
Set.prototype.getIndex = function() {return this._index;}

// ====||| Size Object |||==========================================================
function Size(iIndex, sData) {
	if (!sData || sData.indexOf(",") < 0) return;
	this._index = iIndex;
	this._data = sData.split(",");
		this.Name = eval(this._data[0]);
		this.Code = eval(this._data[1]);
}
new Size();
Size.prototype.getIndex = function() {return this._index;}

// ====||| Terrain Object |||==========================================================
function Terrain(iIndex, sData) {
	if (!sData || sData.indexOf(",") < 0) return;
	this._index = iIndex;
		this.Name = eval(sData.split(",")[0]);
		this.Assembly = eval(sData.split(",")[1]);
}
new Terrain();
Terrain.prototype.getIndex = function() {return this._index;}

// ====||| Warband Object |||==========================================================
function Warband(sData) {
	this._data = new Array();
		this._bCleaning = false;
	this._terrain = new Array();
	//
	this.Name = "";
	this.Faction = -1;
	this.Map = null;
	this.MaxPoints = 200;
	this.MaxMinis = 8;
	this.MaxTerrain = 4;
	this._maxTerrain = 4;
	this.SortMethod = 0;
	this.SortAscending = true;
	this.StandardCostRule = true; // 70% Rule
}
new Warband();

//Add or Remove items
Warband.prototype.addMini = warband_addMini;
Warband.prototype.addMinion = warband_addMinion;
Warband.prototype.addMob = warband_addMob;
Warband.prototype.addAttendant = warband_addAttendant;
Warband.prototype.addEnvoy = warband_addEnvoy;
Warband.prototype.addTerrain = function(oTerrain) {this._terrain[this._terrain.length] = oTerrain.getIndex(); this.Map = null;}
Warband.prototype.clearMap = function() {this.Map = null; this.MaxTerrain = this._maxTerrain;}
Warband.prototype.removeMini = warband_removeMini;
Warband.prototype.removeMinion = warband_removeMinion;
Warband.prototype.removeMob = warband_removeMob;
Warband.prototype.removeAttendant = warband_removeAttendant;
Warband.prototype.removeEnvoy = warband_removeEnvoy;
Warband.prototype.removeTerrain = warband_removeTerrain;
Warband.prototype.setMap = function(oMap) {this.Map = oMap; this._terrain = new Array(); if (this.MaxTerrain != 0) {this._maxTerrain = this.MaxTerrain; this.MaxTerrain = 0;} }
Warband.prototype._cleanUp = warband_cleanUp;

//Check to see if you can Add
Warband.prototype.canAddMini = warband_canAddMini;
Warband.prototype.canCommandMini = function(oMini) {if (oMini._data[C_CONSTRUCTIONSPECIAL1] == "Always out of Command") return false; if (!oMini.isDifficult() && !oMini.isWild()) return true; for (var i = 0; i < this._data.length; i++) if (this._data[i].canCommand(oMini)) return true; return false;}
Warband.prototype.canLeadMini = function(oMini, bAsMinion) {for (var i = 0; i < this._data.length; i++) if (this._data[i].hasMinions()) if (this._data[i].canLead(oMini, bAsMinion)) if (!this._data[i].Minions || this._data[i].Minions.length < this._data[i].getMaxMinions()) return true; return false;}
Warband.prototype.canMobMini = function(oMini) {for (var i = 0; i < this._data.length; i++) if (this._data[i].isMob()) if (this._data[i].canMob(oMini)) if (!this._data[i].Mob || this._data[i].Mob.length < oMini.getMobCount() - 1) return true; return false;}
Warband.prototype.canAttendantMini = function(oMini) {if (oMini.isAttendant()&&oMini.getCost()<=this.MaxPoints-this.getCost()) for (var i = 0; i < this._data.length; i++) if (this._data[i].isSpellcaster()) if (this._data[i].Attendants.length == 0) return true; return false;}
Warband.prototype.canEnvoyMini = function(oMini) {if(oMini.getCost()<=this.MaxPoints-this.getCost())for (var i = 0; i < this._data.length; i++) if (this._data[i].isEnvoy()) if (this._data[i].canEnvoy(oMini)) if (!this._data[i].Envoy || this._data[i].Envoy.length == 0) return true; return false;}
Warband.prototype.isValidCost = function(oMini) {var cost = oMini.getCost() + (this.hasEpicUltroloth() && !oMini.isCommander() && oMini.hasSubType("Yugoloth")? -10 : 0); if (500 <= this.MaxPoints || !this.StandardCostRule) return cost <= this.MaxPoints; return cost <= this.MaxPoints * 0.7;}

//Other
Warband.prototype.getCommanderCount = function() {var iRetVal = 0; for (var i = 0; i < this._data.length; i++) if (this._data[i].isCommander() || (this._data[i].Envoy.length && this._data[i].Envoy[0].isCommander())) iRetVal++; return iRetVal;}
Warband.prototype.getDwarfCommanderCount = function() {var iRetVal = 0; for (var i = 0; i < this._data.length; i++) if (this._data[i].isCommander() && this._data[i].hasSubType("Dwarf")) iRetVal++; return iRetVal;}
Warband.prototype.getCost = function() {
	var iPoints = 0;
	var bEpicUltroloth = this.hasEpicUltroloth();
	for (var i = 0; i < this._data.length; i++) {
		iPoints += (this._data[i].getCost() + (bEpicUltroloth && !this._data[i].isCommander() && this._data[i].hasSubType("Yugoloth")? -10 : 0)) * (this._data[i].Mob.length + 1);
		for(var j = 0; j < this._data[i].Attendants.length; j++) iPoints += this._data[i].Attendants[j].getCost();
		for(var j = 0; j < this._data[i].Envoy.length; j++) iPoints += this._data[i].Envoy[j].getCost();
	}
	return iPoints;
}
Warband.prototype.getCountIndex = function(oMini) {var iRetVal = 1; for (var i = 0; i < this._data.length; i++) {if (0 < i && this._data[i-1].getIndex() == this._data[i].getIndex()) iRetVal++; else iRetVal = 1; if (this._data[i] == oMini) return iRetVal;} return -1;}
Warband.prototype.getMinis = function() {return this._data;}
Warband.prototype.getMiniCount = function(oMini) {var iCount = 0; for (var i = 0; i < this._data.length; i++) {if (!oMini || this._data[i].getIndex() == oMini.getIndex()) iCount++; if (this._data[i].Envoy.length) if (!oMini || this._data[i].Envoy[0].getIndex()==oMini.getIndex()) iCount++;} return iCount;}
Warband.prototype.getMinionCount = function() {var iRetVal = 0; for (var i = 0; i < this._data.length; i++) iRetVal += this.data[i].Minions.length; return iRetVal;}
Warband.prototype.getTerrain = function() {return this._terrain;}
Warband.prototype.getTerrainCount = function() {return this._terrain.length;}
Warband.prototype.hasAssemblyTerrain = function() {for (var i = 0; i < this._terrain.length; i++) if (aTerrainData[this._terrain[i]].Assembly) return true; return false;}
Warband.prototype.hasCommander = function() {for (var i = 0; i < this._data.length; i++) if (this._data[i].isCommander() || (this._data[i].Envoy.length && this._data[i].Envoy[0].isCommander())) return true; return false;}
Warband.prototype.hasDwarfCommander = function() {for (var i = 0; i < this._data.length; i++) if (this._data[i].isCommander() && this._data[i].hasSubType("Dwarf")) return true; return false;}
Warband.prototype.hasDomineering = function() {for (var i = 0; i < this._data.length; i++) if (this._data[i].isCommander() && this._data[i].isDomineering()) return true; return false;}
Warband.prototype.hasEpicUltroloth = function() {for (var i = 0; i < this._data.length; i++) if (this._data[i].isEpic() && this._data[i].getName() == "Ultroloth") return true; return false;}
Warband.prototype.hasMini = function(oMini) {if (!oMini) return false; for (var i = 0; i < this._data.length; i++) if (this._data[i].getIndex() == oMini.getIndex()) return true; return false;}
Warband.prototype.hasMinis = function() {return 0 < this._data.length;}
Warband.prototype.hasNotes = function() {for (var i = 0; i < this._data.length; i++) if (this._data[i].hasMinions()) return true; for (var i = 0; i < this._data.length; i++) if (this._data[i].hasWarbandBuilding()) return true; return false;}
Warband.prototype.hasSpellcaster = function() {for (var i = 0; i < this._data.length; i++) if (this._data[i].isSpellcaster()) return true; return false;}
Warband.prototype.hasTerrain = function(oTerrain) {if (!oTerrain) return 0 < this._terrain.length; for (var i = 0; i < this._terrain.length; i++) if (oTerrain.getIndex() == this._terrain[i]) return true; return false;}
Warband.prototype.isValidMember = warband_isValidMember;
Warband.prototype.load = warband_load;
Warband.prototype.save = warband_save;
Warband.prototype.sort = warband_sort;

//=====================================================================================
//The Functions
//=====================================================================================
//Faction
function faction_isSelected() {
	if (this._index == C_LG || this._index == C_CG || this._index == C_LE || this._index == C_CE) return this.Selected;
	if (this._index == C_LGCG) return aFactionData[C_LG].Selected || aFactionData[C_CG].Selected;
	if (this._index == C_LGLE) return aFactionData[C_LG].Selected || aFactionData[C_LE].Selected;
	if (this._index == C_CGCE) return aFactionData[C_CG].Selected || aFactionData[C_CE].Selected;
	if (this._index == C_LECE) return aFactionData[C_LE].Selected || aFactionData[C_CE].Selected;
	if (this._index == C_ANY) return aFactionData[C_LG].Selected || aFactionData[C_CG].Selected || aFactionData[C_LE].Selected || aFactionData[C_CE].Selected;
	return false;
}

//Mini
function mini_canCommand(oMini) {
	if (oMini._data[C_CONSTRUCTIONSPECIAL1] == "Not Subject to Commander Effects") return;
	if (!oMini || !this.isCommander()) return false;
	
	if (oMini.isCommander()) {
		if (this._data[C_RESERVED3] == "xv") {}
		else if (this.isUnique && oMini.isSubCommander("H")) {}
		else if (this.hasType("Kuo-Toa") && oMini.isSubCommander("K")) {}
		else if (this.hasInName("Drizzt") && oMini.isSubCommander("Z")) {}
		else if (oMini.isSubCommander()) {}
		else return false;
	}else {
		if (this._data[C_RESERVED3] == "xv" && oMini.getName() == "Standardbearer") return true;
		if (this._data[C_RESERVED3] == "xxiv" && oMini.getName() == "Standardbearer") return false;
	}
	if (oMini.isDifficult() || oMini.isWild()) {
		if (
			(this.isBeastmaster() && oMini.isBeast())
			|| (this.isDisplacermaster() && oMini.hasInName("Displacer Beast"))
			|| (this.isDragonmaster() && oMini.hasType("Dragon"))
			|| (this.isElementalmaster() && oMini.hasType("Elemental"))
			|| (this.isFireElementalMaster() && oMini.isImmuneFire())
			|| (this.isGiantmaster() && oMini.hasType("Giant"))
			|| (this.isHyenamaster() && oMini.hasInName("Hyena"))
			|| (this.isPlantmaster() && oMini.hasType("Plant"))
			|| (this.isSpidermaster() && oMini.hasInName("Spider"))
			|| (this.isSlaadmaster() && oMini.hasInName("Slaad"))
			|| (this.isDemonmaster() && oMini.isDemon()) ) {
			if (this.getCommanderRating() < oMini.getDifficultRating() || oMini.isWild())
				if (this.getMasterRating() < oMini.getLevel()) return false;
		}else if (!oMini.isWild()) {
			if (this.getCommanderRating() < oMini.getDifficultRating()) return false;
		}else {
			return false;
		}
	}
	return true;
}
function mini_hasFaction(iFaction) {
	var iThisFaction = this._data[C_FACTION].getIndex();
	switch (iFaction) {
		case C_LG:
			return (iThisFaction == C_LG || iThisFaction == C_LGCG || iThisFaction == C_ANY || iThisFaction == C_LGLE);
		case C_CG:
			return (iThisFaction == C_LGCG || iThisFaction == C_CG || iThisFaction == C_ANY || iThisFaction == C_CGCE);
		case C_ANY:
			return (iThisFaction == C_ANY);
		case C_LE:
			return (iThisFaction == C_LGLE || iThisFaction == C_ANY || iThisFaction == C_LE || iThisFaction == C_LECE);
		case C_CE:
			return (iThisFaction == C_CGCE || iThisFaction == C_ANY || iThisFaction == C_LECE || iThisFaction == C_CE);
	}
	return false;
}
function mini_getSubType() {
	sRetVal = this._data[C_SUBTYPE1];
	if (!sRetVal) return "";
	if (this._data[C_SUBTYPE2]) sRetVal += ", " + this._data[C_SUBTYPE2];
	if (this._data[C_SUBTYPE3]) sRetVal += ", " + this._data[C_SUBTYPE3];
	if (this._data[C_SUBTYPE4]) sRetVal += ", " + this._data[C_SUBTYPE4];
	sRetVal = "(" + sRetVal + ")";

	return sRetVal;
}
function mini_hasSubType(sSubType) {
	var iLoop;
	for (iLoop = C_SUBTYPE1; iLoop <= C_SUBTYPE4; iLoop++) {
		if (this._data[iLoop] && this._data[iLoop] == sSubType) {
			return true;
		}
	}
	return false;
}
function mini_getNotes(oTheWarband, bIsMinion) {
	var bCanCommand = oTheWarband.canCommandMini(this);
	var sRetVal = "";

	if (this._data[C_CONSTRUCTIONSPECIAL1]) sRetVal += this._data[C_CONSTRUCTIONSPECIAL1];
	if (this.isAttendant()) {
		if (sRetVal) sRetVal += ", ";
		sRetVal += "<span title='Does not count as a creature for the purpose of warband construction.'>Attendant</span>";
	}
	if (this.isBeastmaster()) sRetVal += (sRetVal? ", " : "") + "Beastmaster " + this.getMasterRating();
	if (this.isDifficult() && !bIsMinion) {
		if (sRetVal) sRetVal += ", ";
		if (!bCanCommand && !this.isBeast() && !this.isDemon() && !this.hasInName("Displacer Beast") && !this.hasType("Dragon") && !this.hasType("Elemental") && !this.hasType("Giant") && !this.hasInName("Fire Elemental") && !this.hasType("Plant") && !this.hasInName("Slaad") && !this.hasInName("Spider")) sRetVal += "<span style='color:red;' title=\"You don't have a high enough Commander.\">";
		else if (!bCanCommand && this.hasInName("Hyena")) sRetVal += "<span style='color:red;' title=\"You don't have a high enough Beastmaster or Hyenamaster.\">";
		else if (!bCanCommand && this.hasInName("Displacer Beast")) sRetVal += "<span style='color:red;' title=\"You don't have a high enough Commander or Displacermaster.\">";
		else if (!bCanCommand && this.isBeast()) sRetVal += "<span style='color:red;' title=\"You don't have a high enough Beastmaster.\">";
		else if (!bCanCommand && this.isDemon()) sRetVal += "<span style='color:red;' title=\"You don't have a high enough Commander or Demonmaster.\">";
		else if (!bCanCommand && this.hasType("Dragon")) sRetVal += "<span style='color:red;' title=\"You don't have a high enough Commander or Dragonmaster.\">";
		else if (!bCanCommand && this.hasType("Elemental")) sRetVal += "<span style='color:red;' title=\"You don't have a high enough Commander or Elementalmaster.\">";
		else if (!bCanCommand && this.hasInName("Fire Elemental")) sRetVal += "<span style='color:red;' title=\"You don't have a high enough Commander or Fire Elemental Master.\">";
		else if (!bCanCommand && this.hasType("Giant")) sRetVal += "<span style='color:red;' title=\"You don't have a high enough Commander or Giantmaster.\">";
		else if (!bCanCommand && this.hasType("Plant")) sRetVal += "<span style='color:red;' title=\"You don't have a high enough Commander or Plantmaster.\">";
		else if (!bCanCommand && this.hasInName("Slaad")) sRetVal += "<span style='color:red;' title=\"You don't have a high enough Commander or Slaadmaster.\">";
		else if (!bCanCommand && this.hasInName("Spider")) sRetVal += "<span style='color:red;' title=\"You don't have a high enough Commander or Spidermaster.\">";
		sRetVal += "Difficult " + this.getDifficultRating();
		if (!bCanCommand) sRetVal += "</span>";
	}
	if (this.isDisplacermaster()) sRetVal += (sRetVal? ", " : "") + "Displacermaster " + this.getMasterRating();
	if (this.isDemonmaster()) sRetVal += (sRetVal? ", " : "") + "Demonmaster " + this.getMasterRating();
	if (this.isDomineering()) {
		if (sRetVal) sRetVal += ", ";
		if (oTheWarband.hasCommander() && !oTheWarband.hasMini(this)) sRetVal += "<span style='color:red' title=\"You can't have another Commander.\">";
		sRetVal += "Domineering";
		if (oTheWarband.hasCommander() && !oTheWarband.hasMini(this)) sRetVal += "</span>";
	}
	if (this.isDragonmaster()) sRetVal += (sRetVal? ", " : "") + "Dragonmaster " + this.getMasterRating();
	if (this.isElementalmaster()) sRetVal += (sRetVal? ", " : "") + "Elementalmaster " + this.getMasterRating();
	if (this.isFireElementalMaster()) sRetVal += (sRetVal? ", " : "") + "Fire Elemental Master " + this.getMasterRating();
	if (this.isGiantmaster()) sRetVal += (sRetVal? ", " : "") + "Giantmaster " + this.getMasterRating();
	if (this.isHyenamaster()) sRetVal += (sRetVal? ", " : "") + "Hyenamaster " + this.getMasterRating();
	if (this.isIndependent()) sRetVal += (sRetVal? ", " : "") + "Independent";
	if (this.hasMinions()) sRetVal += (sRetVal? ", " : "") + "<span title='" + this.getMinionsEffect() + "'>Minions<sup>" + this.getMinionsEffect(true) + "</sup></span>";
	if (this.isMount()) sRetVal += (sRetVal? ", " : "") + "<span title='" + this.getMountRider() + "'>Mount<sup>" + this.getMountRider(true) + "</sup></span>";
	if (this.isPlantmaster()) sRetVal += (sRetVal? ", " : "") + "Plantmaster " + this.getMasterRating();
	if (this.requiresCommander()) {
		if (sRetVal) sRetVal += "<br />";
		if (!oWarband.hasCommander()) sRetVal += "<span style='color:red;' title=\"You don't have a Commander.\">";
		sRetVal += "Requires Commander";
		if (!oWarband.hasCommander()) sRetVal += "</span>";
	}
	if (this.requiresDwarfCommander()) {
		if (sRetVal) sRetVal += "<br />";
		if (!oWarband.hasDwarfCommander()) sRetVal += "<span style='color:red;' title=\"You don't Dwarf have a Commander.\">";
		sRetVal += "Requires Dwarf Commander";
		if (!oWarband.hasDwarfCommander()) sRetVal += "</span>";
	}
	if (this.isAttendant()) {
		if (sRetVal) sRetVal += "<br />";
		if (!oWarband.hasSpellcaster()) sRetVal += "<span style='color:red;' title=\"You don't have a Spellcaster.\">";
		sRetVal += "Requires Spellcaster";
		if (!oWarband.hasSpellcaster()) sRetVal += "</span>";
	}
	if (this.isSlaadmaster()) sRetVal += (sRetVal? ", " : "") + "Slaadmaster " + this.getMasterRating();
	if (this.isSpidermaster()) sRetVal += (sRetVal? ", " : "") + "Spidermaster " + this.getMasterRating();
	if (this.isUnique()) sRetVal += (sRetVal? ", " : "") + "Unique";
	if (this.isWild() && !bIsMinion) {
		if (sRetVal) sRetVal += ", ";
		if (!bCanCommand && !this.isBeast()) sRetVal += "<span style='color:red;' title=\"You don't have a high enough Commander.\">";
		else if (!bCanCommand && this.isBeast()) sRetVal += "<span style='color:red;' title=\"You don't have a high enough Beastmaster.\">";
		sRetVal += "Wild";
		if (!bCanCommand) sRetVal += "</span>";
	}
	if (this.hasWarbandBuilding()) sRetVal += (sRetVal? ", " : "") + "<span title='" + this.getWarbandBuildingEffect() + "'>Warband Building<sup>" + this.getWarbandBuildingEffect(true) + "</sup></span>";
	return sRetVal;
}

//Warband
function warband_addMini(oMini) {
	this._data[this._data.length] = oMini.clone();
	this._data[this._data.length - 1].Attendants = new Array();
	this._data[this._data.length - 1].Envoy = new Array();
	this._data[this._data.length - 1].Minions = new Array();
	this._data[this._data.length - 1].Mob = new Array();
	this._data.sort(_compareByColumn(this.SortMethod, this.SortAscending));
	if (this._data.length == 1 && this._data[0].getFaction().Icon)
		this.Faction = this._data[0].getFaction().getIndex();
}
function warband_addMinion(oMini) {
	for (var i = 0; i < this._data.length; i++) {
		if (!this._data[i].hasMinions()) continue;
		if (!this._data[i].canLead(oMini)) continue;
		if (this._data[i].Minions && this._data[i].getMaxMinions() == this._data[i].Minions.length) continue;
		this._data[i].Minions[this._data[i].Minions.length] = oMini;
		this._data[i].Minions.sort(_compareByColumn(this.SortMethod, this.SortAscending));
		break;
	}
}
function warband_addAttendant(oMini) {
	if (oMini.isAttendant()) {
		for (var i = 0; i < this._data.length; i++) {
			if (!this._data[i].isSpellcaster() || this._data[i].Attendants.length) continue;
			this._data[i].Attendants[this._data[i].Mob.length] = oMini;
			break;
		}
	}
}
function warband_addEnvoy(oMini) {
	if (oMini.isPsionic()) {
		for (var i = 0; i < this._data.length; i++) {
			if (!this._data[i].isEnvoy() || this._data[i].Envoy.length) continue;
			this._data[i].Envoy[0] = oMini;
			break;
		}
	}
}
function warband_addMob(oMini) {
	if (oMini.isMob()) {
		for (var i = 0; i < this._data.length; i++) {
			if (!oMini.canMob(this._data[i])) continue;
			if (this._data[i].Mob && oMini.getMobCount() - 1 == this._data[i].Mob.length) continue;
			this._data[i].Mob[this._data[i].Mob.length] = oMini;
			break;
		}
	}
}
function warband_canAddMini(oMini) {
	var bCount = false;
		if (this.getMiniCount() < this.MaxMinis) bCount = true;

	var bFaction = false;
		if (this.Faction < 0 || oMini.hasFaction(this.Faction)) bFaction = true;
	var bWarbandBuilder = false;
		if (!bFaction && 0 < this.getCommanderCount()) {
			for (var i = 0; i < this._data.length; i++) {
				if (this._data[i].canAdd(oMini)) {
					bWarbandBuilder = true;
					break;
				}
			}
		}

	var bCost = false;
		if (oMini.getCost() + (this.hasEpicUltroloth() && !oMini.isCommander() && oMini.hasSubType("Yugoloth")? -10 : 0) <= this.MaxPoints - this.getCost()) bCost = true;
		if (bCost) if (!this.isValidCost(oMini)) bCost = false;

	var bDuplicateUnique = false;
		if (oMini.isUnique()) {
			for (var i = 0; i < this._data.length; i++) {
				if (this._data[i].getIndex() == oMini.getIndex()) {
					bDuplicateUnique = true;
					break;

				}else {
					var sName = oMini.getName();
					var sOtherName = this._data[i].getName();
					var bComma = -1 < sName.indexOf(",");

					if (!bComma) {
						if (sName == sOtherName) {
							bDuplicateUnique = true;
							break;
						}
						continue;
					}

					if (bComma && sOtherName.indexOf(",") < 0) continue;

					sName = sName.substring(0, sName.indexOf(","));
					sOtherName = sOtherName.substring(0, sOtherName.indexOf(","));
					if (sName == sOtherName) {
						bDuplicateUnique = true;
						break;
					}
				}
			}
		}

	var bNeedCommander = false;
		if (oMini.requiresCommander() && this.getCommanderCount() == 0) bNeedCommander = true;
	var bNeedDwarfCommander = false;
		if (oMini.requiresDwarfCommander() && this.getDwarfCommanderCount() == 0) bNeedDwarfCommander = true;
	
	var bDomineering = false;
		if (oMini.isDomineering() && 0 < this.getCommanderCount()) bDomineering = true;
		if (oMini.isCommander() && this.hasDomineering()) bDomineering = true;

	return bCount && (bFaction || bWarbandBuilder) && bCost && !bDuplicateUnique && !bNeedCommander && !bNeedDwarfCommander && !bDomineering && !oMini.isAttendant();
}
function warband_cleanUp() {
	if (this._bCleaning) return;
	this._bCleaning = true;
	var index = 0;
	while (index < this._data.length) {
		if ((this._data[index].requiresCommander() && this.getCommanderCount() == 0) || (this._data[index].requiresDwarfCommander() && this.getDwarfCommanderCount() == 0)) {
			this.removeMini(this._data[index]);
			index = 0;
			continue;
		}
		if (!this._data[index].hasFaction(this.Faction)) {
			var bWarbandBuilder = false;
			for (var i = 0; i < this._data.length; i++) {
				if (this._data[i].hasWarbandBuilding()) {
					bWarbandBuilder = this._data[i].canAdd(this._data[index]);
				}
			}
			if (!bWarbandBuilder) {
				this.removeMini(this._data[index]);
				index = 0;
				continue;
			}
		}
		index++;
	}
	if (this._data.length == 0) this.Faction = -1;
	this._bCleaning = false;
}
function warband_isValidMember(oMini) {
	var bFaction = false;
		if (oMini.hasFaction(this.Faction) || this.Faction < 0) bFaction = true;
	var bWarbandBuilder = false;
		if (!bFaction && 0 < this.getCommanderCount()) {
			for (var i = 0; i < this._data.length; i++) {
				if (this._data[i].canAdd(oMini)) {
					bWarbandBuilder = true;
					break;
				}
			}
		}
	return bFaction || bWarbandBuilder;
}
function warband_load(sWarband) {
	if (-1 < sWarband.indexOf("%20") || -1 < sWarband.indexOf("%27"))
		sWarband = unescape(sWarband);

	if (sWarband.indexOf(",") < 0) return alert("Warband value is not valid!");

	var bOld = (sWarband.substring(0, 1) == ",")? false : true;
	
	var aInformation = sWarband.split(",");
	if (aInformation.length < 6) return false;

	this._data = new Array();
	this._terrain = new Array();
	this.MaxPoints = parseInt(aInformation[bOld? 0 : 1]);
	this.Name =	aInformation[bOld? 1 : 2];
	var iFaction;
	if (bOld) {
		iFaction = aInformation[2] == 1? C_LG : aInformation[2] == 2? C_CG : aInformation[2] == 3? C_LE : C_CE;
	}else {
		 iFaction = parseInt(aInformation[3]);
	}
	setFaction(iFaction);
	this.MaxMinis =	parseInt(aInformation[bOld? 3 : 4]);

	var iCount, iMini, aMinions;
	//Set figures
	for (iCount = 0; iCount < parseInt(aInformation[bOld? 4 : 5]); iCount++) {
		iMini = aInformation[(bOld? 5 : 6) + iCount];
		if (-1 < iMini.indexOf("/")) {
			aMinions = iMini.split("/")[1].split("~");
			iMini = iMini.split("/")[0];
		}else {
			aMinions = "";
		}
		if (bOld) iMini--;

		if (iMini == parseInt(iMini) + "e") this.addMini(aEpicData[parseInt(iMini)]);
		else this.addMini(aMiniData[parseInt(iMini)]);
		if (aMinions.length) {
			if (this.canMobMini(aMiniData[aMinions[0]])) {
				for (var i = 0; i < aMinions.length; i++) {
					this.addMob(aMiniData[aMinions[i]]);
				}
			}else {
				for (var i = 0; i < aMinions.length; i++) {
					this.addMinion(aMiniData[aMinions[i]]);
				}
			}
		}
	}

	this.Faction = iFaction;

	var iBase = (bOld? 5 : 6) + iCount;
		this.MaxTerrain = parseInt(aInformation[iBase]);

	if (aInformation.length - 1 == iBase) return true;

	iBase++;

	if (this.MaxTerrain != 0) {
		//Set tiles
		var iTerrain;
		for (iCount = 0; iCount < this.MaxTerrain; iCount++) {
			iTerrain = parseInt(aInformation[iBase + iCount]);
			if (bOld) iTerrain--;
			if (aTerrainData[iTerrain]) this.addTerrain(aTerrainData[iTerrain]);
		}
	}else {
		this.setMap(aMapData[parseInt(aInformation[iBase])]);
	}

	//Clear existing minions
	if (bOld) {
		var aMinions = aInformation[aInformation.length - 1].split("~");
		for (var i = 0; i < aMinions.length; i++) {
			this.addMinion(aMiniData[aMinions[i]-1]);
		}
	}
	return true;
}
function warband_removeMini(oMini) {
	for (var i = 0; i < this._data.length; i++) {
		if (this._data[i].getIndex() == oMini.getIndex() && this._data[i].isEpic() == oMini.isEpic()) {
			this._data[i] = this._data[this._data.length - 1];
			this._data.length--;
			break;
		}
	}
	this._cleanUp();
}
function warband_removeMinion(oMini) {
	for (var i = 0; i < this._data.length; i++) {
		if (this._data[i].Minions.length == 0) continue;
		for (var j = 0; j < this._data[i].Minions.length; j++) {
			if (this._data[i].Minions[j].getIndex() == oMini.getIndex()) {
				this._data[i].Minions[j] = this._data[i].Minions[this._data[i].Minions.length - 1];
				this._data[i].Minions.length--;
				return;
			}
		}
	}
}
function warband_removeAttendant(oMini) {
	for (var i = 0; i < this._data.length; i++) {
		if (!oMini.isAttendant()) continue;
		if (this._data[i].Attendants.length == 0) continue;
		this._data[i].Attendants.length--;
		return;
	}
}
function warband_removeEnvoy(oMini) {
	for (var i = 0; i < this._data.length; i++) {
		if (!oMini.isPsionic()) continue;
		if (this._data[i].Envoy.length == 0) continue;
		this._data[i].Envoy.length--;
		return;
	}
}
function warband_removeMob(oMini) {
	for (var i = 0; i < this._data.length; i++) {
		if (!oMini.canMob(this._data[i])) continue;
		if (this._data[i].Mob.length == 0) continue;
		this._data[i].Mob.length--;
		return;
	}
}
function warband_removeTerrain(oTerrain) {
	for (var i = 0; i < this._terrain.length; i++) {
		if (aTerrainData[this._terrain[i]].getIndex() == oTerrain.getIndex()) {
			this._terrain[i] = this._terrain[this._terrain.length - 1];
			this._terrain.length--;
			break;
		}
	}
}
function warband_sort(iSortValue) {
	if (iSortValue && iSortValue != this.SortMethod) {
		this.SortMethod = iSortValue;
		this.SortAscending = true;
	}else if (iSortValue) {
		this.SortAscending = !this.SortAscending;
	}else {
		iSortValue = this.SortMethod;
	}
	this._data.sort(_compareByColumn(this.SortMethod, this.SortAscending));
}
function warband_save(bMinisOnly) {
	var sRetVal = "", sMinions = "", sMob = "";
	var iLoop = 0, jLoop = 0;

	if (!bMinisOnly) {
		sRetVal = "," + this.MaxPoints + "," + this.Name + "," + this.Faction + "," + this.MaxMinis + "," + this.getMiniCount();
	}

	//Add Minis
	for (iLoop = 0; iLoop < this._data.length; iLoop++) {
		sMinions = sMob = "";
		sRetVal += ((sRetVal != "")? "," : "") + this._data[iLoop].getIndex();
		if (this._data[iLoop].isEpic()) sRetVal += "e";

		for (jLoop = 0; jLoop < this._data[iLoop].Minions.length; jLoop++) {
			sMinions += sMinions? "~" : "/";
			sMinions += this._data[iLoop].Minions[jLoop].getIndex();
		}
		for (jLoop = 0; jLoop < this._data[iLoop].Mob.length; jLoop++) {
			sMob += sMob? "~" : "/";
			sMob += this._data[iLoop].Mob[jLoop].getIndex();
		}
		
		if (!bMinisOnly) sRetVal += sMinions + sMob;
	}

	if (!bMinisOnly) {
		//Add Terrain
		sRetVal += "," + this.getTerrainCount();
		for (iLoop = 0; iLoop < this._terrain.length; iLoop++) {
			sRetVal += "," + this._terrain[iLoop];
		}
		//Add Map
		if (this.Map) sRetVal += "," + this.Map.getIndex();
	}
	return sRetVal;
}