// Seraphiel
// version 0.84
// 2009-01-24
// Copyright (c) 2006-09, Joel Rein (Jivlain)
// Contact: jivlain@gmail.com
//
// Released under the GPL (v2) license
// http://www.gnu.org/copyleft/gpl.html
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// ==Recommended editor settings==
// Insert tabs as tabs
// Tab width: 4 spaces
//
// ==UserScript==
// @name Seraphiel
// @namespace http://jivlain.livejournal.com/
// @description Formatters and calculators for Utopia
// ==/UserScript==

/* VERSION HISTORY
 VERSION    DATE        AUTHOR				DESCRIPTION
 0.1b1		17/09/06	Jivlain				Initial version
 0.1b2		18/09/06	Jivlain				Toggle preferences button fixed
 0.2b2		25/09/06	Jivlain				Improved calcs, show monarch message, kd numbers->links
 0.2b3		26/09/06	Jivlain				Reduced memory leakage issues
 0.2b4		27/09/06	Jivlain				Themes updates
 0.2b5		02/10/06	Jivlain				Bug fixes - buildings calculator, style changes, performance problems
 0.2b6		09/10/06	Jivlain				UI changes - buildings calculator
 0.3b1		15/10/06	Jivlain				Added kingdom tagging feature
 0.3b2		21/10/06	Jivlain				Bug fixes - Genesis kingdom page; improved stability
 0.3b3		22/10/06	Jivlain				Bug fix - Utopian time now updating correctly
 0.3b4(XPI)	29/10/06	Jivlain				Bug fix - XPI only; FF 2.0 compatability added
 0.3b5		10/11/06	Jivlain				Bug fix - sorting of large provinces on kd page; kd page formatting changes
 0.3b6		15/11/06	Jivlain				Bug fixes - thievery ops being incorrectly remembered
 0.3b7		22/12/06	Jivlain				Age update
 0.41		11/02/07	Jivlain				Direct links to councillors in top menu
 0.42		14/02/07	Jivlain				Bug fix - tags not working
 0.50		21/02/07	Jivlain				Added mass messaging assist feature
 0.51		07/03/07	Jivlain				Buildings calculator supports DBE; military training cost calc; improved UI
 0.52		10/03/07	Jivlain				Bug fixes - kingdom page sorting, formatting unpinned resource bars
 0.53		10/03/07	Jivlain				Bug fixes - restored attack calc
 0.54		11/03/07	Jivlain				Bug workaround - disabled forum links for page/monarch.
 0.55		09/04/07	Jivlain				Security update - improved host detection and reading
 0.56		13/04/07	Jivlain				Quickfix to issue with previous version, Gen kingdom page fix
 0.57		28/04/07	Jivlain				Numerous bug fixes
 0.58		12/06/07	Jivlain				Removed attack calculator, slight enhancements
 0.59		26/06/07	Jivlain				Updated for the Age of Bravery (age 36)
 0.60		07/07/07	Jivlain, avarice	See http://jivlain.wordpress.com/2007/07/09/seraphiel-060-released/
 0.61		21/08/07	Jivlain				Kingdom page fix, SoM bug fix, Angel copy fixes, remembers attack forces
 0.62		02/10/07	Jivlain				Updated for age 37
 0.63		21/10/07	Jivlain				Added disable option, improved top bar at low resolutions
 0.64		29/11/07	Jivlain				GUW 2 compatability, raw offense, low food alert
 0.642		01/12/07	Jivlain				Fixing top bar, DE offense, version number
 0.645		02/12/07	Jivlain				Fixed weird crashing bugs that were coming up in some circumstances
 0.7		14/03/08	Jivlain				Updated for age 37; select t/m/msg on kd page, links to kd page from target pages
 0.71		10/04/08	Jivlain				Works better with the new CAPTCHA
 0.72		19/04/08	Jivlain				Fixes buildings calculator bug for >10k acres, bug fixes on magic/thievery pages
 0.73		03/05/08	Jivlain				Updated for age 39
 0.74   	19/05/08	Jivlain				Yet Another CAPTCHA Fix
 0.8		18/06/08	Jivlain				Bug fixes (see changelog), added spell/operation memory (1h)
 0.81		25/07/08	Jivlain				Link to Swirve/OMAC blog, throne page formatter bug fix for large numbers
 0.82		24/08/08	Jivlain				Update for initial UI changes, FF 3.01 compatability
 0.83		11/11/08	Jivlain				Updated for age 41, attack page improvements
 0.84		24/01/09	Jivlain				Bug fixes - kingdom name, buildings calculator, sidebar
*/

/* CREDITS
 * Joel Rein (http://jivlain.wordpress.com)
 * avarice
 * Anthony Lieuallen (http://www.arantius.com/)
 * David Vignoni (http://icon-king.com/?p=15) 
*/

function inURL(str){
	return location.href.indexOf(str)>=0;
}

function inBody(str){
	return document.body.innerHTML.indexOf(str)>=0;
}

var server="0";
if(inURL("wol.swirve.com")||inURL("wol.swirve.com/boards"))
    server="wol";
else if(inURL("u3.swirve.com")||inURL("uboards2.swirve.com"))
    server="u3";
else if(inURL("b.swirve.com")||inURL("uboards.swirve.com/tourney"))
	server="b";
 
var enabled=GM_getValue('enable', true);
if(!enabled&&!inURL('pref.cgi'))
	return;
	
function GetServer(full){
	return server;
	/*if(full)
		return server;
	else
		return server[server.length-1];*/
}

if(GetServer(false)!='0'&&!inURL("side_a.htm")&&!inURL("forum.cgi")&&
  !inBody("As a security measure within the game")&&!inBody("To ensure you provided a valid email address")){
	if(inURL('board.cgi'))
		SeraphielForums();
    if(!inURL("scores.cgi")&&!inURL("status.cgi")&&!inURL("magic.cgi"))
        ClickableLinks();
	if(!inURL('board.cgi')&&!inURL('bot.htm'))
		Seraphiel();	
}

function ClickableLinksInStr(str, nullIfNoLinks){
	var locations=str.match(new RegExp("\([0-9]{1,2}:[0-9]{1,2}\)","g"));
    var page=str.indexOf('<input name="DELMESSAGES" value="Delete Messages" type="submit">')>0;
    page=page||(str.indexOf('<input name="DELTHREADS" value="Delete Threads" type="submit">')>0);
    if(locations!=null&&!page){
        if(!str)
            return;
        //remove duplicate locations so paper processing isn't extremely slow
		locations=locations.sort();
		var last=locations[0];
		for(var i=1;i<locations.length;i++){
			if(last==locations[i]){
				locations.splice(i,1);
				i--;
			}
			else 
				last=locations[i];
        }
        for(var i=0;i<locations.length;i++){
            var index=locations[i].indexOf(":");
            var kd=locations[i].substring(0, index);
			var island=locations[i].substring(index+1);
			var link="<a href='http://"+GetServer(true)+".swirve.com/scores.cgi?ks="+kd+"&is="+island+"'>"+kd+":"+island+"</a>";
			str=str.replace(new RegExp(locations[i],'g'), link);
        }
        return str;
    } 
    else
		return nullIfNoLinks?null:str;
}

//make links clickable
function ClickableLinks(){
	var str=ClickableLinksInStr(document.body.innerHTML, true);
    if(str!=null)
		document.body.innerHTML=str;
}

if((location.host=="uboards.swirve.com"||location.host=="uboards3.swirve.com")&&inURL("board.cgi")){
	ClickableLinks();
}

function Seraphiel(){
    var version="0.8";
    var fullname='<a href="http://jivlain.wordpress.com/seraphiel">http://jivlain.wordpress.com/Seraphiel</a> v'+version;
    
    if(document.getElementsByTagName("td").length>6){
        var newmsg=document.getElementsByTagName("td")[6].innerHTML;
        if(newmsg.indexOf("NEW MSG")>=0){
            document.getElementsByTagName("td")[5].innerHTML+=" | "+newmsg;
            document.getElementsByTagName("tr")[1].deleteCell(5);
        }
        newmsg=null;
    }
    
    //checks if we're actually on one of the hall of honours pages
    function increasePageIfIsChart(){
		var str=location.href;
		if(str.indexOf(".htm")>0)
			if(str.indexOf("land")>0||str.indexOf("nw")>0||str.indexOf("honor")>0||str.indexOf("Honor")>0)
				document.body.innerHTML+="<br><br><br>";
	}
	increasePageIfIsChart();
    
    function replaceAll(original, search, replace){
		if(original.replace)
			return original.replace(new RegExp(search, "gi"), replace);
		return original;        
    }
                
	//clean up a string (eg before parsing it as an int)
	function clean(str){
		if(!str)
			return;
		return replaceAll(replaceAll(striptags(str),"\n",""),",","");
	}
    
	//calculate a per-acre ratio
	function calcRatio(num1, num2){
		num1=(""+num1).replace(",","");
		num2=(""+num2).replace(",","");
		var num=nanParseInt(num1)/nanParseInt(num2)+"";
		return ""+new Number(num).toFixed(2);
	}
    
    //strip HTML tags from a string
    //be careful about editing this, it's easy to create an infinite loop
	function striptags(str){
		if(!str)
			return;
		var start=str.indexOf("<");
		while(start>=0){
			var end=str.indexOf(">");
			str=str.replace(str.substring(start, end+1), "");
			start=str.indexOf("<");
		}
		return str;
	}
	
	function stripcommas(str){
		if(!str)
			return;
		return str.replace(",", "");
	}
    
    //checks whether you are in the currently stored kingdom
    function isMyKingdom(kd){
        var kingdom=GM_getValue("kingdom"+GetServer(false));
        return kd==kingdom;
    }
    
	//finds a table containing some string
	function findTable(str){
		var tables=document.getElementsByTagName("table");
		for(var i=0;i<tables.count;i++)
			if(tables[i].innerHTML.indexOf(str)>=0)
				return tables[i];
	}    
    
	function insertSeparator(str, delimiter){
		var start=0;
		var end= str.length%3;
		var arr=new Array();
		var i=0;
		while(end<=str.length){
			arr[i]=str.substring(start, end);
			start=end;
			end+=3;
			i++;
		}
		str=arr.join(delimiter);
		if(str.charAt(0)==",")
			str=str.substring(1);
		return str;
	}
	
	function targetKdLink(index, y){
		var inputs=document.getElementsByTagName('input');
		var kd=inputs[index].value;
		var is=inputs[index+1].value;
		var str='<a href="http://'+GetServer(true)+'.swirve.com/scores.cgi?ks='+kd+'&is='+is;
		str+='" style="position:absolute;left:0em;top:'+y+'em;">'+kd+':'+is+'</a>';
		whereToAdd().innerHTML+=str;
	}
	
//*****************************************************ADD****************************************************
	function whereToAdd(){
		var cells=document.getElementsByTagName("td");
		if(inURL("aid.cgi")||(inURL("menu.cgi")&&inBody("Please type this 6 letter security code:")))
			return cells[1];
		else if(inURL("magic.cgi")||inURL("thievery.cgi")||inURL("attack.cgi")||inURL("msg.cgi")){
			if(cells.length==1)
				return document.body;
			return cells[cells.length-1];
		}
		else if(inURL("msg.cgi"))
			return cells[1];
		else
			return document.body;
	}  
    
	if(!inURL("magic.cgi")){ //see Note 1 (at bottom of script)
		function ThemeColours(){
			var cells=document.getElementsByTagName("td");
			for(var i=0;i<cells.length;i++){
				//FF automatically verifies the code into XHTML compliance as soon as it gets into the DOM
				var str=cells[i].innerHTML;
				if(!str)
					return;
				//so we need to keep it out of the DOM until we're finished
				str=replaceAll(str, '<font color="#ffeecc">', '<span class="value">');
				str=replaceAll(str, "</font>", "</span>");
				cells[i].innerHTML=str;
			}
		}        
		ThemeColours();
	}
    
    //set up styles
    //styleName: the name of this style
    //body: the style for the <body> element
    //resources: used for the boxes with resources up the top of each screen
    //title: replacement for the title; bluetitle classes
    //label: the font for the left-hand side + units in reports and summaries
    //value: the font for the right-hand side in reports and summaries
    //report: formatting for the report space on report pages. Remember that the font will be dependant on the label
    //        and value settings
    //        this will also be used for the previews and also for the headers on the preferences page (mostly
    //        because it's convenient)
    //button: formatting for Seraphiel's UI buttons. Note that left: is preset and top: defined by individual buttons.
    //        if you want to horizontally align the buttons you will need to adjust each button's generation code
    //kdColumnHead: the header of each column on the kingdom page
    //kdColumn1: the first, third, and fifth columns on the kingdom page
    //kdColumn2: the second, fourth and (if visible) sixth columns on the kingdom page
    //kdProv: a basic province province
    //kdMeKing: where the province is the player and the player is the monarch
    //kdKing: monarch (not the current player)
    //kdMe: current player
    //kdInactive: an inactive player (only visible for monarchs)
    //kdOnline: an online player
    //kdMeKingOnline: where the province is the player and the player is the monarch and are displayed as being online
    //kdKingOnline: the king is online
    //kdMeOline: the player is showing as online
    //kdProtection: a province in protection
    //throneTime: font for the time on the throne page. Not currently implemented
    //rowBg: background colour for rows (currently only on unpinned resource boxes)
    //hiddenMenu: the menu in its hidden state (NOTE: must completely cancel all of visibleMenu's attributes)
    //visibleMenu: the menu in its visible state (NOTE: must completely cancel all of hiddenMenu's attributes)
    //msg: received messages are shown in this colour
    function Style(styleName, body, resources, title, label, value, report, button, link, vlink, kdColumnHead, kdColumn1, kdColumn2, kdProv, kdMeKing, kdKing, kdMe, kdInactive, kdOnline, kdMeKingOnline, kdKingOnline, kdMeOnline, kdProtection, throneTime, rowBg, hiddenMenu, visibleMenu, msg){
        this.styleName=styleName;
        this.body=body;
        this.resources=resources;
        this.title=title;
        this.label=label;
        this.value=value;
        this.report=report ;
        this.button=button;
        this.link=link;
        this.vlink=vlink;
        this.kdColumnHead=kdColumnHead;
        this.kdColumn1=kdColumn1;
        this.kdColumn2=kdColumn2;
        this.kdProv=kdProv ;
        this.kdMeKing=kdMeKing;
        this.kdKing=kdKing;
        this.kdMe=kdMe;
        this.kdInactive=kdInactive;
        this.kdOnline=kdOnline;
        this.kdMeKingOnline=kdMeKingOnline;
        this.kdKingOnline=kdKingOnline;
        this.kdMeOnline=kdMeOnline;
        this.kdProtection=kdProtection;
        this.throneTime=throneTime;
        this.rowBg=rowBg;
        this.hiddenMenu=hiddenMenu;
        this.visibleMenu=visibleMenu;
        this.msg=msg;
    }
    
    function CreateStyle(name){
		return new Style(name, "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "");
	}
    
    function GetStyle(StyleNum){
        var style;
        switch(StyleNum){
		case 0:
			style=CreateStyle("Utopia");
			style.body="{background-color:#000000;color:#fffffe;background-image:none;}";
			style.resources="{background-color:#400000;color:#fffffe;position:fixed;top:0;border:1px solid #400000;padding:1px 1em 1px 1em;left:10em;left:10em;white-space:nowrap;}";
			style.title="{background-color:#400000;color:#fffffe;width:100%;}";
			style.label="{color:#b0b0b0;}";
			style.value="{color:#ffeecc;font-weight:bold;}";
			style.report="{background-color:#000040;color:#ffeecc;}";
			style.button="{position:fixed;left:0;cursor:pointer;width:10em;height:3em;background-color:#003366;color:#fff}";
			 style.link="{color:#ffeecc;text-decoration:underline;}";
			style.vlink="{color:#ffddbb;text-decoration:underline;}";
			style.kdColumnHead="{background-color:#000040;cursor:pointer;}";
			style.kdColumn1="{background-color:#000000;color:#ffffff;}";
			style.kdColumn2="{background-color:#303030;color:#ffffff;}";
			style.kdProv="{color:#ffffff;}";
			style.kdMeKing="{color:#ffaaaa;font-weight:bold;}";
			style.kdKing="{color:#ffaaaa;}";
			style.kdMe="{color:#66ccff;font-weight:bold;}";
			 style.kdOnline="{color:cyan;}";
			style.kdMeKingOnline="{color:#ffaaaa;font-weight:bold;}";
			style.kdKingOnline="{color:#ffaaaa;}";
			style.kdMeOnline= "{color:#66ccff;font-weight:bold;}";
			style.kdInactive="{color:yellow;}";
			style.kdProtection="{color:#99ffbb;}";
			style.throneTime="{color:#a0a0a0;}";
			style.rowBg="#400000";
			style.msg="{color:#ffffff;}";
			break;
        case 1:
			style=CreateStyle("Crikey!");
			style.body="{background-color:#006600;color:#ffff00;background-image:none;}";
			style.resources="{background-color:#003300;color:#ffff00;position:fixed;top:0;border:1px solid #ffff00;padding:1px 1em 1px 1em;left:10em;white-space:nowrap;}";
			style.title="{background-color:#003300;color:#ffff00;width:100%;}";
			style.label="{color:#ffff00;}";
			style.value="{color:#ffd700;font-weight:bold;}";
			style.report="{background-color:#004400;color:#ffff00;}";
			style.button="{position:fixed;left:0;cursor:pointer;width:10em;height:3em;background-color:#00ff00;color:#000000}";
			style.link="{color:#00aa00;text-decoration:underline;}";
			style.vlink="{color:#006600;text-decoration:underline;}";
			style.kdColumnHead="{background-color:#00ff00;color:#003300;cursor:pointer;}";
			style.kdColumn1="{background-color:#006600;color:#ffff00;}";
			style.kdColumn2="{background-color:#004400;color:#ffff00;}";
			style.kdProv="{color:#ffffff;}";
			style.kdMeKing="{color:#ffaaaa;font-weight:bold;}";
			style.kdKing="{color:#ffaaaa;}";
			style.kdMe="{color:#66ccff;font-weight:bold;}";
			style.kdOnline="{color:cyan;}";
			style.kdMeKingOnline="{color:#ffaaaa;font-weight:bold;}";
			style.kdKingOnline="{color:#ffaaaa;}";
			style.kdMeOnline= "{color:#66ccff;font-weight:bold;}";
			style.kdInactive="{color:yellow;}";
			style.kdProtection="{color:#99ffbb;}";
			style.throneTime="{color:#a0a0a0;}";
			style.rowBg="#003300";
			style.msg="{color:#ffff00;}";
			break;
        case 2:
			style=CreateStyle("Stars and Stripes Forever");
			style.body="{background-color:#ffffff;color:#aa0000;background-image:none;}";
			style.resources="{background-color:#ffffff;color:#0000ff;position:fixed;top:0;border:1px solid #ff0000;padding:1px 1em 1px 1em;left:10em;white-space:nowrap;}";
			style.title="{background-color:#ffffff;color:#0000ff;font-weight:bold;width:100%;}";
			style.label="{color:#ff0000;}";
			style.value="{color:#0000aa;font-weight:bold;}";
			style.report="{background-color:#ffffff;color:#0000ff;}";
			style.button="{position:fixed;left:0;cursor:pointer;width:10em;height:3em;background-color:#0000ff;color:#ffffff}";
			style.link="{color:#0000ff;text-decoration:underline;}";
			style.vlink="{color:#0000aa;text-decoration:underline;}";
			style.kdColumnHead="{background-color:#0000ff;cursor:pointer;color:#ffffff}";
			style.kdColumn1="{background-color:#ff4444;color:#ffffff;}";
			style.kdColumn2="{background-color:#4444ff;color:#ffffff;}";
			style.kdProv="{color:#ffffff;}";
			style.kdMeKing="{color:#000000;font-weight:bold;text-decoration:underline;}";
			style.kdKing="{color:#000000;text-decoration:underline;}";
			style.kdMe="{color:#000000;font-weight:bold;}";
			style.kdOnline="{color:cyan;}";
			style.kdMeKingOnline="{color:#000000;font-weight:bold;}";
			style.kdKingOnline="{color:#000000;text-decoration:underline}";
			style.kdMeOnline="{color:#66ccff;font-weight:bold;}";
			style.kdInactive="{color:yellow;}";
			style.kdProtection="{color:#00ff00;}";
			style.throneTime= "{color:#a0a0a0;}";
			style.rowBg="#ffffff";
			style.msg="{color:#0000ff;}";
			break;
        case 3:
			style=CreateStyle("Dutch Courage");
			style.body="{background-color:#ffa500;color:#000000;background-image:none;}";
			style.resources="{background-color:#ff8c00;color:#ffffff;position:fixed;top:0;border:1px solid #ffffff;padding:1px 1em 1px 1em;left:10em;white-space:nowrap;}";
			style.title="{background-color:#ffffff;color:#0000ff;font-weight:bold;width:100%;}";
			style.label="{color:#000000;}";
			style.value="{color:#ffffff;font-weight:bold;}";
			style.report="{background-color:#ff8c00;color:#ffffff;}";
			style.button="{position:fixed;left:0;cursor:pointer;width:10em;height:3em;background-color:#ff8c00;}";
			style.link="{color:#aa4c00;text-decoration:underline;}";
			style.vlink="{color:#aa3c00;text-decoration:underline;}";
			style.kdColumnHead="{background-color:#ff8c00;cursor:pointer;}";
			style.kdColumn1="{background-color:#dd8500;color:#ffffff;}"; //ffa500
			style.kdColumn2="{background-color:#dd7500;color:#ffffff;}"; //ffb500
			style.kdProv="{color:#ffffff;}";
			style.kdMeKing="{color:#000000;font-weight:bold;}";
			style.kdKing="{color:#000000;}";
			style.kdMe="{color:#66ccff;font-weight:bold;}";
			 style.kdOnline="{color:cyan;}";
			style.kdMeKingOnline="{color:#000000;font-weight:bold;}";
			style.kdKingOnline="{color:#000000;}";
			style.kdMeOnline= "{color:#66ccff;font-weight:bold;}";
			style.kdInactive="{color:yellow;}";
			style.kdProtection="{color:#99ffbb;}";
			style.throneTime="{color:#000000;}";
			style.rowBg="#ff8c00";
			style.msg="{color:#000000;}";
			break;
        case 4:
			style=CreateStyle("Teh 1");
			style.body="{background-color:#000000;color:#00ff00;background-image:none;}";
			style.resources="{background-color:#444444;color:#00ff00;position:fixed;top:0;border:1px solid #00ff00;padding:1px 1em 1px 1em;left:10em;white-space:nowrap;}";
			style.title="{background-color:#444444;color:#00ff00;font-weight:bold;width:100%;}";
			style.label="{color:#00ff00;}";
			style.value="{color:#ffffff;font-weight:bold;}";
			style.report="{background-color:#444444;color:#00ff00;}";
			style.button="{position:fixed;left:0;cursor:pointer;width:10em;height:3em;background-color:#444444;color:#00ff00}";
			style.link="{color:#aaffaa;text-decoration:underline;}";
			style.vlink="{color:#66ff66;text-decoration:underline;}";
			style.kdColumnHead="{background-color:#444444;color:#00ff00;cursor:pointer;}";
			style.kdColumn1="{background-color:#222222;color:#ffffff;}";
			style.kdColumn2="{background-color:#666666;color:#ffffff;}";
			style.kdProv="{color:#ffffff;}";
			style.kdMeKing="{color:#00ff00;font-weight:bold;}";
			style.kdKing="{color:#ffaaaa;}";
			style.kdMe="{color:#00aa00;font-weight:bold;}";
			style.kdOnline="{color:cyan;}";
			style.kdMeKingOnline="{color:#00aa00;font-weight:bold;}";
			style.kdKingOnline="{color:#00ff00;}";
			style.kdMeOnline= "{color:#00aa00;font-weight:bold;}";
			style.kdInactive="{color:yellow;}";
			style.kdProtection="{color:#aaaaff;}";
			style.throneTime="{color:#aaffaa;}";
			style.rowBg="#444444";
			style.msg="{color:#ffffff;}";
			break;
        case 5:
			style=CreateStyle("Comrade Mehul");
			style.body="{background-color:#000000;color:#ff0000;background-image:none;}";
			style.resources="{background-color:#000000;color:#ffffff;position:fixed;top:0;border:1px solid #ff0000;white-space:nowrap;left:10em;padding:1px 1em 1px 1em;}";
			style.title="{background-color:#ff0000;color:#000000;width:100%;}";
			style.label="{color:#ffffff;}";
			style.value="{color:#ffffff;font-weight:bold;}";
			style.report="{background-color:#000000;color:#aa0000;}";
			style.button="{position:fixed;left:0;cursor:pointer;width:10em;height:3em;background-color:#aa0000;color:#000000}";
			 style.link="{color:#ffffff;text-decoration:underline;}";
			style.vlink="{color:#aaaaaa;text-decoration:underline;}";
			style.kdColumnHead="{background-color:#440000;cursor:pointer;}";
			style.kdColumn1="{color:#aa0000;background-color:#000000;}";
			style.kdColumn2="{color:#cc0000;background-color:#000000;}";
			style.kdProv="{color:#ffffff;}";
			style.kdMeKing="{color:#ff0000;font-weight:bold;}";
			style.kdKing="{color:#ff0000;}";
			style.kdMe="{color:#66ccff;font-weight:bold;}";
			style.kdOnline="{color:cyan;}";
			style.kdMeKingOnline="{color:#ff0000;font-weight:bold;}";
			style.kdKingOnline="{color:#ff0000;}";
			style.kdMeOnline= "{color:#66ccff;font-weight:bold;}";
			style.kdInactive="{color:yellow;}";
			style.kdProtection="{color:#99ffbb;}";
			style.throneTime="{color:#ff0000;}";
			style.rowBg="#000000";
			style.msg="{color:#ffffff;}";
			break;
        case 6:
			style=CreateStyle("Starbright");
			style.body="{background-color:#000000;color:#ffff00;background-image:none;}";
			style.resources="{background-color:#444444;color:#ffff00;position:fixed;top:0;border:1px solid #ffff00;white-space:nowrap;left:10em;padding:1px 1em 1px 1em;}";
			style.title="{background-color:#444444;color:#ffff00;font-weight:bold;width:100%;}";
			style.label="{color:#ffff00;}";
			style.value="{color:#ffffff;font-weight:bold;}";
			style.report="{background-color:#444444;color:#ffff00;}";
			style.button="{position:fixed;left:0;cursor:pointer;width:10em;height:3em;background-color:#444444;color:#ffff00}";
			style.link="{color:#ffffaa;text-decoration:underline;}";
			style.vlink="{color:#ffff66;text-decoration:underline;}";
			style.kdColumnHead="{background-color:#444444;color:#ffff00;cursor:pointer;}";
			style.kdColumn1="{background-color:#222222;color:#ffffff;}";
			style.kdColumn2="{background-color:#666666;color:#ffffff;}";
			style.kdProv="{color:#ffffff;}";
			style.kdMeKing="{color:#ffff00;font-weight:bold;}";
			style.kdKing="{color:#ffaaaa;}";
			style.kdMe="{color:#aaaa00;font-weight:bold;}";
			 style.kdOnline="{color:cyan;}";
			style.kdMeKingOnline="{color:#aaaa00;font-weight:bold;}";
			style.kdKingOnline="{color:#ffff00;}";
			style.kdMeOnline= "{color:#aaaa00;font-weight:bold;}";
			style.kdInactive="{color:yellow;}";
			style.kdProtection="{color:#aaaaff;}";
			style.throneTime="{color:#aaffaa;}";
			style.rowBg="#000000";
			style.msg="{color:#ffffff;}";
			break;
		case 7:
			style=CreateStyle("Tranquility");
			style.body="{background-color:#000000;color:#aaaaff;background-image:none;}";
			style.resources="{background-color:#444444;color:#aaaaff;position:fixed;top:0;border:1px solid #ffff00;white-space:nowrap;left:10em;padding:1px 1em 1px 1em;}";
			style.title="{background-color:#444444;color:#aaaaff;font-weight:bold;width:100%;}";
			style.label="{color:#aaaaff;}";
			style.value="{color:#ffffff;font-weight:bold;}";
			style.report="{background-color:#444444;color:#aaaaff;}";
			style.button="{position:fixed;left:0;cursor:pointer;width:10em;height:3em;background-color:#444444;color:#aaaaff}";
			style.link="{color:#ffffaa;text-decoration:underline;}";
			style.vlink="{color:#ffff66;text-decoration:underline;}";
			style.kdColumnHead="{background-color:#444444;color:#aaaaff;cursor:pointer;}";
			style.kdColumn1="{background-color:#222222;color:#ffffff;}";
			style.kdColumn2="{background-color:#666666;color:#ffffff;}";
			style.kdProv="{color:#ffffff;}";
			style.kdMeKing="{color:#aaaaff;font-weight:bold;}";
			style.kdKing="{color:#aaffff;}";
			style.kdMe="{color:#aa00aa;font-weight:bold;}";
			style.kdOnline="{color:cyan;}";
			style.kdMeKingOnline="{color:#aa00aa;font-weight:bold;}";
			style.kdKingOnline="{color:#aaaaff;}";
			style.kdMeOnline= "{color:#aa00aa;font-weight:bold;}";
			style.kdInactive="{color:yellow;}";
			style.kdProtection="{color:#aaaaff;}";
			style.throneTime="{color:#aaaaff;}";
			style.rowBg="#000000";
			style.msg="{color:#ffffff;}";
			break;
		/*case 8: //this theme (black and white) is still in progress
			style=CreateStyle("Magpie");
			style.body="{background-color:#ffffff;color:#000000;background-image:none;}";
			style.resources="{background-color:#eeeeee;color:#000000;position:fixed;top:0;border:1px solid #000000;white-space:nowrap;left:10em;padding:1px 1em 1px 1em;}";
			style.title="{background-color:#ffffff;color:#000000;font-weight:bold;width:100%;}";
			style.label="{color:#444444;}";
			style.value="{color:#000000;font-weight:bold;}";
			style.report="{background-color:#aaaaaa;color:#000000;}";
			style.button="{position:fixed;left:0;cursor:pointer;width:10em;height:3em;background-color:#444444;color:#ffffff}";
			style.link="{color:#0000aa;text-decoration:underline;}";
			style.vlink="{color:#aa0000;text-decoration:underline;}";
			style.kdColumnHead="{background-color:#444444;color:#dddddd;cursor:pointer;}";
			style.kdColumn1="{background-color:#dddddd;color:#000000;}";
			style.kdColumn2="{background-color:#bbbbbb;color:#000000;}";
			style.kdProv="{color:#000000;}";
			style.kdMeKing="{color:#aaaaff;font-weight:bold;}";
			style.kdKing="{color:#aa0000;}";
			style.kdMe="{color:#aa00aa;font-weight:bold;}";
			style.kdOnline="{color:navy;}";
			style.kdMeKingOnline="{color:#aa00aa;font-weight:bold;}";
			style.kdKingOnline="{color:#aa0000;}";
			style.kdMeOnline= "{color:#aa00aa;font-weight:bold;}";
			style.kdInactive="{color:00aa00;}";
			style.kdProtection="{color:#aaaaff;}";
			style.throneTime="{color:#aaaaff;}";
			style.rowBg="#000000";
			style.msg="{color:#ffffff;}";
			break; */
        default:
            return null;
        }        
        
		//16x16 "xmag" icon from the Nuvola set by David Vignoni (http://icon-king.com/?p=15) 
		//Licensed under the LGPL (http://www.gnu.org/licenses/lgpl.html)
		var zoom='data:image/png;base64,' +
		'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29m' +
		'dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAN6SURBVHjaYrS2smL4z8DIwM/H7aynq90oI6+px8Iu' +
		'wPnl09u/Vy8efXbgwL5lDx49a2FgYPzBAFSJDgACiFlCUpJBRIgv198/ZJ6WVawSn7QJu6CEGhOXiAaL' +
		'qJyhoIaStN2bF/ecXr5+swmo/hu6AQABxKyipOAaHhEzT9YsjpORX4hBQYadQUKCjUFQhJOBSUCE4Sen' +
		'MoOkAJvsvRvntD5/+bYc3QCAAGIOCvBZbOGTrfiCiYdBgJeB4e8/BobPQMd+/QV0MDMjwx9uLoZf/wUY' +
		'GD/cVroBBEA915ANAAggJn0DU70v7EIMn4AaXn5iYHj2GUh/BWIg/fQ9A8PP3wwM/NIKDDIqhiwCvNxR' +
		'6C4ACCAWPiExTlZWBgYuFqCtQMUMQMwIpP4Dw4sRyOAHinOLcTA8EhRl4OTkVHr/6StQhOEPzACAAGL5' +
		'9vXLX1keBmYWZgaG70DNP/5ANDMzMTBwAJUKA731D+iv3z8+M/z8+esfugsAAojp7Mmjzzn+fmUQ5mNg' +
		'kAJiWX4GBjkBBgYZIC3Jw8AgAjTg0+vHDPdvnGd4++nzRWTbQQAggJjfvnkjZqSrZSurosrABvQKBxBz' +
		'gjAbAwMv0IDv334znN63nWHtknlfOT9+ylUCBg3QbAZgsDKAnAMQQMwfPn06/PLpI2dFKUlZEXEpBnZ2' +
		'VgZ2FogXXr98wXBi9w4GVqBh1lKSzNqPbkm/+vh1F9Dcb7xAA74ADQAIAEEAvv8DCAkJ/ePk467Py8cr' +
		'9e3pIvbx7gPo4+MA1M3JALmuqQCspJ30JQQEA2eCWQM9Pu4m5crgT9Dq+bECAAHy7wAAAAKIgYubm4Gf' +
		'nx/sH35+vhA5Gen1WpoaF+XlZc9xsLMvBArbZMmKbPvSZ/L//xWr/59P+Pyv1Be9qsvAIC0OlAQIILgB' +
		'rMC4FBQUhMcOKIBhHGMGBrEaQYYbH7O5/v+/avP/03Hf/2VG4teFGRllAQKImZWNDehfJobfv38D/c/O' +
		'8P37dwYWFpZ/////h+ccRWamr5e//V/74O5vT7Pvr0UFnIUYDPSkRLZteyYDEEAsDEQAJmCCAsbm8+3v' +
		'GNx+rfi+u4zlsubFrzwMz379YQQIIEaQF1hZWBi+ffvGwMvLy/Du3TuQCxj+/v3LAHOEDQvQN3/+gbMi' +
		'MIVLcrExTHzxi4HxJQNDPUCAAQA4ARwJcntJDAAAAABJRU5ErkJggg==';
		style.hiddenMenu='{position:fixed;left:0;top:0;overflow:hidden;padding-left:16px;padding-top:16px;cursor:default;background-image:url(' + zoom + ');background-position:bottom right;background-repeat:no-repeat;width:0;height:0;}';
		style.visibleMenu='{width:10em;padding:0;overflow:visible;}'
        return style;
    }
    
    var fixResources=GM_getValue("fixResources");
    var autoHide=GM_getValue("autoHide");
    
    function SetStyle(){
        var styleNum=nanParseInt(GM_getValue("style"), 0);
        return GetStyle(styleNum);
    }
        
    var CurrentStyle=SetStyle();
    //implement global styles
    GM_addStyle(".swirvemsg{font-color:red;}");
    GM_addStyle("body"+CurrentStyle.body);
    GM_addStyle(".resources"+CurrentStyle.resources);
    GM_addStyle(".bluetitle,.title"+CurrentStyle.title);
    GM_addStyle(".button"+CurrentStyle.button);
    GM_addStyle("#topMenu"+CurrentStyle.hiddenMenu);
    GM_addStyle(".gray,.label"+CurrentStyle.label);
    GM_addStyle(".y,.value"+CurrentStyle.value);
    GM_addStyle(".unit"+CurrentStyle.value);
    GM_addStyle(".report"+CurrentStyle.report);
    GM_addStyle("a:link"+CurrentStyle.link);
    GM_addStyle("a:visited"+CurrentStyle.vlink);
    GM_addStyle(".value"+CurrentStyle.value);
    GM_addStyle(".report"+CurrentStyle.report);
    GM_addStyle("img{background-color:#000000;}");
    GM_addStyle(".monarchMsg"+CurrentStyle.report.substring(0, CurrentStyle.report.length-1)+'position:fixed;width:75%;text-align:left;left:0;bottom:0;}');
    GM_addStyle(".msg"+CurrentStyle.msg);
    
//************************************************RESOURCES BAR***********************************************
    var ProvNetworth="";
    var rows=document.getElementsByTagName("tr");
    if(rows.length>1&&rows[1].cells.length>4)
		ProvNetworth=nanParseInt(rows[1].cells[4].innerHTML.substring(4).replace(",",""));
    function PinResources(){
		var resourceBar='<div class="resources" style="margin-left:4em;font-size:0.85em;">';
        var rows=document.getElementsByTagName ("tr");
        for(var i=0;i<rows.length;i++){
            var str=rows[i].innerHTML;
            if(str&&str.indexOf("<tr")<0&&str.indexOf("Money:")>=0&&str.indexOf("Food:")>=0&&str.indexOf("Runes:")>=0&&str.indexOf("Peasants:")>=0&&str.indexOf("NW:")>=0){
				resourceBar='<div class="resources" style="margin-left:4em;font-size:0.85em;">';
                for(var j=0;j<rows[i].cells.length;j++){
					if(j==2){
						var food=nanParseInt(rows[i].cells[2].innerHTML.replace(',', '').substr(6));
						if(food<10000)
							resourceBar+='<span style="background-color:#ff9999;color:#000000;font-weight:bold;">';
						
					}
                    resourceBar+=rows[i].cells[j].innerHTML;
                    if(j==2&&food<10000)
						resourceBar+='</span>';
                    if(j<rows[i].cells.length-1)
						resourceBar+=' | ';
					rows[i].cells[j].style.display="none";
				
                }
            }
        }
        resourceBar+="</div>";
        if(resourceBar.length>40)
			whereToAdd().innerHTML+=resourceBar;
    }
    
    function ThemeResources(){
        var rows=document.getElementsByTagName("tr");
        if(rows.length>1&&rows[1].cells.length>2){
            //rows[1].bgColor= CurrentStyle.rowBg;
			var food=nanParseInt(rows[1].cells[2].innerHTML.replace(',', '').substr(6));
			if(food<10000){
				rows[1].cells[2].bgColor="#ff9999";
				rows[1].cells[2].style.color="#000000";
				rows[1].cells[2].style.fontWeight="bold";
			}
		}
    }
    
	if(fixResources)
		PinResources();
	else
		ThemeResources();
    
//************************************************MONARCH MSG***********************************************
	function GetTime(){
		if(inURL("menu.cgi")&&!inBody("As a security measure within the game")&&!inBody("To ensure you provided a valid email address")){  
			var ths=document.getElementsByTagName('th');
			var index=ths.length-1;
			if(document.body.innerHTML.indexOf("Stay In Kingdom?"))
				index--;
			var str=ths[index].innerHTML;
			if(!str)
				return;
			GM_setValue("Date"+GetServer(false), str.substring(str.indexOf("as of")+5));
		}        
	}      
	function MonarchMsg(){
		if(inURL("enter.cgi")){
			var cells=document.getElementsByTagName ("td");
			if(cells.length>15)
				GM_setValue('MonarchMsg'+GetServer(false), striptags(cells[15].innerHTML));
		}
		else if(!inURL("music")&&!inURL("top.htm")){
			var MonarchMsg=GM_getValue('MonarchMsg'+GetServer(false));
			var UtoDate=GM_getValue('Date'+GetServer(false));
			var str="<div id='MonarchMsg' class='monarchMsg'>";
			if(MonarchMsg){
				str+='<b>Monarch message:</b> <span class="value">'+MonarchMsg+'</span>';
				if(UtoDate)
					str+='<br />';
			}
			if(UtoDate)
				str+='<b>Utopian date:</b> <span class="value">'+UtoDate+'</span> (updated on throne page visits)';
			str+="</div>";
			whereToAdd().innerHTML+=str;
		}
	}
	GetTime();
	MonarchMsg();		

	//off/def values for units of each race
	function Strength(OffSpec, DefSpec, EliteOff, EliteDef, MercPoints){
		this.OffSpec=OffSpec;
		this.DefSpec=DefSpec ;
		this.EliteOff=EliteOff;
		this.EliteDef=EliteDef;
		this.MercPoints=MercPoints;
	}

	function GetStrength(RaceIndex){
		switch(RaceIndex){ //ospec dspec oleet dleet merc
			case 0: return new Strength(5, 6, 6, 3, 3); //human
			case 1: return new Strength(5, 5, 6, 4, 3); //elf
			case 2: return new Strength(5, 5, 7, 4, 3); //dwarf
			case 3: return new Strength(5, 5, 8, 2, 3); //orc
			case 4: return new Strength(5, 5, 5, 4, 3); //gnome
			case 5: return new Strength(6, 5, 5, 6, 3); //dark elf
			default: return new Strength(0, 0, 0, 0); //some default values to display if we can't find the race correctly
		}
	}

	//gets an index for each race in the  array
	function GetRaceIndex(race){
		switch(race){
			case "Human": return 0;
			case "Elf": return 1;
			case "Dwarf": return 2;
			case "Orc": return 3;
			case "Gnome": return 4;
			case "Dark Elf": return 5;
			default: return 8;
		}
	}

	function GetRaceIndexFromElite(elite){
		switch(elite){
		case "Knights": return 0;
		case "Elf Lords": return 1;
		case "Berserkers": return 2;
		case "Ogres": return 3;
		case "Golems": return 4;
		case "Drow": return 5;
		default:
			return 8;
		}
	}
    
	function extractPersonality(ruler){
		if(ruler.substring(0, 12)=="The Wealthy ")
			return "Merchant";
		else if(ruler.substring(ruler.length-10)==" the Rogue")
			return "Rogue";
		else if(ruler.substring(ruler.length-12)==" the Warrior")
			return "Warrior";
		else if(ruler.substring(0, 9)=="The Wise ")
			return "Sage";
		else if(ruler.substring(0, 11)=="The Humble ")
			return "Shepherd";
		else if(ruler.substring(0, 11)=="The Heroic ")
			return "War Hero";
		else if(ruler.substring(ruler.length-11)==" the Mystic")
			return "Mystic";
		else if(ruler.substring(ruler.length-14)==" the Craftsman")
			return "Artisan";
		else
			return "Unknown";
	}
    
	function findTextInCell(str){
		if(!str)
			return;
		var cells= document.getElementsByTagName("td");
		for(var i=0;i<cells.length;i++){
			if(cells[i].innerHTML.indexOf("<tr")<0&&cells[i].innerHTML.indexOf("<td")<0&&cells[i].innerHTML.indexOf(str)>=0)
				return cells[i];
		}
	}

	function findCell(str){
		if(!str)
			return;
		var cells=document.getElementsByTagName("td");
		for(var i=0;i< cells.length;i++){
			if(cells[i].innerHTML.indexOf("<tr")<0&&cells[i].innerHTML.indexOf("<td")<0&&cells[i].innerHTML.indexOf(str)==0)
				return cells[i];
		}
	}

	function findHeader(str){
		if(!str)
			return;
		var cells=document.getElementsByTagName("th");
		for(var i=0;i<cells.length ;i++){
			if(cells[i].innerHTML.indexOf("<tr")<0&&cells[i].innerHTML.indexOf("<td")<0&&cells[i].innerHTML.indexOf(str)==0)
				return cells[i];
		}
	}

	function findStringsInTable(arr){
		if(!arr.length)
			return;
		var tables=document.getElementsByTagName("table");
		for(var i=0;i< tables.length;i++){
			var str=tables[i].innerHTML;
			if(!str)
				break;
			if(str.indexOf("<table")<0){
				var works=true;
				for(var j=0;j< arr.length;j++){
					if(str.indexOf(arr[j])<0)
						works=false;
				}
				if(works==true)
					return tables[i];
			}
		}
	}

	function nanParseInt(str, def){
		var val=parseInt(str);
		if(""+val=="NaN")
			val=def;
		return val;
	}

	function nanParseFloat(str){
		var val=parseFloat(str);
		if(""+val=="NaN")
			val=0;
		return val;
	}

	function ShowTags(page){            
		var str=GM_getValue("tags"+GetServer(false));
		if(!str)
			return;        
		if(str!=null&&str.indexOf("|")>=0){
			var tags=str.split ("|");
			var str="";        
			var comments=GM_getValue("tagcomments"+GetServer(false)).split("|");
			if(tags.length>0&&comments.length==tags.length ){
				for(var i=1;i<tags.length;i++){
					var kd=tags[i].split(":")[0];
					var island=tags[i].split(":")[1];
					var loc=kd+":"+island;
					if(tags.indexOf(loc)>=0){                    
						str+="<a href='http://"+GetServer(true)+".swirve.com/"+page+".cgi?ks="+kd+"&is="+island+"' title='";
						str+=comments[i]+"'>"+loc+"</a><br>\n";
					}
				}
				document.body.innerHTML+="<div id='lblTags' class='report' style='position:fixed;top:2em;width:5em;right:0;'>"+str+"</div>";
			}
		}                        
	}		

	function topMenu(str){
		if(autoHide){
			GM_addStyle('.button{position:static;}');
			return '<div id="topMenu">'+str+'</div>';
		}
		else
			return str;
	}        

	function createButton(name, height, text){
		return "<div id='"+name+"' class='button' style='top:"+(height*3)+"em;'>"+text+"</div>";
	}
	
//*******************************************T/M SUPPORT FUNCTIONS*******************************************
	function ShowPostTags(page){
		var str=GM_getValue("tags"+GetServer(false));
		if(!str)
			return;
		if(str.indexOf("|")>=0){
			var tags=str.split("|");
			var comments=GM_getValue("tagcomments"+GetServer(false)).split("|");
			var str="";
			if(tags.length>0&&comments.length== tags.length){
				for(var i=1;i<tags.length;i++){
					var kd=tags[i].split(":")[0];
					var island=tags[i].split(":")[1];
					var loc=kd+":"+island;
					if(tags.indexOf(loc)>=0){    
						str+="<form action='"+page+".cgi' method='post' id='taglink"+i+"'>";
						str+="<input type='hidden' name='SelectK' value='"+kd+"'>";
						str+="<input type='hidden' name='SelectI' value='"+island+"'>";
						str+="<input type='submit' name='ChangeSelect' value='"+kd+":"+island+"' title='"+comments[i]+"'>";
						str+="</form>\n";
					}
				}
				whereToAdd().innerHTML+="<div id='lblTags' class='report' style='position:fixed;top:2em;width:5em;right:0;'>"+str+"</div>";
			}
		}
	}
	
	function opRecorder(type, selectIndex, tagname, tagindex){
		if(!inBody("Your wizards gather their runes and begin casting")&&!inBody("You send your thieves, and the operation commences..."))
			return;
		var currHour=(new Date()).getHours();
		var lastHour=nanParseInt(GM_getValue('last'+type+GetServer(false)), -1);
		var currTarget=nanParseInt(GM_getValue(type.toLowerCase()+'target'+GetServer(false)), -1);
		var lastTarget=nanParseInt(GM_getValue('lasttarget'+type+GetServer(false)), -1);
		var propname='ops'+type+GetServer(false);
		var text=document.getElementsByTagName(tagname)[tagindex].innerHTML;
		if(currHour!=lastHour){
			GM_setValue('last'+type+GetServer(false), currHour);
			GM_setValue(propname, "");
		}		
		if(currTarget!=lastTarget||currHour!=lastHour){
			GM_setValue('lasttarget'+type+GetServer(false), currTarget);
			var selectName=document.getElementsByTagName('select')[selectIndex];
			text=selectName.options[selectName.selectedIndex].text+': <br />'+text;
		}
		function definedGetValue(name){
			var str=GM_getValue(name);
			if(str=="undefined")
				return "";
			return str;
		}
		
		GM_setValue(propname, definedGetValue(propname)+text+'<br />');
	}
		
//************************************************KINGDOM PAGE***********************************************
	if(inURL("scores.cgi")){
		//local styles
		GM_addStyle(".columnHead"+CurrentStyle.kdColumnHead);
		GM_addStyle(".column1"+CurrentStyle.kdColumn1);
		GM_addStyle(".column2"+CurrentStyle.kdColumn2);
		GM_addStyle(".prov"+CurrentStyle.kdProv);
		GM_addStyle(".meking"+CurrentStyle.kdMeKing);
		GM_addStyle(".king"+CurrentStyle.kdKing);
		GM_addStyle(".me"+CurrentStyle.kdMe);
		GM_addStyle(".inactive"+CurrentStyle.kdInactive);
		GM_addStyle(".online"+CurrentStyle.kdOnline);
		GM_addStyle(".mekingonline"+CurrentStyle.kdMeKingOnline);
		GM_addStyle(".kingonline"+CurrentStyle.kdKingOnline);
		GM_addStyle(".meonline"+CurrentStyle.kdMeOnline);
		GM_addStyle(".protection"+CurrentStyle.kdProtection);
		
		//change the formatting on the kingdom summary section to fit the style
		function SummaryFormatting(){
			var details=document.getElementsByTagName("td")[12];
			var str=details.innerHTML;
			if(!str)
				return;
			str=replaceAll(str, '<font color="#b0b0b0">', '<span class=label>');
			str=replaceAll(str, '<font color="#ffeecc">', '<span class=unit>');
			str=replaceAll(str, '</font>', '</span>');
			details.innerHTML=str;        
			//change the formatting on the legend to fit the style
			var legendCol=15;
			if(GetServer(true)=="u3")
				legendCol=14;
			var legend=document.getElementsByTagName("td")[legendCol];
			var str='Key: <span class="protection">Protection</span> <span class="king">Monarch</span> ';
			str+='<span class="me">You</span> ';
			str+='<span class="inactive">+ = inactive</span> <span class="online">* = online</span>';
			legend.innerHTML=str;
		}
		if(GetServer(true)!="u3")
		  SummaryFormatting();
		document.body.innerHTML+="<br><br>";
			
		ShowTags("scores");

		//sorting related declarations
		var List=new Array(); //the collection of provinces
		var LastSort=-1; //used for toggling ascending/descending sort
		var showratios=false;//GM_getValue("ShowRatio"); //false; //show the ratios? [toggle]
		var currorder=0; //used for the toggle ratios button        
		
		function Prov(ProvName, Race, Land, Networth, Rank, Ratio, Class){
			this.ProvName=ProvName;
			this.Race=Race;
			this.Land=Land;
			this.Networth=Networth;
			this.Rank=Rank;
			this.Ratio=Ratio;
			this.Class=Class;
		}            
				
		//used for sorting ranks as they cannot be sorted alphabetically or numerically
		function GetRankOrder(name){
			switch(name){
				case "DEAD\n":
					return -1;
				case "Peasant\n":
					return 0;
				case "Knight\n":
				case "Lady\n":
					return 1;
				case "Lord\n":
				case "Noble Lady\n":
					return 2;
				case "Baron\n":
				case "Baroness\n":
					return 3;
				case "Viscount\n":
				case "Viscountess\n":
					return 4;
				case "Count\n":
				case "Countess\n":
					return 5;
				case "Marquis\n":
				case "Marchioness\n":
					return 6;
				case "Duke\n":
				case "Duchess\n":
					return 7;
				case "Prince\n":
				case "Princess\n":
					return 8;
				case "King\n":
				case "Queen\n":
					return 9;
			}
		}		
		
		//do a Bubble sort (another algorithm could be used, but why bother? Max 25 items, after all...)
		function Sort(arr, Order){
			cont=true;
			while(cont==true){
				cont=false;
				for(i=NumProvs-1;i>=1;i--){
					for(j=0;j<i;j++)
					{
						if(arr[j]>arr[j+1]){
							var temp=arr[j];
							arr[j]=arr[j+1];
							arr[j+1]=temp;
							temp=Order[j];
							Order[j]=Order[j+1];
							Order[j+1]=temp;
							cont=true;
						}
					}
				}
			}
			return Order;
		}
        
		function GetHeaderCell(index, OrderBy, LastSort){
			var ids=new Array('lblProvince', 'lblRace', 'lblLand', 'lblNw', 'lblRatio', 'lblRank');
			var text=new Array('Province', 'Race', 'Land Acres', 'Net Worth', 'NW/Acre', 'Rank');
			var str='<th class="columnHead" valign="top" ';
			if(index==0)
				str+='width="40%" ';
			str+='id="'+ids[index]+'">'+text[index];
			var arrow="";
			if(OrderBy==index+1){
				if(OrderBy==LastSort) //up arrow
					arrow='data:image/png;base64,' +
						'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAABGdBTUEAALGPC/xhBQAAABh0RVh0U29m' +
						'dHdhcmUAUGFpbnQuTkVUIHYzLjA4ZXKc4QAAAD5JREFUKFNj/P//PwNeAFKAD8M1//v3j+UfA8N/MP73' +
						'jwfFVBRJdEVASUa4TpgksiKcklBFIAey4XUkIV8AANpVhIrQ04nHAAAAAElFTkSuQmCC';
					
				else //down arrow
					arrow='data:image/png;base64,' +
						'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAABGdBTUEAALGPC/xhBQAAABh0RVh0U29m' +
						'dHdhcmUAUGFpbnQuTkVUIHYzLjA4ZXKc4QAAADpJREFUKFNj/P//PwNeAFKADzMA9YPMwIbfg8QhunEp' +
						'+v/fAmE8uiKo1aj2wxQBdcLchdeBYB8S8gUAX2OWy+tQ4oIAAAAASUVORK5CYII=';
				str+='<br /><img align="center" src="'+arrow+'" class="columnHead" />';
			}				
			str+='</th>';
			return str;
		}
		
		function Print(OrderBy){
			var str="<tr>";
			for(var i=0;i<6;i++)
				str+=GetHeaderCell(i, OrderBy, LastSort);
			str+="</tr><tr>";
			//Create order
			//OrderBy: 0=none, 1=prov name, 2=Race, 3=Acres, 4=Networth, 5=Ratio, 6=Rank
			var Order=new Array(NumProvs);
			currorder=OrderBy;
			var i;
			var j;
			var arr=new Array(NumProvs);
			for(i=0;i<window.NumProvs;i++)
				Order[i]=i;
			//load the appropriate array so it can be sorted
			switch(OrderBy){
			case 1: //sort by province name
				for(i=0;i<window.NumProvs;i++)
					arr[i]=List[i].ProvName.toLowerCase();
				break;
			case 2: //sort by race
				for(i=0;i<window.NumProvs;i++)
					arr[i]=List[i].Race.replace("*","").replace("+","");
				break;
			case 3: //sort by landsize
				for(i=0;i<window.NumProvs;i++)
					arr[i]=nanParseInt(replaceAll(List[i].Land,",",""), 0);
				break;
			case 4: //sort by nw
				for(i=0;i<window.NumProvs;i++)
					arr[i]=nanParseInt(replaceAll(List[i].Networth,",",""), 0);
				break;
			case 5: //sort by nw/acre ratio
				for(i=0;i<window.NumProvs;i++)
					arr[i]=nanParseInt(List[i].Ratio, 0);
				break;
			case 6: //sort by rank
				for(i=0;i<window.NumProvs;i++)           
					arr[i]=GetRankOrder(List[i].Rank);
				break;
			default: //no particular order
				for(i=0;i<window.NumProvs;i++)
					arr[i]=i;
				break;
			}
			//Sort!
			if(OrderBy>0){
				Sort(arr, Order);
				//toggle ascension, descension
				if(LastSort==OrderBy){
					Order.reverse();
					LastSort=-1; //go the other way next time
				}
				else
					LastSort=OrderBy;
			}
			//Prov names
			str+='<TD NOWRAP align=left class="column1">';
			for(i=0;i<window.NumProvs;i++)
				str+="<span class='"+List[Order[i]].Class+"'>"+List[Order[i]].ProvName+"</span><br>";
			//Races
			str+="</td><TD align=right class='column2'>";
			for(i=0;i<window.NumProvs;i++)
				str+="<span class='"+List[Order[i]].Class+"'>"+List[Order[i]].Race+"</span><br>";
			//Land
			str+="</td><TD align=right class='column1'>";
			for(i=0;i<window.NumProvs;i++)
				str+="<span class='"+List[Order[i]].Class+"'>"+List[Order[i]].Land+"</span><br>";
			//Networth
			str+="</td><TD align=right class='column2'>";
			for(i=0;i<window.NumProvs;i++)
				str+="<span class='"+List[Order[i]].Class+"'>"+List[Order[i]].Networth+"</span><br>";
			//Rank
			str+="</td><TD align=center class='column1'>";
			for(i=0;i< window.NumProvs;i++)
				str+="<span class='"+List[Order[i]].Class+"'>"+List[Order[i]].Ratio+"</span><br>";
			str+="</td><TD align=right class='column2'>";
			for(i=0;i<window.NumProvs;i++)
				str+="<span class='"+List[Order[i]].Class+"'>"+List[Order[i]].Rank+"</span><br>";
			str+="</td></tr>";
			findStringsInTable(new Array("Province", "Race", "Land Acres", "Net Worth", "NW/Acre", "Rank")).innerHTML=str;
		}
		
		function CreateTMButton(desc, page, ks, is, position){
			var str='<form action="'+page+'.cgi" method="post">';
			str+='<input type="hidden" name="SelectK" value="'+ks+'">';
			str+='<input type="hidden" name="SelectI" value="'+is+'">';
			str+='<input type="submit" name="ChangeSelect" class="button" style="top:'+(position*3.3)+'em;" value="'+desc+'">';
			str+="</form>\n";
			return str;
		}
		
		function AddButtons(){
			var tags=GM_getValue("tags"+GetServer(false));
			var kd=document.getElementsByTagName("input")[0].value;
			var island= document.getElementsByTagName("input")[1].value;
			var tagaction="Tag this kingdom";
			if(tags!=null&&tags.indexOf(kd+":"+island)>0)
				tagaction="Untag this kingdom";                          
			//var str=createButton('btnRatio', 0, 'Toggle Ratio column');
			var str=createButton('btnDefault', 0, 'Ingame prov order');
			str+=createButton('btnTag', 1, tagaction);
			str+=CreateTMButton('Send Message', 'msg', kd, island, 2.4);
			str+=CreateTMButton('Select magic', 'magic', kd, island, 3.4);
			str+=CreateTMButton('Select thievery', 'thievery', kd, island, 4.4);
			whereToAdd().innerHTML+=topMenu(str);
		}
		AddButtons();
		
		
		function CreateProvinceArray(){
			//set up the province array
			window.NumProvs=0;
			for(var i=0;i<25;i++)
				List[i]=new Prov("", "", "", "", "", "", "prov");
			var row=findStringsInTable(new Array("Province", "Race", "Land Acres", "Net Worth", "NW/Acre", "Rank")).getElementsByTagName('tr')[1]; //grab the row in which the lists are displayed
			var cells=row.getElementsByTagName('td'); //grab the cells in said row
			for(var i=0;i<cells.length;i++){ //loop through each cell
				var text=cells[i].innerHTML.split("<br>"); //divide each cell up into arrays
				if(i==0)
					window.NumProvs=text.length-1;
				//use j=1 and List[j-1] because the first line break in the cell is BEFORE the first entry...
				for(var j=1;j< text.length;j++){
					switch(i){
					case 0: //column 0: Province name (also check if they are the monarch, self player, or in protection)
						if(text[j].indexOf('<b><font color="#ffaaaa">')>=0)
							List[j-1].Class="meking";
						else if(text[j].indexOf('<font color="#ffaaaa">')>=0)
							List[j-1].Class="king";
						else if(text[j].indexOf('<font color="#99ffbb">')>=0)
							List[j-1].Class="protection";
						else if(text[j].indexOf("<b>")>=0||text[j].indexOf('<font color="#77ffff">')>=0)
							List[j-1].Class="me";
						List[j-1].ProvName=striptags(text[j]);
						break;
					case 1: //column 1: Race (also check if they are online or inactive)
						if(text[j].indexOf("*")>=0&&List[j-1].Class=="me")
							List[j-1].Class="meonline";
						else if(text[j].indexOf("*")>=0&&List[j-1].Class=="king")
							List[j-1].Class="kingonline";
						else if(text[j].indexOf("*")>=0&&List[j-1].Class=="meking")
							List[j-1].Class="mekingonline";
						else if(text[j].indexOf("*")>=0)
							List[j-1].Class="online";
						else if(text[j].indexOf("+")>=0)
							List[j-1].Class="inactive";
						List[j-1].Race=striptags(text[j]);
						break;
					case 2: //column 2: Land
						List[j-1].Land=striptags(text[j]);
						break;
					case 3: //column 3: networth
						List[j-1].Networth=striptags(text[j]);
						break;
					case 4: //column 4: ratio
						List[j-1].Ratio=striptags(text[j]);
						break;
					case 5: //column 5: rank
						List[j-1].Rank=striptags(text[j]);
						break;
					}
				}
			}
			//calculate nw/acre
			/*for(var i=0;i<NumProvs;i++){
				var land=parseInt(clean(List[i].Land));
				var nw=parseInt(clean(List[i].Networth));
				List[i].Ratio=calcRatio(nw, land)+"gc";
				if(List[i].Ratio.indexOf("NaNgc")>-1)
					List[i].Ratio="0gc";
			}*/
		}
		CreateProvinceArray();
		
		//display the list (unsorted)
		Print(nanParseInt(GM_getValue("SortOrder"), 0));
		//set up an event listener to respond to click events
		document.addEventListener('click', function(event) {
			if(event.target.id=="lblProvince"){ //sort by name
				Print(1);
				GM_setValue("SortOrder", 1);
			}
			else if(event.target.id=="lblRace"){ //sort by race
				Print(2);
				GM_setValue("SortOrder", 2);
			}
			else if( event.target.id=="lblLand"){ //sort by land
				Print(3);
				GM_setValue("SortOrder", 3);
			}
			else if(event.target.id=="lblNw"){ //sort by nw
				Print(4);
				GM_setValue("SortOrder", 4);
			}
			else if(event.target.id=="lblRatio"){ //sort by nw/acre ratio
				Print(5);
				GM_setValue("SortOrder", 5);
			}
			else if(event.target.id=="lblRank"){ //sort by rank
				Print(6);
				GM_setValue("SortOrder", 6);
			}
			else if(event.target.id=="btnRatio"){ //toggle ratio
				showratios=!showratios;
				GM_setValue("ShowRatio", showratios);
				LastSort=currorder;
				Print(LastSort);
			}
			else if(event.target.id=="btnDefault"){ //ingame prov order
				Print(0);
				GM_setValue("SortOrder", 0);
			}  
			else if(event.target.id=="btnTag"){ //tag or untag the kd
				var tags=GM_getValue("tags"+GetServer(false));
				var kd=document.getElementsByTagName("input")[0].value;
				var island=document.getElementsByTagName("input")[1].value;
				var loc=kd+":"+island;
				if(tags+""=="undefined"||tags.indexOf(loc)<0)
				{
					var comment=prompt("Enter a comment","");
					while( comment.indexOf("|")>=0)
						comment=prompt("Please do not include any pipes (|) in your comment. Enter a comment...","");
					GM_setValue("tags"+GetServer(false),tags+"|"+loc);
					GM_setValue("tagcomments"+GetServer(false),GM_getValue("tagcomments"+GetServer(false))+"|"+comment);            
					location.reload();        
				}
				else{
					//tags="";
					var comments=GM_getValue("tagcomments"+GetServer(false));
					var tagsarr=tags.split("|");
					var commentsarr=comments.split("|");
					tags="";
					comments="";
					for(var i=0;i<tagsarr.length;i++){                        
						if(tagsarr[i]!=loc&&tagsarr[i]!=""){
							tags+="|"+tagsarr[i];
							comments+="|"+commentsarr[i];
						}
					}
					GM_setValue("tags"+GetServer(false),tags);
					GM_setValue("tagcomments"+GetServer(false), comments);
					alert("Location "+loc+" untagged.");
					location.reload();
				}
			}                
		}, true);
	}
    
//************************************************THRONE PAGE***********************************************
    
	else if(inURL("menu.cgi")){
		var str=document.body.innerHTML ;
		if(str.indexOf("Please type this 3 letter")<0&&str.indexOf("Please type this 6 letter security code:")
			&&str.indexOf("To ensure you provided a valid email address")<0&&str.indexOf("Transfer Information")<0
			&&str.indexOf("Here at Utopia, we try to ensure that our world is fun for ")<0){
			//make sure we're not on the CAPTCHA page or activation page...
			var view=0;
			//set up local styles
			GM_addStyle(".time"+CurrentStyle.throneTime);
			//add the standard/report toggle button
			document.body.innerHTML+= topMenu(createButton('btnView', 0, 'Switch view'));
		
			//listen for click events
			document.addEventListener('click', function(event){
				if(event.target.id=="btnView"){
					if(view==0)
						view=Report();
					else
						view=Standard();
				}
			}, true);
			
			//print out a line in report mode
			function ReportLine(label, value, unit){
				var str="<span class=label>"+label+": </span>";
				str+="<span class=value>"+value+"</span>";
				if(unit!="")
					str+="<span class=label>"+unit+"</span>";
				str+="<br />";
				return str;
			}
			
			//print out a line in report mode
			function ReportRatioLine(label, value, unit, land){
				var str='<span class="label">'+label+': </span>';
				str+='<span class="value">'+value+'</span>';
				if(unit!='')
					str+='<span class="label">'+unit+'</span>';
				str+=' (<span class="value">'+calcRatio(value, land)+'</span> per acre)';
				str+='<br />';
				return str;
			}
			
			function GetSwitchLocation(){
				var tds=document.getElementsByTagName('td');
				for(i=0;i<tds.length;i++){
					//alert('-'+tds[i].innerHTML+'-');
					if(tds[i].innerHTML.indexOf('<table width="475"')==0)						
						return i;
				}
				return -1;
			}
			var SwitchLoc=GetSwitchLocation();
			var StandardView=document.getElementsByTagName("td")[SwitchLoc].innerHTML;
			var ReportView="";
			
			//print a standard-view window
			function Standard(){
				document.getElementsByTagName("td")[SwitchLoc].innerHTML=StandardView;
				return 0;
			}
			
			function Report(){
				document.getElementsByTagName("td")[SwitchLoc].innerHTML=ReportView;
				return 1;
			}
			
			function GetCell(cells, index){
				return clean(cells[index].innerHTML);
			}
			
			//print a report
			function CreateReport(){
				//parse in original document... TODO: upgrade with findCell(...) calls
				var ths=document.getElementsByTagName('th');
				var str=ths[ths.length-1].innerHTML;
				var Province=striptags(str.substring(str.indexOf("of ")+3, str.indexOf("(")));
				var Kingdom= str.substring(str.indexOf("(")+1, str.indexOf(")"));
				//GM_setValue("kingdom"+GetServer(false), striptags(Kingdom));
				var UtopiaDate=str.substring(str.indexOf("as of")+5);
				var cells=document.getElementsByTagName("td");
				if(cells.length<=56)
					return;
				var Networth=ProvNetworth; 
				var start=12;
				var Race=GetCell(cells, start);
				var Soldiers=GetCell(cells, start+3);
				var Ruler=GetCell(cells, start+5);
				var Personality=extractPersonality(Ruler);
				var OffSpecName=GetCell(cells, start+7);
				var OffSpecs=GetCell(cells, start+8);
				var Land=GetCell(cells, start+10).substring(0, GetCell(cells, start+10).length-5);
				var DefSpecName=GetCell(cells, start+12);
				var DefSpecs=GetCell(cells, start+13);
				var Peasants=GetCell(cells, start+15);
				var EliteName=GetCell(cells, start+17);
				var Elites=GetCell(cells, start+18);
				var BuildingEff=GetCell(cells, start+20).substring(0, GetCell(cells, start+20).length-1);
				var Thieves=GetCell(cells, start+23).substring(0, GetCell(cells, start+23).indexOf(" ("));
				var Stealth=GetCell(cells, start+23).substring(GetCell(cells, start+23).indexOf("(")+1, GetCell(cells, start+23).indexOf("%)"));
				var Gold=GetCell(cells, start+25).substring(0, GetCell(cells, start+25).length-2);
				var Wizards=GetCell(cells, start+28).substring(0, GetCell(cells, start+28).indexOf(" ("));
				var Mana=GetCell(cells, start+28).substring(GetCell(cells, start+28).indexOf("(")+1, GetCell(cells, start+28).indexOf("%)"));
				var Food=GetCell(cells, start+30).substring(0, GetCell(cells, start+30).indexOf(" bushels"));
				var WarHorses=GetCell(cells, start+33);
				var Runes=GetCell(cells, start+35).substring(0, GetCell(cells, start+35).indexOf(" runes"));
				var Prisoners=GetCell(cells, start+38);
				var TradeBalance=GetCell(cells, start+40).substring(0, GetCell(cells, start+40).length-2);
				var OffPoints=GetCell(cells, start+43);
				var ServiceLevel=GetCell(cells, start+45);
				var DefPoints=GetCell(cells, start+48);
				var Population=parseInt(Soldiers)+parseInt(OffSpecs)+parseInt(DefSpecs)+parseInt(Elites)+parseInt(Thieves)+parseInt(Wizards)+parseInt(Peasants);

				var str="<div class=report>";
				str+="<b>The Province of <span class='value'>"+Province+"</span> (<span class='value'>"+Kingdom+"</span>)<br>";
				str+="["+fullname+"]<br><br></font>";
				str+=ReportLine("Utopian Date", UtopiaDate, "");
				str+=ReportLine("Ruler Name",Ruler, "");
				str+=ReportLine("Race", Race, "");
				str+=ReportLine("Personality", Personality, "");
				str+=ReportLine("Land", Land, " Acres");
				str+=ReportLine("Money", Gold, "gc");
				str+=ReportLine("Food", Food, " bushels");
				str+=ReportLine("Runes", Runes, " runes");
				str+=ReportLine("Population", Population, " citizens");
				str+=ReportLine("Peasants", Peasants, "");
				str+=ReportLine("Building Efficiency", BuildingEff, "%");
				str+=ReportLine("Trade Balance", TradeBalance, "gc");
				
				str+=ReportRatioLine("Networth", Networth, "gc", Land)+"<br />";
				str+=ReportLine("Soldiers", Soldiers, "");
				str+=ReportRatioLine(OffSpecName, OffSpecs, "", Land);
				str+=ReportRatioLine(DefSpecName, DefSpecs, "", Land);
				str+=ReportRatioLine(EliteName, Elites, "", Land);
				str+=ReportLine("War horses", WarHorses, "");
				str+=ReportLine("Prisoners", Prisoners, "")+"<br />";
				str+=ReportRatioLine("Off. Points", OffPoints, "", Land);
				str+=ReportRatioLine("Def. Points", DefPoints, "", Land)+"<br />";
				
				str+=ReportRatioLine("Thieves", Thieves, "", Land);
				str+=ReportLine("Stealth", Stealth, "%");
				str+=ReportRatioLine("Wizards", Wizards, "", Land);
				str+=ReportLine("Mana", Mana, "%");
				
				str=str+"</div>";
				ReportView=str;
			}
			
			CreateReport();
		}
	}
    
//************************************************MAGIC PAGE***********************************************
	else if(inURL("magic.cgi")){
		//this function is temporarily deactivated as it was breaking the start/stop wizards training
		//this temporary deactivation seems to be lasting a good long while...
		function themeMagic(){
			var table=document.getElementsByTagName('table')[3];
			for(var i=0;i<table.rows.length;i++){
				var cell=table.rows[i].cells[1];
				cell.innerHTML=replaceAll(cell.innerHTML, '<font color="#ffeecc">', '<span class="value">');
			}
		}
		//themeMagic();
		//listen for change events
		document.addEventListener('change', function(event){
			if(event.target.name=="targetprovince")
				GM_setValue("magictarget"+GetServer(false), document.getElementsByTagName("select")[0].value);
			else if(event.target.name=="spellnum")
				GM_setValue("magicop"+GetServer(false), document.getElementsByTagName("select")[1].value);
			//alert(GM_getValue("magictarget"+GetServer(false))+"\n"+GM_getValue("magicop"+GetServer(false)));
		}, true);
		//reload previous operations
		function retrieveValues(){
			var selects=document.getElementsByTagName('select');
			selects[0].value=GM_getValue("magictarget"+GetServer(false));
			selects[1].value=GM_getValue("magicop"+GetServer(false));
			//alert(GM_getValue("magictarget"+GetServer(false))+"\n"+GM_getValue("magicop"+GetServer(false)));
		}
		retrieveValues();
				
		targetKdLink(1, 3);	
		
		ShowPostTags("magic");
		
		opRecorder('Magic', 0, 'font', 0);
		
		//cb handler
		if(inBody("Our crystal ball shows ...")){
			var view=0;
			var StandardView=ClickableLinksInStr(document.getElementsByTagName("table")[2].innerHTML, true);
			var ReportView="";
						
			document.getElementsByTagName ("td")[1].innerHTML+=topMenu(createButton('btnView', 0, 'Switch view')); //see Note 1
			
			//listen for click events
			 document.addEventListener('click', function(event){
				if(event.target.id=="btnView"){
					if(view==0){
						Report();
						view=1;
					}
					else{
						Standard();
						view=0;
					}
				}
			}, true);
			
			function Standard(){
				document.getElementsByTagName("table")[2].innerHTML=StandardView;
			}
			Standard();
			
			function Report(){
				document.getElementsByTagName("table")[2].innerHTML=ReportView;
			}            
			
			function CreateReport(){
				var cells=document.getElementsByTagName("td");
				if(cells.length<=56)
					return;
				var str=document.getElementsByTagName("th")[0].innerHTML;
				var ProvName=str.substring (str.indexOf('The Province of <font color="#ffeecc">')+38, str.indexOf('</font> as of'));
				var UtopiaDate=str.substring (str.indexOf(' as of')+6);            
				var Race=cells[8].innerHTML;
				var Ruler=cells[13].innerHTML;
				var Personality=extractPersonality(Ruler);
				var Land=cells[18].innerHTML;
				var Peasants=cells[23].innerHTML;
				var BuildingEff=cells[28].innerHTML;
				var Gold=cells[33].innerHTML;
				var Food=cells[38].innerHTML;
				var Runes=cells[43].innerHTML;
				var TB=cells[48].innerHTML;
				var Soldiers=cells[11].innerHTML;
				var OffSpecName=cells[15].innerHTML;
				var OffSpecs=cells[16].innerHTML;
				var DefSpecName=cells[20].innerHTML;
				var DefSpecs=cells[21].innerHTML;
				var EliteName=cells[25].innerHTML;
				var Elites=cells[26].innerHTML;
				var Horses=cells[41].innerHTML;
				var Prisoners=cells[46].innerHTML;
				var OffPoints=cells[51].innerHTML;
				var DefPoints=cells[56].innerHTML;
				var RaceIndex=GetRaceIndex(Race);
				var OffSpecPoints=GetStrength(RaceIndex).OffSpec;
				var DefSpecPoints=GetStrength(RaceIndex).DefSpec;
				var EliteOff=GetStrength(RaceIndex).EliteOff;
				var EliteDef=GetStrength(RaceIndex).EliteDef;
				var MilitaryEff=new Number(parseInt( DefPoints.replace(",",""))/(parseInt(Soldiers)+parseInt(DefSpecs)*DefSpecPoints+parseInt(Elites)*EliteDef)*100).toFixed(1)+"%";

				var str="<tr><td><div class='report'><b>The province of <span class='value'>"+ProvName+"</span></b><br>";
				str+="["+fullname+"]<br><br></font>";
				str+="Utopian Date: <span class='value'>"+UtopiaDate+"</span><br><br>";
				str+="Ruler Name: <span class='value'>"+Ruler+"</span><br>";
				str+="Personality &amp; Race: <span class='value'>"+Personality+", "+Race+"</span><br>";
				str+="Land: <span class='value'>"+Land+"</span><br>";
				str+="Money: <span class='value'>"+Gold+"</span><br>";
				str+="Food: <span class='value'>"+Food+"</span><br>";
				//note nothing about population (we don't have anything on thieves/wizards)
				str+="Peasants: <span class='value'>"+Peasants+"</span> ("+calcRatio(Peasants, Land)+" per acre)<br>";
				str+="Building Effiency: <span class='value'>"+BuildingEff+"</span><br>";
				str+="Trade Balance: <span class='value'>"+TB+"</span><br><br>";
				str+="Military Effiency: <span class='value'>"+MilitaryEff+"</span><br>";
				str+="Soldiers: <span class='value'>"+Soldiers+"</span><br>";
				str+=OffSpecName+": <span class='value'>"+OffSpecs+"</span> ("+OffSpecs*OffSpecPoints+" offense)<br>";
				str+=DefSpecName+": <span class='value'>"+DefSpecs+"</span> ("+DefSpecs*DefSpecPoints+" defense)<br>";
				str+=EliteName+": <span class='value'>"+Elites+"</span> ("+Elites*EliteOff+" offense, "+Elites*EliteDef+" defense)<br>";
				str+="War-Horses: <span class='value'>"+Horses+"</span><br>";
				str+="Prisoners: <span class='value'>"+Prisoners+"</span> ("+Prisoners*3+" offense)<br><br>";
				str+="Modified Offense: <span class='value'>"+OffPoints+"</span> ("+calcRatio(OffPoints, Land)+" per acre)<br>";
				str+="Modified Defense: <span class='value'>"+DefPoints+"</span> ("+calcRatio(DefPoints, Land)+" per acre)<br>";
				ReportView=str;
			}
			CreateReport();
		}
	}
//**********************************************MAGIC ADVISOR PAGE********************************************
	else if(inURL('council.cgi?elder=6')){
		function prepareRecordReport(type){
			return '<b><u>'+type.toUpperCase()+'</u></b><br />'+GM_getValue('ops'+type+GetServer(false))+'<br /><br />';
		}
		if(inBody('As leader of your Province, you know that the peasantry'))
			document.body.innerHTML+=ClickableLinksInStr(prepareRecordReport('Magic')+prepareRecordReport('Thievery'), false)+'<br />';
	}
//************************************************THIEVERY PAGE***********************************************
	else if(inURL("thievery.cgi")){   
		targetKdLink(0, 3);
		ShowPostTags("thievery");
		//listen for change events
		document.addEventListener('change', function(event){
			var selects=document.getElementsByTagName("select");
			if(event.target.name=="targetprovince")
				GM_setValue("thieverytarget"+GetServer(false), selects[0].value);
			else if(event.target.name=="Thiefnum"){
				GM_setValue("thieveryop"+GetServer(false), selects[1].value);
				if(selects.length>2) //what was Mehul thinking?
					GM_setValue("arsontarget"+GetServer(false), selects[2].value);
			}
			else if(event.target.name=="AmtSend"){
				var inputs=document.getElementsByTagName("input");        
				GM_setValue("thieveryqty"+GetServer(false), inputs[3].value);
			}
		}, true);   
             
		function reloadOperations(){
			var selects=document.getElementsByTagName("select");
			selects[0].value=GM_getValue("thieverytarget"+GetServer(false));
			selects[1].value=GM_getValue("thieveryop"+GetServer(false));
			if(selects.length>2)
				selects[2].value=GM_getValue("arsontarget"+GetServer(false));
			document.getElementsByTagName("input")[3].value=nanParseInt(GM_getValue("thieveryqty"+GetServer(false)), 0);
		}
		reloadOperations();
		
		opRecorder('Thievery', 0, 'font', 1);
        
        //sos formatting
		if(inBody("Our thieves visit the research centers of")){
			var cells=document.getElementsByTagName ("td");
			var view=0;
			var StandardView=document.getElementsByTagName("table")[2].innerHTML;
			var ReportView="";
            
			//add the standard/report toggle button
			whereToAdd().innerHTML+=topMenu(createButton('btnView', 0, 'Switch view'));

			//listen for click events
			document.addEventListener('click', function(event){
				if(event.target.id=="btnView"){
					if(view==0){
						Report();
						view=1;
					}
					else{
						Standard();
						view=0;
					}
				}
			}, true);
            
			//print the standard view
			function Standard(){ //same for the report, and presumably for other forms.
				findStringsInTable(new Array("Science Intelligence")).innerHTML=StandardView;
			}

			function Report(){
				findStringsInTable(new Array("Current Effects of our Research")).innerHTML=ReportView;
			}            

			//print in report mode
			function CreateReport(){
				var target=document.body.innerHTML.substring(document.body.innerHTML.indexOf("Our thieves visit the research centers of")+41, document.body.innerHTML.indexOf("</span>")+7);
				var effects=new Array();
				var arts=new Array();
				var columnArts=findTextInCell("Alchemy").innerHTML.split("<br>");
				var columnEffects=findTextInCell("Magic Effectiveness &amp; Rune Production").innerHTML.split("<br>");
				for(var i=0;i<7;i++){
					arts[i]=columnArts[i];
					effects[i]="<span class='value'>"+columnEffects[i];
					effects[i]=effects[i].replace("%", "%</span>");
				}

				var str="<div class='report'>Science Intelligence on "+target+"<br>";
				str+="["+fullname+"]<br><br></font>";
				str+="*** Effects Summary ***<br>";
				for(var i=0;i<7;i++)
					str+="<span style='white-space:nowrap;'>"+effects[i]+"<br>";
				str+="</div>";
				ReportView=str;
			}
            CreateReport();
        }
		//survey report
		else if(inBody("Our thieves scour the lands of")){
		//the text provided is a bit... long... let's have a shorter version
            function SummariseEffect(str){
				if(str.indexOf("Increase Max Population by ")>=0) //homes
					return "+"+str.substring(27)+" pop";
				else if(str.indexOf("Bushels of Food")>=0) //farms
					return "+"+str.substring(8, str.indexOf(" Bushels"))+" bushels";
				else if(str.indexOf("Lower Building Costs")>=0) //mills
					return "-"+str.substring(0, str.indexOf("Lower"))+" building costs; -"+str.substring(str.indexOf("Exploration Costs by ")+21)+" exploration cost";
				else if(str.indexOf("Higher Income")>=0) //banks
					return "+"+str.substring(8, str.indexOf(" per Day"))+str.substring(str.indexOf("; "), str.indexOf(" Higher Income"))+" income";
				else if( str.indexOf("Higher Offensive Efficiency")>=0) //tgs
					return "+"+str.substring(0, str.indexOf(" Higher"))+" offensive strength";
				else if( str.indexOf("Lower Military Training Costs")>=0) //armouries
					return "-"+str.substring(0, str.indexOf(" Lower Military Training Costs"))+" military training costs"+str.substring( str.indexOf("; "), str.indexOf(" Lower Military Wages"))+"% wages";
				else if(str.indexOf("Lower Attack Times")>=0) //raxx
					return "-"+str.substring(0, str.indexOf(" Lower Attack Times"))+" attack time";
				else if(str.indexOf("Higher Defensive Efficiency")>=0) //forts
					return "+"+str.substring(0, str.indexOf(" Higher Defensive Efficiency"))+" defensive strength";
				else if(str.indexOf("Lower Resource Losses")>=0) //gs
					return "-"+str.substring(0, str.indexOf(" Lower"))+" resource losses";
				else if(str.indexOf("Chance to Cure the Plague")>=0) //hosps
					return str.substring(0, str.indexOf(" Chance to Cure"))+" cure plague; -"+str.substring( str.indexOf("; ")+2, str.indexOf(" Lower Military Losses"))+" military losses";
				//leave guilds/towers for the moment... they're short enough
				else if( str.indexOf(" Lower Losses in Thievery Operations")>=0) //tds
					return "+"+str.substring(0, str.indexOf(" Lower Losses"))+" thief losses; +"+str.substring(str.indexOf ("; ")+2, str.indexOf(" Higher Thievery Effectiveness"))+" thief effectiveness";
				else if(str.indexOf("Chance of Catching Enemy Thieves")>=0) //wts
					return "+"+str.substring(0, str.indexOf(" Chance of Catching"))+" catch thieves; +"+str.substring(str.indexOf("; ")+2, str.indexOf(" Chance of Identifying"))+" identification";
				//leave libs, schools should be done
				else
					return str;
            }
        
			var view=0;
			var StandardView=document.getElementsByTagName("table")[2].innerHTML;
			var ReportView="";

			//listen for click events
			document.addEventListener('click', function(event){
				if(event.target.id=="btnView"){
					if(view==0){
						Report();
						view=1;
					}
					else{
						Standard();
						view=0;
					}
				}
			}, true);
            
			function Standard(){
				document.getElementsByTagName ("table")[2].innerHTML=StandardView;
			}

			function Report(){
				document.getElementsByTagName("table")[2].innerHTML=ReportView;
			}
            
			function CreateReport(){
				var cells=document.getElementsByTagName("td");
				//add the standard/report toggle button
				whereToAdd().innerHTML+=topMenu(createButton('btnView', 0, 'Switch view'));
				var BuildingName=new Array();
				var Owned=new Array();
				var Percentage=new Array();
				var Effect=new Array();
				var start=17;
				for(var i=0;i<19;i++){
					BuildingName[i]=cells[16+i*4].innerHTML;                
					Owned[i]=cells[17+i*4].innerHTML.replace("<b>","").replace("</b>", "");
					Percentage[i]=cells[18+i*4].innerHTML;
					Effect[i]=SummariseEffect(cells[19+i*4].innerHTML.replace("<br>", "; "));
				}
				var Workers=cells[9].innerHTML;
				var Jobs=cells[11].innerHTML;
				var BE=cells[13].innerHTML;
				var WorkersForMaxBE=cells[15].innerHTML;
				var str=document.body.innerHTML;
				var TargetName=str.substring(str.indexOf("Our thieves scour the lands of ")+31, str.indexOf(" and learn..."));

				var str="<tr><td><div class='report'><b>Survey of <span class='value'>"+TargetName+"</span></b><br>";
				str+="["+fullname+"]<br><br></font>";
				str+="Workers: "+Workers+"<br>";
				str+="Jobs: "+Jobs+"<br>";
				str+="BE: "+BE+"<br>";
				str+="Workers needed for max BE: "+WorkersForMaxBE+"<br><br>";
				for(var i=0;i<19;i++)
					if(parseInt(Owned[i])>0)
						str+=BuildingName[i]+": <span class='value'>"+Owned[i]+"</span> (<span class='value'>"+Percentage[i]+"</span>)<br>";
				str+="<br>*** Effects Summary ***<br>";
				for(var i=1;i<19;i++)
					if(parseInt(Owned[i])>0)
						str+=BuildingName[i]+": <span class='value'>"+Effect[i]+"</span><br>";
				str+="</div></td></tr>";
				ReportView=str;
			}
			CreateReport();
        }
        //som report
        else if(inBody("Our thieves listen in on a report of")){
			//gets an index for each race in the Points array
			function GetRaceIndexFromElite(race){
				switch(race){
					case "Knights": return 0;
					case "Elf Lords": return 1;
					case "Berserkers": return 2;
					case "Ogres": return 3;
					case "Golems": return 4;
					case "Trolls": return 5;
					default:  return 8;
				}
			}
        
			var view=0;
			//add the standard/report toggle button
			whereToAdd().innerHTML+=topMenu(createButton('btnView', 0, 'Switch view'));
			var StandardView1=document.getElementsByTagName("table")[2].innerHTML;
			var StandardView2=document.getElementsByTagName("table")[3].innerHTML;
			var StandardView3= document.getElementsByTagName("table")[4].innerHTML;
			var StandardView4=document.getElementsByTagName("table")[5].innerHTML;
			var ReportView="";
                        
			//listen for click events
			document.addEventListener('click', function(event){
				if(event.target.id=="btnView"){
					if(view==0){
						Report();
						view=1;
					}
					else{
						Standard();
						view=0;
					}
				}
			}, true);
            
			function Standard(){
				document.getElementsByTagName("table")[2].innerHTML=StandardView1;
				document.getElementsByTagName("table")[3].innerHTML=StandardView2;
				document.getElementsByTagName("table")[4].innerHTML=StandardView3;
				document.getElementsByTagName ("table")[5].innerHTML=StandardView4;
			}

			function Report(){
				document.getElementsByTagName("table")[2].innerHTML=ReportView;
				document.getElementsByTagName("table")[3].innerHTML="";
				document.getElementsByTagName("table")[4].innerHTML="";
				document.getElementsByTagName ("table")[5].innerHTML="";
			}
            
			function CreateReport(){    
				var rows=document.getElementsByTagName("tr");
				var Status=new Array();
				var Soldiers=new Array();
				var DefSpecs=new Array();
				var OffSpecs=new Array();
				var Elites=new Array();
				var WarHorses=new Array();
				var Gains=new Array();
				var RawDef=new Array();
				var RawOff=new Array();
				var DefSpecName=rows[7].cells[0].innerHTML;
				var OffSpecName=rows[8].cells[0].innerHTML;
				var EliteName=rows[9].cells[0].innerHTML;

				var RaceIndex=GetRaceIndexFromElite(EliteName);
				var OffSpecPoints=GetStrength(RaceIndex).OffSpec;
				var DefSpecPoints=GetStrength(RaceIndex).DefSpec;
				var EliteOff=GetStrength(RaceIndex).EliteOff;
				var EliteDef=GetStrength(RaceIndex).EliteDef;
                
				for(var i=0;i<rows[5].cells.length-1;i++){
					Status[i]=rows[5].cells[i+1].innerHTML;
					Soldiers[i]=rows[6].cells[i+1].innerHTML;
					DefSpecs[i]=rows[7].cells[i+1].innerHTML;
					OffSpecs[i]=rows[8].cells[i+1].innerHTML;
					Elites[i]=rows[9].cells[i+1].innerHTML;
					WarHorses[i]=rows[10].cells[i+1].innerHTML;
					Gains[i]=rows[11].cells[i+1].innerHTML;
					if(i==0)
						RawDef[i]=parseInt(Soldiers[i])+parseInt(DefSpecs[i])*DefSpecPoints+parseInt(Elites[i])*EliteDef;
					else
						RawDef[i]=parseInt(Soldiers[i])+parseInt(OffSpecs[i])*OffSpecPoints+parseInt(Elites[i])*EliteOff;
					var HorsePower=Math.min(parseInt(WarHorses[i]), parseInt(Soldiers[i])+parseInt(OffSpecs[i])+parseInt(Elites[i]));
					RawOff[i]=parseInt(Soldiers[i])+parseInt(OffSpecs[i])*OffSpecPoints+parseInt(Elites[i])*EliteOff+parseInt(HorsePower);
				}

				var str="Military Intelligence on <br>";
				str+="["+fullname+"]<br><br></font>";
				for(var i=0;i<5;i++){
					if(i==0||parseInt(Soldiers[i+1])>0||parseInt(OffSpecs[i+1])>0||parseInt(DefSpecs[i+1])>0||parseInt(Elites[i+1])>0){
						if(i==0)
							str+="*** Standing Army (at home) ***<br><br>";
						else
							str+="*** Army "+i+" ***<br>";
						str+="Soldiers: <span class='value'>"+Soldiers[i]+"</span><br>";
						str+=OffSpecName+": <span class='value'>"+OffSpecs[i]+"</span><br>";
						str+=DefSpecName+": <span class='value'>"+DefSpecs[i]+"</span><br>";
						str+=EliteName+": <span class='value'>"+Elites[i]+"</span><br>";
						str+="War Horses: <span class='value'>"+WarHorses[i]+"</span><br>";
						str+="Raw attack points: <span class='value'>"+RawOff[i]+"</span><br>";
						if(i>0){
							str+="Defense against ambush: <span class='value'>"+RawDef[i]+"</span><br>";
							str+="Captured land: <span class='value'>"+Gains[i+1]+"</span><br><br>";
						}
						else
							str+="Raw defense points: <span class='value'>"+RawDef[i]+"</span><br><br>";
					}
				}
				ReportView=str;
			}
			CreateReport();
		}
	}
//************************************************SCIENCE PAGE***********************************************
    else if(inURL("science.cgi")){
		var cells=document.getElementsByTagName("td");
		var view=0;
		
		function checkInstructions(){
			return inBody("You have ordered your universities to study")&&fixResources;
		}
		function getrti(){
			if(checkInstructions())
				return 8;
			else
				return 7;
		}
		
		var StandardView=document.getElementsByTagName("table")[getrti()].innerHTML;
		var ReportView="";
		
		//add the standard/report toggle button
		 whereToAdd().innerHTML+=topMenu(createButton('btnView', 0, 'Switch view'));
		
		//listen for click events
		document.addEventListener ('click', function(event){
			if(event.target.id=="btnView"){
				if(view==0){
					Report();
					view=1;
				}
				else{
					Standard();
					view=0;
				}
			}
		}, true);
		
		//print the standard view
		function Standard(){
			document.getElementsByTagName("table")[getrti()].innerHTML=StandardView;
		}
		
		//print the report view
		function Report(){
			document.getElementsByTagName("table")[getrti()].innerHTML=ReportView;
		}
		
		function CreateReport(){
			var points=new Array();
			var effects=new Array();
			var arts=new Array();
			var inprogress=new Array();
			var start=22;
			if(inBody("You have ordered your universities to study"))
				start+=5;
			for(var i=0;i<7;i++){
				arts[i]=cells[start+i*5].innerHTML;
				points[i]=cells[start+1+i*5].innerHTML;
				effects[i]="<span class='value'>"+cells[start+2+i*5].innerHTML;
				effects[i]=effects[i].replace("%", "%</span>");
				inprogress[i]=cells[start+3+i*5].innerHTML;
			}
			var cost=cells[start-8].innerHTML;

			var str="<tr><td><div class='report'><b>Science</b><br>";
			str+="["+fullname+"]<br><br></font>";
			str+="Research costs: "+cost+"<br><br>";
			str+="*** Effects Summary ***<br>";
			for(var i=0;i<7;i++){
				str+="<span style='white-space:nowrap;'>"+effects[i]+" (<span class='value'>"+points[i]+"</span> points)</span><br>";
			}
			str+="<br>*** In Progress ***<br>";
			for(var i=0;i<7;i++)
				if(parseInt(inprogress[i])!=0)
					str+=arts[i]+": <span class='value'>"+inprogress[i]+"</span> points in progress<br>";
			str+="</div></td></tr>";
			ReportView=str;
		}
		CreateReport();
	}
//************************************************BUILDINGS PAGE***********************************************
	else if(inURL("build.cgi")&&GetServer(true)!='u3'){
		var enablecalc=true;
		var count=18;
		
		function checkInstructions(){
			return (inBody("You have given orders to your construction")&&fixResources);
		}
		
		function Building(name, owned, progress){
			this.name=name;
			this.owned=owned;
			this.progress=progress;
		}
		
		function CreateBuilding(cells, index){
			return new Building(cells[index].innerHTML, parseInt(cells[index+1].innerHTML), 
				nanParseInt(cells[index+2].innerHTML));
		}			
		
		function ParseBuildings(){
			var buildings=new Array();
			var cells=document.getElementsByTagName("td");
			var j=23;
			if(checkInstructions())
				j=30;
			var jump=5;
			var i=0;
			//alert(cells[j].innerHTML);
			while(cells[j+3]&&cells[j+3].innerHTML.indexOf('<input size="5" name="Build')>=0){
				buildings[i]=CreateBuilding(cells, j);
				//alert(buildings[i].name+' '+buildings[i].owned+' '+buildings[i].progress);
				j+=jump;
				jump=(jump==5)?4:5;
				i++;           
			}
			//alert(buildings[10].name+' '+buildings[10].owned+' '+buildings[10].progress);
			//alert(buildings[1].name);
			return buildings;
		}
		
		if(inURL('destroy=true'))
			document.body.innerHTML+='<br /><br />';
		else{		
			if(enablecalc==true||enablecalc+""=="undefined"){
				if(checkInstructions())
					var acres=nanParseInt(striptags(stripcommas(document.getElementsByTagName("td")[21].innerHTML)),0);
				else
					var acres=nanParseInt(striptags(stripcommas(document.getElementsByTagName("td")[14].innerHTML)),0);
				var view=0;
				document.body.innerHTML+=topMenu(createButton('btnView', 0, 'Switch view'));
				
				function Show(title, text){ //show the little help doobylackey down the bottom
					var obj=document.getElementById("help");
					obj.innerHTML=title+": <span class='value'>"+text+"</span>";
				}
				
				//print the effect to the right of the Construct column
				function ShowEffect(index, text, Current, New, Acres){
					var buildings=ParseBuildings();
					var table=document.getElementsByTagName("div")[3];
					table.innerHTML=buildings[index-1].name+": "+text+"<br>";		        
				}
				
				function GetEffect(Current, New, Acres, Multiplier, Percentage, DBE, Text){
					var amount;
					if(DBE)
						amount=CalcEffect(calcRatio(Current*100), calcRatio(New*100), Multiplier,  true, acres)+" "+Text;
					else
						amount=CalcEffect(Current, New, Multiplier, false, 0)+" "+Text;
					return amount;				
				}
				
				//Calculates the effects of a building (does not consider BE)
				//Note: this does not actually currently consider DBE. It should.
				//Current: number of buildings currently owned+in progress
				//New: number of buildings currently listed in the Build input
				//multiplier: a number to multiply by
				//dbe: boolean - consider DBE
				//max: use if there is an explicitly declared maximum to effect (eg mills -99% building costs). Pass in 0 otherwise    
				function CalcEffect(Current, New, multiplier, dbe, max){
					Current=nanParseFloat(Current);
					New=nanParseFloat(New);
					var str="";
					if(dbe==true){
						/*CurrentEffect*=multiplier-((multiplier/50)*(Current/acres)); //(1-parseFloat(Current)/100)*2/3;
						FutureEffect*=(1-parseFloat(Current+New)/100)*2/3;
						if(Current>0)
							alert(""+multiplier-((multiplier/50)*(Current/acres)));*/
						var CurrentEffect=-(Math.pow(-Current/50+1,2)-1)*1*multiplier/0.04;
						var FutureEffect=-( Math.pow(-(Current+New)/50+1,2)-1)*1*multiplier/0.04;
					}
					else{
						var CurrentEffect=Current*multiplier;
						var FutureEffect=(Current+New)*multiplier;
					}
					if(max>0){
						CurrentEffect=Math.min(CurrentEffect, max);
						FutureEffect=Math.min(FutureEffect, max);
					}
					CurrentEffect=""+CurrentEffect;
					FutureEffect=""+FutureEffect;
					ConstructEffect=""+CurrentEffect;
					if(CurrentEffect.indexOf (".")>=0)
						CurrentEffect=new Number(CurrentEffect).toFixed(2);
					if(FutureEffect.indexOf(".")>=0)
						FutureEffect=new Number(FutureEffect).toFixed(2);
					str=CurrentEffect+" (<span class='value'>"+FutureEffect+"</span>)";
					return str;
				}
				
				//figure out how to update whichever cell needs updating
				//index: int 1-18 with the index of the cell to be updated
				//Current: how many of this are already built or currently in construction
				//New: how many are currently in construction
				function Update(BuildingName, index, Current, New){
					//alert(BuildingName+'\n'+index+'\n'+Current+'\n'+New);
					index=parseInt(index);
					Current=nanParseFloat(Current);
					New=nanParseFloat(New);
					if(""+Current=="NaN")
						Current=0;
					if(""+New=="NaN")
						New=0;
					switch(BuildingName){ //this is a bit of a mess. my apologies. feel free to clean it up a bit.
						case "Homes":
							ShowEffect(index, "+"+CalcEffect(Current, New, 8, false, 0)+" pop, +"+CalcEffect(calcRatio(Current*100, acres), calcRatio(New*100, acres), 4, true, 0)+"% birth rates, 0 jobs", Current, New, acres);
							break;
						case "Farms":
							ShowEffect(index, "+"+CalcEffect(Current, New, 70, false, 0)+" bushels", Current, New, acres);
							break;
						case "Mills":
							ShowEffect(index, "-"+CalcEffect(calcRatio(Current*100, acres), calcRatio(New*100, acres), 4, true, 99)+"% building costs, -"+CalcEffect(calcRatio(Current*100, acres), calcRatio(New*100, acres), 3, true, 0)+"% exploration cost", Current, New, acres);
							break;
						case "Banks":
							ShowEffect(index, "+"+CalcEffect(Current, New, 25, false, 0)+"gc; +"+CalcEffect(calcRatio(Current*100, acres), calcRatio(New*100, acres), 1.25, true, 0)+"% income", Current, New, acres);
							break;
						case "Training Grounds":
							ShowEffect(index, "+"+CalcEffect(calcRatio(Current*100, acres), calcRatio(New*100, acres), 1.5, true, 0)+"% offensive strength", Current, New, acres);
							break;
						case "Armouries":
							ShowEffect(index, "-"+CalcEffect(calcRatio(Current*100, acres), calcRatio(New*100, acres), 1.5, true, 0)+"% military training; -"+CalcEffect(calcRatio(Current*100, acres), calcRatio(New*100, acres), 2, true, 0)+"% draft costs & wages", Current, New, acres);
							break;
						case "Barracks":
							ShowEffect(index, "-"+CalcEffect(calcRatio(Current*100, acres), calcRatio(New*100, acres), 1.5, true, 0)+"% attack time", Current, New, acres);
							break;
						case "Forts":
							ShowEffect(index, "+"+CalcEffect(calcRatio(Current*100, acres), calcRatio(New*100, acres), 1.5, true, 0)+"% defensive strength", Current, New, acres);
							break;
						case "Guard Stations":
							ShowEffect(index, "-"+CalcEffect(calcRatio(Current*100, acres), calcRatio(New*100, acres), 2, true, 0)+"% resource losses", Current, New, acres);
							break;
						case "Hospitals":
							ShowEffect(index, ""+CalcEffect(calcRatio(Current*100, acres), calcRatio(New*100, acres), 2, true, 0)+"% chance of curing plauge; -"+CalcEffect(calcRatio(Current*100, acres), calcRatio(New*100, acres), 3, true, 99)+"% military losses", Current, New, acres);
							break;
						case "Guilds":
							ShowEffect(index, "Approximately "+CalcEffect(Current, New, 0.02, false, 0)+" wizards per day", Current, New, acres);
							break;
						case "Towers":
							ShowEffect(index, "+"+CalcEffect(Current, New, 12, false, 0)+" runes", Current, New, acres);
							break;
						case "Thieves' Dens":
							ShowEffect(index, "-"+CalcEffect(calcRatio(Current*100, acres), calcRatio(New*100, acres), 4, true, 0)+"% losses; +"+CalcEffect(calcRatio(Current*100, acres), calcRatio(New*100, acres), 3, true, 99)+"%  effectiveness", Current, New, acres);
							break;
						case "Watchtowers":
							ShowEffect(index, "+"+CalcEffect(calcRatio(Current*100, acres), calcRatio(New*100, acres), 2, true, 0)+"% stop thieves; +"+CalcEffect(calcRatio(Current*100, acres), calcRatio(New*100, acres), 3, true, 0)+"%  enemy losses", Current, New, acres);
							break;
						case "Libraries":
							ShowEffect(index, "+"+CalcEffect(calcRatio(Current*100, acres), calcRatio(New*100, acres), 2, true, 0)+"% science effects (not affected by BE)", Current, New, acres);
							break;
						case "Schools":
							ShowEffect(index, "-"+CalcEffect(Current, New, 1.5, false, 0)+" science costs; +"+CalcEffect(calcRatio(Current*100, acres), calcRatio(New*100, acres), 3.5, true, 0)+"% book protection", Current, New, acres);
							break;
						case "Stables":
							ShowEffect(index, "Holds "+CalcEffect(Current, New, 60, false, 0)+" horses", Current, New, acres);
							break;
						case "Dungeons":
							ShowEffect(index, "Holds "+CalcEffect(Current, New, 20, false, 0)+" prisoners", Current, New, acres);
							break;
					}
				}
				
				//build the little help doobylackey down the bottom
				document.body.innerHTML+="<br><br><br><div id='help' class='report' style='position:fixed;left:0;bottom:0em;width:75%;height:1.3em;'>[Building name]: [current effect] ([current+in construction effect]) [description]. <i>BE is ignored.</i></div>";         
				
				//show help down the bottom
				document.addEventListener('focus', function(event){
					if(event.target.name){
						if(event.target.name.substring(0, 5)=="Build"){
							var buildings=ParseBuildings();
							var number=event.target.name.substring(5);
							var effect= document.getElementById ("effect"+number);
							Update(buildings[number-1].name, number, buildings[number-1].owned, buildings[number-1].progress);
						}
					}
				}, true);
				
				
				//listen for click events
				document.addEventListener('click', function(event){
					if(event.target.id=="btnView"){
						if(view==0){
							view=1;
							Report();						
						}
						else{
							view=0;
							Standard();                    
						}
					}
				}, true);
				
				var StandardView= document.getElementsByTagName ("table")[5].innerHTML;
				if(checkInstructions())
					StandardView=document.getElementsByTagName("table")[6].innerHTML;
				
				function Standard(){
					var table;
					if(checkInstructions())
						table=document.getElementsByTagName("table")[6];
					else
						table= document.getElementsByTagName("table")[5];
					table.innerHTML=StandardView;
				}
				
				function Report(){
					var buildings=ParseBuildings();
					var str="<div class='report'><b>Buildings Report Information</b><br>";
					str+="["+fullname+"]<br><br></font>";
					for(var i=0;i<buildings.length;i++){
						if(buildings[i].owned!=0||buildings[i].progress!=0){
							str+=buildings[i].name+": "+buildings[i].owned+" ("+calcRatio(parseInt(buildings[i].owned)*100, parseInt(acres))+"%)";
							if(buildings[i].progress[i]!=0)
								str+=" + "+buildings[i].progress+" ("+calcRatio(parseInt(buildings[i].progress)*100, parseInt(acres))+"%)";
							str+="<br>";
						}
					}
					str+="<br>";
					var table;
					if(checkInstructions())
						table=document.getElementsByTagName("table")[6];
					else
						table=document.getElementsByTagName("table")[5];
					table.innerHTML=str;
					for(var i=1;i<=buildings.length;i++)
						if(buildings[i-1].owned>0||buildings[i-1].progress>0)
							Update(i, buildings[i-1].owned, buildings[i-1].progress);
					table.innerHTML+="</div>";
				}
			}    
			
			document.addEventListener('click', function(event){
				if(event.target.id=="btnToggle"){
					if(enablecalc+""=="undefined")
						enablecalc=true;
					enablecalc=!enablecalc;
					GM_setValue("BuildingsCalc", enablecalc);
					location.reload();
				}        
			}, true);
		}
	}
//************************************************PREFERENCES PAGE***********************************************
	else if(inURL("pref.cgi")){
		//local styles
		GM_addStyle('th'+CurrentStyle.report);
		//set up the boxes
		GM_addStyle('.theme{position:fixed;height:2em;left:0;width:10em;cursor:pointer}');    
		
		var str='<table align="center"><tr><th>Seraphiel preferences</th></tr>';
		str+='<tr><td><input type="checkbox" value="enable" id="enable" ';
		if(enabled)
			str+='checked="true"';
		str+='> Enable Seraphiel</td></tr>'        
		str+='<tr><td>Choose theme: <select id="theme">';
		for(var i=0;GetStyle(i)!=null;i++){
			var style=GetStyle(i);
			GM_addStyle('.preview'+i+style.report);
			str+='<option ';
			if(i==nanParseInt(GM_getValue('style'), 0))
				str+='selected="selected" ';
			str+='>'+style.styleName+'</option>';
		}
		str+='</select><span id="preview" class="preview'+nanParseInt(GM_getValue("style"), 0)+'">'+CurrentStyle.styleName;
		str+='</span></td></tr>';
		//pin resources
		str+='<tr><td><input type="checkbox" id="pin" ';
		if(fixResources)
			str+="checked ";
		str+='>Pin resources</td></tr>';
		str+='<tr><td><input type="checkbox" id="autoHide" ';
		if(autoHide)
			str+="checked ";
		str+=">Auto-hide menu and monarch message</td></tr>";
		str+='<tr><td><center><input type="button" id="setTheme" value="Set options"></center></td></tr></table><br><br><br><br>';
		document.body.innerHTML+=str;
		
		function showPreview(){
			var preview=document.getElementById("preview");
			var theme=document.getElementById ("theme")
			preview.className="preview"+theme.selectedIndex;
			preview.innerHTML=theme.options[theme.selectedIndex].text;
		}
		
		document.addEventListener('keyup', showPreview, true);
		document.addEventListener('change', showPreview, true);
		
		document.addEventListener('click', function(event){
			if(event.target.id=="setTheme"){
				GM_setValue("enable", document.getElementById('enable').checked);
				GM_setValue("style", document.getElementById("theme").selectedIndex);
				GM_setValue("fixResources", document.getElementById("pin").checked);
				GM_setValue("autoHide", document.getElementById("autoHide").checked);
				location.reload();
			}
		}, true);
	}
//************************************************READ MESSAGES PAGE***********************************************
	else if(inURL("readmsg.cgi")){
		var str=replaceAll(document.body.innerHTML, '<font color="#aaffaa">', '<span class="msg">');
		document.body.innerHTML=replaceAll(str, '<font color="#ffaaaa">', '<span class="swirvemsg">');
	}
//************************************************SEND MESSAGES PAGE***********************************************
	else if(inURL("msg.cgi")){
		targetKdLink(0, 0);
		ShowPostTags("msg");
		var inputs=document.getElementsByTagName("input");
		var kingdom=inputs[0].value+":"+inputs[1].value;
		document.addEventListener('submit', function(event){
			var inputs=document.getElementsByTagName("input");            
			if(event.target.action){
				GM_setValue("msgtarget"+GetServer(false), document.getElementsByTagName("select")[0].value);
				GM_setValue("msggreeting"+GetServer(false), document.getElementsByTagName ("select")[1].value);
				GM_setValue("msgtext"+GetServer(false), document.getElementsByTagName("textarea")[0].value);
			}
		}, true);
		if(document.referrer.indexOf("msg.cgi")>0){
			document.getElementsByTagName("select")[0].value=parseInt(GM_getValue("msgtarget"+GetServer(false)))+1;
			document.getElementsByTagName ("select")[1].value=GM_getValue("msggreeting"+GetServer(false));
			document.getElementsByTagName("textarea")[0].value=GM_getValue("msgtext"+GetServer(false));
		}
		
		function maxLength(){
			var textarea=document.getElementsByTagName("textarea")[0];
			textarea.addEventListener('keyup', function(event){
					var obj=event.target;
					var cells=document.getElementsByTagName("td");
					var cell=null;
					for(var i=0;i<cells.length;i++){
						if(cells[i].innerHTML.indexOf("(Your message can be up to 1500 characters)")>=0||cells[i].innerHTML.indexOf("Current length: ")>=0)
							cell=cells[i];
					}
					if(cell!=null){
						var str='<span>';
						if(obj.value.length>=1500)
							str='<span style="color:red;font-weight:bold;">';
						str+='Current length: '+obj.value.length+' (max: 1500 characters)<br />';
						str+='<input type="submit" value="Send Message">';
						str+='</span>';
						cell.innerHTML=str;
					}
				}, true);
		}
		maxLength();
	}
//************************************************MILITARY PAGE***********************************************
	else if(inURL("military.cgi")){
		function getStartRow(){
			if(inBody("You have ordered"))
				return 21;
			else
				return 20;
		}

		function setup(){
			var rows=document.getElementsByTagName("tr");
			var start=getStartRow();
			for(var i=start;i<start+4;i++)
				if(rows[i].cells.length==6)
					rows[i].insertCell(6);  
		}
		setup();
		
		document.addEventListener('keyup', function(event){
			if(event.target.name&&event.target.name.indexOf("Train")==0){
				var rows=document.getElementsByTagName ("tr");
				var start=getStartRow();
				for(var i=0;i<4;i++){
					if(rows[start+i].cells.length==7){
						var qty=nanParseInt(rows[start+i].cells[5].getElementsByTagName("input")[0].value, 0);
						var cost=nanParseInt(rows[start+i].cells[3].innerHTML, 0);
						rows[start+i].cells[6].innerHTML=insertSeparator(""+(qty*cost),",")+"gc";
					}
				}
			}                
		}, true);
	}
//************************************************TOP BAR***********************************************
	else if(inURL("top.htm")){
		function addCouncilLinks(){
			var councillor=new Array();
			for(var i=1;i<8;i++)
				councillor[i]="";
			councillor[3]="Military";
			councillor[4]="Buildings";
			councillor[6]="Spells";
			var str='<font size="1" face="verdana">';
			str+='<a target="utomain" href="http://blog.swirve.com/">Blog</a> ';
			str+='<a target="utomain" href="http://games.swirve.com/utopia/theexp.htm">About</a> ';
			str+='<a target="utomain" href="/services.cgi">Service</a> ';
			str+='<a target="utomain" href="/cheater.cgi">Cheaters</a> ';
			str+='<a target="utomain" href="/friend.cgi">Invite</a> ';
			str+='<a target="utomain" href="http://games.swirve.com/utopia/banners.htm">Promote</a> | ';
			for(var i=1;i<8;i++)
				if(councillor[i].length>0)
					str+='<a href="http://'+GetServer(true)+'.swirve.com/council.cgi?elder='+i+'" target="utomain">'+councillor[i]+'</a> ';   
			str+='<a href="http://'+GetServer(true)+'.swirve.com/build.cgi?destroy=true" target="utomain">Raze</a> ';
			document.body.innerHTML=str;
		}
		addCouncilLinks();
	}
//*************************************************WAR ROOM************************************************
    else if(inURL("attack.cgi")){
		var selects=document.getElementsByTagName("select");
		var inputs=document.getElementsByTagName("input");
		targetKdLink(0, 0);
		
		function LoadInputValue(name){
			for(var i=0;i<inputs.length;i++)
				if(inputs[i].name==name)
					inputs[i].value=nanParseInt(GM_getValue(name+GetServer(false)), 0);
		}
		
		function SaveInputValue(name){
			GM_setValue(name+GetServer(false), "0");
			for(var i=0;i<inputs.length;i++)
				if(inputs[i].name==name)
					GM_setValue(name+GetServer(false), inputs[i].value);
		}
		
		//remember forces
        document.addEventListener('change', function(event){			
			var inputs=document.getElementsByTagName("input");
			var selects=document.getElementsByTagName("select");
			GM_setValue("targetprovince"+GetServer(false), selects[0].value);
			GM_setValue("attacknum"+GetServer(false), selects[1].value);
			GM_setValue("extratime"+GetServer(false), selects[2].value);
			SaveInputValue('NUMGEN');
			SaveInputValue('ARMY1');
			SaveInputValue('ARMY2');
			SaveInputValue('ARMY4');
			SaveInputValue('ARMY6');
			SaveInputValue('MERC');
			SaveInputValue('PRIS');
		}, true);
		
		//find the elite name... this technique is like hitting a nail with a jackhammer
		//but it should work - on each server, and even after attacks
        function FindRaceIndex(){
			var rows=document.getElementsByTagName("tr");
			var RaceIndex=-1;
			var i=0;
			while(RaceIndex<0||RaceIndex==8){
				RaceIndex=GetRaceIndexFromElite(rows[i].cells[0].innerHTML);
				i++;
			}
			return RaceIndex;
		}
		
		function Update(){
			var RaceIndex=FindRaceIndex();
			var texts=document.getElementsByTagName("input")
			if(RaceIndex!=8){
				//calculate offense
				var SoldierText=-1, SpecText=-1, EliteText=-1, HorseText=-1, PrisonerText=-1, MercenaryText=-1;
				for(var i=0;i<texts.length;i++){
					switch(texts[i].name){
						case "ARMY1":
							SoldierText=i;
							break;
						case "ARMY2":
							SpecText=i;
							break;
						case "ARMY4":
							EliteText=i;
							break;
						case "ARMY6":
							HorseText=i;
							break;
						case "PRIS":
							PrisonerText=i;
							break;
						case "MERC":
							MercenaryText=i;
							break;
					}
				}
				
				var RaceStrength=GetStrength(RaceIndex);
				var OffSpecPoints=RaceStrength.OffSpec;
				var EliteOff= RaceStrength.EliteOff;
				var MercPoints=RaceStrength.MercPoints;
				var generals=nanParseInt(texts[3].value, 0);
				
				function GetArmyValue(index){
					if(index>0)
						return nanParseInt(texts[index].value, 0);
					return 0;
				}
				
				soldiers=GetArmyValue(SoldierText);
				specs=GetArmyValue(SpecText);
				elites=GetArmyValue(EliteText);
				horses=GetArmyValue(HorseText);
				prisoners=GetArmyValue(PrisonerText);
				mercenaries=GetArmyValue(MercenaryText);						
			   
				var offense=soldiers+specs*OffSpecPoints+elites*EliteOff+horses+prisoners*MercPoints+mercenaries*MercPoints;
				var efficiency=1+(generals-1)*.03;
				offense=new Number(offense*efficiency).toFixed(0);
				var box=document.getElementById('rawoff');
				document.getElementById('rawoff').innerHTML='Raw off: '+offense;
			}
		}		
		document.body.innerHTML+="<br><br><br><div id='rawoff' class='report' style='position:fixed;left:0;bottom:2.5em;width:75%;height:1.3em;'>Raw off: 0</div>";  
		
		document.addEventListener('change', function(event){
			Update();
		}, true);           
		
		/*double+triple+quad buttons... coming soon :)
		document.addEventListener('click', function(event){
			switch(event.target.id){
				case 'btnDouble':
					break;
				case 'btnTriple':
					break;
				case 'btnQuad':
					break;
			}
		}, true);
		whereToAdd+=topMenu(createButton('btnDouble', 0, 'Double tap'));
		whereToAdd+=topMenu(createButton('btnTriple', 1, 'Triple tap'));
		whereToAdd+=topMenu(createButton('btnQuad', 2, 'Quad tap'));*/
        ShowPostTags("attack");
        
		if(document.referrer.indexOf("attack.cgi")>0){ //reload previous operations
			selects[0].value=GM_getValue("targetprovince"+GetServer(false));
			selects[1].value=GM_getValue("attacknum"+GetServer(false));
			selects[2].value=GM_getValue("extratime"+GetServer(false));
			LoadInputValue('NUMGEN');
			LoadInputValue('ARMY1');
			LoadInputValue('ARMY2');
			LoadInputValue('ARMY4');
			LoadInputValue('ARMY6');
			LoadInputValue('MERC');
			LoadInputValue('PRIS');
		}
		else
			inputs[3].value=0; //default to 0 generals when not reloading, for user's safety
		
	}
//*************************************************AID PAGE************************************************
    else if(inURL("aid.cgi")){
		var str=document.body.innerHTML;
		if(str.indexOf('<input value="Block Incoming Aid" type="submit">')>0){
			str=str.replace('<input value="Block Incoming Aid" type="submit">', '<input type="button" id="BlockAid" value="Block Incoming Aid">');
			document.body.innerHTML=str+'<br /><br />';
			document.getElementById("BlockAid").addEventListener('click', function(event){
				location.href="aid.cgi?block=TRUE";}, true);
        }
        else if(str.indexOf('<input value="Allow Aid Shipments" type="submit">')>0){
			str=str.replace('<input value="Allow Aid Shipments" type="submit">', '<input type="button" id="AllowAid" value="Allow Aid Shipments">');
			document.body.innerHTML=str+'<br /><br />';
			document.getElementById("AllowAid").addEventListener('click', function(event){
				location.href="aid.cgi?block=FALSE";}, true);
        }
	}
//*********************************************WORLD SURVEY PAGE*******************************************	
	else if(inURL('players/race.htm')){
		document.body.innerHTML+='<br /><br />';
	}
//************************************************MAIN FRAME***********************************************	
	else if(inURL("game.cgi")&&!inURL("horizdisp=1")){
		function scrollable()
		{
			var frames=document.getElementsByTagName("frame");
			frames[2].scrolling="no";
		}		
		scrollable();
	}

//************************************************AUTO HIDE************************************************
	function expandTopMenu(){
		GM_addStyle("#topMenu"+CurrentStyle.visibleMenu);
		GM_addStyle("#monarchMsg{display:block;}");
	}
	function shrinkTopMenu(){
		GM_addStyle("#topMenu"+CurrentStyle.hiddenMenu);
		GM_addStyle("#monarchMsg{display:none;}");
	}
	var tm=document.getElementById('topMenu');
	if(tm==null&&!inURL("side.htm")&&!inURL("music.htm")&&!inURL("thievery.cgi")&&!inURL("top.htm")&&!inURL("botframe.cgi")){
		whereToAdd().innerHTML+=topMenu('<div style="width:10em">&nbsp;</div>');
		tm=document.getElementById('topMenu');
	}
	if(tm!=null){
		tm.addEventListener('mouseover',expandTopMenu,true);
		tm.addEventListener('mouseout',shrinkTopMenu,true);        
		if(autoHide)
				GM_addStyle("#monarchMsg{display:none;}");
	}
}

//**************************************************FORUMS*************************************************
function SeraphielForums(){
	if(inURL("board.cgi")){
		var links=document.getElementsByTagName("a");
		for(i=0;i<links.length;i++){
			links[i].innerHTML="&nbsp;"+links[i].innerHTML;
		}
	}
}

/************************************************NOTES***********************************************
1. The DOM on the Magic page was coded incorrectly (the <form> tag is a child of a <tr> tag and wraps across rows. FF, meanwhile, 
automatically corrects the DOM as soon as you document.innerHTML any part of it. Therefore, we must make sure not to write any 
element that includes the form.
*/
