KabaListics (DoA Power Tools Plus II modded by Jawz)

By Senclaw Last update Apr 11, 2012 — Installed 87,331 times.

There are 5 previous versions of this script.

the source is over 100KB, syntax highlighting in the browser is too slow

// ==UserScript==
// @name            KabaListics (DoA Power Tools Plus II modded by Jawz)
// @namespace       http://userscripts.org/scripts/show/118446
// @icon            http://img66.xooimage.com/files/3/6/d/jaws64-2b5041c.png
// @description     Enhanced Power Tools for Dragons of Atlantis, modded by Jawz, Senclaw
// @include         *://apps.facebook.com/dragonsofatlantis/*
// @include         *://*.castle.wonderhill.com/platforms/*/game
// @match           *://apps.facebook.com/dragonsofatlantis/*
// @match           *://*.castle.wonderhill.com/platforms/*/game
// @include         *://plus.google.com/games/659749063556*
// @include         *://plus.google.com/*/games/659749063556*
// @include         *://*.googleusercontent.com/gadgets/ifr?url=app://659749063556*
// @match           *://plus.google.com/games/659749063556*
// @match           *://*.googleusercontent.com/gadgets/ifr?url=app://659749063556*
// @include         *://www.kabam.com/dragons-of-atlantis/play
// @exclude         *://apps.facebook.com/dragonsofatlantis/rubies
// @exclude         *://apps.facebook.com/ai.php*
// @exclude         *://www.facebook.com/plugins/like.php*
// @exclude         *://kabam1-a.akamaihd.net/pixelkabam/*
// @exclude         *://*.akamaihd.net/pixelkabam/*
// @exclude         *://plus.google.com/_/apps-static/*
// @exclude         *://plus.google.com/u/0/_/gadgets/contactPicker*
// @exclude         *://accounts.google.com/*
// @exclude         *://talkgadget.google.com/*
// @exclude         *://www.googleapis.com/static*
// @version         2012.0405
// @changeLog		<ul><li>Added basic troops statistics & food consumption in the info tab, in the might sub-tab renamed as troops</li><li>Added the bullshit called Leaderboards (like available from Kabam.com)</li><li>Fixed some bugs</li></ul>
// ==/UserScript==


/*	===== TO DO =====
	- Review of march handling (max simultaneous march per types & to fix more than one tab enabled at the same time)
	- Bookmarks enhancements (to add sequences, loop on sequences, to review report deletion)
	- Wall management (add abaility to set Max troop minus a number of troops to keep in city. i.e. Max Lava - 25k)
	- Add speed-ups for current training queues
	===== TO DO =====
*/

(function() {

var scriptVersion	= '2012.0405';
var scriptId = '118446';

// To remove header bar "play | rubies | ...."
var REMOVE_HD = false;

/********************************************************************************
* Check to see if script is running in an iframe or not and removes            *
* unnecessary elements before continuing with the script.                      *
*                                                                              *
* Current actions:                                                             *
*  - Set width all parent div of 'iframe_canvas' to 100%                       *
*  - Hide 'rightCol' div                                                       *
*  - Hide unwanted objects                                                     *
*  - Set width of 'hd' div to 760px                                            *
*  - Set margin of parent to game object to 0px                                *
*  - Hide unwanted elements in 'hd' div                                        *
*  - Hide 'ft' div                                                             *
********************************************************************************/
var window = unsafeWindow || window;

// Check all iframes where the code should not be executed
//if (/(pixelkabam|akamaihd|plugins|ai\.php|talkgadget|apps\-static|notifications|contactPicker|accounts|googleapis\.com\/static)/.test(window.location.href)) return;
if (/(pixelkabam|akamaihd|plugins|ai\.php|talkgadget|notifications|contactPicker|accounts|googleapis\.com\/static)/.test(window.location.href)) return;

// Check if we are in the right sites (in case of the Metadata Blocks don't work)
if ( !( (/apps\.facebook\.com\/dragonsofatlantis/.test(window.location.href) && /rubies/.test(window.location.pathname) == false) ||
 		/castle\.wonderhill\.com\/platforms\/.+\/game/.test(window.location.href) ||
 		/plus\.google\.com.*\/games.*\/659749063556/.test(window.location.href)         || 
 		/googleusercontent\.com\/gadgets\/.*\/659749063556/.test(window.location.href)  || 
 		/kabam.com\/dragons-of-atlantis\/play/.test(window.location.href)
 	)){
 		return;
}
var REALM_URL = '';


if (window.top === window.self) {
	function setWide() {
		if ( window.location.href.indexOf('facebook') !== -1 ) {
			iframe	 = document.getElementById('iframe_canvas');
			platform = 'facebook';
			REALM_URL = 'http://apps.facebook.com/dragonsofatlantis/realm/';
		}
		else if ( window.location.href.indexOf("google") !== -1 ) {
			iframe	 = document.getElementById('oz-gadgets-canvas-iframe-659749063556'); //content').getElementsByTagName('iframe');
			platform = 'google';
		}
		else if ( window.location.href.indexOf("kabam.com") !== -1 ) {
			iframe	 = document.getElementById('game_frame');
			platform = 'kabam';
			REALM_URL = 'https://www.kabam.com/dragons-of-atlantis/play/game/8?path=/realm/';
		}

		if (!iframe || iframe.length < 1) {
			setTimeout (setWide, 1000);
			return;
		}
		var background_118446 = localStorage.getItem( '118446_background' );
		var USE_BACKGROUND = (background_118446 && background_118446 != undefined && background_118446 != null) ? eval(background_118446) : true;
		switch (platform) {
			case 'facebook' :
				while ((iframe = iframe.parentNode) != null) {
					if (iframe.tagName == 'DIV')
						iframe.style.width = '100%';
				}
				document.getElementById('rightCol').style.display = 'none';
				document.getElementById('rightCol').style.display = 'none';
				document.getElementById('blueBarHolder').style.display = 'none';
				document.getElementById('blueBar').style.display = 'none';
				document.getElementById('pageHead').style.display = 'none';
				document.getElementById('jewelContainer').style.display = 'none';
				document.getElementById('headNav').style.display = 'none';
				document.getElementById('contentCol').style.margin = '0px';
				document.getElementById('contentCol').style.background = 'transparent';
				var contentColChild = document.getElementById('contentCol').childNodes;
				for (var i=0; i<contentColChild.length; i++)
					if (contentColChild[i].tagName == 'DIV')
						contentColChild[i].style.margin = '0px';
				document.scrollTop = '42px';
				if (USE_BACKGROUND) {
					var body_elements = document.getElementsByTagName ('body');
					for (var el=0; el < body_elements.length; el++)
						body_elements[el].style.background = '#888 url(https://kabam1-a.akamaihd.net/wwwkabam/cdn/sites/doa/img/bg_doa.jpg)';
				}
				break;
			case 'google' :
				var iframeTag = document.getElementById('content').getElementsByTagName('iframe');
				var iframeId = iframeTag[0].id;
				var iframe = document.getElementById(iframeId);
				while ((iframe = iframe.parentNode) != null) {
					if (iframe.tagName == 'DIV') {
						iframe.style.width = '100%';
						iframe.style.margin = '0';
						iframe.style.border = '0';
						iframe.style.backgroundColor = 'transparent';
					}
					if (iframe.tagName == 'DIV' && iframe.className == "Mca") {
						var found = false;
						var div_elements = iframe.getElementsByTagName('div');
						for (var i=0; i<div_elements.length && !found; i++) {
							if (div_elements[i].className == "Pca") {
								div_elements[i].style.display = 'none';
								found = true;
							}
						}
					}
				}
				var found = false;
				var body_elements = document.getElementsByTagName ('body');
				for (var el=0; el < body_elements.length; el++) {
					var div_elements = body_elements[el].getElementsByTagName('div');
					for (var i=0; i<div_elements.length && !found; i++) {
						if (div_elements[i].className == "c-cb-V c-i-cb-V" || div_elements[i].className == "c-C c-cb-C" || div_elements[i].className == "c-cb-vf-V") {
							div_elements[i].style.display = 'none';
							found = true;
						}
					}
				}
				break;
			case 'kabam' :
				iframe.style.width = '100%';
				iframe.style.margin = '0';
				iframe.style.border = '0';
				if (USE_BACKGROUND)
					iframe.style.backgroundColor = 'transparent';
				else
					iframe.style.backgroundColor = 'white';
				while ((iframe = iframe.parentNode) != null) {
					if (iframe.tagName == 'DIV') {
						iframe.style.width = '100%';
						iframe.style.margin = '0';
						iframe.style.border = '0';
						iframe.style.backgroundColor = 'transparent';
					}
				}
				break;
		}
	}
	setWide();
} else {
	platform = document.body.className.split(' ');
	if (platform && platform[0]){
		platform = platform[0].replace(/(platforms_|_game)/g,'');
	} else {
		platform = 'google';
	}
	var errors = 0;
	function setHigh() {
		clearTimeout;
		var object = document.getElementsByTagName('object');
		if (object.length < 1 || (window.location.hostname.indexOf("realm") == -1 && platform != 'google')) {
			if ( ++errors > 6 ){
				errors = 0;
				window.location =  window.location.href;
			}
			setTimeout (setHigh, 1000);
			return;
		}
		var background_118446 = localStorage.getItem( '118446_background' );
		var USE_BACKGROUND = (background_118446 && background_118446 != undefined && background_118446 != null) ? eval(background_118446) : true;
		switch (platform) {
			case 'facebook' :
				REALM_URL = 'http://apps.facebook.com/dragonsofatlantis/realm/';
				for (var i=0; i<object.length; i++) {
					switch (object[i].parentNode.id) {
						case 'hd' :
							object[i].style.display = 'none'; 
							break;
						default :
							object[i].parentNode.style.margin = '0px';
					}
				}
				document.getElementById('hd').parentNode.style.width = '760px';
				var hdChild = document.getElementById('hd').childNodes;
				for (var i=0; i<hdChild.length; i++)
					if (hdChild[i].tagName == 'DIV') hdChild[i].style.display = 'none';  
				document.getElementById('ft').style.display = 'none';
				document.scrollTop = '42px';
				if (REMOVE_HD) document.getElementById('hd').style.display = 'none';
				if (USE_BACKGROUND) {
					var body_elements = document.getElementsByTagName ('body');
					for (var el=0; el < body_elements.length; el++)
						body_elements[el].style.background = 'transparent';
					var html_elements = document.getElementsByTagName ('html');
					for (var el=0; el < html_elements.length; el++)
						html_elements[el].style.background = 'transparent';
				}
				break;
			case 'google' :
				document.getElementById('pane_hd').style.display = 'none';
				if (USE_BACKGROUND) {
					var body_elements = document.getElementsByTagName ('body');
					for (var el=0; el < body_elements.length; el++) {
						body_elements[el].style.background = 'transparent';
						body_elements[el].style.background = '#888 url(https://kabam1-a.akamaihd.net/wwwkabam/cdn/sites/doa/img/bg_doa.jpg)';
					}
				}
				break;
			case 'kabam' :
				REALM_URL = 'https://www.kabam.com/dragons-of-atlantis/play/game/8?path=/realm/';
				var html_elements = document.getElementsByTagName ('html');
				for (var el=0; el < html_elements.length; el++) {
					html_elements[el].style.overflow = 'hidden'
					html_elements[el].style.backgroundColor = 'transparent';
				}
				if (!USE_BACKGROUND) document.body.style.backgroundColor = 'white';
				break;
		}
		initScript(object);
	}
	setHigh();
}



function initScript (SWF_OBJECT) {
/********************************************************************************
* All global variables MUST be set here or they will not be available to all   *
* functions throughout the script.                                             *
********************************************************************************/
var api_version		= 'xylvan';

// Styles List
var styleList = [
 'bnt_blue',
 'blue',
 'bnt_cyan',
 'bnt_green',
 'btn_on',
 'btn_off',
 'bnt_red',
 'bnt_purple',
 'bnt_red',
 'bnt_yellow',
 'bold_red',
 'compact_table',
 'content',
 'content_table',
 'defending',
 'hiding',
 'popup_bar',
 'popup_close',
 'popup_main',
 'popup_outer',
 'popup_top',
 'row_headers',
 'row_style',
 'row_top_headers',
 'row_headers_left',
 'scrollable',
 'status_feedback',
 'status_report',
 'status_ticker',
 'subtitle',
 'support_link',
 'table',
 'table_console',
 'table_headers',
 'table_targets',
 'title',
 'red',
 'green',
 'btn_disabled',
 'title_main',
 'info_protect',
 'info_alerts',
 ];

// Skins
var urlBackgroundImage = '';
var urlBackgroundLogo = 'http://img73.xooimage.com/files/4/3/1/logojaws-2b7e9d0.jpg';

// Alert sound
var DEFAULT_ALERT_SOUND_URL = 'http://kabam2-a.akamaihd.net/edgeworld/music/edge_fanfare.mp3';
var SWF_PLAYER_URL = 'http://flash-mp3-player.net/medias/player_mp3_multi.swf';
var DEFAULT_BUILDING_SOUND_URL = 'http://wackoscripts.com/mp3/construction.mp3';
var DEFAULT_TRAINING_SOUND_URL = 'http://wackoscripts.com/mp3/training.mp3';
var DEFAULT_RESEARCH_SOUND_URL = 'http://wackoscripts.com/mp3/research.mp3';

// Tab order
var INFO_TAB_ORDER			= 1;     
var JOBS_TAB_ORDER			= 2;
var WAVE_TAB_ORDER			= 3;
var ATTACK_TAB_ORDER		= 4;
var ALLIANCE_TAB_ORDER		= 5;
var SEARCH_TAB_ORDER		= 6;
var BATTLE_TAB_ORDER		= 7;
var TOWER_TAB_ORDER			= 8;
var WALL_TAB_ORDER			= 9;
var OPTIONS_TAB_ORDER		= 10;
var MULTI_TAB_ORDER			= 20;
var SPY_TAB_ORDER			= 21;
var BOOKMARK_TAB_ORDER		= 22;
var LEADERBOARD_TAB_ORDER	= 23;
var LOG_TAB_ORDER			= 99;

// Tab enable/disable
var ALLIANCE_TAB_ENABLE		= true;
var ATTACK_TAB_ENABLE		= true;
var BATTLE_TAB_ENABLE		= true;
var BOOKMARK_TAB_ENABLE		= true;
var INFO_TAB_ENABLE			= true;     
var JOBS_TAB_ENABLE			= true;
var LEADERBOARD_TAB_ENABLE	= true;
var LOG_TAB_ENABLE			= true;
var MULTI_TAB_ENABLE		= true;
var OPTIONS_TAB_ENABLE		= true;
var SEARCH_TAB_ENABLE		= true;
var SPY_TAB_ENABLE			= true;
var TOWER_TAB_ENABLE		= true;
var WALL_TAB_ENABLE			= true;
var WAVE_TAB_ENABLE			= true;

// CHECK THESE VARIABLES
var DEBUG_TRACE_AJAX	= 2;
var DEBUG_MARCHES		= false;
var MAP_DELAY			= 750; //1250;
var MIN_DELAY			= 15;
var EMULATE_NET_ERROR	= 0;  // percentage
var ENABLE_WINLOG		= false;
var ALERT_ON_BAD_DATA	= false;
var MIN_DELAY_BETWEEN_WAVE = 30;

var BUTTON_BGCOLOR		= '#436';
var JOB_BUTTON_BGCOLOR	= '#436'; //'#049C93'; // Jawz

// Jawz - Message handling
var MESSAGES_ALL = 0;
var MESSAGES_ONLY = 1;
var REPORTS_ONLY = 2;
// Jawz - Message types
var MSG_BATTLE_REPORT = 1;
var TRANSPORT_MARCH_REPORT = 2;
var SPY_REPORT = 3;
var SENTINEL_WARNING = 4;
var REINFORCEMENTS_REPORT = 5;
var SYSTEM_MESSAGE = 6;
var PLAYER_MESSAGE = 7;
var ALLIANCE_MESSAGE = 8;

// Jawz - Capital and outposts IDs
var CAPITAL_ID = 0;
var SPECTRAL_OUTPOST_ID = 1;
var ICE_OUTPOST_ID = 2;
var SWAMP_OUTPOST_ID = 3;
var FOREST_OUTPOST_ID = 4;
var WATER_OUTPOST_ID = 5;
var STONE_OUTPOST_ID = 6;
var FIRE_OUTPOST_ID = 7;
var WIND_OUTPOST_ID = 8;

var IsChrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;

//
// Variables strings
//
// Terrain
var kAnthropusCamp		= 'AnthropusCamp';
var kCity				= 'City';
var kForest				= 'Forest';
var kGrassland			= 'Grassland';
var kHill				= 'Hill';
var kLake				= 'Lake';
var kMountain			= 'Mountain';
var kOutpost			= 'Outpost';
var kPlain				= 'Plain';
var kBog				= 'Bog';
var kWildernesses		= 'Wildernesses';
var kFog				= 'Fog';
var kSwamp				= 'Swamp';

// Buildings
var kDragonKeep			= 'DragonKeep';
var kFactory			= 'Factory';
var kFarm				= 'Farm';
var kFortress			= 'Fortress';
var kGarrison			= 'Garrison';
var kHome				= 'Home';
var kLumbermill			= 'Lumbermill';
var kMetalsmith			= 'Metalsmith';
var kMine				= 'Mine';
var kMusterPoint		= 'MusterPoint';
var kOfficerQuarter		= 'OfficerQuarter';
var kQuarry				= 'Quarry';
var kRookery			= 'Rookery';
var kScienceCenter		= 'ScienceCenter';
var kSentinel			= 'Sentinel';
var kSilo				= 'Silo';
var kStorageVault		= 'StorageVault';
var kTheater			= 'Theater';
var kTrainingCamp		= 'TrainingCamp';
var kWall				= 'Wall';
// Jawz - Added for spectral outpost
var kSpectralDragonKeep	= 'SpectralDragonKeep';
var kDarkPortal			= 'DarkPortal';
var kMausoleum			= 'Mausoleum';
var kEnergyCollector	= 'EnergyCollector';

// Research
var kAgriculture		= 'Agriculture';
var kWoodcraft			= 'Woodcraft';
var kMasonry			= 'Masonry';
var kMining				= 'Mining';
var kClairvoyance		= 'Clairvoyance';
var kRapidDeployment	= 'RapidDeployment';
var kBallistics			= 'Ballistics';
var kMetallurgy			= 'Metallurgy';
var kMedicine			= 'Medicine';
var kDragonry			= 'Dragonry';
var kLevitation			= 'Levitation';
var kMercantilism		= 'Mercantilism';
var kAerialCombat		= 'AerialCombat';
var kEnergyCollection	= 'EnergyCollection';
var kWarriorRevival		= 'WarriorRevival';
var kGuardianRevival	= 'GuardianRevival';

// Troops
var kArmoredTransport	= 'ArmoredTransport';
var kBattleDragon		= 'BattleDragon';
var kConscript			= 'Conscript';
var kFireMirror			= 'FireMirror';
var kGiant				= 'Giant';
var kHalberdsman		= 'Halberdsman';
var kLongbowman			= 'Longbowman';
var kMinotaur			= 'Minotaur';
var kPorter				= 'Porter';
var kSpy				= 'Spy';
var kSwiftStrikeDragon	= 'SwiftStrikeDragon';

// Special Troops
var kAquaTroop			= 'AquaTroop';
var kFireTroop			= 'FireTroop';
var kStoneTroop			= 'StoneTroop';
var kWindTroop			= 'WindTroop';
var kIceTroop			= 'IceTroop';
var kSwampTroop			= 'SwampTroop';
var kPackDragon			= 'PackDragon';
var kFrostGiant			= 'FrostGiant';
var kForestTroop		= 'ForestTroop';

// Dragons
var kFireDragon			= 'FireDragon';
var kGreatDragon		= 'GreatDragon';
var kStoneDragon		= 'StoneDragon';
var kWaterDragon		= 'WaterDragon';
var kWindDragon			= 'WindDragon';
var kIceDragon			= 'IceDragon';
var kSwampDragon		= 'SwampDragon';
var kSpectralDragon		= 'SpectralDragon';
var kForestDragon		= 'ForestDragon';

// Troop abbreviations
var kATrans		= 'ATrans';
var kWTroop		= 'Banshee';
var kBatDrg		= 'BatDrg';
var kConscr		= 'Conscr';
var kATroop		= 'Fang';
var kFireM		= 'FireM';
var kITroop		= 'SReaper';
var kFireDrg	= 'FireDrg';
var kGrtDrg		= 'GrtDrg';
var kHalbrd		= 'Halbrd';
var kFTroop		= 'Magma';
var kLBM		= 'LBM';
var kMino		= 'Mino';
var kSTroop		= 'Ogre';
var kSwTroop	= 'Venom';
var kSSDrg		= 'SSDrg';
var kStnDrg		= 'StnDrg';
var kWatDrg		= 'WatDrg';
var kWndDrg		= 'WndDrg';
var kIceDrg		= 'IceDrg';
var kSwpDrg		= 'SwpDrg';
var kPackDrg	= 'PackDrg';
var kSpctDrg	= 'SpctDrg';
var kFGiant		= 'FGiant';
var kForDrg		= 'ForDrg';
var kForTroop	= 'Titan';

// Items
var kAquaTroopRespirator	= 'AquaTroopRespirator';
var kStoneTroopItem			= 'StoneTroopItem';
var kFireTroopItem			= 'FireTroopItem';
var kWindTroopItem			= 'WindTroopItem';
var kIceTroopItem			= 'IceTroopItem';
var kSwampTroopItem			= 'SwampTroopItem';
var kFrostGiantItem			= 'FrostGiantItem';
var kForestTroopItem		= 'ForestTroopItem';

// Error messages
var kFatalSeedTitle	= 'ERROR WHILST FETCHING DATA FROM SERVER';
var kFatalSeedMsg	= 'Please disable the script and see if you are able to play the game manually. If normal play is possible then enable the script and try again. If the error persists please read the following post before submitting a report. If normal play is not possible then wait until it is and try again.';


// Main arrays used in the script
// Troops arrays
var all_dragon_list		 = ['GreatDragon', 'WaterDragon', 'StoneDragon', 'FireDragon', 'WindDragon', 'IceDragon', 'SwampDragon', 'ForestDragon', 'SpectralDragon'];
var all_unit_types		 = [ kPorter, kConscript, kSpy, kHalberdsman, kMinotaur, kLongbowman, kSwiftStrikeDragon, kBattleDragon, kArmoredTransport, kGiant, kFireMirror, kPackDragon, kAquaTroop, kStoneTroop, kFireTroop, kWindTroop, kIceTroop, kSwampTroop, kFrostGiant, kForestTroop];
var capital_units		 = [ kPorter, kConscript, kSpy, kHalberdsman, kMinotaur, kLongbowman, kSwiftStrikeDragon, kBattleDragon, kArmoredTransport, kGiant, kFireMirror ];
var water_outpost_units	 = [ kPorter, kConscript, kSpy, kHalberdsman, kMinotaur, kLongbowman, kSwiftStrikeDragon, kBattleDragon, kArmoredTransport, kGiant, kFireMirror, kAquaTroop, kStoneTroop, kFireTroop, kWindTroop, kIceTroop, kSwampTroop, kFrostGiant, kForestTroop];
var stone_outpost_units	 = [ kPorter, kConscript, kSpy, kHalberdsman, kMinotaur, kLongbowman, kSwiftStrikeDragon, kBattleDragon, kArmoredTransport, kGiant, kFireMirror, kAquaTroop, kStoneTroop, kFireTroop, kWindTroop, kIceTroop, kSwampTroop, kFrostGiant, kForestTroop];
var fire_outpost_units	 = [ kPorter, kConscript, kSpy, kHalberdsman, kMinotaur, kLongbowman, kSwiftStrikeDragon, kBattleDragon, kArmoredTransport, kGiant, kFireMirror, kAquaTroop, kStoneTroop, kFireTroop, kWindTroop, kIceTroop, kSwampTroop, kFrostGiant, kForestTroop];
var wind_outpost_units	 = [ kPorter, kConscript, kSpy, kHalberdsman, kMinotaur, kLongbowman, kSwiftStrikeDragon, kBattleDragon, kArmoredTransport, kGiant, kFireMirror, kAquaTroop, kStoneTroop, kFireTroop, kWindTroop, kIceTroop, kSwampTroop, kFrostGiant, kForestTroop];
var ice_outpost_units	 = [ kPorter, kConscript, kSpy, kHalberdsman, kMinotaur, kLongbowman, kSwiftStrikeDragon, kBattleDragon, kArmoredTransport, kGiant, kFireMirror, kAquaTroop, kStoneTroop, kFireTroop, kWindTroop, kIceTroop, kSwampTroop, kFrostGiant, kForestTroop];
var swamp_outpost_units	 = [ kPorter, kConscript, kSpy, kHalberdsman, kMinotaur, kLongbowman, kSwiftStrikeDragon, kBattleDragon, kArmoredTransport, kGiant, kFireMirror, kAquaTroop, kStoneTroop, kFireTroop, kWindTroop, kIceTroop, kSwampTroop, kFrostGiant, kForestTroop];
var forest_outpost_units = [ kPorter, kConscript, kSpy, kHalberdsman, kMinotaur, kLongbowman, kSwiftStrikeDragon, kBattleDragon, kArmoredTransport, kGiant, kFireMirror, kAquaTroop, kStoneTroop, kFireTroop, kWindTroop, kIceTroop, kSwampTroop, kFrostGiant, kForestTroop];
var all_trainable_units	 = [ kPorter, kConscript, kSpy, kHalberdsman, kMinotaur, kLongbowman, kSwiftStrikeDragon, kBattleDragon, kArmoredTransport, kGiant, kFireMirror, kAquaTroop, kStoneTroop, kFireTroop, kWindTroop, kIceTroop, kSwampTroop, kFrostGiant, kForestTroop];
var attack_unit_types	 = [ kPorter, kConscript, kSpy, kHalberdsman, kMinotaur, kLongbowman, kSwiftStrikeDragon, kBattleDragon, kArmoredTransport, kPackDragon, kGiant, kFireMirror, kAquaTroop, kStoneTroop, kFireTroop, kWindTroop, kIceTroop, kSwampTroop, kFrostGiant, kForestTroop];
var wave_unit_types		 = [ kPorter, kConscript, kSpy, kHalberdsman, kMinotaur, kLongbowman, kArmoredTransport, kPackDragon, kSwiftStrikeDragon, kBattleDragon, kGiant, kFireMirror, kAquaTroop, kStoneTroop, kFireTroop, kWindTroop, kIceTroop, kSwampTroop, kFrostGiant, kForestTroop];
var spy_unit_types		 = [ kSpy ];
var transport_unit_types = [ kPorter, kATrans, kPackDrg ]; // Beware : Use abbreviations here
// Resources arrays
var all_resource_types				= [	'gold', 'food', 'wood', 'ore', 'stone', 'blue_energy'];
var transportable_resource_types	= [	'gold', 'food', 'wood', 'ore', 'stone'];
// Buildings arrays
var capital_buildings	= [	kHome, kGarrison, kScienceCenter, kMetalsmith, kOfficerQuarter, kMusterPoint, kRookery, kStorageVault, kTheater, kSentinel, kFactory, kFortress, kDragonKeep, kWall];
var outpost_buildings	= [	kTrainingCamp, kHome, kSilo, kMusterPoint, kDragonKeep, kWall];
var field_buildings		= [	kMine, kFarm, kLumbermill, kQuarry];
var spectral_buildings	= [	kDarkPortal, kMausoleum, kSpectralDragonKeep];
var spectral_fields		= [	kEnergyCollector];
// Research arrays
var research_list		= {	Agriculture:'Agriculture', Woodcraft:kWoodcraft, Masonry:'Masonry', Mining:kMining, Clairvoyance:'Clairvoyance', RapidDeployment:'RapidDeployment', Ballistics:'Ballistics', Metallurgy:'Metallurgy', Medicine:'Medicine', Dragonry:kDragonry, Levitation:kLevitation, Mercantilism:'Mercantilism', AerialCombat:'AerialCombat', EnergyCollection:'EnergyCollection', WarriorRevival:'WarriorRevival', GuardianRevival:'GuardianRevival'};
var research_name		= [	kAgriculture, kWoodcraft, kMasonry, kMining, kClairvoyance, kRapidDeployment, kBallistics, kMetallurgy, kMedicine, kDragonry, kLevitation, kMercantilism, kAerialCombat, kEnergyCollection, kWarriorRevival, kGuardianRevival];
// Items arrays
var armor_item_list     = [	'GreatDragonClawGuards','GreatDragonBodyArmor',		'GreatDragonTailGuard',		'GreatDragonHelmet',
							'WaterDragonHelmet',	'WaterDragonBodyArmor',		'WaterDragonClawGuards',	'WaterDragonTailGuard',
							'StoneDragonHelmet',	'StoneDragonClawGuards',	'StoneDragonTailGuard',		'StoneDragonBodyArmor',
							'FireDragonHelmet',		'FireDragonClawGuards',		'FireDragonTailGuard',		'FireDragonBodyArmor',
							'WindDragonHelmet',		'WindDragonClawGuards',		'WindDragonTailGuard',		'WindDragonBodyArmor',
							'SpectralDragonHead',	'SpectralDragonTalons',		'SpectralDragonTail',		'SpectralDragonBody', 
							'SpectralDragonHelmet', 'SpectralDragonClawGuards', 'SpectralDragonTailGuard',	'SpectralDragonBodyArmor', 
							'IceDragonHelmet',		'IceDragonClawGuards',		'IceDragonTailGuard',		'IceDragonBodyArmor',
							'SwampDragonHelmet',	'SwampDragonClawGuards',	'SwampDragonTailGuard',		'SwampDragonBodyArmor',
							'ForestDragonHelmet',	'ForestDragonClawGuards',	'ForestDragonTailGuard',	'ForestDragonBodyArmor' ];


/*******************************************************************************
***************************      TRANSLATIONS      ****************************
*******************************************************************************/
var LANG_CODE = navigator.language.substring(0,2).toLowerCase();
var IS_NOT_NATIVE_LANG = (LANG_CODE !== 'en');
var TRANSLATION_ARRAY = {};

function setLanguage ( user_language ) {
LANG_CODE = user_language || LANG_CODE;
switch ( LANG_CODE ){
	/*******************************************************************************
		German  (by Northlight & rosebandit)
	*******************************************************************************/
case 'de':
	TRANSLATION_ARRAY = {
		'</B> and <B>' : '</B> und <B>',
		'<B>Attacker\'s move turn</B>' : '<B>Bewegungszug des Angreifers</B>',
		'<B>Attacker\'s attack turn</B>' : '<B>Angriffszug des Angreifers</B>',
		'<b>Bad request!</b>' : '<b>Ungültige Anfrage</b>',
		'<B>Defender\'s move turn</B>' : '<B>Bewegungszug des Verteidigers</B>',
		'<B>Defender\'s attack turn</B>' : '<B>Angriffszug des Verteidigers</B>',
		'<b>Rate Limit Exceeded</b>, too many requests!' : '<b>Serveranfragenlimit überschritten</b>',
		'About KabaListics' : 'Über KabaListics',
		'above the first value' : 'über dem ersten Wert liegen',
		'Action Log' : 'Aktions Log',
		'Actions' : 'Aktionen',
		'Activate Attacks Logs' : 'Angriffslogs aktivieren',
		'Alerts log' : 'Alarmlog',
		'Alives' : 'Überlebt',
		'All alliances' : 'Alle Allianzen',
		'All players' : 'Alle Spieler',
		'All types' : 'Alle',
		'Alliance features' : 'Allianzmerkmale',
		'Alliances list retrieved' : 'Allianzliste empfangen',
		'Alliance members list retrieved' : 'Mitgliederliste erneuert',
		'Alliance messages' : 'Allianznachrichten',
		'and' : 'und',
		'Another march request is pending' : 'Eine andere Marschanforderung ist unerledigt',
		'Are you sure you want to delete All Permanent Data' : 'Bist du sicher, dass du deine permanenten Daten löschen willst',
		'Arrival time' : 'Ankunftszeit',
		'at' : 'an',
		' at ' : ' an ',
		' at range' : ' in Reichweite',
		'Attack sent to' : 'Angriff gesendet an',
		'Attack One Target in Multiple waves' : 'Multiwellenangriff auf ein Ziel',
		'Attacker' : 'Angreifer',
		'Attacking' : 'Angriff',
		'Attacks Configuration' : 'Angriffseinstellung',
		'Attacks Stats' : 'Angriffsstats',
		'Attacks' : 'Angriffe',
		'attempted' : 'versuche',
		'attempt for' : 'versuch für',
		'Auto harvest resources from outposts every' : 'Ressourcen einsammeln vom Außenposten',
		'Auto refresh info tab data every' : 'automatisches Auffrischen des Info-Reiters alle',
		'Automatically' : 'Automatisch',
		'Automatically recall transport 1 minute before delivery' : 'Automatisches Zurückrufen des Transports 1 Min vor Lieferung',
		'available' : 'vorhanden',
		'Available troops' : 'Verfügbare Truppen',
		'Awaiting task completion notification' : 'erwarte Fertigmeldung',
		'Back at the same time' : 'Zur gleichen Zeit zurück',
		'Backup' : 'Sicherung',
		'Battle' : 'Kampf',
		'Battle calculator' : 'Kampf-Simulator',
		'Battle forces' : 'Streitkräfte',
		'Battle log' : 'Kampfbericht',
		'Battle lost !!' : 'Kampf verloren !!',
		'Battle mechanics' : 'Kampfmechaniken',
		'Battle won !!' : 'Kampf gewonnen !!',
		'blue_energy' : 'Blaue Energie',
		'Bookmark' : 'Lesezeichen',
		'Bookmark saved' : 'Lesezeichen gespeichert',
		'Bookmarks' : 'Lesezeichen',
		'Bookmarks Configuration' : 'Lesezeicheneinstellungen',
		'Building' : 'Gebäude',
		'Busy' : 'Beschäftigt',
		'by' : 'von',
		'By distance ascending' : 'Nach kürzeste Entfernung',
		'By distance descending' : 'Nach weiteste Entfernung',
		'Cache data' : 'Permanente Daten',
		'Calculate' : 'Simuliere',
		'Camps/wilds attack reports' : 'Anthro/Wildnis Kampfbericht',
		'Capital data' : 'Hauptstadtdaten',
		'Capital data successfully fetched' : 'Hauptstadtdaten erfolgreich eingelesen',
		'Check sentinel reports every ' : 'Überprüfe den Sentinelbericht alle',
		'Check to use UTC time instead of local time' : 'prüfe, ob UTC Zeit anstatt der eigenen Zeitzone verwendet werden soll',
		'Check the following great dragons to exclude them from being sent' : 'Prüfe, ob die folgenden Groß-/Elementdrachen vom Angriff ausgeschlossen werden sollen',
		'Claim' : 'Holen',
		'Claimed' : 'Abgeholt',
		'Claiming quest' : 'Quest abholen',
		'Clear' : 'löschen',
		'Clear all' : 'alles löschen',
		'Clear all data' : 'Alle Daten löschen',
		'Clear last attack on all maps' : 'Lösche die letzten Angriffe auf allen Karten',
		'Clear last attack on current map' : 'Lösche die letzten Angriffe auf der aktuellen Karte',
		'Clear local storage (internet cache)' : 'Lösche den Internet Cache',
		'Clear log' : 'Log löschen',
		'Clear Stats' : 'Statistik löschen',
		'Collected resources at outpost' : 'eingesammelte Resourcen im Aussenposten',
		'Completing...' : 'Fertigstellen...',
		'Completion errors' : 'Fehler beim Fertigstellen',
		'Config' : 'Einstellung',
		'Confirmation' : 'Bestätigung',
		'Console Log' : 'Konsolen Log',
		'Console' : 'Konsole',
		'Coordinates' : 'Koordinaten',
		'Coords' : 'Koords',
//		'Copy troops reported by the sentinel to the battle calculator' : '?????',
		' damages taken' : ' Schaden genommen',
		' damages to ' : ' Schaden verursacht am ',
		'data' : 'Daten',
		'data successfully fetched' : 'Daten erfolgreich eingesammelt',
		'Date range' : 'Daten Reichweite',
		'Days' : 'Tage',
		' deal ' : ' Deal ',
		'Defender' : 'Verteidiger',
		'Defending' : 'Verteidigen',
		'Defense force modified' : 'Verteidigung aktualisiert',
		'Defense strategy' : 'Verteidigungsstrategie',
		'Delay before script startup' : 'Verzögerung vor Scriptstart',
		'Delay Between Attacks' : 'Verzögerung zwischen Angriffen',
		'Delay Between Transports' : 'Verzögerung zwischen den Transporten',
		'delayed due to' : 'Verzögerung, weil',
		'delayed due to march limit reached' : 'Verzögerung, weil Anzahl max. Märsche erreicht wurde',
		'delayed due to muster point full' : 'Verzögerung, weil Truppensammelplatz voll ist',
		'delayed due to no available generals' : 'Verzögerung, weil keine Generäle verfügbar sind',
		'delayed due to no available Great Dragon' : 'Verzögerung, weil keine Drachen verfügbar sind',
		'delayed due to pending march request' : 'Verzögerung, weil die Rückmeldung zum Marsch aussteht',
		'delayed due to insufficient troops' : 'Verzögerung, weil keine passenden Truppen verfügbar sind',
		'Delete now' : 'jetzt löschen',
		'Delete Battle Reports' : 'Kampfberichte löschen',
		'Delete messages' : 'Nachrichten löschen',
		'Delete messages of this type' : 'Nachrichten diesen Typs löschen',
		'Delete spy reports' : 'Spion-Berichte löschen',
		'Detailed search' : 'detaillierte Suche', 
		'Disable <B>Alliance</B> tab' : 'Deaktivieren <B>Allianz</B> Reiter',
		'Disable <B>Battle</B> tab' : 'Deaktivieren <B>Kampf-Simulator</B> Reiter',
		'Disable <B>Bookmarks</B> tab' : 'Deaktivieren <B>Lesezeichen</B> Reiter',
		'Disable <B>Multi</B> tab' : 'Deaktivieren <B>Multi</B> Reiter',
		'Disable <B>Search</B> tab' : 'Deaktivieren <B>Karte</B> Reiter',
		'Disable <B>Spy</B> tab' : 'Deaktivieren <B>Spio</B> Reiter',
		'Disable <B>Wall</B> tab' : 'Deaktivieren <B>Stadtmauer</B> Reiter',
		'Disable <B>Wave</B> tab' : 'Deaktivieren <B>Welle</B> Reiter',
		'Disable <B>Log</B> tab' : 'Deaktivieren <B>Log</B> Reiter',
		'Disabled' : 'Deaktiviert',
		'Display official background image' : 'Offizielles Hintergrundbild anzeigen',
		'Dist' : 'Distanz',
		'Distance must be between' : 'Entfernung muss liegen zwischen',
		'Distance' : 'Distanz',
		'Dragon healing' : 'Drachen Heilung',
		'Dragons' : 'Drachen',
		'Do not show alerts obsolete since' : 'Keine Alarme anzeigen vor',
//		'Do you want to delete existing Permanent Data' : '?????',
		'Do you want to save in Permanent Data the current script setting' : 'Möchtest du deine aktuellen Einstellungen in den permanenten Daten speichern',
		'Do you want to save Map Data in local file' : 'Möchtest du die kartendaten in einer lokalen Datei speichern', // Jawz
		'Do you want to save Permanent Data in local file' : 'Möchtest du die permanenten Daten in einer lokalen Datei speichern',
		'Dutch' : 'Holländisch',
		'Edit' : 'bearbeiten',
		'Edit defense' : 'Verteidigung bearbeiten',
		'Edit bookmark' : 'Lesezeichen bearbeiten',
		'Enable' : 'Aktivieren',
//		'Enable cheat (all troops in all outposts, transport of blue energy)' : 'Aktiviere cheat (alle truppen in allen Außenposten, transport von Blaue Energie)', // Jawz
		'Enable transport of blue energy' : 'Aktiviere transport von Blaue Energie',
		'Enable use of speed-ups in attacks waves' : 'Beschleuniger in Attacken und Wellen benutzen',
		'Enable verbose logging' : 'Aktiviere ausführlichen Log',
		'Enable window drag' : 'Fensterverschiebung aktivieren',
		'Enable the sentinel tower' : 'Aktiviere Sentinelturm',
		'Enabled' : 'Aktiviert',
		'End' : 'Ende',
		'English' : 'Englisch',
		'Ennemy General' : 'Feindlicher General',
		'Ennemy research levels' : 'Feindlicher Forschungslevel',
		'Enter -1 as troop quantity to use the maximum available' : 'Trage -1 ein, um die max. verfügbaren Truppen zu benutzen',
		'Error' : 'Fehler',
		'Error while retrieving the list of members' : 'Fehler beim Empfang der Mitgliederliste',
		'Error while setting defense choice' : 'Fehler beim Einstellen der Verteidigung',
		'Evol' : 'Entwicklung',
		'Except' : 'außer',
		'Exception' : 'Ausnahme',
		'failed' : 'gescheitert',
		'failed and returned error' : 'gescheitert mit Fehler',
		'Fast search' : 'schnelle Suche', 
		'Features' : 'Features',
		'Fetching' : 'Auslesen',
		'Fetching Capital data' : 'Hauptstadtdaten auslesen',
		'Fetching Manifest' : 'Manifest auslesen',
		'Fetching Outpost #' : 'Außenposten auslesen #',
		'Fetching Seed' : 'Seed auslesen',
		'Fetching Translation matrix' : 'Übersetzungsmatrix auslesen',
		'Fire' : 'Feuer',
		'fire_dragon outpost' : 'Feueraußenposten',
		'First value must be between' : 'Erster Wert muss liegen zwischen ',
		'Flash game Auto refresh every' : 'Automatisches Auffrischen des Spiels alle:',
//		'Foes' : '?????',
		'for' : 'für',
		'Force saving current script settings' : 'speichern der aktuellen Einstellungen erzwingen',
		'Forum link' : 'Link zum Forum',
		'French' : 'Französisch',
		'Game messages' : 'Spielnachrichten',
		'Game Options' : 'Spieloptionen',
		'GD' : 'Stadtdrache',
		'Generals' : 'Generäle',
		'German' : 'Deutsch',
		'Getting basic data...' : 'Grunddaten abholen...',
		'Getting cities data...' : 'Städtedaten abholen...',
		'Getting game data...' : 'Spieldaten abholen... ',
		'Got' : 'Gefunden',
		'Great dragons' : 'Gross-/Elementdrachen',
		'Help/About' : 'Hilfe/Über',
		'Hide spy alerts' : 'Verstecke Spionagealarme',
		'Hiding' : 'Verstecken',
		'History' : 'Zielespeicher',
		'h' : 'std',
		'Hours' : 'Stunden',
		'ice_dragon outpost' : 'Eisaußenposten',
		'Ice' : 'Eis',
		'Idle pop' : 'Freie Bürger',
		'Idle' : 'inaktiv',
		'In city' : 'In der Stadt',
		'In march' : 'In Bewegung',
		' in melee' : ' im Nahkampf',
		'in progress' : 'in Barbeitung',
		'Include Great Dragon' : 'Groß-/Elementdrachen einschließen',
		'Info' : 'Info',
		'Initialization' : 'Initialisierung',
		'Initializing...' : 'initialisiere...',
		'Initializing map, auto-collect, ...' : 'Initialisierung Karte, Auto-Einsammeln , ...',
		'Invalid Date From' : 'Ungültiges Datumsformat von',
		'Invalid Date To' : 'Ungültiges Datumsformat bis',
		'Invalid date range' : 'Ungültige Datumsangabe',
		'Invalid delays' : 'Ungültige Verzögerung',
		'Invalid number of troops' : 'Ungültige Truppengröße',
		'Inventory' : 'Inventar',
		'Joined' : 'Eingetreten',
		'Keep battle reports of attacks from other players' : 'Kampfberichte anderer Spieler behalten',
		'Keep battle reports of my attacks on other players' : 'Meine Kampfberichte gegen andere Spieler behalten',
		' (kill ' : ' (töte ',
		'Killed' : 'Getötet',
		'Last attack' : 'Letzter Angriff',
		'leader' : 'Anführer',
		'life lost' : 'Leben verloren',
		'Loaded' : 'Geladen',
		'Loading basic data' : 'Grunddaten laden',
		'Locale data was Successfully requested from the server' : 'Lokale Daten erfolgreich vom Server abgerufen',
		'Logs' : 'Log',
		'Log' : 'Log',
		'lord' : 'Lord',
		'Manifest not available, using defaults' : 'Manifest nicht verfügbar, nutze Standardeinstellungen',
		'Manifest Successfully initialized' : 'Manifest erfolgreich initialisiert',
		'Manifest was Successfully requested from the server' : 'Manifest erfolgreich vom Server abgerufen',
		'Manual attack sent to' : 'Manueller Angriff gesendet an',
		'March limit reached' : 'Marschlimit erreicht',
		'Max level' : 'Max Level',
		'Map Search' : 'Kartensuche',
		'Maximize resource to transport according to max load' : 'max. Ressourcen auffüllen, um die volle Ladung zu transportieren',
		'Maximum level reached' : 'Maximales Level erreicht',
		'Maximum simultaneous marches' : 'Maximal gleichzeitige Märsche',
		'Maximum training queues possible per city, according to available resources' : 'Maximale Anzahl an Ausbildungsschleifen pro Stadt, bezogen auf die verfügbaren Ressourcen',
		'Members' : 'Mitglieder',
		'Members list ' : 'Mitgliederliste ',
		'Message(s) deleted' : 'Nachricht(en) gelöscht',
		'Message(s) deletion in progress' : 'Nachrichtenlöschung in Verarbeitung',
		'miles' : 'Meilen',
		'Min level' : 'Min Level',
		'Minutes' : 'Minuten',
		' move to ' : ' gehe zu ',
		'Multi' : 'Multi',
		'Muster Point Full' : 'Truppensammelplatz voll',
		'Need' : 'benötige',
//		'New version has been installed...' : '?????...',
		'No Generals Available' : 'Keine Generäle verfügbar',
		'No great dragon available' : 'Keine Groß-/Elementdrachen verfügbar',
		'no max' : 'kein Maximum',
		'No new Version of' : 'Keine neue Version von',
		'No resources to transport defined' : 'Keine Rohstoffe für Transport ausgewählt',
		'No Troops Defined' : 'Keine Truppen ausgewählt',
		'Not enough' : 'Nicht genug',
		'Not' : 'nicht',
		'Not ready' : 'Nicht bereit',
		'of' : 'von',
		'one attack' : 'ein Angriff',
		'one spy' : 'ein Spion',
		'Only one training queue per city' : 'Nur eine Ausbildungsschleife pro Stadt ',
		'Options' : 'Optionen',
		'Opts' : 'Opts',
		'Outpost 1' : 'Wasseraußenposten',
		'Outpost 2' : 'Steinaußenposten',
		'Outpost 3' : 'Feueraußenposten',
		'Outpost 4' : 'Windaußenposten',
		'Outpost #1' : 'Outpost #1',
		'Outpost #2' : 'Outpost #2',
		'Outpost #3' : 'Outpost #3',
		'Outpost #4' : 'Outpost #4',
		'Outpost #5' : 'Outpost #5',
		'Outpost #6' : 'Outpost #6',
		'Outpost #7' : 'Outpost #7',
		'Outpost damages' : 'Schaden am Außenposten',
		'overlord' : 'Oberster Lord',
		'Overview' : 'Übersicht',
		'Owner' : 'Besitzer',
		'Play for' : 'abspielen für',
		'Play sound on incoming sentinel report' : 'Sound bei eingehendem Sentinelbericht abspielen',
		'Play sound on task completion' : 'Soundbenachrichtigung bei Fertigstellung',
		'Player cities' : 'Spieler Städte',
		'Player cities list' : 'Liste Spieler Städte',
		'Player data was Successfully requested from the server' : 'Spielerdaten wurden erfolgreich vom Server abgefragt',
		'Player messages' : 'Spieler Nachrichten',
		'Player name' : 'Spielername',
		'Please wait...' : 'bitte warten...',
		'Preset' : 'Voreinstellung',
		'Preset name' : 'Name der Voreinstellung',
		'Primary attack to ' : 'Primär Angriff auf ',
		'Putting build job in persistent data' : 'Bauauftrag in permanente Daten erfassen',
		'Putting research job in persistent data' : 'Ausbildungsauftrag in permanente Daten erfassen',
		'Putting resurrect job in persistent data' : 'Wiederbelebungauftrag in permanente Daten erfassen',
//		'Quantity' : '?????',
		'Quest' : 'Quest',
		'Quest claim Error' : 'Fehler bei der Questbeanspruchung',
		'Rate Limit Exceeded because there were too many requests' : 'Zulässige Anfragenzahl überschritten',
		'Read page ' : 'Seite auslesen ',
		'Ready' : 'Bereit',
		'Recipient' : 'Empfänger',
		'Refresh' : 'Auffrischen',
		'Refresh list' : 'Liste auffrischen',
		'Refresh map data' : 'Kartendaten auffrischen',
		'Refresh selection' : 'Auswahl auffrischen',
		'Reinforcement' : 'Verstärkung',
		'Reinforcement reports' : 'Verstärkungsbericht',
		'Reinforcement sent to' : 'Verstärkung gesendet an',
		'Reload' : 'Neuladen',
		'Remove all' : 'Alle Truppen entfernen',
		'Repairing' : 'Reparieren',
		'Repeat every' : 'Wiederholen alle',
		'Research Started' : 'Forschung gestartet',
		'Researching' : 'Forschen',
		'Reset Stats' : 'Statistik zurücksetzen',
		'Resources stock levels update failed' : 'Kapazitätenupdate gescheitert',
		'Resources to transport' : 'Rohstoffe zum Transportieren',
		'Restore' :  'Wiederherstellen',
		'Restore script settings from local file' : 'Skript Einstellungen aus lokaler Datei wiederherstellen',
		'Resurrect' : 'Auferstehen',
		'Resurrection' : 'Wiederauferstehung',
		'Retry in' : 'Wiederholen in :',
		'Reviving' : 'Wiederbelebung',
		'Role' : 'Rolle',
		'Rules' : 'Regeln',
		'Run Time' : 'Laufzeit',
		'Safe Mode' : 'Sicherheitsmodus',
		'Save Attaque' : 'Speichern',
		'Save current script settings in a local file' : 'Aktuelle Script Einstellungen in lokaler Datei speichern',
		'Save current map data in a local file' : 'Speichern der aktuellen Kartendaten in eine lokale Datei', 
		'Save preset' : 'Voreinstellung speichern',
		'Scanning map' : 'Scanne die Karte nur für Städte',
		'Scanning map for cities/wildernesses' : 'Scanne die Karte nach Städten und Wildnissen',
		'Scanning map for wildernesses' : 'Scanne die Karte nur fûr Wildnisse',
		'Script language' : 'Script Sprache',
		'Script Options' : 'Script Optionen',
		'Search coords' : 'Koords suchen',
		'Search for alliance list' : 'Suche nach Allianzliste',
		'Search for alliance members' : 'Allianzmitglieder suchen',
		'Search max radius' : 'Max. Suchradius',
		'Search Radius' : 'Suchradius',
		'Second value must be at least' : 'Der zweite Wert muss mindestens',
		'Seconds' : 'Sekunden',
		'seconds' : 'Sekunden',
		'Secondary attack to ' : 'Zweite Attacke auf ',
		'Seed Successfully initialized' : 'Seed erfolgreich eingelesen',
		'Select at least one type of message or report to delete' : 'wähle mind. eine Nachricht oder einen Bericht zum Löschen',
		'Send reinforcement' : 'Verstärkung senden',
		'Send transport' : 'Transport senden',
		'Sending reinforcement' : 'Verstärkung senden',
		'Sending transport' : 'Transport senden',
		'Sentinel messages' : 'Sentinelnachricht',
		'Sentinel tower' : 'Sentinelturm',
		'Set defense' : 'Verteidigung aktivieren',
		'Set Def' : 'Deff aktivieren',
		'Setting defense' : 'Veteidigung einstellen',
		'several attacks' : 'einige Attacken',
		'several spies' : 'einige Spios',
		'Souls' : 'Seelen',
		'Sound configuration' : 'Soundeinstellung',
		'Sound file' : 'Sounddatei',
		'Spanish' : 'Spanisch',
		'spectral_dragon outpost' : 'Spektral Ruine',
		'Spectral' : 'Spektral',
		'SpectralDragonKeep' : 'Drachenaltar',
		' spent. 1 min timeout (defense respawn)' : ' warte 1 min timeout (Verteidiger Respawn)',
		' spent. 2 min timeout (defense respawn)' : ' warte 2 min timeout (Verteidiger Respawn)',
		'Spies done' : 'Spione erledigt',
		'Spies number' : 'Anzahl Spione',
		'Spy One Target' : 'Ein Ziel spionieren',
		'Spy reports' : 'Spiobericht',
		'Spy to ' : 'Spion zu ',
		'Stars' : 'Sterne',
		'Start' : 'Start',
		'Start Date' : 'Startdatum',
		'Starting...' : 'Starten...',
		'Step' : 'Schritt',
		'Stone' : 'Stein',
		'stone_dragon outpost' : 'Steinaußenposten',
		'Stop if any troops lost' : 'Stopp bei Truppenverlust',
		'succeeded' : 'gelungen',
		'Successfully initialized' : 'Erfolgreich initialisiert',
		'Successfully' : 'Erfolgreich',
		'Summary' : 'Zusammenfassung',
		' survivals)' : ' Überlebende)',
//		'Swamp' : '?????',
		'swamp_dragon outpost' : 'Sumpfaußenposten',
		'Swedish' : 'Schwedisch',
		'switchDefense OK' : 'Verteidigungswechsel erfolgreich',
		'Switch defense wall status' : 'wechsel Status der Mauer',
		'Switching defense' : 'Verteidigung wechseln',
		'Tabs Options' : 'Reiter Optionen',
		'Target' : 'Ziel',
		'Targets' : 'Ziele',
		'Task Completed' : 'Aufgabe erledigt',
		'Tasks' : 'Aufgaben',
		'Terrain length set to ' : 'Gebietsgröße gesetzt auf ',
//		'This should not clear map and alliance data.' : '?????.',
		'Time' : 'Dauer',
		'to' : 'bis',
		'To be refreshed' : 'aktualisiert',
		'Toggle Flash' : 'Flash umswitchen',
		'Too many troops for muster point level' : 'Zuviele Truppen für Truppensammelplatzstufe',
		'Total souls' : 'Seelen total',
		'Tower' : 'Wachturm',
		'Tower configuration' : 'Wachturmeinstellung',
		'Training Configuration' : 'Ausbildungseinstellung',
		'Translation Matrix Successfully initialized' : 'Übersetzung erfolgreich initialisiert ',
		'Transport reports' : 'Transportbericht',
		'Transport sent to' : 'Transport zu',
		'Troops Capped' : 'Truppen gestoppt',
		'Troops for Bookmarks Attack' : 'Truppen für Lesezeichen Angriff',
		'Troops for defense' : 'Truppen für Verteidigung',
		'Troops for Primary Attack' : 'Truppenauswahl für erste Attacke',
		'Troops for reinforcement' : 'Truppen für Verstärkung',
		'Troops for Secondary Attacks' : 'Truppenauswahl für zweite Attacke',
		'Troops for transport' : 'Truppen für Transport',
		'Troops for Wave Attack' : 'Truppen für Welle',
		'Troops lost' : 'Truppen verloren',
		'Troops max' : 'max. Truppen',
		'Troops statistics' : 'Truppenstatistik',
		'Troops statistics for' : 'Truppenstatistik',
		'Turkish' : 'Türkisch',
		'Turned Off' : 'Abgeschaltet',
		'Unlimited' : 'Unendlich',
		'Unowned only' : 'Nur unbesetzte Wildnisse',
		'Updating City values' : 'Stadteinstellungen aktualisieren',
		'Upgrading items' : 'Verbesserungs-Items',
		'Use the Levels Tab to select attack areas' : 'benutze den Level-Reiter, um das Angriffsgebiet auszuwählen',
		'Version update' : 'Versions Update',
		'Wall defense setting' : 'Verteidigungseinstellung',
		'Wall management' : 'Mauer Einstellung',
		'Warning for ' : 'Warnung für ',
		'was returned with a status of' : 'zurückgewiesen mit dm Status',
		'Water' : 'Wasser',
		'water_dragon outpost' : 'Wasseraußenposten',
		'Wave attack to ' : 'Wellenangriff auf ',
		'Wave' : 'Welle',
		'Wiki URL' : 'Wiki URL',
		'Wildernesses list' : 'Wildnisliste',
		'Wind' :'Wind',
		'wind_dragon outpost' : 'Windaußenposten',
		'Without alliance' : 'Allianzlos',
		'You are' : 'Du bist',
		'Yoyo' : 'Jo-Jo',
		'Yoyo functionality' : 'Jo-Jo Funktion',
		'ATrans' : 'Luftis',		/* abbr gepanzerte Lufttransporter */
		'Banshee' : 'Banshee',		/* abbr Banshee */
		'BatDrg' : 'KampfDr',		/* abbr Kampfdrache */
		'Conscr' : 'Rekrut',		/* abbr Rekrut */
		'Fang' : 'Giftis',			/* abbr Giftklaue */
//		'FGiant' : '?????',			/* abbr Frost giant */
		'FireDrg' : 'FeuerDr',		/* abbr Feuerdrache */
		'FireM' : 'FeuerSp',		/* abbr Feuerspiegel */
		'GrtDrg' : 'GroßDr',		/* abbr Großdrache */
		'Halbrd' : 'Helle',			/* abbr Hellebarde */
		'IceDrg' : 'EisDr',			/* abbr Eisdrachen */
		'LBM' : 'Bogi',				/* abbr Bogenschütze */
		'Magma' : 'Pyro',			/* abbr Pyrosaurier */
		'Mino' : 'Mino',			/* abbr Minotaurus */
		'Ogre' : 'Oger',			/* abbr Granit-Oger */
		'PackDrg' : 'TransportDr',	/* abbr Transportdrache */
		'SpctDrg' : 'SpektralDr',	/* abbr Steindrache */
		'SReaper' : 'SRäuber',		/* abbr Seelenräuber */
		'SSDrg' : 'kFD',			/* abbr kleiner Feuerdrache */
		'StnDrg' : 'SteinDr',		/* abbr Steindrache */
		'SwpDrg' : 'Giftschlange',	/* abbr Swamp Dragon */
		'Venom' : 'Kröten',			/* abbr Sumpfkröte */
		'WatDrg' : 'WasserDr',		/* abbr Wasserdrache */
		'WndDrg' : 'WindDr',		/* abbr Wind Dragon */
		// Missing Kabam translations 
		'Fire Dragon' : 'Feuerdrache',
		// Objects
		'WaterEgg' : 'Ei des Wasserdrachen',
		'StoneEgg' : 'Ei des Steindrachen',
		'FireEgg' : 'Ei des Feuerdrachen',
		'WindEgg' : 'Ei des Winddrachen',
		'IceEgg' : 'Ei des Eisdrachen',
		'SwampEgg' : 'Schlangenei',
		'GD Body' : 'Rüstung des Großdrachen',
		'GD Helmet' : 'Helm des Großdrachen',
		'GD Tail' : 'Schweifschutz des Großdrachen',
		'GD Claw' : 'Klauenschutz des Großdrachen',
		'IceD Body' : 'Rüstung des Eisdrachen',
		'IceD Helmet' : 'Helm des Eisdrachen',
		'IceD Tail' : 'Schweifschutz des Eisdrachen',
		'IceD Claw' : 'Klauenschutz des Eisdrachen',
		'SpD Armor' : 'Körper des Spektraldrachen - Hügel',
		'SpD Body' : 'Körper des Spektraldrachen - Hügel',
		'SpD Helmet' : 'Kopf des Spektraldrachen - Wald',
		'SpD Head' : 'Kopf des Spektraldrachen - Wald',
		'SpD Tail' : 'Schweif des Spektraldrachen - See',
		'SpD TailG' : 'Schweif des Spektraldrachen - See',
		'SpD Claw' : 'Gebeine des Spektraldrachen - Berg',
		'SpD Talons' : 'Gebeine des Spektraldrachen - Berg',
		'WD Body' : 'Rüstung des Wasserdrachen',
		'WD Helmet' : 'Helm des Wasserdrachen',
		'WD Tail' : 'Schweifschutz des Wasserdrachen',
		'WD Claw' : 'Klauenschutz des Wasserdrachen',
		'SD Body' : 'Rüstung des Steindrachen',
		'SD Helmet' : 'Helm des Steindrachen',
		'SD Tail' : 'Schweifschutz des Steindrachen',
		'SD Claw' : 'Klauenschutz des Steindrachen',
		'FD Body' : 'Rüstung des Feuerdrachen',
		'FD Helmet' : 'Helm des Feuerdrachen',
		'FD Tail' : 'Schweifschutz des Feuerdrachen',
		'FD Claw' : 'Klauenschutz des Feuerdrachen',
		'WiD Body' : 'Rüstung des Winddrachen',
		'WiD Helmet' : 'Helm des Winddrachen',
		'WiD Tail' : 'Schweifschutz des Winddrachen',
		'WiD Claw' : 'Klauenschutz des Winddrachen',
		'SwD Body' : 'Rüstung der Giftschlange',
		'SwD Helmet' : 'Helm der Giftschlange',
		'SwD Tail' : 'Schweifschutz der Giftschlange',
		'SwD Claw' : 'Klauenschutz der Giftschlange',
		'Respirators' : 'Atemgeräte',
		'Respirator-100' : '100 Atemgeräte',
		'Respirator-500' : '500 Atemgräte',
		'Respirator-1000' : '1000 Atemgeräte',
		'Mandrakes' : 'Zauberwurzeln',
		'Mandrakes-100' : '100 Zauberwurzeln',
		'Mandrakes-500' : '500 Zauberwurzeln',
		'Mandrakes-1000' : '1000 Zauberwurzeln',
		'Runes' : 'Runen',
		'Runes-100' : '100 Runen',
		'Runes-500' : '500 Runen',
		'Runes-1000' : '1000 Runen',
		'Talons' : 'Krallen',
		'Talons-100' : '100 Krallen',
		'Talons-500' : '500 Krallen',
		'Talons-1000' : '1000 Krallen',
		'Totems' : 'Todes-Totems',
		'Totems-100' : '100 Todes-Totems',
		'Totems-500' : '500 Todes-Totems',
		'Totems-1000' : '1000 Todes-Totems',
		'Scales' : 'Sumpfschuppen', // Jawz
		'Scales-100' : '100 Sumpfschuppen', // Jawz
		'Scales-500' : '500 Sumpfschuppen', // Jawz
		'Scales-1000' : '1000 Sumpfschuppen', // Jawz
		'Zzz' : 'Zzz'
	};
	break;
	/*******************************************************************************
		Español (by Phantomas)
	*******************************************************************************/
case 'es':
	TRANSLATION_ARRAY = {
		'</B> and <B>' : '</B> y <B>',
		'<B>Attacker\'s move turn</B>' : '<B>Turno de movimiento del Atacante</B>',
		'<B>Attacker\'s attack turn</B>' : '<B>Turno de ataque del Atacante</B>',
		'<b>Bad request!</b>' : '<b>Solicitud incorrecta!</b>',
		'<B>Defender\'s move turn</B>' : '<B>Turno de movimiento del Defensor</B>',
		'<B>Defender\'s attack turn</B>' : '<B>Turno de ataque del Defensor</B>',
		'<b>Rate Limit Exceeded</b>, too many requests!' : '<b>Excedió el límite de las solicitudes</b>, demasiado muchas solicitudes enviadas!',
		'About KabaListics' : 'Sobre KabaListics',
		'above the first value' : 'encima del primer valor',
		'Action Log' : 'Reporte de Acciones',
		'Actions' : 'Acciones',
		'Activate Attacks Logs' : 'Activar Registro de Ataques',
		'Alerts log' : 'Log alertas',
		'Alives' : 'Sobrevivientes',
		'All alliances' : 'Todas la alianzas',
		'All players' : 'Todos los Jugadores',
		'All types' : 'Todos',
		'Alliance features' : 'Informacion de Alianzas',
		'Alliances list retrieved' : 'Lista de las alianzas obtenido',
		'Alliance members list retrieved' : 'Listado de Miembros de la alianza',
		'Alliance messages' : 'Mensajes de Alianza',
		'and' : 'y',
		'Another march request is pending' : 'Otra solicitud de marcha encuentra pendiente',
		'Are you sure you want to delete All Permanent Data' : 'Está seguro que desea eliminar todos los datos permanentes',
		'Arrival time' : 'Tiempo de Arrivo',
		'at' : 'a',
		' at ' : ' a ',
		' at range' : ' à distancia',
		'Attack sent to' : 'Ataque enviado a',
		'Attack One Target in Multiple waves' : 'Ataque en Olas Multiple',
		'Attacker' : 'Atacante',
		'Attacking' : 'Atacando',
		'Attacks Configuration' : 'Configuración de Ataques',
		'Attacks Stats' : 'Estadísticas de Ataques',
		'Attacks' : 'Ataques',
		'attempted' : 'intentado',
		'attempt for' : 'intento de',
		'Auto harvest resources from outposts every' : 'Auto-Recolectar recursos de Avanzadas cada',
		'Auto refresh info tab data every' : 'Auto-Refrescar de datos de la info tab cada',
		'Automatically' : 'Automáticamente',
		'Automatically recall transport 1 minute before delivery' : 'Regresar el envio 1 minuto despues de ser enviado',
		'available.' : 'disponible.',
		'Available troops' : 'Tropas disponibles',
		'Awaiting task completion notification' : 'En espera de la notificación de finalización de la tarea',
		'Back at the same time' : 'Volver al mismo tiempo',
		'Backup' : 'Salvaguardar',
		'Battle' : 'Simul',
		'Battle calculator' : 'Simulacion de Batalla',
		'Battle forces' : 'Fuerzas de Batalla',
		'Battle log' : 'Log Simulacion',
		'Battle lost !!' : 'Batalla Perdida !!',
		'Battle mechanics' : 'Mecanica de Batallas',
		'Battle won !!' : 'Batalla Ganada !!',
		'blue_energy' : 'Energy azul',
		'Bookmark' : 'Marcador',
		'Bookmark saved' : 'Marcador guardado',
		'Bookmarks' : 'Marcadores',
		'Bookmarks Configuration' : 'Configuración de marcadores',
		'Building' : 'Construccion',
		'Busy' : 'Ocupado',
		'by' : 'por',
		'By distance ascending' : 'Para distancia arriba',
		'By distance descending' : 'Para distancia abajo',
		'Cache data' : 'Datos de la caché',
		'Calculate' : 'Inicie la simulación',
		'Camps/wilds attack reports' : 'Reportes de ataques a Paramos',
		'Capital data' : 'Datos de la capital',
		'Capital data successfully fetched' : 'Datos de la capital a buscar con éxito',
		'Check sentinel reports every ' : 'Verificar reportes de sentinela cada ',
		'Check the following great dragons to exclude them from being sent' : 'Marque la casilla de dragón para evitar el envío de ellos para atacar',
		'Check to use UTC time instead of local time' : 'Marque la casilla para utilizar la hora UTC en lugar de la hora local',
		'Claim' : 'Reclamo',
		'Claimed' : 'Reclamada',
		'Claiming quest' : 'Reclamar de la misión',
		'Clear' : 'Borrar',
		'Clear all' : 'Borrar Todo',
		'Clear all data' : 'Borrar Todo',
		'Clear last attack on all maps' : 'Borrar todos los registros de últimos ataques',
		'Clear last attack on current map' : 'Borrar registro de últimos ataques actuales',
		'Clear local storage (internet cache)' : 'Borrar los datos permanentes (caché de Internet)',
		'Clear log' : 'Borrar Log',
		'Clear Stats' : 'Borrar Estadísticas',
		'Collected resources at outpost' : 'Recursos recolectados de avanzada',
		'Completing...' : 'Finalizando...',
		'Completion errors' : 'Error de finalización',
		'Config' : 'Config',
		'Confirmation' : 'Confirmación',
		'Console Log' : 'Registros de Consola',
		'Console' : 'Consola',
		'Coordinates' : 'Coordenadas',
		'Coords' : 'Coords',
//		'Copy troops reported by the sentinel to the battle calculator' : '?????',
		' damages taken' : ' daños sufridos',
		' damages to ' : ' daños à ',
		'data' : 'datos',
		'data successfully fetched' : 'datos con éxito a buscar',
		'Date range' : 'Rango de tiempo',
		'Days' : 'Dias',
		' deal ' : ' daño ',
		'Defender' : 'Defensor',
		'Defending' : 'En defensa',
		'Defense force modified' : 'Fuerza de Defensa modificado',
		'Defense strategy' : 'Estrategia defensiva',
		'Delay before script startup' : 'Retraso inicial antes arranque del script',
		'Delay Between Attacks' : 'Tiempo de retraso entre ataques',
		'Delay Between Transports' : 'Retardo entre transporta',
		'delayed due to' : 'retrasado,',
		'delayed due to march limit reached' : 'retrasado, alcanzó el número máximo de marchas',
		'delayed due to muster point full' : 'retrasado, punto de encuentro completo',
		'delayed due to no available generals' : 'retrasado, no hay geneal disponible',
		'delayed due to no available Great Dragon' : 'retrasado, Gran Dragon no disponible',
		'delayed due to pending march request' : 'retrasado, otra solicitud de marcha encuentra pendiente',
		'delayed due to insufficient troops' : 'retrasado debido a las tropas insuficientes',
		'Delete now' : 'Borrar',
		'Delete Battle Reports' : 'Borrar reportes de batalla',
		'Delete messages' : 'Borrar Mensajes',
		'Delete messages of this type' : 'Borrar mensajes de este tipo',
		'Delete spy reports' : 'Suprimir reportes de Espias',
		'Detailed search' : 'Búsqueda detallada',
		'Disable <B>Alliance</B> tab' : 'Desactivar <B>Alianza</B>',
		'Disable <B>Battle</B> tab' : 'Desactivar <B>Simulador</B>',
		'Disable <B>Bookmarks</B> tab' : 'Desactivar <B>Marcadores</B>',
		'Disable <B>Multi</B> tab' : 'Desactivar <B>Multi</B>',
		'Disable <B>Search</B> tab' : 'Desactivar <B>Busqueda</B>',
		'Disable <B>Spy</B> tab' : 'Desactivar <B>Espias</B>',
		'Disable <B>Wall</B> tab' : 'Desactivar <B>Muralla</B>',
		'Disable <B>Wave</B> tab' : 'Desactivar <B>Oleadas</B>',
		'Disable <B>Log</B> tab' : 'Desactivar <B>Log</B>',
		'Disabled' : 'Desactivado',
		'Display official background image' : 'Visualización de la imagen de fondo oficial',
		'Dist' : 'Dist',
		'Distance must be between' : 'La distancia debe estar entre',
		'Distance' : 'Distancia',
		'Dragon healing' : 'Curando Dragon',
		'Dragons' : 'Dragones',
		'Do not show alerts obsolete since' : 'No mostrar alertas obsoletas desde',
//		'Do you want to delete existing Permanent Data' : '?????',
		'Do you want to save in Permanent Data the current script setting' : 'Quieres guardar la configuración actual del script en los datos permanentes',
		'Do you want to save Map Data in local file' : 'Quieres guardar los datos del mapa en un archivo local',
		'Do you want to save Permanent Data in local file' : 'Quieres guardar los datos permanentes en un archivo local',
		'Dutch' : 'Holandés',
		'Edit' : 'Editar',
		'Edit bookmark' : 'Editar marcador',
		'Edit defense' : 'Modificar defensa',
		'Enable' : 'Activar',
//		'Enable cheat (all troops in all outposts, transport of blue energy)' : 'Activar los trucos (todas las tropas en todos los puestos de avanzada, el transporte de la energía azul)',
		'Enable transport of blue energy' : 'Activar el transporte de la energía azul',
		'Enable use of speed-ups in attacks waves' : 'Permitir el uso de aceleraciones de las ondas de ataque',
		'Enable verbose logging' : 'Activar el registro detallado',
		'Enable window drag' : 'Permiten arrastrar la ventana',
		'Enable the sentinel tower' : 'Activar Torre Sentinela',
		'Enabled' : 'Activado',
		'End' : 'Finalizar',
		'English' : 'Inglés',
		'Ennemy General' : 'General Enemigo',
		'Ennemy research levels' : 'Niveles de investigacion del enemigo',
		'Enter -1 as troop quantity to use the maximum available' : 'Introduzca la cantidad en -1 para utilizar la cantidad máxima disponible de las tropas',
		'Error' : 'Error',
		'Error while retrieving the list of members' : 'Error al buscar Miembro',
		'Error while setting defense choice' : 'Error al actualizar la elección de la defensa',
		'Evol' : 'Evol',
		'Except' : 'Exepto',
		'Exception' : 'Exepto',
		'failed' : 'fracasado',
		'failed and returned error' : 'fracasado y devolvió el error',
		'Fast search' : 'Búsqueda rápida',
		'Features' : 'Funcionalidades',
		'Fetching' : 'Obtención',
		'Fetching Capital data' : 'Obtención de datos de la capital',
		'Fetching Manifest' : 'Obtención de manifiesto',
		'Fetching Outpost #' : 'Obtención de Outpost #',
		'Fetching Seed' : 'Obtención de datos del jugador',
		'Fetching Translation matrix' : 'Obtención de la matriz de Traducción',
		'Fire' : 'Fuego',
		'fire_dragon outpost' : 'Ciudad del Fuego',
		'First value must be between' : 'El primer valor debe ser de',
		'Flash game Auto refresh every' : 'Actualización automática del juego flash cada',
//		'Foes' : '?????',
		'for' : 'para',
		'Force saving current script settings' : 'Fuerza de guardar la configuración actual del script',
		'Forum link' : 'Forum link',
		'French' : 'Francés',
		'Game messages' : 'Mensajes de Juego',
		'Game Options' : 'Opciones del Juego',
		'GD' : 'GD',
		'Generals' : 'Generales',
		'German' : 'Alemán',
		'Getting basic data...' : 'Obtención de datos básicos',
		'Getting cities data...' : 'Obtención de datos de las ciudades',
		'Getting game data...' : 'Obtención de datos del juego',
		'Got' : 'Encontrado',
		'Great dragons' : 'Dragones Elementales',
		'Help/About' : 'Ayuda/Acerca',
		'Hide spy alerts' : 'Esconder alertas de espias',
		'Hiding' : 'Santuario',
		'History' : 'Historia',
		'h' : 'h',
		'Hours' : 'Horas',
		'ice_dragon outpost' : 'Ciudad del Hielo',
		'Ice' : 'Hielo',
		'Idle' : 'Inactivo',
		'Idle pop' : 'Población inactiva',
		'In city' : 'En la ciudad',
		'In march' : 'En movimiento',
		' in melee' : ' cuerpo a cuerpo',
		'in progress' : 'en progreso',
		'Include Great Dragon' : 'Enviar Gran Dragon en el Ataque',
		'Info' : 'Info',
		'Initialization' : 'inicialización',
		'Initializing...' : 'inicializar...',
		'Initializing map, auto-collect, ...' : 'Inicializar el mapa, la recopilación automática, ...',
		'Invalid date From' : 'Formato de fecha de inicio invalido',
		'Invalid date To' : 'Formato de fecha de finalizacion invalido',
		'Invalid date range' : 'Rango de datos invalido',
		'Invalid delays' : 'Intervalo de retraso invalido',
		'Invalid number of troops' : 'Cantidad de tropas invalida',
		'Inventory' : 'Inventario',
		'Joined' : 'Registrado',
		'Keep battle reports of attacks from other players' : 'Guardar los reportes de ataque de otros jugadores al mio',
		'Keep battle reports of my attacks on other players' : 'Guardas los reportes de ataques mios hacia otro jugador',
		' (kill ' : ' (asesinado ',
		'Killed' : 'Asesinados',
		'Last attack' : 'Ultimo ataque',
		'leader' : 'Lider',
		'life lost' : 'vida perdida',
		'Loaded' : 'Script cargado',
		'Loading basic data' : 'Carga de datos básicos',
		'Locale data was Successfully requested from the server' : 'Solicitud para los datos de traducción ha sido procesada correctamente por el servidor',
		'Logs' : 'Log',
		'Log' : 'Log',
		'lord' : 'Señor',
		'Manifest not available, using defaults' : 'Manifiesto no disponible, utilizando los valores predeterminados',
		'Manifest Successfully initialized' : 'Manifiesto inicializado correctamente',
		'Manifest was Successfully requested from the server' : 'Solicitud para el Manifiesto ha sido procesada correctamente por el servidor',
		'Manual attack sent to' : 'Ataque manual enviado a',
		'March limit reached' : 'Alcanzó el número máximo de marchas',
		'Max level' : 'Nivel max',
		'Map Search' : 'Buscando en mapa',
		'Maximize resource to transport according to max load' : 'Maximizar los recursos para el transporte de acuerdo a la carga máxima disponible',
		'Maximum level reached' : 'Nivel máximo alcanzado',
		'Maximum simultaneous marches' : 'Maximo de marchas simultaneas',
		'Maximum training queues possible per city, according to available resources' : 'Máximas posible de formación por la ciudad, según los recursos disponibles',
		'Members' : 'Miembros',
		'Members list ' : 'Listado de miembros ',
		'Message(s) deleted' : 'Mensajes Borrados',
		'Message(s) deletion in progress' : 'Borrando mensajes',
		'miles' : 'millas',
		'Min level' : 'Nivel min',
		'Minutes' : 'Minutos',
		' move to ' : ' mover a ',
		'Multi' : 'Multi',
		'Muster Point Full' : 'Punto de encuentro completo',
		'Need' : 'Req',
//		'New version has been installed...' : '?????...',
		'No Generals Available' : 'No hay geneal disponible',
		'No great dragon available' : 'Gran Dragon no disponible',
		'no max' : 'sin limite',
		'No new version of' : 'No hay nueva versión de',
		'No resources to transport defined' : 'no se definieron recursos a transportar',
		'No Troops Defined' : 'No hay tropas definidas',
		'Not enough' : 'No hay suficiente',
		'Not ready' : 'No listo',
		'of' : 'de',
		'one attack' : 'un ataque',
		'one spy' : 'un espia',
		'Only one training queue per city' : 'Sólo una cola de formación por ciudad',
		'Options' : 'Opciones',
		'Opts' : 'Opcs',
		'Outpost 1' : 'Ciudad del Agua',
		'Outpost 2' : 'Ciudad de la Piedra',
		'Outpost 3' : 'Ciudad del Fuego',
		'Outpost 4' : 'Ciudad del Viento',
		'Outpost #1' : 'Ciudad #1',
		'Outpost #2' : 'Ciudad #2',
		'Outpost #3' : 'Ciudad #3',
		'Outpost #4' : 'Ciudad #4',
		'Outpost #5' : 'Ciudad #5',
		'Outpost #6' : 'Ciudad #6',
		'Outpost #7' : 'Ciudad #7',
		'Outpost damages' : 'Daños causados en avanzada',
		'overlord' : 'Señor Feudal',
		'Overview' : 'Resumen General',
		'Owner' : 'Propietario',
		'Play for' : 'Sonar para',
		'Play sound on incoming sentinel report' : 'Sonar alarma cuando entre reporte de sentinela',
		'Play sound on task completion' : 'Reproducir un sonido al final de la tarea',
		'Player cities' : 'Ciudades',
		'Player cities list' : 'Lista de Ciudades de jugador',
		'Player data was Successfully requested from the server' : 'Solicitud para los datos del jugador ha sido procesada correctamente por el servidor',
		'Player messages' : 'Mensajes de Jugador',
		'Player name' : 'Nombre del jugador',
		'Please wait...' : 'Gracias por su espere...',
		'Preset' : 'Preset',
		'Preset name' : 'nombre del preset',
		'Primary attack to ' : 'Primario ataque a ',
		'Putting build job in persistent data' : 'Guardando tareas de edificación en datos persistentes',
		'Putting research job in persistent data' : 'Guardando tareas de investigación en datos persistentes',
		'Putting resurrect job in persistent data' : 'Guardando tareas de resurrección en datos persistentes',
//		'Quantity' : '?????',
		'Quest' : 'Misión',
		'Quest claim Error' : 'Error de reclamación',
		'Rate Limit Exceeded because there were too many requests' : 'Excedió el límite de las solicitudes, demasiado muchas solicitudes se han enviadas',
		'Read page ' : 'Lectura de la pagina ',
		'Ready' : 'Listo',
		'Recipient' : 'Destinatario',
		'Refresh' : 'Refrescar',
		'Refresh list' : 'Refrescar lista',
		'Refresh map data' : 'Refrescar datos del mapa',
		'Refresh selection' : 'Actualizar la selección',
		'Reinforcement' : 'Refuerzos',
		'Reinforcement reports' : 'Reportes de refuerzosr',
		'Reinforcement sent to' : 'Refuerzos enviados a',
		'Reload' : 'Actualizar DOA',
		'Remove all' : 'Retirar todo',
		'Repairing' : 'Reparando',
		'Repeat every' : 'Repetir cada',
		'Researching' : 'Investigando',
		'Research Started' : 'Investigación comenzó',
		'Reset Stats' : 'Borrar Estadisticas',
		'Resources stock levels update failed' : 'Actualización de los niveles de inventario de los recursos ha fracasado',
		'Resources to transport' : 'Recursos a transportar',
		'Restore' : 'Restaurar',
		'Restore script settings from local file' : 'Restaurar la configuración del script de un archivo local',
		'Resurrection' : 'Resurrección',
		'Resurrect' : 'Resucitar',
		'Retry in' : 'Reintentando en',
		'Reviving' : 'Reviviendo',
		'Role' : 'Rol',
		'Rules' : 'Reglas',
		'Run Time' : 'Tiempo de ejecucion',
		'Safe Mode' : 'Modo Seguro',
		'Save Attaque' : 'Guardar Ataque',
		'Save current script settings in a local file' : 'Guardar la configuración actual del script en un archivo local',
		'Save current map data in a local file' : 'Guardar los datos del mapa actual en un archivo local', 
		'Save preset' : 'Guardar preset',
		'Scanning map' : 'Buscando el mapa sólo para las ciudades',
		'Scanning map for cities/wildernesses' : 'Buscando Ciudades y Paramos en el mapa',
		'Scanning map for wildernesses' : 'Buscando el mapa sólo para las paramos',
		'Script language' : 'Lenguaje del script',
		'Script Options' : 'Opciones del script',
		'Search coords' : 'Buscando coords',
		'Search for alliance list' : 'Buscador de la lista de las alianzas',
		'Search for alliance members' : 'Buscador de miembro de alianza',
		'Search max radius' : 'Radio Max. Busqueda',
		'Search Radius' : 'Radio de Busqueda',
		'Second value must be at least' : 'El segundo valor debe ser al menos',
		'Seconds' : 'Segundos',
		'seconds' : 'segundos',
		'Secondary attack to ' : 'Secundario ataque a ',
		'Seed Successfully initialized' : 'Datos del jugador inicializado correctamente',
		'Select at least one type of message or report to delete' : 'Seleccion por lo menos un tipo de mensaje o reporte para borrar',
		'Send reinforcement' : 'Enviar refuerzos',
		'Send transport' : 'Enviar Transportes',
		'Sending reinforcement' : 'Enviando refuerzos',
		'Sending transport' : 'Enviando Transporte',
		'Sentinel messages' : 'Alertas de Sentinela',
		'Sentinel tower' : 'Torre de Sentinela',
		'Set defense' : 'Activar defensa',
		'Set Def' : 'Activar Def',
		'Setting defense' : 'Actualización de la defensa',
		'several attacks' : 'muchos ataques',
		'several spies' : 'muchos espias',
		'Souls' : 'Almas',
		'Sound configuration' : 'Configuracion de Sonido',
		'Sound file' : 'Sonido',
		'Spanish' : 'Español',
		'Spectral' : 'Espectral',
		'SpectralDragonKeep' : 'Altar del Dragón',
		'spectral_dragon outpost' : 'Ruinas Espectrales',
		' spent. 2 min timeout (defense respawn)' : ' Demora de 1 minutos para restablecer defensa',
		' spent. 1 min timeout (defense respawn)' : ' Demora de 2 minutos para restablecer defensa',
		'Spies done' : 'Espionajes efectuados',
		'Spies number' : 'Numero de Espias',
		'Spy One Target' : 'Espias un objetivo',
		'Spy reports' : 'Reportes de espionaje',
		'Spy to ' : 'Espias enviados a ',
		'Stars' : 'Estrellas',
		'Start' : 'Iniciar',
		'Start Date' : 'Fecha de Inicio',
		'Starting...' : 'Puesta en marcha...',
		'Step' : 'Paso',
		'Stone' : 'Piedra',
		'stone_dragon outpost' : 'Ciudad de la Piedra',
		'Stop if any troops lost' : 'Detener si pierdo tropas',
		'succeeded' : 'se las arregló',
		'Successfully initialized' : 'Inicializado correctamente',
		'Successfully' : 'Exitosamente',
		'Summary' : 'Detalles',
		' survivals)' : ' sobrevivientes)',
//		'Swamp' : '?????',
		'swamp_dragon outpost' : '????? (swamp OP)',
		'Swedish' : 'Sueco',
		'switchDefense OK' : 'Cambio de la defensa OK',
		'Switch defense wall status' : 'Cambio en el estado de la muralla',
		'Switching defense' : 'Cambio de la defensa',
		'Tabs Options' : 'Opciones de Tabs',
		'Target' : 'Objetivo',
		'Targets' : 'Objetivos',
		'Task Completed' : 'Tarea Finalizada',
		'Tasks' : 'Tareas',
		'Terrain length set to ' : 'Largo de terreno en ',
//		'This should not clear map and alliance data.' : '?????.',
		'Time' : 'Duración',
		'to' : 'a',
		'To be refreshed' : 'a Refrescar',
		'Toggle Flash' : 'Flash toggle',
		'Too many troops for muster point level' : 'Demasiadas tropas para el Nivel actual del Punto de Encuentro',
		'Total souls' : 'Total almas',
		'Tower' : 'Torres',
		'Tower configuration' : 'Configuracion de Sentinela',
		'Training Configuration' : 'Configuracion de entrenamiento',
		'Translation Matrix Successfully initialized' : 'Traducción Matrix inicializado correctamente',
		'Transport reports' : 'Reportes de Transporte',
		'Transport sent to' : 'Transporte enviado a',
		'Troops Capped' : 'Las tropas tope',
		'Troops for Bookmarks Attack' : 'Tropas para atacar Marcador',
		'Troops for reinforcement' : 'Tropas para reforzar',
		'Troops for defense' : 'Tropas para defensa',
		'Troops for Primary Attack' : 'Tropas para ataque principal',
		'Troops for Secondary Attacks' : 'Tropas para ataque secundario',
		'Troops for transport' : 'Tropas para Transporte',
		'Troops for Wave Attack' : 'Tropas para ataque en olas',
		'Troops lost' : 'Tropas perdidas',
		'Troops max' : 'max. Tropas',
		'Troops statistics' : 'Estadísticas de las tropas',
		'Troops statistics for' : 'Estadísticas para',
		'Turkish' : 'Turco',
		'Turned Off' : 'Desactivado',
		'Unlimited' : 'Ilimitado',
		'Unowned only' : 'Libres solamente',
		'Updating City values' : 'Actualización de los datos de la ciudad',
		'Upgrading items' : 'Items especiales',
		'Use the Levels Tab to select attack areas' : 'Usar la solapa de Niveles para seleccionar el rango de ataque',
		'Version update' : 'Actualizar de la versión',
		'Wall defense setting' : 'Configuración de los defensores',
		'Wall management' : 'Gestión de la muralla',
		'Warning for ' : 'Esperando para ',
		'was returned with a status of' : 'ha devolvió el estado de',
		'Water' : 'Aqua',
		'water_dragon outpost' : 'Ciudad del Agua',
		'Wave attack to ' : 'Ataque en Oleada a ',
		'Wave' : 'Oleadas',
		'Wiki URL' : 'Wiki URL',
		'Wildernesses list' : 'Listado de Paramos',
		'Wind' : 'Viento',
		'wind_dragon outpost' : 'Ciudad del Viento',
		'Without alliance' : 'Sin alianza',
		'You are' : 'Tu eres',
		'Yoyo' : 'Yoyo',
		'Yoyo functionality' : 'Funcionalidad Yoyo',
		'ATrans' : 'Globo',		/* abbr Armored Transport */
		'Banshee' : 'Banshee',	/* abbr Wind Troop - Banshee */
		'BatDrg' : 'DrgComb',	/* abbr Battle Dragon */
		'Conscr' : 'Conscr',	/* abbr Conscript */
		'Fang' : 'Tritón',		/* abbr Aqua Troop */
//		'FGiant' : '?????',			/* abbr Frost giant */
		'FireDrg' : 'DrgFue',	/* abbr Fire Dragon */
		'FireM' : 'EFuego',		/* abbr Fire Mirror */
		'GrtDrg' : 'GrnDrg',	/* abbr Great Dragon */
		'Halbrd' : 'Alabar',	/* abbr Halberdsman */
		'IceDrg' : 'DrgHielo',	/* abbr Ice Dragon */
		'LBM' : 'Arcos',		/* abbr Longbowman */
		'Magma' : 'Magma',		/* abbr Fire Troop - Magmasaurus */
		'Mino' : 'Mino',		/* abbr Minotaur */
		'Ogre' : 'Ogro',		/* abbr Stone Troop - Ogre */
		'PackDrg' : 'DrgTrans',	/* abbr Pack dragons */
		'SpctDrg' : 'EspctDrg',	/* abbr Spectral Dragon */
		'SReaper' : 'Segador',	/* abbr Ice Troop - SoulReaper */
		'SSDrg' : 'DRapid',		/* abbr Swift Strike Dragon */
		'StnDrg' : 'DrgPie',	/* abbr Stone Dragon */
		'SwpDrg' : 'SerpMefi',	/* abbr Swamp Dragon */
		'Venom' : 'Venom',		/* abbr Swamp Troop - Venom */
		'WatDrg' : 'DrgAgua',	/* abbr Water Dragon */
		'WndDrg' : 'DraCef',	/* abbr Wind Dragon */
		// Missing Kabam translations
		'FireDragon' : 'Dragón del Fuego',
		// Objects
		'WaterEgg' : 'Huevo Agua',
		'StoneEgg' : 'Huevo Piedra',
		'FireEgg' : 'Huevo Fuego',
		'WindEgg' : 'Huevo Cefiro',
		'IceEgg' : 'Huevo Hielo',
		'SwampEgg' : 'Huevo Serpiente',
		'GD Body' : 'Armadura GD',
		'GD Helmet' : 'Casco GD',
		'GD Tail' : 'Protector GD',
		'GD Claw' : 'Garras GD',
		'WD Body' : 'Armadura DAg',
		'WD Helmet' : 'Casco DAg',
		'WD Tail' : 'Protector DAg',
		'WD Claw' : 'Garras DAg',
		'SD Body' : 'Armadura DdP',
		'SD Helmet' : 'Casco DdP',
		'SD Tail' : 'Protector DdP',
		'SD Claw' : 'Garras DdP',
		'FD Body' : 'Armadura DdF',
		'FD Helmet' : 'Casco DdF',
		'FD Tail' : 'Protector DdF',
		'FD Claw' : 'Garras DdF',
		'WiD Body' : 'Armadura DCe',
		'WiD Helmet' : 'Casco DCe',
		'WiD Tail' : 'Protector DCe',
		'WiD Claw' : 'Garras DCe',
		'IceD Body' : 'Armadura DHi',
		'IceD Helmet' : 'Casco DHi',
		'IceD Tail' : 'Protector DHi',
		'IceD Claw' : 'Garras DHi',
		'SpD Armor' : 'Armadura EspD',
		'SpD Body' : 'Armadura EspD',
		'SpD Helmet' : 'Casco EspD',
		'SpD Head' : 'Casco EspD',
		'SpD Tail' : 'Protector EspD',
		'SpD TailG' : 'Protector EspD',
		'SpD Claw' : 'Garras EspD',
		'SpD Talons' : 'Garras EspD',
		'SwD Body' : 'Armadura Serpiente',
		'SwD Helmet' : 'Casco Serpiente',
		'SwD Tail' : 'Protector Serpiente',
		'SwD Claw' : 'Garras Serpiente',
		'Respirators' : 'Respiradores',
		'Respirator-100' : '100 Respiradores',
		'Respirator-500' : '500 Respiradores',
		'Respirator-1000' : '1000 Respiradores',
		'Mandrakes' : 'Mandragoras',
		'Mandrakes-100' : '100 Mandragoras',
		'Mandrakes-500' : '500 Mandragoras',
		'Mandrakes-1000' : '1000 Mandragoras',
		'Runes' : 'Runas',
		'Runes-100' : '100 Runas',
		'Runes-500' : '500 Runas',
		'Runes-1000' : '1000 Runas',
		'Talons' : 'Garras',
		'Talons-100' : '100 Garras',
		'Talons-500' : '500 Garras',
		'Talons-1000' : '1000 Garras',
		'Totems' : 'Tótems',
		'Totems-100' : '100 Tótems',
		'Totems-500' : '500 Tótems',
		'Totems-1000' : '1000 Tótems',
		'Scales' : 'Escalas',
		'Scales-100' : '100 Escalas',
		'Scales-500' : '500 Escalas',
		'Scales-1000' : '1000 Escalas',
		'Zzz' : 'Zzz'
	};
	break;
	/**********************************************************************
	     Français  (by Jawz)
	***********************************************************************/
case 'fr':
	TRANSLATION_ARRAY = {
		'</B> and <B>' : '</B> et <B>',
		'<B>Attacker\'s move turn</B>' : '<B>Déplacement des unités offensives</B>',
		'<B>Attacker\'s attack turn</B>' : '<B>Attaque des unités offensives</B>',
		'<b>Bad request!</b>' : '<b>Mauvaise requête!</b>',
		'<B>Defender\'s move turn</B>' : '<B>Déplacement des unités défensives</B>',
		'<B>Defender\'s attack turn</B>' : '<B>Riposte des unités défensives</B>',
		'<b>Rate Limit Exceeded</b>, too many requests!' : '<b>Limitation des Requêtes Dépassée</b>, Trop de requêtes envoyées!',
		'About KabaListics' : 'A propos de KabaListics',
		'above the first value' : 'au-dessus de la première valeur',
		'Action Log' : 'Journal d\'évenements',
		'Actions' : 'Actions',
		'Activate Attacks Logs' : 'Activer journalisation des attaques',
		'Alerts log' : 'Log alertes',
		'Alives' : 'Survécu',
		'All alliances' : 'Toutes alliances',
		'All players' : 'Tous les joueurs',
		'All types' : 'Tous les types',
		'Alliance features' : 'Fonctionnalités Alliance',
		'Alliances list retrieved' : 'Liste des alliances récupérée',
		'Alliance members list retrieved' : 'Liste des membres de l\'alliance récupérée',
		'Alliance messages' : 'Message de l\'alliance',
		'and' : 'et',
		'Another march request is pending' : 'Une autre demande de marche est en attente',
		'Are you sure you want to delete All Permanent Data' : 'Etes-vous sûr de vouloir supprimer les données permanentes',
		'Arrival time' : 'Heure arrivée',
		'at' : 'à',
		' at ' : ' à ',
		' at range' : ' à distance',
		'Attack sent to' : 'Attaque envoyée sur',
		'Attack One Target in Multiple waves' : 'Attaquer une cible en Vagues successives',
		'Attacker' : 'Attaquant',
		'Attacking' : 'Attaque',
		'Attacks Configuration' : 'Configuration Attaques',
		'Attacks Stats' : 'Statistiques attaques',
		'Attacks' : 'Attaques',
		'attempted' : 'tenté',
		'attempt for' : 'tentative pour',
		'Auto harvest resources from outposts every' : 'Collecte automatique des outposts chaque',
		'Auto refresh info tab data every' : 'Rafraîchissement auto des données de l\'onglet info chaque',
		'Automatically' : 'Automatiquement',
		'Automatically recall transport 1 minute before delivery' : 'Rappel automatique du transport une minute avant livraison',
		'available.' : 'disponible.',
		'Available troops' : 'Troupes disponibles',
		'Awaiting task completion notification' : 'En attente de la notification de fin de tâche',
		'Back at the same time' : 'Retour au même instant',
		'Backup' : 'Backup',
		'Battle' : 'Simul',
		'Battle calculator' : 'Simulation bataille',
		'Battle forces' : 'Forces de bataille',
		'Battle log' : 'Log de bataille',
		'Battle lost !!' : 'Bataille perdue !!',
		'Battle mechanics' : 'Mécanique des bataille',
		'Battle won !!' : 'Bataille gagnée !!',
		'blue_energy' : 'Energie bleue',
		'Bookmark' : 'Signet',
		'Bookmarks' : 'Signets',
		'Bookmarks Configuration' : 'Configuration signets',
		'Bookmark saved' : 'Signet sauvegardé',
		'Building' : 'Construction',
		'Busy' : 'Occupé',
		'by' : 'par',
		'By distance ascending' : 'Par distance croissante',
		'By distance descending' : 'Par distance décroissante',
		'Cache data' : 'Données en cache',
		'Calculate' : 'Lancer simulation',
		'Camps/wilds attack reports' : 'Rapports d\'attaque de camps/ES',
		'Capital data' : 'Données de la ville principale',
		'Capital data successfully fetched' : 'Données de la ville principale chargée avec succès',
		'Check sentinel reports every ' : 'Contrôler les rapports de sentinelle chaque ',
		'Check the following great dragons to exclude them from being sent' : 'Cocher les grands dragons suivants pour éviter de les envoyer',
		'Check to use UTC time instead of local time' : 'Cocher pour afficher l\'heure UTC à la place de l\'heure locale',
		'Claim' : 'Réclame',
		'Claimed' : 'Réclamé',
		'Claiming quest' : 'Réclamation',
		'Clear' : 'Effacer',
		'Clear all' : 'Effacer tout',
		'Clear all data' : 'Réinitialiser données',
		'Clear last attack on all maps' : 'Réinitialiser toutes les cartes',
		'Clear last attack on current map' : 'Réinitialiser les attaques sur la carte',
		'Clear local storage (internet cache)' : 'Supprimer le stockage local (cache internet)',
		'Clear log' : 'Effacer log',
		'Clear Stats' : 'Effacer stats',
		'Collected resources at outpost' : 'Ressources collectées sur l\'avant-poste',
		'Completing...' : 'Finalisation...',
		'Completion errors' : 'Erreur lors de fin de tâche',
		'Config' : 'Config',
		'Confirmation' : 'Confirmation',
		'Console Log' : 'Log Console',
		'Console' : 'Console',
		'Coordinates' : 'Coordonnées',
		'Coords' : 'Coords',
		'Copy troops reported by the sentinel to the battle calculator' : 'Copie des troupes rapportée par la sentinelle dans le simulateur de bataille',
		' damages taken' : ' dommages subis',
		' damages to ' : ' dommages à ',
		'data' : 'données',
		'data successfully fetched' : 'données chargées avec succès',
		'Date range' : 'Plage de dates',
		'Days' : 'Jours',
		' deal ' : ' infligent ',
		'Defender' : 'Défenseur',
		'Defending' : 'En défense',
		'Defense force modified' : 'Choix des défenseurs modifié',
		'Defense strategy' : 'Stratégie défensive',
		'Delay before script startup' : 'Délai initial avant chargement du script',
		'Delay Between Attacks' : 'Délai entre les attaques',
		'Delay Between Transports' : 'Délai entre chaque transport',
		'delayed due to' : 'retardé,',
		'delayed due to march limit reached' : 'retardé, nombre maximum de marches atteint',
		'delayed due to muster point full' : 'retardé, caserne complète',
		'delayed due to no available generals' : 'retardé, aucun général disponible',
		'delayed due to no available Great Dragon' : 'retardé, aucun Grand Dragon disponible',
		'delayed due to pending march request' : 'retardé, une autre demande de marche est en attente',
		'delayed due to insufficient troops' : 'retardé, nombre de troupes insuffisant',
		'Delete now' : 'Supprimer',
		'Delete Battle Reports' : 'Supprimer les rapports de bataille',
		'Delete messages' : 'Suppression des messages',
		'Delete messages of this type' : 'Suppression des messages de ce type',
		'Delete spy reports' : 'Supprimer les rapports d\'espionnage',
		'Detailed search' : 'Recherche détaillée',
		'Disable <B>Alliance</B> tab' : 'Désactiver l\'onglet <B>Alliance</B>',
		'Disable <B>Battle</B> tab' : 'Désactiver l\'onglet <B>Simu</B>',
		'Disable <B>Bookmarks</B> tab' : 'Désactiver l\'onglet <B>Signets</B>',
		'Disable <B>Multi</B> tab' : 'Désactiver l\'onglet <B>Multi</B>',
		'Disable <B>Search</B> tab' : 'Désactiver l\'onglet <B>Carte</B>',
		'Disable <B>Spy</B> tab' : 'Désactiver l\'onglet <B>Espionnage</B>',
		'Disable <B>Wall</B> tab' : 'Désactiver l\'onglet <B>Rempart</B>',
		'Disable <B>Wave</B> tab' : 'Désactiver l\'onglet <B>Vague</B>',
		'Disable <B>Log</B> tab' : 'Désactiver l\'onglet <B>Log</B>',
		'Disabled' : 'Désactivé',
		'Display official background image' : 'Afficher l\'image officielle en arrière-plan',
		'Dist' : 'Dist',
		'Distance must be between' : 'La distance doit être comprise entre',
		'Distance' : 'Distance',
		'Dragon healing' : 'Dégâts causés au dragon',
		'Dragons' : 'Dragons',
		'Do not show alerts obsolete since' : 'Ne pas afficher les alertes obsolètes depuis',
		'Do you want to delete existing Permanent Data' : 'Voulez-vous supprimer les données permanentes',
		'Do you want to save in Permanent Data the current script setting' : 'Voulez-vous sauvegarder le paramétrage actuel du script dans les données permanentes',
		'Do you want to save Map Data in local file' : 'Voulez-vous sauvegarder les données de la carte dans un fichier local',
		'Do you want to save Permanent Data in local file' : 'Voulez-vous sauvegarder les données permanentes dans un fichier local',
		'Dutch' : 'Hollandais',
		'Edit' : 'Modifier',
		'Edit bookmark' : 'Modifier signet',
		'Edit defense' : 'Modifier défenseurs',
		'Enable' : 'Activer',
//		'Enable cheat (all troops in all outposts, transport of blue energy)' : 'Activer la triche (toutes troupes dans tous les outposts, transport de l\'énergie bleue)',
		'Enable transport of blue energy' : 'Activer le transport de l\'énergie bleue',
		'Enable use of speed-ups in attacks waves' : 'Activer l\'utilisation des accélérateurs de temps dans les vagues d\'attaque',
		'Enable verbose logging' : 'Activer la journalisation d\'évenements',
		'Enable window drag' : 'Autoriser le déplacement de la fenêtre',
		'Enable the sentinel tower' : 'Activer la sentinelle',
		'Enabled' : 'Activé',
		'End' : 'Fin',
		'English' : 'Anglais',
		'Ennemy General' : 'Général ennemi',
		'Ennemy research levels' : 'Niveaux de recherche de l\'ennemi',
		'Enter -1 as troop quantity to use the maximum available' : 'Saisir -1 comme quantité de troupes pour utiliser le maximum disponible',
		'Error' : 'Erreur',
		'Error while retrieving the list of members' : 'Erreur lors de la récuparation de la liste des membres',
		'Error while setting defense choice' : 'Erreur lors de la mise à jour du choix des défenseurs',
		'Evol' : 'Evol',
		'Except' : 'Sauf',
		'Exception' : 'Exception',
		'failed' : 'a échoué',
		'failed and returned error' : 'a échoué et a retourné l\'erreur',
		'Fast search' : 'Recherche rapide',
		'Features' : 'Fonctionalités',
		'Fetching' : 'Récupération',
		'Fetching Capital data' : 'Chargement des données de la ville principale',
		'Fetching Manifest' : 'Chargement du Manifeste',
		'Fetching Outpost #' : 'Chargement de l\'outpost n°',
		'Fetching Seed' : 'Chargement des données joueur',
		'Fetching Translation matrix' : 'Chargement de la matrice de traductions',
		'Fire' : 'Feu',
		'fire_dragon outpost' : 'Avant-poste de feu',
		'First value must be between' : 'La première valeur du délai doit être comprise entre',
		'Flash game Auto refresh every' : 'Auto-refraîchissement du jeu flash chaque',
		'Foes' : 'Ennemis',
		'for' : 'pour',
		'Force saving current script settings' : 'Forcer la sauvegarde du paramétrage actuel du script dans le stockage local',
		'Forum link' : 'Lien Forum',
		'French' : 'Français',
		'Game messages' : 'Message du jeu',
		'Game Options' : 'Options de jeu',
		'GD' : 'GD',
		'Generals' : 'Généraux',
		'German' : 'Allemand',
		'Getting basic data...' : 'Récupération des données de base',
		'Getting cities data...' : 'Récupération des données des cités',
		'Getting game data...' : 'Récupération des données de jeu',
		'Got' : 'Trouvé',
		'Great dragons' : 'Grands Dragons',
		'Help/About' : 'Aide/A propos',
		'Hide spy alerts' : 'Masquer les alertes d\'espionnage',
		'Hiding' : 'Sanctuaire',
		'History' : 'Historique',
		'h' : 'h',
		'Hours' : 'Heures',
		'ice_dragon outpost' : 'Avant-poste de glace',
		'Ice' : 'Glace',
		'Idle' : 'Inoccupé',
		'Idle pop' : 'Inactifs',
		'In city' : 'En ville',
		'In march' : 'En marche',
		' in melee' : ' en corps-à-corps',
		'in progress' : 'en cours',
		'Include Great Dragon' : 'Envoyer un grand dragon avec chaque attaque',
		'Info' : 'Info',
		'Initialization' : 'Initialisation',
		'Initializing...' : 'Initialisation...',
		'Initializing map, auto-collect, ...' : 'Initialisation de la carte, collecte automatique, ...',
		'Invalid date From' : 'Date "du" non valide',
		'Invalid date To' : 'Date "au" non valide',
		'Invalid date range' : 'Plage de dates invalide',
		'Invalid delays' : 'Délais invalides',
		'Invalid number of troops' : 'Nombre d\'unités invalide',
		'Inventory' : 'Inventaire',
		'Joined' : 'Adhésion',
		'Keep battle reports of attacks from other players' : 'Gardez les rapports de bataille des attaques d\'autres joueurs',
		'Keep battle reports of my attacks on other players' : 'Gardez les rapports de bataille de mes attaques contre d\'autres joueurs',
		' (kill ' : ' (tuent ',
		'Killed' : 'Tués',
		'Last attack' : 'Dernière attaque',
		'leader' : 'Leader',
		'life lost' : 'vie perdue',
		'Loaded' : 'Script chargé',
		'Loading basic data' : 'Chargement des données de base',
		'Locale data was Successfully requested from the server' : 'La requête pour les traductions a bien été traitée par le serveur',
		'Logs' : 'Logs',
		'Log' : 'Log',
		'lord' : 'Seigneur',
		'Manifest not available, using defaults' : 'Manifeste non disponible, utilisation des stats par défaut',
		'Manifest Successfully initialized' : 'Manifeste initialisé avec succès',
		'Manifest was Successfully requested from the server' : 'La requête pour le Manifeste a bien été traitée par le serveur',
		'Manual attack sent to' : 'Attaque manuelle envoyé sur',
		'March limit reached' : 'Nombre maximum de marches atteint',
		'Max level' : 'Niveau max',
		'Map Search' : 'Recherche sur la carte',
		'Maximize resource to transport according to max load' : 'Maximiser ressources en fonction de la charge maximale',
		'Maximum level reached' : 'Niveau maximum atteint',
		'Maximum simultaneous marches' : 'Nombre maximum de marches simultanées',
		'Maximum training queues possible per city, according to available resources' : 'Maximum de formations possibles par ville, en fonction des ressources disponibles',
		'Members' : 'Membres',
		'Members list ' : 'Liste des membres ',
		'Message(s) deleted' : 'Message(s) supprimé(s)',
		'Message(s) deletion in progress' : 'Message(s) en cours de suppression',
		'miles' : 'miles',
		'Min level' : 'Niveau min',
		'Minutes' : 'Minutes',
		' move to ' : ' vont à la position ',
		'Multi' : 'Multi',
		'Muster Point Full' : 'Caserne complète',
		'Need' : 'Requiert',
		'New version has been installed...' : 'Une nouvelle version a été installée...',
		'No Generals Available' : 'Aucun général disponible',
		'No great dragon available' : 'Aucun grand dragon disponible',
		'no max' : 'pas de limite',
		'No new version of' : 'Aucune nouvelle version de',
		'No resources to transport defined' : 'Aucune ressource à envoyer n\'est définie',
		'No Troops Defined' : 'Aucune troupe définie',
		'Not enough' : 'Pas assez de',
		'Not ready' : 'Non prêt',
		'of' : 'sur',
		'one attack' : 'une attaque',
		'one spy' : 'un espionnage',
		'Only one training queue per city' : 'Une seule formation de troupe par ville',
		'Options' : 'Options',
		'Opts' : 'Opts',
		'Outpost 1' : 'Avant-poste aquatique',
		'Outpost 2' : 'Avant-poste de pierre',
		'Outpost 3' : 'Avant-poste de feu',
		'Outpost 4' : 'Avant-poste éolien',
		'Outpost #1' : 'Outpost #1',
		'Outpost #2' : 'Outpost #2',
		'Outpost #3' : 'Outpost #3',
		'Outpost #4' : 'Outpost #4',
		'Outpost #5' : 'Outpost #5',
		'Outpost #6' : 'Outpost #6',
		'Outpost #7' : 'Outpost #7',
		'Outpost damages' : 'Dégâts causés au poste extérieur',
		'overlord' : 'Grand Seigneur',
		'Overview' : 'Vue d\'ensemble',
		'Owner' : 'Propriétaire',
		'Play for' : 'Jouer pendant',
		'Play sound on incoming sentinel report' : 'Jouer un son à l\'arrivée de nouvelles alertes sentinelle',
		'Play sound on task completion' : 'Jouer un son lors des fins de tâches',
		'Player cities' : 'Cités joueurs',
		'Player cities list' : 'Liste des cités des joueurs',
		'Player data was Successfully requested from the server' : 'La requête pour les données joueur a bien été traitée par le serveur',
		'Player messages' : 'Messages de joueurs',
		'Player name' : 'Nom joueur',
		'Please wait...' : 'Veuillez patienter...',
		'Preset' : 'Préréglage',
		'Preset name' : 'Nom du préréglage',
		'Primary attack to ' : 'Vague principale envoyée à ',
		'Putting build job in persistent data' : 'Sauvegarde de la construction dans les données persistantes',
		'Putting research job in persistent data' : 'Sauvegarde de la recherche dans les données persistantes',
		'Putting resurrect job in persistent data' : 'Sauvegarde de la résurrection dans les données persistantes',
		'Quantity' : 'Quantité',
		'Quest' : 'Mission',
		'Quest claim Error' : 'Erreur de réclamation',
		'Rate Limit Exceeded because there were too many requests' : 'Limitation des requêtes dépassée, trop de requêtes ont été envoyées',
		'Read page ' : 'Lecture de la page ',
		'Ready' : 'Prêt',
		'Recipient' : 'Destinataire',
		'Refresh' : 'Actualiser',
		'Refresh list' : 'Rafraîchir la liste',
		'Refresh map data' : 'Rafraîchir données carte',
		'Refresh selection' : 'Rafraîchir sélection',
		'Reinforcement' : 'Renforcement',
		'Reinforcement reports' : 'Rapports de renforcement',
		'Reinforcement sent to' : 'Renforcement envoyé à',
		'Reload' : 'Recharger DOA',
		'Remove all' : 'Enlever tout',
		'Repairing' : 'Réparation',
		'Repeat every' : 'Répéter chaque',
		'Research Started' : 'Recherche lancée',
		'Researching' : 'Recherche',
		'Reset Stats' : 'Réinitialiser Stats',
		'Resources stock levels update failed' : 'Mise à jour des niveaux de stock des ressources a échoué',
		'Resources to transport' : 'Ressources à envoyer',
		'Restore' : 'Restaurer',
		'Restore script settings from local file' : 'Restaurer le paramétrage du script à partir d\'un fichier texte local',
		'Resurrection' : 'Résurrection',
		'Resurrect' : 'Résurrection',
		'Retry in' : 'Nouvel essai dans',
		'Reviving' : 'Résurrection',
		'Role' : 'Rôle',
		'Rules' : 'Règles',
		'Run Time' : 'Temps d\'exécution',
		'Safe Mode' : 'Mode Sans échec',
		'Save Attaque' : 'Sauvegarder',
		'Save current map data in a local file' : 'Sauvegarder les données actuelles de la carte dans un fichier local',
		'Save current script settings in a local file' : 'Sauvegarder le paramétrage du script dans un fichier local',
		'Save preset' : 'Sauvegarder réglage',
		'Scanning map' : 'Balayage de la carte pour cités uniquement',
		'Scanning map for cities/wildernesses' : 'Balayage de la carte pour cités/ES',
		'Scanning map for wildernesses' : 'Balayage de la carte pour ES uniquement',
		'Script language' : 'Langage du script',
		'Script Options' : 'Options du script',
		'Search coords' : 'Coords recherche',
		'Search for alliance list' : 'Recherche de la liste des alliances',
		'Search for alliance members' : 'Recherche des membres de l\'alliance',
		'Search max radius' : 'Rayon rech. max',
		'Search Radius' : 'Rayon de balayage',
		'Second value must be at least' : 'La seconde valeur doit être au moins à ',
		'Seconds' : 'Secondes',
		'seconds' : 'secondes',
		'Secondary attack to ' : 'Vague secondaire envoyée à ',
		'Seed Successfully initialized' : 'Données joueur initialisée avec succès',
		'Select at least one type of message or report to delete' : 'Sélectionnez au moins un type de message ou de rapport à supprimer',
		'Send reinforcement' : 'Envoyer les renforts',
		'Send transport' : 'Envoyer le transport',
		'Sending reinforcement' : 'Envoi de renforts',
		'Sending transport' : 'Envoi de transport',
		'Sentinel messages' : 'Alertes sentinelle',
		'Sentinel tower' : 'Sentinelle / Tour de guet',
		'Set defense' : 'Actualiser défenseurs',
		'Set Def' : 'Màj déf',
		'Setting defense' : 'Mise à jour du choix des défenseurs',
		'several attacks' : 'plusieurs attaques',
		'several spies' : 'plusieurs espionnages',
		'Souls' : 'Âmes',
		'Sound configuration' : 'Configuration du son',
		'Sound file' : 'Fichier son',
		'Spanish' : 'Espagnol',
		'Spectral' : 'Spectral',
		'SpectralDragonKeep' : 'Autel du Dragon',
		'spectral_dragon outpost' : 'Ruines Spectrales',
		' spent. 2 min timeout (defense respawn)' : ' écoulé. Temporisation de 2 min (retour défense)',
		' spent. 1 min timeout (defense respawn)' : ' écoulé. Temporisation de 1 min (retour défense)',
		'Spies done' : 'Espionnages effectués',
		'Spies number' : 'Nombre d\'espions',
		'Spy One Target' : 'Espionner une cible en rafale',
		'Spy reports' : 'Rapports d\'espionnage',
		'Spy to ' : 'Espion(s) envoyé à ',
		'Stars' : 'Etoiles',
		'Start' : 'Début',
		'Start Date' : 'Date de début',
		'Starting...' : 'Démarrage...',
		'Step' : 'Etape',
		'Stone' : 'Pierre',
		'stone_dragon outpost' : 'Avant-poste de pierre',
		'Stop if any troops lost' : 'Désactiver en cas de pertes',
		'succeeded' : 'a réussi',
		'Successfully initialized' : 'initialisé avec succès',
		'Successfully' : 'Avec succès',
		'Summary' : 'Général',
		' survivals)' : ' survivants)',
		'Swamp' : 'Marais',
		'swamp_dragon outpost' : 'Temple Immergé',
		'Swedish' : 'Suédois',
		'switchDefense OK' : 'Switch défense OK',
		'Switch defense wall status' : 'Changement du statut du rempart',
		'Switching defense' : 'Changement de la défense',
		'Tabs Options' : 'Options des onglets',
		'Target' : 'Cible',
		'Targets' : 'Cibles',
		'Task Completed' : 'Tâche éffectuée',
		'Tasks' : 'Tâches',
		'Terrain length set to ' : 'Longueur du terrain initialisée à ',
		'This should not clear map and alliance data.' : 'Ceci n\'effacera pas les données carte et alliance.',
		'Time' : 'Durée',
		'to' : 'a',
		'To be refreshed' : 'A rafraîchir',
		'Toggle Flash' : 'Switcher flash',
		'Too many troops for muster point level' : 'Déploiement maximal atteint',
		'Total souls' : 'Âmes total',
		'Tower' : 'Guet',
		'Tower configuration' : 'Configuration sentinelle',
		'Training Configuration' : 'Configuration de la formation',
		'Translation Matrix Successfully initialized' : 'Matrice de traduction initialisée avec succès',
		'Transport reports' : 'Rapports de transport',
		'Transport sent to' : 'Transport envoyé à',
		'Troops Capped' : 'Troupes plafonnées',
		'Troops for Bookmarks Attack' : 'Troupes pour attaque du signet',
		'Troops for defense' : 'Défenseurs',
		'Troops for Primary Attack' : 'Troupes pour Attaque principale',
		'Troops for reinforcement' : 'Troupes pour le renforcement',
		'Troops for Secondary Attacks' : 'Troupes pour Attaques secondaires',
		'Troops for transport' : 'Troupes pour le transport',
		'Troops for Wave Attack' : 'Troupes pour Attaque en Vague',
		'Troops lost' : 'Troupes perdues',
		'Troops max' : 'Max. troupes',
		'Troops statistics' : 'Statistiques des troupes',
		'Troops statistics for' : 'Statistiques pour',
		'Turkish' : 'Turc',
		'Turned Off' : 'Désactivé',
		'Unlimited' : 'Illimité',
		'Unowned only' : 'Libres seulement',
		'Updating City values' : 'Mise à jour des données de la ville',
		'Upgrading items' : 'Objets d\'amélioration',
		'Use the Levels Tab to select attack areas' : 'Utilisez l\'onglet "Niveaux" pour sélectionner les cibles',
		'Version update' : 'Mise à jour',
		'Wall defense setting' : 'Paramétrage des défenseurs',
		'Wall management' : 'Gestion rempart',
		'Warning for ' : 'Alerte pour ',
		'was returned with a status of' : 'a retourné le statut',
		'Water' : 'Eau',
		'water_dragon outpost' : 'Avant-poste aquatique',
		'Wave attack to ' : 'Attaque en vagues sur ',
		'Wave' : 'Vague',
		'Wiki URL' : 'Lien Wiki',
		'Wildernesses list' : 'Liste des étendues sauvages',
		'Wind' : 'Vent',
		'wind_dragon outpost' : 'Avant-poste éolien',
		'Without alliance' : 'Sans alliance',
		'You are' : 'Vous êtes',
		'Yoyo' : 'Yoyo',
		'Yoyo functionality' : 'Fonctionalité Yoyo',
		'ATrans' : 'Ballons',		/* abbr Armored Transport */
		'Banshee' : 'Banshee',		/* abbr Wind Troop - Banshee */
		'BatDrg' : 'DG',			/* abbr Battle Dragon */
		'Conscr' : 'Conscr',		/* abbr Conscript */
		'Fang' : 'GueAqua',			/* abbr Aqua Troop */
		'FGiant' : 'GéantGla',		/* abbr Frost giant */
		'FireDrg' : 'DrgFeu',		/* abbr Fire Dragon */
		'FireM' : 'Miroir',			/* abbr Fire Mirror */
		'GrtDrg' : 'GrdDrag',		/* abbr Great Dragon */
		'Halbrd' : 'Halbrd',		/* abbr Halberdsman */
		'IceDrg' : 'DrgGlace',		/* abbr Ice Dragon */
		'LBM' : 'Archer',			/* abbr Longbowman */
		'Magma' : 'Magma',			/* abbr Fire Troop - Magmasaurus */
		'Mino' : 'Mino',			/* abbr Minotaur */
		'Ogre' : 'Ogre',			/* abbr Stone Troop - Ogre */
		'PackDrg' : 'DrgTrans',		/* abbr Pack dragons */
		'SpctDrg' : 'DrgSpct',		/* abbr Spectral Dragon */
		'SReaper' : 'Faucheurs',	/* abbr Ice Troop - SoulReaper */
		'SSDrg' : 'Rapide',			/* abbr Swift Strike Dragon */
		'StnDrg' : 'DrgPier',		/* abbr Stone Dragon */
		'SwpDrg' : 'SerpMeph',		/* abbr Swamp Dragon */
		'Venom' : 'Venom',			/* abbr Sumpfkröte */
		'WatDrg' : 'DrgAqua',		/* abbr Water Dragon */
		'WndDrg' : 'DrgEol',		/* abbr Wind Dragon */
		// Missing or wrong Kabam translations
		'FireDragon' : 'Dragon du Feu',
		'WindDragon' : 'Dragon Eolien',
		// Objects
		'WaterEgg' : 'Oeuf Aqua',
		'StoneEgg' : 'Oeuf Pierres',
		'FireEgg' : 'Oeuf Feu',
		'WindEgg' : 'Oeuf Eol',
		'IceEgg' : 'Oeuf Glace',
		'SwampEgg' : 'Oeuf Marais',
		'GD Body' : 'Armure GD',
		'GD Helmet' : 'Casque GD',
		'GD Tail' : 'Queue GD',
		'GD Claw' : 'Griffes GD',
		'WD Body' : 'Armure Aqua',
		'WD Helmet' : 'Casque Aqua',
		'WD Tail' : 'Queue Aqua',
		'WD Claw' : 'Griffes Aqua',
		'SD Body' : 'Armure DdP',
		'SD Helmet' : 'Casque DdP',
		'SD Tail' : 'Queue DdP',
		'SD Claw' : 'Griffes DdP',
		'FD Body' : 'Armure DdF',
		'FD Helmet' : 'Casque DdF',
		'FD Tail' : 'Queue DdF',
		'FD Claw' : 'Griffes DdF',
		'WiD Body' : 'Armure DEo',
		'WiD Helmet' : 'Casque DEo',
		'WiD Tail' : 'Queue DEo',
		'WiD Claw' : 'Griffes DEo',
		'IceD Body' : 'Armure DGla',
		'IceD Helmet' : 'Casque DGla',
		'IceD Tail' : 'Queue DGla',
		'IceD Claw' : 'Griffes DGla',
		'SpD Armor' : 'Armure Spect',
		'SpD Body' : 'Armure Spect',
		'SpD Helmet' : 'Casque Spect',
		'SpD Head' : 'Casque Spect',
		'SpD Tail' : 'Queue Spect',
		'SpD TailG' : 'Queue Spect',
		'SpD Claw' : 'Griffes Spect',
		'SpD Talons' : 'Griffes Spect',
		'SwD Body' : 'Armure Serpent',
		'SwD Helmet' : 'Casque Serpent',
		'SwD Tail' : 'Queue Serpent',
		'SwD Claw' : 'Griffes Serpent',
		'Respirators' : 'Recycleurs',
		'Respirator-100' : '100 Recycleurs',
		'Respirator-500' : '500 Recycleurs',
		'Respirator-1000' : '1000 Recycleurs',
		'Mandrakes' : 'Mandragores',
		'Mandrakes-100' : '100 Mandragores',
		'Mandrakes-500' : '500 Mandragores',
		'Mandrakes-1000' : '1000 Mandragores',
		'Runes' : 'Runes',
		'Runes-100' : '100 Runes',
		'Runes-500' : '500 Runes',
		'Runes-1000' : '1000 Runes',
		'Talons' : 'Serres',
		'Talons-100' : '100 Serres',
		'Talons-500' : '500 Serres',
		'Talons-1000' : '1000 Serres',
		'Totems' : 'Totems',
		'Totems-100' : '100 Totems',
		'Totems-500' : '500 Totems',
		'Totems-1000' : '1000 Totems',
		'Scales' : 'Ecailles',
		'Scales-100' : '100 Ecailles',
		'Scales-500' : '500 Ecailles',
		'Scales-1000' : '1000 Ecailles',
		'Zzz' : 'Zzz'
	};
	break;
	/*******************************************************************************
		Dutch  (by Kaas)
	*******************************************************************************/
case 'nl':
	TRANSLATION_ARRAY = {
		'</B> and <B>' : '</B> en <B>',
		'<B>Attacker\'s move turn</B>' : '<B>Beurt van de aanvaller</B>',
		'<B>Attacker\'s attack turn</B>' : '<B>Aanvalsbeurt van de aanvaller</B>',
		'<b>Bad request!</b>' : '<b>Ongeldige aanvraag</b>',
		'<B>Defender\'s move turn</B>' : '<B>Beurt van de verdediger</B>',
		'<B>Defender\'s attack turn</B>' : '<B>Aanvalsbeurt van de verdediger</B>',
		'<b>Rate Limit Exceeded</b>, too many requests!' : '<b>Limiet Serveraanvragen overschreden</b>',
		'About KabaListics' : 'Over KabaListics',
		'above the first value' : 'boven de eerste waarde',
		'Action Log' : 'Actie Log',
		'Actions' : 'Acties',
		'Activate Attacks Logs' : 'Aanvalslog activeren',
		'Alerts log' : 'Alarmlog',
		'Alives' : 'Overleefd',
		'All alliances' : 'Alle Allianties',
		'All players' : 'Alle spelers',
		'All types' : 'Alle types',
		'Alliance features' : 'Kenmerken van allianties ',
		'Alliances list retrieved' : 'Lijst allianties geladen',
		'Alliance members list retrieved' : 'Ledenlijst alliantie geladen',
		'Alliance messages' : 'Alliantieberichten',
		'and' : 'en',
		'Another march request is pending' : 'Een ander marsaanvraag is al onderweg',
		'Are you sure you want to delete All Permanent Data' : 'Ben je zeker dat je permanente gegevens wil verwijderen',
		'Arrival time' : 'Aankomsttijd',
		'at' : 'bij',
		' at ' : ' bij ',
		' at range' : ' in bereik',
		'Attack sent to' : 'Aanval verzonden naar',
		'Attack One Target in Multiple waves' : 'Aanval van één doel via meerdere Waves',
		'Attacker' : 'Aanvaller',
		'Attacking' : 'Bezig met aanval',
		'Attacks Configuration' : 'Aanvalconfiguratie',
		'Attacks Stats' : 'Aanvalstatistieken',
		'Attacks' : 'Aanvallen',
		'attempted' : 'geprobeerd',
		'attempt for' : 'Geprobeerd voor',
		'Auto harvest resources from outposts every' : 'Automatisch oogsten van buitenposten elke',
		'Auto refresh info tab data every' : 'Autoverversen van Infotab elke',
		'Automatically' : 'Automatisch',
		'Automatically recall transport 1 minute before delivery' : 'Automatisch terugroepen van transport 1 min voor levering',
		'available.' : 'beschikbaar.',
		'Available troops' : 'Beschikbare troepen',
		'Awaiting task completion notification' : 'In afwachtig van klaarmelding',
		'Back at the same time' : 'Terug op hetzelfde moment',
		'Backup' : 'Backup',
		'Battle' : 'Gevecht',
		'Battle calculator' : 'Gevechtscalculator',
		'Battle forces' : 'Strijdkrachten',
		'Battle log' : 'Gevechtslogboek',
		'Battle lost !!' : 'Strijd verloren !!',
		'Battle mechanics' : 'Strijdleer',
		'Battle won !!' : 'Strijd gewonnen !!',
		'blue_energy' : 'Blauwe Energie',
		'Bookmark' : 'Bookmark',
		'Bookmarks' : 'Bookmarks',
		'Bookmarks Configuration' : 'Bookmarks configuratie',
		'Bookmark saved' : 'Bookmarks weggeschreven',
		'Building' : 'Bezig met bouwen',
		'Busy' : 'Bezig',
		'by' : 'door',
		'By distance ascending' : 'Op afstand oplopend',
		'By distance descending' : 'Op afstand aflopend',
		'Cache data' : 'Cache gegevens',
		'Calculate' : 'Berekenen',
		'Camps/wilds attack reports' : 'Athropus strijdbericht',
		'Capital data' : 'Kerngegevens',
		'Capital data successfully fetched' : 'Kerngegevens geladen',
		'Check sentinel reports every ' : 'Controleren van helderziendebericht elke',
		'Check the following great dragons to exclude them from being sent' : 'Klik volgende draken zodat ze niet gebruikt worden',
		'Check to use UTC time instead of local time' : 'Klik om UTC tijd te gebruiken ipv. locale tijd',
		'Claim' : 'Vorderen',
		'Claimed' : 'Gevorderd',
		'Claiming quest' : 'Quest gevorderd',
		'Clear' : 'Verwijderen',
		'Clear all' : 'Alle verwijderen',
		'Clear all data' : 'Alle info verwijderen',
		'Clear last attack on all maps' : 'Laatste aanval op alle kaarten verwijderen',
		'Clear last attack on current map' : 'Laatste aanval op actuele kaart verwijderen',
		'Clear local storage (internet cache)' : 'Opschonen internet cache',
		'Clear log' : 'Log verwijderen',
		'Clear Stats' : 'Statistieken verwijderen',
		'Collected resources at outpost' : 'Verzamelde rijkdommen bij buitenpost',
		'Completing...' : 'Bezig met ...',
		'Completion errors' : 'Voltooiingsfouten',
		'Config' : 'Instelling',
		'Confirmation' : 'Bevestiging',
		'Console Log' : 'Console Log',
		'Console' : 'Console',
		'Coordinates' : 'Coordinaten',
		'Coords' : 'Coords',
//		'Copy troops reported by the sentinel to the battle calculator' : '?????',
		' damages taken' : ' Schade',
		' damages to ' : ' Schade aan ',
		'data' : 'gegevens',
		'data successfully fetched' : 'Het laden van gegevens is geslaagd ',
		'Date range' : 'Gegevensbereik',
		'Days' : 'Dagen',
		' deal ' : ' overeenkomst ',
		'Defender' : 'Verdediger',
		'Defending' : 'Verdedigen',
		'Defense force modified' : 'Verdedigingssterkte gewijzigd',
		'Defense strategy' : 'Verdeding strategie',
		'Delay before script startup' : 'Vertraging voordat script wordt opgestart',
		'Delay Between Attacks' : 'Vertraging tussen aanvalgolven',
		'Delay Between Transports' : 'Vertraging tussen transporten',
		'delayed due to' : 'vertraging veroorzaakt door,',
		'delayed due to march limit reached' : 'vertraging omdat limiet van aantal marsen is bereikt',
		'delayed due to muster point full' : 'vertraging omdat verzamelplaats vol is',
		'delayed due to no available generals' : 'vertraging omdat generaals niet beschikbaar zijn',
		'delayed due to no available Great Dragon' : 'vertraging omdat Grote Draak niet beschikbaar is',
		'delayed due to pending march request' : 'vertraging omdat er al een mars is begonnen',
		'delayed due to insufficient troops' : 'vertraging omdat er geen troepen beschikbaar zijn',
		'Delete now' : 'Nu verwijderen',
		'Delete Battle Reports' : 'Strijdrapporten verwijderen',
		'Delete messages' : 'Berichten verwijderen',
		'Delete messages of this type' : 'Berichten van dit type verwijderen',
		'Delete spy reports' : 'Spionberichten verwijderen',
		'Detailed search' : 'Uitgebreid zoeken',
		'Disable <B>Alliance</B> tab' : 'Uitschakelen <B>Alliantie</B> tab',
		'Disable <B>Battle</B> tab' : 'Uitschakelen <B>Strijd</B> tab',
		'Disable <B>Bookmarks</B> tab' : 'Uitschakelen <B>Bookmarks</B> tab',
		'Disable <B>Multi</B> tab' : 'Uitschakelen <B>Multi</B> tab',
		'Disable <B>Search</B> tab' : 'Uitschakelen <B>Zoek</B> tab',
		'Disable <B>Spy</B> tab' : 'Uitschakelen <B>Spion</B> tab',
		'Disable <B>Wall</B> tab' : 'Uitschakelen <B>Muur</B> tab',
		'Disable <B>Wave</B> tab' : 'Uitschakelen <B>Wave</B> tab',
		'Disable <B>Log</B> tab' : 'Uitschakelen <B>Log</B> tab',
		'Disabled' : 'Uitgeschakeld',
		'Display official background image' : 'Tonen van officiele achtergrond afbeelding',
		'Dist' : 'Afst',
		'Distance must be between' : 'Afstand moet zijn tussen',
		'Distance' : 'Afstand',
		'Dragon healing' : 'Draak genezing',
		'Dragons' : 'Draken',
		'Do not show alerts obsolete since' : 'Laat geen waarschuwing zien sinds',
//		'Do you want to delete existing Permanent Data' : '?????',
		'Do you want to save in Permanent Data the current script setting' : 'Wil je permanente gegevens in actuele script wegschrijven',
		'Do you want to save Map Data in local file' : 'Wil je kaartgegevens in lokaal bestand wegschrijven',
		'Do you want to save Permanent Data in local file' : 'Wil je permanente gegevens in lokaal bestand wegschrijven',
		'Dutch' : 'Nederlands',
		'Edit' : 'Wijzigen',
		'Edit bookmark' : 'Bookmark wijzigen',
		'Edit defense' : 'Verdediging wijzigen',
		'Enable' : 'Aanzetten',
//		'Enable cheat (all troops in all outposts, transport of blue energy)' : 'Cheat aanzetten (alle troepen in alle buitenposten, transport van blauwe energie)',
		'Enable transport of blue energy' : 'Aanzetten van transport van blauwe energie',
		'Enable use of speed-ups in attacks waves' : 'Aanzetten van het gebruik van speed-ups in aanvalWaves',
		'Enable verbose logging' : 'Aanzetten van log',
		'Enable window drag' : 'Aanzetten van slepen van venster',
		'Enable the sentinel tower' : 'Aanzetten van Helderziendetoren',
		'Enabled' : 'Aangezet',
		'End' : 'Einde',
		'English' : 'Engels',
		'Ennemy General' : 'Vijandige generaal',
		'Ennemy research levels' : 'Vijandig onderzoekniveaus',
		'Enter -1 as troop quantity to use the maximum available' : 'Vul -1 in als hoeveelheid troepen zodat max. aantal wordt gebruikt',
		'Error' : 'Fout',
		'Error while retrieving the list of members' : 'Fout bij het ophalen van ledenlijst',
		'Error while setting defense choice' : 'Fout bij het selecteren van verdediging',
		'Evol' : 'Evol',
		'Except' : 'Uitgezonderd',
		'Exception' : 'Uitzondering',
		'failed' : 'mislukt',
		'failed and returned error' : 'mislukt met foutmelding',		
		'Fast search' : 'Snel zoeken',
		'Features' : 'Functies',
		'Fetching' : 'Bezig met laden',
		'Fetching Capital data' : 'Bezig met ophalen van kerngegevens',
		'Fetching Manifest' : 'Bezig met ophalen van Manisfest',
		'Fetching Outpost #' : 'Bezig met ophalen van Buitenpost #',
		'Fetching Seed' : 'Bezig met ophalen van overige gegevens',		
		'Fetching Translation matrix' : 'Bezig met ophalen van vertaalmatrix',
		'Fire' : 'Vuur',
		'fire_dragon outpost' : 'Vuur Buitenpost',
		'First value must be between' : 'Eerste waarde moet liggen tussen',
		'Flash game Auto refresh every' : 'Verversen FlashGame elke',
//		'Foes' : '?????',
		'for' : 'voor',
		'Force saving current script settings' : 'Forceren van wegschrijven van scriptinstellingen',
		'Forum link' : 'Forum link',
		'French' : 'Frans',
		'Game messages' : 'Spelberichten',
		'Game Options' : 'Spelopties',
		'GD' : 'GD',
		'Generals' : 'Generaals',
		'German' : 'Duits',
		'Getting basic data...' : 'Bezig met ophalen van basisgegevens',
		'Getting cities data...' : 'Bezig met ophalen van stadgegevens',
		'Getting game data...' : 'Bezig met ophalen van spelgegevens',
		'Got' : 'Ontvangen',
		'Great Dragons' : 'Grote Draken',
		'Help/About' : 'Help/Over',
		'Hide spy alerts' : 'Verbergen spionwaarschuwingen',
		'Hiding' : 'Verbergen',
		'History' : 'Geschiedenis',
		'h' : 'u',
		'Hours' : 'Uren',
		'ice_dragon outpost' : 'IJsdraak buitenpost',
		'Ice' : 'IJs',
		'Idle' : 'Niet aktief',
		'Idle pop' : 'Werkloze Bevolking',
		'In city' : 'In stad',
		'In march' : 'Onderweg',
		' in melee' : ' bezig met strijd',
		'in progress' : 'bezig',
		'Include Great Dragon' : 'Grote Draak toevoegen',
		'Info' : 'Info',
		'Initialization' : 'Initialisatie',
		'Initializing...' : 'Bezig met Initialisatie',
		'Initializing map, auto-collect, ...' : 'Initialisatie kaart, Auto-inzamelen , ...',
		'Invalid date From' : 'Verkeerde datum van',
		'Invalid date To' : 'Verkeerde datum tot',
		'Invalid date range' : 'Verkeerde datumreeks',
		'Invalid delays' : 'Verkeerde vertraging',
		'Invalid number of troops' : 'Verkeerde aantal troepen',
		'Inventory' : 'Inventaris',
		'Joined' : 'Toegevoegd',
		'Keep battle reports of attacks from other players' : 'Behoud strijdrapporten van aanvallen van andere spelers',
		'Keep battle reports of my attacks on other players' : 'Behoud strijdrapporten van mijn aanvallen met andere spelers',
		' (kill ' : ' (dood ',
		'Killed' : 'Gedood',
		'Last attack' : 'Laatste aanval',
		'leader' : 'leider',
		'life lost' : 'Verloren levens',
		'Loaded' : 'Geladen',
		'Loading basic data' : 'Laden van algemene gegevens',
		'Locale data was Successfully requested from the server' : 'Lokale Data zijn succesvol geladen',		
		'Logs' : 'Logbestanden',
		'Log' : 'Log',
		'lord' : 'Meester',
		'Manifest not available, using defaults' : 'Manifest niet beschikbaar, gebruikt standaardgegevens',
		'Manifest Successfully initialized' : 'Manifest succesvol geinitialiseerd',
		'Manifest was Successfully requested from the server' : 'Manifest is succesvol van server opgevraagd',
		'Manual attack sent to' : 'Handmatige aanval gestuurd naar',
		'March limit reached' : 'Marsenlimiet bereikt',
		'Max level' : 'Max niveau',
		'Map Search' : 'Zoeken van kaarten',
		'Maximize resource to transport according to max load' : 'Maximale middelen voor transporten ivm maximale last',
		'Maximum level reached' : 'Maximale niveau bereikt',
		'Maximum simultaneous marches' : 'Maximaal aantal gelijktijde marsen',
		'Maximum training queues possible per city, according to available resources' : 'Maximaal aantal trainings per stad vergelekeb met beschikbare middelen',
		'Members' : 'Leden',
		'Members list ' : 'Ledenlijst ',
		'Message(s) deleted' : 'Bericht(en) verwijderd',
		'Message(s) deletion in progress' : 'Bericht(en)verwijdering aan de gang',
		'miles' : 'Mijlen',
		'Min level' : 'Min niveau',
		'Minutes' : 'Minuten',
		' move to ' : ' gaan naar ',
		'Multi' : 'Multi',
		'Muster Point Full' : 'Verzamelplaats is vol',
		'Need' : 'Nodig',
//		'New version has been installed...' : '?????...',
		'No Generals Available' : 'Geen generaals beschikbaar',
		'No great dragon available' : 'Geen Grote Draak beschikbaar',
		'no max' : 'Geen maximum',
		'No new version of' : 'Geen nieuwe versie van',
		'No resources to transport defined' : 'Geen middelen voor transport gedefinieerd',
		'No Troops Defined' : 'Geen troepen gedefinieerd',
		'Not enough' : 'Niet genoeg',
		'Not ready' : 'Niet klaar',
		'of' : 'van',
		'one attack' : 'één aanval',
		'one spy' : 'één spion',
		'Only one training queue per city' : 'Slechts één training per stad',
		'Options' : 'Opties',
		'Opts' : 'Opts',
		'Outpost 1' : 'Water buitenpost',
		'Outpost 2' : 'Steen Buitenpost',
		'Outpost 3' : 'Vuur Buitenpost',
		'Outpost 4' : 'Wind Buitenpost',
		'Outpost #1' : 'Buitenpost #1',
		'Outpost #2' : 'Buitenpost #2',
		'Outpost #3' : 'Buitenpost #3',
		'Outpost #4' : 'Buitenpost #4',
		'Outpost #5' : 'Buitenpost #5',
		'Outpost #6' : 'Buitenpost #6',
		'Outpost #7' : 'Buitenpost #7',
		'Outpost damages' : 'Schade aan buitenpost',
		'overlord' : 'Opperheer',
		'Overview' : 'Overzicht',
		'Owner' : 'Eigenaar',
		'Play for' : 'Spelen voor',
		'Play sound on incoming sentinel report' : 'Speel geluid bij in komend Helderziende rapport',
		'Play sound on task completion' : 'Speel geluid bij voltooiing van taal',
		'Player cities' : 'Steden van speler',
		'Player cities list' : 'Stedenlijst van speler',
		'Player data was Successfully requested from the server' : 'Spelergegevens succesvol van server aangevraagd',
		'Player messages' : 'Berichten van speler',
		'Player name' : 'Spelernaam',
		'Please wait...' : 'Even geduld...',
		'Preset' : 'Standaard instelling',
		'Preset name' : 'Standaard naam',
		'Primary attack to ' : 'Eerste aanval naar ',
		'Putting build job in persistent data' : 'Bezig met bouwtaak ',
		'Putting research job in persistent data' : 'Bezig met onderzoekstaak',
		'Putting resurrect job in persistent data' : 'Bezig met herrijzen van levens',
//		'Quantity' : '?????',
		'Quest' : 'Opdracht',
		'Quest claim Error' : 'Opdracht foutmelding',
		'Rate Limit Exceeded because there were too many requests' : 'Teveel aanvragen voor taken',
		'Read page ' : 'Laden van pagina ',
		'Ready' : 'Klaar',
		'Recipient' : 'Ontvanger',
		'Refresh' : 'Verversen',
		'Refresh list' : 'Te verversenlijst',
		'Refresh map data' : 'Verversen kaart',
		'Refresh selection' : 'Keuze verversen',
		'Reinforcement' : 'Versterking',
		'Reinforcement reports' : 'Versterkingsrapporten',
		'Reinforcement sent to' : 'Versterking zenden naar',
		'Reload' : 'Opnieuw laden',
		'Remove all' : 'Alles verwijderen',
		'Repairing' : 'Aan het repareren',
		'Repeat every' : 'Herhaal elke',
		'Research Started' : 'Onderzoek gestart',
		'Researching' : 'Aan het onderzoeken',
		'Reset Stats' : 'Reset statistieken',
		'Resources stock levels update failed' : 'Verversen van voorraadgegevens mislukt',
		'Resources to transport' : 'Middelen voor transport',
		'Restore' : 'Terugzetten',
		'Restore script settings from local file' : 'Terugzetten van scriptsettings uit bestand',
		'Resurrection' : 'Herrijzenis',
		'Resurrect' : 'Herrijzen',
		'Retry in' : 'Opnieuw proberen in',
		'Reviving' : 'Herleving',
		'Role' : 'Rol',
		'Rules' : 'Regels',
		'Run Time' : 'Looptijd',
		'Safe Mode' : 'Beveligingswijze',
		'Save Attaque' : 'Aanval opslaan',
		'Save current map data in a local file' : 'Wegschrijven van aktuele kaartgegevens in lokaal bestand',
		'Save current script settings in a local file' : 'Wegschrijven van aktuele scriptgegevens in lokaal bestand',
		'Save preset' : 'Wegschrijven standaardgegevens',
		'Scanning map' : 'Scannen van kaart op steden',
		'Scanning map for cities/wildernesses' : 'Scannen van kaart op steden/wildernissen',
		'Scanning map for wildernesses' : 'Scannen van kaart op wildernissen',
		'Script language' : 'Scripttaal',
		'Script Options' : 'Script Opties',
		'Search coords' : 'Zoeken van coördinaten',
		'Search for alliance list' : 'Zoeken naar allianties',
		'Search for alliance members' : 'Zoeken naar leden van allianties',
		'Search max radius' : 'Zoeken naar maximale straal',
		'Search Radius' : 'Zoeken naar straal',
		'Second value must be at least' : 'Twee waard moet minstens zijn',
		'Seconds' : 'Seconden',
		'seconds' : 'seconden',
		'Secondary attack to ' : 'Tweede aanval naar ',
		'Seed Successfully initialized' : 'Seed succesvol geinitialiseerd',
		'Select at least one type of message or report to delete' : 'Selecteren tenminste één bericht om te verwijderen',
		'Send reinforcement' : 'Versterking sturen',
		'Send transport' : 'Transport sturen',
		'Sending reinforcement' : 'Bezig met verzenden van versterking',
		'Sending transport' : 'Bezig met verzending van transport',
		'Sentinel messages' : 'Helderziende berichten',
		'Sentinel tower' : 'Helderziendetoren',
		'Set defense' : 'Zet verdediging',
		'Set Def' : 'Zet verd',
		'Setting defense' : 'Bezig met verdediging',
		'several attacks' : 'meerdere aanvallen',
		'several spies' : 'meerdere spionnen',
		'Souls' : 'Zielen',
		'Sound configuration' : 'Geluidsinstelling',
		'Sound file' : 'Geluidsbestand',
		'Spanish' : 'Spaans',
		'Spectral' : 'Spectral',
		'SpectralDragonKeep' : 'Sprookruïnedraak',
		'spectral_dragon outpost' : 'Spookruïne buitenpost',
		' spent. 1 min timeout (defense respawn)' : ' gebruik 1 min timeout (Verdediger Respawn)',
		' spent. 2 min timeout (defense respawn)' : ' gebruik 2 min timeout (Verdediger Respawn)',
		'Spies done' : 'Aantal bespionneringen',
		'Spies number' : 'Aantal spionnen',
		'Spy One Target' : 'Eén doel bespionneren',
		'Spy reports' : 'Spionberichten',
		'Spy to ' : 'Spion naar ',
		'Stars' : 'Sterren',
		'Start' : 'Begin',
		'Start Date' : 'Startdatum',
		'Starting...' : 'Beginnen...',
		'Step' : 'Stap',
		'Stone' : 'Steen',
		'stone_dragon outpost' : 'Steen Buitenpost',
		'Stop if any troops lost' : 'Stoppen in geval van troepverlies',
		'succeeded' : 'geslaagd',
		'Successfully initialized' : 'Inlezen geslaagd',
		'Successfully' : 'Geslaagd',
		'Summary' : 'Samenvatting',
		' survivals)' : ' overlevenden)',
//		'Swamp' : '?????',
		'swamp_dragon outpost' : 'Zwavelslang buitenpost',
		'Swedish' : 'Zweeds',
		'switchDefense OK' : 'Omschakelen verdediging OK',
		'Switch defense wall status' : 'Omschakelen muurverdediging status',
		'Switching defense' : 'Bezig met omschakelen verdediging',
		'Tabs Options' : 'Tab Opties',
		'Target' : 'Opdrachten',
		'Targets' : 'Opdrachten',
		'Task Completed' : 'Taak gereed',
		'Tasks' : 'Taken',
		'Terrain length set to ' : 'Gebiedsgrootte gezet tot ',
//		'This should not clear map and alliance data.' : '?????.',
		'Time' : 'Tijd',
		'to' : 'naar',
		'To be refreshed' : 'Verversen aanzetten',
		'Toggle Flash' : 'Flash aan-uitzetten',
		'Too many troops for muster point level' : 'Teveel troepen voor troepenverzamelplaats',
		'Total souls' : 'Totaalaantal zielen',
		'Tower' : 'Toren',
		'Tower configuration' : 'Torenconfiguratie',
		'Training Configuration' : 'Trainingconfiguratie',
		'Translation Matrix Successfully initialized' : 'Vertalingsmatrix met succes ingelezen', 
		'Transport reports' : 'Transportbericht',
		'Transport sent to' : 'Transport verzonden naar',
		'Troops Capped' : 'Troepenstop',
		'Troops for Bookmarks Attack' : 'Troepen voor Bookmark aanval',
		'Troops for defense' : 'Verdedigingstroepen',
		'Troops for Primary Attack' : 'Troepen voor eerste aanval',
		'Troops for reinforcement' : 'Troepen voor versterking',
		'Troops for Secondary Attacks' : 'Troepen voor tweede aanval',
		'Troops for transport' : 'Troepen voor transport',
		'Troops for Wave Attack' : 'Troepen voor Waveaanval',
		'Troops lost' : 'Verloren troepen',
		'Troops max' : 'Max. troepen',
		'Troops statistics' : 'Statistieken van troepen',
		'Troops statistics for' : 'Statistieken van troepen voor',
		'Turkish' : 'Turks',
		'Turned Off' : 'Uit',
		'Unlimited' : 'Onbeperkt',
		'Unowned only' : 'Alleen niet in bezit',
		'Updating City values' : 'Stadinstellingen verversen',
		'Upgrading items' : 'Verbeteringsobjecten',
		'Use the Levels Tab to select attack areas' : 'Gebruik de Level tab om aanvalsgebieden te kiezen',
		'Version update' : 'Versie update',
		'Wall defense setting' : 'Muurverdeding instelling',
		'Wall management' : 'Muurbeheer',
		'Warning for ' : 'Waarschuwing voor ',
		'was returned with a status of' : 'teruggekomen met status',
		'Water' :'Water',
		'water_dragon outpost' : 'Water buitenpost',
		'Wave attack to ' : 'Waveaanvaal naar',
		'Wave' : 'Wave',
		'Wiki URL' : 'Url van Wiki',
		'Wildernesses list' : 'Wildernissenlijst',
		'Wind' :'Wind',
		'wind_dragon outpost' : 'Wind Buitenpost',
		'Without alliance' : 'Zonder alliantie',
		'You are' : 'Je bent',
		'Yoyo' : 'Yoyo',
		'Yoyo functionality' : 'Yoyo functie',
		'ATrans' : 'GepTrn',	/* abbr Armored Transport */
		'Banshee' : 'Banshee',	/* abbr Wind Troop - Banshee */
		'BatDrg' : 'StrDrk',	/* abbr Battle Dragon */
		'Conscr' : 'Rekr',  	/* abbr Conscript */
		'Fang' : 'SnijVis',		/* abbr Aqua Troop */
//		'FGiant' : '?????',		/* abbr Frost giant */
		'FireDrg' : 'VuuDrk',	/* abbr Fire Dragon */
		'FireM' : 'VuuSpi', 	/* abbr Fire Mirror */
		'GrtDrg' : 'GD',		/* abbr Great Dragon */
		'Halbrd' : 'HBD',		/* abbr Halberdsman */
		'IceDrg' : 'IJSD',		/* abbr Ice Dragon */
		'LBM' : 'BooS',			/* abbr Longbowman */
		'Magma' : 'Pyro',		/* abbr Fire Troop - Magmasaurus */
		'Mino' : 'Mino',		/* abbr Minotaur */
		'Ogre' : 'Graniet',		/* abbr Stone Troop - Ogre */
		'PackDrg' : 'TrnDrK',	/* abbr Pack dragons */
		'SpctDrg' : 'SpDrK',	/* abbr Spectral Dragon */
		'SReaper' : 'ZRov',		/* abbr Ice Troop - SoulReaper */
		'SSDrg' : 'SneDrK',		/* abbr Swift Strike Dragon */
		'StnDrg' : 'SteDrK',	/* abbr Stone Dragon */
		'SwpDrg' : 'ZwSlg',		/* abbr Swamp Dragon */
		'Venom' : 'Gif',		/* abbr Swamp Troop - Venom */
		'WatDrg' : 'WatDrK',	/* abbr Water Dragon */
		'WndDrg' : 'WindDrK',	/* abbr Wind Dragon */
		// Missing or wrong Kabam translations
		'FireDragon' : 'Vuurdraak',
		'WindDragon' : 'Winddraak',
		// Objects
		'WaterEgg' : 'WaterEi',
		'StoneEgg' : 'SteenEi',
		'FireEgg' : 'VuurEi',
		'WindEgg' : 'WindEi',
		'IceEgg' : 'IJsEi',
		'SwampEgg' : 'ZwavelslangEi',
		'GD Body' : 'GD Lichaam',
		'GD Helmet' : 'GD Helm',
		'GD Tail' : 'GD Staart',
		'GD Claw' : 'GD Klauw',
		'WD Body' : 'WaD Lichaam',
		'WD Helmet' : 'WaD Helm',
		'WD Tail' : 'WaD Staart',
		'WD Claw' : 'WaD Klauw',
		'SD Body' : 'SD Lichaam',
		'SD Helmet' : 'SD Helm',
		'SD Tail' : 'Sd Staart',
		'SD Claw' : 'SD Klauw',
		'FD Body' : 'FD Lichaam',
		'FD Helmet' : 'FD Helm',
		'FD Tail' : 'FD Staart',
		'FD Claw' : 'FD Klauw',
		'WiD Body' : 'WD Lichaam',
		'WiD Helmet' : 'WD Helm',
		'WiD Tail' : 'WD Staart',
		'WiD Claw' : 'WD Klauw',
		'IceD Body' : 'IJSD Lichaam',
		'IceD Helmet' : 'IJSD Helm',
		'IceD Tail' : 'IJSD Staart',
		'IceD Claw' : 'IJSD Klauw',
		'SpD Armor' : 'SpD Lichaam',
		'SpD Body' : 'SpD Lichaam',
		'SpD Helmet' : 'SpD Helm',
		'SpD Head' : 'SpD Helm',
		'SpD Tail' : 'SpD Staart',
		'SpD TailG' : 'SpD Staart',
		'SpD Claw' : 'SpD Klauw',
		'SpD Talons' : 'SpD Klauw',
		'SwD Body' : 'ZwS Lichaam',
		'SwD Helmet' : 'ZwS Helm',
		'SwD Tail' : 'ZwS Staart',
		'SwD Claw' : 'ZwS Klauw',
		'Respirators' : 'Ademapparaat',
		'Respirator-100' : '100 Ademapparaat',
		'Respirator-500' : '500 Ademapparaat',
		'Respirator-1000' : '1000 Ademapparaat',
		'Mandrakes' : 'Toverwortels',
		'Mandrakes-100' : '100 Toverwortels',
		'Mandrakes-500' : '500 Toverwortels',
		'Mandrakes-1000' : '1000 Toverwortels',
		'Runes' : 'Runes',
		'Runes-100' : '100 Runes',
		'Runes-500' : '500 Runes',
		'Runes-1000' : '1000 Runes',
		'Talons' : 'Klauwen',
		'Talons-100' : '100 Klauwen',
		'Talons-500' : '500 Klauwen',
		'Talons-1000' : '1000 Klauwen',
		'Totems' : 'Totems',
		'Totems-100' : '100 Totems',
		'Totems-500' : '500 Totems',
		'Totems-1000' : '1000 Totems',
		'Scales' : 'Schubben',
		'Scales-100' : '100 Schubben',
		'Scales-500' : '500 Schubben',
		'Scales-1000' : '1000 Schubben',
		'Zzz' : 'Zzz'
	};
	break;
	/**********************************************************************
	     Turkish  (by RedSoldier)
	***********************************************************************/
case 'tr':
case 'tk':
	TRANSLATION_ARRAY = {
		'</B> and <B>' : '</B> ve <B>',
		'<B>Attacker\'s move turn</B>' : '<B>Saldırganın Hareket Sırası</B>',
		'<B>Attacker\'s attack turn</B>' : '<B>Saldırganın Saldırı Sırası</B>',
		'<b>Bad request!</b>' : '<b>Kötü Istek</b>',
		'<B>Defender\'s move turn</B>' : '<B>Savunanın Saldırı Sırası</B>',
		'<B>Defender\'s attack turn</B>' : '<B>Savunanın Hareket Sırası</B>',
		'<b>Rate Limit Exceeded</b>, too many requests!' : '<b>Limite Ulasildi</b>, Çok Fazla Istek Var!',
		'Action Log' : 'Faaliyet Logları',
		'Actions' : 'Faaliyet',
		'Activate Attacks Logs' : 'Saldırı Loglarını Aktifleştir',
		'Alerts log' : 'Alarm Logları',
		'Alives' : 'Hayatta Kalan',
		'All alliances' : 'Tüm İttifaklar',
		'All players' : 'Tüm Oyuncular',
		'All types' : 'Tüm Türler',
		'Alliance features' : 'İttifak Sekmesi',
		'Alliance members list retrieved' : 'İttifak Üyeleri Listesi',
		'Alliance messages' : 'İttifak Mesajları',
		'and' : 've',
		'Another march request is pending' : 'Bir Baska Yürüyüs Istegi Beklemede',
		'Arrival time' : 'Varış Süresi',
		'at' : 'Şurda',
		' at ' : ' Şurda ',
		' at range' : ' Şurda Mesafe',
		'Attack sent to' : 'Saldırı Yollandı :',
		'Attack One Target in Multiple waves' : 'Aynı Hedefe Çoklu Saldırı',
		'Attacker' : 'Saldırgan',
		'Attacking' : 'Saldırılıyor',
		'Attacks Configuration' : 'Saldırı Yapılandırması',
		'Attacks Stats' : 'Saldırı İstatisliği',
		'Attacks' : 'Saldırılar',
		'attempted' : 'Girişimi',
		'attempt for' : 'Girisim',
		'Auto harvest resources from outposts every' : 'Kasabalardaki Malzemeleri Topla Her :',
		'Auto refresh info tab data every' : 'İnfo Sekmesi İstatistiklerini Yenile Her :',
		'Automatically' : 'Otomatikman',
		'Automatically recall transport 1 minute before delivery' : 'Ele geçirdikten 1 Dakika Sonra geri Çağır',
		'Available troops' : 'Kullanılabilir Askerler',
		'Awaiting task completion notification' : 'Görev Tamamlama Bildirimi Bekleniyor',
		'Battle' : 'Simülatör',
		'Battle calculator' : 'Saldırı Simülatörü',
		'Battle forces' : 'Savaç Birliklerie',
		'Battle log' : 'Simülasyon Log.e',
		'Battle lost !!' : 'Savaş Kaybedildi !!',
		'Battle mechanics' : 'Savaç Tekniği',
		'Battle won !!' : 'Savaç Kazanıldı !!',
		'blue_energy' : 'Mavi Enerji',
		'Building' : 'İnşaat',
		'Busy' : 'Yoğun',
		'by' : 'By',
		'Calculate' : 'Hesapla',
		'Camps/wilds attack reports' : 'Kamp/Bozkır Saldırı Raporları',
		'Capital data' : 'Sermaye Veri',
		'Capital data successfully fetched' : 'Sermaye Veri Basariyla alindi',
		'Check sentinel reports every ' : 'Gözcü Raporlarını Kontrol Et Her :',
		'Check to use UTC time instead of local time' : 'UTC Saatini Yerel saat Olarak Kontrol Et',
		'Claim' : 'Al',
		'Claimed' : 'Alındı',
		'Claiming quest' : 'Görev Alınıyor',
		'Clear all data' : 'Tüm verileri Temizle',
		'Clear last attack on all maps' : 'Tüm haritalardaki Son Saldırıları Sil',
		'Clear last attack on current map' : 'Şuanki haritada Son Saldırıyı Sil',
		'Clear log' : 'Günlüğü Temizle',
		'Clear Stats' : 'İst. Temizle',
		'Collected resources at outpost' : 'Kasabadaki Malzeme Toplandı',
		'Completing...' : 'Tamamlaniyor...',
		'Config' : 'Yapılandırma',
		'Console Log' : 'Günlük Konsolu',
		'Console' : 'Konsol',
		'Coordinates' : 'Kordinat',
		'Coords' : 'Koord',
		' damages taken' : ' Alınan Zarar',
		' damages to ' : ' Verilen Zarar ',
		'data' : 'Veri',
		'data successfully fetched' : 'Veri Basariyla Alindi',
		'Date range' : 'Gün Aralığı',
		'Days' : 'Gün',
		' deal ' : ' Zarar ',
		'Defender' : 'Savunan',
		'Defending' : 'Savunuluyor',
		'Delay before script startup' : 'Scriptin Devreye girme Gecikmesi',
		'Delay Between Attacks' : 'Saldırılar Arası Süre farkı',
		'delayed due to' : 'Nedeniyle Gecikti',
		'delayed due to march limit reached' : 'Yürüyüs Limitne Ulasildigi Için Gecikti',
		'delayed due to muster point full' : 'Içtima Meydani Dolu Oldugu Için Geçikti',
		'delayed due to no available generals' : 'Kullanilabilir gEneral Olmadigi Için Gecikti',
		'delayed due to no available Great Dragon' : 'Kullanilabilir Ejderha Olmadigi Için gecikti',
		'delayed due to pending march request' : 'Baska Bir Yürüyüs Istegi nedeniyle Gecikti',
		'delayed due to insufficient troops' : 'Yetersiz brlik Nedeniyle Gecikti',
		'Delete now' : 'Şimdi Sil',
		'Delete Battle Reports' : 'Saldırı Raporlarını Sil',
		'Delete messages' : 'Mesajları Sil',
		'Delete messages of this type' : 'Bu Türdeki Mesajları Sil',
		'Delete spy reports' : 'Casus Raporlarını Sil',
		'Disable <B>Alliance</B> tab' : '<B>İttifakı</B> Devre Dışı Bırak',
		'Disable <B>Battle</B> tab' : '<B>Simülatörü</B> Devre Dışı Bırak',
		'Disable <B>Multi</B> tab' : '<B>Multi</B> Devre Dışı Bırak',
		'Disable <B>Search</B> tab' : '<B>Aramayı</B> Devre Dışı Bırak',
		'Disable <B>Spy</B> tab' : '<B>Casus Sekmesini</B> Devre Dışı Bırak',
		'Disable <B>Wave</B> tab' : '<B>Spami</B> Devre Dışı Bırak',
		'Disable <B>Log</B> tab' : '<B>Günlüğü</B> Devre Dışı Bırak',
		'Disabled' : 'Devredışı',
		'Dist' : 'Msfe',
		'Distance must be between' : 'Mesafe Bunların Arasında Olmalı :',
		'Distance' : 'Mesafe',
		'Dragon healing' : 'İyileştirme',
		'Dragons' : 'Ejderhalar',
		'Do not show alerts obsolete since' : 'Bundan Eski Alarmları Gösterme :',
		'Enable use of speed-ups in attacks waves' : 'Saldirilarda Kisaltmalari Aktive Et',
		'Enable verbose logging' : 'Ayrıntılı Günlüğü Etkinleştir',
		'Enable window drag' : 'Pencerenin Kaydırılmasını Etkinleştir',
		'Enable' : 'Etkin',
		'Enable the sentinel tower' : 'Gözcüyü Etkinleştir',
		'Enabled' : 'Etkinleştirildi',
		'End' : 'Son',
		'Ennemy General' : 'Düşman General',
		'Ennemy research levels' : 'Düşman Araştırma Seviyeleri',
		'Error' : 'Hata',
		'Error while retrieving the list of members' : 'Üyelerin Listesi Oluşturuurken Hata',
		'Evol' : 'Evol',
		'Exception' : 'İstisna',
		'failed' : 'Basarisiz',
		'failed and returned error' : 'Basarisiz ve Hata Döndü',
		'Features' : 'Özellikler',
		'Fetching' : 'Aliniyor',
		'Fetching Capital data' : 'Ana bilgi Aliniyor',
		'Fetching Manifest' : 'Menifest Aliniyor',
		'Fetching Outpost #' : 'Kasabalar Aliniyor',
		'Fetching Seed' : 'Seed Aliniyor',
		'Fire' : 'Ates',
		'First value must be between' : 'İlk Değer Bunların Arasında Olmalı',
		'Game messages' : 'Oyun Mesajları',
		'Game Options' : 'Oyun Ayarları',
		'Generals' : 'Generaller',
		'Getting basic data...' : 'Temel Veri Alınıyor',
		'Getting cities data...' : 'Şehir verileri Alınıyor',
		'Getting game data...' : 'Oyun Verileri Alınıyor',
		'Great dragons' : 'Ejderhalar',
		'Hide spy alerts' : 'Casus Alarmalrını Gizle',
		'Hiding' : 'Saklanılıyor',
		'History' : 'Geçmiş',
		'h' : 'saat',
		'Hours' : 'Saat',
		'Idle' : 'Boş',
		'Idle pop' : 'Boş Nüfus',
		' in melee' : ' in melee',
		'in progress' : 'İşlemde',
		'Include Great Dragon' : 'Büyük Dragon Yolla',
		'Info' : 'Info',
		'Initialization' : 'Yükleme',
		'Initializing...' : 'Yükleniyor...',
		'Initializing map, auto-collect, ...' : 'Harita,Oto Toplama,.... Yükleniyor...',
		'Invalid date From' : 'Geçersiz Başlangıç Tarihi',
		'Invalid date To' : 'Geçersiz Bitiş Tarihi',
		'Invalid date range' : 'Geçersiz Tarih Aralığı',
		'Invalid delays' : 'Geçersiz Gecikmeler',
		'Invalid number of troops' : 'Geçersiz asker Sayısı',
		'Inventory' : 'Ögeler',
		'Keep battle reports of attacks from other players' : 'Başkalarından Gelen Saldırıları Sakla',
		'Keep battle reports of my attacks on other players' : 'Benim Saldırdığım Raporları Sakla',
		' (kill ' : ' (Öldürülmüş ',
		'Killed' : 'Öldürüldü',
		'Last attack' : 'Son Saldırı',
		'leader' : 'Lider',
		'life lost' : 'Hayatını Kaybetti',
		'Loaded' : 'Yüklendi',
		'Loading basic data' : 'Temel Bilgi Yükleniyor',
		'Locale data was Successfully requested from the server' : 'Yerel Data Basariyla Dünyadan Istendi',
		'Logs' : 'Log',
		'Log' : 'Log',
		'lord' : 'Lord',
		'Manifest not available, using defaults' : 'Değiştirilmiş Kullanılamaz, Varsayılanları Kullan',
		'Manifest Successfully initialized' : 'Manifest basariyla Yüklendi',
		'Manifest was Successfully requested from the server' : 'Manifest Basariyla Dünyadan Istendi',
		'Manual attack sent to' : 'Manuel Saldırı Yollandı',
		'March limit reached' : 'Saldiri Limitine Ulasildi',
		'Max level' : 'max Level',
		'Map Search' : 'Harita Arama',
		'Maximum level reached' : 'Maks. Levele Ulasildi',
		'Maximum simultaneous marches' : 'Aynı Anda Grçklştirilcek Saldırı Sayısı',
		'Maximum training queues possible per city, according to available resources' : '?????',
		'Members' : 'Üyeler',
		'Members list ' : 'Üye Listesi ',
		'Message(s) deleted' : 'Mesaj(lar) Silindi',
		'Message(s) deletion in progress' : 'Mesaj(lar) Siliniyor',
		'miles' : 'Mil',
		'Min level' : 'min Level',
		'Minutes' : 'Dakika',
		' move to ' : ' Hareket Ediliyor ',
		'Multi' : 'Multi',
		'Muster Point Full' : 'İçtima Meydanı Full',
		'Need' : 'Gerekli',
		'No Generals Available' : 'Kullanılabilir General Yok',
		'No great dragon available' : 'Büyük Ejderha Kullanılamaz',
		'no max' : 'Limitli',
		'No resources to transport defined' : 'Nakliye İçin Malzeme Belirtilmedi',
		'No Troops Defined' : 'Asker Belirtilmemiş',
		'Not enough' : 'Yeterli değil',
		'Not ready' : 'Hazir Degil',
		'of' : ',',
		'one attack' : '1 Saldırı',
		'one spy' : '1 Casus',
		'Only one training queue per city' : 'Her SEhir Için 1 Sira Asker Egit',
		'Options' : 'Ayarlar',
		'Opts' : 'Ayrlr',
		'Outpost 1' : 'Su Kasabası',
		'Outpost 2' : 'Taş Kasabası',
		'Outpost 3' : 'Ateş Kasabası',
		'Outpost 4' : 'Rüzgar Kasabası',
		'Outpost damages' : 'Kasaba Hasarı',
		'overlord' : 'Feodal Beyi',
		'Overview' : 'Genel Bakış',
		'Owner' : 'Sahip',
		'Play for' : 'Bunun İçin Çal',
		'Play sound on incoming sentinel report' : 'Gözcü Alarmı Gelince Alarm Çal',
		'Player cities' : 'Oyuncu Şehirleri',
		'Player cities list' : 'Oyuncu Şehir Listesi',
		'Player data was Successfully requested from the server' : 'Oyuncu datasi Basariyla Dünyadan Istendi',
		'Player messages' : 'Oyuncu Mesajalrı',
		'Player name' : 'Oyuncu Adı',
		'Primary attack to ' : 'İlk saldırı : ',
		'Putting build job in persistent data' : 'Bina Görevlerinin Kalıcı Tutulması',
		'Putting research job in persistent data' : 'Araştırma Görevlerinin Kalıcı Tutulması',
		'Putting resurrect job in persistent data' : 'Diriltme Görevlerinin Kalici Tutulmasi',
		'Quest' : 'K.Seferi',
		'Quest claim Error' : 'K.Seferi Alım Hatası',
		'Rate Limit Exceeded because there were too many requests' : 'Rate Limiti Asildi Çünkü Çok Fazla Istek Var',
		'Read page ' : 'Sayfa Okuma ',
		'Ready' : 'Hazir',
		'Recipient' : 'Alıcı',
		'Refresh' : 'Yenile',
		'Refresh list' : 'Listeyi Yenile',
		'Refresh map data' : 'Harita Verilerini Yenile',
		'Reinforcement' : 'Tahkim',
		'Reinforcement reports' : 'Tahkim Raporları',
		'Reinforcement sent to' : 'Tahkim Buraya Yollandı :',
		'Reload' : 'Yenile(F5)',
		'Repairing' : 'Tamir',
		'Repeat every' : 'Tekrar Et Her',
		'Researching' : 'Araştırılıyor',
		'Reset Stats' : 'İst. Sıfırla',
		'Resources stock levels update failed' : 'Kaynak Stok Levelleri Güncellemesi Basarisiz',
		'Resources to transport' : 'Nakliye İçin Kaynaklar',
		'Resurrect' : 'Diriltmek',
		'Retry in' : 'Tekrar :',
		'Reviving' : 'Canlandiriliyor',
		'Role' : 'Rol',
		'Rules' : 'Kurallar',
		'Run Time' : 'Çalışma Süresi',
		'Safe Mode' : 'Güvenli Mod',
		'Save Attaque' : 'Saldırıyı Kaydet',
		'Scanning map' : 'Harita taranıyor',
		'Scanning map for cities/wildernesses' : 'Harita taranıyor',
		'Script Options' : 'Script Ayarları',
		'Search coords' : 'Arama Kordinatları',
		'Search for alliance members' : 'İttifak Üyeleri İçin Ara',
		'Search max radius' : 'Arama Maximum Uzaklığı',
		'Search Radius' : 'Arama Mesafesi',
		'Seconds' : 'Saniye',
		'seconds' : 'saniye',
		'Secondary attack to ' : '2 Saldırı Buraya: ',
		'Seed Successfully initialized' : 'Tohumlar Basariyla Yüklendi',
		'Select at least one type of message or report to delete' : 'Silinmesi İçin ir Mesaj Tipi Seç',
		'Send reinforcement' : 'Tahkimle',
		'Send transport' : 'Nakliye Et',
		'Sending reinforcement' : 'Tahkim Yollanıyor',
		'Sending transport' : 'Nakliye Yollanıyor',
		'Sentinel messages' : 'Gözcü Mesajı',
		'Sentinel tower' : 'Gözcü',
		'several attacks' : 'Birkaç Saldırı',
		'several spies' : 'Birkaç Casus',
		'Souls' : 'Ruhlar',
		'Sound configuration' : 'Ses Kofigürasyonu',
		'Sound file' : 'Ses Dosyası',
		'Spectral' : 'Hayali',
		'SpectralDragonKeep' : 'Ejderha Sunagi',
		'spectral_dragon outpost' : 'Hayalet Kasabası',
		' spent. 2 min timeout (defense respawn)' : ' Korumanın Kalkmasına 2 Dakika Kldı',
		' spent. 1 min timeout (defense respawn)' : ' Korumanın Kalkmasına 1 Dakika Kldı',
		'Spies done' : 'Casuslama Başarılı',
		'Spies number' : 'Casus Numarası',
		'Spy One Target' : '1 Hedefi Casusla',
		'Spy reports' : 'Casus Raporları',
		'Spy to ' : 'Casus Buraya : ',
		'Stars' : 'Yıldızlar',
		'Start' : 'Başlangıç',
		'Start Date' : 'Başlangıç Tarihi',
		'Starting...' : 'Baslatiliyor...',
		'Stone' : 'Tas',
		'Stop if any troops lost' : 'Asker Kaybında Durdur',
		'succeeded' : 'Basarili',
		'Successfully initialized' : 'Basariyla Yüklendi',
		'Successfully' : 'Başarılı',
		'Summary' : 'Özet',
		' survivals)' : ' Hayatta Kalan)',
		'Tabs Options' : 'Ayarlar Sekmesi',
		'Target' : 'Hedef',
		'Targets' : 'Hedefler',
		'Task Completed' : 'Tarea Finalizada',
		'Tasks' : 'Görevler',
		'Terrain length set to ' : 'Terrain Uzaklığı ayarlandı : ',
		'To be refreshed' : 'Yenilendi',
		'Too many troops for muster point level' : 'İçtima Alanı seviyesi Yetersiz',
		'Total souls' : 'Toplam Ruh',
		'Tower' : 'Gözcü',
		'Tower configuration' : 'Gözcü Yapılandırması',
		'Training Configuration' : 'Eğitim Konfigrasyonu',
		'Translation Matrix Successfully initialized' : 'Matrix Çvirisi basariyla Yüklendi',
		'Transport reports' : 'Nakliye Raporu',
		'Transport sent to' : 'Nakliye Yollandı :',
		'Troops Capped' : 'Askerler Kepli',
		'Troops for reinforcement' : 'Tahkim İçin Askerler',
		'Troops for Primary Attack' : 'Ana Saldırı İçin Askerler',
		'Troops for Secondary Attacks' : 'İkincil Saldırı İçin Askerler',
		'Troops for transport' : 'Nakliye İçin Askerler',
		'Troops for Wave Attack' : 'Spam saldırısı İçin Askerler',
		'Troops lost' : 'Asker Kaybedildi',
		'Troops statistics for' : 'Bnun İçn Asker İst. :',
		'Turned Off' : 'Kapatıldı',
		'Unowned only' : 'Sadece Sahipsiz',
		'Updating City values' : 'Sehir degierleri Güncelleniyor',
		'Upgrading items' : 'İnşaa edilenler',
		'Use the Levels Tab to select attack areas' : 'Level Skmsine Geri Dön ve Sald. Lvlleri Seç',
		'Warning for ' : 'Uyarı.Bunun İçin : ',
		'was returned with a status of' : 'Durumu Ile geri Döndü',
		'Water' : 'Su',
		'Wave attack to ' : 'Spam saldırısı : ',
		'Wave' : 'Spam',
		'Wildernesses list' : 'Bozkır Listesi',
		'Wind' : 'Rüzgar',
		'You are' : 'Sen',
		'Yoyo functionality' : 'İşlevsellik',
		'ATrans' : 'ZeplinZeplin',	/* abbr Armored Transport */
		'Fang' : 'Zehirli Pençe',	/* abbr Aqua Troop */
		'BatDrg' : 'Savaş Dragonu',	/* abbr Battle Dragon */
		'Conscr' : 'Acemi Er',		/* abbr Conscript */
//		'FGiant' : '?????',			/* abbr Frost giant */
		'FireDrg' : 'Ateş E.',		/* abbr Fire Dragon */
		'FireM' : 'Ayna',			/* abbr Fire Mirror */
		'Magma' : 'Lav Dino',		/* abbr Fire Troop - Magmasaurus */
		'GrtDrg' : 'B Ejderha',		/* abbr Great Dragon */
		'Halbrd' : 'Baltacı',		/* abbr Halberdsman */
		'LBM' : 'Okçu',				/* abbr Longbowman */
		'Mino' : 'Mino',			/* abbr Minotaur */
		'PackDrg' : 'Yük Dr',		/* abbr Pack dragons */
		'SSDrg' : 'Çevik Dr',		/* abbr Swift Strike Dragon */
		'StnDrg' : 'Taş E',			/* abbr Stone Dragon */
		'Ogre' : 'Granit',			/* abbr Stone Troop - Ogre */
		'WatDrg' : 'Su E',			/* abbr Water Dragon */
		'WndDrg' : 'Rüzgar E',		/* abbr Wind Dragon */
		'Banshee' : 'Ö Meleği',		/* abbr Wind Troop - Banshee */
		// Objects
		'WaterEgg' : 'Yumurta- Su E.',
		'StoneEgg' : 'Yumurta- Taş E.',
		'FireEgg' : 'Yumurta- Ateş E.',
		'WindEgg' : 'Yumurta- Rüzgar E.',
		'GD Body' : 'Gövde Koruyucu- B.Dr.',
		'GD Helmet' : 'Miğfer- B.Dr.',
		'GD Tail' : 'Kuyruk Zırhı- B.Dr.',
		'GD Claw' : 'Pençe Zırhı- B.Dr',
		'WD Body' : 'Gövde Koruyucu- Su E.',
		'WD Helmet' : 'Miğfer- Su E.',
		'WD Tail' : 'Kuyruk Zırhı- Su E.',
		'WD Claw' : 'Pençe Zırhı- Su E.',
		'SD Body' : 'Gövde Koruyucu- Taş E.',
		'SD Helmet' : 'Miğfer- Taş E.',
		'SD Tail' : 'Kuyruk Zırhı- Taş E.',
		'SD Claw' : 'Pençe Zırhı- Taş E.',
		'FD Body' : 'Gövde Koruyucu- Ateş E.',
		'FD Helmet' : 'Miğfer- Ateş E.',
		'FD Tail' : 'Kuyruk Zırhı- Ateş E.',
		'FD Claw' : 'Pençe Zırhı- Ateş E.',
		'WiD Body' : 'Gövde Koruyucu- Rüzgar E.',
		'WiD Helmet' : 'Miğfer- Rüzgar E.',
		'WiD Tail' : 'Kuyruk Zırhı- Rüzgar E.',
		'WiD Claw' : 'Pençe Zırhı- Rüzgar E.',
		'Respirators' : 'Nefes Aleti',
		'Respirator-100' : '100 Nefes Aleti',
		'Respirator-500' : '500 Nefes Aleti',
		'Respirator-1000' : '1000 Nefes Aleti',
		'Mandrakes' : 'Kök',
		'Mandrakes-100' : '100 Kök',
		'Mandrakes-500' : '500 Kök',
		'Mandrakes-1000' : '1000 Kök',
		'Runes' : 'Run',
		'Runes-100' : '100 Run',
		'Runes-500' : '500 Run',
		'Runes-1000' : '1000 Run',
		'Talons' : 'Pençe',
		'Talons-100' : '100 Pençe',
		'Talons-500' : '500 Pençe',
		'Talons-1000' : '1000 Pençe',
		'Zzz' : 'Zzz'
	};
	break;
	/**********************************************************************
	     Swedish  (by Toruk & Robert)
	***********************************************************************/
case 'sv':
	TRANSLATION_ARRAY = {
		'</B> and <B>' : '</B> och <B>',
		'<B>Attacker\'s move turn</B>' : '<B>Försvara med offensiva enheter</B>',
		'<B>Attacker\'s attack turn</B>' : '<B>Attackera med offensiva enheter</B>',
		'<b>Bad request!</b>' : '<b>Dålig begäran!</b>',
		'<B>Defender\'s move turn</B>' : '<B>Försvara med defensiva enheter</B>',
		'<B>Defender\'s attack turn</B>' : '<B>Attackera med defensiva enheter</B>',
		'<b>Rate Limit Exceeded</b>, too many requests!' : '<b>Begränsa fråga överstiger</b>, alltför många förfrågningar skickats!',
		'About KabaListics' : 'Om KabaListics',
		'above the first value' : 'över det första värdet',
		'Action Log' : 'Händelselogg',
		'Actions' : 'Händelser',
		'Activate Attacks Logs' : 'Aktivera attackloggning',
		'Alerts log' : 'Varning log',
		'Alives' : 'Överlevande',
		'All alliances' : 'Samtliga allianser',
		'All players' : 'Alla spelare',
		'All types' : 'Alla typer',
		'Alliance features' : 'Alliansens funktioner',
		'Alliances list retrieved' : 'Allians-listan hämtat',
		'Alliance members list retrieved' : 'Förteckning över medlemmar i alliansen återvinns',
		'Alliance messages' : 'Allians inlägg',
		'and' : 'och',
		'Another march request is pending' : 'En annan begäran av marcher är avvaktande',
		'Are you sure you want to delete All Permanent Data' : 'Är du säker på att du vill radera all permanent Data',
		'Arrival time' : 'Ankomsttid',
		'at' : 'vid',
		' at ' : ' hos ',
		' at range' : ' på distans',
		'Attack sent to' : 'Attack skickad till',
		'Attack One Target in Multiple waves' : 'Attackera ett mål I flera vågor',
		'Attacker' : 'Anfallare',
		'Attacking' : 'Attackerar',
		'Attacks Configuration' : 'Konfigurera attacker',
		'Attacks Stats' : 'Attack Stats',
		'Attacks' : 'Attacker',
		'attempted' : 'försökt',
		'attempt for' : 'försök för',
		'Auto harvest resources from outposts every' : 'Automatisk insamling av resurser från utpost(erna) varje',
		'Auto refresh info tab data every' : 'Auto uppdatering data av fliken info varje',
		'Automatically' : 'Automatiskt',
		'Automatically recall transport 1 minute before delivery' : 'Automatiskt hämta transport 1 minut före leverans',
		'available.' : 'tillgänglig.',
		'Available troops' : 'Tillgängliga trupper',
		'Awaiting task completion notification' : 'Väntar på anmälan om utgången av uppdrag',
		'Back at the same time' : 'Tillbaka på samma tid',
		'Backup' : 'Backup',
		'Battle' : 'Strid',
		'Battle calculator' : 'Strids simulator',
		'Battle forces' : 'Stridande trupper',
		'Battle log' : 'Strids log',
		'Battle lost !!' : 'Förlorade strider !!',
		'Battle mechanics' : 'Strids mekanism',
		'Battle won !!' : 'Vunna strider !!',
		'blue_energy' : 'Blå energi',
		'Bookmark' : 'Bokmärke',
		'Bookmarks' : 'Bokmärken',
		'Bookmarks Configuration' : 'Inställningar för bokmärken',
		'Bookmark saved' : 'Bokmärke sparat',
		'Building' : 'Konstruktionsförlopp',
		'Busy' : 'Upptagen',
		'by' : 'av',
		'By distance ascending' : 'Med stigande avstånd',
		'By distance descending' : 'Med fallande avstånd',
		'Cache data' : 'Cache data',
		'Calculate' : 'Beräkna',
		'Camps/wilds attack reports' : 'Rapporter om läger/vildmarker attack',
		'Capital data' : 'Stads data',
		'Capital data successfully fetched' : 'Stads data hämtat med framgång',
		'Check sentinel reports every ' : 'Kontrollera portvakt rapporter varje ',
		'Check the following great dragons to exclude them from being sent' : 'Markera följande drakar som ej ska skickas med i attacker',
		'Check to use UTC time instead of local time' : 'Kontrollera för använda UTC-tid i stället för lokal tid',
		'Claim' : 'Hävdar',
		'Claimed' : 'Hävdade',
		'Claiming quest' : 'Skickar förfrågan',
		'Clear' : 'Rensa',
		'Clear all' : 'Rensa all',
		'Clear all data' : 'Rensa all info',
		'Clear last attack on all maps' : 'Rensa senaste attacker på alla kartor',
		'Clear last attack on current map' : 'Rensa senaste attacker på aktuella kartan',
		'Clear local storage (internet cache)' : 'Radera webbhistorik',
		'Clear log' : 'Rensa loggen',
		'Clear Stats' : 'Radera stats',
		'Collected resources at outpost' : 'Resurser samlas från utpost',
		'Completing...' : 'Slutför...',
		'Completion errors' : 'Fel vid slutförande',
		'Config' : 'Konfig',
		'Confirmation' : 'Bekräfta',
		'Console Log' : 'Konsol Log',
		'Console' : 'Konsol',
		'Coordinates' : 'Koordinater',
		'Coords' : 'Kords',
//		'Copy troops reported by the sentinel to the battle calculator' : '?????',
		' damages taken' : ' tagen skada',
		' damages to ' : ' skada till ',
		'data' : 'data',
		'data successfully fetched' : 'data hämtades med framgång',
		'Date range' : 'Datumintervall',
		'Days' : 'Dagar',
		' deal ' : ' göra skada ',
		'Defender' : 'Försvarare',
		'Defending' : 'Försvarar',
		'Defense force modified' : 'Försvars-styrka modifierad',
		'Defense strategy' : 'Försvars strategi',
		'Delay before script startup' : 'Initial fördröjning innan skriptet startas',
		'Delay Between Attacks' : 'Fördröjning mellan attacker',
		'Delay Between Transports' : 'Fördröjning mellan transporter',
		'delayed due to' : 'försenad,',
		'delayed due to march limit reached' : 'försenad, max. antal marcher uppnådda',
		'delayed due to muster point full' : 'försenad, träningskö full',
		'delayed due to no available generals' : 'försenad, generaler ej tillgängliga',
		'delayed due to no available Great Dragon' : 'försenad, ingen stor drake tillgängliga',
		'delayed due to pending march request' : 'försenad, begäran av avvaktande marcher',
		'delayed due to insufficient troops' : 'försenad, otillräckligt med trupper',
		'Delete now' : 'Radera nu',
		'Delete Battle Reports' : 'Radera Strids rapporter',
		'Delete messages' : 'Ta bort inlägg',
		'Delete messages of this type' : 'Ta bort inlägg av denna typ',
		'Delete spy reports' : 'Radera spionrapporter',
		'Detailed search' : 'Detaljerad sökning',
		'Disable <B>Alliance</B> tab' : 'Inaktivera <B>Allians</B>',
		'Disable <B>Battle</B> tab' : 'Inaktivera <B>Strid</B>',
		'Disable <B>Bookmarks</B> tab' : 'Inaktivera <B>Bokmärken</B>',
		'Disable <B>Multi</B> tab' : 'Inaktivera <B>Multi</B>',
		'Disable <B>Search</B> tab' : 'Inaktivera <B>Sök</B>',
		'Disable <B>Spy</B> tab' : 'Inaktivera <B>Spionage</B>',
		'Disable <B>Wall</B> tab' : 'Inaktivera <B>Mur</B>',
		'Disable <B>Wave</B> tab' : 'Inaktivera <B>Våg</B>',
		'Disable <B>Log</B> tab' : 'Inaktivera <B>Logg</B>',
		'Disabled' : 'Inaktiverad',
		'Display official background image' : 'Visa den officiella bakrundsbilden',
		'Dist' : 'Avstånd',
		'Distance must be between' : 'Avståndet måste vara mellan',
		'Distance' : 'Avstånd',
		'Dragon healing' : 'Drakhälsa',
		'Dragons' : 'Drakar',
		'Do not show alerts obsolete since' : 'visa ej äldre varningar än',
//		'Do you want to delete existing Permanent Data' : '?????',
		'Do you want to save in Permanent Data the current script setting' : 'Vill du spara permanent data i det aktuella skriptets inställningar',
		'Do you want to save Map Data in local file' : 'Vill du spara den kartdata i den lokala filen',
		'Do you want to save Permanent Data in local file' : 'Vill du spara den permanenta datan i den lokala filen',
		'Dutch' : 'Holländska',
		'Edit' : 'Redigera',
		'Edit bookmark' : 'Redigera bokmärken',
		'Edit defense' : 'Redigera försvar',
		'Enable' : 'Aktivera',
//		'Enable cheat (all troops in all outposts, transport of blue energy)' : 'Aktivera fusk (alla trupper i alla utposter,transportera blå energi)',
		'Enable transport of blue energy' : 'Aktivera transportera blå energi',
		'Enable use of speed-ups in attacks waves' : 'Aktivera användning av hastighetsbegränsande upp attackerna',
		'Enable verbose logging' : 'Aktivera detaljerad loggning',
		'Enable window drag' : 'Aktivera fönsterdrag',
		'Enable the sentinel tower' : 'Aktivera vakttorn',
		'Enabled' : 'Aktiverad',
		'End' : 'Stopp',
		'English' : 'Engelska',
		'Ennemy General' : 'Fiende General',
		'Ennemy research levels' : 'Fiendens forsknings nivå',
		'Enter -1 as troop quantity to use the maximum available' : 'Ange -1 på truppkvantitet för att använda maximalt tillgängliga',
		'Error' : 'Fel',
		'Error while retrieving the list of members' : 'Fel vid hämtning av medlems listan',
		'Error while setting defense choice' : 'Fel medans inställning av försvar',
		'Evol' : 'Förändring',
		'Except' : 'Undantag',
		'Exception' : 'Undantag',
		'failed' : 'misslyckades',
		'failed and returned error' : 'misslyckades och återkallade felet',
		'Fast search' : 'Snabb sökning',
		'Features' : 'Funktioner',
		'Fetching' : 'Laddar',
		'Fetching Capital data' : 'Laddar av största staden data',
		'Fetching Manifest' : 'Laddar Manifest',
		'Fetching Outpost #' : 'Laddar Utpost ',
		'Fetching Seed' : 'Laddar av spelar data',
		'Fetching Translation matrix' : 'Hämtar översättning',
		'Fire' : 'Eld',
		'fire_dragon outpost' : 'Eld utpost',
		'First value must be between' : 'Första värdet måste ligga mellan',
		'Flash game Auto refresh every' : 'Autorefresh av Flashspel varje',
//		'Foes' : '?????',
		'for' : 'för',
		'Force saving current script settings' : 'Spara samtliga skript-inställningar',
		'Forum link' : 'Forum länk',
		'French' : 'Franska',
		'Game messages' : 'Meddelande av spelet',
		'Game Options' : 'Spelalternativ',
		'GD' : 'JD',
		'Generals' : 'Generaler',
		'German' : 'Tyska',
		'Getting basic data...' : 'Återvinning av grund data...',
		'Getting cities data...' : 'Återvinning av städer data...',
		'Getting game data...' : 'Återvinning av speldata...',
		'Got' : 'Läst in',
		'Great dragons' : 'Jätte Drakar',
		'Help/About' : 'Hjälp/Angående',
		'Hide spy alerts' : 'Dölj spion varningar',
		'Hiding' : 'Göm',
		'History' : 'Historia',
		'h' : 't',
		'Hours' : 'Timma',
		'ice_dragon outpost' : 'Is utpost',
		'Ice' : 'Is',
		'Idle' : 'Overksam',
		'Idle pop' : 'Tomgång folk',
		'In city' : 'I staden',
		'In march' : 'I marsh',
		' in melee' : ' i närstrid',
		'in progress' : 'pågår',
		'Include Great Dragon' : 'Skicka en stor drake med varje attack',
		'Info' : 'Info',
		'Initialization' : 'Initierar',
		'Initializing...' : 'Initierar...',
		'Initializing map, auto-collect, ...' : 'Initiera kartan, automatisk insamling, ...',
		'Invalid date From' : 'Ogiltig datum Från',
		'Invalid date To' : 'Ogiltig datum Till',
		'Invalid date range' : 'Ogiltigt datumintervall',
		'Invalid delays' : 'Ogiltig fördröjning',
		'Invalid number of troops' : 'Inkorrekt antal av trupper',
		'Inventory' : 'Föremål',
		'Joined' : 'Anslöt',
		'Keep battle reports of attacks from other players' : 'Spara stridsrapporter av attacker från andra spelare',
		'Keep battle reports of my attacks on other players' : 'Spara stridsrapporter av mina attacker på andra spelare',
		' (kill ' : ' (Döda ',
		'Killed' : 'Förlust',
		'Last attack' : 'Senaste attack',
		'leader' : 'Ledare',
		'life lost' : 'Förlorat liv',
		'Loaded' : 'Laddad',
		'Loading basic data' : 'Laddar grunddata',
		'Locale data was Successfully requested from the server' : 'Lokal data har lyckats hämtats från servern',
		'Logs' : 'Log',
		'Log' : 'Log',
		'lord' : 'Härskare',
		'Manifest not available, using defaults' : 'Manifestet är ej tillgänglig, använder standardinställningar',
		'Manifest Successfully initialized' : 'Manifesto initierades framgångsrikt',
		'Manifest was Successfully requested from the server' : 'Manifestet har framgångsrikt behandlats av servern',
		'Manual attack sent to' : 'Manuellattack skickad till',
		'March limit reached' : 'Max. antal marcher uppnådda',
		'Max level' : 'Nivå max',
		'Map Search' : 'Kart sök',
		'Maximize resource to transport according to max load' : 'Maximera resurser för transport enligt maximal last',
		'Maximum level reached' : 'Maximinivån uppnådde',
		'Maximum simultaneous marches' : 'Max. antal marcher',
		'Maximum training queues possible per city, according to available resources' : 'Maximera köer enligt tillgängliga resurser',
		'Members' : 'Medlemmar',
		'Members list ' : 'Medlemslista ',
		'Message(s) deleted' : 'Meddelande(n) borttagna',
		'Message(s) deletion in progress' : 'Meddelande(n) radering pågår',
		'miles' : 'miles',
		'Min level' : 'Nivå min',
		'Minutes' : 'Minuter',
		' move to ' : ' flytta till ',
		'Multi' : 'Flera',
		'Muster Point Full' : 'Träningskö full',
		'Need' : 'Behöver',
//		'New version has been installed...' : '?????...',
		'No Generals Available' : 'Generaler ej tillgängliga',
		'No great dragon available' : 'Ingen stor drake tillgänglig',
		'no max' : 'ingen gräns',
		'No new version of' : 'Ingen ny version av',
		'No resources to transport defined' : 'Ej tillräckligt med resurser',
		'No Troops Defined' : 'Inga trupper tagna',
		'Not enough' : 'Ej tillräckligt',
		'Not ready' : 'Inte redo',
		'of' : 'av',
		'one attack' : 'en attack',
		'one spy' : 'en spion',
		'Only one training queue per city' : 'En enda utbildning per stad',
		'Options' : 'Inställningar',
		'Opts' : 'Inställ',
		'Outpost 1' : 'Vatten utpost',
		'Outpost 2' : 'Sten utpost',
		'Outpost 3' : 'Eld utpost',
		'Outpost 4' : 'Vind utpost',
		'Outpost #1' : 'Utpost #1',
		'Outpost #2' : 'Utpost #2',
		'Outpost #3' : 'Utpost #3',
		'Outpost #4' : 'Utpost #4',
		'Outpost #5' : 'Utpost #5',
		'Outpost #6' : 'Utpost #6',
		'Outpost #7' : 'Utpost #7',
		'Outpost damages' : 'Skada på utpost',
		'overlord' : 'Överhärskare',
		'Overview' : 'Översyn',
		'Owner' : 'Ägare',
		'Play for' : 'Spela för',
		'Play sound on incoming sentinel report' : 'Spela upp ljud vid varning från Vaktposten',
		'Play sound on task completion' : 'Spela ljud vid slutförande',
		'Player cities' : 'Spelares Städer',
		'Player cities list' : 'Förteckning av spelarstäder',
		'Player data was Successfully requested from the server' : 'Spelardatan har framgångsrikt hämtats från servern',
		'Player messages' : 'Meddelanden av spelare',
		'Player name' : 'Spelar namn',
		'Please wait...' : 'Vänligen vänta...',
		'Preset' : 'Förinställd',
		'Preset name' : 'Namn på försvar',
		'Primary attack to ' : 'Huvudattacken till ',
		'Putting build job in persistent data' : 'Registrering av byggnation i den ihållande datauppgiften',
		'Putting research job in persistent data' : 'Registrering av forskning i den ihållande datauppgiften',
		'Putting resurrect job in persistent data' : 'Registrering av återupplivning i den ihållande datauppgiften',
//		'Quantity' : '?????',
		'Quest' : 'Begäran',
		'Quest claim Error' : 'Fel med begäran',
		'Rate Limit Exceeded because there were too many requests' : 'Gränsen är uppnådd på grund av för många förfrågningar',
		'Read page ' : 'Läs sidan ',
		'Ready' : 'Redo',
		'Recipient' : 'Mottagare',
		'Refresh' : 'Uppdatera',
		'Refresh list' : 'Uppdatera lista',
		'Refresh map data' : 'Uppdatera kartdata',
		'Refresh selection' : 'Uppdatera utvald',
		'Reinforcement' : 'Förstärkning',
		'Reinforcement reports' : 'Förstärkning rapporter',
		'Reinforcement sent to' : 'Förstärkning skickat till',
		'Reload' : 'Uppdaterar DOA',
		'Remove all' : 'Ta bort allt',
		'Repairing' : 'Reparerar',
		'Repeat every' : 'Upprepa varje',
		'Research Started' : 'Forskning startad',
		'Researching' : 'Forska',
		'Reset Stats' : 'Nollställ statistik',
		'Resources stock levels update failed' : 'Uppdatering av lagernivåer av resurser har misslyckades',
		'Resources to transport' : 'Resurser för att skicka',
		'Restore' : 'Återställ',
		'Restore script settings from local file' : 'Återställ skript-inställningar från lokal fil',
		'Resurrection' : 'Återupplivar',
		'Resurrect' : 'Återuppliva',
		'Retry in' : 'Fortsätta igen',
		'Reviving' : 'Återuppliva',
		'Role' : 'Roll',
		'Rules' : 'Regler',
		'Run Time' : 'Tidsförlopp',
		'Safe Mode' : 'Felsäkert läge',
		'Save Attaque' : 'Spara attack',
		'Save current map data in a local file' : 'Spara aktuell data i lokal fil',
		'Save current script settings in a local file' : 'Spara skript-inställningar i lokal fil',
		'Save preset' : 'Spara förinställning',
		'Scanning map' : 'Skannar kartan endast efter städer',
		'Scanning map for cities/wildernesses' : 'Skanna kartan efter städer/vildmarker',
		'Scanning map for wildernesses' : 'Skannar kartan endast efter vildmarker',
		'Script language' : 'Skript språk',
		'Script Options' : 'Script alternativ',
		'Search coords' : 'Sök kords',
		'Search for alliance list' : 'Leta efter allians listan',
		'Search for alliance members' : 'Sök efter allians medlemmar',
		'Search max radius' : 'Sök max. avstånd',
		'Search Radius' : 'Sök avstånd',
		'Second value must be at least' : 'Andra värdet måste vara minst',
		'Seconds' : 'Sekunder',
		'seconds' : 'sekunder',
		'Secondary attack to ' : 'Påföljande attacken till ',
		'Seed Successfully initialized' : 'Spelare data initieras framgångsrikt',
		'Select at least one type of message or report to delete' : 'Välj minst en typ av meddelande eller rapport ta bort',
		'Send reinforcement' : 'Skicka förstärkning',
		'Send transport' : 'Skicka transporter',
		'Sending reinforcement' : 'Skickar förstärkning',
		'Sending transport' : 'Skickar transporter',
		'Sentinel messages' : 'Varningar från Vaktposten',
		'Sentinel tower' : 'Vaktposttorn',
		'Set defense' : 'Ange försvar',
		'Set Def' : 'Ange Frs',
		'Setting defense' : 'Anger försvar',
		'several attacks' : 'flera attacker',
		'several spies' : 'flera spioner',
		'Souls' : 'Själar',
		'Sound configuration' : 'Ljudinställning',
		'Sound file' : 'Ljudfil',
		'Spanish' : 'Spanska',
		'Spectral' : 'Spöklik',
		'SpectralDragonKeep' : 'Spöklik Drakaltare',
		'spectral_dragon outpost' : 'Spöklika Ruiner',
		' spent. 2 min timeout (defense respawn)' : ' Spenderat abort efter 2 min (försvar återskapat)',
		' spent. 1 min timeout (defense respawn)' : ' Spenderat abort efter 1 min (försvar återskapat)',
		'Spies done' : 'Spion klar',
		'Spies number' : 'Antal spioner',
		'Spy One Target' : 'Speja av 1 mål',
		'Spy reports' : 'Spion rapporter',
		'Spy to ' : 'Spion skickad till ',
		'Stars' : 'Stjärnor',
		'Start' : 'Start',
		'Start Date' : 'Startdatum',
		'Starting...' : 'Starta...',
		'Step' : 'Steg',
		'Stone' : 'Sten',
		'stone_dragon outpost' : 'Sten utpost',
		'Stop if any troops lost' : 'Avbryt vågor vid truppförlust',
		'succeeded' : 'lyckades',
		'Successfully initialized' : 'Framgångsrikt initierats',
		'Successfully' : 'Framgångsrikt',
		'Summary' : 'Sammandrag',
		' survivals)' : ' överlevande)',
//		'Swamp' : '?????',
		'swamp_dragon outpost' : 'Sjunket tempel',
		'Swedish' : 'Svenska',
		'switchDefense OK' : 'Försvars ändring OK',
		'Switch defense wall status' : 'Ändra försvar på mur',
		'Switching defense' : 'Ändrar försvar',
		'Tabs Options' : 'Flikar alternativ',
		'Target' : 'Mål',
		'Targets' : 'Målen',
		'Task Completed' : 'Utförd uppgift',
		'Tasks' : 'Uppgifter',
		'Terrain length set to ' : 'Terräng avstånd inställd på ',
//		'This should not clear map and alliance data.' : '?????.',
		'Time' : 'Tid',
		'to' : 'till',
		'To be refreshed' : 'Att uppdatera',
		'Toggle Flash' : 'Förnya Flash',
		'Too many troops for muster point level' : 'Maximal utplacering nått',
		'Total souls' : 'Total själar',
		'Tower' : 'Torn',
		'Tower configuration' : 'Konfigurera Vakttorn',
		'Training Configuration' : 'Konfig av autoträning',
		'Translation Matrix Successfully initialized' : 'Översättning Matrix initierades framgångsrikt',
		'Transport reports' : 'Transport rapporter',
		'Transport sent to' : 'Transport skickat till',
		'Troops Capped' : 'Capped trupper',
		'Troops for Bookmarks Attack' : 'Trupper för bokmärkta attacker',
		'Troops for defense' : 'Trupper för försvar',
		'Troops for Primary Attack' : 'Trupper I Huvudanfallet',
		'Troops for reinforcement' : 'Trupper för förstärkning',
		'Troops for Secondary Attacks' : 'Trupper I påföljande anfallsvågor',
		'Troops for transport' : 'Trupper för transport',
		'Troops for Wave Attack' : 'Trupper för vågattacker',
		'Troops lost' : 'Trupper förlorade',
		'Troops max' : 'Max. trupper',
		'Troops statistics' : 'Statistik trupper',
		'Troops statistics for' : 'Statistik för',
		'Turkish' : 'Turkiska',
		'Turned Off' : 'Avstängd',
		'Unlimited' : 'Obegränsat',
		'Unowned only' : 'Bara lediga',
		'Updating City values' : 'Uppdatera data av stadens',
		'Upgrading items' : 'Uppgradera saker',
		'Use the Levels Tab to select attack areas' : 'Använd fliken "Nivåer" för att välja mål',
		'Version update' : 'Uppdatering version',
		'Wall defense setting' : 'Försvarsintällning på mur',
		'Wall management' : 'Hantera mur',
		'Warning for ' : 'Varning för ',
		'was returned with a status of' : 'returnerades med status',
		'Water' : 'Vatten',
		'water_dragon outpost' : 'Vatten utpost',
		'Wave attack to ' : 'Vågor skickade till ',
		'Wave' : 'Vågor',
		'Wiki URL' : 'Wiki URL',
		'Wildernesses list' : 'Vildmarks lista',
		'Wind' : 'Vind',
		'wind_dragon outpost' : 'Vind utpost',
		'Without alliance' : 'Allianslös',
		'You are' : 'Du är',
		'Yoyo' : 'Yoyo',
		'Yoyo functionality' : 'Yoyo funktionalitet',
		'ATrans' : 'AT',			/* abbr Armored Transport */
		'Banshee' : 'Banshee',		/* abbr Wind Troop - Banshee */
		'BatDrg' : 'BD',			/* abbr Battle Dragon */
		'Conscr' : 'Bärare',		/* abbr Conscript */
		'Fang' : 'Fisk',			/* abbr Aqua Troop */
//		'FGiant' : '?????',			/* abbr Frost giant */
		'FireDrg' : 'Eld drake',	/* abbr Fire Dragon */
		'FireM' : 'FM',				/* abbr Fire Mirror */
		'GrtDrg' : 'JätteDrg',		/* abbr Great Dragon */
		'Halbrd' : 'Halbrd',		/* abbr Halberdsman */
		'IceDrg' : 'FrostDrg',		/* abbr Ice Dragon */
		'LBM' : 'LBM',				/* abbr Longbowman */
		'Magma' : 'Lava',			/* abbr Fire Troop - Magmasaurus */
		'Mino' : 'Mino',			/* abbr Minotaur */
		'Ogre' : 'Troll',			/* abbr Stone Troop - Ogre */
		'PackDrg' : 'PckDrg',		/* abbr Pack dragons */
		'SpctDrg' : 'SpökDrag',		/* abbr Spectral Dragon */
		'SReaper' : 'Själskördare',	/* abbr Ice Troop - SoulReaper */
		'SSDrg' : 'SSD',			/* abbr Swift Strike Dragon */
		'StnDrg' : 'DrgSten',		/* abbr Stone Dragon */
		'SwpDrg' : 'TräskDrk',		/* abbr Swamp Dragon */
		'Venom' : 'Giftväktare',	/* abbr Swamp Troop - Venom */
		'WatDrg' : 'DrgVatten',		/* abbr Water Dragon */
		'WndDrg' : 'Vind drake',	/* abbr Wind Dragon */
		// Missing Kabam translations
		'FireDragon' : 'Elddrakar',
		'WindDragon' : 'Vinddrakar',
		// Objects
		'WaterEgg' : 'Vatten ägg',
		'StoneEgg' : 'Sten ägg',
		'FireEgg' : 'Eld ägg',
		'WindEgg' : 'Vind ägg',
		'IceEgg' : 'Is ägg',
		'SwampEgg' : 'Träskägg',
		'GD Body' : 'Harnesk JD',
		'GD Helmet' : 'Hjälm JD',
		'GD Tail' : 'Svans JD',
		'GD Claw' : 'Klo JD',
		'WD Body' : 'Harnesk VD',
		'WD Helmet' : 'Hjälm VD',
		'WD Tail' : 'Svans VD',
		'WD Claw' : 'Klo VD',
		'SD Body' : 'Harnesk SD',
		'SD Helmet' : 'Hjälm SD',
		'SD Tail' : 'Svans SD',
		'SD Claw' : 'Klo SD',
		'FD Body' : 'Harnesk ED',
		'FD Helmet' : 'Hjälm ED',
		'FD Tail' : 'Svans ED',
		'FD Claw' : 'Klo ED',
		'WiD Body' : 'Harnesk ViD',
		'WiD Helmet' : 'Hjälm ViD',
		'WiD Tail' : 'Svans ViD',
		'WiD Claw' : 'Klo ViD',
		'IceD Body' : 'Harnesk FroD',
		'IceD Helmet' : 'Hjälm FroD',
		'IceD Tail' : 'Svans FroD',
		'IceD Claw' : 'Klo FroD',
		'SpD Armor' : 'Harnesk SpökD',
		'SpD Body' : 'Harnesk SpökD',
		'SpD Helmet' : 'Hjälm SpökD',
		'SpD Head' : 'Hjälm SpökD',
		'SpD Tail' : 'Svans SpökD',
		'SpD TailG' : 'Svans SpökD',
		'SpD Claw' : 'Klo SpökD',
		'SpD Talons' : 'Klo SpökD',
		'SwD Body' : 'Harnesk TräskDrk',
		'SwD Helmet' : 'Hjälm TräskDrk',
		'SwD Tail' : 'Svans TräskDrk',
		'SwD Claw' : 'Klo TräskDrk',
		'Respirators' : 'Huggtands andare',
		'Respirator-100' : '100 Huggtands andare',
		'Respirator-500' : '500 Huggtands andare',
		'Respirator-1000' : '1000 Huggtands andare',
		'Mandrakes' : 'Alrunor',
		'Mandrakes-100' : '100 Alrunor',
		'Mandrakes-500' : '500 Alrunor',
		'Mandrakes-1000' : '1000 Alrunor',
		'Runes' : 'Runor',
		'Runes-100' : '100 Runor',
		'Runes-500' : '500 Runor',
		'Runes-1000' : '1000 Runor',
		'Talons' : 'Klor',
		'Talons-100' : '100 Klor',
		'Talons-500' : '500 Klor',
		'Talons-1000' : '1000 Klor',
		'Totems' : 'Skörde totem',
		'Totems-100' : '100 Totems',
		'Totems-500' : '500 Totems',
		'Totems-1000' : '1000 Totems',
		'Scales' : 'Träskfjäll',
		'Scales-100' : '100 Träskfjäll',
		'Scales-500' : '500 Träskfjäll',
		'Scales-1000' : '1000 Träskfjäll',
		'Zzz' : 'Zzz'
	};
	break;
default:
	TRANSLATION_ARRAY = {
		'FireDragon' : 'Fire Dragon',
		'fire_dragon outpost' : 'Fire dragon outpost',
		'WindDragon' : 'Wind Dragon',
		'ice_dragon outpost' : 'Ice dragon outpost',
		'Outpost 1' : 'Water dragon outpost',
		'Outpost 2' : 'Stone dragon outpost',
		'Outpost 3' : 'Fire dragon outpost',
		'Outpost 4' : 'Wind dragon outpost',
		'spectral_dragon outpost' : 'Spectral ruins',
		'stone_dragon outpost' : 'Stone dragon outpost',
		'water_dragon outpost' : 'Water dragon outpost',
		'wind_dragon outpost' : 'Wind dragon outpost',
		'Zzz':'Zzz'
	};
}
} // End changeLang

// Set initial Language
setLanguage();

/*******************************************************************************
***************************          STYLES         ****************************
*******************************************************************************/
/********************************************************************************
* All id and class names must be scrambled to prevent the script from being    *
* blocked. These names have to be generated and allocated to CSS prior to      *
* rest of the script being initialised.                                        *
********************************************************************************/ 
var UID = {};
var UIDN = {};
function makeUID(len){
	var len = ( len != undefined ? len : 20);
	var chars = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','u','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','U','R','S','T','U','V','W','X','Y','Z','0','1','2','3','4','5','6','7','8','9','_'];
	var uid = chars[Math.floor(Math.random()*54)];
	for(var i = 0; i < len; i++)
	{
		uid += chars[Math.floor(Math.random()*64)];
	}
	return uid;
}
function getUID(name){
	return UID[name] != undefined ? UID[name] : name;
}
function setUID(name){
	var uid = makeUID();
	while(UIDN[uid] != undefined){
		uid = makeUID();
	}
	UIDN[uid] = 1;
	UID[name] = uid;
	return uid;
}

function initStylesUID () {
	for (var i=0; i < styleList.length; i++) {
		setUID(styleList[i]);
	}
}
initStylesUID();


var TIMER_COLOR = '#2B4988';

function setMainStyles() { 
	var css = '\
	.jewel {\
		padding : 1px;\
		font-size: 7pt !important;\
		color: #666 !important;\
	}\
	.progress_on {\
		height:12px;\
		width:2px;\
		background-color: rgb(0,125,189);\
		background-image: linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
		background-image: -moz-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
		background-image: -webkit-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
	}\
	.progress_off {\
		height:12px;\
		width:2px;\
		background-color:rgb(255,255,255);\
	}\
	.progress_bar {\
		border: 1px solid #333;\
		border-radius: 3px;\
		-moz-border-radius: 3px;\
		-webkit-box-shadow: rgba(0,0,0,0.52) 1px 1px 1px;\
		-moz-box-shadow: rgba(0,0,0,0.52) 1px 1px 1px;\
	}\
	.' + UID['popup_outer'] + ' {\
		border: 1px solid #777;\
		padding-left:3px;\
		padding-right:3px;\
		padding-bottom:3px;\
		border-radius: 5px;\
		-moz-border-radius: 5px;\
		-webkit-box-shadow: rgba(0,0,0,0.52) 0 0 5px;\
		-moz-box-shadow: rgba(0,0,0,0.52) 0 0 5px;\
	}\
	.' + UID['popup_close'] + ' {\
		position: absolute;\
		display:block;\
		right:-1px;\
		margin-top:-1px;\
		width:20px;\
		height:18px;\
		text-align:center;\
		color:#fff;\
		background-color:#555;\
		font-weight:bold;\
		font-size:12px !important;\
		padding:1px;\
		border: 1px solid #666;\
		border-radius: 5px;\
		-moz-border-radius: 5px;\
		cursor: pointer;\
	}\
	.' + UID['popup_close'] + ':hover {\
		background-color:#922;\
		background-image: linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.6) 99%);\
		background-image: -moz-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.6) 99%);\
		background-image: -webkit-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.6) 99%);\
	}\
	.' + UID['popup_bar'] + ':hover {\
		cursor: move;\
	}\
	#' + UID['main_outer'] + ' {\
		background-color: rgb(255,255,255);\
	}\
	#' + UID['main_outer'] + ' * {\
		font-size:8pt;\
		font-family:helvetica,"lucida grande",tahoma,verdana,arial,sans-serif;\
	}\
	#' + UID['main_outer'] + ' div.container {\
		background-color:rgb(245,245,228);\
		height:100%;\
		width:100%;\
		overflow-x: auto;\
	}\
	.confirm_button {\
		width:60px;\
		padding-top:1px;\
		padding-bottom:1px;\
		color:white;\
		font-weight:bold;\
		border: 1px solid #333;\
		border-radius: 3px;\
		-moz-border-radius: 3px;\
		background-image: linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
		background-image: -moz-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
		background-image: -webkit-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
		-webkit-box-shadow: rgba(0,0,0,0.52) 1px 1px 1px;\
		-moz-box-shadow: rgba(0,0,0,0.52) 1px 1px 1px;\
		cursor:hand;\
		cursor:pointer;\
		background-color: rgb(0,94,189);\
	}\
	.confirm_button:hover {\
		background-color: rgb(0,125,150);\
	}\
	div.' + UID['title'] + ' {\
		border:1px solid;\
		border-color:#ffffff;\
		font-weight:bold;\
		padding-top:2px;\
		padding-bottom:2px;\
		text-align:center;\
		color:#ffffff;\
		background-color:rgb(60,90,150);\
		background-image:url(\'' + urlBackgroundLogo + '\');\
		border-radius: 2px;\
		-moz-border-radus: 2px;\
	}\
	.' + UID['title'] + ' * {\
		display:inline-block !important;\
		font-style: normal !important;\
		text-decoration: none !important;\
		font-weight:bold;\
		color:#ffffff;\
		font-size: 10pt !important;\
		line-height: 10pt !important;\
		padding: 0;\
		text-shadow			: 1px 1px rgba(0,0,0,0.6) !important;\
		-moz-text-shadow	: 1px 1px rgba(0,0,0,0.6) !important;\
		-webkit-text-shadow	: 1px 1px rgba(0,0,0,0.6) !important;\
		-khtml-text-shadow	: 1px 1px rgba(0,0,0,0.6) !important;\
	}\
	';
	addStyle(css);
}

function setStyles() { 
	var css = '\
	.jewel {\
		padding : 1px;\
		font-size: 7pt !important;\
		color: #666 !important;\
	}\
	.bluejwl {\
		padding : 1px;\
		font-size: 7pt !important;\
		color: #2B4988 !important;\
	}\
	.wrap {\
		white-space: normal !important;\
	}\
	div.short {\
		color: #000;\
		height:7px;\
	}\
	.emptyline {\
		height:3px;\
	}\
	.progress_on {\
		height:12px;\
		width:2px;\
		background-color: rgb(0,125,189);\
		background-image: linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
		background-image: -moz-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
		background-image: -webkit-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
	}\
	.progress_off {\
		height:12px;\
		width:2px;\
		background-color:rgb(255,255,255);\
	}\
	.progress_bar {\
		border: 1px solid #333;\
		border-radius: 3px;\
		-moz-border-radius: 3px;\
		-webkit-box-shadow: rgba(0,0,0,0.52) 1px 1px 1px;\
		-moz-box-shadow: rgba(0,0,0,0.52) 1px 1px 1px;\
	}\
	.' + UID['hiding'] + ' {\
		background-color: rgb(0,160,110);\
		color: white;\
		padding-left: 10px;\
		padding-right: 10px;\
		margin-right: -2px;\
		border-radius: 2px;\
		-moz-border-radius: 2px;\
		-webkit-box-shadow: rgba(0,0,0,0.52) 0 0 2px;\
		-moz-box-shadow: rgba(0,0,0,0.52) 0 0 2px;\
	}\
	.' + UID['defending'] + ' {\
		background-color: rgb(184,0,46);\
		color: white;\
		padding-left: 10px;\
		padding-right: 10px;\
		margin-right: -2px;\
		border-radius: 2px;\
		-moz-border-radius: 2px;\
		-webkit-box-shadow: rgba(0,0,0,0.52) 0 0 2px;\
		-moz-box-shadow: rgba(0,0,0,0.52) 0 0 2px;\
	}\
	.' + UID['scrollable'] + ' {\
		overflow: auto !important;\
	}\
	.' + UID['popup_outer'] + ' {\
		border: 1px solid #777;\
		padding-left:3px;\
		padding-right:3px;\
		padding-bottom:3px;\
		border-radius: 5px;\
		-moz-border-radius: 5px;\
		-webkit-box-shadow: rgba(0,0,0,0.52) 0 0 5px;\
		-moz-box-shadow: rgba(0,0,0,0.52) 0 0 5px;\
	}\
	.' + UID['popup_close'] + ' {\
		position: absolute;\
		display:block;\
		right:-1px;\
		margin-top:-1px;\
		width:20px;\
		height:18px;\
		text-align:center;\
		color:#fff;\
		background-color:#555;\
		font-weight:bold;\
		font-size:12px !important;\
		padding:1px;\
		border: 1px solid #666;\
		border-radius: 5px;\
		-moz-border-radius: 5px;\
		cursor: pointer;\
	}\
	.' + UID['popup_close'] + ':hover {\
		background-color:#922;\
		background-image: linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.6) 99%);\
		background-image: -moz-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.6) 99%);\
		background-image: -webkit-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.6) 99%);\
	}\
	.' + UID['popup_bar'] + ':hover {\
		cursor: move;\
	}\
	#' + UID['main_outer'] + ' {\
		background-color: rgb(255,255,255);\
	}\
	#' + UID['main_outer'] + ' * {\
		font-size:8pt;\
		font-family:helvetica,"lucida grande",tahoma,verdana,arial,sans-serif;\
	}\
	#' + UID['main_outer'] + ' ul.tabs {\
		overflow: hidden;\
		display: block;\
		border-bottom: 1px solid #898989;\
		height: 26px;\
		list-style: none;\
		margin: 0;\
		padding: 0;\
		font-size: 10px;\
	}\
	#' + UID['main_outer'] + ' ul.line2 {\
		height: 20px;\
	}\
	#' + UID['main_outer'] + ' ul.tabs li.tab {\
		display: inline-block;\
		float: left;\
		cursor:pointer !important;\
	}\
	#' + UID['main_outer'] + ' ul.tabs li.tab a {\
		background-color: rgb(235,238,245);\
		border-bottom-width: 1px;\
		border: 1px solid #898989;\
		border-left-width: 0;\
		color: #333;\
		font-weight: bold;\
		display: block;\
		height: 16px;\
		margin-top: 6px;\
		padding: 2px 9px 3px 8px;\
		position: relative;\
		text-decoration: none;\
		cursor:pointer;\
	}\
	#' + UID['main_outer'] + ' ul.tabs li.line1 a {\
		padding: 2px 9px 0px 8px;\
	}\
	#' + UID['main_outer'] + ' ul.tabs li.line2 a {\
		height: 16px;\
		margin-top: 0px;\
	}\
	#' + UID['main_outer'] + ' ul.tabs li.first a {\
		border-left-width: 1px;\
	}\
	#' + UID['main_outer'] + ' ul.tabs li.tab a.selected {\
		background-color: rgb(60,90,150);\
		border-top-color: #3B5998;\
		border-bottom-color: #3B5998;\
		border-left-color: #5973A9;\
		border-right-color: #5973A9;\
		color: white;\
		-webkit-box-shadow: rgba(0,0,0,0.6) 1px 0px 1px;\
		-moz-box-shadow: rgba(0,0,0,0.6) 1px 0px 1px;\
		background-image: linear-gradient(bottom, rgba(0,0,0,0) 12%, rgba(255,255,255,0.3) 90%, rgba(255,255,255,0.9) 99%);\
		background-image: -moz-linear-gradient(bottom, rgba(0,0,0,0) 12%, rgba(255,255,255,0.3) 90%, rgba(255,255,255,0.9) 99%);\
		background-image: -webkit-linear-gradient(bottom, rgba(0,0,0,0) 12%, rgba(255,255,255,0.3) 90%, rgba(255,255,255,0.9) 99%);\
	}\
	#' + UID['main_outer'] + ' div.container {\
		height: 100%;\
		width: 100%;\
		overflow-x: auto;\
	}\
	#' + UID['main_outer'] + ' div.container ul.tabs li.tab a {\
		height: 13px;\
		background-color: rgb(241,241,241);\
	}\
	#' + UID['main_outer'] + ' div.container ul.tabs li.tab a.selected {\
		background-color: rgb(110,132,181);\
	}\
	div.' + UID['title'] + ' {\
		border:1px solid;\
		border-color:#ffffff;\
		font-weight:bold;\
		padding-top:2px;\
		padding-bottom:2px;\
		text-align:center;\
		color:#ffffff;\
		background-color:rgb(60,90,150);\
		background-image:url(\'' + urlBackgroundLogo + '\');\
		border-radius: 2px;\
		-moz-border-radus: 2px;\
	}\
	.' + UID['title'] + ' * {\
		display:inline-block !important;\
		font-style: normal !important;\
		text-decoration: none !important;\
		font-weight:bold;\
		color:#ffffff;\
		font-size: 10pt !important;\
		line-height: 10pt !important;\
		padding: 0;\
		text-shadow			: 1px 1px rgba(0,0,0,0.6) !important;\
		-moz-text-shadow	: 1px 1px rgba(0,0,0,0.6) !important;\
		-webkit-text-shadow	: 1px 1px rgba(0,0,0,0.6) !important;\
		-khtml-text-shadow	: 1px 1px rgba(0,0,0,0.6) !important;\
	}\
	div.' + UID['title_main'] + ' {\
		border:1px solid;\
		border-color:#ffffff;\
		font-weight:bold;\
		font-size:13pt;\
		padding-top:2px;\
		padding-bottom:0;\
		white-space:nowrap;\
		text-align:center;\
		color:#ffffff;\
		background-color:rgb(60,90,150);\
		background-image:url(\'' + urlBackgroundLogo + '\');\
		border-radius: 2px;\
		-moz-border-radus: 2px;\
	}\
	div.' + UID['title_main'] + ' td a {\
		cursor:pointer;\
	}\
	div.' + UID['subtitle'] + ' {\
		border:1px solid;\
		border-color:#ffffff;\
		font-weight:bold;\
		padding-top:2px;\
		padding-bottom:2px;\
		text-align:center;\
		color:#ffffff;\
		background-color: rgb(60,60,60);\
		border-radius: 2px;\
		-moz-border-radus: 2px;\
	}\
	div.' + UID['content'] + ' {\
		border:1px solid rgb(255,200,50);\
		background-color: rgb(245,245,228);\
		padding:3px;\
		border-radius: 2px;\
		color: #000;\
		-moz-border-radus: 2px;\
		-webkit-box-shadow: rgba(0,0,0,0.52) 0 0 2px;\
		-moz-box-shadow: rgba(0,0,0,0.52) 0 0 2px;\
	}\
	div.' + UID['status_ticker'] + ' {\
		border:1px solid #995;\
		background-color: rgb(239,239,224);\
		padding:2px;\
		border-radius: 2px;\
		color: #000;\
		-moz-border-radus: 2px;\
		-webkit-box-shadow: rgba(0,0,0,0.52) 0 0 2px;\
		-moz-box-shadow: rgba(0,0,0,0.52) 0 0 2px;\
	}\
	div.' + UID['status_report'] + ' {\
		height: 106px;\
		max-height: 106px;\
		overflow:auto;\
		color: #000;\
	}\
	div.' + UID['status_feedback'] + ' {\
		border: 1px solid #ddd;\
		padding-top: 5px;\
		padding-right: 5px;\
		padding-bottom: 0.5em;\
		padding-left: 5px;\
		height: 34px;\
		background-color: rgb(255,235,235);\
		text-align:left;\
		font-weight:bold;\
		border-radius: 3px;\
		color: #000;\
		-moz-border-radius: 3px;\
	}\
	table.' + UID['row_style'] + ' tr td {\
		padding: 1px 1px;\
	}\
	table.' + UID['row_style'] + ' tr td.right {\
		font-weight:bold;\
		text-align:right;\
		padding-right: 5px;\
	}\
	table.' + UID['row_style'] + ' tr:nth-child(odd) {\
		background: rgba(255, 255, 255, 0.0);\
	}\
	table.' + UID['row_style'] + ' tr:nth-child(even) {\
		background: rgba(255, 255, 255, 1.0);\
	}\
	table.' + UID['table_targets'] + ' tr td {\
		white-space:normal;\
		vertical-align:top;\
		padding-top: 5px;\
		padding-bottom: 5px;\
	}\
	table.' + UID['table'] + ' tr td,\
	table.' + UID['compact_table'] + ' tr td,\
	table.' + UID['table'] + ' tr td div {\
		border:none;\
		background:none;\
		white-space:nowrap;\
		padding: 1px 1px;\
		cursor: default;\
	}\
	table.' + UID['table'] + ' tr td {\
		padding: 1px 4px;\
	}\
	table.' + UID['table'] + ' tr td.right,\
	table.' + UID['compact_table'] + ' tr td.right,\
	table.' + UID['table'] + ' tr td.right div {\
		font-weight:bold;\
		text-align:right;\
		padding-right: 5px;\
	}\
	table.' + UID['table'] + ' tr td.left,\
	table.' + UID['compact_table'] + ' tr td.left,\
	table.' + UID['table'] + ' tr td.left div {\
		font-weight:bold;\
		text-align:left;\
		padding-right: 5px;\
	}\
	table.' + UID['table_console'] + ' tr td {\
		white-space:normal;\
		vertical-align:top;\
	}\
	td.' + UID['underline'] + ' {\
		border-bottom:1px solid #ccc;\
		background:none;\
		padding: 1px 4px 1px 4px;\
	}\
	table tr.' + UID['row_top_headers'] + ' td,\
	table tr.' + UID['row_headers'] + ' td {\
		color: white;\
		background-color: rgb(110,115,125);\
		border-right: 2px solid #eef;\
		font-weight:bold;\
		text-align:center;\
		line-height:11pt;\
	}\
	table tr.' + UID['row_top_headers'] + ' td {\
		background-color: rgb(90,95,115);\
	}\
	table tr.' + UID['row_headers'] + ' td a {\
		cursor:pointer;\
	}\
	table tr.' + UID['row_headers_left'] + ' td {\
		color: white;\
		background-color: rgb(110,115,125);\
		border-right: 2px solid #eef;\
		font-weight:bold;\
		text-align:left;\
		line-height:11pt;\
	}\
	tr.' + UID['row_marchOther'] + ' td {\
		color:#888888;\
	}\
	tr.' + UID['row_marchMine'] + ' td {\
		color:#000000;\
	}\
	tr.' + UID['row_owned'] + ' {\
	}\
	table tr td div.' + UID['info_protect'] + ' {\
		border:1px solid;\
		border-color:#ffffff;\
		font-weight:bold;\
		padding-top:2px;\
		padding-bottom:2px;\
		text-align:center;\
		color:yellow;\
		background-color:#0044a0;\
		border-radius: 2px;\
		-moz-border-radus: 2px;\
	}\
	table tr td div.' + UID['info_alerts'] + ' {\
		border:1px solid;\
		border-color:#ffffff;\
		font-weight:bold;\
		padding-top:2px;\
		padding-bottom:2px;\
		text-align:center;\
		color:white;\
		background-color:#770000;\
		border-radius: 2px;\
		-moz-border-radus: 2px;\
	}\
	input.short {\
		width:30px;\
	}\
	input.' + UID['btn_on'] + ',\
	input.' + UID['btn_off'] + ',\
	input.' + UID['bnt_red'] + ',\
	input.' + UID['bnt_green'] + ',\
	input.' + UID['bnt_blue'] + ',\
	input.' + UID['bnt_yellow'] + ',\
	input.' + UID['bnt_cyan'] + ',\
	input.' + UID['bnt_purple'] + ',\
	input.' + UID['bnt_disabled'] + ',\
	#' + UID['main_outer'] + ' input[type=button] {\
		width:130px;\
		padding-top:1px;\
		padding-bottom:1px;\
		color:white;\
		font-weight:bold;\
		border: 1px solid #333;\
		border-radius: 3px;\
		-moz-border-radius: 3px;\
		background-image: linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
		background-image: -moz-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
		background-image: -webkit-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
		-webkit-box-shadow: rgba(0,0,0,0.52) 1px 1px 1px;\
		-moz-box-shadow: rgba(0,0,0,0.52) 1px 1px 1px;\
		cursor:hand;\
		cursor:pointer;\
	}\
	#' + UID['main_outer'] + ' input[type=button] {\
		background-color: rgb(0,125,189);\
	}\
	#' + UID['main_outer'] + ' input[type=button]:hover {\
		background-color: rgb(40,150,210);\
	}\
	input.' + UID['btn_on'] + ' {\
		background-color: rgb(0,160,110) !important;\
	}\
	input.' + UID['btn_on'] + ':hover {\
		background-color: rgb(0,200,150) !important;\
	}\
	input.' + UID['btn_off'] + ' {\
		background-color: rgb(184,0,46) !important;\
	}\
	input.' + UID['btn_off'] + ':hover {\
		background-color: rgb(200,50,100) !important;\
	}\
	input.thin {\
		width: auto !important;\
		font-size: 7pt !important;\
		margin:0;\
		padding-top:0;\
		padding-top:0;\
		padding-bottom:0;\
		padding-left:2px;\
		padding-right:2px;\
	}\
	input.small {\
		margin:0;\
		padding-top:0;\
		padding-bottom:0;\
		padding-left:1px;\
		padding-right:1px;\
		font-size:10pt;\
	}\
	input.Xtrasmall {\
		margin:0;\
		padding-top:0;\
		padding-bottom:0;\
		padding-left:1px;\
		padding-right:1px;\
		font-size:7pt;\
	}\
	.confirm_button {\
		width:60px;\
		padding-top:1px;\
		padding-bottom:1px;\
		color:white;\
		font-weight:bold;\
		border: 1px solid #333;\
		border-radius: 3px;\
		-moz-border-radius: 3px;\
		background-image: linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
		background-image: -moz-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
		background-image: -webkit-linear-gradient(bottom, rgba(0,0,0,0.1) 10%, rgba(255,255,255,0.3) 60%, rgba(255,255,255,0.5) 99%);\
		-webkit-box-shadow: rgba(0,0,0,0.52) 1px 1px 1px;\
		-moz-box-shadow: rgba(0,0,0,0.52) 1px 1px 1px;\
		cursor:hand;\
		cursor:pointer;\
		background-color: rgb(0,94,189);\
	}\
	.confirm_button:hover {\
		background-color: rgb(0,125,150);\
	}\
	input.' + UID['bnt_red'] + ' {\
		background-color: rgb(184,0,46) !important;\
	}\
	input.' + UID['bnt_red'] + ':hover {\
		background-color: rgb(200,50,100) !important;\
	}\
	input.' + UID['bnt_green'] + ' {\
		background-color: rgb(0,160,110) !important;\
	}\
	input.' + UID['bnt_green'] + ':hover {\
		background-color: rgb(0,210,150) !important;\
	}\
	input.' + UID['bnt_blue'] + ' {\
		background-color: rgb(0,94,189);\
	}\
	input.' + UID['bnt_blue'] + ':hover {\
		background-color: rgb(0,125,150);\
	}\
	input.' + UID['bnt_yellow'] + ' {\
		background-color:#BFBF00 !important;\
	}\
	input.' + UID['bnt_yellow'] + ':hover {\
		background-color:#DFDF00 !important;\
	}\
	input.' + UID['bnt_cyan'] + ' {\
		background-color:#00BFBF !important;\
	}\
	input.' + UID['bnt_cyan'] + ':hover {\
		background-color:#00DFDF !important;\
	}\
	input.' + UID['bnt_purple'] + ' {\
		background-color:#BF00BF !important;\
	}\
	input.' + UID['bnt_purple'] + ':hover {\
		background-color:#DF00DF !important;\
	}\
	input.' + UID['bnt_disabled'] + ' {\
		background-color:#D8D8D8 !important;\
	}\
	input.' + UID['bnt_disabled'] + ':hover {\
		background-color:#F8F8F8F8 !important;\
	}\
	#' + UID['main_outer'] + ' input[type=text] {\
		border: 1px solid #888;\
		border-radius: 2px;\
		-moz-border-radius: 2px;\
		-webkit-box-shadow: rgba(0,0,0,0.2) 1px 1px 3px inset;\
		-moz-box-shadow: rgba(0,0,0,0.2) 1px 1px 3px inset;\
	}\
	#' + UID['main_outer'] + ' input[type=text]:active,\
	#' + UID['main_outer'] + ' input[type=text]:focus {\
		border-color: #000;\
		-webkit-box-shadow: rgba(0,0,0,0.5) 1px 1px 4px inset;\
		-moz-box-shadow: rgba(0,0,0,0.5) 1px 1px 4px inset;\
	}\
	span.' + UID['bold_red'] + ' {\
		color:#550000;\
		font-weight:bold;\
	}\
	span.' + UID['green'] + ' {\
		color:#009C1F;\
		font-weight:bold;\
	}\
	span.' + UID['blue'] + ' {\
		color:#0000AA;\
		font-weight:bold;\
	}\
	span.' + UID['red'] + ' {\
		color:#AA0000;\
		font-weight:bold;\
	}\
	hr.thin {\
		margin:0px;\
		padding:0px;\
	}\
	div#' + UID['tooltip'] + ' {\
		position: absolute;\
		max-width:185px;\
		padding: 5px 8px;\
		color:#fff;\
		font-family: "Lucida Grande","Lucida Sans Unicode","bitstream vera sans","trebuchet ms",verdana,sans-serif;\
		font-size:9pt;\
		background-color: rgb(60,90,150);\
		background-color: rgba(60,90,150,0.6);\
		border: 1px solid white;\
		border-radius: 3px;\
		-webkit-box-shadow: rgb(0,0,0) 0px 0px 5px;\
		-moz-box-shadow: rgb(0,0,0) 0px 0px 5px;\
		background-image: linear-gradient(bottom, rgba(30,30,30,0.9) 1%, rgba(30,30,30,0.5) 100%);\
		background-image: -moz-linear-gradient(bottom, rgba(30,30,30,0.9) 1%, rgba(30,30,30,0.5) 100%);\
		background-image: -webkit-linear-gradient(bottom, rgba(30,30,30,0.9) 1%, rgba(30,30,30,0.5) 100%);\
		visibility: hidden;\
		z-index: 1000;\
	}\
	';
	addStyle(css);
}

// Global variables
var Tabs = {};
var progressBarPop;
var updaterPop;
var mainPop;
var gAttScrollPos = 0;
var gMapScrollPos = 0;
var C = {};
C.attrs = {};
var DATA_MAP;

var gFormatTime = ':';
var gFormatDate = '/';
var soundRepeatTimer = null;
var soundStopTimer   = null;

function parseQuotedVars(str){
	var obj = {};
	var pattern = /\s*(.*?)\s*=\s*('|")(.*?)\2/gi;
	var match;
	while ((match = pattern.exec(str)) != null){
		obj[match[1]] = match[3];
	}
	return obj;
}

function getFlashVars (swf){
	// "use strict";
	var params = swf.innerHTML;
	var pattern = /\<\s*param\s*(.*?)\>/gi;
	var attrs={};
	var args, match, p;
	while ((match = pattern.exec(params)) != null){
		var p = parseQuotedVars(match[1]);
		if (p.name && p.name == 'flashvars')
		{
			args = decodeEntity(p.value).split('&');
			for (var i=0; i < args.length; i++)
			{
				var v = args[i].split('=');
				attrs[v[0].strip()] = v[1].strip();
			}
			break;
		}
	}
	// will have to enhance this if they change the names ...
	C.attrs.apiServer	= attrs.api_server;
	C.attrs.sessionId	= attrs.session_id;
	C.attrs.dragonHeart = attrs.dragon_heart;
	C.attrs.userId		= attrs.user_id;
	C.attrs.locale		= attrs.locale;
	USER_ID		 		= attrs.user_id;
	S3_SERVER	 		= attrs.s3_server;
	S3_SWF_PREFIX		= attrs.s3_swf_prefix;
	SERVER_ID	 		= ( /realm(\d+)\./.exec( attrs.api_server ) || ['',''] )[1];
}

// Jawz - URLs
var kForumLink = 'Forum';
var kWikiLink = 'Wiki DoA';

var mainAuthor		= 'Jawz';
var scriptName		= 'KabaListics';
var scriptUrlError	= 'http://www.mmogwiki.com/forum/index.php?f=5&t=409&rb_v=viewtopic';
var scriptTitle		= '';
var scriptSite		= '';
var scriptTimeout	= null;
var scriptLoaded	= false;
var startupCount	= 0;
var initTimeout		= null;

var kFatalSWF	= '"<B>Error initializing:</b><BR><BR>Unable to find SWF element"';
var kStartupErr	= '"Unable to start "'+ scriptName +'"<BR>"';
var kInitErr	= '"<B>Error initializing:</b><BR><BR>"';

var STARTUP_TIMER;
var citySteps;

// Main entry
function scriptStartup() {
	var i;
	progressBar.hideshow(false);
	clearTimeout(scriptTimeout);

	if (scriptLoaded){
		return;
	}

	if (++startupCount > 10) {
		dialogFatal (kFatalSWF);
		return;
	}

	try {  
		var swf = null;
		var object = document.getElementsByTagName ('object');
		if (object.length < 1) {
			scriptTimeout = setTimeout(scriptStartup, 1000);
			return;
		}
		for (i=0; i < object.length; i++) {
			if (object[i].type && object[i].type=='application/x-shockwave-flash') {
				swf = object[i];
				getFlashVars(swf);
				if (C.attrs.apiServer){
					break;
				}
			}
		}
		if (!C.attrs.apiServer) {
			scriptTimeout = setTimeout(scriptStartup, 1000);
			return;
		}  
	} catch (e) {
		scriptTimeout = setTimeout(scriptStartup, 1000);
		return;
	}

	scriptLoaded = true;

	try {
		AutoUpdater.check();
		var retry = 0;
		var startupDelay = Math.randRange(10000, 15000);
		progressBar.start({ steps:20, delay:startupDelay, title:translate('Initializing...'), stepText:translate('Loading basic data') });
		WinLog.enabled = ENABLE_WINLOG;

		Data.init({
			log		: [ [], [] ],
			// Static data and scripts settings - Will be stored in local storage and be backup in local file
			options	: {
				popUp	: {
					open : true,
					drag : true,
					x	 : 0,
					y	 : 0
				},
				background			: true,
				currentTab			: false,
				forumUrl			: 'http://',
				wikiUrl				: 'http://fr.dragonsofatlantis.wikia.com/wiki/Accueil',
				disable_wave		: !WAVE_TAB_ENABLE,
				disable_multi		: MULTI_TAB_ENABLE,
				disable_bookmark	: !BOOKMARK_TAB_ENABLE,
				disable_spies		: SPY_TAB_ENABLE,
				disable_search		: !SEARCH_TAB_ENABLE,
				disable_battle		: !BATTLE_TAB_ENABLE,
				disable_alliance	: !ALLIANCE_TAB_ENABLE,
				disable_wall		: !WALL_TAB_ENABLE,
				disable_leaderboard	: !LEADERBOARD_TAB_ENABLE,
				disable_log			: !LOG_TAB_ENABLE,
				speedups_enabled	: false,
				cheat_enabled		: true,
				utc_time			: false,
				user_language		: LANG_CODE,
				play_jobssound		: true,
				b_sound_url			: DEFAULT_BUILDING_SOUND_URL,
				t_sound_url			: DEFAULT_TRAINING_SOUND_URL,
				r_sound_url			: DEFAULT_RESEARCH_SOUND_URL,

				alliance	: {
					last_update		: '',
					alliance_update	: '',
					current_tab		: 0,
					transport_id	: 0,
					reinforce_id	: 0,
					auto_id			: 0,
					sort_list		: '0',
					sort_alliance	: '0',
					data		 : {
						transports	: {},
						resources	: {},
						units		: {}
					},
					auto		 : {
						enabled		: false,
						recall 		: false,
						max_load	: false,
						delay_min	: 30,
						delay_max	: 45,
						max_marches	: null,
						transports	: {},
						resources	: {}
					},
					recall		 :false
				},

				autoCollect	: {
					enabled		: true,
					last_time	: 0,
					delay		: 60,
					unit		: 60
				},

				autoRefresh	: {
					enabled	: false,
					delay	: 1,
					unit	: 3600
				},
				flashRefresh	: {
					enabled	: false,
					delay	: 30,
					unit	: 60
				},

				info	: {	current_tab	: 0, troop_sub_tab : 0, consumption_sel : 0	},
				jobs	: {	current_tab	: 0	},
				building	: {
					enabled		 : false,
					level_enable : [{},{},{},{},{},{},{},{},{}], // Add 1 for new outpost
					level_cap	 : [{},{},{},{},{},{},{},{},{}]  // Add 1 for new outpost
				},
				research	: {
					enabled		: false,
					res_enable	: [{},{},{},{},{},{}],
					res_cap		: [{},{},{},{},{},{}]
				},
				training	: {
					enabled		: false,
					current_tab	: 0,
					city		: [ // Add 1 line for new outpost
						{ enabled : true, units : [], cap : [] }, // main
						{ enabled : true, units : [], cap : [] }, // spectral
						{ enabled : true, units : [], cap : [] }, // ice
						{ enabled : true, units : [], cap : [] }, // swamp
						{ enabled : true, units : [], cap : [] }, // water
						{ enabled : true, units : [], cap : [] }, // stone
						{ enabled : true, units : [], cap : [] }, // fire
						{ enabled : true, units : [], cap : [] }, // wind
						{ enabled : true, units : [], cap : [] }  // forest
					],
					mode		: 'min_housing'
				},
				resurrect	: {
					enabled		: false,
					res_enable	: [{},{},{},{},{},{}],
					res_max		: [{},{},{},{},{},{}]
				},
				tJobs		: [],
				rJobs		: [],
				sJobs		: [], // resurrection jobs

				calculator	: {
					current_tab		: 0,
					ownStatus		: 1,
					attDragLevel	: 0,
					defDragLevel	: 0,
					battleTurn		: 0,
					attGeneral		: 5,
					defGeneral		: 5,
					defWall			: 1,
					data : {
						ennemyResearch	: {	RapidDeployment:0, Ballistics:0, Metallurgy:0, Medicine:0, Dragonry:0, AerialCombat:0 },
						attackItems		: [false, false, false, false],
						defenseItems	: [false, false, false, false],
						attackUnits		: {
							Porter            :{meleeDamage:1,		rangeDamage:0,		defense:10,		life:45,			speed:100,	range:0,    x:0, qty:0},
							Conscript         :{meleeDamage:10,		rangeDamage:0,		defense:10,		life:75,			speed:200,	range:0,    x:0, qty:0},
							Spy               :{meleeDamage:5,		rangeDamage:0,		defense:5,		life:10,			speed:3000,	range:0,    x:0, qty:0},
							Halberdsman       :{meleeDamage:40,		rangeDamage:0,		defense:40,		life:150,			speed:300,	range:0,    x:0, qty:0},
							Minotaur          :{meleeDamage:70,		rangeDamage:0,		defense:45,		life:225,			speed:275,	range:0,    x:0, qty:0},
							Longbowman        :{meleeDamage:5,		rangeDamage:80,		defense:30,		life:75,			speed:250,	range:1200, x:0, qty:0},
							SwiftStrikeDragon :{meleeDamage:150,	rangeDamage:0,		defense:60,		life:300,			speed:1000,	range:0,    x:0, qty:0},
							BattleDragon      :{meleeDamage:300,	rangeDamage:0,		defense:300,	life:1500,			speed:750,	range:0,    x:0, qty:0},
							ArmoredTransport  :{meleeDamage:5,		rangeDamage:0,		defense:200,	life:750,			speed:150,	range:0,    x:0, qty:0},
							Giant             :{meleeDamage:1000,	rangeDamage:0,		defense:400,	life:4000,			speed:120,	range:0,    x:0, qty:0},
							FireMirror        :{meleeDamage:20,		rangeDamage:1200,	defense:30,		life:1500,			speed:50,	range:1500, x:0, qty:0},
							PackDragon        :{meleeDamage:150,	rangeDamage:0,		defense:400,	life:850,			speed:1000,	range:0,    x:0, qty:0},
							AquaTroop         :{meleeDamage:1600,	rangeDamage:800,	defense:300,	life:3000,			speed:500,	range:600,  x:0, qty:0},
							StoneTroop        :{meleeDamage:650,	rangeDamage:0,		defense:900,	life:15000,			speed:350,	range:0,    x:0, qty:0},
							FireTroop         :{meleeDamage:500,	rangeDamage:2000,	defense:150,	life:1000,			speed:400,	range:1600, x:0, qty:0},
							WindTroop         :{meleeDamage:700,	rangeDamage:0,		defense:200,	life:2850,			speed:1350,	range:0,    x:0, qty:0},
							IceTroop          :{meleeDamage:1000,	rangeDamage:0,		defense:500,	life:3000,			speed:450,	range:0,    x:0, qty:0},
							SwampTroop        :{meleeDamage:900,	rangeDamage:800,	defense:225,	life:3500,			speed:300,	range:700,  x:0, qty:0},
							FrostGiant        :{meleeDamage:1500,	rangeDamage:0,		defense:200,	life:5500,			speed:200,	range:0,	x:0, qty:0},
							ForestTroop       :{meleeDamage:5000,	rangeDamage:0,		defense:1500,	life:7500,			speed:50,	range:0,	x:0, qty:0},
							GreatDragon       :{meleeDamage:2425,	rangeDamage:2425,	defense:2425,	life:242514,		speed:750,	range:1500, x:0, qty:0},
							WaterDragon       :{meleeDamage:2728,	rangeDamage:2425,	defense:2122,	life:242514,		speed:800,	range:1500, x:0, qty:0},
							StoneDragon       :{meleeDamage:9700,	rangeDamage:7276,	defense:14550,	life:970056,		speed:650,	range:1700, x:0, qty:0},
							FireDragon        :{meleeDamage:6398,	rangeDamage:9564,	defense:4132,	life:413216,		speed:850,	range:1800, x:0, qty:0},
							WindDragon        :{meleeDamage:10306,	rangeDamage:7275,	defense:6063,	life:606285, 		speed:1300,	range:1000, x:0, qty:0},
							IceDragon         :{meleeDamage:9700,	rangeDamage:10135,	defense:8488,	life:706285,		speed:850,	range:1500, x:0, qty:0},
							SwampDragon       :{meleeDamage:22135,	rangeDamage:0,		defense:8488,	life:813285,		speed:800,	range:0,	x:0, qty:0},
							ForestDragon      :{meleeDamage:6425,	rangeDamage:6425,	defense:2105,	life:990357,		speed:300,	range:1500,	x:0, qty:0},
							SpectralDragon    :{meleeDamage:2149700,rangeDamage:219800,	defense:100,	life:104967350000,	speed:1100,	range:1900, x:0, qty:0}
						},
						defenseUnits	: {
							Porter            :{meleeDamage:1,		rangeDamage:0,		defense:10,		life:45,			speed:100,	range:0,    x:0, qty:0},
							Conscript         :{meleeDamage:10,		rangeDamage:0,		defense:10,		life:75,			speed:200,	range:0,    x:0, qty:0},
							Spy               :{meleeDamage:5,		rangeDamage:0,		defense:5,		life:10,			speed:3000,	range:0,    x:0, qty:0},
							Halberdsman       :{meleeDamage:40,		rangeDamage:0,		defense:40,		life:150,			speed:300,	range:0,    x:0, qty:0},
							Minotaur          :{meleeDamage:70,		rangeDamage:0,		defense:45,		life:225,			speed:275,	range:0,    x:0, qty:0},
							Longbowman        :{meleeDamage:5,		rangeDamage:80,		defense:30,		life:75,			speed:250,	range:1200, x:0, qty:0},
							SwiftStrikeDragon :{meleeDamage:150,	rangeDamage:0,		defense:60,		life:300,			speed:1000,	range:0,    x:0, qty:0},
							BattleDragon      :{meleeDamage:300,	rangeDamage:0,		defense:300,	life:1500,			speed:750,	range:0,    x:0, qty:0},
							ArmoredTransport  :{meleeDamage:5,		rangeDamage:0,		defense:200,	life:750,			speed:150,	range:0,    x:0, qty:0},
							Giant             :{meleeDamage:1000,	rangeDamage:0,		defense:400,	life:4000,			speed:120,	range:0,    x:0, qty:0},
							FireMirror        :{meleeDamage:20,		rangeDamage:1200,	defense:30,		life:1500,			speed:50,	range:1500, x:0, qty:0},
							PackDragon        :{meleeDamage:150,	rangeDamage:0,		defense:400,	life:850,			speed:1000,	range:0,    x:0, qty:0},
							AquaTroop         :{meleeDamage:1600,	rangeDamage:800,	defense:300,	life:3000,			speed:500,	range:600,  x:0, qty:0},
							StoneTroop        :{meleeDamage:650,	rangeDamage:0,		defense:900,	life:15000,			speed:350,	range:0,    x:0, qty:0},
							FireTroop         :{meleeDamage:500,	rangeDamage:2000,	defense:150,	life:1000,			speed:400,	range:1600, x:0, qty:0},
							WindTroop         :{meleeDamage:700,	rangeDamage:0,		defense:200,	life:2850,			speed:1350,	range:0,    x:0, qty:0},
							IceTroop          :{meleeDamage:1000,	rangeDamage:0,		defense:500,	life:3000,			speed:450,	range:0,    x:0, qty:0},
							SwampTroop        :{meleeDamage:900,	rangeDamage:800,	defense:225,	life:3500,			speed:300,	range:700,  x:0, qty:0},
							FrostGiant        :{meleeDamage:1500,	rangeDamage:0,		defense:200,	life:5500,			speed:200,	range:0,	x:0, qty:0},
							ForestTroop       :{meleeDamage:5000,	rangeDamage:0,		defense:1500,	life:7500,			speed:50,	range:0,	x:0, qty:0},
							GreatDragon       :{meleeDamage:2425,	rangeDamage:2425,	defense:2425,	life:242514,		speed:750,	range:1500, x:0, qty:0},
							WaterDragon       :{meleeDamage:2728,	rangeDamage:2425,	defense:2122,	life:242514,		speed:800,	range:1500, x:0, qty:0},
							StoneDragon       :{meleeDamage:9700,	rangeDamage:7276,	defense:14550,	life:970056,		speed:650,	range:1700, x:0, qty:0},
							FireDragon        :{meleeDamage:6398,	rangeDamage:9564,	defense:4132,	life:413216,		speed:850,	range:1800, x:0, qty:0},
							WindDragon        :{meleeDamage:10306,	rangeDamage:7275,	defense:6063,	life:606285, 		speed:1300,	range:1000, x:0, qty:0},
							IceDragon         :{meleeDamage:9700,	rangeDamage:10135,	defense:8488,	life:706285,		speed:850,	range:1500, x:0, qty:0},
							SwampDragon       :{meleeDamage:22135,	rangeDamage:0,		defense:8488,	life:813285,		speed:800,	range:0,	x:0, qty:0},
							ForestDragon      :{meleeDamage:6425,	rangeDamage:6425,	defense:2105,	life:990357,		speed:300,	range:1500,	x:0, qty:0},
							SpectralDragon    :{meleeDamage:2149700,rangeDamage:219800,	defense:100,	life:104967350000,	speed:1100,	range:1900, x:0, qty:0}
						},
						battleLog		: []
					}
				},

				collapsed	: {
					quests	: [],
					train	: [],
					build	: []
				},
				leaderboards	: {
					current_subtab	: 0,
					current_tab		: 0,
					week_sel		: 0,
					scope_sel		: 0
				},

				map	: {
					radius		: 14,
					radius_fast	: 35,
					x			: 0,
					y			: 0
				},
				messages	: {
					last_read	: 0,
					missing		: 0
				},
				messages_tower	: [],
				messages_delete	: {
					type				: 0,
					msgGame				: true,
					msgPlayer			: true,
					msgSentinel			: true,
					msgAlliance			: true,
					rptAnthropus		: true,
					rptTransport		: true,
					rptSpy				: true,
					rptBattle			: true,
					rptReinforcement 	: true,
					rptExceptMyAttacks	: true,
					rptExceptYourAttacks: true,
					dateAll				: true
				},
				search	: {
					enabled		: false,
					current_tab	: 0,
					sort_list	: '0',
					last_update	: '',
					target		: {
						enabled	 : false,
						alliance : null,
						player	 : null,
						distance : 14,
						x		 : 999,
						y		 : 999,
						type	 : '',
						level	 : 0
					},
					grassland	: true,
					lake		: true,
					hill		: true,
					mountain	: true,
					forest		: true,
					nuage		: true,
					plain		: true,
					swamp		: true,
					min_level	: 1,
					max_level	: 10,
					unowned		: false
				},
				verboseLog	: { enabled : false },

				tower	: {
					enabled			: true,
					current_tab		: 0,
					alarm_active	: false,
					nospy			: false,
					delay			: 2,
					unit			: 60,
					play_sound		: true,
					play_length		: 17,
					sound_url		: DEFAULT_ALERT_SOUND_URL,
					repeat			: false,
					repeat_delay	: 2,
					delete_report	: true,
					delete_delay	: 1,
					delete_unit		: 3600,
					preset			: ''
				},

				attacks	: {
					enabled				: false,
					current_tab			: 0,
					choice				: kAnthropusCamp,
					delay_min			: 30,
					delay_max			: 60,
					delete_reports		: true,
					stop_on_loss		: true,
					log_attacks			: true,
					max_marches			: null,
					level_enable		: ['',     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0],
					level_distance		: ['',    15,    15,    15,    15,    15,    15,    15,    15,    15,    15,    15],
					units				: ['',	  {},    {},    {},    {},    {},    {},    {},    {},    {},    {},    {}],
					include_great_dragon: ['', false, false, false, false, false, false, false, false, false, false, false],
					except_great_dragon	: ['',    {},    {},    {},    {},    {},    {},    {},    {},    {},    {},    {}],
					clear_all_targets	: false
				},
				bookmarks	: {
					enabled			: false,
					current_tab		: 0,
					choice			: 3,
					sort			: 0,
					delay_min		: 30,
					delay_max		: 45,
					max_marches		: null,
					stop_on_loss	: true,
					delete_reports	: true,
					targets	: [],
					new_bookmark	: {
						x			: 0,
						y			: 0,
						sequence	: '',
						type		: '',
						level		: 0,
						units		: {},
						dragons		: {},
						include_great_dragon : false
					}
				},
				multiple : {
					enabled				: false,
					delay_min			: 30,
					delay_max			: 45,
					max_marches			: null,
					stop_on_loss		: true,
					delete_reports		: true,
					include_great_dragon: false,
					target	: {
						x				: 0,
						y				: 0,
						type			: '',
						level			: 0,
						ai				: 0,
						primary_units	: {},
						secondary_units	: {},
						saved_units		: {}
					}
				},
				spies	: {
					enabled			: false,
					delay_min		: 30,
					delay_max		: 45,
					max_marches		: null,
					stop_on_loss	: true,
					delete_reports	: false,
					target	: {
						x		: 0,
						y		: 0,
						type	: '',
						level	: 0,
						ai		: 0,
						units	: {}
					},
				},
				wall	: {
					current_tab		: 0,
					current_preset	: '',
					presets			: [],
					preset			: {
						name		: '',
						units		: {}
					}
				},
				waves	: {
					enabled				: false,
					current_tab			: 0,
					delay_min			: 30,
					delay_max			: 45,
					max_marches			: null,
					stop_on_loss		: true,
					delete_reports		: true,
					target	: {
						x			: 0,
						y			: 0,
						type		: '',
						level		: 0,
						ai			: 0,
						units		: {},
						dragons		: {},
						saved_units	: {},
						include_great_dragon : false
					},
					history		: []
				}
			},
			// Statistics data - Will be stored in local storage and WON'T be backup in local file
			stats	: {
				attacks	: {
					start_at		: 0,
					run_time		: 0,
					total_attacks	: 0,
					items			:{},
					resources		:{},
					by_level		:[ '',
						{total_attacks:0, items:{}, resources:{}},
						{total_attacks:0, items:{}, resources:{}},
						{total_attacks:0, items:{}, resources:{}},
						{total_attacks:0, items:{}, resources:{}},
						{total_attacks:0, items:{}, resources:{}},
						{total_attacks:0, items:{}, resources:{}},
						{total_attacks:0, items:{}, resources:{}},
						{total_attacks:0, items:{}, resources:{}},
						{total_attacks:0, items:{}, resources:{}},
						{total_attacks:0, items:{}, resources:{}},
						{total_attacks:0, items:{}, resources:{}}
					]
				},
				bookmarks	: {
					start_at		: 0,
					run_time		: 0,
					total_attacks	: 0,
					items			:{},
					resources		:{}
				},
				leaderboards	: {
					alliance	: {
						offensive_kills : [ {}, {}, {} ],
						defensive_kills	: [ {}, {}, {} ],
						power_taken		: [ {}, {}, {} ],
						power_gained	: [ {}, {}, {} ]
					},
					player	: {
						offensive_kills : [ [ {}, {}, {} ], [ {}, {}, {} ] ],
						defensive_kills	: [ [ {}, {}, {} ], [ {}, {}, {} ] ],
						power_taken		: [ [ {}, {}, {} ], [ {}, {}, {} ] ]
					},
					last_refresh : '',
				},
				multiple : {
					start_at		: 0,
					run_time		: 0,
					total_attacks	: 0,
					spoils			: {}
				},
				spies	: {
					start_at		: 0,
					run_time		: 0,
					total_attacks	: 0
				},
				waves	: {
					start_at		: 0,
					run_time		: 0,
					total_attacks	: 0,
					items			: {},
					resources		: {}
				}
			},
			// Dynamic data - Will be stored in local storage and WON'T be backup in local file
			dynamic	: {
				recall_marches	: [],
				players	: {
					memberships				: [],
					memberships_evolution	: [],
					alliances				: [],
					friends					: [],
					foes					: [],
					alliances_evolution		: []
				}
			},
			map	: {
				terrains	: {},
				players		: {},
				evolution	: {},
				alliance	: {},
				coords		: {}
			}
		});

		verboseLog ('Session parameters : '+inspectObj (C, 6, 1));
		clearAndReload ();

		// Set the default locale use
		if ( Data.options.user_language != undefined && Data.options.user_language != null && Data.options.user_language != LANG_CODE) {
			setLanguage(Data.options.user_language);
		}
		// Set all troops on all OP and blue energy transportable if cheat enabled
		if (Data.options.cheat_enabled) {
			//water_outpost_units	= cloneProps(all_trainable_units);
			//stone_outpost_units	= cloneProps(all_trainable_units);
			//fire_outpost_units	= cloneProps(all_trainable_units);
			//wind_outpost_units	= cloneProps(all_trainable_units);
			//ice_outpost_units 	= cloneProps(all_trainable_units);
			//swamp_outpost_units	= cloneProps(all_trainable_units);
			transportable_resource_types = cloneProps(all_resource_types);
		}
		//  Check basic initialization
		function stepStarting (current_step) {
			var wait_time = Math.randRange(1500, 2500);
			var error_code;
			var error_msg;
            var progress_title;
			progressBar.resume ();

			function onSuccess (message, waitTime, currentStep) {
				verboseLog ( message );
				console.log ( message );
				STARTUP_TIMER = setTimeout(stepStarting, waitTime, currentStep);
			}

			function onError (errorCode, errorMsg, message, waitTime, currentStep) {
				error_code = errorCode;
				switch (errorCode) {
					// Bad request (API version ?)
					case 400 :	error_msg = translate('<b>Bad request!</b>');
								progressBar.stop;
								progressBar.hideshow(false);
								retry = 400;
								dialogFatal('<b>' + kFatalSeedTitle + '</b><br><br>\
											<font color="#BF0000"><b> ' + errorMsg + '</b></font>\
											<br><br><div align=left>\
											' + kFatalSeedMsg + '<br><br></div>\
											<a id="' + UID['support_link'] + '" href="" target="_blank">Bugs and Known Issues</a><br>');
								return;
								break;
					// Forbidden (RefControl or --no-referrers missing ?)
					case 403 :	error_msg = translate('<b>Forbidden!</b>');
								retry = 403;
								return;
								break;
					// Rate Limit Exceeded
					case 509 :	error_msg = translate('<b>Rate Limit Exceeded</b>, too many requests!');
								waitTime = 600;
								progressBar.update ({ step:currentStep, title:progress_title, stepText:translate('Fetching') + ' ' + message +'<br>'+ error_msg + ' - ' + translate('Retry in') + ' ' + waitTime });
								progressBar.pause ();
								verboseLog(error_msg + ' - ' + translate('Retry in :') + waitTime);
								STARTUP_TIMER = setTimeout( stepStarting, waitTime * 1000, currentStep );
								return;
								break;
					default : break;
				}
				error_msg = errorMsg;
				console.log('stepStarting: '+message+', Error '+errorCode+', '+error_msg+'. Retry ' + retry);
				STARTUP_TIMER = setTimeout( stepStarting, waitTime, currentStep, ++retry);
			}

			switch ( current_step ) {
				case 1: //  Translation Initialization
					progress_title = translate('Getting basic data...');
					progressBar.update ({ step:current_step, title:progress_title, stepText:translate('Fetching Translation matrix') });
					Translation.init(function (res) {
						if (res.ok) {
							onSuccess (translate('Translation Matrix Successfully initialized'), wait_time, current_step + 1);
						} else {
							onError (res.status, res.errmsg, translate('Translation matrix'), wait_time, current_step);
						}
					});
					break;
				case 2: //  Manifest Initialization
					progress_title = translate('Getting game data...');
					progressBar.update ({ step:current_step, title:progress_title, stepText:translate('Fetching Manifest') });
					Manifest.init(function (res) {
						if (res.ok) {
							onSuccess (translate('Manifest Successfully initialized'), wait_time, current_step + 1);
						} else {
							onError (res.status, res.errmsg, translate('Manifest'), wait_time, current_step);
						}
					});
					break;
				case 3: //  Seed Initialization
					progress_title = translate('Getting game data...');
					progressBar.update ({ step:current_step, title:progress_title, stepText:translate('Fetching Seed') });
					Seed.init(function (res) {
						if (res.ok) {
							onSuccess (translate('Seed Successfully initialized'), wait_time, current_step + 1);
						} else {
							onError (res.status, res.errmsg, translate('Seed'), wait_time, current_step);
						}
					});
					break;
				case 4: // Fetch capital data
					progress_title = translate('Getting cities data...');
					var cityIdx;
					// We make sure to first start the capital
					for (var i=0; i < Seed.cityInit.length; i++) {
						if (Seed.cityInit[i].type == 'capital') {
							cityIdx = Seed.cityInit[i].id;
						}
					}
					// Set progress bar steps / city
					citySteps = Math.floor(16 / (Seed.cityInit.length-1));
					progressBar.update ({ step:current_step, title:progress_title, stepText:translate('Fetching Capital data') });
					Seed.fetchCity (cityIdx, function(res) {
						if (res.ok) {
							wait_time = Math.randRange(1500,4000);
							onSuccess (translate('Capital data successfully fetched'), wait_time, current_step + 1);
						} else {
							onError (res.status, res.errmsg, translate('Capital data'), wait_time, current_step);
						}
					});
					break;
				case 5: // Fetch outposts data
					progress_title = translate('Getting cities data...');
					for (var i=0; i < Seed.cityInit.length; i++) {
						if (Seed.cityInit[i].loaded) {
							continue;
						}
						progressBar.update ({ step:current_step+(citySteps*i), title:progress_title, stepText:translate('Fetching Outpost #')+(i+1) });
						if (Seed.cityInit[i].timer) {
							clearTimeout (Seed.cityInit[i].timer);
						}
						var current_index = i;
						var cityIdx = Seed.cityInit[i].id;
						Seed.fetchCity (cityIdx, function(res) {
							if (res.ok) {
								wait_time = Math.randRange(2500,4000);
								if (current_index == Seed.cityInit.length - 1) {
									wait_time = 1500;
								}
								onSuccess (translate('Outpost #'+(i+1))+' '+translate('data successfully fetched'), wait_time, current_step);
							} else {
								onError (res.status, res.errmsg, translate('Outpost #'+(i+1)), wait_time, current_step);
							}
						});
						return;
					}
					startScript();
					return;
					break;
			}
			// Retries Limit
			if (retry > 20) {
				clearTimeout( STARTUP_TIMER );
				progressBar.stop;
				progressBar.hideshow(false);
				if (retry < 400) { // to avoid displaying twice a dialogFatal popup
					dialogFatal('<b>' + kFatalSeedTitle + '</b><br><br>\
								<font color="#BF0000"><b> ' + (error_code || retry) + ' - ' + error_msg + '</b></font>\
								<br><br><div align=left>\
								' + kFatalSeedMsg + '<br><br></div>\
								<a id="' + UID['support_link'] + '" href="" target="_blank">Bugs and Known Issues</a><br>');
				}
				return;
			}
		}
		
		actionLog('<B>' + scriptVersion + ' ' +translate('Loading...') + '</B>');
		consoleLog('<B>' + scriptVersion + ' ' +translate('Loading...') + '</B>');
		stepStarting( 1 );

		function startScript() {

			if (updaterPop)	setTimeout (function(){updaterPop.destroy()}, 100);

			progressBar.update ({ step:19, title:translate('Completing...'), stepText:translate('Initializing map, auto-collect, ...') });
			Names.init ();
			Map.init ();
			Marches.init ();
			AutoCollect.init ();
			AutoRefresh.init ();
			Messages.init ();

			progressBar.stop;
			progressBar.hideshow(false);
			progressBarPop.destroy();

			if (Data.options.popUp==null || Data.options.popUp.x==null || Data.options.popUp.x=='' || isNaN(Data.options.popUp.x)){
				Data.options.popUp.x = 745;
				Data.options.popUp.y = 1;
			}
			var popupWidth = 540 + Math.floor(Math.random()*11);
			var popupHeight = 795 + Math.floor(Math.random()*5);

			// Random Title
			makeRandomTitle();

			// Create a new popup DIV for the main script window
			mainPop = new PopUp ('main', Data.options.popUp.x, Data.options.popUp.y, popupWidth, popupHeight, Data.options.popUp.drag, function () { tabManager.hideTab(); }); //resetScript(); });

			// Check Our Coords
			Map.checkOurCoords();

			// Create all the tabs and insert them into the main script popup DIV
			tabManager.init(mainPop.getMainDiv());

			// Display everything
			Data.options.popUp.open = true;
			if (Data.options.popUp.open) {
				mainPop.show(true);
				tabManager.showTab();
			}

			RecallMarch.init ();
			simpleSoundPlayer.init();

			window.addEventListener('unload', Data.onUnload, false);

			// Apply CSS styles (THIS MUST BE THE LAST ALWAYS)
			setStyles();

			actionLog('<B>' + scriptVersion + ' ' +translate('Loaded') + '</B>');
			consoleLog('<B>' + scriptVersion + ' ' +translate('Loaded') + '</B>');

		}
	} catch (e) {
		dialogFatal(kInitErr + e);
		logit(inspectObj (e, 8, 1));
	}
}


//*********************************** MyAjax package *********************************************
var MyAjax = {
	buildingUpgrade : function (cityId, buildingId, callback){
		var t = MyAjax;
		var p = {};
		p['user_id']		= C.attrs.userId;
		p['dragon_heart']	= C.attrs.dragonHeart;
		p['_session_id']	= C.attrs.sessionId;
		p['_method']		= 'put';
		p['version']		= api_version;
		p['timestamp']		= parseInt(serverTime());
		new MyAjaxRequest ('cities/'+ cityId +'/buildings/'+ buildingId +'.json', p, mycb, true);
		function mycb (rslt){
			//logit ("BUILD RESPONSE:\n" + inspectObj (rslt, 10, 1));
			if (rslt.ok && !rslt.dat.errors) {
				if (rslt.dat.result.success){
					Seed.jsonAddJob (rslt.dat.result.job);
				} 
			}
			else if(rslt.dat.result) {
				rslt.ok = false;
				rslt.errmsg = rslt.dat.result.errors[0];
				verboseLog('Ajax.buildingUpgrade ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
			}
			if (callback){
				callback (rslt);
			}
		}
	},

	cancelTraining : function (jobId, callback){
		var t = MyAjax;
		var p = {};
		p['user_id']	  = C.attrs.userId;
		p['job_id']		  = jobId;
		p['_method']	  = 'delete';
		p['_session_id']  = C.attrs.sessionId;
		p['timestamp']	  = parseInt(serverTime());
		p['version']	  = api_version;
		p['dragon_heart'] = C.attrs.dragonHeart;

		new MyAjaxRequest ('jobs/'+ jobId +'.json', p, mycb, true);
		function mycb (rslt){
			if (rslt.ok && !rslt.dat.errors) {
				if (rslt.dat.result.success){
					Seed.jsonDelJob (rslt.dat.result.job);
					Seed.updateCity (rslt.dat.result.city);
				} 
			}
			else if(rslt.dat.result) {
				rslt.ok = false;
				rslt.errmsg = rslt.dat.result.errors[0];
				verboseLog('Ajax.cancelTraining ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
			}
			if (callback){
				callback (rslt);
			}
		}
	},

	claimQuest : function (questName, callback){
		var p = {};
		p['user_id']		= C.attrs.userId;
		p['version']		= api_version;
		p['timestamp']		= parseInt(serverTime());
		p['quest_name']		= questName;
		p['_method']		= 'put';
		p['_session_id']	= C.attrs.sessionId;
		p['dragon_heart']	= C.attrs.dragonHeart;
		new MyAjaxRequest ('player_quests/claim.json', p, mycb, true);
		function mycb (rslt){
			if (rslt.ok && !rslt.dat.errors) {
				try {
					if (rslt.dat.quests.claimed) Seed.player.quests.claimed = cloneProps(rslt.dat.quests.claimed);
					if (rslt.dat.result.items) Seed.player.items = cloneProps(rslt.dat.result.items);
				} catch (e) {
					actionLog( translate('Quest claim Error') +': ' + e.name +' - '+ e.message);
				}
			}
			else if(rslt.dat.errors) {
				rslt.ok = false;
				rslt.errmsg = rslt.dat.errors[0];
				actionLog( translate('Quest claim Error') +': ' + rslt.errmsg);
			}
			if (callback){
				callback (rslt);
			}
		}
	},

	collectResources : function (cityId, callback){
		var p = {};
		p['user_id']		= C.attrs.userId;
		p['timestamp']		= parseInt(serverTime());
		p['_session_id']	= C.attrs.sessionId;
		p['version']		= api_version;
		p['dragon_heart']	= C.attrs.dragonHeart;
		new MyAjaxRequest ('cities/'+ cityId +'/move_resources.json', p, mycb, true);
		function mycb (rslt){
			if (rslt.ok && !rslt.dat.errors) {
				Seed.updateCity (rslt.dat.city);
			}
			else if(rslt.dat.result) {
				rslt.ok = false;
				rslt.errmsg = rslt.dat.result.errors[0];
				actionLog( translate('Auto-Collect Error') +': ' + rslt.msg);
			}
			if (callback){
				callback (rslt.ok);
			}
		}
	},

	marchRecall : function (cityId, marchId, callback){
		var t = MyAjax;
		var p = {};
		p['user_id']		= C.attrs.userId;
		p['dragon_heart']	= C.attrs.dragonHeart;
		p['_session_id']	= C.attrs.sessionId;
		p['_method']		= 'delete';
		p['version']		= api_version;
		p['timestamp']		= parseInt(serverTime());
		new MyAjaxRequest ('cities/'+ cityId +'/marches/'+ marchId +'.json', p, mycb, true);
		function mycb (rslt){
			//logit ("MARCH RESPONSE:\n" + inspectObj (rslt, 10, 1));
			if (rslt.ok && !rslt.dat.errors) {
				if (rslt.dat.result.success){
					Seed.updateCity(rslt.dat.result.city);
				} 
				else if(rslt.dat.result) {
					rslt.ok = false;
					rslt.errmsg = rslt.dat.result.errors[0];
					verboseLog('Ajax.marchRecall ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
				}
			} else if (rslt.ok && rslt.dat.errors) {
				rslt.ok = false;
				rslt.errmsg = rslt.dat.errors;
				verboseLog('Ajax.marchRecall ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
			}
			if (callback){
				callback (rslt);
			}
		}
	},

	marchBusy : 0,
	marchSend : function (cityId, x, y, generalId, units, ownerId, callback) {
		var t = MyAjax;
		
		++t.marchBusy;
	    var dragon_type = null;
		var found_in_list = false;
		var u = {}
		var mt = false;
		var sendTroops = "{";
		for (var pu in units){
			if (units[pu] > 0) {
				for (var gd=0; gd < Seed.dragonList.length && !found_in_list; gd++) {
					if (Seed.dragonList[gd].type == units[pu]) {
						found_in_list = true;
						dragon_type = units[pu];
					}
				}
				u[pu] = units[pu];
				if (mt == true ){
					sendTroops += ',';
				}
				sendTroops += '"' + pu + '":' + units[pu];
				mt = true;
			}
		}
		sendTroops += "}";

		var p = {};
		p['march[march_type]']	= 'attack';
		p['march[y]']			= y;
		p['timestamp']			= parseInt(serverTime());
		p['march[units]']		= sendTroops;
		p['march[general_id]']	= generalId;
		p['version']			= api_version;
		p['_method']			= 'post';
		p['dragon_heart']		= C.attrs.dragonHeart;
		p['user_id']			= C.attrs.userId;
		p['march[x]']			= x;
		p['_session_id']		= C.attrs.sessionId;
		// Send request
		new MyAjaxRequest ('cities/'+ cityId +'/marches.json', p, mycb, true);
		function mycb(rslt) {
			--t.marchBusy;
			if (rslt.ok && !rslt.dat.errors) {
				if (rslt.dat.result.success) {
					try {
						Seed.updateCity(rslt.dat.result.city);
						Seed.marches[rslt.dat.result.job.march_id].ownerId = ownerId;
						if (dragon_type !== null && Seed.dragons[dragon_type])
							Seed.dragons[dragon_type].is_in_city = false;
					} catch (e) {
						WinLog.write ('***********'+ e);
					}
				}
				else if(rslt.dat.result) {
					rslt.ok = false;
					rslt.errmsg = rslt.dat.result.reason;
					verboseLog('Ajax.marchSend ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
				}
			} else if (rslt.ok && rslt.dat.errors) {
				rslt.ok = false;
				rslt.errmsg = rslt.dat.errors;
				verboseLog('Ajax.marchSend ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
			} else if (rslt.status === 509){
				rslt.ok = false;
				rslt.errmsg = translate('<b>Rate Limit Exceeded</b>, too many requests!');
				verboseLog('Ajax.marchSend ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
			}
			if (callback){
				callback (rslt);
			}
		}
	},

	marchSpeedUp : function (cityId, url, jobId, callback){
		var p = {};
		p['job_id']			= jobId;
		p['version']		= api_version;
		p['_session_id']	= C.attrs.sessionId;
		p['user_id']		= C.attrs.userId;
		p['timestamp']		= parseInt(serverTime());
		p['_method']		= 'delete';
		p['dragon_heart']	= C.attrs.dragonHeart;
		new MyAjaxRequest ('player_items/'+url+'.json', p, mycb, true);
		function mycb (rslt){
			if (rslt.ok && !rslt.dat.errors) {
				try {
					if (rslt.dat.result.items) Seed.player.items = cloneProps(rslt.dat.result.items);
				} catch (e) {
					rslt.ok = false;
					rslt.errmsg = e.name +' - '+ e.message;
					actionLog( translate('March speedup Error') +': ' + e.name +' - '+ e.message);
				}
			}
			else if(rslt.dat.errors) {
				rslt.ok = false;
				rslt.errmsg = rslt.dat.errors[0];
				actionLog( translate('March speedup Error') +': ' + rslt.errmsg);
			}
			if (callback){
				callback (rslt);
			}
		}
	},

	marchSpy : function (cityId, x, y, units, ownerId, callback) {
		var t = MyAjax;
		
		++t.marchBusy;
		var u = {}
		var mt = false;
		var sendTroops = "{";
		for (var pu in units){
			if (units[pu] > 0) {
				u[pu] = units[pu];
				if (mt == true ){
					sendTroops += ',';
				}
				sendTroops += '"' + pu + '":' + units[pu];
				mt = true;
			}
		}
		sendTroops += "}";
		
		var p = {};
		p['march[march_type]']	= 'spy';
		p['march[y]']			= y;
		p['timestamp']			= parseInt(serverTime());
		p['march[units]']		= sendTroops;
		p['version']			= api_version;
		p['_method']			= 'post';
		p['dragon_heart']		= C.attrs.dragonHeart;
		p['user_id']			= C.attrs.userId;
		p['march[x]']			= x;
		p['_session_id']		= C.attrs.sessionId;
		new MyAjaxRequest ('cities/'+ cityId +'/marches.json', p, mycb, true);
		function mycb(rslt) {
			--t.marchBusy;
			if (rslt.ok && !rslt.dat.errors) {
				if (rslt.dat.result.success) {
					try {
						Seed.updateCity(rslt.dat.result.city);
						Seed.marches[rslt.dat.result.job.march_id].ownerId = ownerId;          
					} catch (e) {
						WinLog.write ('***********'+ e);
					}
				}
				else if(rslt.dat.result) {
					rslt.ok = false;
					rslt.errmsg = rslt.dat.result.reason;
					verboseLog('Ajax.marchSpy ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
				}
			} else if (rslt.ok && rslt.dat.errors) {
				rslt.ok = false;
				rslt.errmsg = rslt.dat.errors;
				verboseLog('Ajax.marchSpy ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
			} else if (rslt.status === 509){
				rslt.ok = false;
				rslt.errmsg = translate('<b>Rate Limit Exceeded</b>, too many requests!');
				verboseLog('Ajax.marchSpy ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
			}
			if (callback){
				callback (rslt);
			}
		}
	},

	messageDetail : function (id, callback){
		var p = {}
		p['user_id']		= C.attrs.userId;
		p['timestamp']		= parseInt(serverTime());
		p['_session_id']	= C.attrs.sessionId;
		p['version']		= api_version;
		p['dragon_heart']	= C.attrs.dragonHeart;
		new MyAjaxRequest ('reports/'+ id +'.json',p , mycb, false);
		function mycb (rslt){
			if (rslt.ok && !rslt.dat.errors) {
				if (callback){
					callback (rslt.dat.result);
				}
			}
			else if(rslt.dat.result) {
				rslt.ok = false;
				rslt.errmsg = rslt.dat.result.errors[0];
				verboseLog('Ajax.messageDetail ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
			}
			if (callback) {
				callback (null);
			}
		}
	},

	messageDelete : function (ids, callback){
		var p = {}
		p['user_id']		= C.attrs.userId;
		p['_method']		= 'delete';
		p['timestamp']		= parseInt(serverTime());
		p['_session_id']	= C.attrs.sessionId;
		p['ids']			= ids.join('|');
		p['dragon_heart']	= C.attrs.dragonHeart;
		p['version']		= api_version;
		new MyAjaxRequest ('reports/bulk_delete.json', p, mycb, true);
		function mycb (rslt){
			if (rslt.ok && !rslt.dat.errors) {
				rslt.ok = false;
			}
			else if(rslt.dat.result) {
				rslt.ok = false;
				rslt.errmsg = rslt.dat.result.errors[0];
				verboseLog('Ajax.messageDelete ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
			}
			if (callback){
				callback (rslt.ok);
			}
		}
	},

	messageList : function (cat, numpage, callback){
		if (!cat){
			cat = 'all';
		}
		var npage = (numpage == -1 ? 1 : numpage);
		var p = {}
		p['user_id']		= C.attrs.userId;
		p['dragon_heart']	= C.attrs.dragonHeart;
		p['count']			= 12;
		p['timestamp']		= parseInt(serverTime());
		p['_session_id']	= C.attrs.sessionId;
		p['category']		= cat;
		p['page']			= npage;
		p['version']		= api_version;
		new MyAjaxRequest ('reports.json', p, mycb, false);
		function mycb (rslt){
			if (rslt.ok && !rslt.dat.errors) {
				if (numpage == -1 && callback)
					callback (rslt.dat.result.total);
				else if (callback){
					callback (rslt.dat.result.report_notifications);
				}
			}
			else if(rslt.dat.result) {
				rslt.ok = false;
				rslt.errmsg = rslt.dat.result.errors[0];
				verboseLog('Ajax.messageList ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
			}
			if (callback) {
				callback (null);
			}
		}
	},

	researchStart : function (cityId, researchType, callback){
		var t = MyAjax;
		var p = {};
		p['user_id']		= C.attrs.userId;
		p['_method']		= 'post';
		p['timestamp']		= parseInt(serverTime());
		p['_session_id']	= C.attrs.sessionId;
		p['research[research_type]'] = researchType;
		p['dragon_heart']	= C.attrs.dragonHeart;
		p['version']		= api_version;
		new MyAjaxRequest ('cities/'+ cityId +'/researches.json', p, mycb, true);
		function mycb (rslt){
			//logit ("RESEARCH RESPONSE:\n" + inspectObj (rslt, 10, 1));
			if (rslt.ok && !rslt.dat.errors) {
				if (rslt.dat.result.success){
					Seed.updateCity (rslt.dat.result.city);
					Seed.jsonAddJob (rslt.dat.result.job);
				} 
			} 
			else if(rslt.dat.result) {
				rslt.ok = false;
				rslt.errmsg = rslt.dat.result.errors[0];
				verboseLog('Ajax.researchStart ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
			}
			if (callback){
				callback (rslt);
			}
		}
	},

	setDefenseForce : function (cityId, units, callback) {
		var t = MyAjax;
		var u = {}
		var mt = false;
		var defenseForce = "{";
		for (var pu in units){
			if (units[pu] > 0) {
				u[pu] = units[pu];
				if (mt == true ){
					defenseForce += ',';
				}
				defenseForce += '"' + pu + '":' + units[pu];
				mt = true;
			}
		}
		defenseForce += "}";
		var p = {};
		p['user_id']				= C.attrs.userId;
		p['_method']				= 'put';
		p['dragon_heart']			= C.attrs.dragonHeart;
		p['timestamp']				= parseInt(serverTime());
		p['version']				= api_version;
		p['defense_force[units]']	= defenseForce;
		p['_session_id']			= C.attrs.sessionId;
		new MyAjaxRequest ('cities/'+ cityId +'/defense_force.json', p, mycb, true);
		function mycb(rslt) {
			if (rslt.ok && !rslt.dat.errors) {
				if (rslt.dat.result.success) {
					try {
						Seed.updateCity(rslt.dat.result.city);
					} catch (e) {
						WinLog.write ('***********'+ e);
					}
				}
				else if(rslt.dat.result) {
					rslt.ok = false;
					rslt.errmsg = rslt.dat.result.reason;
					verboseLog('Ajax.setDefenseForce ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
				}
			} else if (rslt.ok && rslt.dat.errors) {
				rslt.ok = false;
				rslt.errmsg = rslt.dat.errors;
				verboseLog('Ajax.setDefenseForce ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
			} else if (rslt.status === 509){
				rslt.ok = false;
				rslt.errmsg = translate('<b>Rate Limit Exceeded</b>, too many requests!');
				verboseLog('Ajax.setDefenseForce ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
			}
			if (callback){
				callback (rslt);
			}
		}
	},

	switchDefense : function (cityId, onOff, callback){
		var p = {};
		p['user_id']		= C.attrs.userId;
		p['_session_id']	= C.attrs.sessionId;
		p['callback']		= 'function Function() {}';
		p['version']		= api_version;
		p['dragon_heart']	= C.attrs.dragonHeart;
		p['timestamp']		= parseInt(serverTime());
		p['_method']		= 'put';
		p['defended']		= onOff ? '0' : '1';
		new MyAjaxRequest ('cities/'+ cityId +'.json', p, mycb, true);
		function mycb (rslt){
			if (rslt.ok && !rslt.dat.errors) {
				actionLog( translate('switchDefense OK') );
				Seed.updateCity (rslt.dat.city);
			}
			else if(rslt.dat.result) {
				rslt.ok = false;
				rslt.errmsg = rslt.dat.result.errors[0];
				actionLog( translate('switchDefense Error') +': ' + rslt.msg);
			}
			else if(rslt.dat.errors) {
				rslt.ok = false;
				rslt.errmsg = rslt.dat.errors[0];
				actionLog( translate('switchDefense Error') +': ' + rslt.errmsg);
			}
			if (callback){
				callback (rslt);
			}
		}
	},

	TransportMarch : function (cityId, x, y, units, resources, ownerId, callback) {
		var t = MyAjax;
		
		++t.marchBusy;
		var r = {}
		var trs = false;
		var sendResources = "{";
		for (var pr in resources){
			if (resources[pr] > 0) {
				r[pr] = resources[pr];
				if (trs == true ){
					sendResources += ',';
				}
				sendResources += '"' + pr + '":' + resources[pr];
				trs = true;
			}
		}
		sendResources += "}";
		var u = {}
		var mt = false;
		var sendTroops = "{";
		for (var pu in units){
			if (units[pu] > 0) {
				u[pu] = units[pu];
				if (mt == true ){
					sendTroops += ',';
				}
				sendTroops += '"' + pu + '":' + units[pu];
				mt = true;
			}
		}
		sendTroops += "}";
		
		var p = {};
		p['march[type]']	= 'TransportMarch';
		p['march[y]']			= y;
		p['timestamp']			= parseInt(serverTime());
		p['march[resources]']	= sendResources;
		p['march[units]']		= sendTroops;
		p['version']			= api_version;
		p['_method']			= 'post';
		p['dragon_heart']		= C.attrs.dragonHeart;
		p['user_id']			= C.attrs.userId;
		p['march[x]']			= x;
		p['_session_id']		= C.attrs.sessionId;
		new MyAjaxRequest ('cities/'+ cityId +'/marches.json', p, mycb, true);
		function mycb(rslt) {
			--t.marchBusy;
			if (rslt.ok && !rslt.dat.errors) {
				if (rslt.dat.result.success) {
					try {
						Seed.updateCity(rslt.dat.result.city);
						Seed.marches[rslt.dat.result.job.march_id].ownerId = ownerId;          
					} catch (e) {
						WinLog.write ('***********'+ e);
					}
				}
				else if(rslt.dat.result) {
					rslt.ok = false;
					rslt.errmsg = rslt.dat.result.reason;
					verboseLog('Ajax.TransportMarch ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
				}
			} else if (rslt.ok && rslt.dat.errors) {
				rslt.ok = false;
				rslt.errmsg = rslt.dat.errors;
				verboseLog('Ajax.TransportMarch ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
			} else if (rslt.status === 509){
				rslt.ok = false;
				rslt.errmsg = translate('<b>Rate Limit Exceeded</b>, too many requests!');
				verboseLog('Ajax.marchSend ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
			}
			if (callback){
				callback (rslt);
			}
		}
	},

	troopTraining : function (troopType, troopQty, cityId, callback){
		var t = MyAjax;
		var p = {};
		p['user_id']		  = C.attrs.userId;
		p['_method']		  = 'post';
		p['timestamp']		  = parseInt(serverTime());
		p['_session_id']	  = C.attrs.sessionId;
		p['units[quantity]']  = troopQty;
		p['units[unit_type]'] = troopType;
		p['dragon_heart']	  = C.attrs.dragonHeart;
		p['version']		  = api_version;
		new MyAjaxRequest ('cities/'+ cityId +'/units.json', p, mycb, true);
		function mycb (rslt){
			//logit ("Troop Training Response:\n" + inspectObj (rslt, 10, 1));
			if (rslt.ok && !rslt.dat.errors) {
				if (rslt.dat.result.success){
					Seed.updateCity (rslt.dat.result.city);
					Seed.jsonAddJob (rslt.dat.result.job);
				} else if (rslt.dat.result) {
					rslt.ok = false;
					rslt.errmsg = rslt.dat.result.errors[0];
					verboseLog('Ajax.troopTraining ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
				}
			}
			else if (rslt.dat.result) {
				rslt.ok = false;
				rslt.errmsg = rslt.dat.result.errors[0];
				verboseLog('Ajax.troopTraining ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
			}
			if (callback){
				callback (rslt);
			}
		}
	},

	troopReviving : function (troopType, troopQty, cityId, callback){
		var t = MyAjax;
		var p = {};
		p['_session_id']	  = C.attrs.sessionId;
		p['units[quantity]']  = troopQty;
		p['version']		  = api_version;
		p['_method']		  = 'post';
		p['user_id']		  = C.attrs.userId;
		p['units[unit_type]'] = troopType;
		p['timestamp']		  = parseInt(serverTime());
		p['dragon_heart']	  = C.attrs.dragonHeart;
		new MyAjaxRequest ('cities/'+ cityId +'/units/resurrect.json', p, mycb, true);
		function mycb (rslt){
			if (rslt.ok && !rslt.dat.errors) {
				if (rslt.dat.result.success){
					Seed.jsonAddJob (rslt.dat.result.job);
				} 
			}
			else if(rslt.dat.result) {
				rslt.ok = false;
				rslt.errmsg = rslt.dat.result.errors[0];
				verboseLog('Ajax.troopReviving ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
			}
			if (callback){
				callback (rslt);
			}
		}
	}
};
//*********************************** MyAjax package *********************************************


//*********************************** Auto-collect package *********************************************
var AutoCollect = {
	init : function (){
		var t = AutoCollect;
		t.setEnable (Data.options.autoCollect.enabled);
	},
	
	setEnable : function (onOff){
		var t = AutoCollect;
		clearTimeout (t.timer);
		Data.options.autoCollect.enabled = onOff;
		if (onOff){
			var time = (Data.options.autoCollect.delay*Data.options.autoCollect.unit) - serverTime() + Data.options.autoCollect.last_time;
			if (time <= 0){
				t.doit ();
			} else {
				t.timer = setTimeout (t.doit, time*1000);
			}
		}
	},
	
	doit : function (){
		var t = AutoCollect;
		Data.options.autoCollect.last_time = serverTime();
		for (var out=2; out<Seed.cities.length; ++out){  // Jawz - Start at 2 (0=Capital, 1=Spectral waiting to know if we can collect from spectral)
			collect (out, out*30000);
		}
		var delay_time = ((Data.options.autoCollect.delay * Data.options.autoCollect.unit) + (Math.random()*120))*1000;
		t.timer = setTimeout (t.doit, delay_time);

		function collect (cityIdx, delay){
			setTimeout (function(){
				MyAjax.collectResources (Seed.cities[cityIdx].id);
				actionLog (translate('Collected resources at outpost')+ ' <B>#'+ cityIdx +'</B>');
			}, delay);
		}
	}
};
//*********************************** Auto-collect package *********************************************


//*********************************** Falsh auto-refresh package *********************************************
var AutoRefresh = {
	timer			: null,
	current_mouse	: [0,0],
	last_mouse		: [0,0],
	last_time		: 0,

	init : function () {
		var t = AutoRefresh;
		t.setEnable (Data.options.flashRefresh.enabled);
	},
	setEnable : function (onOff) {
		var t = AutoRefresh;
		Data.options.flashRefresh.enabled = onOff;
		if (Data.options.flashRefresh.enabled){
			t.last_time = parseInt(serverTime());
			window.addEventListener('mousemove', t.onMouseMove, false);
			t.onTimeout();
		} else {
			window.removeEventListener('mousemove', t.onMouseMove, false);
		}
	},
	onMouseMove : function (event) {
		AutoRefresh.current_mouse = [event.clientX, event.clientY];
	},
	onTimeout : function () {
		var t = AutoRefresh;
		clearTimeout(t.timer);
		if (t.current_mouse.join() !== t.last_mouse.join()) {
			t.last_time = parseInt(serverTime());
			t.last_mouse = [].concat(t.current_mouse);
		}
		if (parseInt(serverTime()) - t.last_time > Data.options.flashRefresh.delay*Data.options.flashRefresh.unit) {
			t.last_time = parseInt(serverTime());
			verboseLog ('Flash refresh');
			setTimeout(toggleFlash,500);
			setTimeout(toggleFlash,5000);
		}
		if (Data.options.flashRefresh.enabled) {
			t.timer = setTimeout(t.onTimeout, 30000);
		}
	}
}
//*********************************** Falsh auto-refresh package *********************************************


//*********************************** Buildings package *********************************************
var Buildings = {
	getList : function (cityIdx, type) {
		var ret = [];
		for (var i=0; i < Seed.cities[cityIdx].buildings.length; i++) {
			if (Seed.cities[cityIdx].buildings[i].type === type){
				ret.push (Seed.cities[cityIdx].buildings[i]);
			}
		}
		return ret;
	},
	getLevel : function (cityIdx, type){
		var build_list = Buildings.getList(cityIdx, type );
		if (build_list.length < 1){
			return {min:0, max:0};
		}
		build_list.sort(function(a,b){return a.level - b.level;});
		return {min:build_list[0].level, max:build_list[build_list.length-1].level};
	},
	getById : function (cityIdx, bid){
		for (var i=0; i < Seed.cities[cityIdx].buildings.length; i++){
			if (Seed.cities[cityIdx].buildings[i].id == bid){
				return (Seed.cities[cityIdx].buildings[i]);
			}
		}
		return null;
	},
	setLevel : function (city_id, bid, level){
		var cityIdx = Seed.cityIdx[city_id];
		for (var i=0; i < Seed.cities[cityIdx].buildings.length; i++){
			if (Seed.cities[cityIdx].buildings[i].id == bid){
				Seed.cities[cityIdx].buildings[i].level = level;
			}
		}
	}
};
//*********************************** Buildings package *********************************************


//*********************************** Data package *********************************************
var Data = {
	log			: [ [], [] ],
	defaults	: {},

	init : function (obj) {
		try {
			//Saves defaults properties
			Data.defaults.mergeWith( obj || {} );
			for ( var item_name in obj ) {
				// Checks if the object is already defined in the Data Object
				if ( typeof (Data[item_name]) == 'undefined' ) {
					//  Assign default object properties, if defined, otherwise an empty object
					Data[item_name] = typeof(obj[item_name]) != 'undefined' ? cloneProps(obj[item_name]) : {};
				}
				// Load the data stored, of the current item from localStorage
				var stored_object = Data.getObject( item_name );
				// Clean removed values from stored object ( max depth 2 )
				if (stored_object != null && typeof (stored_object) == 'object') {
					verboseLog ('Clean Removed Vars from : [ ' + name + ' ]');
					stored_object.cleanRemoved (Data[item_name], 1);
				}
				// Check if the default object is really an object
				if (Data[item_name] !== null && typeof (Data[item_name]) == 'object' ) {
					// Assign the properties of stored objeto into the default object, overwriting the values
					Data[item_name].mergeWith(stored_object);
				}
				else { //if ( stored_object !== '' )
					Data[item_name] = stored_object;
				}
			}
		} catch (e) {
			alert ('This browser does not support LocalStorage\n\n'+e);
			return false;
		}
	},
	
	clearStorage : function (keep_map) {
		if (keep_map) {
			var temp_storage = {};
			var keys = getKeys (Data.defaults);
			for (var i=0; i < keys.length; i++) {
				if ( /(map|dynamic)/i.test( keys[i] ) ) {
					var item_name = keys[i];
					temp_storage[item_name] = cloneProps(Data[item_name]);
				}
			}
		}
		localStorage.clear();
		for ( var item_name in Data.defaults ) {
			Data[item_name] = cloneProps(Data.defaults[item_name]);
		}
		if (keep_map) {
			var keys = getKeys (temp_storage);
			for (var i=0; i < keys.length; i++) {
				var item_name = keys[i];
				Data[item_name] = cloneProps(temp_storage[item_name]);
				Data.setObject ( item_name, Data[item_name] );
			}
		}
		actionLog('localStorage Deleted!');
	},

	getObject : function (key) {
		var item = localStorage.getItem( [SERVER_ID, USER_ID, key].join('_') );
		//logit('load setting ['+SERVER_ID+', '+USER_ID+', '+key+' = '+item);
		return ( item || '' ).charAt(0) === '{' ? JSON.parse( item || '{}' ) : eval( item );
	},

	setObject : function (key, value) {
		if (key == 'log') return;
		try {
			//logit('save setting ['+SERVER_ID+', '+USER_ID+', '+key+' = '+JSON.stringify( value ) );
			localStorage.setItem( [SERVER_ID, USER_ID, key].join('_'), JSON.stringify( value ) );
		} catch(e){
			if ( e === QUOTA_EXCEEDED_ERR )	{
				logit (translate('LocalStorage') + ' : ' + translate('Quota exceeded') + '! ' + translate('Please, delete the cache and persistent data in your browser'));
			}
		}
	},

	onUnload : function () {
		verboseLog('Save Data in localStorage');
		var keys = getKeys (Data.defaults);
		for (var i=0; i < keys.length; i++) {
			var item_name = keys[i];
			Data.setObject ( item_name, Data[item_name] );
		}
	},

	setDefaultValues : function(tab) {
		switch (tab) {
			case 'alliance'		: setAllianceDefaults (); break;
			case 'attacks'		: setAttacksDefaults (); break;
			case 'bookmark'		: setBookmarksDefaults (); break;
			case 'jobs'			: setJobsDefaults (); break;
			case 'leaderboard'	: setLeaderboardDefaults (); break;
			case 'multiple'		: setMultipleDefaults (); break;
			case 'search'		: setSearchDefaults (); break;
			case 'spies'		: setSpiesDefaults (); break;
			case 'waves'		: setWavesDefaults (); break;
			case 'all'			: setAllianceDefaults ();
								  setAttacksDefaults ();
								  setBookmarksDefaults ();
								  setJobsDefaults ();
								  setLeaderboardDefaults ();
								  setMultipleDefaults ();
								  setSearchDefaults ();
								  setSpiesDefaults ();
								  setWavesDefaults ();
						  break;
			default : break;
		}
		function setAllianceDefaults () {
			if (Seed.cities[CAPITAL_ID].figures.marches.maximum &&
				(!Data.options.alliance.auto.max_marches || Data.options.alliance.auto.max_marches == null || Data.options.alliance.auto.max_marches == undefined))
				Data.options.alliance.auto.max_marches = parseIntZero(Seed.cities[CAPITAL_ID].figures.marches.maximum);
		}
		function setAttacksDefaults () {
			for (var x=1; x<=11; x++) {
				if (!Data.options.attacks.units[x])
					Data.options.attacks.units[x] = {};
				// check if troops have been entered. Is not, set to default
				var exists = false;
				for (var j=0; j<attack_unit_types.length && !exists; j++) {
					if (Data.options.attacks.units[x][attack_unit_types[j]] && Data.options.attacks.units[x][attack_unit_types[j]] > 0)
						exists = true;
				}
				if (!exists) {
					for (var j=0; j<attack_unit_types.length; j++) {
						var num = 0
						switch (x) {
							case 1: 
								switch (attack_unit_types[j]) {
									case 'Longbowman': num = 110; break;
									case 'ArmoredTransport': num = 25; break;
									default: num = 0; break;
								}
								break;
							case 2:
								switch (attack_unit_types[j]) {
									case 'Longbowman': num = 550; break;
									case 'ArmoredTransport': num = 50; break;
									default: num = 0; break;
								}
								break;
							case 3:
								switch (attack_unit_types[j]) {
									case 'Longbowman': num = 1050; break;
									case 'ArmoredTransport': num = 80; break;
									default: num = 0; break;
								}
								break;
							case 4:
								switch (attack_unit_types[j]) {
									case 'Longbowman': num = 2100; break;
									case 'ArmoredTransport': num = 100; break;
									default: num = 0; break;
								}
								break;
							case 5:
								switch (attack_unit_types[j]) {
									case 'Longbowman': num = 5500; break;
									case 'ArmoredTransport': num = 130; break;
									default: num = 0; break;
								}
								break;
							case 6:
								switch (attack_unit_types[j]) {
									case 'Longbowman': num = 11000; break;
									case 'ArmoredTransport': num = 150; break;
									default: num = 0; break;
								}
								break;
							case 7:
								switch (attack_unit_types[j]) {
									case 'Longbowman': num = 30000; break;
									case 'ArmoredTransport': num = 1000; break;
									default: num = 0; break;
								}
								break;
							case 8:
								switch (attack_unit_types[j]) {
									case 'FireTroop': num = 2500; break;
									case 'ArmoredTransport': num = 1000; break;
									default: num = 0; break;
								}
								break;
							case 9:
								switch (attack_unit_types[j]) {
									case 'FireTroop': num = 3000; break;
									case 'ArmoredTransport': num = 1000; break;
									default: num = 0; break;
								}
								break;
							case 10:
								switch (attack_unit_types[j]) {
									case 'FireTroop': num = 4000; break;
									case 'ArmoredTransport': num = 1000; break;
									default: num = 0; break;
								}
								break;
							default: num = 0; break;
						}
						if (num > 0) {
							Data.options.attacks.units[x][attack_unit_types[j]] = num;
						}
					}
				}
			}
			for (var x=1; x<=11; x++) {
				if (!Data.options.attacks.except_great_dragon[x])
					Data.options.attacks.except_great_dragon[x] = {};
				if (Data.options.attacks.except_great_dragon[x] == null || Data.options.attacks.except_great_dragon[x] == undefined) {
					for (var j=0; j<Seed.dragonList.length; j++) {
						var dragon = Seed.dragonList[j];
						Data.options.attacks.except_great_dragon[x][dragon.type] = false;
					}
				}
			}
			if (Seed.cities[CAPITAL_ID].figures.marches.maximum &&
				(!Data.options.attacks.max_marches || Data.options.attacks.max_marches == null || Data.options.attacks.max_marches == undefined)){
				Data.options.attacks.max_marches = Seed.cities[CAPITAL_ID].figures.marches.maximum;
			}
		}
		function setBookmarksDefaults () {
			if (!Data.options.bookmarks.new_bookmark.dragons)
				Data.options.bookmarks.new_bookmark.dragons = {};
			if (Data.options.bookmarks.new_bookmark.dragons == null || Data.options.bookmarks.new_bookmark.dragons == undefined) {
				for (var j=0; j<Seed.dragonList.length; j++) {
					var dragon = Seed.dragonList[j];
					Data.options.bookmarks.new_bookmark.dragons[dragon.type] = false;
				}
			}
			if (Seed.cities[CAPITAL_ID].figures.marches.maximum &&
				(!Data.options.bookmarks.max_marches || Data.options.bookmarks.max_marches == null || Data.options.bookmarks.max_marches == undefined))
				Data.options.bookmarks.max_marches = parseIntZero(Seed.cities[CAPITAL_ID].figures.marches.maximum);
		}
		function setJobsDefaults () {
			// Training initialization
			for (var cityIdx=0; cityIdx < Seed.cities.length; ++cityIdx){
				if (cityIdx != SPECTRAL_OUTPOST_ID) {
					if (!Data.options.training.city[cityIdx]){
						Data.options.training.city[cityIdx] = {};
					}
					if (!Data.options.training.city[cityIdx].units)
						Data.options.training.city[cityIdx].units = [];

					var initDefault_units;
					switch (cityIdx) {
						case CAPITAL_ID			 : initDefault_units = capital_units; break;
						case WATER_OUTPOST_ID	 : initDefault_units = water_outpost_units; break;
						case STONE_OUTPOST_ID	 : initDefault_units = stone_outpost_units; break;
						case FIRE_OUTPOST_ID	 : initDefault_units = fire_outpost_units; break;
						case WIND_OUTPOST_ID	 : initDefault_units = wind_outpost_units; break;
						case ICE_OUTPOST_ID		 : initDefault_units = ice_outpost_units; break;
						case SWAMP_OUTPOST_ID	 : initDefault_units = swamp_outpost_units; break;
						case FOREST_OUTPOST_ID	 : initDefault_units = forest_outpost_units; break;
					}
					var exists = false;
					for (var tt=0; tt < initDefault_units.length && !exists; tt++) {
						if (Data.options.training.city[cityIdx].units[tt] && Data.options.training.city[cityIdx].units[tt] > 0)
							exists = true;
					}
					if (!exists) {
						for (var tt=0; tt < initDefault_units.length; tt++){
							Data.options.training.city[cityIdx].units[tt] = 0;
							// User defined initialization for units
							// Just change the troops number and activate the lines to have always the same settings when cleaning the cache

							/* -Remove this line to activate-
							switch (initDefault_units[tt]) {
								case kPorter			: num = 0; break;
								case kConscript			: num = 1000; break;
								case kSpy				: num = 2000; break;
								case kHalberdsman		: num = 3000; break;
								case kMinotaur			: num = 4000; break;
								case kLongbowman		: num = 2500; break;
								case kSwiftStrikeDragon	: num = 2000; break;
								case kBattleDragon		: num = 1150; break;
								case kArmoredTransport	: num = 2000; break;
								case kGiant				: num = 1125; break;
								case kFireMirror		:
									switch (cityIdx) {
										case CAPITAL_ID : num = 1000; break;
										default : num = 0; break;
									}
									break;
								case kAquaTroop			: num = 1000; break;
								case kStoneTroop		: num = 1250; break;
								case kFireTroop			: num = 900;  break;
								case kWindTroop			: num = 1600; break;
								case kIceTroop			: num = 1400; break;
								case kSwampTroop		: num = 2000; break;
								case kFrostGiant		: num = 1125; break;
								case kForestTroop		: num = 700; break;
								default : num = 0; break;
							}
							if (num > 0) {
								Data.options.training.city[cityIdx].units[tt] = num;
							}
							// */

						}
					}
					if (!Data.options.training.city[cityIdx].cap)
						Data.options.training.city[cityIdx].cap = [];

					var exists = false;
					for (var tt=0; tt < all_trainable_units.length && !exists; tt++) {
						if (Data.options.training.city[cityIdx].cap[tt] && Data.options.training.city[cityIdx].cap[tt] > 0)
							exists = true;
					}
					if (!exists) {
						for (var tt=0; tt < all_trainable_units.length; tt++){
							Data.options.training.city[cityIdx].cap[tt] = 0;

							// User defined cap initialization
							// Just change the troops cap and activate the lines
							// to have always the same cap settings when cleaning the cache

							/* -Remove this line to activate-
							switch (all_trainable_units[tt]) {
								case kPorter			: num = 10; break;
								case kConscript			: num = 1000000; break;
								case kSpy				: num = 1000000; break;
								case kHalberdsman		: num = 1000000; break;
								case kMinotaur			: num = 1000000; break;
								case kLongbowman		: num = 1000000; break;
								case kSwiftStrikeDragon	: num = 300000; break;
								case kBattleDragon		: num = 300000; break;
								case kArmoredTransport	: num = 1000000; break;
								case kGiant				: num = 150000; break;
								case kFireMirror		: num = 100000; break;
								case kAquaTroop			: num = 500000; break;
								case kStoneTroop		: num = 0; break;
								case kFireTroop			: num = 0; break;
								case kWindTroop			: num = 500000; break;
								case kIceTroop			: num = 300000; break;
								case kSwampTroop		: num = 300000; break;
								case kFrostGiant		: num = 100000; break;
								case kForestTroop		: num = 100000; break;
								default : num = 0; break;
							}
							Data.options.training.city[cityIdx].cap[tt] = num;
							// */
						}
					}
				}
			}
			// Build initilization
			for (var cityIdx=0; cityIdx < Seed.cities.length; ++cityIdx) {
				if (!Data.options.building.level_enable[cityIdx]){
					Data.options.building.level_enable[cityIdx] = {};
				}
				if (!Data.options.building.level_cap[cityIdx]){
					Data.options.building.level_cap[cityIdx] = {};
				}
			}
			// Research initialization
			for (var cityIdx=0; cityIdx < Seed.cities.length; ++cityIdx) {
				if (!Data.options.research.res_enable[cityIdx]) {
					Data.options.research.res_enable[cityIdx] = {};
				}
				if (!Data.options.research.res_cap[cityIdx]) {
					Data.options.research.res_cap[cityIdx] = {};
				}
			}
			// Resurrection initialization
			for (var cityIdx=0; cityIdx < Seed.cities.length; ++cityIdx){
				if (!Data.options.resurrect.res_enable[cityIdx]){
					Data.options.resurrect.res_enable[cityIdx] = {};
				}
				if (!Data.options.resurrect.res_max[cityIdx]) {
					Data.options.resurrect.res_max[cityIdx] = {};
				}
				for (tt=0; tt < all_unit_types.length; tt++){
					if (!Data.options.resurrect.res_max[cityIdx][all_unit_types[tt]]) {
						Data.options.resurrect.res_max[cityIdx][all_unit_types[tt]] = 0;
					}
				}
			}
		}
		function setLeaderboardDefaults () {
			if (!Data.options.leaderboards.week_sel || Data.options.leaderboards.week_sel == null || Data.options.leaderboards.week_sel == undefined)
				Data.options.leaderboards.week_sel = 0;
			if (!Data.options.leaderboards.scope_sel || Data.options.leaderboards.scope_sel == null || Data.options.leaderboards.scope_sel == undefined)
				Data.options.leaderboards.scope_sel = 0;
		}
		function setMultipleDefaults () {
			if (Seed.cities[CAPITAL_ID].figures.marches.maximum &&
				(!Data.options.multiple.max_marches || Data.options.multiple.max_marches == null || Data.options.multiple.max_marches == undefined))
				Data.options.multiple.max_marches = parseIntZero(Seed.cities[CAPITAL_ID].figures.marches.maximum);
		}
		function setSearchDefaults () {
			if (!Data.options.search.target.x || Data.options.search.target.x == 999) {
				Data.options.search.target.x = Seed.cities[CAPITAL_ID].x;
				Data.options.search.target.y = Seed.cities[CAPITAL_ID].y;
			}
			if (!Data.options.search.target.alliance || Data.options.search.target.alliance == null || Data.options.search.target.alliance == undefined)
				Data.options.search.target.alliance = '*';
			if (!Data.options.search.target.player || Data.options.search.target.player == null || Data.options.search.target.player == undefined)
				Data.options.search.target.player = '*';
			if (!Data.options.search.target.distance || Data.options.search.target.distance == null || Data.options.search.target.distance == undefined)
				Data.options.search.target.distance = 14;
			if (!Data.options.search.sort_list || Data.options.search.sort_list == null || Data.options.search.sort_list == undefined)
				Data.options.search.sort_list = '0';
			if (!Data.options.search.min_level || Data.options.search.min_level == null || Data.options.search.min_level == undefined)
				Data.options.search.min_level = 1;
			if (!Data.options.search.max_level || Data.options.search.max_level == null || Data.options.search.max_level == undefined)
				Data.options.search.max_level = 10;
		}
		function setSpiesDefaults () {
			if (Seed.cities[CAPITAL_ID].figures.marches.maximum &&
				(!Data.options.spies.max_marches || Data.options.spies.max_marches == null || Data.options.spies.max_marches == undefined))
				Data.options.spies.max_marches = parseIntZero(Seed.cities[CAPITAL_ID].figures.marches.maximum);
		}
		function setWavesDefaults () {
			if (!Data.options.waves.target.dragons)
				Data.options.waves.target.dragons = {};
			if (Data.options.waves.target.dragons == null || Data.options.waves.target.dragons == undefined) {
				for (var j=0; j<Seed.dragonList.length; j++) {
					var dragon = Seed.dragonList[j];
					Data.options.waves.target.dragons[dragon.type] = false;
				}
			}
			if (Seed.cities[CAPITAL_ID].figures.marches.maximum &&
				(!Data.options.waves.max_marches || Data.options.waves.max_marches == null || Data.options.waves.max_marches == undefined))
				Data.options.waves.max_marches = Seed.cities[CAPITAL_ID].figures.marches.maximum;
		}
	}
};
//*********************************** Data package *********************************************


//*********************************** Manifest package *********************************************
var Manifest = {
	data : {},
	
	init : function (callback) {
		Manifest.fetchManifest(function (res) {
			if (res.ok) {
				verboseLog(translate('Manifest was Successfully requested from the server'));
			} else {
				verboseLog('fetchManifest ' + translate('was returned with a status of') + ' ' + res.ok + ' - ' + res.errmsg);
			}
			if (callback){
				callback(res);
			}
		});
	},
	
	fetchManifest : function (callback) {
		var now = new Date().getTime() / 1000;
		var params = {};
		params['user_id'] = C.attrs.userId;
		params['timestamp'] = parseInt(serverTime());
		params['_session_id'] = C.attrs.sessionId;
		params['version'] = api_version;
		params['dragon_heart'] = C.attrs.dragonHeart;
		new MyAjaxRequest ('manifest.json', params, function (res) {
			if (res.ok && !res.dat.errors) {
				Manifest.data = res.dat;
				try {
					Manifest.updateManifest();
				} catch (e) {
					res.ok = false;
					res.errmsg = 'fetchManifest when calling updateManifest returned this error: ' + e.toString();
				}
			} else if (res.ok && res.dat.errors) {
				res.ok = false;
				res.errmsg = res.dat.errors;
			}
			
			if (callback){
				callback(res);
			}
		}, false);
	},
	
	buildings : {
		byCityType : function (cityType, buildable, order) {
			var buildings = Manifest.data.buildings;
			var i, j, res = [];
			if (!buildable) {
				buildable = 'all';
			}
			if (!cityType) {
				cityType = 'all';
			}
			if (buildings.length > 0) {
				for (i = 0; i < buildings.length; i = i + 1) {
					if (buildings[i].buildable === buildable || buildable.toLowerCase() === 'all') {
						if (buildings[i].city_type.length > 0) {
							for (j = 0; j < buildings[i].city_type.length; j = j + 1) {
								if (buildings[i].city_type[j] === cityType.toLowerCase() || cityType.toLowerCase() === 'all') {
									res[res.length] = buildings[i];
									break;
								}
							}
						}
					}
				}
			}
			if (order) {
				res = Manifest.buildings.sortBy(res, order);
			}
			return res;
		},
		
		byLocation : function (location, buildable, order) {
			var buildings = Manifest.data.buildings;
			var i, res = [];
			if (!buildable) {
				buildable = 'all';
			}
			if (!location) {
				cityType = 'all';
			}
			if (buildings.length > 0) {
				for (i = 0; i < buildings.length; i = i + 1) {
					if (buildings[i].buildable === buildable || buildable.toLowerCase() === 'all') {
						if (buildings[i].location === location.toLowerCase() || location.toLowerCase() === 'all') {
							res[res.length] = buildings[i];
						}
					}
				}
			}
			if (order) {
				res = Manifest.buildings.sortBy(res, order);
			}
			return res;
		},

		sortBy : function (data, order) {
			var orderBy;
			if (!order) {
				order = {alphabetical: 'asc'};
			}
			for (orderBy in order) {
				switch (orderBy) {
				case 'alphabetical' :
					orderAlphabetical(order[orderBy]);
					break;
				case 'buildable' :
					orderBuildable(order[orderBy]);
					break;
				case 'location' :
					orderLocation(order[orderBy]);
					break;
				}
			}
			return data;

			function orderAlphabetical(order) {
				if (order.toLowerCase() === 'asc') {
					data.sort(function (a, b) {
						var typeA = a.type.toLowerCase(), typeB = b.type.toLowerCase();
						if (typeA < typeB) {return -1}
						if (typeA > typeB) {return 1}
						return 0;
					});
				} else if (order.toLowerCase() === 'desc') {
					data.sort(function (a, b) {
						var typeA = a.type.toLowerCase(), typeB = b.type.toLowerCase();
						if (typeA > typeB) {return -1}
						if (typeA < typeB) {return 1}
						return 0;
					});
				}
			}

			function orderBuildable(order) {
				if (order === true) {
					data.sort(function (a, b) {
						var buildableA = a.buildable, buildableB = b.buildable;
						if (buildableA < buildableB) {return -1}
						if (buildableA > buildableB) {return 1}
						return 0;
					});
				} else if (order === false) {
					data.sort(function (a, b) {
						var buildableA = a.buildable, buildableB = b.buildable;
						if (buildableA > buildableB) {return -1}
						if (buildableA < buildableB) {return 1}
						return 0;
					});
				}
			}

			function orderLocation(order) {
				if (order.toLowerCase() === 'city') {
					data.sort(function (a, b) {
						var locationA = a.location.toLowerCase(), locationB = b.location.toLowerCase();
						if (locationA < locationB) {return -1}
						if (locationA > locationB) {return 1}
						return 0;
					});
				} else if (order.toLowerCase() === 'field') {
					data.sort(function (a, b) {
						var locationA = a.location.toLowerCase(), locationB = b.location.toLowerCase();
						if (locationA > locationB) {return -1}
						if (locationA < locationB) {return 1}
						return 0;
					});
				}
			}
		},
	},

	building : function (type) { 
		console.log('Manifest.building');
		var b;

		if (type) {
			for (b = 0; b < Manifest.data.buildings.length; b = b + 1) {
			}
		} else {
			// Return an error message because no type was specificed
		}
	},

	updateManifest : function () {
		var data, i, j;
		// Initialise levels for each building & Save requirements and Stats
		data = Manifest.data.buildings;
		for (i=0; i < data.length; i++) {
			if (!Seed.requirements.building[data[i].type]) {
				Seed.requirements.building[data[i].type] = {};
			}
			if (!Seed.requirements.building[data[i].type].level) {
				Seed.requirements.building[data[i].type].level = [];
			}
			if (!Seed.stats.building[data[i].type]) {
				Seed.stats.building[data[i].type] = {};
			}
			if (!Seed.stats.building[data[i].type].level) {
				Seed.stats.building[data[i].type].level = [];
			}
			for (j=0; j < data[i].levels.length; j++) {
				Seed.requirements.building[data[i].type].level[data[i].levels[j].level] = data[i].levels[j].requirements;
				Seed.stats.building[data[i].type].level[data[i].levels[j].level] = {};
				Seed.stats.building[data[i].type].level[data[i].levels[j].level].time = data[i].levels[j].time;
			}
			if (data[i].capacity && data[i].capacity != null && data[i].capacity != undefined) {
				for (var k in data[i].capacity) {
					if (k != "lignore me!") {
						var lvl = k.substring(1);
						Seed.stats.building[data[i].type].level[lvl].capacity = data[i].capacity[k];
					}
				}
			}
		}

		// Initialise levels for each research & Save requirements and Stats
		data = Manifest.data.research;
		for (i=0; i < data.length; i++) {
			if (!Seed.requirements.research[data[i].type]) {
				Seed.requirements.research[data[i].type] = {};
			}
			if (!Seed.requirements.research[data[i].type].level) {
				Seed.requirements.research[data[i].type].level = [];
			}
			if (!Seed.stats.research[data[i].type]) {
				Seed.stats.research[data[i].type] = {};
			}
			if (!Seed.stats.research[data[i].type].level) {
				Seed.stats.research[data[i].type].level = [];
			}
			for (j=0; j < data[i].levels.length; j++) {
				Seed.requirements.research[data[i].type].level[data[i].levels[j].level] = data[i].levels[j].requirements;
				Seed.stats.research[data[i].type].level[data[i].levels[j].level] = { time:data[i].levels[j].time };
			}
		}

		// Initialise units & Save requirements and Stats ( by Jawz )
		data = Manifest.data.city.capital.units;
		for (i=0; i < data.length; i++) {
			if (!Seed.requirements.unit[data[i].type]) {
				Seed.requirements.unit[data[i].type] = [];
			}
			Seed.requirements.unit[data[i].type] = data[i].requirements;
			if (!Seed.stats.unit[data[i].type]) {
				Seed.stats.unit[data[i].type] = {};
			}
			Seed.stats.unit[data[i].type] = data[i].stats;
			Seed.stats.unit[data[i].type].time = data[i].time;
			Seed.stats.unit[data[i].type].upkeep = data[i].upkeep;
		}

		// Initialise troops resurrection requirements and Stats
		data = Manifest.data.city.spectral.units;
		for (i=0; i < data.length; i++) {
			if (!Seed.requirements.resurrect[data[i].type]) {
				Seed.requirements.resurrect[data[i].type] = [];
			}
			Seed.requirements.resurrect[data[i].type] = data[i].requirements;
			if (!Seed.stats.resurrect[data[i].type]) {
				Seed.stats.resurrect[data[i].type] = {};
			}
			Seed.stats.resurrect[data[i].type] = data[i].stats;
			Seed.stats.resurrect[data[i].type].time = data[i].time;
			Seed.stats.resurrect[data[i].type].upkeep = data[i].upkeep;
		}

		// Save quests manifest
		data = Manifest.data.quests;
		for (i=0; i < data.length; i++) {
			if (!Seed.quests.category[i]) {
				Seed.quests.category[i] = [];
			}
			Seed.quests.category[i] = data[i][0];
			for (j=0; j < data[i][1].length; j++){
				if (!Seed.quests.list[data[i][0]]) {
					Seed.quests.list[data[i][0]] = [];
				}
				var rec = {
					name		: data[i][1][j].name,
					recommended	: data[i][1][j].recommended,
					reward		: data[i][1][j].reward
				};
				Seed.quests.list[data[i][0]].push(rec);
			}
		}

		// Save item types & list from store manifest
		data = Manifest.data.store;
		for (var i in data) {
			if (!Seed.items[i]) {
				Seed.items[i] = [];
			}
			for (j=0; j < data[i].length; j++){
				Seed.items[i].push(data[i][j].type);
			}
		}

		// Save Great dragons statistics by level
		var greatDragonLvlsManifest		= Manifest.data.great_dragon_levels;
		var waterDragonLvlsManifest		= Manifest.data.water_dragon_levels;
		var stoneDragonLvlsManifest		= Manifest.data.stone_dragon_levels;
		var fireDragonLvlsManifest		= Manifest.data.fire_dragon_levels;
		var windDragonLvlsManifest		= Manifest.data.wind_dragon_levels;
		var iceDragonLvlsManifest		= Manifest.data.ice_dragon_levels;
		var swampDragonLvlsManifest		= Manifest.data.swamp_dragon_levels;
		var forestDragonLvlsManifest	= Manifest.data.forest_dragon_levels;
		var spectralDragonLvlsManifest	= Manifest.data.spectral_dragon_levels;
		for (var m=1; m<11; m++) {
			if (!Seed.greatDragons.GreatDragon[m])
				Seed.greatDragons.GreatDragon[m] = [];
			Seed.greatDragons.GreatDragon[m] = greatDragonLvlsManifest[m];
			if (!Seed.greatDragons.WaterDragon[m])
				Seed.greatDragons.WaterDragon[m] = [];
			Seed.greatDragons.WaterDragon[m] = waterDragonLvlsManifest[m];
			if (!Seed.greatDragons.StoneDragon[m])
				Seed.greatDragons.StoneDragon[m] = [];
			Seed.greatDragons.StoneDragon[m] = stoneDragonLvlsManifest[m];
			if (!Seed.greatDragons.FireDragon[m])
				Seed.greatDragons.FireDragon[m] = [];
			Seed.greatDragons.FireDragon[m] = fireDragonLvlsManifest[m];
			if (!Seed.greatDragons.WindDragon[m])
				Seed.greatDragons.WindDragon[m] = [];
			Seed.greatDragons.WindDragon[m] = windDragonLvlsManifest[m];
			if (!Seed.greatDragons.IceDragon[m])
				Seed.greatDragons.IceDragon[m] = [];
			Seed.greatDragons.IceDragon[m] = iceDragonLvlsManifest[m];
			if (!Seed.greatDragons.SwampDragon[m])
				Seed.greatDragons.SwampDragon[m] = [];
			Seed.greatDragons.SwampDragon[m] = swampDragonLvlsManifest[m];
			if (!Seed.greatDragons.ForestDragon[m])
				Seed.greatDragons.ForestDragon[m] = [];
			Seed.greatDragons.ForestDragon[m] = forestDragonLvlsManifest[m];
			if (!Seed.greatDragons.SpectralDragon[m])
				Seed.greatDragons.SpectralDragon[m] = [];
			Seed.greatDragons.SpectralDragon[m] = spectralDragonLvlsManifest[m];
		}
	}
};
//*********************************** Manifest package *********************************************


//*********************************** Map package *********************************************
var Map = {
	map_bin      : null,
	is_refreshing: false,
	x			 : 0,
	y			 : 0,
	names : {
		type : {
			0  : 'bog',
			1  : 'plain',
			2  : 'mountain',
			3  : 'forest',
			4  : 'hill',
			5  : 'grassland',
			6  : 'lake',
			7  : 'City',
			8  : 'AnthropusCamp',
			9  : 'Clouds',
			10 : 'Spectral',
			11 : 'Water',
			12 : 'Stone',
			13 : 'Fire',
			14 : 'Wind',
			15 : 'Ice',
			16 : 'Swamp',
			17 : 'Forest',
			'bog'			: 0,
			'plain'			: 1,
			'mountain'		: 2,
			'forest'		: 3,
			'hill'			: 4,
			'grassland'		: 5,
			'lake'			: 6,
			'City'			: 7,
			'AnthropusCamp' : 8,
			'Clouds'		: 9,
			'Spectral'		: 10,
			'Water'			: 11,
			'Stone'			: 12,
			'Fire'			: 13,
			'Wind'			: 14,
			'Ice'			: 15,
			'Swamp'			: 16,
			'Forest'		: 17
		}
	},
	targets : {
		AnthropusCamp:[],
		forest		 :[],
		grassland	 :[],
		hill		 :[],
		lake		 :[],
		mountain	 :[],
		plain		 :[],
		City		 :[],
		Outpost		 :[]
	},
	to_refresh : {
		forest		 :[],
		grassland	 :[],
		hill		 :[],
		lake		 :[],
		mountain	 :[],
		plain		 :[],
		City		 :[]
	},
	// List of coords indicated as camps or wilds but that are in fact clouds - Added list of all known clouds
	to_avoid : ['45,651',  '45,652',  '45,653',  '45,654',  '45,655',  '46,651',  '46,652',  '46,653',  '46,654',  '46,655',  '47,651',  '47,652',  '47,653',  '47,654',  '47,655',  '48,651',  '48,652',  '48,653',  '48,654',  '48,655',  '49,651',  '49,652',  '49,653',  '49,654',  '49,655',
				'134,189', '134,190', '134,191', '134,192', '134,193', '135,189', '135,190', '135,191', '135,192', '135,193', '136,189', '136,190', '136,191', '136,192', '136,193', '137,189', '137,190', '137,191', '137,192', '137,193', '138,189', '138,190', '138,191', '138,192', '138,193',
				'141,235', '141,236', '141,237', '141,238', '141,239', '142,235', '142,236', '142,237', '142,238', '142,239', '143,235', '143,236', '143,237', '143,238', '143,239', '144,235', '144,236', '144,237', '144,238', '144,239', '145,235', '145,236', '145,237', '145,238', '145,239',
				'158,632', '158,633', '158,634', '158,635', '158,636', '159,632', '159,633', '159,634', '159,635', '159,636', '160,632', '160,633', '160,634', '160,635', '160,636', '161,632', '161,633', '161,634', '161,635', '161,636', '162,632', '162,633', '162,634', '162,635', '162,636',
				'196,183', '196,184', '196,185', '196,186', '196,187', '197,183', '197,184', '197,185', '197,186', '197,187', '198,183', '198,184', '198,185', '198,186', '198,187', '199,183', '199,184', '199,185', '199,186', '199,187', '200,183', '200,184', '200,185', '200,186', '200,187',
				'206,240', '206,241', '206,242', '206,243', '206,244', '207,240', '207,241', '207,242', '207,243', '207,244', '208,240', '208,241', '208,242', '208,243', '208,244', '209,240', '209,241', '209,242', '209,243', '209,244', '210,240', '210,241', '210,242', '210,243', '210,244',
				'319,341', '319,342', '319,343', '319,344', '319,345', '320,341', '320,342', '320,343', '320,344', '320,345', '321,341', '321,342', '321,343', '321,344', '321,345', '322,341', '322,342', '322,343', '322,344', '322,345', '323,341', '323,342', '323,343', '323,344', '323,345',
				'343,676', '343,677', '343,678', '343,679', '343,680', '344,676', '344,677', '344,678', '344,679', '344,680', '345,676', '345,677', '345,678', '345,679', '345,680', '346,676', '346,677', '346,678', '346,679', '346,680', '347,676', '347,677', '347,678', '347,679', '347,680',
				'423,510', '423,511', '423,512', '423,513', '423,514', '424,510', '424,511', '424,512', '424,513', '424,514', '425,510', '425,511', '425,512', '425,513', '425,514', '426,510', '426,511', '426,512', '426,513', '426,514', '427,510', '427,511', '427,512', '427,513', '427,514',
				'451,46',  '451,47',  '451,48',  '451,49',  '451,50',  '452,46',  '452,47',  '452,48',  '452,49',  '452,50',  '453,46',  '453,47',  '453,48',  '453,49',  '453,50',  '454,46',  '454,47',  '454,48',  '454,49',  '454,50',  '455,46',  '455,47',  '455,48',  '455,49',  '455,50',
				'459,284', '459,285', '459,286', '459,287', '459,288', '460,284', '460,285', '460,286', '460,287', '460,288', '461,284', '461,285', '461,286', '461,287', '461,288', '462,284', '462,285', '462,286', '462,287', '462,288', '463,284', '463,285', '463,286', '463,287', '463,288',
 				'636,669', '636,670', '636,671', '636,672', '636,673', '637,669', '637,670', '637,671', '637,672', '637,673', '638,669', '638,670', '638,671', '638,672', '638,673', '639,669', '639,670', '639,671', '639,672', '639,673', '640,669', '640,670', '640,671', '640,672', '640,673',
				'660,445', '660,446', '660,447', '660,448', '660,449', '661,445', '661,446', '661,447', '661,448', '661,449', '662,445', '662,446', '662,447', '662,448', '662,449', '663,445', '663,446', '663,447', '663,448', '663,449',	'664,445', '664,446', '664,447', '664,448', '664,449',
				'684,483', '684,484', '684,485', '684,486', '684,487', '685,483', '685,484', '685,485', '685,486', '685,487', '686,483', '686,484', '686,485', '686,486', '686,487', '687,483', '687,484', '687,485', '687,486', '687,487', '688,483', '688,484', '688,485', '688,486', '688,487',
				'701,384', '701,385', '701,386', '701,387', '701,388', '702,384', '702,385', '702,386', '702,387', '702,388', '703,384', '703,385', '703,386', '703,387', '703,388', '704,384', '704,385', '704,386', '704,387', '704,388', '705,384', '705,385', '705,386', '705,387', '705,388',
				'712,87',  '712,88',  '712,89',  '712,90',  '712,91',  '713,87',  '713,88',  '713,89',  '713,90',  '713,91',  '714,87',  '714,88',  '714,89',  '714,90',  '714,91',  '715,87',  '715,88',  '715,89',  '715,90',  '715,91',  '716,87',  '716,88',  '716,89',  '716,90',  '716,91',
				'730,551', '730,552', '730,553', '730,554', '730,555', '731,551', '731,552', '731,553', '731,554', '731,555', '732,551', '732,552', '732,553', '732,554', '732,555', '733,551', '733,552', '733,553', '733,554', '733,555', '734,551', '734,552', '734,553', '734,554', '734,555',
				'738,712', '738,713', '738,714', '738,715', '738,716', '739,712', '739,713', '739,714', '739,715', '739,716', '740,712', '740,713', '740,714', '740,715', '740,716', '741,712', '741,713', '741,714', '741,715', '741,716', '742,712', '742,713', '742,714', '742,715', '742,716'],

	coords_to_avoid : {},

	init : function () {
		var t = Map;
		// Load the binary data map into mem
		t.map_bin = new Base64Reader( DATA_MAP );
		t.map_bin.fillBuffer();

		// Save our coords
		t.x = Seed.cities[CAPITAL_ID].x || 0;
		t.y = Seed.cities[CAPITAL_ID].y || 0;

		Data.init({
			map	: {
				terrains	: {},
				players		: {},
				evolution	: {},
				alliance	: {},
				coords		: {}
			}
		});

		// Initialize the coords_to_avoid object using the array of coords to avoid
		for (var c=0; c < t.to_avoid.length; c++)
			t.coords_to_avoid[t.to_avoid[c]] = {x:0}; // Just add the coord in the object. The check will be done regarding if a row exists or not.

		// Check Our Coords
		t.checkOurCoords();
		// set Ourselves Data Map
		t.setOurselves();
	},

	setOurselves : function () {
		var t = Map;
		for (var i = 0; i < Seed.player.player_wildernesses.length; i++ ) {
			var wilderness = Seed.player.player_wildernesses[i];
			var xy = wilderness.x + ',' + wilderness.y;
			Data.map.terrains[xy] = [
				Seed.player.id,
				Seed.player.name,
				t.checkType(wilderness.type),
				wilderness.level
			];
			Data.map.coords[xy] = { A:0, la:0 };
		}
		var alliance_id = Seed.player.alliance && Seed.player.alliance.id ? Seed.player.alliance.id : 0;
		Data.map.players[Seed.player.id] = [
			Seed.player.name,
			Seed.player.level,
			Seed.player.might,
			alliance_id,
			1
		];
		if (alliance_id) {
			Data.map.alliance[alliance_id] = Seed.player.alliance.name;
		}
	},

	getTargets : function (options) {
		var t = Map;
		var terrains = {
			AnthropusCamp:[],
			forest		 :[],
			grassland	 :[],
			hill		 :[],
			lake		 :[],
			mountain	 :[],
			plain		 :[],
			City		 :[],
			Outpost		 :[]
		};
		var radius = options.radius || 14;
		var _x = options.x || t.x;
		var _y = options.y || t.y;
		var _type = options.map_type || 'all';
		// Terrains
		for (var x = _x - radius; x < _x + radius; x++) {
			for (var y = _y - radius; y < _y + radius; y++) {
				var coord_x = t.normalize (x);
				var coord_y = t.normalize (y);
				var tile = t.map_bin.buffer[coord_y + (coord_x * 750) + 2];
				var type  = (tile >> 4) &0x0f;
				var level = tile &0x0f;

				if (!tile) continue;
				var xy = coord_x + ',' +coord_y;
				var to_skip = (t.coords_to_avoid[xy]) ? true : false;
				if (to_skip) continue;
				// Skip Clouds
				if ((!type || type == 9) || (_type != 'all' && 
					(_type == 'C' && type != 7 && type <= 9) &&    // Search for Cities & outposts ; and type is not corresponding
					(_type == 'W' && (type == 0 || type >= 7)) ) ) // Search for Wildernesses ; and type is not corresponding
				{
					continue;
				}
				if (!Data.map.coords[xy] ) {
					Data.map.coords[xy] = { A:1, la:0 };
				}
				var obj = {
					x  : coord_x,
					y  : coord_y,
					t  : type,
					l  : level,
					A  : ((Data.map.coords[xy].A == 0) ? false : true),
					la : Data.map.coords[xy].la
				};

				var terrain = Data.map.terrains[xy];
				if (terrain) {
					obj.id = terrain[0] || 0;			// player_id
					obj.cn = terrain[1];				// city name
					obj.t  = t.checkType(terrain[2]);	// city type
					obj.l  = (terrain[3] || obj.l); 	// level
					if (obj.id)	{
						var player = Data.map.players[obj.id];
						if (player)	{
							obj.n  = player[0];
							obj.pl = player[1];
							obj.m  = player[2];
							obj.ai = player[3];
							obj.a  = Data.map.alliance[player[3]] || player[3];
							var coords_A = (Data.map.coords[xy].A == 0) ? false : true;
							obj.A  = coords_A = obj.a ? false : true;
							obj.F  = player[4];
						}
					}
				} else {
					if (type == 7){
						obj.l = 1;
					}
				}
				obj.d = getDistance (_x, _y, coord_x, coord_y);
				var terrain_type = t.names.type[type];
				if (obj.t > 9) terrain_type = 'Outpost';
				if ((obj.t == 7 && (!obj.n || obj.n == undefined || obj.n == null) && (!obj.cn || obj.cn == undefined || obj.cn == null)) || cJzA(obj.ai)) continue; // City without name, should be a wamp. Do not take it into account
				terrains[terrain_type].push(obj);
			}
		}
		Map.targets = terrains;
		return terrains;
	},

	tileAt : function (options, callback)	{
		var t = Map;
		var x = t.normalize ( options.x || t.x );
		var y = t.normalize ( options.y || t.y );

		var tile = t.map_bin.buffer[y + (x * 750) + 2];
		var type  = (tile >> 4) &0x0f;
		var level = tile &0x0f;
		if (!tile) return (null);

		var xy = x + ',' + y;
		if (!Data.map.coords[xy]) {
			Data.map.coords[xy] = { A:1, la:0 };
		}
		var target = {
			x  : x,
			y  : y,
			t  : type,
			l  : level,
			A  : Data.map.coords[xy].A,
			la : Data.map.coords[xy].la
		};
		//logit ('tileAt '+xy+' base target = '+inspectObj(target,8,1));

		// No need to request more data for AnthropusCamp
		if (type == 8) {
			target.ok = true;
			callback (target);
			return;
		}

		// We make sure we have the necessary data in our database
		if (Data.map.terrains[xy] && Data.map.terrains[xy][0] ) {
			var terrain_xy = Data.map.terrains[xy];
			target.id = terrain_xy[0];				// player_id
			target.cn = terrain_xy[1];				// city name
			target.t  = t.checkType(terrain_xy[2]); // city type
			target.l  = terrain_xy[3];				// level

			if ( Data.map.players[target.id] && Data.map.players[target.id][0] ) {
				var player = Data.map.players[target.id];
				target.n     = player[0];
				target.pl    = player[1];
				target.m	 = player[2];
				target.ai	 = player[3];
				target.a     = Data.map.alliance[target.ai] || target.ai;
				target.F     = player[4];
				if (!options.wild_detail || (options.wild_detail && target.l < 7)) {
					target.ok = true;
					if (callback) callback (target);
					return;
				}
			}
		}
		if (target.n && !options.force_request) {
			target.ok = true;
			if (callback) callback (target);
			return;
		}

		var p = {};
		p['user_id']	  = C.attrs.userId;
		p['x']			  = x;
		p['y']			  = y;
		p['timestamp']	  = parseInt(serverTime());
		p['_session_id']  = C.attrs.sessionId;
		p['dragon_heart'] = C.attrs.dragonHeart;
		p['version']	  = api_version;
		new MyAjaxRequest ('map/tile_at.json', p, mycb, true);
		function mycb (rslt) {
			//logit('tile_at.json = '+inspectObj(rslt,8,1));
			if (rslt.ok && !rslt.dat.errors) {
				if (rslt.dat.map_player && rslt.dat.map_player != null && rslt.dat.map_player.id) {
					var alliance = 0;
					var is_friend = 0;
					var xy = rslt.dat.map_terrain.x + ',' + rslt.dat.map_terrain.y;
					if (rslt.dat.map_player.alliance) {
						alliance = rslt.dat.map_player.alliance.id;
						Data.map.alliance[alliance] = rslt.dat.map_player.alliance.name;
						target.A = Data.map.coords[xy].A = 0;
						if (Seed.player.alliance && rslt.dat.map_player.alliance.id === Seed.player.alliance.id) {
							is_friend = 1;
						}
					}
					Data.map.players[rslt.dat.map_player.id] = [
						rslt.dat.map_player.name,
						rslt.dat.map_player.level,
						rslt.dat.map_player.might,
						alliance,
						is_friend
					];
					target.n  = rslt.dat.map_player.name;
					target.pl = rslt.dat.map_player.level;
					target.m  = rslt.dat.map_player.might;
					target.ai = alliance;
					target.a  = Data.map.alliance[alliance] || alliance;
					target.F  = is_friend;
					var city_type = rslt.dat.map_terrain.type ? Map.names.type[rslt.dat.map_terrain.type] : type;
					var city_name = rslt.dat.map_terrain.name;

					Data.map.terrains[xy] = [
						rslt.dat.map_terrain.map_player_id, 
						city_name,
						Map.checkType(city_type), 
						(rslt.dat.map_terrain.level || target.l)
					];
					target.id = rslt.dat.map_terrain.map_player_id;
					target.cn = city_name;
					target.t  = Map.checkType(city_type);
					target.l  = Data.map.terrains[xy][3];
				}
				target.ok = true;
				if (callback) callback (target);
			}
			else if(rslt.dat.errors) {
				rslt.ok = false;
				rslt.errmsg = rslt.dat.errors[0];
				actionLog( translate('Map tileAt Error') +': ' + rslt.errmsg);
				if (callback) callback (rslt);
			}
			else if (rslt.status === 509){
				rslt.ok = false;
				rslt.errmsg = translate('<b>Rate Limit Exceeded</b>, too many requests!');
				verboseLog('Map tileAt ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
				if (callback) callback (rslt);
			} else if (callback){
				callback (rslt);
			}
		}
	},

	scanMap : function (options, callback){
		var t = Map;

		t.callback   = callback; 
		t.radius     = (!options.radius || options.radius < 7) ? 7 : options.radius;
		t.pos_x      = t.normalize ( options.x - t.radius + 7 );
		t.pos_y      = t.normalize ( options.y - t.radius + 7 );
		t.step_x     = t.step_y = 0;
		t.steps_side = Math.ceil( (t.radius*2) / 14 );
		t.steps      = parseInt( t.steps_side * t.steps_side );
		t.step       = 0;
		t.percent    = parseInt( t.step * 100 / t.steps );
		t.tile_count = 0;
		t.total_tiles = 0;
		t.old_percent = 0;
		t.tile_percent = parseInt( t.tile_count * 100 / ((t.total_tiles == 0) ? 1 : t.total_tiles));
		t.forwards	 = true;
		t.city_detail = options.city_detail || false;
		t.wild_detail = options.wild_detail || false;
		t.force_request = options.force_request || false;

		t.options   = options;

		var p = {};
		p['user_id']	  = C.attrs.userId;
		p['x']			  = t.pos_x;
		p['y']			  = t.pos_y;
		p['timestamp']	  = parseInt(serverTime());
		p['_session_id']  = C.attrs.sessionId;
		p['dragon_heart'] = C.attrs.dragonHeart;
		p['version']	  = api_version;
		new MyAjaxRequest ('map.json', p, t.gotMapCities, true);
	},  

	gotMapCities : function (r) {
		var t = Map;
		var m = Data.map;
		t.tile_count = 0;
		t.total_tiles = 0;

		if (!r.ok){
			if (t.callback)
				t.callback (null); // error !?!
			return;
		}

		var to_refresh = {
			forest		 :[],
			grassland	 :[],
			hill		 :[],
			lake		 :[],
			mountain	 :[],
			plain		 :[],
			City		 :[]
		};

		//logit('gotMapCities : '+inspectObj(r,8,1));
		//Cities & Outpost
		for (var i=0; i < r.dat.map_cities.length; i++)	{
			var target = r.dat.map_cities[i];
			var alliance = 0;
			var is_friend = 0;
			if (target.alliance_name) {
				alliance = target.alliance_name;
				if (Seed.player.alliance && target.alliance_name === Seed.player.alliance.name) {
					is_friend = 1;
				}
			}
			if (!Data.map.players[target.map_player_id]) {
				// [Player Name, Level, Might, Alliance, isFriend ]
				Data.map.players[target.map_player_id] = [
					0, 
					0,
					target.might,
					alliance,
					is_friend
				];
			} else {
				if (!Data.map.players[target.map_player_id][3]) {
					Data.map.players[target.map_player_id][3] = alliance;
				}
			}
			var xy = target.x + ',' + target.y;
			// [ player_id, city_name, city_type, level]
			Data.map.terrains[xy] = [ 
				target.map_player_id,
				(target.name || 0 ),
				t.checkType(target.type), //t.names.type[target.type], 
				(target.level || 0), 
			];
			if (!Data.map.coords[xy]) {
				Data.map.coords[xy] = { A:1, la:0 };
			}
			Data.map.coords[xy].A = alliance ? 0 : 1;
			if (Seed.player.id === target.map_player_id) {  
				Data.map.coords[xy].A  = 0;
			}
			if (t.city_detail) {
				var loc_to_refresh = {x : target.x, y : target.y};
				to_refresh.City.push(loc_to_refresh);
			}
		}
		// Wildernesses
		if (t.wild_detail) {
			var _x = t.pos_x;
			var _y = t.pos_y;
			for (var x = _x - t.radius; x < _x + t.radius; x++) {
				for (var y = _y - t.radius; y < _y + t.radius; y++) {
					var wild_x = t.normalize (x);
					var wild_y = t.normalize (y);
					var tile = t.map_bin.buffer[wild_y + (wild_x * 750) + 2];
					var type  = (tile >> 4) &0x0f;
					var level = tile &0x0f;
					if (tile) {
						var xy = wild_x + ',' +wild_y;
						var to_skip = (t.coords_to_avoid[xy]) ? true : false;
						if (type > 0 && type < 7 && level >= 7 && !to_skip) {
							var terrain_type = t.names.type[type];
							to_refresh[terrain_type].push({x : wild_x, y : wild_y});
						}
					}
				}
			}
		}
		if (t.city_detail || t.wild_detail) {
			for (var map_type in to_refresh) {
				if ((to_refresh[map_type]).length > 0) {
					(to_refresh[map_type]).shuffle();
				}
			}
			Map.to_refresh = to_refresh;
			Map.is_refreshing = true;
			for (var map_type in Map.to_refresh) {
				t.total_tiles += ((Map.to_refresh[map_type]).length || 0);
			}
			t.getDetails ();
		}
		t.callNext ();
	},

	scanWilds : function (options, callback) {
		var t = Map;
		var m = Data.map;

		t.callback   = callback; 
		t.radius   = (!options.radius || options.radius < 7) ? 7 : options.radius;
		var _x       = options.x || t.x;
		var _y       = options.y || t.y;
		t.steps      = 1;
		t.step       = 0;
		t.percent    = parseInt( t.step * 100 / t.steps );
		t.tile_count = 0;
		t.total_tiles = 0;
		t.old_percent = 0;
		t.tile_percent = parseInt( t.tile_count * 100 / ((t.total_tiles == 0) ? 1 : t.total_tiles));
		t.options   = options;

		var to_refresh = {
			forest		 :[],
			grassland	 :[],
			hill		 :[],
			lake		 :[],
			mountain	 :[],
			plain		 :[],
			City		 :[]
		};

		for (var x = _x - t.radius; x < _x + t.radius; x++) {
			for (var y = _y - t.radius; y < _y + t.radius; y++) {
				var wild_x = t.normalize (x);
				var wild_y = t.normalize (y);
				var tile = t.map_bin.buffer[wild_y + (wild_x * 750) + 2];
				var type  = (tile >> 4) &0x0f;
				var level = tile &0x0f;
				if (tile) {
					var xy = wild_x + ',' +wild_y;
					var to_skip = (t.coords_to_avoid[xy]) ? true : false; //false;
					//for (var a=0; a<t.to_avoid.length && !to_skip; a++)
					//	if (xy == t.to_avoid[a]) to_skip = true;
					if ((type > 0 && type < 7 && level >= 7 && !to_skip) &&
						( (type == 1	&& Data.options.search.plain) ||
						  (type == 2	&& Data.options.search.mountain) ||
						  (type == 3	&& Data.options.search.forest) ||
						  (type == 4	&& Data.options.search.hill) ||
						  (type == 5	&& Data.options.search.grassland) ||
						  (type == 6	&& Data.options.search.lake) ) ) {
						var terrain_type = t.names.type[type];
						to_refresh[terrain_type].push({x : wild_x, y : wild_y});
					}
				}
			}
		}
		for (var map_type in to_refresh) {
			if ((to_refresh[map_type]).length > 0) {
				(to_refresh[map_type]).shuffle();
			}
		}
		//logit('Wilds to refresh : '+inspectObj(to_refresh,8,1));
		Map.to_refresh = to_refresh;
		Map.is_refreshing = true;
		for (var map_type in Map.to_refresh) {
			t.total_tiles += ((Map.to_refresh[map_type]).length || 0);
		}
		t.getDetails ();
		t.callNextWilds ();
	},

	checkOurCoords : function(){
		var t = Map;
		if (Data.options.map.x != Seed.cities[CAPITAL_ID].x || Data.options.map.y != Seed.cities[CAPITAL_ID].y){
			Data.options.map.x = Seed.cities[CAPITAL_ID].x;
			Data.options.map.y = Seed.cities[CAPITAL_ID].y;
		}
	},
	normalize : function (x){
		if (x > 749){
			x -= 750;
		}
		if (x < 0){
			x += 750;
		}
		return x;
	},
	checkType : function (type){
		var ret = type;
		if (type >= 0 && type <= 17) ret = type;  // Add 1 if new OP type
		else ret = (Map.names.type[type] || type);
		return ret;
	},
	callNext : function () {
		var t = Map;
		if (t.is_refreshing) {
			setTimeout (t.callNext, 1000);
		} else {
			t.step = t.step + 1;
			t.percent = parseInt( t.step * 100 / t.steps );
			progressBar.update ({ step:t.percent });
			// This performs a scan in zig-zag
			// (To simulate a little more the way a human would)
			if (t.forwards) {
				++t.step_x;
				if (t.step_x >= t.steps_side) {
					++t.step_y;
					t.forwards = false;
					--t.step_x;
				}
			} else {
				--t.step_x;
				if (t.step_x < 0) {
					++t.step_y;
					t.forwards = true;
					++t.step_x;
				}
			}

			if (t.step_y >= t.steps_side) {
				if (t.callback) {
					t.callback ({done:true,terrains:t.terrains});
					return;
				}
			}
			t.callback ({done:false});

			setTimeout (function(){
				var p = {};
				p['user_id']	  = C.attrs.userId;
				p['x']			  = t.normalize( t.pos_x + (t.step_x*14) );
				p['y']			  = t.normalize( t.pos_y + (t.step_y*14) );
				p['timestamp']	  = parseInt(serverTime());
				p['_session_id']  = C.attrs.sessionId;
				p['dragon_heart'] = C.attrs.dragonHeart;
				p['version']	  = api_version;
				new MyAjaxRequest ('map.json', p, t.gotMapCities, true);
			}, MAP_DELAY * Math.floor(Math.random() * (-1) + 2));
		}
	},
	callNextWilds : function () {
		var t = Map;
		if (t.is_refreshing) {
			setTimeout (t.callNextWilds, 1000);
		} else {
			if (t.callback) {
				t.callback ({done:true,terrains:t.terrains});
				return;
			}
		}
	},
	getDetails : function () {
		var t = Map;
		for (var map_type in t.to_refresh) {
			if ((t.to_refresh[map_type]).length > 0) {
				var refresh_x = (t.to_refresh[map_type])[0].x;
				var refresh_y = (t.to_refresh[map_type])[0].y;
				var refresh_type = map_type;
				Map.tileAt({x:refresh_x, y:refresh_y}, function(target){
					if (target && target.ok){
						(t.to_refresh[refresh_type]).splice(0,1);
						t.tile_count++;
						t.tile_percent = Math.floor( t.tile_count * 100 / ((t.total_tiles == 0) ? 1 : t.total_tiles));
						t.percent	   = parseInt( t.step * 100 / t.steps );
						//logit('getDetails : tile_count='+t.tile_count+', tile_percent = parseInt( '+t.tile_count+' * 100 / '+t.total_tiles+') = '+t.tile_percent+', t.percent = '+t.percent+' + ('+t.tile_percent+' / '+t.steps+')');
						t.percent      = t.percent + (t.tile_percent / t.steps);
						if (t.percent != t.old_percent) {
							progressBar.update ({ step:t.percent, stepText:translate('Please wait...')+'<br>'
									+translate('Step')+' '+(t.step+1)+'/'+t.steps+' : '
									+translate('Got')+' '+t.tile_count+'/'+t.total_tiles+' ('+translate(refresh_type)+')' });
							t.old_percent = t.percent;
						}
						setTimeout (t.getDetails, MAP_DELAY * Math.floor(Math.random() * (-1) + 2));
					} else {
						verboseLog('Map tileAt ' + translate('was returned with a status of') + ' ' + target.ok + ' - ' + target.errmsg);
						var error_msg = target.errmsg;
						var waitTime  = 600;
						switch (target.status) {
							case 400 :	error_msg = translate('<b>Bad request!</b>');
										waitTime  = 0;
										break;
							case 403 :	error_msg = translate('<b>Forbidden!</b>');
										waitTime  = 0;
										break;
							case 509 :	error_msg = translate('<b>Rate Limit Exceeded</b>, too many requests!');
										waitTime  = 300;
										break;
						}
						if (waitTime > 0) {
							progressBar.update ({ stepText:error_msg + ' - ' + translate('Retry in') + ' ' + waitTime });
							setTimeout (t.getDetails, waitTime * 1000);
						} else {
							progressBar.update ({ stepText:error_msg });
							(t.to_refresh[refresh_type]).splice(0,1);
							setTimeout (t.getDetails, MAP_DELAY * Math.floor(Math.random() * (-1) + 2));
						}
					}
				});
				break;
			}
		}
		var done = true;
		for (var map_type in t.to_refresh) {
			if ((t.to_refresh[map_type]).length > 0) {
				done = false;
			}
		}
		if (done) Map.is_refreshing = false;
	}
};
//*********************************** Map package *********************************************


// Jawz *********************************** March package *********************************************
var Marches = {
	table_output : {
		attacks  : {},
		bookmark : {},
		waves	 : {},
		spies	 : {},
		transport: {},
		multiple : {}
	},
	timeItems : [ {	name:'Blink',text:'1m'},
				  {	name:'Hop',  text:'5m'},
				  {	name:'Skip', text:'15m'},
				  {	name:'Jump', text:'1h00'},
				  {	name:'Leap', text:'2h30'},
				  {	name:'ForcedMarchDrops', text:'25%'},
				  {	name:'TranceMarchDrops', text:'50%'} ],

	init : function () {
		var t = Marches;
		Data.init ({
			marches	: {
				start_at	: 0,
				attacks		: {},
				bookmark	: {},
				waves		: {},
				spies		: {},
				transport	: {},
				multiple	: {},
				count_limit	: 1
			}
		});
	},

	add : function (march_id, type) {
		var t = Marches;
		var march = Seed.marches[march_id];
		if (march === null) {
			if (DEBUG_MARCHES) WinLog.write ('***** ERRROR march missing from seed: '+ march.id);
		}  else {
			(Data.marches[type])[march_id] = cloneProps(march);
			if (DEBUG_MARCHES) WinLog.write ('Marches.add: ID=' + march.id + '  (' + march.x + ',' + march.y + ') General:' + march.general.id);
		}
	},

	remove : function (march_id, type) {   
		var t = Marches;
		if (march_id)
			delete ((Data.marches[type])[march_id]);
	},

	checkTimer : null,
	check : function () {
		var t = Marches;
		var now = parseInt(serverTime());
		clearTimeout (t.checkTimer);
		for (var type in Data.marches) {
			if ( !(/(attacks|waves|spies|multiple|bookmark|transport)/.test( type )) ){
				continue;
			}
			var marches = Data.marches[type];
			for (var id in marches) {
				if (marches[id].run_at < ( now - 60 )  && !(marches[id].has_report)) {
					// Will force at least 5 minute wait for the report to come in before it gives up on it. (fixed by Lord Mimir)
					if (marches[id].retry && marches[id].run_at < (now - 300)) {
						++Data.options.messages.missing;
						// Prevent errors in the marches queuing ?
						if (MyAjax.march_busy && t.march_busy > 0)
							--t.march_busy;
						if (DEBUG_MARCHES) WinLog.write ('March report never received! (now=' + now + ')\n'+ inspectObj (marches[id], 6, 1));    
						marches[id].has_report = true;
					} else {
						marches[id].retry = true;
						Messages.checkMessages( {category:'reports'} );
					}
				}
			}
		}
		t.checkTimer = setTimeout (t.check, Math.randRange(30000, 70000));
	},

	updateTable : function (table, type) {
		var t = Marches;
		var now = parseInt(serverTime());

		// shortcut for current table_output
		var table_output = t.table_output[type];

		// Clear table of old data  (by Lord Mimir)
		var cleared=0;
		for (var row = 0; row < table.rows.length; row++) {  
			var id = table.rows[row].getAttribute('ref');  
			if (Seed.marches[id] === undefined) {  
				cleared++;  
				table.deleteRow( row );  
				delete table_output[id];  
				row--;  
				continue;  
			} else if (cleared > 0) { 
				table_output[id].row -= cleared;   
			}
		}

		// loop to clear the attack if both no longer active and report has been recieved also sets dragons back in city.
		for (var id in Data.marches[type]) {
			if ( (Seed && Seed.marches[id] === undefined) && (Data.marches[type])[id].has_report ){
			    var dragon_type = null;
				var found_in_list = false;
				for (var unit_type in (Data.marches[type])[id].units) {
					for (var gd=0; gd < Seed.dragonList.length && !found_in_list; gd++) {
						if (Seed.dragonList[gd].type == unit_type) {
							found_in_list = true;
							dragon_type = unit_type;
						}
					}
				}
				if (dragon_type !== null && Seed.dragons[dragon_type])
					Seed.dragons[dragon_type].is_in_city = true;
				Marches.remove (id, type);
			}
		}

		//	NOTE: We use a dual system, the first one to create the rows and
		//	the another to update it. We do it in this way because we don't want 
		//	to lose the event listeners of the buttons.
		for (var id in Seed.marches) {
			var iRow, iCell;
			if (( Seed.marches[id].x === Seed.cities[CAPITAL_ID].x ) &&  
				( Seed.marches[id].y === Seed.cities[CAPITAL_ID].y ) && 
				( Seed.marches[id].status === 'marching' )
			   ){
				//Delete march as one can not attack own capital city.  
				//This part of code should not happen at all but is present as a catchall.
				delete Seed.marches[id];
				continue;
			}
			// Add the current march if it's not in the Data.marches
			if ( Data.marches.attacks[id]	=== undefined && 
				 Data.marches.bookmark[id]	=== undefined && 
				 Data.marches.waves[id]		=== undefined && 
				 Data.marches.spies[id]		=== undefined && 
				 Data.marches.transport[id]	=== undefined && 
				 Data.marches.multiple[id]	=== undefined
			   ){
				t.add(id,'attacks');
			}
			if ( ( Data.marches.attacks[id]   === undefined && type == 'attacks' ) || 
				 ( Data.marches.bookmark[id]  === undefined && type == 'bookmark' ) || 
				 ( Data.marches.waves[id]     === undefined && type == 'waves' ) || 
				 ( Data.marches.spies[id]     === undefined && type == 'spies' ) || 
				 ( Data.marches.transport[id] === undefined && type == 'transport' ) || 
				 ( Data.marches.multiple[id]  === undefined && type == 'multiple' )
			   ){
				//Only allow attacks on correct table.
				continue;
			}
			// shortcut of current march
			var march = Seed.marches[id];
			var retreating = (march.status === 'retreating');
			var time_left = march.run_at - now;
			var time_format;
			if (time_left < 0) {
				time_format = '...';
			} else if (isNaN(time_left)){
				time_format = '---';
			} else {
				time_format = timestr(time_left, true);
			}

			var units = '';
			for (var unit_type in march.units)
				units += ' ' + translate(unit_type) + ': ' + march.units[unit_type] + ' +';
			units = units.substr(1, units.length - 2);

			// Inserting Row
			if (table_output[id] === undefined && (time_left || march.status==='encamped')) {
				// Insert a new row
				iRow = table.insertRow(-1);
				// associates the current row number to the id of the march
				table_output[id] = {row:table.rows.length-1};
				iRow.setAttribute ('ref', id);
				iRow.title = [
							'(' + (march.general && march.general.name ? march.general.name : '----') + ')'
							,march.target_name
							,march.terrain_level
							,'[' + march.x + '/' + march.y + ']\n'
							,units.replace(/\+/g,'\n')
					].join(' ');
				// Retreating case
				if ( retreating ) {
					table_output[id].row_status = 2; // Retreating mode
					// march Status
					iCell = iRow.insertCell(-1);
					iCell.innerHTML = '<b>'+ translate('Returning') + ':</b>';
					// march Target
					iCell = iRow.insertCell(-1);
					iCell.className = 'wrap';
					iCell.innerHTML = march.target_name.nowrap();
					// march Coords
					iCell = iRow.insertCell(-1);
					iCell.style.textAlign = 'right';
					iCell.innerHTML = '&nbsp;<b>&lt;</b>&nbsp;';
					// march time_left
					iCell = iRow.insertCell(-1);
					iCell.innerHTML = time_format;
					// march Recall Button
					iCell = iRow.insertCell(-1);
					iCell.style.textAlign = 'right';
					iCell.innerHTML = '&nbsp;';
					// Speedups buttons
					for (var i=0; i<t.timeItems.length; i++) {
						iCell = iRow.insertCell(-1);
						iCell.style.textAlign = 'right';
						iCell.innerHTML = '&nbsp;';
						t.addSpeedUpButton(i, iCell, iRow.cells[3], id);
					}
				}

				// Marching case
				else {
					table_output[id].row_status = 1; // Marching mode
					// march Status
					iCell = iRow.insertCell(-1);
					switch (march.march_type) {
						case 'TransportMarch': iCell.innerHTML =  '<b>' + (RecallMarch.exists(id) ? translate('Yoyo') : translate('Transport')).capitalize() + ':</b>'; break;
						case 'SpyMarch'		 : iCell.innerHTML =  '<b>' + translate('Spy').capitalize() + ':</b>'; break;
						default: iCell.innerHTML =  '<b>' + translate(march.status).capitalize() + ':</b>'; break;
					}
					// march Target
					iCell = iRow.insertCell(-1);
					iCell.className = 'wrap';
					iCell.innerHTML = march.target_name.nowrap()  + '&nbsp;' + march.terrain_level + '&nbsp;';
					// march Coords
					iCell = iRow.insertCell(-1);
					iCell.style.textAlign = 'right';
					iCell.innerHTML = '<span class=jewel> [' + march.x +'/'+ march.y +']</span>&nbsp;<b>&gt;</b>&nbsp;';
					// march time_left
					iCell = iRow.insertCell(-1);
					iCell.style.textAlign = 'right';
					iCell.innerHTML = time_format;
					// march Recall Button
					iCell = iRow.insertCell(-1);

					var button = document.createElement('input');
					button.type = 'button';
					// Save the current March id in the attibute "ref" of the button
					button.setAttribute ('ref', id);
					if (march.status === 'encamped') {
						button.className = 'thin';
						button.value = 'X';
					} else {
						button.className = UID['bnt_red'] + ' thin';
						button.value = 'X';
					}
					button.addEventListener ('click', function (event){
						var self = event.target;
						self.disabled = true;
						self.style.display = 'none';
						// Take the march id from the "ref" attribute
						var march_id = self.getAttribute('ref');
						// Verify that the march really exists in Seed.marches
						if (Seed.marches[march_id]) {
							var city_id = Seed.marches[march_id].city_id;
							MyAjax.marchRecall (city_id, march_id, function (r) {
								if (r.ok && r.dat.result.success) {
									Seed.marches[march_id].status = 'retreating';
									(Data.marches[type])[march_id].status = 'retreating';
								}
							});
						}
					}, false);
					iCell.appendChild (button);
					// Speedups buttons
					for (var i=0; i<t.timeItems.length; i++) {
						iCell = iRow.insertCell(-1);
						iCell.style.textAlign = 'right';
						iCell.innerHTML = '&nbsp;';
						if (march.status != 'encamped')
							t.addSpeedUpButton(i, iCell, iRow.cells[3], id);
					}
				}
			}

			// Upgrade Row
			else {
				if (table_output[id] === undefined) continue;
				iRow = table.rows[ table_output[id].row ];
				if (iRow === undefined) {
					delete table_output[id];
					continue;
				}
				// Row Status cases
				switch ( table_output[id].row_status ) {
					// Finish state
					case 0:
						if (retreating && time_left > 0) { // added a check to prevent hidding of marches before they finish retreating.
							table_output[id].row_status = 2;
							// march Recall Button
							iRow.cells[4].innerHTML = '';
							// Speedups buttons
							for (var i=0; i<t.timeItems.length; i++) {
								iRow.cells[(5+i)].innerHTML = '';
							}
							continue;
						}
						iRow.style.display = 'none';
						table_output[id].row_status = -1;
						continue;
						break;
					// Marching state (Waiting for retreating)
					case 1:
					case 2:
						if (retreating) {
							table_output[id].row_status = 3; // Change to retreating state
							// march Status
							var html_status = '';
							html_status += '<b>' + translate('Returning') + ':</b>';
							iRow.cells[0].innerHTML = html_status;
							// march Target
							iRow.cells[1].innerHTML = march.target_name.nowrap();
							// march Coords
							iRow.cells[2].innerHTML = '&nbsp;<b>&lt;</b>&nbsp;';
							// march Recall Button
							iRow.cells[4].innerHTML = '';
							for (var i=0; i<t.timeItems.length; i++) {
								iRow.cells[(5+i)].innerHTML = '';
								t.addSpeedUpButton(i, iRow.cells[(5+i)], iRow.cells[3], id);
							}
						}
						else if ( (isNaN(time_left) || time_left < 0) &&  table_output[id].row_status === 1 ) {
							if ( march.terrain_type && !( /(Anthropus|City|Outpost|Bog)/.test(march.terrain_type)) ) {
								if (march.status === 'marching') {
									table_output[id].row_status = 2; // Change to Waiting for retreating (Action Taken)
								} else if ( march.status === 'encamped' ) {
									table_output[id].row_status = 4; // Change to encamped
									// Change button to  show recall
									// first clear old button. 
									iRow.cells[4].innerHTML = '';
									//now create button
									var button = document.createElement('input');
									button.type = 'button';
									// Save the current March id in the attibute "ref" of the button
									button.setAttribute ('ref', id);
									button.className = 'thin';
									button.value = 'X';
									button.addEventListener ('click', function (event){
										var self = event.target;
										self.disabled = true;
										self.style.display = 'none';
										// Take the march id from the "ref" attribute
										var march_id = self.getAttribute('ref');
										// Verify that the march really exists in Seed.marches
										if (Seed.marches[march_id]) {
											var city_id = Seed.marches[march_id].city_id;
											MyAjax.marchRecall (city_id, march_id, function (r) {
												if (r.ok && r.dat.result.success) {
													Seed.marches[march_id].status = 'retreating';
													(Data.marches[type])[march_id].status = 'retreating';
												}
											});
										}
									}, false);
									iRow.cells[4].appendChild (button);
									for (var i=0; i<t.timeItems.length; i++) {
										iRow.cells[(5+i)].innerHTML = '';
									}
								}
							}
						}
						break;
					// retreating state (Waiting for finish)
					case 3:
						if (isNaN(time_left) || time_left < 0) {
							table_output[id].row_status = 0; // Change to Finish state
						}
						break;
					//units encamped;
					case 4:
						if (retreating) {
							table_output[id].row_status = 3; // Change to retreating state
							// march Status
							iRow.cells[0].innerHTML = '<b>'+ translate('Retreating') + ':</b>';
							// march Target
							iRow.cells[1].innerHTML = march.target_name.nowrap();
							// march Coords
							iRow.cells[2].innerHTML = '&nbsp;<b>&lt;</b>&nbsp;';
							// march Recall Button
							iRow.cells[4].innerHTML = '';
							for (var i=0; i<t.timeItems.length; i++) {
								iRow.cells[(5+i)].innerHTML = '';
								t.addSpeedUpButton(i, iRow.cells[(5+i)], iRow.cells[3], id);
							}
						}
						break;
				}
				// march time_left
				iRow.cells[3].innerHTML = time_format;
			}
		}
	},

	addSpeedUpButton : function (itemId, nCell, nTimeCell, marchId) {
		if (!Data.options.speedups_enabled) return;
		var t = Marches;
		nCell.innerHTML = '';
		var num = isEmpty(Seed.player.items[t.timeItems[itemId].name],0);
		var button = document.createElement('input');
		button.type = 'button';
		// Save the current March id in the attibute "ref" of the button
		button.setAttribute ('ref', t.timeItems[itemId].name + '_' + marchId);
		button.value = t.timeItems[itemId].text;
		if (num > 0) {
			button.disabled = false;
			button.className = UID['bnt_green'] + ' thin';
			button.addEventListener ('click', function (event){
				var self = event.target;
				self.disabled = true;
				self.className = UID['bnt_disabled'] + ' thin';
				// Take the march id from the "ref" attribute
				var ids = self.getAttribute('ref').split('_');
				// Verify that the march really exists in Seed.marches
				if (Seed.marches[ids[1]]) {
					var city_id = Seed.marches[ids[1]].city_id;
					MyAjax.marchSpeedUp (city_id, ids[0], Seed.marches[ids[1]].job_id, function (r) {
						if (r.ok && r.dat.result.success) {
							if (r.dat.result.item_response) {
								itmResp = r.dat.result.item_response;
								if (itmResp.queue == 'march' && Seed.marches[itmResp.march_id]) {
									Seed.marches[itmResp.march_id].run_at   = itmResp.run_at;
									Seed.marches[itmResp.march_id].duration = itmResp.duration;
									var time_left = Seed.marches[itmResp.march_id].run_at - parseInt(serverTime());
									var time_format;
									if (time_left < 0) {
										time_format = '...';
									} else if (isNaN(time_left)){
										time_format = '---';
									} else {
										time_format = timestr(time_left, true);
									}
									nTimeCell.innerHTML = time_format;
								}
							}
							var num = isEmpty(Seed.player.items[ids[0]],0);
							if (num > 0) {
								button.disabled = false;
								button.className = UID['bnt_green'] + ' thin';
							}
						}
					});
				}
			}, false);
		} else {
			button.disabled = true;
			button.className = UID['bnt_disabled'] + ' thin';
		}
		nCell.appendChild (button);
	},
};
// Jawz *********************************** March package *********************************************


// Jawz *********************************** MemberShips package *********************************************
var MemberShips = {
	fetchMembership : function (id, callback, doDetail){
		var t = MemberShips;
		t.callback = callback; 
		t.doDetail = doDetail;
		if (id){
			var p = {};
			p['user_id']	  = C.attrs.userId;
			p['_session_id']  = C.attrs.sessionId;
			p['timestamp']	  = parseInt(serverTime());
			p['count']		  = 120;
			p['approved']	  = 1;
			p['dragon_heart'] = C.attrs.dragonHeart;
			p['version']	  = api_version;  
			var jsonType = 'alliances/'+id+'/memberships';
			new MyAjaxRequest (jsonType, p, t.updateMemberships, false);
		}
	},
	updateMemberships : function (rslt){
		var t = MemberShips;
		if (!rslt.ok){
			t.callback (null);
			return;
		}
		var memberList = rslt.dat.alliance_memberships; 
		var ret = {member:[]};
		for (var m=0; m<memberList.length; m++) {
			var d = {	player : memberList[m].player.name,
						id     : memberList[m].player.id,
						role   : memberList[m].role,
						might  : memberList[m].player.might,
						joined : memberList[m].created_at_i*1000,
						city   : memberList[m].player.city.name,
						x      : memberList[m].player.city.x,
						y      : memberList[m].player.city.y,
						dist   : getDistance(Seed.cities[CAPITAL_ID].x, Seed.cities[CAPITAL_ID].y, memberList[m].player.city.x, memberList[m].player.city.y)};
			ret.member.push (d);
		}
		ret.done = true;
		t.callback (ret); 
		return;
	},
	fetchAlliances : function (callback) {
		var t = MemberShips;
		t.callback = callback; 
		var p = {};
		p['q']				= '';
		p['_session_id']	= C.attrs.sessionId;
		p['sort']			= 'might';
		p['user_id']		= C.attrs.userId;
		p['count']			= 100;
		p['timestamp']		= parseInt(serverTime());
		p['version']		= api_version;
		p['page']			= 1;
		p['dragon_heart']		= C.attrs.dragonHeart;
		new MyAjaxRequest ('alliances', p, t.updateAlliances, false);
	},
	updateAlliances : function (rslt){
		var t = MemberShips;
		var allianceList = rslt.dat.alliances;
		if (!rslt.ok){
			t.callback (null);
			return;
		}
		if (allianceList) {
			var ret = {alliance:[], friends:[], foes:[]};
			for (var m=0; m<allianceList.length; m++) {
				var d = {	name  : allianceList[m].name,
							id    : allianceList[m].id,
							count : allianceList[m].member_count,
							rank  : allianceList[m].rank,
							might : allianceList[m].might,
							lord  : allianceList[m].overlord.name,
							desc  : allianceList[m].description};
				ret.alliance.push (d);
			}
			if (rslt.dat.friend_ids) {
				for (var f=0; f<rslt.dat.friend_ids.length; f++)
					ret.friends.push (rslt.dat.friend_ids[f]);
			}
			if (rslt.dat.foe_ids) {
				for (var f=0; f<rslt.dat.foe_ids.length; f++)
					ret.foes.push (rslt.dat.foe_ids[f]);
			}
		}
		ret.done = true;
		t.callback (ret); 
		return;
	},
}
// Jawz *********************************** MemberShips package *********************************************


//*********************************** Messages package *********************************************
var Messages = {
	readList : [],
	fetchTimer : null,
	lastQueued : 0,
	battleReportListeners : [],
	checkBusy : false,
	delete_queue : [],

	init : function (){
		Messages.checkMessages({ wait : 1000 });
		window.addEventListener ('unload', Messages.onUnload, false);
	},

	marchAtTarget : function (){
		var t = Messages;
		//t.checkMessages( {category:'reports'} );
		setTimeout(t.checkMessages, Math.randRange(5000,8000) , {category:'reports'} );
	},

	deleteMessage : function (msgId){
		var t = Messages;
		t.delete_queue.push (msgId);
		if (t.delete_queue.length >= Math.randRange (5, 12)) {
			doit();
		}
		function doit (){
			var t = Messages;
			//logit ('DELETE MESSAGES:\n'+ inspectObj (t.deleteQueue, 5, 1));      
			MyAjax.messageDelete (t.delete_queue, function (rslt){
				var t = Messages;
				t.delete_queue = [];
			});
		}
	},

	onUnload : function (){
		var t = Messages;
		if (t.delete_queue.length>0){
			MyAjax.messageDelete (t.delete_queue);
		}
	},

	// check for battle reports
	checkMessages : function ( options ){
		var t = Messages;
		if (t.battleReportListeners.length == 0){
			return;
		}
		var category = ( options.category || 'all' ).toLowerCase();
		var waitTime = options.wait || 30000;

		RequestQueue.add ('checkMessages', function(){ doit(category); }, Math.randRange(waitTime, waitTime*1.5) );

		function doit (category){
			MyAjax.messageList (category, 1, function (rslt){
				var t = Messages;
				if (rslt == null) return;
				for (var i = rslt.length-1; i >= 0; i--) {
					if (rslt[i].report_type === 'BattleReport' && !rslt[i].read_at) {
						if (t.readList.indexOf(rslt[i].id) < 0){
							t.readList.push (rslt[i].id);
						}
					}
				}
				clearTimeout (t.fetchTimer);
				if (t.readList.length > 0){
					t.fetchTimer = setTimeout (t.fetchNext, Math.randRange(2000,4000));
				}
			});
		}
	},  

	fetchNext : function (){
		var t = Messages;
		var id = t.readList[0];
		if (!id){
			logit ('Messages.fetchNext BAD MESSAGE ID:\n'+ inspectObj (t.readList, 8, 1));
			return;
		}    
		clearTimeout (t.fetchTimer);
		MyAjax.messageDetail (id, function (rslt){
			var t = Messages;
			t.readList.shift();
			if (rslt) t.gotBattleReport (rslt);
			if (t.readList.length > 0){
				t.fetchTimer = setTimeout (t.fetchNext, Math.randRange(2000,4000));
			}
		});
	},

	gotBattleReport : function (rpt){
		var t = Messages;
		if (!rpt || !rpt.report) return;
		if (DEBUG_MARCHES){
			WinLog.write ('Read Message: '+ rpt.report.location.terrain +' , '+ rpt.report.location.x +','+  rpt.report.location.y +' General: '+ rpt.report.attacker.general.id );    
		}
		for (var i=0; i < t.battleReportListeners.length; i++){
			t.battleReportListeners[i](rpt);
		}
	},

	addBattleReportListener : function (notify){
		var t = Messages;
		t.battleReportListeners.push (notify);
	},

	removeBattleReportListener : function (notify){
		var t = Messages;
		var i = t.battleReportListeners.indexOf (notify);
		if (i>=0){
			t.battleReportListeners.splice (i, 1);
		}
	}
};
//*********************************** Messages package *********************************************


// Jawz *********************************** MyLeaderboards package *********************************************
var MyLeaderboards = {
	fetchLeaderboards : function (type, by_player, period, scope, callback, doDetail){
		var t = MyLeaderboards;
		t.callback = callback; 
		t.doDetail = doDetail;
		switch (type){  // 0=Offensive kills, 1=Defensive kills, 2=Power taken, 3=Power gained
			case 0 : var jsonType = 'offensive-kills'; break;
			case 1 : var jsonType = 'defensive-kills'; break;
			case 2 : var jsonType = 'power-taken'; break;
			default : var jsonType = 'power-gained'; break;
		}
		if (by_player == 1)  // 0=By alliance, 1=By player
			jsonType = jsonType.concat('-by-player');
		else
			jsonType = jsonType.concat('-by-alliance');
		var p = {};
		p['limit']		  = 500;
		switch (period) {
			case 0 : p['period'] = '0w'; break;
			case 1 : p['period'] = '-1w'; break;
			default : break;
		}
		p['_session_id']  = C.attrs.sessionId;
		p['offset']		  = 0;
		if (by_player == 1 && scope == 1) p['scope'] = 'alliance';
		p['dragon_heart'] = C.attrs.dragonHeart;
		p['user_id']	  = C.attrs.userId;
		p['timestamp']	  = parseInt(serverTime());
		p['version']	  = api_version;
		//logit('leaderboards/'+jsonType+' : Params = '+inspectObj(p,8,1));
		new MyAjaxRequest ('leaderboards/'+jsonType, p, t.updateLeaderboards, false);
	},
	updateLeaderboards : function (rslt){
		var t = MyLeaderboards;
		if (!rslt.ok){
			t.callback (null);
			return;
		}
		//logit('Update LeaderBoards : '+inspectObj(rslt,8,1));
		if (rslt.ok && rslt.dat.error) {
			var ret = cloneProps(rslt.dat);
			ret.done = true;
			t.callback (ret); 
			return;
		}
		var _my = rslt.dat.my; 
		var _raising = rslt.dat.raising; 
		var _top = rslt.dat.top; 
		var ret = {my:[], raising:[], top:[], last_refresh:''};
		if (_my.entries) {
			if (_my.last_refresh) Data.stats.leaderboards.last_refresh = _my.last_refresh;
			for (var m=0; m<_my.entries.length; m++) {
				var entries = _my.entries[m];
				var d = {	alliance	: (entries.alliance ? entries.alliance.name : ''),
							diplomacy	: (entries.alliance ? entries.alliance.diplomacy : 'neutral'),
							score		: entries.score,
							change		: ((isNaN(entries.change) || !entries.change || entries.change == null) ? 0 : entries.change),
							rank		: entries.rank,
							player		: (entries.player ? entries.player.name : '')};
				ret.my.push (d);
			}
		}
		if (_raising.entries) {
			if (_raising.last_refresh) Data.stats.leaderboards.last_refresh = _raising.last_refresh;
			for (var m=0; m<_raising.entries.length; m++) {
				var entries = _raising.entries[m];
				var d = {	alliance	: (entries.alliance ? entries.alliance.name : ''),
							diplomacy	: (entries.alliance ? entries.alliance.diplomacy : 'neutral'),
							score		: entries.score,
							change		: ((isNaN(entries.change) || !entries.change || entries.change == null) ? 0 : entries.change),
							rank		: entries.rank,
							player		: (entries.player ? entries.player.name : '')};
				ret.raising.push (d);
			}
		}
		if (_top.entries) {
			if (_top.last_refresh) Data.stats.leaderboards.last_refresh = _top.last_refresh;
			for (var m=0; m<_top.entries.length; m++) {
				var entries = _top.entries[m];
				var d = {	alliance	: (entries.alliance ? entries.alliance.name : ''),
							diplomacy	: (entries.alliance ? entries.alliance.diplomacy : 'neutral'),
							score		: entries.score,
							change		: ((isNaN(entries.change) || !entries.change || entries.change == null) ? 0 : entries.change),
							rank		: entries.rank,
							player		: (entries.player ? entries.player.name : '')};
				ret.top.push (d);
			}
		}
		ret.done = true;
		//logit('Update LeaderBoards ret = '+inspectObj(ret,8,1));
		t.callback (ret); 
		return;
	},
	fetchTops : function (type, by_player, period, scope, callback, doDetail){
		var t = MyLeaderboards;
		t.callback = callback; 
		t.doDetail = doDetail;
		switch (type){  // 0=Offensive kills, 1=Defensive kills, 2=Power taken, 3=Power gained
			case 0 : var jsonType = 'offensive-kills'; break;
			case 1 : var jsonType = 'defensive-kills'; break;
			case 2 : var jsonType = 'power-taken'; break;
			default : var jsonType = 'power-gained'; break;
		}
		if (by_player == 1)  // 0=By alliance, 1=By player
			jsonType = jsonType.concat('-by-player');
		else
			jsonType = jsonType.concat('-by-alliance');
		var p = {};
		p['offset']		  = 0;
		switch (period) {
			case 0 : p['period'] = '0w'; break;
			case 1 : p['period'] = '-1w'; break;
			default : break;
		}
		p['limit']		  = 500;
		if (by_player == 1 && scope == 1) p['scope'] = 'alliance';
		p['timestamp']	  = parseInt(serverTime());
		p['version']	  = api_version;
		p['user_id']	  = C.attrs.userId;
		p['_session_id']  = C.attrs.sessionId;
		p['dragon_heart'] = C.attrs.dragonHeart;
		new MyAjaxRequest ('leaderboards/'+jsonType+'/top', p, t.updateTops, false);
	},
	updateTops : function (rslt){
		var t = MyLeaderboards;
		if (!rslt.ok){
			t.callback (null);
			return;
		}
		if (rslt.ok && rslt.dat.error) {
			var ret = cloneProps(rslt.dat);
			ret.done = true;
			t.callback (ret); 
			return;
		}
		var _top = rslt.dat; 
		var ret = {top:[], last_refresh:_top.last_refresh};
		if (_top.entries) {
			for (var m=0; m<_top.entries.length; m++) {
				var entries = _top.entries[m];
				var d = {	alliance	: (entries.alliance ? entries.alliance.name : ''),
							diplomacy	: (entries.alliance ? entries.alliance.diplomacy : 'neutral'),
							score		: entries.score,
							change		: ((isNaN(entries.change) || !entries.change || entries.change == null) ? 0 : entries.change),
							rank		: entries.rank,
							player		: (entries.player ? entries.player.name : '')};
				ret.top.push (d);
			}
		}
		ret.done = true;
		t.callback (ret); 
		return;
	},
}
// Jawz *********************************** MyLeaderboards package *********************************************


//*********************************** Names package *********************************************
var Names = {
	troops : {
		'names' : [
		[0, kPorter, kPorter],
		[1, kConscript, kConscr],
		[2, kSpy, kSpy],
		[3, kHalberdsman, kHalbrd],
		[4, kMinotaur, kMino],
		[5, kLongbowman, kLBM],
		[6, kSwiftStrikeDragon, kSSDrg],
		[7, kBattleDragon, kBatDrg],
		[8, kArmoredTransport, kATrans],
		[9, kGiant, kGiant],
		[10, kFireMirror, kFireM],
		[11, kGreatDragon, kGrtDrg],
		[12, kWaterDragon, kWatDrg],
		[13, kStoneDragon, kStnDrg],
		[14, kFireDragon, kFireDrg],
		[15, kWindDragon, kWndDrg],
		[16, kIceDragon, kIceDrg],
		[17, kSwampDragon, kSwpDrg],
		[18, kSpectralDragon, kSpctDrg],
		[19, kAquaTroop, kATroop],
		[20, kStoneTroop, kSTroop],
		[21, kFireTroop, kFTroop],
		[22, kWindTroop, kWTroop],
		[23, kIceTroop, kITroop],
		[24, kSwampTroop, kSwTroop],
		[25, kPackDragon, kPackDrg],
		[26, kFrostGiant, kFGiant],
		[27, kForestDragon, kForDrg],
		[24, kForestTroop, kForTroop],
		],
	}, 

	items : {
		'names' : [
		[1, 'Blink', 'Blink'],
		[2, 'Hop', 'Hop'],
		[3, 'Skip', 'Skip'],
		[4, 'Jump', 'Jump'],
		[5, 'Leap', 'Leap'],
		[6, 'Bounce', 'Bounce'],
		[100, 'GreatDragonBodyArmor', 'GD Body'],
		[101, 'GreatDragonHelmet', 'GD Helmet'],
		[102, 'GreatDragonTailGuard', 'GD Tail'],
		[103, 'GreatDragonClawGuards', 'GD Claw'],
		[110, 'WaterDragonEgg', 'WaterEgg'],
		[111, 'WaterDragonBodyArmor', 'WD Body'],
		[112, 'WaterDragonHelmet', 'WD Helmet'],
		[113, 'WaterDragonTailGuard', 'WD Tail'],
		[114, 'WaterDragonClawGuards', 'WD Claw'],
		[115, 'AquaTroopRespirator', 'Respirator'],
		[116, 'AquaTroopRespiratorStack100', 'Respirator-100'],
		[117, 'AquaTroopRespiratorStack500', 'Respirator-500'],
		[118, 'AquaTroopRespiratorStack1000', 'Respirator-1000'],
		[120, 'StoneDragonEgg', 'StoneEgg'],
		[121, 'StoneDragonBodyArmor', 'SD Body'],
		[122, 'StoneDragonHelmet', 'SD Helmet'],
		[123, 'StoneDragonTailGuard', 'SD Tail'],
		[124, 'StoneDragonClawGuards', 'SD Claw'],
		[125, 'StoneTroopItem', 'Mandrakes'],
		[126, 'StoneTroopItemStack100', 'Mandrakes-100'],
		[127, 'StoneTroopItemStack500', 'Mandrakes-500'],
		[128, 'StoneTroopItemStack1000', 'Mandrakes-1000'],
		[130, 'FireDragonEgg', 'FireEgg'],
		[131, 'FireDragonBodyArmor', 'FD Body'],
		[132, 'FireDragonHelmet', 'FD Helmet'],
		[133, 'FireDragonTailGuard', 'FD Tail'],
		[134, 'FireDragonClawGuards', 'FD Claw'],
		[135, 'FireTroopItem', 'Runes'],
		[136, 'FireTroopItemStack100', 'Runes-100'],
		[137, 'FireTroopItemStack500', 'Runes-500'],
		[138, 'FireTroopItemStack1000', 'Runes-1000'],
		[140, 'WindDragonEgg', 'WindEgg'],
		[141, 'WindDragonBodyArmor', 'WiD Body'],
		[142, 'WindDragonHelmet', 'WiD Helmet'],
		[143, 'WindDragonTailGuard', 'WiD Tail'],
		[144, 'WindDragonClawGuards', 'WiD Claw'],
		[145, 'WindTroopItem', 'BansheeTalon'],
		[146, 'WindTroopItemStack100', 'Talons-100'],
		[147, 'WindTroopItemStack500', 'Talons-500'],
		[148, 'WindTroopItemStack1000', 'Talons-1000'],
		[149, 'AnthropusTalisman', 'Talisman'],
		[150, 'AnthropusTalisman50K', 'Talisman-50K'],
		[151, 'IceDragonEgg', 'IceEgg'],
		[152, 'IceDragonBodyArmor', 'IceD Body'],
		[153, 'IceDragonHelmet', 'IceD Helmet'],
		[154, 'IceDragonTailGuard', 'IceD Tail'],
		[155, 'IceDragonClawGuards', 'IceD Claw'],
		[156, 'SpectralDragonBodyArmor', 'SpD Armor'],
		[157, 'SpectralDragonHelmet', 'SpD Helmet'],
		[158, 'SpectralDragonTailGuard', 'SpD TailG'],
		[159, 'SpectralDragonClawGuards', 'SpD Claw'],
		[160, 'SpectralDragonBody', 'SpD Body'],
		[161, 'SpectralDragonHead', 'SpD Head'],
		[162, 'SpectralDragonTail', 'SpD Tail'],
		[163, 'SpectralDragonTalons', 'SpD Talons'],
		[164, 'IceTroopItem', 'Totems'],
		[165, 'IceTroopItemStack100', 'Totems-100'],
		[166, 'IceTroopItemStack500', 'Totems-500'],
		[167, 'IceTroopItemStack1000', 'Totems-1000'],
		[168, 'SwampDragonEgg', 'SwampEgg'],
		[169, 'SwampDragonBodyArmor', 'SwD Body'],
		[170, 'SwampDragonHelmet', 'SwD Helmet'],
		[171, 'SwampDragonTailGuard', 'SwD Tail'],
		[172, 'SwampDragonClawGuards', 'SwD Claw'],
		[173, 'SwampTroopItem', 'Scales'],
		[174, 'SwampTroopItemStack100', 'Scales-100'],
		[175, 'SwampTroopItemStack500', 'Scales-500'],
		[176, 'SwampTroopItemStack1000', 'Scales-1000'],
		[177, 'FrostGiantItem', 'Ice Runes'],
		[178, 'FrostGiantItemStack100', 'Ice Runes-100'],
		[179, 'FrostGiantItemStack500', 'Ice Runes-500'],
		[180, 'FrostGiantItemStack1000', 'Ice Runes-1000'],
		[181, 'ForestDragonEgg', 'ForestEgg'],
		[182, 'ForestDragonBodyArmor', 'FoD Body'],
		[183, 'ForestDragonHelmet', 'FoD Helmet'],
		[184, 'ForestDragonTailGuard', 'FoD Tail'],
		[185, 'ForestDragonClawGuards', 'FoD Claw'],
		[186, 'ForestTroopItem', '?????'],
		[187, 'ForestTroopItemStack100', '?????-100'],
		[188, 'ForestTroopItemStack500', '?????-500'],
		[189, 'ForestTroopItemStack1000', '?????-1000'],
		],
	}, 

	init : function (){
		var t = Names;
		t.makeIdx (t.troops);
		t.makeIdx (t.items);
	},
	getItemAbbr : function (name){
		var x = Names.items.byName[name]; 
		if (x){
			return x[2];
		}
		return name.substr (0, 14);
	},
	getTroopAbbr : function (name){
		var x = Names.troops.byName[name]; 
		if (x){
			return x[2];
		}
		return name.substr (0, 14);
	},
	makeIdx : function (o){
		byId = {};
		byAbbr = {};
		byName = {};
		var n = o.names;
		for (var i=0; i < n.length; i++){
			byId[n[i][0]] = n[i];
			byAbbr[n[i][2]] = n[i];
			byName[n[i][1]] = n[i];
		}
		o.byId = byId;
		o.byAbbr = byAbbr;
		o.byName = byName;
	}
};
//*********************************** Names package *********************************************


// Jawz *********************************** Recall march package *********************************************
var RecallMarch = {
	init : function (){
		var t = RecallMarch;
		if (!Data.dynamic.recall_marches || Data.dynamic.recall_marches == undefined || Data.dynamic.recall_marches == "")
			Data.dynamic.recall_marches = [];
		t.timer = setTimeout (t.doit, 1000);
	},

	doit : function (){
		var t = RecallMarch;
		// first of all, we clear the array
		for (var m=0; m<Data.dynamic.recall_marches.length; m++){
			if (Data.dynamic.recall_marches[m] === undefined)
				Data.dynamic.recall_marches.splice(m,1);
			else if ((Data.dynamic.recall_marches[m] !== undefined) && (!Seed.marches[Data.dynamic.recall_marches[m].marchId] || Seed.marches[Data.dynamic.recall_marches[m].marchId] == null)){
				logit ('***** March to recall missing from seed: '+ inspectObj(Data.dynamic.recall_marches[m])); 
				Data.dynamic.recall_marches.splice(m,1);
			}
		}
		// Then, we deal with the remaining march to recall present into the array
		for (var m=0; m<Data.dynamic.recall_marches.length; m++){
			if ((Data.dynamic.recall_marches[m] !== undefined) && (Seed.marches[Data.dynamic.recall_marches[m].marchId] !== null)){
				var now = parseInt(serverTime());
				if ((Data.dynamic.recall_marches[m].run_at - now) < 60 && !Data.dynamic.recall_marches[m].recalling) {
					Data.dynamic.recall_marches[m].recalling = true;
					verboseLog ('Recalling march '+Data.dynamic.recall_marches[m].marchId+
							' arrives at '+timestr(Data.dynamic.recall_marches[m].run_at, true)+' '+
							', current time '+timestr(now, true)+', diff '+(Data.dynamic.recall_marches[m].run_at - now)+'s');
					doRecallMarch (Data.dynamic.recall_marches[m]);
				}
			}
		}
		t.timer = setTimeout (t.doit, 1000);
		function doRecallMarch (march){
			var targMsg = 'Recall march ' + march.marchId;
			verboseLog(targMsg + ' ' + translate('attempted'));
			new MyAjax.marchRecall (march.cityId, march.marchId, function (rslt){
				if (rslt.ok) {
					delete (march);
					verboseLog(targMsg + ' ' + translate('succeeded'));
				} else {
					march.recalling = false; // in order to try again a march recall
					verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
				}
			});
		}
	},
	exists : function (march_id){
		var t = RecallMarch;
		if (!Data.dynamic.recall_marches || Data.dynamic.recall_marches.length === 0) return false;
		var found = false;
		for (var m=0; m<Data.dynamic.recall_marches.length && !found; m++){
			if (Data.dynamic.recall_marches[m].marchId == march_id) found = true;
		}
		return found;
	},
};
// Jawz *********************************** Recall march package *********************************************


//*********************************** RequestQueue package *********************************************
var RequestQueue = {
	que : {},
	add : function (id, func, maxWaitMillis){
		var t = RequestQueue;
		var now = serverTime();
		var maxWait = maxWaitMillis/1000;
		if (isNaN(maxWaitMillis)){
			maxWait = 1;
		}
		if (t.que[id]){
			if (now + maxWaitMillis >= t.que[id][2]){
				return;
			}
			clearTimeout(t.que[id][1]);  
		} 
		var timer = setTimeout (function(){myFunc(id)}, maxWait*1000);
		t.que[id] = [func, timer, now+maxWait];
		//dispQ ('RequestQueue.add id='+ id);  
		function myFunc(id){
			var t = RequestQueue;
			var func = t.que[id][0];
			delete t.que[id];
			//dispQ ('RequestQueue.doit id='+ id);  
			func();
		}

		// Translation
		function dispQ (msg){
			var now = serverTime();
			var m = msg + ' (now='+ now +'):\n';
			for (var p in RequestQueue.que){
				m += p +' : '+ RequestQueue.que[p][1] +' : '+ RequestQueue.que[p][2] +' ('+ (RequestQueue.que[p][2]-now) +')\n';
			}
			WinLog.write (m);
		}   
	}, 

	isPending : function (id){
		var t = RequestQueue;
		return t.que[id]?true:false;
	}
};
//*********************************** RequestQueue package *********************************************


//*********************************** Seed package *********************************************
var Seed = {
	cities			: [],	  // cities
	cityIdx			: {},     // 'indicies'
	cityTs			: {},     // timestamps of last update
	cityInit		: [],
	jobs			: {},     // by city
	marches			: {},
	numMarches		: 0,
	generals		: {},
	requirements	: { building:[], research:[], resurrect:[], unit:[] },
	stats			: { building:{}, dragons:{}, research:{}, resurrect:{}, unit:{} },
	refresh_cities 	: [],
	greatDragons	: {GreatDragon:[], WaterDragon:[], StoneDragon:[], FireDragon:[], WindDragon:[], IceDragon:[], SwampDragon:[], ForestDragon:[], SpectralDragon:[]},
	dragonList		: [],
	dragons			: {},
	items			: {},
	quests			: {category:[], list:[]},
	numGenerals		: 0,
	serverTimeOffset: 0,
	lastRefresh		: 0,
	tickTimer		: 0,
	numCities		: 0,

	init : function (callback) {
		var t = Seed;
		t.fetchPlayer(function (rslt) {
			if (rslt.ok) {
				verboseLog(translate('Player data was Successfully requested from the server'));
			} else {
				verboseLog('fetchPlayer ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
			}
			if (callback){
				callback(rslt);
			}
		}, { noCities: true } );
		clearInterval(t.tickTimer);
		t.tickTimer = setInterval(t.tick, 1000);
	},

	fetchPlayer : function (callback, options) {
		var city;
		if (callback instanceof Function) {
			var callback = callback;
			var options = options || {};
		} else {
			var options = callback;
			var callback = null;
		}

		if (options && options.noPlayer) {
			// options.cities (array)
			// only fetch the cities id in the array
			if (options && options.cities) {
				for (var i = 0; i < options.cities.length;  i++) {
					// First, check if exist the city_id (by Lord Mimir)
					if (Seed.cityIdx[options.cities[i]] !== undefined) {
						verboseLog('FetchPlayer : Call fetchCity');
						Seed.addToRefresh(options.cities[i], true);
						setTimeout( Seed.fetchCity, Math.randRange(i*1000,i*3000) , options.cities[i], callback );
					}
				}
				return;
			}
		}

		var p = {};
		p['user_id']		= C.attrs.userId;
		p['dragon_heart']	= C.attrs.dragonHeart;
		p['_session_id']	= C.attrs.sessionId;
		p['version']		= api_version;
		p['timestamp']		= parseInt(serverTime());		
		new MyAjaxRequest ('player.json', p, function (rslt) {
			if (rslt.ok && !rslt.dat.errors) {
				if (rslt.dat.timestamp){
					Seed.serverTimeOffset = rslt.dat.timestamp - (new Date().getTime() / 1000);
				}
				Seed.player = rslt.dat; 

				// options.cities (array)
				// only fetch the cities id in the array
				if (options && options.cities) {
					for (var i = 0; i < options.cities.length;  i++) {
						// First, check if exist the city_id (by Lord Mimir)
						if (Seed.cityIdx[options.cities[i]] !== undefined) {
							verboseLog('FetchPlayer / player.json : Call fetchCity');
							Seed.addToRefresh(options.cities[i], true);
							setTimeout( Seed.fetchCity, Math.randRange(i*1000,i*3000) , options.cities[i], callback );
						}
					}
					return;
				}

				// Fill the cityInit array 
				// (used here & in the StartUp process so it must be before to verified options.noCities)
				var i = 0;
				for (city in rslt.dat.cities) {
					if (Seed.cityInit[i] === undefined ) {
						Seed.cityInit[i] = {};
					}
					Seed.cityInit[i].id = rslt.dat.cities[city].id;
					Seed.cityInit[i].type = city;
					i++;
				}

				// option.noCities (boolean)
				// Don't fetch Cities if we are from StartUp, because we do from there
				if (options && options.noCities) {
					if (callback)
						callback (rslt);
					return;
				}
				// OK, fetch all cities
				try {
					for (var i=0; i < Seed.cityInit.length; i++) {
						if (Seed.cityInit[i].timer){
							clearTimeout (Seed.cityInit[i].timer);
						}
						verboseLog('FetchPlayer / all cities : Call fetchCity');
						Seed.addToRefresh(Seed.cityInit[i].id, true);
						Seed.cityInit[i].timer = setTimeout (Seed.fetchCity, Math.randRange(i*2000,i*4000), Seed.cityInit[i].id, callback);
					}
				} catch (e) {
					rslt.ok = false;
					rslt.errmsg = e.toString();
				}
			}
			else if (rslt.ok && rslt.dat.errors) {
				rslt.ok = false;
				rslt.errmsg = rslt.dat.errors;
			}
			if ( callback ){
				callback (rslt);
			}
		});
	},

	fetchCity : function (cityId, callback) {
		if ( !cityId ) return;
		var t = Seed;
		var p = {};
		p['user_id'] = C.attrs.userId;
		p['dragon_heart'] = C.attrs.dragonHeart;
		p['_session_id'] = C.attrs.sessionId;
		p['timestamp'] = parseInt(serverTime());
		p['version'] = api_version;
		new MyAjaxRequest ('cities/'+ cityId +'.json', p, function (rslt) {
			if (rslt.ok && !rslt.dat.errors) {
				if (rslt.dat.timestamp){
					t.serverTimeOffset = rslt.dat.timestamp - (new Date().getTime() / 1000);
					if (rslt.dat.city.type == 'Capital')
						t.lastRefresh = serverTime ();
				}
				try {
					t.updateCity(rslt.dat.city);
				} catch (e) {
					rslt.ok = false;
					rslt.errmsg = 'Exception - '+e.toString();
				}
			}
			else if (rslt.ok && rslt.dat.errors) {
				rslt.ok = false;
				rslt.errmsg = rslt.dat.errors;
			}
			if (!rslt.ok)
			//	verboseLog('fetchCity ' + translate('attempt for') + ' ' + cityId + ' ' + translate('was returned with a status of') + ' ' + rslt.ok);
			// else 
				verboseLog('fetchCity ' + translate('attempt for') + ' ' + cityId + ' ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
			if (callback){
				callback (rslt);
			}
		}, true);
	},

	addToRefresh : function (cityId, is_refreshing) {
		var t = Seed;
		var found = false;
		var now = serverTime ();
		for (var c=0; c < t.refresh_cities.length && !found; c++)
			if (t.refresh_cities[c].id == cityId) found = true;
		// if city not queued to refresh and time elapsed since last refresh done is greater than 1 minute
		if (!found) // && (now - t.cityTs[t.cities[cityId].id]) > 30)
			t.refresh_cities.push({id:cityId, isRefreshing:is_refreshing});
	},

	tick : function () {  // called once per second - to check for job completion
		var t = Seed;
		var now = parseInt(serverTime ());
		var lock_food = false;
		try {
			for (var p=0; p < all_resource_types.length; p++){
				var production = t.cities[CAPITAL_ID].figures.resource_rates[all_resource_types[p]];
				var actual = t.cities[CAPITAL_ID].resources[all_resource_types[p]];
				if (t.player.boosts && t.player.boosts.collect_resources && all_resource_types[p] == 'food' && actual > production.capacity) lock_food = true;
				if (((actual < production.capacity && production.rate > 0) ||
					(actual > 0 && production.rate < 0)) && !lock_food) {
					if (t.lastRefresh && t.lastRefresh != 0) {
						// Case when a delay is to take into account when city data has just been updated
						actual = actual + ((production.rate/3600) * parseInt(now - t.lastRefresh));
						t.lastRefresh = 0;
					} else
						actual = actual + (production.rate/3600);
					if (actual > production.capactity) actual = production.capacity;
					if (actual < 0) actual = 0; // Case of food with negative production rate
					// update the Seed resource total only if the city is not queued for refresh
					if (!t.refresh_cities[CAPITAL_ID])
						t.cities[CAPITAL_ID].resources[all_resource_types[p]] = actual;
				}
			}
		} catch (e) {
			verboseLog (translate('Resources stock levels update failed') + ': ' + inspectObj(e, 8, 1));
			clearInterval(t.tickTimer);
			setTimeout (t.restartTick, 30000);
			return;
		}

		// check for job completion
		for (var cityIdx in t.jobs) {
			for (var jobId in t.jobs[cityIdx]) {
				var job = t.jobs[cityIdx][jobId];
				if (job.done) {
					if (now > (job.run_at - 5)) {
						var march = t.marches[job.march_id];
						if (march) {
							if (march.status == 'marching')
								Messages.marchAtTarget(march);
							if (march.status !== 'encamped')
								delete (t.jobs[cityIdx][jobId]);
						} else {
							delete (t.jobs[cityIdx][jobId]);
						}
					}
				} else {
					if (now > (job.run_at - 5)) {
						job.done = true;
						switch ( job.queue ) {
							case 'building':
								simpleSoundPlayer.soundJobs ('building');
								Buildings.setLevel (cityIdx, job.city_building_id, job.level);
								break;
							case 'march':
								var march = t.marches[job.march_id];
								if (march.status == 'marching') {
									t.addToRefresh(cityIdx, false);
									Messages.marchAtTarget(march);
									if (t.numMarches && t.numMarches > 0)
										--t.numMarches;
								}
								break;
							case 'research':
								simpleSoundPlayer.soundJobs ('research');
								Seed.player.research[job.research_type] = job.level;
								break;
							case 'units':
								simpleSoundPlayer.soundJobs ('training');
								Seed.cities[CAPITAL_ID].units[job.unit_type] += job.quantity;
								break;
							default : t.addToRefresh(cityIdx, false);
						}
						delete (t.jobs[cityIdx][jobId]);
					}
				}
			}
		}
		// delete expired marches ...
		for (var id in t.marches) {
			var march = t.marches[id];
			if ((march.run_at < now-10) || ((march.status=='returning' || march.status=='retreating') && march.run_at < now-2)) {
				delete (t.marches[id]);
				if (march.status=='returning' || march.status == 'retreating')
					t.addToRefresh(t.cities[CAPITAL_ID].id, false);
				if (march.units['WaterDragon'])  t.addToRefresh(t.cities[WATER_OUTPOST_ID].id, false);
				if (march.units['StoneDragon'])  t.addToRefresh(t.cities[STONE_OUTPOST_ID].id, false);
				if (march.units['FireDragon'])   t.addToRefresh(t.cities[FIRE_OUTPOST_ID].id, false);
				if (march.units['WindDragon'])   t.addToRefresh(t.cities[WIND_OUTPOST_ID].id, false);
				if (march.units['IceDragon'])    t.addToRefresh(t.cities[ICE_OUTPOST_ID].id, false);
				if (march.units['SwampDragon'])  t.addToRefresh(t.cities[SWAMP_OUTPOST_ID].id, false);
				if (march.units['ForestDragon']) t.addToRefresh(t.cities[FOREST_OUTPOST_ID].id, false);
				if (t.numMarches > 0) --t.numMarches;
			}
		}

		if (t.refresh_cities.length) {
			for (var idx = t.refresh_cities.length-1; idx >=0 ; idx-- ) {
				var city_id = t.refresh_cities[idx];
				if (!city_id.isRefreshing) {
					city_id.isRefreshing = true;
					verboseLog('Seed.tick : Call fetchCity for ' + city_id.id);
					t.fetchCity (city_id.id, function(res) {
						if (res.ok) {
							t.refresh_cities.splice (idx, 1);
						} else {
							var error_msg;
							if (res.status === 509) {
								error_msg = '<b>Rate Limit Exceeded</b>, too many requests!';
							} else error_msg = res.errmsg;
							verboseLog('Seed.tick : Call fetchCity returned code '+res.status+' - ' + res.errmsg);
							clearInterval(t.tickTimer);
							setTimeout (t.restartTick, 30000);
							return;
						}
					});
				}
			}
		}
	},
	restartTick : function () {
		var t = Seed;
		if (t.tickTimer) clearInterval(t.tickTimer);
		t.tickTimer = setInterval(t.tick, 1000);
	},

	updateCity : function (city) {
		var t = Seed;
		if (!city) return;
		verboseLog(translate('Updating City values')+': ' + city.name);
		var cityIdx = (city.type == 'Capital') ? CAPITAL_ID : (city.name.charAt(city.name.length-1));
		var cityIdx;    
		if (typeof t.cityIdx[city.id] !== 'undefined' && t.cityIdx[city.id] !== null) {
			cityIdx = t.cityIdx[city.id];
		}
		else if (city.type == 'Capital') {
			cityIdx = CAPITAL_ID;
		} else {
			switch (city.outpost_type){
				case 'WaterDragonOutpost'	: cityIdx = WATER_OUTPOST_ID; break;
				case 'StoneDragonOutpost'	: cityIdx = STONE_OUTPOST_ID; break;
				case 'FireDragonOutpost'	: cityIdx = FIRE_OUTPOST_ID; break;
				case 'WindDragonOutpost'	: cityIdx = WIND_OUTPOST_ID; break;
				case 'IceDragonOutpost'		: cityIdx = ICE_OUTPOST_ID; break;
				case 'SwampDragonOutpost'	: cityIdx = SWAMP_OUTPOST_ID; break;
				case 'ForestDragonOutpost'	: cityIdx = FOREST_OUTPOST_ID; break;
				case 'SpectralOutpost'		: cityIdx = SPECTRAL_OUTPOST_ID; break;
				default: cityIdx = SPECTRAL_OUTPOST_ID; // Spectral outpost
			}

			if (cityIdx == CAPITAL_ID) cityIdx = ICE_OUTPOST_ID;

			if (typeof t.cities[cityIdx] !== 'undefined' && t.cities[cityIdx] !== null)
			{
				t.cityIdx[t.cities[cityIdx].id] = t.cities.length;
				t.cities[t.cities.length] = t.cities[cityIdx];
			}
		}

		t.cities[cityIdx] = city;
		t.cityIdx[city.id] = cityIdx;
		t.cityTs[city.id] = serverTime();  

		// Add dragons object (by Didi)
		var dragon = null;
		switch (parseInt(cityIdx)) {
			case CAPITAL_ID			: dragon = city.great_dragon; break;
			case WATER_OUTPOST_ID	: dragon = city.water_dragon; break;
			case STONE_OUTPOST_ID	: dragon = city.stone_dragon; break;
			case FIRE_OUTPOST_ID	: dragon = city.fire_dragon; break;
			case WIND_OUTPOST_ID	: dragon = city.wind_dragon; break;
			case ICE_OUTPOST_ID		: dragon = city.ice_dragon; break;
			case SWAMP_OUTPOST_ID	: dragon = city.swamp_dragon; break;
			case FOREST_OUTPOST_ID	: dragon = city.forest_dragon; break;
			default : dragon = null; break;
		}
		if (dragon !== null) {
			var dragon_type = dragon.type.substring(dragon.type.indexOf('::')+2);
			dragon_type = (dragon_type == 'CityGreatDragon') ? 'GreatDragon' : dragon_type;
			var aerial_combat_level = (Seed.player.research['AerialCombat']) ? Seed.player.research['AerialCombat'] : 0;
			t.dragons[dragon_type] = dragon;
			t.dragons[dragon_type].name       = dragon_type;
			t.dragons[dragon_type].can_attack = (t.checkArmorDragon(dragon_type) && t.dragons[dragon_type].level >=8 && aerial_combat_level > 0 && dragon_type != 'SpectralDragon');
			t.dragons[dragon_type].city_id    = city.id;

			if (dragon.life !== dragon.maximum_life) {
				t.dragons[dragon_type].cure_at = serverTime() + ((dragon.maximum_life - dragon.life) / dragon.recovery_rate)*3600;
			} else {
				t.dragons[dragon_type].cure_at = serverTime();
			}
			var found_in_list = false;
			for (var gd=0; gd < t.dragonList.length && !found_in_list; gd++)
				if (t.dragonList[gd].type == dragon_type) found_in_list = true;
			if (!found_in_list)	{
				t.dragonList.push ({type:dragon_type, city:cityIdx});
				t.dragonList.sort( function(a,b){ return a.city - b.city; } );
			}
		}

		if (cityIdx == CAPITAL_ID) {
			// generals
			for (var i=0; i<city.generals.length; i++) {
				t.generals[city.generals[i].id] = city.generals[i];
			}
			t.numGenerals = city.generals.length;

			// marches
			t.numMarches = 0;
			for (var i=0; i < city.marches.length; i++) {
				var march = city.marches[i];
				if (march.general_id){
					t.generals[march.general_id].busy = true;
				}
				var dragon_type = null;
				var found_in_list = false;
				for (var unit_type in  march.units)	{
					for (var gd=0; gd < t.dragonList.length && !found_in_list; gd++) {
						if (t.dragonList[gd].type == unit_type) {
							found_in_list = true;
							dragon_type = unit_type;
						}
					}
				}
				if (dragon_type !== null && t.dragons[dragon_type])
					t.dragons[dragon_type].is_in_city = false;

				if (t.marches[march.id] != undefined){
					++t.numMarches;
				}
				t.checkMarchStatus (march);
				//verboseLog(march.id+' '+march.march_type+' '+march.target+' '+march.status);
			}
			verboseLog('Num of Marches: '+t.numMarches);
		}
		// jobs
		for (var i=0; i < city.jobs.length; i++){
			t.checkAddJob (city.jobs[i]);
		}

		for (var i=0; i < t.cityInit.length; i++){
			if (t.cityInit[i].id === city.id && !t.cityInit[i].loaded) {
				t.cityInit[i].loaded = true;
				var message = translate('City') + ' ' + city.id + ' ' + translate('Successfully initialized');
				verboseLog(message);
				console.log(message);
			}
		}
	},

	// Function to count number of piece armor (by Didi)
	checkArmorDragon : function (dragon_type) {
		var t = Seed;
		var armors = ['BodyArmor', 'ClawGuards', 'TailGuard', 'Helmet'];
		var ret = 0;
		for (var i = 0; i < armors.length; i++) {
			if ( isEmpty(Seed.player.items[ dragon_type + armors[i] ],0) !== 0 ) {
				ret++;
			}
		}
		if (ret == 4) return true;
		else return false;
	},

	// if fetchcity is pending, will notify when complete, else notifies right away...
	updateNotifyQueue : [],
	notifyOnUpdate : function (notify) {
		consoleLog('updateNotifyQueue');
		var t = Seed;
		if (!RequestQueue.isPending('fetchCity')) {
			notify();
			return;
		}
		t.updateNotifyQueue.push (notify);
	},

	checkMarchStatus : function (march){
		var t = Seed;
		var m = cloneProps(march);
		m.target_name = m.destination_name  ? translate('City') +' '+ m.destination_name : translate(m.terrain_type);
		t.marches[m.id] = m;
	},

	checkAddJob : function (job){
		var t = Seed;
		var cityId = job.city_id;
		if (!job.run_at){
			WinLog.write ('checkAddJob job.run_at is null:\n'+ inspectObj (job, 5, 1));
			if (ALERT_ON_BAD_DATA){
				alert ('checkAddJob job.run_at is null');
			}
		}    
		if (!t.jobs[cityId]){
			t.jobs[cityId] = {};
		}
		if (job.queue == 'march'){
			if (!t.marches[job.march_id]){
				WinLog.write ('checkAddJob MISSING MARCH:\n'+ inspectObj (job, 5, 1) +'\n'+ inspectObj(t.marches, 5, 1));
				if (ALERT_ON_BAD_DATA){
					alert ('checkAddJob MISSING MARCH');
				}
				if (job.run_at < serverTime()){
					return; // delete from Seed.jobs ?
				}
			} 
			else {  
				t.marches[job.march_id].run_at = job.run_at;
				t.marches[job.march_id].duration = job.duration;
				t.marches[job.march_id].job_id = job.id;
			}
		} 
		if (job.queue == 'units'){
		}

		if (t.jobs[cityId][job.id]){
			return;
		}
		job.run_at += 2;      
		t.jobs[cityId][job.id] = cloneProps(job);
	},

	jsonAddJob : function (job){  // called from various jsons (buildUpgrade) when new job rx'd 
		var t = Seed;
		t.checkAddJob (job);
	},

	jsonDelJob : function (job){
		var t = Seed;
		delete (t.jobs[job.city_id][job.id]);
	},

	checkIncomingData : function (rslt){
		var t = Seed;
		// check seed for missing building ...      
		for (var ij=0; ij < rslt.dat.city.jobs.length; ij++) {
			var job = rslt.dat.city.jobs[ij];
			if (job.queue == 'building'){
				var building = null;
				for (var im=0; im < rslt.dat.city.buildings.length; im++) {
					if (rslt.dat.city.buildings[im].id == job.city_building_id){
						building = rslt.dat.city.buildings[im];
						break;
					}
				}
				if (!building){
					WinLog.writeText ('*********************** MISSING BUILDING! ('+ job.city_building_id +') now='+ serverTime() +'\n' + inspectObj (job, 7, 1) +'\n'+ inspectObj (rslt, 12, 1));
					if (ALERT_ON_BAD_DATA){
						alert ('Danger Will Robinson! (missing building)');
					}
				}
			}
		}
		if (!rslt.dat.city.marches){
			return;
		}
		// check seed for missing march ...  
		for (var ij=0; ij < rslt.dat.city.jobs.length; ij++) {
			var job = rslt.dat.city.jobs[ij];
			if (job.march_id){
				if (t.findMarch(job.march_id, rslt.dat.city.marches) == null){
					WinLog.writeText ('*********************** MISSING MARCH, Job ID:'+ job.march_id +' (now='+ serverTime() +')\n'+ inspectObj (job, 7, 1) +'\n'
					+ inspectObj (rslt, 12, 1));
					if (ALERT_ON_BAD_DATA){
						alert ('Danger Will Robinson! (missing march)');
					}
				}
			}
		}   
		// check seed for missing march job ...  
		for (var im=0; im < rslt.dat.city.marches.length; im++) {
			var march = rslt.dat.city.marches[im];
			var job = null;
			for (var ij=0; ij < rslt.dat.city.jobs.length; ij++) {
				if (rslt.dat.city.jobs[ij].march_id == march.id){
					job = rslt.dat.city.jobs[ij];
					break;
				}
			}
			if (job==null){
				WinLog.writeText ('*********************** MISSING JOB FOR MARCH!  marchId:'+ march.id +'\n'+ inspectObj (rslt, 11, 1));
				if (ALERT_ON_BAD_DATA){
					alert ('MISSING JOB FOR MARCH!');
				}
			}
		}
	},

	findMarch : function (mid, marches){
		for (var im=0; im < marches.length; im++){
			if (marches[im].id == mid){
				return marches[im];
			}
		}
		return null;
		}
};
//*********************************** Seed package *********************************************


// Jawz *********************************** simpleSoundPlayer package *********************************************
var simpleSoundPlayer = {
	alertString			: '',
	checkInterval		: null,

	init : function (){
		var t = simpleSoundPlayer;
		t.oldAlertCount = 0;
		if (Data.options.tower.enabled)
			t.checkInterval = setInterval (t.checkAlerts, 1000);
	},

	checkAlerts : function () {
		var t = simpleSoundPlayer;
		t.alertString = '';
		var attacks = 0;
		var spies = 0;
		var raise_alarm = false, d;
		if (Data.options.tower.enabled && Data.options.messages_tower.length != 0) {
			for (var i=0; i<Data.options.messages_tower.length; i++) {
				d = Date.parse(Data.options.messages_tower[i].arrive_at)/1000;
				var now = parseInt(serverTime());
				var diff = now - d;
				if (diff<0) {
					// Raise alarm sound only for new reports
					if (!Data.options.messages_tower[i].warned) {
						Data.options.messages_tower[i].warned = true;
						raise_alarm = true;
					}
					// Counts only sentinel reports for which the theroical arrival time is not past
					if (Data.options.messages_tower[i].type == 0) attacks++;
					if (Data.options.messages_tower[i].type == 1) spies++;
				}
			}
		}
		if (attacks + spies > 0) {
			t.alertString += '<tr><td colspan=4 width=100%"><div class=' + UID['info_alerts'] + '>' + translate('Warning for ') + '<B>';
			if (attacks == 0) {
				if (spies > 1) t.alertString += translate('several spies');
				else t.alertString += translate('one spy');
			} else if (attacks > 1) {
				if (spies > 1)  t.alertString += translate('several spies') + translate('</B> and <B>') + translate('several attacks');
				else if (spies == 1)  t.alertString += translate('one spy') + translate('</B> and <B>') + translate('several attacks');
				else t.alertString += translate('several attacks');
			} else {
				if (spies > 1)  t.alertString += translate('several spies') + translate('</B> and <B>') + translate('one attack');
				else if (spies == 1)  t.alertString += translate('one spy') + translate('</B> and <B>') + translate('one attack');
				else t.alertString += translate('one attack');
			}
			t.alertString += '</B> ' + translate('in progress') + '</div></td></tr>';
		}
		if (Data.options.tower.play_sound && !Data.options.tower.alarm_active && raise_alarm)
			t.soundTheAlert(Data.options.tower.repeat);
	},
	addPlayer : function (container, url) {
		var audio =	 '<object class="playerpreview" id="swfSoundPlayerObj" type="application/x-shockwave-flash" data="'+SWF_PLAYER_URL+'" width="0" height="0">'
					+'	<param name="movie" value="'+SWF_PLAYER_URL+'">'
					+'	<param name="AllowScriptAccess" value="always" />'
					+'	<param name="FlashVars" value="mp3='+url+'&amp;autoplay=1" />'
					+'</object>';
		if (container) document.getElementById(container).innerHTML = audio;
	},
	removePlayer : function (container) {
		if (container) document.getElementById(container).innerHTML = "";
	},
	soundTheAlert : function (doRepeats){
		var t = simpleSoundPlayer;
		Data.options.tower.alarm_active = true;
		clearTimeout (soundStopTimer);
		clearTimeout (soundRepeatTimer);
		t.addPlayer(UID['jawz_SwfPlyr'], Data.options.tower.sound_url);
		soundStopTimer = setTimeout (t.stopSoundAlerts, Data.options.tower.play_length*1000);
		if (doRepeats && Data.options.tower.repeat)
			soundRepeatTimer = setTimeout (function (){t.soundTheAlert(true)}, Data.options.tower.repeat_delay*60000);
	},
	stopSoundAlerts : function (){
		var t = simpleSoundPlayer;
		t.removePlayer(UID['jawz_SwfPlyr']);
		clearTimeout (soundStopTimer);
		Data.options.tower.alarm_active = false;
	},
	soundJobs : function (task){
		var t = simpleSoundPlayer;
		var sound_url = '';
		clearTimeout (soundStopTimer);
		switch (task) {
			case 'building' : sound_url = Data.options.b_sound_url; break;
			case 'training' : sound_url = Data.options.t_sound_url; break;
			case 'research' : sound_url = Data.options.r_sound_url; break;
		}
		if (sound_url != '' && Data.options.play_jobssound) {
			t.addPlayer(UID['jawz_SwfPlyr'], sound_url);
			soundStopTimer = setTimeout (t.stopSoundJobs, 4000);
		}
	},
	stopSoundJobs : function (){
		var t = simpleSoundPlayer;
		t.removePlayer(UID['jawz_SwfPlyr']);
		clearTimeout (soundStopTimer);
	},
}
// Jawz *********************************** simpleSoundPlayer package *********************************************


//*********************************** Translation package *********************************************
var Translation = {
	loaded : false,
	xml		 : {},
	available_langs : [ {code:'de', desc:'German' },
						{code:'en', desc:'English' },
						{code:'es', desc:'Spanish' },
						{code:'fr', desc:'French' },
						{code:'nl', desc:'Dutch' },
						{code:'sv', desc:'Swedish' },
						{code:'tr', desc:'Turkish' } ],

	/* WARNING: DON'T CHANGE THIS ORDER */
	_section : [
		'items',
		'common',
		'buildings',
		'messages',
		'dialogs',
		'levels',
		'troops',
		'map',
		'research',
		'quests'
	],

	init : function (notify) {
		var t = Translation;
		t.fetchLocale(function (rslt) {
			if (rslt.ok) {
				verboseLog(translate('Locale data was Successfully requested from the sever'));
				t.loaded = true;
				t.fixResults();
			} else {
				verboseLog('fetchLocale ' + translate('was returned with a status of') + ' ' + rslt.ok + ' - ' + rslt.errmsg);
			}
			if (notify){
				notify(rslt);
			}
		});
	},

	fetchLocale : function (notify) {
		var t = Translation;
		new MyAjaxRequest ('locales/' + C.attrs.locale + '.xml', {'_swf_session_id':C.attrs.sessionId}, function (rslt) {
			if (rslt.ok) {
				try {
					t.parseXML(rslt.dat);
					
				} catch (e) {
					rslt.ok = false;
					rslt.errmsg = e.toString();
				}
			} 
			else if (rslt.errmsg.indexOf('404') !== -1) {
				new MyAjaxRequest('locales/en.xml', {'%5Fswf%5Fsession%5Fid':C.attrs.sessionId}, function (rslt) {
					if (rslt.ok) {
						try {
						
							t.parseXML(rslt.dat);
							
						} catch (e) {
							rslt.ok = false;
							rslt.errmsg = e.toString();
						}
					}
					if (notify) {
						notify(rslt);
					}
				});
			}
			if (notify){
				notify(rslt);
			}
		});
	},

	parseXML : function(xmlStr){
		var t = Translation;
		var XMLString = [];
		var XMLsections = [];
		var tmpStr = xmlStr;

		// Jawz - First identify the section list in the XML string
		if (tmpStr.indexOf('<translations>') > 0)
			tmpStr = tmpStr.substring(tmpStr.indexOf('<translations>') + 14, tmpStr.indexOf('</translations>') -1);
		while (tmpStr.length > 2) {
			var section_name = tmpStr.substring(tmpStr.indexOf('<') + 1, tmpStr.indexOf('>'));
			XMLsections.push(section_name);
			var start = tmpStr.indexOf('</'+section_name+'>') + section_name.length + 3;
			tmpStr = tmpStr.substring(start);
		}
		// Jawz - Then, for each section, bypass it if not in the t._section, keep it if in the t._section
		XMLString.push('<?xml version="1.0" encoding="UTF-8"?>');
		XMLString.push('<translations>');
		for (var s=0; s < XMLsections.length; s++) {
			var to_keep = false;
			for (i=0; i < t._section.length && !to_keep; ++i){
				if (XMLsections[s] == t._section[i]) {
					to_keep = true;
				}
			}
			var start = xmlStr.indexOf('<'+XMLsections[s]+'>');
			var end = xmlStr.indexOf('</'+XMLsections[s]+'>') + XMLsections[s].length + 3;
			if (to_keep) XMLString.push(xmlStr.substring(start, end));
			xmlStr = xmlStr.substring(1, start) + xmlStr.substring(end);
		}
		XMLString.push('</translations>');
		//logit('Traductions : '+inspectObj(XMLString));

		XmlTree = new XML.ObjTree();
		t.xml = XmlTree.parseXML( XMLString.join('').replace(/\n/g,'') );

		if (t.xml.translations){
			t.xml = t.xml.translations;
		} else {
			verboseLog('Error in the XML file structure: <translations> element not found!');
		}
	},

	fixResults : function(){
		var t = Translation.xml;

		function objectToFlat (obj) {
			var r={};
			for (var key in obj) {
				if (typeof obj[key] === 'object') {
					for (var subkey in obj[key]) {
						if (typeof (obj[key])[subkey] === 'object' ) {
							for (var subsubkey in (obj[key])[subkey]) {
								if (subsubkey === 'title' || subsubkey === 'name') {
									r[key+'-'+subkey] = ((obj[key])[subkey])[subsubkey];
								} else {
									r[key+'-'+subkey+'-'+subsubkey] = ((obj[key])[subkey])[subsubkey];
								}
							}
						} else {
							if (subkey === 'title' || subkey === 'name') {
								r[key] = (obj[key])[subkey];
							} else {
								r[key+'-'+subkey] = (obj[key])[subkey];
							}
						}
					}
				} else {
					r[key] = obj[key];
				}
			}
			return r;
		}

		var section = ['dialogs','messages'];//,'errors','confirmations'
		for ( var i=0; i < section.length; i++ ) {
			t[section[i]] = objectToFlat(t[section[i]]);
		}

		var newObjQuests={};
		for(var key in t.quests){
			if(typeof t.quests[key] == 'object'){
				for (var subkey in t.quests[key]){
					switch (subkey) {
						case 'title' : newObjQuests[key] = (t.quests[key])[subkey]; break;
						case 'objectives' : newObjQuests[key+'-'+subkey] = (t.quests[key])[subkey]; break;
						default : break;
					}
				}
			} else {
				newObjQuests[key] = t.quests[key];
			}
		}
		Translation.xml['quests'] = cloneProps(newObjQuests);

		t.common.information = t.common.info;
		t.common.omit = t.common.skip;
		t.common['spy-on'] = t.common.spy;
		t.dialogs.researching = t.dialogs.research;

		t.common['enter-coords'] = t.dialogs['attack-screen-enter-coords'];
		t.common['battle-report'] = t.messages['battle-report-title'];
		t.common['auto-collection-of-resources'] = t.dialogs['boost-collect-day'].replace(/:/,'');

		t.common.levels = findSimilarWord(t.common.level, t.messages['spy-tip-prefix']);

		delete t.common.error;
		delete t.common.home;
		delete t.common.info;
		delete t.common['ranged-attack'];
		delete t.common.skip;
		delete t.common.spy;
		delete t.messages.date;
		delete t.messages.fought;
		delete t.messages.subject;
		delete t.messages.to;
		delete t.dialogs.research;
		delete t.dialogs.spy;
		delete t.dialogs.unavailable;
		delete t.dialogs.upkeep;
	},
	
	_normalize : function (str){
		return (str || '').toLowerCase().replace(/ /g,'-');
	},
	getContent : function(section,key,subkey){
		key = Translation._normalize(key);
		if(Translation.xml[section] != undefined) {
			if( (Translation.xml[section])[key] != undefined ) {
				return subkey ? ((Translation.xml[section])[key])[subkey] : (Translation.xml[section])[key];
			}
		}
		return false;
	},
	buildings : function(key,subkey){
		subkey = subkey != undefined ? subkey : 'name';
		return Translation.getContent('buildings',key,subkey);
	},
	common : function(key){
		return Translation.getContent('common',key);
	},
	items : function(key,subkey){
		subkey = subkey != undefined ? subkey : 'name';
		return Translation.getContent('items',key,subkey);
	},
	dialogs : function(key){
		return Translation.getContent('dialogs',key);
	},
	levels : function(key){
		return Translation.getContent('levels',key,'title');
	},
	map : function(key,subkey){
		subkey = subkey != undefined ? subkey : 'name';
		return Translation.getContent('map',key,subkey);
	},
	messages : function(key){
		return Translation.getContent('messages',key);
	},
	troops :  function(key,subkey){
		subkey = subkey != undefined ? subkey : 'name';
		return Translation.getContent('troops',key,subkey);
	},
	research :  function(key,subkey){
		subkey = subkey != undefined ? subkey : 'name';
		return Translation.getContent('research',key,subkey);
	},
	quests :  function(key,subkey){
		subkey = subkey != undefined ? subkey : 'name';
		return Translation.getContent('quests',key,subkey);
	},
};
//*********************************** Translation package *********************************************


// Provide language translation services based on the browswer language
var needTranslate = {};
function translate( str ) {
	if ( TRANSLATION_ARRAY[str] != undefined ) {
		return TRANSLATION_ARRAY[str];
	}
	else if ( Translation.loaded ){
		var newStr;
		for (var i=0; i < Translation._section.length; ++i){
			newStr = Translation[Translation._section[i]](str);
			if (newStr){
				return newStr;
			}
		}
		if (IS_NOT_NATIVE_LANG && needTranslate[str] == undefined) {
			needTranslate[str] = 1;
			if(Tabs.Log){
				logit( '( Translate ) -> ' + str );
			}
		}
	}
	return str;
}
function translateByKey( str, key ) {
	if ( TRANSLATION_ARRAY[str] != undefined ) {
		return TRANSLATION_ARRAY[str];
	}
	else if ( Translation.loaded ){
		var newStr;
		for (var i=0; i < Translation._section.length; ++i){
			newStr = Translation[Translation._section[i]](key);
			if (newStr){
				return newStr;
			}
		}
		if (IS_NOT_NATIVE_LANG && needTranslate[str] == undefined) {
			needTranslate[str] = 1;
			if(Tabs.Log){
				logit( '( Translate ) -> ' + str );
			}
		}
	}
	return str;
}


//*********************************** VerboseLog package *********************************************
var VerboseLog = {
	init : function () {
		var t = VerboseLog;
		t.setEnable(Data.options.verboseLog.enabled);
	},

	setEnable : function (onOff) {
		var t = VerboseLog;
		Data.options.verboseLog.enabled = onOff;
	}
};
//*********************************** VerboseLog package *********************************************


//****************
// Functions
//****************
function deleteBuildJob(cityIdx, job){
	var cid = Seed.cities[cityIdx].id;
	var jobs = Seed.jobs[cid];
	for (var p in jobs){
		if (jobs[p] == job){
			delete jobs[p];
		}
	} 
}
function deleteResearchJob(job){
	var cid = Seed.cities[CAPITAL_ID].id;
	var jobs = Seed.jobs[cid];
	for (var p in jobs){
		if (jobs[p] == job){
			delete jobs[p];
		}
	} 
}
function objAddTo (o, name, val){
	if (!o[name]){
		o[name] = val;
	} else {
		o[name] += val;
	}
}
function generalList (cityIdx){
	var ret = {};
	var generals = Seed.cities[cityIdx].generals;
	for (var i=0; i < generals.length; i++){
		ret[generals[i].id] = generals[i].name +' ('+ generals[i].rank +')';
	}
	return ret;
}
function getAllianceRelationship (id, name){
	var found = false;
	var ret = name;
	if (Data.dynamic.players.friends) {
		for (var x=0; x<Data.dynamic.players.friends.length && !found; x++) {
			if (Data.dynamic.players.friends[x] == id) {
				found = true;
				ret = '<span class=' + UID['green'] + '>' + name + '</span>';
			}
		}
	}
	if (Data.dynamic.players.foes && !found) {
		for (var x=0; x<Data.dynamic.players.foes.length && !found; x++) {
			if (Data.dynamic.players.foes[x] == id) {
				found = true;
				ret = '<span class=' + UID['red'] + '>' + name + '</span>';
			}
		}
	}
	return ret;
}
function getAllianceState (id){
	var found = false;
	var ret = '0';
	if (Data.dynamic.players.friends) {
		for (var x=0; x<Data.dynamic.players.friends.length && !found; x++) {
			if (Data.dynamic.players.friends[x] == id) {
				found = true;
				ret = '1';
			}
		}
	}
	if (Data.dynamic.players.foes && !found) {
		for (var x=0; x<Data.dynamic.players.foes.length && !found; x++) {
			if (Data.dynamic.players.foes[x] == id) {
				found = true;
				ret = '-1';
			}
		}
	}
	return ret;
}
function getAvailableDragon (include_exclude, dragon_list) {
	// include_exclude : true = list of dragons that can be sent, false = list of dragons to not send
	var found = false;
	for (var gd=0; gd < Seed.dragonList.length && !found; gd++) {
		var dragon		= Seed.dragons[Seed.dragonList[gd].type];
		var curName		= dragon.name;
		var isInCity	= dragon.is_in_city;
		var canAttack	= dragon.can_attack;
		var curLife		= dragon.life;
		var maxLife		= dragon.maximum_life;
		var is_in_list	= true;
		if (dragon_list) is_in_list = dragon_list[Seed.dragonList[gd].type];
		if (((curLife / maxLife) >= 0.75) && isInCity && canAttack && 
			((include_exclude && is_in_list) || (!include_exclude && !is_in_list))) {
			found = true;
		}
	}
	if (found)
		return curName;
	else
		return null;
}
function getAvailableGeneral (){
	for (var p in Seed.generals){
		if (!Seed.generals[p].busy){
			return Seed.generals[p];
		}
	}
	return null;
}
function getBuildingById (cityIdx, bId){
	var b = Seed.cities[cityIdx].buildings;
	for (var i=0; i<b.length;i++){
		if (b[i].id == bId){
			return b[i].type;
		}
	}
	return '';
}
function getBuildingJob (cityIdx){
	var cid = Seed.cities[cityIdx].id;
	for (var p in Seed.jobs[cid]){
		var job = Seed.jobs[cid][p];
		if (job.queue == 'building'){
			return ({job:job, building:Buildings.getById(cityIdx, job.city_building_id)});
		}
	}
	return null;
}
function getBuildJob (cityIdx){
	var cid = Seed.cities[cityIdx].id;
	var jobs = Seed.jobs[cid];
	for (var p in jobs){
		if (jobs[p].queue == 'building'){
			return jobs[p];
		}
	}
	return null;
}
function getDragonJob (cityIdx){
  var cid = Seed.cities[cityIdx].id;
  for (var p in Seed.jobs[cid]){
    var job = Seed.jobs[cid][p];
    if (job.queue == 'dragon')
      return (job);
  }
  return null;
}
function getMarchTime (x, y, units) {
	var dist = getDistance(Seed.cities[CAPITAL_ID].x, Seed.cities[CAPITAL_ID].y, x, y);
	var speed = 99999;
	for (var unit in units) {
		if (units[unit] > 0) {
			if (Seed.stats.unit[unit]) {
				if (Seed.stats.unit[unit].speed < speed) speed = Seed.stats.unit[unit].speed;
			} else speed = 100;
		}
	}
	var time = dist / ((Seed.cities[CAPITAL_ID].figures.marches.speed_multiplier * speed) /6000) + 30;
	return time;
}
function getMusterPointMaxTroops(cityIdx){
	if (!Seed.cities[cityIdx].figures.marches.maximum_troops || Seed.cities[cityIdx].figures.marches.maximum_troops == undefined) {
		var lvl = (Buildings.getLevel (cityIdx, kMusterPoint)).max;
		if (!lvl) return 0;
		else
			switch (lvl) {
				case 11 : var maxLvl = 120000; break;
				case 12 : var maxLvl = 140000; break;
				case 13 : var maxLvl = 160000; break;
				default : var maxLvl = lvl * 10000;
			}
	} else var maxLvl = Seed.cities[cityIdx].figures.marches.maximum_troops;
	return maxLvl;
}
function getMusterPointSlots (cityIdx){
	var lvl = (Buildings.getLevel (cityIdx, kMusterPoint)).max;
	if (!lvl){
		return 0;
	}
	return lvl - Seed.numMarches;
}
function getMusterPointLevel (cityIdx){
	var lvl = (Buildings.getLevel (cityIdx, kMusterPoint)).max;
	return (!lvl) ? 0 : lvl;
}
function getOutpostJob (cityIdx){
  var cid = Seed.cities[cityIdx].id;
  for (var p in Seed.jobs[cid]){
    var job = Seed.jobs[cid][p];
    if (job.queue == 'outpost')
      return (job);
  }
  return null;
}
function getResearchJob (cityIdx){
	var cid = Seed.cities[cityIdx].id;
	for (var p in Seed.jobs[cid]){
		var job = Seed.jobs[cid][p];
		if (job.queue == 'research'){
			return (job);
		}
	}
	return null;
}
function getResurrectionJob (cityIdx){
	var cid = Seed.cities[cityIdx].id;
	var jobs = Seed.jobs[cid];
	for (var p in jobs){
		if (jobs[p].queue == 'resurrection'){
			return jobs[p];
		}
	}
	return null;
}
function getTotTrainTable (){
	var now  = serverTime();
	var totalTrain = [];
	for (var cityIdx=0; cityIdx < Seed.cities.length; ++cityIdx) {
		var time = 0;
		if (Seed.cities[cityIdx] && Seed.cities[cityIdx].jobs) {
			var jobs = Seed.cities[cityIdx].jobs;
			var trains = [];
			for (var j=0; j < jobs.length; j++)
				if (jobs[j].queue=='units' && jobs[j].unit_type && jobs[j].run_at > now) trains.push (jobs[j]);
			if (trains.length > 0) {
				trains.sort( function(a,b){ return a.run_at - b.run_at; } );
				var time = trains[trains.length-1].run_at - now;
			}
		}
		if (Seed.cities[cityIdx])
			totalTrain.push ({cityIdx:cityIdx, total:time});
	}
	totalTrain.sort(function(a,b){return a.total-b.total});
	return totalTrain;
}
function getTrainJob (cityIdx){
	var cid = Seed.cities[cityIdx].id;
	var jobs = Seed.jobs[cid];
	for (var p in jobs){
		if (jobs[p].queue == 'units'){
			return jobs[p];
		}
	}
	return null;
}
function getTroopNumbers (cityIdx, troopType) {
	var indefense = 0;
	var city = (typeof cityIdx == 'number') ? Seed.cities[cityIdx] : cityIdx;
	var incity = city.units[troopType] ? city.units[troopType] : 0;
	if (city.defense_force) indefense = city.defense_force[troopType] ? city.defense_force[troopType] : 0;
	var marches = 0;
	for (var march in Seed.marches){
		for (var name in Seed.marches[march].units){
			if (troopType == name){
				marches += Seed.marches[march].units[name];
			}
		}
	}
	return {incity:incity, indefense:indefense, marches:marches, total:incity+marches+indefense};
}
function refreshPlayerData (container, notify){
	var dial = new ModalDialog (container, 300, 165, '', false, null);
	dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>KabaListics : ' + translate('Message') + '</b></center></div>';
	dial.getContentDiv().innerHTML = translate ('Refreshing player and cities data');
	Seed.fetchPlayer(function (rslt) {
		if (rslt.ok) {
			verboseLog(translate('Player data was Successfully requested from the server'));
			if (notify)
				notify(true);
			dial.destroy();
		} else {
			dial.getContentDiv().innerHTML = translate ('Error while retrieving player data '+rslt.errmsg);
			dial.allowClose (true);
			if (notify)
				notify (false);
			return;
		}
	}, {cities:[Seed.cities[CAPITAL_ID].id]} );
}
function saveBookmark (container, x, y, type, level, units, ai, include_great_dragon, include_exclude, great_dragons){
	if (Data.options.bookmarks.targets && Data.options.bookmarks.targets.length>0) {
		var h = cloneProps(Data.options.bookmarks.targets);
		for (var i=h.length-1; i>=0; i--) {
			if ((h[i].x == x) && (h[i].y == y))
				Data.options.bookmarks.targets.splice(i,1);
		}
	}
	var target_desc = '';
	var target_type = 0;
	Map.tileAt({x:x, y:y, force_request:false}, function(target){
		if (target && target.ok){
			if (target.t == 7 || target.t >= 10) target_type = 0;
			else if (target.t == 8) target_type = 1;
			else target_type = 2;
			var type_name = Map.names.type[target.t] || target.t;
			if (target.cn != undefined && target_type == 0){
				target_desc = translate(type_name) + ' ' + target.n + ' (' + nombreFormate(target.m) + ')<br>' + (target.a != undefined ? ' / '+target.a : '');
			} else {
				target_desc = translate(type_name) + ' ' + target.l;
			}
		}
	});
	var dragon_list = {};
	if (include_great_dragon) {
		for (var gd=0; gd < Seed.dragonList.length; gd++) {
			var dragon		= Seed.dragonList[gd].type;
			var is_in_list	= (include_exclude ? false : true);
			if (great_dragons)
				is_in_list = great_dragons[Seed.dragonList[gd].type];
			if ((include_exclude && is_in_list) || (!include_exclude && !is_in_list)) {
				dragon_list[dragon] = true;
			} else {
				dragon_list[dragon] = false;
			}
		}
	}

	var rec = {
		x		: x,
		y		: y,
		t		: target_type, // 0 = city, outpost, 1 = Anthro, 2 = Wilderness
		d		: getDistance(Seed.cities[CAPITAL_ID].x, Seed.cities[CAPITAL_ID].y, x, y),
		ti		: getMarchTime (x, y, units),
		type	: target_desc,
		level	: level,
		units	: cloneProps(units),
		dragons	: dragon_list,
		inc		: include_great_dragon
	};
	if (!cJzA(ai)) Data.options.bookmarks.targets.push(rec);
	var dial = new ModalDialog (container, 300, 150, '', false);
	dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>KabaListics : ' + translate('Message') + '</b></center></div>';
	dial.getContentDiv().innerHTML = translate('Bookmark saved');
	setTimeout (function(){dial.destroy()}, 1000);
}
function set_defense_forces (container, city_id, units, notify){
	var dial = new ModalDialog (container, 300, 165, '', false, null);
	dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>KabaListics : ' + translate('Message') + '</b></center></div>';
	dial.getContentDiv().innerHTML = translate ('Setting defense');
	MyAjax.setDefenseForce (city_id, units, callback);
	function callback (dat){
		if (dat.ok){
			if (notify)
				notify(true);
			dial.destroy();
		} else {
			dial.getContentDiv().innerHTML = translate ('Error while setting defense choice');
			dial.allowClose (true);
			if (notify)
				notify (false);
			return;
		}
	}
}
function updateTrainTable (table, type, resurrect) {
	var now = parseInt(serverTime());
	var mtClass = UID['row_marchMine'];
	// Clear table
	for (var row = 0; row < table.rows.length; row++) {  
		table.deleteRow(row);  
		row--;  
	}
	for (var cityIdx=0; cityIdx < Seed.cities.length; ++cityIdx) {
		if (Seed.cities[cityIdx] && Seed.cities[cityIdx].jobs && ((cityIdx != SPECTRAL_OUTPOST_ID && !resurrect) || (cityIdx == SPECTRAL_OUTPOST_ID && resurrect)) ) {
			var jobs = Seed.cities[cityIdx].jobs;
			var last = serverTime();
			var trains = [];
			for (var j=0; j < jobs.length; j++) {
				if (jobs[j].queue=='units' && jobs[j].unit_type && jobs[j].run_at > last && !resurrect) trains.push (jobs[j]);
				if (jobs[j].queue=='resurrection' && jobs[j].unit_type && jobs[j].run_at > last && resurrect) trains.push (jobs[j]);
			}
			var iRow, iCell;
			iRow = table.insertRow(-1);
			iRow.className = mtClass;
			iCell = iRow.insertCell(-1);
			iCell.style.textAlign = 'left';
			iCell.style.width = '20%';
			iCell.innerHTML = '<b>'+ ( (cityIdx == CAPITAL_ID) ? Seed.cities[cityIdx].name : translate(Seed.cities[cityIdx].name) ) +'</b>';

			if (trains.length == 0) {
				iCell = iRow.insertCell(-1);
				iCell.innerHTML = translate('Idle');
			} else {
				trains.sort( function(a,b){ return a.run_at - b.run_at; } );
				for (var j=0; j < trains.length; j++) {
					var time_remaining = (trains[j].run_at-last > 0) ? trains[j].run_at-last : 0;
					var tot = '';
					if (j!=0) {
						iRow = table.insertRow(-1);
						iRow.className = mtClass;
						iCell = iRow.insertCell(-1);
						iCell.style.textAlign = 'left';
						iCell.style.width = '20%';
						iCell.innerHTML = '&nbsp;';
						if (j==trains.length-1)
							tot = ' &nbsp <B>('+ timestrShort((trains[j].run_at-serverTime() > 0) ? trains[j].run_at-serverTime() : 0) +')</b>';
					}
					iRow.setAttribute ('ref', cityIdx+'_'+trains[j].id);
					iCell = iRow.insertCell(-1);
					iCell.style.textAlign = 'left';
					iCell.style.width = '35%';
					iCell.innerHTML = nombreFormate(trains[j].quantity,' ') +' '+ translate(trains[j].unit_type);

					// Training cancel Button
					iCell = iRow.insertCell(-1);
					iCell.style.width = '10%';
					var button = document.createElement('input');
					button.type = 'button';
					button.setAttribute ('ref', cityIdx+'_'+trains[j].id);
					button.value = 'X';
					if (trains[j].cancelled) {
						button.disabled = true;
						button.className = UID['bnt_disabled'] + ' thin';
					} else {
						button.className = UID['bnt_red'] + ' thin';
						button.addEventListener ('click', function (event){
							var self = event.target;
							self.disabled = true;
							self.className = UID['bnt_disabled'] + ' thin';
							var ids = self.getAttribute('ref').split('_');
							var found = false;
							var jobs = Seed.cities[ids[0]].jobs;
							for (var x=0; x<jobs.length && !found; x++) {
								if (jobs[x].id == ids[1]) {
									found = true;
									jobs[x].cancelled = true;
									var desc = nombreFormate(jobs[x].quantity,' ') +' '+ translate(jobs[x].unit_type);
									MyAjax.cancelTraining (ids[1], function (r) {
										if (r.ok && r.dat.result.success) {
											verboseLog(translate('Training job cancelled') + ' ('+ desc +')');
										}
									});
								}
							}
						}, false);
					}
					iCell.appendChild (button);

					iCell = iRow.insertCell(-1);
					iCell.style.textAlign = 'left';
					iCell.style.width = '35%';
					iCell.innerHTML = '<font color=' + TIMER_COLOR + '>' + timestr(time_remaining,true) + '</font>' + tot;

					last = trains[j].run_at;
				}   
			}
			iRow = table.insertRow(-1);
			iCell = iRow.insertCell(-1);
			iCell.style.textAlign = 'left';
			iCell.style.width = '20%';
			iCell.innerHTML = '&nbsp;';
		}
	}
}


//******************************** Info Tab *****************************
Tabs.Info = {
	tabOrder		: INFO_TAB_ORDER,
	tabLabel		: 'Info',
	tabDisabled		: !INFO_TAB_ENABLE,
	container		: null,
	timer			: null,
	contentType		: 0, // 0 = overview, 1 = inventory, 2 = quests, 3 = Help/About, 4 = My might
	troopsContentType: 0, // 0 = Might, 1 = Food consumption, 2 = Statistics
	infoScrollPos	: 0,
	lastSubTab		: 'tabInfoOverview',
	refreshPlayerBusy : false,

	init : function (div){
		var t = Tabs.Info;

		// Jawz - Purge completed & claimed quests
		for (var i=0; i<Seed.quests.category.length; i++) {
			for (var j=0; j<Seed.quests.list[Seed.quests.category[i]].length; j++) {
				var quest		= Seed.quests.list[Seed.quests.category[i]][j];
				var claimed = false;
				if (Seed.player.quests.claimed) {
					for (var x=0; x<Seed.player.quests.claimed.length && !claimed; x++) {
						if (name == Seed.player.quests.claimed[x]) claimed = true;
					}
				}
				if (claimed) {
					Seed.quests.list[Seed.quests.category[i]].splice(j,1);
				}
			}
		}

		t.container = div;
		div.innerHTML = '<div class=' + UID['title_main'] + ' style="padding-top:3px; padding-bottom:3px;">'
		+'<table width=80% align=center>'
		+'	<tr align=center><td width="100px"><a id='+ setUID('tabInfo_ScriptUpdate') +' style="color:#FFFFFF;text-decoration:none;">'+ translate('Version update') +'</a></td>'
		+'		<td width="100px"><a href="'+ Data.options.wikiUrl + '" target="_blank" style="color:#FFFFFF;text-decoration:none;">'+ kWikiLink +'</a></td>'
		+'		<td width="100px"><a href="'+ Data.options.forumUrl + '" target="_blank" style="color:#FFFFFF;text-decoration:none;">'+ kForumLink +'</a></td>'
		+'</tr></table></div>'
		+'<table width=100%><tr>'
		+'	<td width=25%><input id='+ setUID('tabInfo_Refresh') +' type=button value="'+ translate('Refresh') +'"></input></td>'
		+'	<td width=25% align=center><input id='+ setUID('tabInfo_Toggle') +' type=button value="'+ translate('Toggle Flash') +'"></input></td>'
		+'	<td width=25% align=center>' + ((REALM_URL == null || REALM_URL == '' || !REALM_URL) ? '' : '<input id='+ setUID('tabInfo_Reload') +' type=button value="'+ translate('Reload') +'"></input>') + '</td>'
		+'	<td width=25% align=center></td>'
		+'</tr></table>'
		+'<ul class=tabs>'
		+'	<li class="tab first"><a id='+ setUID('tabInfoOverview') +'>'+ translate('Overview') +'</a></li>'
		+'	<li class=tab><a id='+ setUID('tabInfoInventory') +'>'+ translate('Inventory') +'</a></li>'
		+'	<li class=tab><a id='+ setUID('tabInfoQuests') +'>'+ translate('Quests') +'</a></li>'
		+'	<li class=tab><a id='+ setUID('tabInfoTroops') +'>'+ translate('Troops') +'</a></li>'
		+'	<li class=tab><a id='+ setUID('tabInfoHelp') +'>'+ translate('Help/About') +'</a></li>'
		+'</ul>'
		+'<div id='+ setUID('tabInfo_Content') +' class="' + UID['scrollable'] + '" style="margin-top:1px !important; height:650px; max-height:650px;"></div>';
		document.getElementById(UID['tabInfo_Refresh']).addEventListener ('click', t.refresh, false);
		if (REALM_URL && REALM_URL != null && REALM_URL != '') document.getElementById(UID['tabInfo_Reload']).addEventListener ('click', reloadTools, false);
		document.getElementById(UID['tabInfo_Toggle']).addEventListener ('click', toggleFlash, false);
		document.getElementById(UID['tabInfoOverview']).addEventListener ('click', t.tabInfoOverview, false);
		document.getElementById(UID['tabInfo_ScriptUpdate']).addEventListener ('click', AutoUpdater.manualCheck, false);
		document.getElementById(UID['tabInfoInventory']).addEventListener ('click', t.tabInfoInventory, false);	
		document.getElementById(UID['tabInfoQuests']).addEventListener ('click', t.tabInfoQuests, false);	
		document.getElementById(UID['tabInfoTroops']).addEventListener ('click', t.tabInfoTroops, false);	
		document.getElementById(UID['tabInfoHelp']).addEventListener ('click', t.tabInfoHelp, false);	
		t.contentType = Data.options.info.current_tab;
		t.show();
	},
	show : function (){
		var t = Tabs.Info;
		switch (isEmpty(t.contentType, 0)) {
			case 0: t.tabInfoOverview(); break;
			case 1: t.tabInfoInventory(); break;
			case 2: t.tabInfoQuests(); break;
			case 3: t.tabInfoHelp(); break;
			case 4: t.tabInfoTroops(); break;
		}
	},
	hide : function (){
		var t = Tabs.Info;
		clearTimeout (t.timer);
	},
	onUnload : function (){
		var t = Tabs.Info;
		logit ('===============  Tabs.Info.onUnload');
		Data.options.info.current_tab = t.contentType;
	},

	tabInfoOverview : function (){
		var t = Tabs.Info;
		//logit (inspectObj (Seed.s, 8, 1));
		clearTimeout (t.timer);

		document.getElementById(UID[t.lastSubTab]).className='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabInfoOverview']).className='selected';
		document.getElementById(UID['tabInfoOverview']).style.zIndex=1;
		t.lastSubTab = 'tabInfoOverview';
		t.contentType = 0;
		Data.options.info.current_tab = t.contentType;

		var city = Seed.cities[CAPITAL_ID];
		var m = '<div class=' + UID['status_ticker'] + '>';
		var alliance_name = (Seed.player.alliance) ? Seed.player.alliance.name : '';
		var wallStatus = translate((Seed.cities[CAPITAL_ID].defended) ? 'Defend' : 'Hiding').toUpperCase();
		m += '<div class=' + UID['subtitle'] + '><table class=' + UID['table'] + '>'
			+'<tr><td align=left width=35%>'+ city.name +'</td>'
			+'<td align=center width=30%>'+ city.x +','+ city.y + '</td>'
			+'<td align=center width=200px><font color=yellow>' + alliance_name +'</font></td>'
			+'<TD width=35% align=right><input id='+ setUID('tabInfo_setDefense') +' type=button value='+ wallStatus +' class=' + UID[(Seed.cities[CAPITAL_ID].defended ? 'btn_off' : 'btn_on')] + '></input></td>'
			+'</tr></table></div>';

		m += dispCurrRessources(CAPITAL_ID);
		m += dispCurrPopulation(CAPITAL_ID)
		m += dispUnits(CAPITAL_ID)
		+'<br>'
		+'<table class=' + UID['table'] + '>' + dispProtection() + simpleSoundPlayer.alertString + dispNanoCollect ()
		+'	<tr>'
		+'		<td class=right width=20%>'+ translate('Marching') +': </td>'
		+'		<td width=30%>'+ Seed.numMarches +'</td>'
		+'		<td class=right width=20%>'+ translate('Wildernesses') +': </td>'
		+'		<td width=30%>'+ dispWildsCount() +'</td>'
		+'	</tr>'
		+ dispDragonJob(CAPITAL_ID)
		+ dispOutpostJob(CAPITAL_ID)
		+ dispBuildingJob(CAPITAL_ID)
		+ dispResearchJob(CAPITAL_ID)
		+ dispTrainingJobs(CAPITAL_ID)
		+'</table>'
		+'</div>';

		// Outposts ...
		if (Seed.cities.length > 0){
			for (var cityIdx=1; cityIdx < Seed.cities.length; ++cityIdx){
				if (Seed.cities[cityIdx]) {
					m += '<div class=' + UID['status_ticker'] + ' style="margin-top:6px !important">'
					+ t.cityTitle(cityIdx)
					+'<table class=' + UID['table'] + ' width=100%>'
					+ dispDragonJob(cityIdx)
					+ dispOutpostJob(cityIdx)
					+ dispBuildingJob(cityIdx) 
					+ dispTrainingJobs(cityIdx)
					+ dispResurrectionJobs(cityIdx)
					+'</table>'
					+'</div>';
				}
			}
		}
		m += '<br>'
		+'<table style="margin-top:3px" width=100%>'
		+'	<tr class=' + UID['row_headers'] + ' align=center>'
		+'		<td width=50%>'+ translate('Generals').toUpperCase() +'</td>'
		+'		<td width=50%>'+ translate('Great dragons').toUpperCase() +'</td>'
		+'	</tr>'
		+'	<tr valign=top align=center>'
		+'		<td width=50% style="border-right: 1px solid;">';

		// Generals
		m += '		<table class=' + UID['table'] + '>';
		var loc = '';
		for (var i=0; i < city.generals.length; i++)
		{
			if (Seed.marches){
				for (var pm in Seed.marches) {
					// The general object will be null if the march is a transport
					if (Seed.marches[pm].march_type != "TransportMarch" && Seed.marches[pm].march_type != "SpyMarch") {
						try {
							if (city.generals[i].name == Seed.marches[pm].general.first_name) {
								loc = Seed.marches[pm].x + ',' + Seed.marches[pm].y;
								if (Seed.marches[pm].status == 'encamped') className = 'bluejwl';
								else className = 'jewel';
							}
						} catch (e) {
							actionLog(translate('Error') + ': '+ 'general first_name not available' + e.name + ' ' + e.message);
						}
					}
				}
			}

			m += '		<tr>'
			+'			<td width=50% align=right><font color="#000000">'+ city.generals[i].name +' ('+ city.generals[i].rank +')</font></td>'
			+'			<td width=50%>'+ (city.generals[i].busy ? '<span class="'+className+'">[' + loc +']</span>' :'') +'</td>'
			+'			</tr>';
		}
		m += '		</table>'
			+'	</td>'
			+'	<td width=50% style=" padding-left:7px">'
			+'		<table class=' + UID['table'] + '>';
		for (var gd=0; gd < Seed.dragonList.length; gd++) {
			var dragon = Seed.dragons[Seed.dragonList[gd].type];
			var dragStatus = '';
			if (((dragon.life / dragon.maximum_life) >= 0.75) && dragon.is_in_city && dragon.can_attack) dragStatus = translate ('Ready');
			else if (!dragon.is_in_city && dragon.can_attack) dragStatus = translate ('Attacking');
			else if (!dragon.can_attack) dragStatus = translate ('Not ready') + countArmorDragon(Seed.dragonList[gd].type);
			else if ((dragon.life / dragon.maximum_life) < 0.75) dragStatus = translate ('Healing');
			else dragStatus = translate ('Not ready') + countArmorDragon(Seed.dragonList[gd].type);
			m += '		<tr>'
			+'			<td width=50% align=right><font color="#000000">'+ translate(dragon.name) +'</font></td>'
			+'			<td width=50%><span class=jewel>' + dragStatus +'</span></td>'
			+'			</tr>';
		}

		m += '		</table>'
		+'		</td>'
		+'	</tr>'
		+'</table>'

		// Marches, building, research, training
		document.getElementById(UID['tabInfo_Content']).innerHTML = m;
		document.getElementById(UID['tabInfo_Content']).scrollTop = t.infoScrollPos;
		document.getElementById(UID['tabInfo_Content']).addEventListener('scroll', onScroll, false);
		document.getElementById(UID['tabInfo_setDefense']).addEventListener ('click', switchDefense, false);
		t.timer = setTimeout (t.show, 1000);

		function onScroll (event){
			if (t.contentType == 0)
				t.infoScrollPos = document.getElementById(UID['tabInfo_Content']).scrollTop;
		}

		function countArmorDragon (dragon_type) {
			var armors = ['BodyArmor', 'ClawGuards', 'TailGuard', 'Helmet'];
			var ret = 0;
			for (var i = 0; i < armors.length; i++) {
				if ( isEmpty(Seed.player.items[ dragon_type + armors[i] ],0) !== 0 ) {
					ret++;
				}
			}
			if (ret == 4) return '';
			else return ' (' + translate('Got') + ' ' + ret + '/4)';
		}
		function dispCurrRessources (cityIdx){
			var m = '<table style="margin-top:3px" width=100% class=' + UID['row_style'] +'>'
				+'	<tr class=' + UID['row_headers'] + ' align=center>'
				+'		<td width=20%>' + translate('Type') + '</td>'
				+'		<td width=20%>' + translate('Reserves') + '</td>'
				+'		<td width=15%>' + translate('Per Hour') + '</td>'
				+'		<td width=20%>' + translate('Consumption') + '</td>'
				+'		<td width=25%>' + translate('Capacity') + '</td>'
				+'	</tr>';

			for (var p=0; p<all_resource_types.length; p++){
				var lock_food = false;
				var production = Seed.cities[cityIdx].figures.resource_rates[all_resource_types[p]];
				var actualStock = nombreFormate(parseInt(Seed.cities[cityIdx].resources[all_resource_types[p]]));
				if (all_resource_types[p] == 'food' && Seed.player.boosts && Seed.player.boosts.collect_resources && parseInt(Seed.cities[cityIdx].resources[all_resource_types[p]]) > production.capacity) lock_food = true;
				m += '	<tr valign=top align=center>'
					+'		<td align=right class=jewel>' + translate(all_resource_types[p]) + '</td>'
					+'		<td align=right class=jewel>' + actualStock + '</td>'
					+'		<td align=right class=jewel>' + (lock_food ? '<font color=blue><b>0</b></font>' : nombreFormate(parseInt(production.rate))) + '</td>'
					+'		<td align=right class=jewel>' + nombreFormate(parseInt(production.unit_consumption || production.general_salaries || 0)) + '</td>'
					+'		<td align=right class=jewel>' +	( production.capacity === 1E+18 ? translate('Unlimited') : nombreFormate(production.capacity) ) + '</td>'
					+'	</tr>';
			}
			m += '</table>';
			return m;
		}
		function dispCurrPopulation(cityIdx){
			var city = Seed.cities[cityIdx].figures.population;
			var m = '<table style="margin-top:3px" width=100%>'
				+'	<tr class=' + UID['row_headers'] + ' align=center>'
				+'		<td width=20%>' + translate('Population') + '</td>'
				+'		<td width=20%>' + translate('Laborers') + '</td>'
				+'		<td width=20%>' + translate('Army') + '</td>'
				+'		<td width=20%>' + translate('IdlePopulation').replace( translate('Population'), '' ) + '</td>'
				+'		<td width=20%>' + translate('Capacity') + '</td>'
				+'	</tr>'
				+'	<tr>'
				+'		<td align=right>' + nombreFormate(city.current) + '</td>'
				+'		<td align=right>' + nombreFormate(city.laborers) + '</td>'
				+'		<td align=right>' + nombreFormate(city.armed_forces) + '</td>'
				+'		<td align=right>' + nombreFormate(city.current - city.laborers - city.armed_forces) + '</td>'
				+'		<td align=right>' + nombreFormate(city.limit) + '</td>'
				+'	</tr>'
				+'</table>';
			return m;
		}
		function dispUnits (cityIdx){
			var m = '<table class=' + UID['row_style'] + ' style="margin-top:3px" width=100%>'
				+'	<tr class=' + UID['row_headers'] + ' align=center>'
				+'		<td width=40%>' + translate('Troops') + '</td>'
				+'		<td width=15%>' + translate('Total') + '</td>'
				+'		<td width=15%>' + translate('Defense') + '</td>'
				+'		<td width=15%>' + translate('In city') + '</td>'
				+'		<td width=15%>' + translate('In march') + '</td>'
				+'	</tr>';
			for (var i=0; i < all_unit_types.length; i++){
				var numTroops = getTroopNumbers(city, all_unit_types[i]);
				m += '	<tr valign=top>'
					+'		<td class=right width=40%>'+ translate(all_unit_types[i]) +':</td>'
					+'		<td align=right width=15%>'+ nombreFormate(numTroops.total,' ') +'</td>'
					+'		<td align=right width=15%>'+ nombreFormate(numTroops.indefense,' ') +'</td>'
					+'		<td align=right width=15%>'+ nombreFormate(numTroops.incity,' ') +'</td>'
					+'		<td align=right width=15%>'+ (numTroops.marches?'&nbsp;+&nbsp;<b>' + nombreFormate(numTroops.marches,' ') + '</b>':'') +'</td>'
					+'	</tr>';
			}
			m += '</table>';
			return m;
		}
		function dispProtection (){
			var m = '';
			if (Seed.cities[CAPITAL_ID].protected && Seed.player.boosts.safety && Seed.player.boosts.safety > serverTime()){
				var expir = timestr(Seed.player.boosts.safety - serverTime(), true);
				m += '<tr><td width=100% colspan=4><div class=' + UID['info_protect'] + '>Protection : '+ expir +'</div></td></tr>';
			}
			return m;
		}
		function dispNanoCollect (){
			var m = '';
			if (Seed.player.boosts && Seed.player.boosts.collect_resources && Seed.player.boosts.collect_resources > serverTime()){
				var expir = timestr(Seed.player.boosts.collect_resources - serverTime(), true);
				m += '<tr><td width=100% colspan=4><div class=' + UID['info_protect'] + '>'+translate('boost-collect-week') +' : '+ expir +'</div></td></tr>';
			}
			return m;
		}
		function dispWildsCount (){
			var max = isEmpty(Seed.player.max_wildernesses, 0);
			var cur = isEmpty(Seed.player.player_wildernesses.length, 0);
			var m = (cur < max) ? '<span class=' + UID['bold_red'] + '>'+ cur +'</span>' : cur;
			m += ' / ' + max;
			return m;
		}
		function dispDragonJob (cityIdx){
			var m = '';
			var job = getDragonJob (cityIdx);
			if (job && job.run_at > serverTime()) {
				m += '<tr><td class=right width=20%>' + translate('Healing') + ':</td>'
				  +'	<td width=50% colspan=2><span class=' + UID['bold_red'] + '>'+ translate ('Dragon healing') + '</span></td>'
				  +'	<td width=30%><font color=' + TIMER_COLOR + '>'+ timestr(job.run_at - serverTime(), true) +'</font></td></tr>';
			}
			return m;
		}
		function dispOutpostJob (cityIdx){
			var m = '';
			var job = getOutpostJob (cityIdx);
			if (job && job.run_at > serverTime()) {
				m += '<tr><td class=right width=20%>' + translate('Repairing') + ':</td>'
				  +'	<td width=50% colspan=2><span class=' + UID['bold_red'] + '>'+ translate ('Outpost damages') + '</span></td>'
				  +'	<td width=30%><font color=' + TIMER_COLOR + '>'+ timestr(job.run_at - serverTime(), true) +'</font></td></tr>';
			}
			return m;
		}
		function dispBuildingJob (cityIdx){
			var m = '<tr><td width=20% class=right>'+ translate('Building') +': </td>';
			var job = getBuildingJob (cityIdx);
			if (job && job.job.run_at > serverTime())
			{
				m += '<td width=50% align=left colspan=2>'+ translate(job.building.type) +' ('+ job.job.level +') &nbsp;</td>'
				  + '<td width=30%><font color=' + TIMER_COLOR + '>' + timestr(job.job.run_at - serverTime(), true) + '</font></td>'
				  + '</tr>';
			} else {
				m += '<td align=left width=80% colspan=3><span class=' + UID['bold_red'] + '>' + translate('None').toUpperCase() + '</span></td></tr>';
			}
			return m;
		}
		function dispResearchJob (cityIdx){
			var m = '<tr>'
				+ '		<td class=right width=20%>'+ translate('Researching') +': </td>';
			var job = getResearchJob (cityIdx);
			if (job && job.run_at > serverTime())
			{
				m += '<td width=50% align=left colspan=2>'+ translate(job.research_type) +' ('+ job.level +') &nbsp;</td>'
				  + '<td width=30%><font color=' + TIMER_COLOR + '>' + timestr(job.run_at - serverTime(), true) + '</font></td>'
				  +'</tr>';
			} else {
				m += '<td align=left width=80% colspan=3><span class=' + UID['bold_red'] + '>' + translate('None').toUpperCase() + '</span></td></tr>';
			}
			return m;
		}
		function dispTrainingJobs (cityIdx){
			var m = '', last = serverTime(), trains = [];
			for (var i=0; i < Seed.cities[cityIdx].jobs.length; i++){
				if (Seed.cities[cityIdx].jobs[i].queue=='units' && 
					Seed.cities[cityIdx].jobs[i].unit_type && 
					Seed.cities[cityIdx].jobs[i].run_at > last
					){
						trains.push (Seed.cities[cityIdx].jobs[i]);
				}
			}
			trains.sort(function(a,b){return a.run_at-b.run_at});
			for (var i=0; i < trains.length; i++){
				var left='', tot='', timeRemaining = 0;
				if (i==0){
					left = translate('Training') + ':';
				}
				else if (i==trains.length-1) {
					timeRemaining = (trains[i].run_at-serverTime() > 0) ? trains[i].run_at-serverTime() : 0;
					tot = '&nbsp;<b>(' + timestrShort(timeRemaining) + ')</b>';
				}
				timeRemaining = (trains[i].run_at-last > 0) ? trains[i].run_at-last : 0;
				m += '<tr>'
				+ '		<td class=right width=20%>' + left + '</td>'
				+ '		<td align=left width=50% colspan=2>' + nombreFormate(trains[i].quantity, ' ') + '&nbsp;&nbsp;' + translate(trains[i].unit_type) + '&nbsp;</td>'
				+ '     <td width=30%><font color=' + TIMER_COLOR + '>' + timestr(timeRemaining, true) + '</font>&nbsp' + tot + '</td>'
				+ '</tr>';
				last = trains[i].run_at;
			}      
			return m;
		}
		function dispResurrectionJobs (cityIdx){
			var m = '', last = serverTime(), trains = [];
			for (var i=0; i < Seed.cities[cityIdx].jobs.length; i++){
				if (Seed.cities[cityIdx].jobs[i].queue=='resurrection' && 
					Seed.cities[cityIdx].jobs[i].unit_type && 
					Seed.cities[cityIdx].jobs[i].run_at > last
					){
						trains.push (Seed.cities[cityIdx].jobs[i]);
				}
			}
			trains.sort(function(a,b){return a.run_at-b.run_at});
			for (var i=0; i < trains.length; i++){
				var left='', tot='', timeRemaining = 0;
				if (i==0){
					left = translate('Resurrection') + ':';
				}
				else if (i==trains.length-1) {
					timeRemaining = (trains[i].run_at-serverTime() > 0) ? trains[i].run_at-serverTime() : 0;
					tot = '&nbsp;<b>(' + timestrShort(timeRemaining) + ')</b>';
				}
				timeRemaining = (trains[i].run_at-last > 0) ? trains[i].run_at-last : 0;
				m += '<tr>'
				+ '		<td class=right width=20%>' + left + '</td>'
				+ '		<td align=left width=50% colspan=2>' + nombreFormate(trains[i].quantity, ' ') + '&nbsp;&nbsp;' + translate(trains[i].unit_type) + '&nbsp;</td>'
				+ '     <td width=30%><font color=' + TIMER_COLOR + '>' + timestr(timeRemaining, true) + '</font>&nbsp' + tot + '</td>'
				+ '</tr>';
				last = trains[i].run_at;
			}      
			return m;
		}
		function switchDefense (event){
			var t = Tabs.Info;
			var button		= event.target;
			var cityId 		= Seed.cities[CAPITAL_ID].id;
			var wallStatus	= Seed.cities[CAPITAL_ID].defended;
			var targMsg		= translate('Switching defense');
			verboseLog(targMsg +' '+ translate('attempted'));
			new MyAjax.switchDefense (cityId, wallStatus, function (rslt){
				if (rslt.ok){
					verboseLog(targMsg +' '+ translate('Successfully'));
					actionLog(targMsg);
					button.className = UID[(Seed.cities[CAPITAL_ID].defended ? 'btn_off' : 'btn_on')];
					button.value = translate(Seed.cities[CAPITAL_ID].defended ? 'Defend' : 'Hiding' ).toUpperCase();
				} else {
					verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
				}
			});
			var state = Seed.cities[CAPITAL_ID].defended;
			button.className = UID[(state ? 'btn_off' : 'btn_on')];
			button.value = translate(state ? 'Defend' : 'Hiding').toUpperCase();
		}
	},

	tabInfoInventory : function (){
		var t = Tabs.Info;
		clearTimeout (t.timer);
		document.getElementById(UID[t.lastSubTab]).className='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabInfoInventory']).className='selected';
		document.getElementById(UID['tabInfoInventory']).style.zIndex=1;
		t.lastSubTab = 'tabInfoInventory';
		t.contentType = 1;
		Data.options.info.current_tab = t.contentType;
		var m = '<div class=' + UID['status_ticker'] + '>';
		m += t.cityTitle(CAPITAL_ID);
		m += '<table style="margin-top:3px" width=100%>';
		var city = Seed.cities[CAPITAL_ID];
		for (var type in Seed.items) {
			var items = [];
			for (item=0; item<Seed.items[type].length; item++){
				var is_armor = false;
				for (var a=0; a<armor_item_list.length && !is_armor; a++)
					if (Seed.items[type][item] == armor_item_list[a])
						is_armor = true;
				num = isEmpty(Seed.player.items[Seed.items[type][item]],0);
				if (num > 0 && !is_armor) items.push ({desc:translate(Seed.items[type][item]), qty:num});
			}
			if (items.length > 0) {
				items.sort (function(a, b){a = a.desc.toLowerCase(); b = b.desc.toLowerCase(); if (a>b) return 1; if (a<b) return -1; return 0;});
				m+= '<tr class=' + UID['row_headers'] + ' align=center><td style="border-bottom: 1px solid; border-bottom: 1px solid;" colspan=2>'+ translate(type) +'</td></tr><tr valign=top align=center>'
				+'<td width=50% style="border-right: 1px solid;"><table class=' + UID['row_style'] + ' width=100%>';
				for (var i=0; i<Math.ceil(items.length/2); i++)
					m += '<tr><td align=left width=80%>'+ items[i].desc +'</td><td align=left width=20%>'+ nombreFormate(items[i].qty,' ') +'</td></tr>';
				m+= '</table></td><td width=50%><table class=' + UID['row_style'] + ' width=100%>';
				for (var i=Math.ceil(items.length/2); i<items.length; i++)
					m += '<tr><td align=left width=80%>'+ items[i].desc +'</td><td align=left width=20%>'+ nombreFormate(items[i].qty,' ') +'</td></tr>';
				m += '</table></td></tr><tr><td> &nbsp </td></tr>';
			}
		}
		m += '</table></div>';
		document.getElementById(UID['tabInfo_Content']).innerHTML = m; 
		t.timer = setTimeout (t.show, 1000);
	},

	tabInfoQuests : function (){
		var t = Tabs.Info;
		document.getElementById(UID[t.lastSubTab]).className='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabInfoQuests']).className='selected';
		document.getElementById(UID['tabInfoQuests']).style.zIndex=1;
		t.lastSubTab = 'tabInfoQuests';
		t.contentType = 2;
		Data.options.info.current_tab = t.contentType;

		var city = Seed.cities[CAPITAL_ID];
		var m = '<div class=' + UID['status_ticker'] + ' stype="width:540px; max-width:540px;">';
		m += t.cityTitle(CAPITAL_ID);
		m += '<table style="margin-top:3px" width=100%>';

		for (var i=0; i<Seed.quests.category.length; i++) {
			if (Data.options.collapsed.quests[i] == undefined) {
				Data.options.collapsed.quests[i] = false;
			}
		}

		var cl = [], ql = [];
		for (var i=0; i<Seed.quests.category.length; i++) {
			var questListId = 'tabInfo_questList_' + i;
			var categoryId 	= 'tabInfo_categ_' + i;
			var first = true;
			for (var j=0; j<Seed.quests.list[Seed.quests.category[i]].length; j++) {
				var quest		= Seed.quests.list[Seed.quests.category[i]][j];
				var questId 	= 'tabInfo_quest_' + i + '_' + j;
				var questFbId 	= 'tabInfo_QFb_' + i + '_' + j;
				var questname	= Translation.xml['quests'][_normalize(quest.name)];
				var completed	= isCompleted (quest.name);
				var claimed		= isClaimed (quest.name);
				if (!claimed) {
					if (first) {
						m += '<tr class=' + UID['row_headers'] + ' align=center>'
						  +'	<td style="border-bottom: 1px solid; border-bottom: 1px solid;" width=100%>'
						  +'		<A><div id=' + setUID(categoryId) + ' ref="' + i + '" >'+ translate(Seed.quests.category[i]) +'</div></A>'
						  +'	</td>'
						  +'</tr>'
						  +'<tr valign=top>'
						  +'	<td width=100%>'
						  +'		<div id=' + setUID(questListId) + '>'
						  +'			<table class=' + UID['row_style'] + '>';
						cl.push(UID[categoryId]);
						first = false;
					}

					var recommended = (quest.recommended && !completed) ? '<span class=' + UID['red'] + '>'+ questname +'</span>' : questname;
					m += '<tr valign=top><td align=left width="160px" style="padding-bottom: 3px; border-bottom: 1px solid #898989;">' + recommended + '</td>'
					  +'	<td align=left width="328px" style="padding-bottom: 3px; border-bottom: 1px solid #898989;">' + Translation.xml['quests'][_normalize(quest.name+'-objectives')] + '<br>'
					  +'		<font color=' + TIMER_COLOR + '>' + getRewards (quest.reward) + '</font>';
					if (completed) {
						m +='<td align=center valign=middle width="50px" style="padding-bottom: 3px; border-bottom: 1px solid #898989;"><div id=' + setUID(questFbId) + '>'
						  +'<input id='+ setUID(questId) +' class="' + UID['bnt_green'] + ' small" ref="' + i + '_' + j + '" style="width:auto !important;" type=submit value=" ' + translate('Claim') + ' " />'
						  +'</div></td>'
						  +'</tr>';
						ql.push(UID[questId]);
					} else m+= '<td width="50px" style="padding-bottom: 3px; border-bottom: 1px solid #898989;"></td></tr>';
				}
			}
			if (!first) m += '</table></div></td></tr>';
		}
		m += '</table></div>';
		document.getElementById(UID['tabInfo_Content']).innerHTML = m;
		for (var c=0; c<cl.length; c++) {
			document.getElementById(cl[c]).addEventListener('click', toggleHideShow, false);
			var categ = document.getElementById(cl[c]).getAttribute('ref');
			var id = 'tabInfo_questList_' + categ;
			var el = document.getElementById(UID[id]);
			if (Data.options.collapsed.quests[categ])
				el.style.display = 'none';
			else
				el.style.display = 'block';
		}

		for (var q=0; q<ql.length; q++)
			document.getElementById(ql[q]).addEventListener('click', claimRewards, false);

		function isClaimed (name){
			var found = false;
			if (Seed.player.quests.claimed) {
				for (var x=0; x<Seed.player.quests.claimed.length && !found; x++) {
					if (name == Seed.player.quests.claimed[x]) found = true;
				}
			}
			return found;
		}
		function isCompleted (name){
			var found = false;
			if (Seed.player.quests.completed) {
				for (var x=0; x<Seed.player.quests.completed.length && !found; x++) {
					if (name == Seed.player.quests.completed[x]) found = true;
				}
			}
			return found;
		}
		function getRewards (list) {
			var result = '';
			var tRes = [];
			for (var i in list) {
				if (list[i] > 0)
					tRes.push (nombreFormate(list[i],' ') + ' ' + translate (i)); 
			}
			if (tRes.length>0) result = tRes.join(', ');
			return result;
		}
		function toggleHideShow (event){
			var categ = event.target.getAttribute('ref');
			var id = 'tabInfo_questList_' + categ;
			var el = document.getElementById(UID[id]);
			if (el.style.display == 'none') {
				el.style.display = 'block';
				Data.options.collapsed.quests[categ] = false;
			} else {
				el.style.display = 'none';
				Data.options.collapsed.quests[categ] = true;
			}
		}
		function claimRewards (event){
			var id   = event.target.getAttribute('ref').split('_');
			var name = Seed.quests.list[Seed.quests.category[id[0]]][id[1]].name;
			event.target.disabled = true;
			Element.removeClassName(event.target, UID['bnt_green']);
			Element.addClassName(event.target, UID['bnt_disabled']);
			var FBid = 'tabInfo_QFb_' + event.target.getAttribute('ref');
			var FBel = document.getElementById(UID[FBid]);
			new MyAjax.claimQuest (name, function (rslt) {
				if (rslt.ok) {
					actionLog('<B>' + translate('Quest') + ' ' + name + '</B> ' + translate('claimed') + ' ' + translate('Successfully'));
					FBel.innerHTML = '<font color=#898989>' + translate('Claimed') + '</font>';
				} else {
					actionLog(translate('Claiming quest') + ' ' + name +' '+ translate('failed and returned error') +': '+ rslt.errmsg);
					FBel.innerHTML = '<font color=#AA0000><B>' + translate('Error') + '</b></font>';
				}
			});	
		}
		function _normalize (str){
			return str.toLowerCase().replace(/_/g,'-');
		}
	},

	tabInfoTroops : function (){
		var t = Tabs.Info;
		document.getElementById(UID[t.lastSubTab]).className='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabInfoTroops']).className='selected';
		document.getElementById(UID['tabInfoTroops']).style.zIndex=1;
		t.lastSubTab = 'tabInfoTroops';
		t.contentType = 4;
		Data.options.info.current_tab = t.contentType;
		var m = '<div class=' + UID['title'] + '>'+ translate('Troops') +' '+ translate('Overview') +'</div>'
			+'<div class=' + UID['status_ticker'] + ' style="margin-bottom: 5px !important">'
			+'<ul class=tabs>'
			+'	<li class="tab first"><a id='+ setUID('tabInfoTroopsMight') +'>'+ translate('Might') +'</a></li>'
			+'	<li class="tab"><a id='+ setUID('tabInfoTroopsFood') +'>'+ translate('Consumption') +'</a></li>'
			+'	<li class="tab"><a id='+ setUID('tabInfoTroopsStats') +'>'+ translate('Statistics') +'</a></li>'
			+'</ul>'
			+'<div id='+ setUID('tabInfoTroops_Content') +' style="height:560px; ; max-height:560px; overflow-y:auto">';
		document.getElementById(UID['tabInfo_Content']).innerHTML = m;
		document.getElementById(UID['tabInfoTroopsMight']).addEventListener ('click', t.tabInfoTroopsMight, false);
		document.getElementById(UID['tabInfoTroopsFood']).addEventListener ('click', t.tabInfoTroopsFood, false);
		document.getElementById(UID['tabInfoTroopsStats']).addEventListener ('click', t.tabInfoTroopsStats, false);
		switch (t.troopContentType || 0) {
			case 0: t.tabInfoTroopsMight(); break;
			case 1: t.tabInfoTroopsFood(); break;
			case 2: t.tabInfoTroopsStats(); break;
		}
	},

	tabInfoTroopsMight : function (){
		var t = Tabs.Info;
		document.getElementById(UID['tabInfoTroopsMight']).className = 'selected';
		document.getElementById(UID['tabInfoTroopsMight']).style.zIndex=1;
		document.getElementById(UID['tabInfoTroopsFood']).className = '';
		document.getElementById(UID['tabInfoTroopsFood']).style.zIndex=0;
		document.getElementById(UID['tabInfoTroopsStats']).className = '';
		document.getElementById(UID['tabInfoTroopsStats']).style.zIndex=0;
		t.troopContentType = 0;
		Data.options.info.troop_sub_tab = t.troopContentType;
		var city = Seed.cities[CAPITAL_ID];
		var alliance_name = (Seed.player.alliance) ? Seed.player.alliance.name : '';
		var m = '<div class=' + UID['status_ticker'] + ' style="margin-top:10px !important">'
			+'<div class=' + UID['subtitle'] + '><table class=' + UID['table'] + '>'
			+'<tr><td align=left width=35%>'+ Seed.player.name + ' / ' + city.name +'</td>'
			+'<td align=center width=30%>'+ city.x +','+ city.y + '</td>'
			+'<td align=center width=200px><font color=yellow>' + alliance_name +'</font></td>'
			+'<td width=35% align=right><font color=yellow>' + nombreFormate(Seed.player.might) +'</font></td>'
			+'</tr></table></div>'
			+'<table class=' + UID['row_style'] + ' style="margin-top:3px" width=80%>'
			+'	<tr class=' + UID['row_headers'] + ' align=center>'
			+'		<td width=50%>' + translate('Troops') + '</td>'
			+'		<td width=20%>' + translate('Quantity') + '</td>'
			+'		<td width=10%>' + translate('Might') + '</td>'
			+'		<td width=20%>' + translate('Total') + '</td>'
			+'	</tr>';
		var total = 0;
		for (var i=0; i < all_unit_types.length; i++){
			var numTroops = getTroopNumbers(CAPITAL_ID, all_unit_types[i]);
			var unit_might = Seed.stats.unit[all_unit_types[i]].power;
			var total_might = numTroops.total * unit_might;
			total += total_might;
			m += '	<tr valign=top>'
				+'		<td class=right>'+ translate(all_unit_types[i]) +' :</td>'
				+'		<td align=right>'+ nombreFormate(numTroops.total,' ') +'</td>'
				+'		<td align=right>'+ nombreFormate(unit_might,' ') +'</td>'
				+'		<td align=right>'+ nombreFormate(total_might,' ') +'</td>'
				+'	</tr>';
		}
		m += '	<tr><td colspan=4>&nbsp</td></tr>'
			+'	<tr><td>&nbsp</td><td colspan=3 align=center><hr></td></tr>'
			+'	<tr valign=top>'
			+'		<td class=right>'+ translate('Troops') +' :</td>'
			+'		<td align=right></td>'
			+'		<td align=right></td>'
			+'		<td align=right><b>'+ nombreFormate(total,' ') +'</b></td>'
			+'	</tr>'
			+'	<tr valign=top>'
			+'		<td class=right>'+ translate('Building') + ' + ' + translate('Quests') +' :</td>'
			+'		<td align=right></td>'
			+'		<td align=right></td>'
			+'		<td align=right><b>'+ nombreFormate(Seed.player.might - total,' ') +'</b></td>'
			+'	</tr>'
			+'	<tr><td>&nbsp</td><td colspan=3 align=center><hr></td></tr>'
			+'	<tr valign=top>'
			+'		<td class=right>'+ translate('Total') +' :</td>'
			+'		<td align=right></td>'
			+'		<td align=right></td>'
			+'		<td align=right><font color=red><b>'+ nombreFormate(Seed.player.might) +'</b></font></td>'
			+'	</tr>'
			+'</table></div>';
		document.getElementById(UID['tabInfoTroops_Content']).innerHTML = m;
	},

	tabInfoTroopsFood : function (){
		var t = Tabs.Info;
		document.getElementById(UID['tabInfoTroopsMight']).className = '';
		document.getElementById(UID['tabInfoTroopsMight']).style.zIndex=0;
		document.getElementById(UID['tabInfoTroopsFood']).className = 'selected';
		document.getElementById(UID['tabInfoTroopsFood']).style.zIndex=1;
		document.getElementById(UID['tabInfoTroopsStats']).className = '';
		document.getElementById(UID['tabInfoTroopsStats']).style.zIndex=0;
		t.troopContentType = 1;
		Data.options.info.troop_sub_tab = t.troopContentType;
		var city = Seed.cities[CAPITAL_ID];
		var alliance_name = (Seed.player.alliance) ? Seed.player.alliance.name : '';
		setUID('tabInfoTroopFood_Sel');
		var m = '<div class=' + UID['status_ticker'] + ' style="margin-top:10px !important">'
			+'<div class=' + UID['subtitle'] + '><table class=' + UID['table'] + '>'
			+'<tr><td align=left width=35%>'+ Seed.player.name + ' / ' + city.name +'</td>'
			+'<td align=center width=30%>'+ city.x +','+ city.y + '</td>'
			+'<td align=center width=200px><font color=yellow>' + alliance_name +'</font></td>'
			+'<td width=35% align=right><font color=yellow>' + nombreFormate(Seed.player.might) +'</font></td>'
			+'</tr></table></div>'
			+'<table><tr>'
			+'	<td><label>' + translate('Troops') + '</label></td>'
			+'	<td><input type=radio name='+ UID['tabInfoTroopFood_Sel'] +' value="0" /></td><td align=left colspan=2><label>'+ translate('Total') +'</label></td>'
			+'	<td width="20px"></td>'
			+'	<td><input type=radio name='+ UID['tabInfoTroopFood_Sel'] +' value="1" /></td><td align=left width=15%><label>'+ translate('In city') +'</label></td>'
			+'	</tr>'
			+'</table><br>'
			+'<table class=' + UID['row_style'] + ' style="margin-top:3px" width=80%>'
			+'	<tr class=' + UID['row_headers'] + ' align=center>'
			+'		<td width=50%>' + translate('Troops') + '</td>'
			+'		<td width=20%>' + translate('Quantity') + '</td>'
			+'		<td width=10%>' + translate('Upkeep') + '</td>'
			+'		<td width=20%>' + translate('Consumption') + '</td>'
			+'	</tr>';
		var total = 0;
		var total_incity = 0;
		for (var i=0; i < all_unit_types.length; i++){
			var numTroops = getTroopNumbers(CAPITAL_ID, all_unit_types[i]);
			var unit_upkeep = Seed.stats.unit[all_unit_types[i]].upkeep.food;
			var total_upkeep = numTroops.total * unit_upkeep;
			var incity_upkeep = (numTroops.incity + numTroops.indefense) * unit_upkeep;
			total += total_upkeep;
			total_incity += incity_upkeep;
			m += '	<tr valign=top>'
				+'		<td class=right>'+ translate(all_unit_types[i]) +' :</td>'
				+'		<td align=right>'+ nombreFormate((Data.options.info.consumption_sel == 1) ? (numTroops.incity + numTroops.indefense) : numTroops.total) +'</td>'
				+'		<td align=right>'+ nombreFormate(unit_upkeep,' ') +'</td>'
				+'		<td align=right>'+ nombreFormate((Data.options.info.consumption_sel == 1) ? incity_upkeep : total_upkeep) +'</td>'
				+'	</tr>';
		}
		var unit_upkeep = Seed.greatDragons.GreatDragon[city.great_dragon.level].upkeep.food;
		m += '	<tr valign=top>'
			+'		<td class=right>'+ translate('GreatDragon') +' :</td>'
			+'		<td align=right></td>'
			+'		<td align=right>'+ nombreFormate(unit_upkeep,' ') +'</td>'
			+'		<td align=right>'+ nombreFormate(unit_upkeep,' ') +'</td>'
			+'	</tr>';
		total += unit_upkeep;
		total_incity += unit_upkeep;
		var figures = city.figures.resource_rates['food'];
		var rate = parseInt(figures.rate);
		var production = figures.production + (figures.production * figures.multipliers.wilderness) + (figures.production * figures.multipliers.boosts) + (figures.production * figures.multipliers.research);
		var total_rate = production - total;
		m += '	<tr><td colspan=4>&nbsp</td></tr>'
			+'	<tr><td>&nbsp</td><td colspan=3 align=center><hr></td></tr>'
			+'	<tr valign=top>'
			+'		<td class=right>'+ translate('Troops') +' :</td>'
			+'		<td align=right></td>'
			+'		<td align=right></td>'
			+'		<td align=right><b>'+ nombreFormate(-1 * ((Data.options.info.consumption_sel == 1) ? total_incity : total )) +'</b></td>'
			+'	</tr>'
			+'	<tr valign=top>'
			+'		<td class=right>'+ translate('Production') +' (' + translate('Per Hour') + ') :</td>'
			+'		<td align=right></td>'
			+'		<td align=right></td>'
			+'		<td align=right><b>'+ nombreFormate(production) +'</b></td>'
			+'	</tr>'
			+'	<tr><td>&nbsp</td><td colspan=3 align=center><hr></td></tr>'
			+'	<tr valign=top>'
			+'		<td class=right>'+ translate('Hourly rate') +' :</td>'
			+'		<td align=right></td>'
			+'		<td align=right></td>'
			+'		<td align=right><font color=red><b>'+ nombreFormate((Data.options.info.consumption_sel == 1) ? rate : total_rate ) +'</b></font></td>'
			+'	</tr>'
			+'</table></div>';
		document.getElementById(UID['tabInfoTroops_Content']).innerHTML = m;
		var r = document.getElementsByName(UID['tabInfoTroopFood_Sel']);
		for (i=0;i<r.length;i++) {
			r[i].addEventListener('change', enableChanged, false);
			r[i].checked = (r[i].value == Data.options.info.consumption_sel);
		}
		function enableChanged(event){
			var t = Tabs.Info;
			Data.options.info.consumption_sel = parseInt(event.target.value);
			t.tabInfoTroopsFood();
		}
	},

	tabInfoTroopsStats : function (){
		var t = Tabs.Info;
		document.getElementById(UID['tabInfoTroopsMight']).className = '';
		document.getElementById(UID['tabInfoTroopsMight']).style.zIndex=0;
		document.getElementById(UID['tabInfoTroopsFood']).className = '';
		document.getElementById(UID['tabInfoTroopsFood']).style.zIndex=0;
		document.getElementById(UID['tabInfoTroopsStats']).className = 'selected';
		document.getElementById(UID['tabInfoTroopsStats']).style.zIndex=1;
		t.troopContentType = 2;
		Data.options.info.troop_sub_tab = t.troopContentType;
		var city = Seed.cities[CAPITAL_ID];
		var alliance_name = (Seed.player.alliance) ? Seed.player.alliance.name : '';
		var m = '<div class=' + UID['status_ticker'] + ' style="margin-top:10px !important">'
			+'<div class=' + UID['subtitle'] + '><table class=' + UID['table'] + '>'
			+'<tr><td align=left width=35%>'+ Seed.player.name + ' / ' + city.name +'</td>'
			+'<td align=center width=30%>'+ city.x +','+ city.y + '</td>'
			+'<td align=center width=200px><font color=yellow>' + alliance_name +'</font></td>'
			+'<td width=35% align=right><font color=yellow>' + nombreFormate(Seed.player.might) +'</font></td>'
			+'</tr></table></div>'
			+'<table class=' + UID['row_style'] + ' style="margin-top:3px; overflow:auto; white-space:nowrap" width=100%>'
			+'	<tr class=' + UID['row_headers'] +'>'
			+'		<td valign=middle width=29%><b>'+ translate('Troops') +'</b></td>'
			+'		<td valign=middle width=12%><b>'+ translate('Melee') +'</b></td>'
			+'		<td valign=middle width=11%><b>'+ translate('Defense') +'</b></td>'
			+'		<td valign=middle width=11%><b>'+ translate('Speed') +'</b></td>'
			+'		<td valign=middle width=11%><b>'+ translate('Range') +'</b></td>'
			+'		<td valign=middle width=12%><b>'+ translate('Ranged') +'</b></td>'
			+'		<td valign=middle width=14%><b>'+ translate('Life') +'</b></td>'
			+'	</tr>';
		var total = 0;
		for (var i=0; i < all_unit_types.length; i++){
			var stats = Seed.stats.unit[all_unit_types[i]];
			m += '	<tr valign=top>'
				+'		<td class=right>'+ translate(all_unit_types[i]) +' :</td>'
				+'		<td align=right>'+ nombreFormate(stats.melee,' ') +'</td>'
				+'		<td align=right>'+ nombreFormate(stats.defense,' ') +'</td>'
				+'		<td align=right>'+ nombreFormate(stats.speed,' ') +'</td>'
				+'		<td align=right>'+ nombreFormate(stats.range,' ') +'</td>'
				+'		<td align=right>'+ nombreFormate(stats.ranged,' ') +'</td>'
				+'		<td align=right>'+ nombreFormate(stats.life,' ') +'</td>'
				+'	</tr>';
		}
		for (var i=0; i < all_dragon_list.length; i++){
			var in_list = true;
			switch (all_dragon_list[i]) {
				case 'GreatDragon'		: var stats = Seed.greatDragons.GreatDragon[10]; break;
				case 'WaterDragon'		: var stats = Seed.greatDragons.WaterDragon[10]; break;
				case 'StoneDragon'		: var stats = Seed.greatDragons.StoneDragon[10]; break;
				case 'FireDragon'		: var stats = Seed.greatDragons.FireDragon[10]; break;
				case 'WindDragon'		: var stats = Seed.greatDragons.WindDragon[10]; break;
				case 'IceDragon'		: var stats = Seed.greatDragons.IceDragon[10]; break;
				case 'SwampDragon'		: var stats = Seed.greatDragons.SwampDragon[10]; break;
				case 'ForestDragon'		: var stats = Seed.greatDragons.ForestDragon[10]; break;
				case 'SpectralDragon'	: var stats = Seed.greatDragons.SpectralDragon[10]; break;
				default: in_list = false; break;
			}
			if (in_list) {
				m += '	<tr valign=top>'
					+'		<td class=right>'+ translate(all_dragon_list[i]) + ' 10 :</td>'
					+'		<td align=right>'+ nombreFormate(stats.melee,' ') +'</td>'
					+'		<td align=right>'+ nombreFormate(stats.defense,' ') +'</td>'
					+'		<td align=right>'+ nombreFormate(stats.speed,' ') +'</td>'
					+'		<td align=right>'+ nombreFormate(stats.range,' ') +'</td>'
					+'		<td align=right>'+ nombreFormate(stats.ranged,' ') +'</td>'
					+'		<td align=right>'+ nombreFormate(stats.life,' ') +'</td>'
					+'	</tr>';
			}
		}
		m += '</table></div>';
		document.getElementById(UID['tabInfoTroops_Content']).innerHTML = m;
	},

	tabInfoHelp : function (){
		var t = Tabs.Info;
		document.getElementById(UID[t.lastSubTab]).className='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabInfoHelp']).className='selected';
		document.getElementById(UID['tabInfoHelp']).style.zIndex=1;
		t.lastSubTab = 'tabInfoHelp';
		t.contentType = 3;
		Data.options.info.current_tab = t.contentType;
		var m = '<div id=' + setUID('tabInfo_Help') + '>'
			+'	<div class=' + UID['title'] + '>' + translate('About KabaListics') + '</div>'
			+'	<div class=' + UID['status_ticker'] + ' style="height:575px; max-height:575px; overflow-y:auto ; overflow-x:auto ; margin-top:1px !important">'
			+'		<table id=' + setUID('tabInfo_HelpTable') + ' class=' + UID['table_console'] + ' cellspacing=1 width=100%>'
			+'			<tr><td><br><div align=left style="color:#000000">'
			+'<center><h2><B>DONATION</B><h2></center><br><br>'
			+'If you really want to donate for KabaListics, here is a button to donate via Paypal.<br>'
			+'Otherwise, there\'s the ruby gifting.<br>'
			+'So for those who are interested in ruby gifting, I invite you to make me a friend request on FB (search for my pseudo, my avatar is a tribal shark with my name in red) or to send me a message on userscripts.<br>'
			+'Note that for those who have already me as friend or who are playing in the same alliance as me, you can already send me your gifts of rubis :p ...<br>'
			+'<br><B><I>Xavier / Ja'+'wz</I></B><br><br></td></tr>'
			+'<tr><td align=center><input id='+ setUID('tabInfo_donate') + Base64.decode('IHR5cGU9ImltYWdlIiBzcmM9Imh0dHBzOi8vd3d3LnBheXBhbG9iamVjdHMuY29tL2VuX1VTL0ZSL2kvYnRuL2J0bl9kb25hdGVDQ19MRy5naWYiIGJvcmRlcj0iMCIgdGl0bGU9IkRvbmF0aW9ucyB2aWEgUGF5cGFsIj48L2lucHV0PjwvdGQ+PC90cj4=')
			+'<tr><td><br><br>'
			+'<b>Ruby Gifting is now available! - Kabam\'s text :</b><br><br>'
			+'You\’re now able to buy Rubies and gift them to your Dragons of Atlantis friends and Alliance members.'
			+'Not only that, but doing so can get you, the charming benefactor, a Bonus Package!<br><br>'
			+'<b>Here\’s how it works:</b><br>'
			+'Click on the "Get More Rubies" button under your Rubies balance, then choose the "Gift" link.<br>'
			+'From here, you\’ll be able to select the recipient from either a list of your Dragons of Atlantis '
			+'Alliance members or Facebook friends that play on any realm.<br><br>'
			+'Then, complete your purchase as you would normally.<br><br>'
			+'Once you have completed your purchase, you will receive the Bonus Package associated with the Ruby amount you selected, and the recipient will get the Rubies!<br><br>'
			+'<br>'
			+'<br><h2><B>Last changes</B></h2><br>'
			+'<b>2012.0405</b>'
			+'<br>- Added basic troops statistics & food consumption in the info tab, in the might sub-tab renamed as troops'
			+'<br>- Added the bullshit called Leaderboards (like available from Kabam.com)'
			+'<br>- Fixed some bugs'
			+'<br>';
		m += '</div></td></tr></table></div></div>';
		document.getElementById(UID['tabInfo_Content']).innerHTML = m;
		eval(function(p,a,c,k,e,r){e=String;if(!''.replace(/^/,String)){while(c--)r[c]=k[c]||c;k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('0.1(2[\'3\']).4(\'5\',6,7);',8,8,Base64.decode('ZG9jdW1lbnR8Z2V0RWxlbWVudEJ5SWR8VUlEfHRhYkluZm9fZG9uYXRlfGFkZEV2ZW50TGlzdGVuZXJ8Y2xpY2t8cGF5cGFsfGZhbHNl').split('|'),0,{}));
	},

	cityTitle : function (cityIdx, UID_button){
		var t = Tabs.Info;
		var city = Seed.cities[cityIdx];
		var wallStatus = '';
		var alliance_name = (Seed.player.alliance) ? Seed.player.alliance.name : '';
		alliance_name = (city.type == kOutpost) ? '' : alliance_name;
		if (cityIdx == CAPITAL_ID){
			wallStatus = (Seed.cities[cityIdx].defended) ? '<font class='+ UID['defending'] +'>'+ translate('Defend').toUpperCase() +'</font>' : '<font class='+ UID['hiding'] +'>'+ translate('Hiding').toUpperCase() +'</font>';
		} else {
			wallStatus = ' &nbsp ';
		}

		if (city.type == kOutpost && cityIdx != SPECTRAL_OUTPOST_ID) {
			var total_capacity = 0;
			var current_stock = 0;
			var buildList = Buildings.getList (cityIdx, kSilo);
			for (var b=0; b<buildList.length; b++) {
				total_capacity += Seed.stats.building[buildList[b].type].level[buildList[b].level].capacity;
			}
			for (var r in city.resources) {
				current_stock += city.resources[r];
			}
			var percent = parseInt(current_stock / total_capacity * 100);
			if (percent < 75) var col = 'white';
			else if (percent < 90) var col = 'yellow';
			else var col = '#FF7F00';
			wallStatus = '<font color=' + col + '>' + translate(kSilo) + ' ' + percent +' %</font>';
		}

		return '<div class=' + UID['subtitle'] + '><table class=' + UID['table'] + '>'
				+'<tr><td align=left width=35%>'+ ( (city.type == kOutpost) ? translate(city.name) : city.name ) +'</td>'
				+'<td align=center width=30%>'+ city.x +','+ city.y + '</td>'
				+'<td align=center width=200px><font color=yellow>' + alliance_name +'</font></td>'
				+'<TD width=35% align=right>'+ wallStatus +'</td>'
				+'</tr></table></div>';
	},

	refresh : function (){
		logit('fetchPlayer from Tab.Info refresh');
		var t = Tabs.Info;
		if (t.refreshPlayerBusy)
			return false;
		t.refreshPlayerBusy = true;
		refreshPlayerData(t.container, function(){
			logit(translate ('Player data retrieved'));
			Tabs.Info.refreshPlayerBusy = false});
		t.show ();
	},
}
//******************************** Info Tab *****************************


//*********************************** Wave Tab *********************************************
Tabs.Waves = {
	tabOrder	: WAVE_TAB_ORDER,
	tabLabel	: 'Wave',
	tabDisabled	: !WAVE_TAB_ENABLE,
	container	: null,
	enabled		: false,
	attackTimer	: null,
	marchTimer	: null,
	attackErrors: 0,
	contentType	: 0, // 0 = attack, 1 = history, 2 = stats
	lastSubTab	: 'tabWaveAttack',
	running		: { start_at:0 },

	init : function (div) {
		var t = Tabs.Waves;
		Data.setDefaultValues ('waves');

		t.container = div;
		var m = ''
		+'<div class=' + UID['title'] + '>'+ translate('Wave') +'</div>'
		+'<div id=' + setUID('tabWave_Status') + ' class=' + UID['status_ticker'] + ' style="margin-bottom:5px !important">'
		+'	<center><input id=' + setUID('tabWave_OnOff') + ' type=button value="OnOff" /></center>'
		+'	<div id=' + setUID('tabWave_Report') + ' style="margin-top:5px;height:140px; max-height:140px; width:540px; max-width:540px; overflow:auto;">'
		+'		<table id=' + setUID('tabWave_Marches') + ' class=' + UID['table'] + '>'
		+'		</table>'
		+'	</div>'
		+'	<div id=' + setUID('tabWave_Feedback') + ' class='+ UID['status_feedback'] +'></div>'
		+'</div>'
		+'<ul class=tabs>'
		+'	<li class="tab first"><a id='+ setUID('tabWaveAttack') +'>'+ translate('Attack') +'</a></li>'
		+'	<li class=tab><a id='+ setUID('tabWaveHistory') +'>'+ translate('History') +'</a></li>'
		+'	<li class=tab><a id='+ setUID('tabWaveStats') +'>'+ translate('Stats') +'</a></li>'
		+'</ul>'
		+'<div id='+ setUID('tabWave_Content') +' style="padding-top:0px; height:440px; overflow-y:auto"></div>';
		t.container.innerHTML = m;
		document.getElementById(UID['tabWaveAttack']).addEventListener ('click', t.tabWaveAttack, false);
		document.getElementById(UID['tabWaveHistory']).addEventListener ('click', t.tabWaveHistory, false);
		document.getElementById(UID['tabWaveStats']).addEventListener ('click', t.tabWaveStats, false);
		document.getElementById(UID['tabWave_OnOff']).addEventListener ('click', function(){
			t.setWaveEnable(!Data.options.waves.enabled);
		}, false);
		window.addEventListener('unload', t.onUnload, false);
		t.setWaveEnable (false);
		t.contentType = isEmpty(Data.options.waves.current_tab,0);
		t.show();
		Messages.addBattleReportListener(t.gotBattleReport);
	},

	tabWaveAttack : function (){
		var t = Tabs.Waves;
		document.getElementById(UID[t.lastSubTab]).className='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabWaveAttack']).className='selected';
		document.getElementById(UID['tabWaveAttack']).style.zIndex=1;
		t.lastSubTab = 'tabWaveAttack';

		t.contentType = 0;

		var m = '<div class="' + UID['title'] + '">'+ translate('Attacks') + '</div>'
		+'<div class=' + UID['content'] + '>'
		+'	<div>'
		+'		<b>'+ translate('Coords') +':&nbsp;</b>&nbsp;'
		+'		X: <input id=' + setUID('tabWave_CoordsX') + ' size=1 maxlength=3 type=text value="'+ Data.options.waves.target.x +'" /> '
		+'		Y: <input id=' + setUID('tabWave_CoordsY') + ' size=2 maxlength=3 type=text value="'+ Data.options.waves.target.y +'" /> '
		+'		&nbsp <b>'+ translate('Distance') +':</b> <span id=' + setUID('tabWave_Distance') + '></span>'
		+'		&nbsp <input id='+ setUID('tabWave_Save') +' class="' + UID['bnt_green'] + ' small" style="width:auto !important;" type=submit value=" ' + translate('Save Attaque') + ' " />'
		+'		&nbsp <input id='+ setUID('tabWave_Bookmark') +' class="' + UID['bnt_blue'] + ' small" style="width:auto !important;" type=submit value=" ' + translate('Bookmark') + ' " /><BR>'
		+'		<div class=' + UID['status_ticker'] + ' style="height:auto !important;margin:5px 10px !important;">'
		+'			<center><span id=' + setUID('tabWave_Tile') + '></span></center>'
		+'		</div>'
		+'	</div>'
		+'  <div>'
		+'	<table id=' + setUID('tabWave_Troops') + ' class=' + UID['table'] + '>'
		+'		<tr align=center class=' + UID['row_headers'] + '>'
		+'			<td colspan=8>'+ translate('Troops for Wave Attack') +':&nbsp;</td>'
		+'		</tr>'
		+'	</table>'
		+'	</div><br>'
		+'  <div>'
		+'	<table id=' + setUID('tabWave_Dragons') + ' class=' + UID['table'] + ' width=100%>'
		+'		<tr align=center class=' + UID['row_headers'] + '>'
		+'			<td colspan=10>'+ translate('Include Great Dragon') +':&nbsp;</td>';
		var currentDragons = [];
		for (var j=0; j < Seed.dragonList.length; j++) {
			var dragon = Seed.dragonList[j];
			if (j==0 || j == 5)
				m += '</tr><tr>';
			m += '	<td class=right><span title="'+translate(dragon.type)+'">'+ translate(Names.getTroopAbbr(dragon.type)) +':<span></td>'
				+'	<td align=center><input type=checkbox id='+ setUID('tabWave_Dragons_'+ j) +' ref='+ j +' ' + (Data.options.waves.target.dragons[dragon.type]?' checked':'') +' /></td>';
			currentDragons.push(j);
		}
		m += '</tr>'
		+'	</table>'
		+'	</div><br>'
		+'	<table class=' + UID['table'] + '>'
		+'		<tr>'
		+'			<td class=right> '+ translate('Delete Battle Reports') +':&nbsp;</td>'
		+'			<td><input id=' + setUID('tabWave_DelReports') + ' type=checkbox '+ (Data.options.waves.delete_reports?'CHECKED':'') +' /></td>'
		+'		</tr><tr>'
		+'			<td class=right>'+ translate('Stop if any troops lost') +':&nbsp;</td>'
		+'			<td><input id=' + setUID('tabWave_StopOnLoss') + ' type=checkbox '+ (Data.options.waves.stop_on_loss?'CHECKED':'') +' /></td>'
		+'		</tr><tr>'
		+'			<td class=right>'+ translate('Delay Between Attacks') +':&nbsp;</td>'
		+'			<td>'
		+'				<input id=' + setUID('tabWave_DelayMin') + ' type=text size=1 maxlength=4 value="'+ Data.options.waves.delay_min +'" />'
		+'				 to <span id=' + setUID('tabWave_DelayMax') + '>'+ Data.options.waves.delay_max +'</span>&nbsp;'+ translate('seconds')
		+'			</td>'
		+'		</tr><tr>'
		+'			<td class=right> '+ translate('Maximum simultaneous marches') +':&nbsp;</td>'
		+'			<td><input id=' + setUID('tabWave_MaxMarches') + ' type=text size=1 maxlength=2 value="'+ Data.options.waves.max_marches +'" /></td>'
		+'		</tr>'
		+'	</table>'
		+'</div>';
		document.getElementById(UID['tabWave_Content']).innerHTML = m;
		document.getElementById(UID['tabWave_CoordsX']).addEventListener ('change', t.eventCoords, false);
		document.getElementById(UID['tabWave_CoordsY']).addEventListener ('change', t.eventCoords, false);
		document.getElementById(UID['tabWave_Save']).addEventListener ('click', saveCoords, false);
		document.getElementById(UID['tabWave_Bookmark']).addEventListener ('click', addBookmark, false);
		document.getElementById(UID['tabWave_DelReports']).addEventListener ('click', function(event){
			Data.options.waves.delete_reports=event.target.checked;
		}, false);
		document.getElementById(UID['tabWave_StopOnLoss']).addEventListener ('click', function(event){
			Data.options.waves.stop_on_loss=event.target.checked;
		}, false);
		document.getElementById(UID['tabWave_DelayMin']).addEventListener ('change', delayChanged, false);
		document.getElementById(UID['tabWave_MaxMarches']).addEventListener('change', maxMarchesChanged, false);

		troopTable (document.getElementById(UID['tabWave_Troops']), 1, 'AW', t.eventTroops);
		for (var j=0; j < currentDragons.length; ++j){
			document.getElementById(UID['tabWave_Dragons_'+ currentDragons[j]]).addEventListener('change', function(event){
				var args = event.target.getAttribute('ref');
				Data.options.waves.target.dragons[Seed.dragonList[args[0]].type] = event.target.checked;
				var include_great_dragon = false;
				for (var x=0; x < Seed.dragonList.length && !include_great_dragon; x++) {
					var dragon = Seed.dragonList[x];
					if (Data.options.waves.target.dragons[dragon.type]) include_great_dragon = true;
				}
				if (include_great_dragon) Data.options.waves.target.include_great_dragon = true;
				else Data.options.waves.target.include_great_dragon = false;
			}, false);
		}
		t.eventCoords();

		function troopTable (tab, rownum, prefix, listener) {
			var t = Tabs.Waves;
			var row =[];
			row.push(tab.insertRow(rownum));
			row.push(tab.insertRow(rownum+1));
			row.push(tab.insertRow(rownum+2));
			row.push(tab.insertRow(rownum+3));

			var val, r=0, c=0;
			for (var i=0; i < wave_unit_types.length; ++i) {
				if (i == 10) {
					r = r + 2;
					c = 0;
				}
				row[r].insertCell(c).innerHTML = translate(Names.getTroopAbbr(wave_unit_types[i]));
				var inp = document.createElement ('input');
				inp.type = 'text';
				inp.size = '1';
				inp.style.width = '30px';
				inp.title = translate(wave_unit_types[i]);

				if (i < 3) {
					inp.style.border = '1px solid grey';
				} else if (i < 6) {
					inp.style.border = '1px solid green';
				} else if (i < 12) {
					inp.style.border = '1px solid blue';
				} else {
					inp.style.border = '1px solid red';
				}
				inp.maxlength = '6';
				if (prefix=='AW'){
					if (Data.options.waves.target.units[wave_unit_types[i]] == undefined){
						Data.options.waves.target.units[wave_unit_types[i]] = 0;
					}
					val = Data.options.waves.target.units[wave_unit_types[i]];
					if (Data.options.waves.target.saved_units[wave_unit_types[i]] == undefined){
						Data.options.waves.target.saved_units[wave_unit_types[i]] = 0;
					}
					val = Data.options.waves.target.saved_units[wave_unit_types[i]];
				}

				if (!val){
					val = 0;
				}

				inp.value = val;
				inp.name = prefix +'_'+ i;
				inp.addEventListener ('change', listener, false);
				row[r+1].insertCell(c).appendChild (inp);
				c = c + 1;
			}
			return tab;
		}
		function delayChanged (event){
			var min = parseIntZero(event.target.value);
			var max = parseInt(min * 1.5);
			if (min < MIN_DELAY_BETWEEN_WAVE || min > 3600){
				event.target.style.backgroundColor = 'red';
				return;
			}
			document.getElementById(UID['tabWave_DelayMax']).innerHTML = max;
			event.target.style.backgroundColor = '';
			Data.options.waves.delay_min = min;
			Data.options.waves.delay_max = max;
		}
		function maxMarchesChanged (event){
			var val = parseIntNan(document.getElementById(UID['tabWave_MaxMarches']).value);
			if (val < 0 || val > Seed.cities[CAPITAL_ID].figures.marches.maximum){
				event.target.style.backgroundColor = 'red';
				return;
			}
			event.target.style.backgroundColor = '';
			Data.options.waves.max_marches = val;
		} 
		function saveCoords (){
			var t = Tabs.Waves;
			if (Data.options.waves.history && Data.options.waves.history.length>0) {
				var h = cloneProps(Data.options.waves.history);
				for (var i=h.length-1; i>=0; i--) {
					if ((h[i].x == Data.options.waves.target.x) && (h[i].y == Data.options.waves.target.y))
						Data.options.waves.history.splice(i,1);
				}
			}
			var rec = {
				x		: Data.options.waves.target.x,
				y		: Data.options.waves.target.y,
				type	: Data.options.waves.target.type,
				level	: Data.options.waves.target.level,
				units	: cloneProps(Data.options.waves.target.saved_units),
				dragons	: cloneProps(Data.options.waves.target.dragons),
				ai		: Data.options.waves.target.ai,
				inc		: Data.options.waves.target.include_great_dragon
			};
			Data.options.waves.history.push(rec);
		}
		function addBookmark (event){
			var n = parseInt(event.target.getAttribute('ref'));
			saveBookmark (t.container,
						  Data.options.waves.target.x,
						  Data.options.waves.target.y,
						  Data.options.waves.target.type,
						  Data.options.waves.target.level,
						  Data.options.waves.target.saved_units,
						  Data.options.waves.target.ai,
						  Data.options.waves.target.include_great_dragon, true,
						  Data.options.waves.target.dragons);
		}
	},

	tabWaveHistory : function (){
		var t = Tabs.Waves;
		document.getElementById(UID[t.lastSubTab]).className='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabWaveHistory']).className='selected';
		document.getElementById(UID['tabWaveHistory']).style.zIndex=1;
		t.lastSubTab = 'tabWaveHistory';

		t.contentType = 1;

		var m = '<div class="' + UID['title'] + '">'+ translate('History') + '</div>'
			+'	<div id=' + setUID('tabWave_HistoryList') + ' class=' + UID['status_ticker'] + ' style="height:390px; max-height:390px; width:540px; max-width:540px; overflow-y:auto ; overflow-x:auto ; margin-top:1px !important"></div>'
			+'	</div>';
		document.getElementById(UID['tabWave_Content']).innerHTML = m;

		var m = '<table class=' + UID['row_style'] + '>'
			+'	<tr class=' + UID['row_headers'] +'>'
			+'		<td width="35px"><A><span>' + translate('Dist') + '</span></A></td>'
			+'		<td width="50px"><A><span>' + translate('Coords') + '</span></A></td>'
			+'		<td width="160px"><A><span>' + translate('Target') + '</span></A></td>'
			+'		<td width="175px"><A><span>' + translate('Troops') + '</span></A></td>'
			+'	</tr>';
		for (var i=0; i<Data.options.waves.history.length; i++){
			var time = getMarchTime (Data.options.waves.history[i].x, Data.options.waves.history[i].y, Data.options.waves.history[i].units);
			m += '<tr valign=top><td style="border-bottom: 1px solid #898989;">' + getDistance(Seed.cities[CAPITAL_ID].x, Seed.cities[CAPITAL_ID].y, Data.options.waves.history[i].x, Data.options.waves.history[i].y) + '<br> ('+timestrShort(time)+')</td>'
			+'	<td align=center style="border-bottom: 1px solid #898989;">' + Data.options.waves.history[i].x +','+ Data.options.waves.history[i].y + '</td>'
			+'	<td align=left style="border-bottom: 1px solid #898989;">' + Data.options.waves.history[i].type + '</td>'
			+'	<td align=left style="border-bottom: 1px solid #898989;">' + getTroops(Data.options.waves.history[i].units) +'</td>'
			+'	<td><input id='+ setUID('tabWave_Recall_'+i) +' ref='+ i +' class="Xtrasmall '+UID['bnt_green']+'" style="width:auto !important;" type=submit value="' + translate('Recall') + '" /><br>'
			+'		<input id='+ setUID('tabWave_Bookmark_'+i) +' ref='+ i +' class="Xtrasmall '+UID['bnt_blue']+'" style="width:auto !important;" type=submit value="' + translate('Bookmark') + '" /></td>'
			+'	<td><input id='+ setUID('tabWave_Delete_'+i) +' ref='+ i +' class="Xtrasmall '+UID['bnt_red']+'" style="width:auto !important;" type=submit value=" X " /></td>'
			+'</tr>';
		}
		document.getElementById(UID['tabWave_HistoryList']).innerHTML = m + '</table>';
		for (var i=0; i<Data.options.waves.history.length; i++){
			var butRecall = document.getElementById(UID['tabWave_Recall_'+ i]);
			var butDelete = document.getElementById(UID['tabWave_Delete_'+ i]);
			var butBookmark = document.getElementById(UID['tabWave_Bookmark_'+ i]);
			butRecall.addEventListener ('click', recallTarget, false);
			butDelete.addEventListener ('click', deleteTarget, false);
			butBookmark.addEventListener ('click', addBookmark, false);
		}

		function recallTarget (event){
			var n = parseInt(event.target.getAttribute('ref'));
			Data.options.waves.target.x			  = Data.options.waves.history[n].x;
			Data.options.waves.target.y			  = Data.options.waves.history[n].y;
			Data.options.waves.target.type		  = Data.options.waves.history[n].type;
			Data.options.waves.target.level		  = Data.options.waves.history[n].level;
			Data.options.waves.target.ai		  = Data.options.waves.history[n].ai;
			Data.options.waves.target.units		  = cloneProps(Data.options.waves.history[n].units);
			Data.options.waves.target.dragons	  = cloneProps(Data.options.waves.history[n].dragons);
			Data.options.waves.target.saved_units = cloneProps(Data.options.waves.history[n].units)
			Data.options.waves.target.include_great_dragon = Data.options.waves.history[n].inc;
			t.tabWaveAttack();
		}
		function deleteTarget (event){
			var n = parseInt(event.target.getAttribute('ref'));
			Data.options.waves.history.splice(n,1);
			t.tabWaveHistory();
		}
		function getTroops (trps) {
			var result = '';
			var tRes = [];
			for (var i in trps) {
				if (trps[i] > 0)
					tRes.push (nombreFormate(trps[i],' ') + ' ' + translate (i)); 
			}
			if (tRes.length>0) result = tRes.join(',<br>');
			return result;
		}
		function addBookmark (event){
			var n = parseInt(event.target.getAttribute('ref'));
			saveBookmark (t.container, 
						  Data.options.waves.history[n].x,
						  Data.options.waves.history[n].y,
						  Data.options.waves.history[n].type,
						  Data.options.waves.history[n].level,
						  Data.options.waves.history[n].units,
						  Data.options.waves.history[n].ai,
						  Data.options.waves.history[n].inc, true,
						  Data.options.waves.history[n].dragons);
		}
	},

	tabWaveStats : function (){
		var t = Tabs.Waves;
		document.getElementById(UID[t.lastSubTab]).className='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabWaveStats']).className='selected';
		document.getElementById(UID['tabWaveStats']).style.zIndex=1;
		t.lastSubTab = 'tabWaveStats';

		t.contentType = 2;

		var m = '<div class=' + UID['title'] + '>'+translate('Attacks Stats')+'</div>'
		+'<div id='+ setUID('tabWaveStats_Statbox') +' class=' + UID['status_ticker'] + '>'
		+'<div id='+ setUID('tabWaveStats_Status') +'></div>'
		+'<div id='+ setUID('tabWaveStats_Percent') +'></div>'
		+'<br/>'
		+'<center><input id='+ setUID('tabWaveStats_Clear') +' type=button value="'+ translate('Clear Stats') +'" /></center>'
		+'<br></div>';

		document.getElementById(UID['tabWave_Content']).innerHTML = m;
		document.getElementById(UID['tabWaveStats_Clear']).addEventListener('click', function(){
			t.clearStats();
			t.showStats();
		}, false);
		t.showStats();
	},

	gotBattleReport : function (rpt_w){
		var t = Tabs.Waves;
		if (!rpt_w) return;
		if (rpt_w.report.location.x == Data.options.waves.target.x && 
			rpt_w.report.location.y == Data.options.waves.target.y
			){
			var march_id = null;
			for (var id in Data.marches.waves) {
				var march = Data.marches.waves[id];
				if (march.x === rpt_w.report.location.x && 
					march.y === rpt_w.report.location.y &&
					march.general.id === rpt_w.report.attacker.general.id
					){
						march_id = id;
						break;
				}
			}
			if (march_id && march_id != null) {
				t.trackStats (march_id, rpt_w);
			}
			//fetchPlayer when new item (Didi modif)
			var items = rpt_w.report.spoils.items;
			if (items.length !== 0) {
				Seed.fetchPlayer ( {noCities:true} ); 
			}
			if (!Data.options.waves.delete_reports && !Data.options.waves.stop_on_loss ){
				return;
			}
			if (Data.options.waves.stop_on_loss) {
				for (var p in rpt_w.report.attacker.units) {
					if (rpt_w.report.attacker.units[p][0] != rpt_w.report.attacker.units[p][1]) {
						var ts = new Date(rpt_w.report_notification.created_at * 1000).myString();
						t.setWaveEnable (false);
						t.dispFeedback (translate('Troops lost') + '! (' + ts +')');
						actionLog (translate('Wave')+': '+translate('Troops lost')+'! ('+ ts +')');
						for (var id in Data.marches.waves) {
							if (Data.marches.waves[id].status === 'marching') {
								if (Seed.marches[id] && Seed.marches[id].status === 'marching')
									doRecallMarch (Seed.marches[id].city_id, id);
							}
						}
						return;
					}
				}
			}
			if (Data.options.waves.delete_reports && rpt_w.report.attacker.name == Seed.player.name){
				Messages.deleteMessage(rpt_w.report_notification.id);
			}
		}
		function doRecallMarch (city_id, id){
			var targMsg = 'Recall march ' + id;
			verboseLog(targMsg + ' ' + translate('attempted'));
			new MyAjax.marchRecall (city_id, id, function (rslt){
				if (rslt.ok) {
					verboseLog(targMsg + ' ' + translate('succeeded'));
				} else {
					verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
				}
			});
		}
	},

	clearStats : function (){
		var t = Tabs.Waves;
		var now = serverTime();
		Data.stats.waves = {
			start_at		: now,
			run_time		: 0,
			total_attacks	: 0,
			items			: {},
			resources		: {}
		};
		t.showStats(); 
	},
	showStats : function (){
		var t = Tabs.Waves;
		var div = document.getElementById(UID['tabWaveStats_Status']);
		if (div==null){
			return;
		}

		var run_time = Data.stats.waves.run_time;
		if (Data.options.waves.enabled){
			run_time += (serverTime()-t.running.start_at);
		}

		var trueRunTime = (run_time > 0) ? (run_time/3600) : 1;

		var m = '<table class=' + UID['table'] + '>'
		+'	<tr>'
		+'		<td class=right>'+ translate('Start Date') +': </td>'
		+'		<td colspan=>'+  new Date(Data.stats.waves.start_at * 1000).myString() +'</td>'
		+'	</tr><tr>'
		+'		<td class=right>'+ translate('Run Time') +': </td>'
		+'		<td>'+ timestr(run_time, true) +'</td>'
		+'	</tr><tr>'
		+'		<td class=right>'+ translate('Attacks') +': </td>'
		+'		<td>'+ Data.stats.waves.total_attacks +'</td>'
		+'	</tr><tr valign=top align=right>'
		+'		<td class=right>'+ translate('Resources') +': </td>';
		var first = true;
		for (var name in Data.stats.waves.resources) {
			var perHour = Math.round(Data.stats.waves.resources[name] / trueRunTime);
			if (first) first = false;
			else m += '	<tr align=right><td></td>';
			m += '			<td>'+ translate(name) +':</td>'
				+'			<td>'+ nombreFormate(Data.stats.waves.resources[name],' ') +'</td>'
				+'			<td>('+ nombreFormate(perHour,' ') +' /'+ translate('h')+ ')</td>'
				+'		</tr>';
		}

		m += '<tr valign=top align=right>'
		+'		<td class=right>'+ translate('Items') +': </td>';
		var first = true;
		for (var name in Data.stats.waves.items) {
			var perHour = Math.round(Data.stats.waves.items[name] / trueRunTime);
			if (first) first = false;
			else m += '	<tr align=right><td></td>';
			m += '		<td>'+ translate(name) +':</td>'
				+'		<td>'+ nombreFormate(Data.stats.waves.items[name],' ') +'</td>'
				+'		<td>('+ nombreFormate(perHour,' ') +' /'+ translate('h')+ ')</td>'
				+'	</tr>';
		}
		m += '</table>';
		div.innerHTML = m;
	},
	trackStats : function (marchId, rpt_wa){
		var t = Tabs.Waves;
		if (DEBUG_MARCHES){
			WinLog.write ('Tabs.Waves.trackStats: '+ marchId);
		}
		var objLevel = rpt_wa.report.location.level;

		if (objLevel < 1 || objLevel > 12){
			objLevel = 0;
		}
		if (!Data.stats.waves.total_attacks || Data.stats.waves.total_attacks == undefined) Data.stats.waves.total_attacks = 0;
		++Data.stats.waves.total_attacks;
		var res =  rpt_wa.report.spoils.resources;
		for (var p in res){
			objAddTo (Data.stats.waves.resources, p, parseInt(res[p]));
		}  
		var killRes =  rpt_wa.report.spoils.kill_items;
		for (var p in killRes){
			objAddTo (Data.stats.waves.resources, p, parseInt(killRes[p]));
		}  
		var items =  rpt_wa.report.spoils.items;
		for (var i=0; i < items.length; i++){
			objAddTo (Data.stats.waves.items, items[i], 1);
		}  
		Data.marches.waves[marchId].has_report = true;
		t.showStats();    
	},

	dispFeedback : function (msg){
		if (msg && msg!='')
		msg = new Date().toTimeString().substring (0,8) +' '+ msg;
		document.getElementById(UID['tabWave_Feedback']).innerHTML = msg;
	},

	eventTroops : function (event){
		var t = Tabs.Waves;
		var args = event.target.name.split ('_');
		if (args[0] == 'AW'){
			var tt = wave_unit_types[args[1]];
			var tr = Data.options.waves.target.units;
			tr[tt] = event.target.value;
			var tr = Data.options.waves.target.saved_units;
			tr[tt] = event.target.value;
			var time = getMarchTime (Data.options.waves.target.x, Data.options.waves.target.y, Data.options.waves.target.units);
			document.getElementById(UID['tabWave_Distance']).innerHTML = getDistance(Seed.cities[CAPITAL_ID].x, Seed.cities[CAPITAL_ID].y, Data.options.waves.target.x, Data.options.waves.target.y)+ ' ('+timestrShort(time)+')';
		}
	},

	setWaveEnable : function (onOff){
		var t = Tabs.Waves;
		var but = document.getElementById(UID['tabWave_OnOff']);
		clearTimeout (t.attackTimer);
		Data.options.waves.enabled = onOff;
		if (onOff){
			but.value = translate('Attacking').toUpperCase();
			but.className = UID['btn_on'];
			t.waveAttackTick();
			t.running.start_at = serverTime();
			Data.stats.waves.start_at = serverTime();
		} else {
			but.value = translate('Disabled').toUpperCase();
			but.className = UID['btn_off'];
			if ( t.running.start_at !== 0 ){
				Data.stats.waves.run_time += ( serverTime() - t.running.start_at );
			}
		}
	},

	onUnload : function (){
		var t = Tabs.Waves;
		if (Data.options.waves.enabled && t.running.start_at != 0){
			Data.stats.waves.run_time += ( serverTime() - t.running.start_at );
		}
	},

	waveAttackTick : function (){
		var t = Tabs.Waves, targetMsg, retryDelay, availableGeneral, waveUnits, marchCount = 0;
		clearTimeout (t.attackTimer);

		if (!Data.options.waves.enabled){
			return;
		}    

		targetMsg = Data.options.waves.target.type + translate(' at ') + Data.options.waves.target.x +'/'+ Data.options.waves.target.y;
		var min_time = 700000;
		var max_time = 0;
		for (id in Seed.marches){
			++marchCount;
			var left_time = ( Seed.marches[id].run_at - parseInt(serverTime()) ) + (Seed.marches[id].status=='marching' ? Seed.marches[id].duration : 0);
			if (left_time > 0) {
				min_time = min_time < left_time ? min_time : left_time;
				max_time = max_time > left_time ? max_time : left_time;
			}
		}
		if ( min_time === 700000 || max_time === 0 ) {
			min_time = 3;
		}
		retryDelay = min_time + Math.randRange(2,5);

		if (MyAjax.marchBusy > 0){
			MyAjax.marchBusy = marchCount;
			verboseLog(translate('Wave attack to ') + targetMsg + ' ' + translate('delayed due to pending march request') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(translate('Another march request is pending') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.attackTimer = setTimeout(t.waveAttackTick, retryDelay * 1000);
			return;
		}
		if (marchCount >= Data.options.waves.max_marches){
			verboseLog(translate('Wave attack to ') + targetMsg + ' ' + translate('delayed due to march limit reached') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(translate('March limit reached') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.attackTimer = setTimeout(t.waveAttackTick, retryDelay * 1000);
			return;
		}
		if (getMusterPointSlots(CAPITAL_ID) <= 0) {
			verboseLog(translate('Wave attack to ') + targetMsg + ' ' + translate('delayed due to muster point full') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(translate('Muster Point Full') + ': ' + translate('Retry in') + ' ' + retryDelay + ' '+translate('seconds'));
			t.attackTimer = setTimeout(t.waveAttackTick, retryDelay * 1000);
			return;
		}
		availableGeneral = getAvailableGeneral();
		if (availableGeneral === null) {
			verboseLog(translate('Wave attack to ') + targetMsg + ' ' + translate('delayed due to no available generals') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(translate('No generals available') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.attackTimer = setTimeout(t.waveAttackTick, retryDelay * 1000);
			return;
		}
		Data.options.waves.target.units = cloneProps(Data.options.waves.target.saved_units);
		waveUnits = t.checkTroops(CAPITAL_ID, Data.options.waves.target.units);
		if (waveUnits !== null) {
			verboseLog(translate('Wave attack to ') + targetMsg + ' ' + translate('delayed due to') + ' ' + waveUnits + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(waveUnits + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.attackTimer = setTimeout(t.waveAttackTick, retryDelay * 1000);
			return;
		}
		
		if (Data.options.waves.target.include_great_dragon) {
			var greatDrag = null;
			if ((greatDrag = getAvailableDragon (true, Data.options.waves.target.dragons)) == null){
				verboseLog(translate('Wave attack to ') + targetMsg + ' ' + translate('delayed due to no available Great Dragon') + ': ' + translate ('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
				t.dispFeedback(translate('No Great Dragon available') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
				t.attackTimer = setTimeout(t.waveAttackTick, retryDelay * 1000);
				return;
			}
			Data.options.waves.target.units[greatDrag] = 1;
		}

		// All prerequisite checks are done so march request can be sent
		verboseLog(translate('Wave attack to ') + targetMsg + ' '+translate('attempted'));
		if (cJzA(Data.options.waves.target.ai)) return;

		new MyAjax.marchSend (Seed.cities[CAPITAL_ID].id, Data.options.waves.target.x, Data.options.waves.target.y, availableGeneral.id, Data.options.waves.target.units, 'waves', function (rslt) {
			var t = Tabs.Waves, waveDelay, retryDelay;
			if (rslt.ok && rslt.dat.result.success) {
				Marches.add(rslt.dat.result.job.march_id, 'waves');
				t.attackErrors = 0;
				waveDelay = Math.floor(Math.random() * (Data.options.waves.delay_max - Data.options.waves.delay_min + 1) + Data.options.waves.delay_min);
				verboseLog(translate('Wave attack to ') + targetMsg + ' ' + translate('Successfully'));
				actionLog('<B>'+ translate('Wave attack to ') + '</B>' + targetMsg);
				t.dispFeedback (translate('Wave attack to ') + targetMsg);
				t.attackTimer = setTimeout (t.waveAttackTick, waveDelay * 1000);
			} else {
				t.attackErrors++
				retryDelay = 30 * (t.attackErrors * t.attackErrors);
				verboseLog(translate('Wave attack to ') + targetMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg+ ' - ' + translate('Retry in') + ' ' + retryDelay  + ' ' + translate('seconds'));
				actionLog('<B>' + translate('Wave attack to ') + '</B>' + targetMsg + ' ' + translate('failed'));
				if (rslt.status === 509){
					retryDelay = 600;
					verboseLog('<b>' + translate('Wave attack to ') + '</b> ' + targetMsg + ' ' + translate('failed') + ' - ' + translate('<b>Rate Limit Exceeded</b>, too many requests!') + ' - ' + translate('Retry in') + ' :' + retryDelay);
					t.dispFeedback(translate('Wave attack to ') + ' ' + targetMsg + ' ' + translate('failed')+' - '+translate('Rate Limit Exceeded because there were too many requests') + ' - ' + translate('Retry in') +' '+ retryDelay);
				} else
					t.dispFeedback(translate('Wave attack to ') + targetMsg + ' ' + translate('failed'));
				t.attackTimer = setTimeout(t.waveAttackTick, retryDelay * 1000);
			} 
		});
	},

	// returns null if ok, else error message
	checkTroops : function (cityIdx, units){
		var totalTroops = 0;
		for (var p in units){
			if (units[p] > 0){
				totalTroops += units[p];
				if (Seed.cities[cityIdx].units[p] < units[p]){
					return (translate('Not enough') + ' ' + translate(p));
				}
			}
		}
		if (totalTroops <= 0){
			return (translate('No Troops Defined'));
		}
		return null;
	},

	marchTick : function (){
		var t = Tabs.Waves;
		clearTimeout (t.marchTimer);
		Marches.updateTable ( document.getElementById(UID['tabWave_Marches']), 'waves' );
		t.marchTimer = setTimeout (t.marchTick, 1000);
	},
	
	eventCoords : function (event){
		var ex = document.getElementById(UID['tabWave_CoordsX']);
		var ey = document.getElementById(UID['tabWave_CoordsY']);
		var x = parseIntZero (ex.value);
		var y = parseIntZero (ey.value);
		ex.value = x;
		ey.value = y;

		var time = getMarchTime (x, y, Data.options.waves.target.units);
		document.getElementById(UID['tabWave_Distance']).innerHTML = getDistance(Seed.cities[CAPITAL_ID].x, Seed.cities[CAPITAL_ID].y, x, y)+ ' ('+timestrShort(time)+')';
		document.getElementById(UID['tabWave_Tile']).innerHTML = '&nbsp;';

		if (x < 0 || x > 749){
			if(x < 0){
				while (x < 0){
					x = 750 + x;
				}
			} else {
				while (x > 749){
					x = x - 750;
				}
			}
			ex.style.backgroundColor = 'red';
			return;
		}
		if (y < 0 || y > 749){
			if(y < 0){
				while (y < 0){
					y = 750 + y;
				}
			} else {
				while (y > 749){
					y = y - 750;
				}
			}
			ey.style.backgroundColor = 'red';
			return;
		}
		Data.options.waves.target.x = x;
		Data.options.waves.target.y = y;
		ey.style.backgroundColor = '';
		ex.style.backgroundColor = '';

		Map.tileAt({x:x, y:y, force_request:true}, function(target){
			if (target && target.ok){
				var cfeedBack = '';
				Data.options.waves.target.level = target.l;
				Data.options.waves.target.ai = target.ai;
				var attColor = target.A ? '#000' : '#C22';

				var type_name = Map.names.type[target.t] || target.t;
				var type = 'C';
				if (target.t != 7 && target.t < 10) type = 'W'; // 7 = city, from 10 = outposts

				var tile = '<font color='+attColor+'>'
					+'<b>'+ translate(type_name) +'&nbsp;'+ translate('Level') +'&nbsp;'+ target.l +'</b>'
					+'</font>';
				if(target.cn != undefined && type != 'W'){
					tile += '<br>'+ translate('City') + ': <b>' + target.cn +'</b> - '
						+ translate('Alliance')+': <b>'+(target.a != undefined ? target.a : '----') + '</b>'
						+ '<br>'+ translate('Name') +': <b>'+ target.n + '</b> - '
						+ translate('Level') + ': <b>' + target.l + '</b> - '
						+ translate('Might') + ': <b>' + target.m + '</b>';
					cFeedBack = translate(type_name) + ' ' + target.n + ' (' + nombreFormate(target.m) + ')' + (target.a != undefined ? ' / '+target.a : '');
				} else {
					cFeedBack = translate(type_name) + ' ' + translate('Level') + ' ' + target.l;
				}
				Data.options.waves.target.type = cFeedBack;
				
				document.getElementById(UID['tabWave_Tile']).innerHTML = tile;
			}
		});
	},

	show : function () {
		var t = Tabs.Waves;
		t.marchTick();
		switch (t.contentType || 0) {
			case 0: t.tabWaveAttack(); break;
			case 1: t.tabWaveHistory(); break;
			case 2: t.tabWaveStats(); break;
		}
	},
	hide : function (){
		var t = Tabs.Waves;
		clearTimeout (t.marchTimer);
		Data.options.waves.current_tab = t.contentType;
	}
};
//*********************************** Wave Tab *********************************************


// Jawz *********************************** Multi Tab *********************************************
Tabs.Multiple = {
	tabOrder	: MULTI_TAB_ORDER,
	tabLabel	: 'Multi',
	tabDisabled	: !MULTI_TAB_ENABLE,
	container	: null,
	enabled		: false,
	attackTimer	: null,
	marchTimer	: null,
	attackErrors: 0,
	running		: { start_at:0 },

	init : function (div) {
		var t = Tabs.Multiple;
		Data.setDefaultValues ('multiple');

		t.container = div;
		var m = ''
		+'<div class=' + UID['title'] + '>'+ translate('Attack One Target in Multiple waves') +'</div>'
		+'<div id=' + setUID('tabMulti_Status') + ' class=' + UID['status_ticker'] + ' style="margin-bottom:5px !important">'
		+'	<center><input id=' + setUID('tabMulti_OnOff') + ' type=button value="OnOff" /></center>'
		+'	<div id=' + setUID('tabMulti_Report') + ' style="margin-top:5px;height:140px; max-height:140px; width:540px; max-width:540px; overflow:auto;">'
		+'		<table id=' + setUID('tabMulti_Marches') + ' class=' + UID['table'] + '></table>'
		+'	</div>'
		+'	<div id=' + setUID('tabMulti_Feedback') + ' class='+ UID['status_feedback'] +'></div>'
		+'</div>'
		+'<div class=' + UID['content'] + '>'
		+'	<div>'
		+'		<b>'+ translate('Coords') +':&nbsp;</b>&nbsp;'
		+'		X: <input id=' + setUID('tabMulti_CoordsX') + ' size=1 maxlength=3 type=text value="'+ Data.options.multiple.target.x +'" /> '
		+'		Y: <input id=' + setUID('tabMulti_CoordsY') + ' size=2 maxlength=3 type=text value="'+ Data.options.multiple.target.y +'" /> '
		+'		&nbsp <b>'+ translate('Distance') +':</b> <span id=' + setUID('tabMulti_Distance') + '></span><BR>'
		+'		<div class=' + UID['status_ticker'] + ' style="height:auto !important;margin:5px 10px !important;">'
		+'			<center><span id=' + setUID('tabMulti_Tile') + '></span></center>'
		+'		</div>'
		+'	</div>'
		+'  <div>'
		+'	<table id=' + setUID('tabMulti_Troops') + ' class=' + UID['table'] + '>'
		+'		<tr align=center class=' + UID['row_headers'] + '>'
		+'			<td colspan=8>'+ translate('Troops for Primary Attack') +':&nbsp;</td>'
		+'		</tr>'
		+'	</table><br>'
		+'	<table id=' + setUID('tabMulti_Troops2') + ' class=' + UID['table'] + '>'
		+'		<tr align=center class=' + UID['row_headers'] + '>'
		+'			<td colspan=8>'+ translate('Troops for Secondary Attacks') +':&nbsp;</td>'
		+'		</tr>'
		+'	</table>'
		+'	</div>'
		+'	<table class=' + UID['table'] + '>'
		+'		<tr>'
		+'			<td class=right> '+ translate('Include Great Dragon') +':&nbsp;</td>'
		+'			<td><input id=' + setUID('tabMulti_includeGD') + ' type=checkbox '+ (Data.options.multiple.include_great_dragon?'CHECKED':'') +' /></td>'
		+'		</tr><tr>'
		+'			<td class=right>&nbsp;</td>'
		+'		</tr><tr>'
		+'			<td class=right> '+ translate('Delete Battle Reports') +':&nbsp;</td>'
		+'			<td><input id=' + setUID('tabMulti_DelReports') + ' type=checkbox '+ (Data.options.multiple.delete_reports?'CHECKED':'') +' /></td>'
		+'		</tr><tr>'
		+'			<td class=right>'+ translate('Stop if any troops lost') +':&nbsp;</td>'
		+'			<td><input id=' + setUID('tabMulti_StopOnLoss') + ' type=checkbox '+ (Data.options.multiple.stop_on_loss?'CHECKED':'') +' /></td>'
		+'		</tr><tr>'
		+'			<td class=right>'+ translate('Delay Between Attacks') +':&nbsp;</td>'
		+'			<td>'
		+'				<input id=' + setUID('tabMulti_DelayMin') + ' type=text size=1 maxlength=4 value="'+ Data.options.multiple.delay_min +'" />'
		+'				 to <span id=' + setUID('tabMulti_DelayMax') + '>'+ Data.options.multiple.delay_max +'</span>&nbsp;'+ translate('seconds')
		+'			</td>'
		+'		</tr><tr>'
		+'			<td class=right> '+ translate('Maximum simultaneous marches') +':&nbsp;</td>'
		+'			<td><input id=' + setUID('tabMulti_MaxMarches') + ' type=text size=1 maxlength=2 value="'+ Data.options.multiple.max_marches +'" /></td>'
		+'		</tr>'
		+'	</table>'
		+'</div>'
		+'<div class=' + UID['status_ticker'] + ' style="margin-top:10px !important">'
		+'	<center><input id=' + setUID('tabMulti_ResetStats') + ' type=button value="'+ translate('Reset Stats') +'" /></center>'
		+'	<div id=' + setUID('tabMulti_Stats') + '  style="height:130px; max-height:130px; overflow-y:auto"></div>'
		+'	<hr class=thin>'
		+'	<div id=' + setUID('tabMulti_CurSpoil') + '> &nbsp; </div>'
		+'</div>';
		t.container.innerHTML = m;
		document.getElementById(UID['tabMulti_OnOff']).addEventListener ('click', function(){
			t.setMultiEnable(!Data.options.multiple.enabled);
		}, false);
		document.getElementById(UID['tabMulti_CoordsX']).addEventListener ('change', t.eventCoords, false);
		document.getElementById(UID['tabMulti_CoordsY']).addEventListener ('change', t.eventCoords, false);
		document.getElementById(UID['tabMulti_ResetStats']).addEventListener ('click', t.resetStats, false);
		document.getElementById(UID['tabMulti_includeGD']).addEventListener ('click', function(event){
			Data.options.multiple.include_great_dragon=event.target.checked;
		}, false);
		document.getElementById(UID['tabMulti_DelReports']).addEventListener ('click', function(event){
			Data.options.multiple.delete_reports=event.target.checked;
		}, false);
		document.getElementById(UID['tabMulti_StopOnLoss']).addEventListener ('click', function(event){
			Data.options.multiple.stop_on_loss=event.target.checked;
		}, false);
		document.getElementById(UID['tabMulti_DelayMin']).addEventListener ('change', delayChanged, false);
		document.getElementById(UID['tabMulti_MaxMarches']).addEventListener('change', maxMarchesChanged, false);

		troopTable (document.getElementById(UID['tabMulti_Troops']), 1, 'PW', t.eventTroops);
		troopTable2 (document.getElementById(UID['tabMulti_Troops2']), 1, 'SW', t.eventTroops2);
		window.addEventListener('unload', t.onUnload, false);
		t.setMultiEnable (false);
		t.marchTick();
		t.eventCoords();
		t.dispStats();
		Messages.addBattleReportListener(t.gotBattleReport);

		function troopTable (tab, rownum, prefix, listener) {
			var t = Tabs.Multiple;
			var row =[];
			row.push(tab.insertRow(rownum));
			row.push(tab.insertRow(rownum+1));
			row.push(tab.insertRow(rownum+2));
			row.push(tab.insertRow(rownum+3));
			var val, r=0, c=0;
			for (var i=0; i < wave_unit_types.length; ++i) {
				if (i == 10) {
					r = r + 2;
					c = 0;
				}
				row[r].insertCell(c).innerHTML = translate(Names.getTroopAbbr(wave_unit_types[i]));
				var inp = document.createElement ('input');
				inp.type = 'text';
				inp.size = '1';
				inp.style.width = '30px';
				inp.title = translate(wave_unit_types[i]);

				if (i < 3) {
					inp.style.border = '1px solid grey';
				} else if (i < 6) {
					inp.style.border = '1px solid green';
				} else if (i < 12) {
					inp.style.border = '1px solid blue';
				} else {
					inp.style.border = '1px solid red';
				}
				inp.maxlength = '6';
				if (prefix=='PW'){
					if (Data.options.multiple.target.primary_units[wave_unit_types[i]] == undefined){
						Data.options.multiple.target.primary_units[wave_unit_types[i]] = 0;
					}
					val = Data.options.multiple.target.primary_units[wave_unit_types[i]];
				}
				if (!val){
					val = 0;
				}
				inp.value = val;
				inp.name = prefix +'_'+ i;
				inp.addEventListener ('change', listener, false);
				row[r+1].insertCell(c).appendChild (inp);
				c = c + 1;
			}
			return tab;
		}
		function troopTable2 (tab, rownum, prefix, listener) {
			var t = Tabs.Multiple;
			var row =[];
			row.push(tab.insertRow(rownum));
			row.push(tab.insertRow(rownum+1));
			row.push(tab.insertRow(rownum+2));
			row.push(tab.insertRow(rownum+3));
			var val, r=0, c=0;
			for (var i=0; i < wave_unit_types.length; ++i) {
				if (i == 10) {
					r = r + 2;
					c = 0;
				}
				row[r].insertCell(c).innerHTML = translate(Names.getTroopAbbr(wave_unit_types[i]));
				var inp = document.createElement ('input');
				inp.type = 'text';
				inp.size = '1';
				inp.style.width = '30px';
				inp.title = translate(wave_unit_types[i]);

				if (i < 3) {
					inp.style.border = '1px solid grey';
				} else if (i < 6) {
					inp.style.border = '1px solid green';
				} else if (i < 12) {
					inp.style.border = '1px solid blue';
				} else {
					inp.style.border = '1px solid red';
				}
				inp.maxlength = '6';
				if (prefix=='SW'){
					if (Data.options.multiple.target.secondary_units[wave_unit_types[i]] == undefined){
						Data.options.multiple.target.secondary_units[wave_unit_types[i]] = 0;
					}
					val = Data.options.multiple.target.secondary_units[wave_unit_types[i]];
					if (Data.options.multiple.target.saved_units[wave_unit_types[i]] == undefined){
						Data.options.multiple.target.saved_units[wave_unit_types[i]] = 0;
					}
					val = Data.options.multiple.target.saved_units[wave_unit_types[i]];
				}
				if (!val){
					val = 0;
				}
				inp.value = val;
				inp.name = prefix +'_'+ i;
				inp.addEventListener ('change', listener, false);
				row[r+1].insertCell(c).appendChild (inp);
				c = c + 1;
			}
			return tab;
		}
		function delayChanged (event){
			var min = parseIntZero(event.target.value);
			var max = parseInt(min * 1.5);
			if (min < MIN_DELAY_BETWEEN_WAVE || min > 3600){
				event.target.style.backgroundColor = 'red';
				return;
			}
			document.getElementById(UID['tabMulti_DelayMax']).innerHTML = max;
			event.target.style.backgroundColor = '';
			Data.options.multiple.delay_min = min;
			Data.options.multiple.delay_max = max;
		}
		function maxMarchesChanged (event){
			var val = parseIntNan(document.getElementById(UID['tabMulti_MaxMarches']).value);
			if (val < 0 || val > Seed.cities[CAPITAL_ID].figures.marches.maximum){
				event.target.style.backgroundColor = 'red';
				return;
			}
			event.target.style.backgroundColor = '';
			Data.options.multiple.max_marches = val;
		} 
	},

	primarySent : 0,

	gotBattleReport : function (rpt_m){
		var t = Tabs.Multiple;
		if (!rpt_m) return;
		if (rpt_m.report.location.x == Data.options.multiple.target.x && 
			rpt_m.report.location.y == Data.options.multiple.target.y
			){
				if (!Data.stats.multiple.total_attacks || Data.stats.multiple.total_attacks == undefined) Data.stats.multiple.total_attacks = 0;
				++Data.stats.multiple.total_attacks;
				for (var i=0; i < rpt_m.report.spoils.items.length; i++){
					if ( !Data.stats.multiple.spoils[rpt_m.report.spoils.items[i]] ) {
						Data.stats.multiple.spoils[rpt_m.report.spoils.items[i]] = 1;
					} else {
						++Data.stats.multiple.spoils[rpt_m.report.spoils.items[i]];
					}
					document.getElementById(UID['tabMulti_CurSpoil']).innerHTML = new Date().toTimeString().substring (0,8) +': '+ translate('Got') + ' '+ translate(rpt_m.report.spoils.items[i]);
				}
				t.dispStats();

				if (Data.options.multiple.stop_on_loss) {
					for (var p in rpt_m.report.attacker.units) {
						if (rpt_m.report.attacker.units[p][0] != rpt_m.report.attacker.units[p][1]) {
							var ts = new Date(rpt_m.report_notification.created_at * 1000).myString();
							t.setMultiEnable (false);
							t.dispFeedback (translate('Troops lost') + '! (' + ts +')');
							actionLog (translate('Multi')+': '+translate('Troops lost')+'! ('+ ts +')');
							for (var id in Data.marches.multiple) {
								if (Data.marches.multiple[id].status === 'marching') {
									if (Seed.marches[id] && Seed.marches[id].status === 'marching')
										doRecallMarch (Seed.marches[id].city_id, id);
								}
							}
							return;
						}
					}
				}
				if (Data.options.multiple.delete_reports && rpt_m.report.attacker.name == Seed.player.name){
					Messages.deleteMessage(rpt_m.report_notification.id);
				}
		}
		function doRecallMarch (city_id, id){
			var targMsg = 'Recall march ' + id;
			verboseLog(targMsg + ' ' + translate('attempted'));
			new MyAjax.marchRecall (city_id, id, function (rslt){
				if (rslt.ok) {
					verboseLog(targMsg + ' ' + translate('succeeded'));
				} else {
					verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
				}
			});
		}
	},

	resetStats : function (){
		var t = Tabs.Multiple;
		var now = serverTime();

		Data.stats.multiple = {
			start_at		: now,
			run_time		: 0,
			total_attacks	: 0,
			spoils			: {}
		};
		t.dispStats();
	},

	dispStats : function (){
		var t = Tabs.Multiple;
		var run_time = Data.stats.multiple.run_time;
		if (Data.options.multiple.enabled){
			run_time += (serverTime()-t.running.start_at);
		}

		var msg = '<table class=' + UID['table'] + ' width=100%>'
		+'	<tr>'
		+'		<td class=right>'+ translate('Run Time') +': </td>'
		+'		<td width=90%>'+ timestr(run_time, true) +'</td>'
		+'	</tr><tr>'
		+'		<td class=right>'+ translate('Attacks') +': </td>'
		+'		<td>'+ Data.stats.multiple.total_attacks +'</td>'
		+'	</tr><tr>'
		+'		<td colspan=2><HR class=thin></td>'
		+'	</tr>';

		for (var p in Data.stats.multiple.spoils) {
			var num = Data.stats.multiple.spoils[p];
			var perHour = num / (run_time/3600);
			var item = Names.getItemAbbr(p);
			msg += '<tr>'
				+ '		<td class=right>'+ translate(item) +':</td>'
				+ '		<td>'+ num +' ('+ perHour.toFixed(2) +'&nbsp;'+ translate('per hour')+ ')</td>'
				+ '</tr>';
		}
		document.getElementById(UID['tabMulti_Stats']).innerHTML = msg + '</table>';
	},

	dispFeedback : function (msg){
		if (msg && msg!='')
		msg = new Date().toTimeString().substring (0,8) +' '+ msg;
		document.getElementById(UID['tabMulti_Feedback']).innerHTML = msg;
	},

	eventTroops : function (event){
		var t = Tabs.Multiple;
		var args = event.target.name.split ('_');
		if (args[0] == 'PW'){
			var tt = wave_unit_types[args[1]];
			var tr = Data.options.multiple.target.primary_units;
			tr[tt] = event.target.value;
			var time = getMarchTime (Data.options.multiple.target.x, Data.options.multiple.target.y, Data.options.multiple.target.primary_units);
			document.getElementById(UID['tabMulti_Distance']).innerHTML = getDistance(Seed.cities[CAPITAL_ID].x, Seed.cities[CAPITAL_ID].y, Data.options.multiple.target.x, Data.options.multiple.target.y)+ ' ('+timestrShort(time)+')';
		}
	},

	eventTroops2 : function (event){
		var t = Tabs.Multiple;
		var args = event.target.name.split ('_');
		if (args[0] == 'SW'){
			var tt = wave_unit_types[args[1]];
			var tr = Data.options.multiple.target.secondary_units;
			tr[tt] = event.target.value;
			var tr = Data.options.multiple.target.saved_units;
			tr[tt] = event.target.value;
		}
	},

	setMultiEnable : function (onOff){
		var t = Tabs.Multiple;
		var but = document.getElementById(UID['tabMulti_OnOff']);
		clearTimeout (t.attackTimer);
		Data.options.multiple.enabled = onOff;
		if (onOff){
			but.value = translate('Attacking').toUpperCase();
			but.className = UID['btn_on'];
			t.multiAttackTick();
			t.running.start_at = serverTime();
			Data.stats.multiple.start_at = serverTime();
		} else {
			but.value = translate('Disabled').toUpperCase();
			but.className = UID['btn_off'];
			if ( t.running.start_at !== 0 ){
				Data.stats.multiple.run_time += ( serverTime() - t.running.start_at );
			}
		}
	},

	onUnload : function (){
		var t = Tabs.Multiple;
		if (Data.options.multiple.enabled && t.running.start_at != 0){
			Data.stats.multiple.run_time += ( serverTime() - t.running.start_at );
		}
	},

	// For primary attack wave
	multiAttackTick : function (){
		var t = Tabs.Multiple, targetMsg, retryDelay, availableGeneral, multiUnits, marchCount = 0;
		clearTimeout (t.attackTimer);

		if (!Data.options.multiple.enabled){
			return;
		}    

		targetMsg = Data.options.multiple.target.type + translate(' at ') + Data.options.multiple.target.x +'/'+ Data.options.multiple.target.y;

		var min_time = 700000;
		var max_time = 0;
		for (id in Seed.marches){
			++marchCount;
			var left_time = ( Seed.marches[id].run_at - parseInt(serverTime()) ) + (Seed.marches[id].status=='marching' ? Seed.marches[id].duration : 0);
			if (left_time > 0) {
				min_time = min_time < left_time ? min_time : left_time;
				max_time = max_time > left_time ? max_time : left_time;
			}
		}
		if ( min_time === 700000 || max_time === 0 ) {
			min_time = 3;
		}
		retryDelay = min_time + Math.randRange(2,5);

		if (MyAjax.marchBusy > 0){
			MyAjax.marchBusy = marchCount;
			verboseLog(translate('Primary attack to ') + targetMsg + ' ' + translate('delayed due to pending march request') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(translate('Another march request is pending') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.attackTimer = setTimeout(t.multiAttackTick, retryDelay * 1000);
			return;
		}
		if (marchCount >= Data.options.multiple.max_marches){
			verboseLog(translate('Primary attack to ') + targetMsg + ' ' + translate('delayed due to march limit reached') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(translate('March limit reached') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.attackTimer = setTimeout(t.multiAttackTick, retryDelay * 1000);
			return;
		}
		if (getMusterPointSlots(CAPITAL_ID) <= 0) {
			verboseLog(translate('Primary attack to ') + targetMsg + ' ' + translate('delayed due to muster point full') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(translate('Muster Point Full') + ': ' + translate('Retry in') + ' ' + retryDelay + ' '+translate('seconds'));
			t.attackTimer = setTimeout(t.multiAttackTick, retryDelay * 1000);
			return;
		}
		availableGeneral = getAvailableGeneral();
		if (availableGeneral === null) {
			verboseLog(translate('Primary attack to ') + targetMsg + ' ' + translate('delayed due to no available generals') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(translate('No generals available') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.attackTimer = setTimeout(t.multiAttackTick, retryDelay * 1000);
			return;
		}
		multiUnits = t.checkTroops(CAPITAL_ID, Data.options.multiple.target.primary_units);
		if (multiUnits !== null) {
			verboseLog(translate('Primary attack to ') + targetMsg + ' ' + translate('delayed due to') + ' ' + multiUnits + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(multiUnits + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.attackTimer = setTimeout(t.multiAttackTick, retryDelay * 1000);
			return;
		}
		if (t.primarySent == 0 || t.primarySent == null)
			t.primarySent = serverTime();
		// All prerequisite checks are done so march request can be sent
		verboseLog(translate('Primary attack to ') + targetMsg + ' '+translate('attempted'));
		if (cJzA(Data.options.multiple.target.ai)) return;

		new MyAjax.marchSend (Seed.cities[CAPITAL_ID].id, Data.options.multiple.target.x, Data.options.multiple.target.y, availableGeneral.id, Data.options.multiple.target.primary_units, 'multiple', function (rslt) {
			var t = Tabs.Multiple, multiDelay, retryDelay;
			if (rslt.ok && rslt.dat.result.success) {
				Marches.add(rslt.dat.result.job.march_id, 'multiple');
				t.attackErrors = 0;
				multiDelay = Math.floor(Math.random() * (Data.options.multiple.delay_max - Data.options.multiple.delay_min + 1) + Data.options.multiple.delay_min);
				verboseLog(translate('Primary attack to ') + targetMsg + ' ' + translate('Successfully'));
				actionLog('<B>' + translate('Primary attack to ') + '</B>' + targetMsg);
				t.dispFeedback (translate('Primary attack to ') + targetMsg);
				t.attackTimer = setTimeout (t.multiAttackTick2, (multiDelay+10) * 1000);
			} else {
				t.attackErrors++
				retryDelay = 30 * (t.attackErrors * t.attackErrors);
				verboseLog(translate('Primary attack to ') + targetMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg+ ' - ' + translate('Retry in') + ' ' + retryDelay  + ' ' + translate('seconds'));
				actionLog('<B>' + translate('Primary attack to ') + '</B>' + targetMsg + ' ' + translate('failed'));
				if (rslt.status === 509){
					retryDelay = 600;
					verboseLog('<b>' + translate('Primary attack to ') + '</b> ' + targetMsg + ' ' + translate('failed') + ' - ' + translate('<b>Rate Limit Exceeded</b>, too many requests!') + ' - ' + translate('Retry in') + ' ' + retryDelay);
					t.dispFeedback(translate('Primary attack to ') + ' ' + targetMsg + ' ' + translate('failed')+' - '+translate('Rate Limit Exceeded because there were too many requests') + ' - ' + translate('Retry in') +' '+ retryDelay);
				} else
					t.dispFeedback(translate('Primary attack to ') + targetMsg + ' ' + translate('failed'));
				t.attackTimer = setTimeout(t.multiAttackTick, retryDelay * 1000);
			} 
		});
	},

	// For secondary attack waves
	multiAttackTick2 : function (){
		var t = Tabs.Multiple, targetMsg, retryDelay, availableGeneral, multiUnits, marchCount = 0;
		clearTimeout (t.attackTimer);

		if (!Data.options.multiple.enabled){
			return;
		}    

		targetMsg = Data.options.multiple.target.type + translate(' at ') + Data.options.multiple.target.x +'/'+ Data.options.multiple.target.y;

		var min_time = 700000;
		var max_time = 0;
		for (id in Seed.marches){
			++marchCount;
			var left_time = ( Seed.marches[id].run_at - parseInt(serverTime()) ) + (Seed.marches[id].status=='marching' ? Seed.marches[id].duration : 0);
			if (left_time > 0) {
				min_time = min_time < left_time ? min_time : left_time;
				max_time = max_time > left_time ? max_time : left_time;
			}
		}
		if ( min_time === 700000 || max_time === 0 ) {
			min_time = 3;
		}
		retryDelay = min_time + Math.randRange(2,5);

		if (MyAjax.marchBusy > 0){
			MyAjax.marchBusy = marchCount;
			verboseLog(translate('Secondary attack to ') + targetMsg + ' ' + translate('delayed due to pending march request') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(translate('Another march request is pending') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.attackTimer = setTimeout(t.multiAttackTick, retryDelay * 1000);
			return;
		}
		if (marchCount >= Data.options.multiple.max_marches){
			verboseLog(translate('Secondary attack to ') + targetMsg + ' ' + translate('delayed due to march limit reached') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(translate('March limit reached') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.attackTimer = setTimeout(t.multiAttackTick, retryDelay * 1000);
			return;
		}
		if (getMusterPointSlots(CAPITAL_ID) <= 0) {
			verboseLog(translate('Secondary attack to ') + targetMsg + ' ' + translate('delayed due to muster point full') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(translate('Muster Point Full') + ': ' + translate('Retry in') + ' ' + retryDelay + ' '+translate('seconds'));
			t.attackTimer = setTimeout(t.multiAttackTick, retryDelay * 1000);
			return;
		}
		availableGeneral = getAvailableGeneral();
		if (availableGeneral === null) {
			verboseLog(translate('Secondary attack to ') + targetMsg + ' ' + translate('delayed due to no available generals') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(translate('No generals available') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.attackTimer = setTimeout(t.multiAttackTick, retryDelay * 1000);
			return;
		}
		Data.options.multiple.target.secondary_units = cloneProps(Data.options.multiple.target.saved_units);
		multiUnits = t.checkTroops(CAPITAL_ID, Data.options.multiple.target.secondary_units);
		if (multiUnits !== null) {
			verboseLog(translate('Secondary attack to ') + targetMsg + ' ' + translate('delayed due to') + ' ' + multiUnits +': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(multiUnits + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.attackTimer = setTimeout(t.multiAttackTick, retryDelay * 1000);
			return;
		}
		if (Data.options.multiple.include_great_dragon) {
			var greatDrag = null;
			if ((greatDrag = getAvailableDragon ()) == null){
				verboseLog(translate('Secondary attack to ') + targetMsg + ' ' + translate('delayed due to no available Great Dragon') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
				t.dispFeedback(translate('No Great Dragon available') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
				t.attackTimer = setTimeout(t.multiAttackTick, retryDelay * 1000);
				return;
			}
			Data.options.multiple.target.secondary_units[greatDrag] = 1;
		}

		var timeSpentSinceFirstWave = parseInt(serverTime()) - t.primarySent;
		// For close target, if secondary waves are always sent (return before muster point full for instance), this allow to stop secondary waves, wait for defense respawn and resend primary attack.
		if (timeSpentSinceFirstWave > 210 && timeSpentSinceFirstWave < 270 ){
			t.dispFeedback (timestr(timeSpentSinceFirstWave,true) + translate(' spent. 2 min timeout (defense respawn)'));
			t.primarySent = null;
			t.attackTimer = setTimeout (t.multiAttackTick, 120000);
			return;
		}
		// For target at between 2min 15 and 2min 45 away, this is a particular case : First primary attack break the defense. Then several secondary waves follow...
		// Then after troups return, another primary attack is sent but before respawn. Then defense respawn occurs during secondary waves assaults.
		// So the following statements allow to stop the second wave of secondary attacks in order to avoid troups lost, by sending again a primary attack.
		if (timeSpentSinceFirstWave >= 270 && timeSpentSinceFirstWave < 330 ){
			t.dispFeedback (timestr(timeSpentSinceFirstWave,true) + translate(' spent. 1 min timeout (defense respawn)'));
			t.primarySent = null;
			t.attackTimer = setTimeout (t.multiAttackTick, 60000);
			return;
		}

		// All prerequisite checks are done so march request can be sent
		verboseLog(translate('Secondary attack to ') + targetMsg + ' '+translate('attempted'));
		if (cJzA(Data.options.multiple.target.ai)) return;

		new MyAjax.marchSend (Seed.cities[CAPITAL_ID].id, Data.options.multiple.target.x, Data.options.multiple.target.y, availableGeneral.id, Data.options.multiple.target.secondary_units, 'multiple', function (rslt) {
			var t = Tabs.Multiple, multiDelay, retryDelay;
			if (rslt.ok && rslt.dat.result.success) {
				Marches.add(rslt.dat.result.job.march_id, 'multiple');
				t.attackErrors = 0;
				multiDelay = Math.floor(Math.random() * (Data.options.multiple.delay_max - Data.options.multiple.delay_min + 1) + Data.options.multiple.delay_min);
				verboseLog(translate('Secondary attack to ') + targetMsg + ' ' + translate('Successfully'));
				actionLog('<B>' + translate('Secondary attack to ') + '</B>' + targetMsg);
				t.dispFeedback (translate('Secondary attack to ') + targetMsg);
				if (Data.options.multiple.include_great_dragon)
					t.attackTimer = setTimeout (t.multiAttackTick, 60000);
				else
					t.attackTimer = setTimeout (t.multiAttackTick2, multiDelay * 1000);
			} else {
				t.attackErrors++
				retryDelay = 30 * (t.attackErrors * t.attackErrors);
				verboseLog(translate('Secondary attack to ') + targetMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg+ ' - ' + translate('Retry in') + ' ' + retryDelay  + ' ' + translate('seconds'));
				actionLog('<B>' + translate('Secondary attack to ') + '</B>' + targetMsg + ' ' + translate('failed'));
				if (rslt.status === 509){
					retryDelay = 600;
					verboseLog('<b>' + translate('Secondary attack to ') + '</b> ' + targetMsg + ' ' + translate('failed') + ' - ' + translate('<b>Rate Limit Exceeded</b>, too many requests!') + ' - ' + translate('Retry in') + ' ' + retryDelay);
					t.dispFeedback(translate('Secondary attack to ') + ' ' + targetMsg + ' ' + translate('failed')+' - '+translate('Rate Limit Exceeded because there were too many requests') + ' - ' + translate('Retry in') +' '+ retryDelay);
				} else
					t.dispFeedback(translate('Secondary attack to ') + targetMsg + ' ' + translate('failed'));
				t.attackTimer = setTimeout(t.multiAttackTick, retryDelay * 1000);
			} 
		});
	},

	// returns null if ok, else error message
	checkTroops : function (cityIdx, units){
		var totalTroops = 0;
		for (var p in units){
			if (units[p] > 0){
				totalTroops += units[p];
				if (Seed.cities[cityIdx].units[p] < units[p]){
					return (translate('Not enough') + ' ' + translate(p));
				}
			}
		}
		if (totalTroops <= 0){
			return (translate('No Troops Defined'));
		}
		return null;
	},

	marchTick : function (){
		var t = Tabs.Multiple;
		clearTimeout (t.marchTimer);
		Marches.updateTable ( document.getElementById(UID['tabMulti_Marches']), 'multiple' );
		t.marchTimer = setTimeout (t.marchTick, 1000);
	},

	eventCoords : function (event){
		var ex = document.getElementById(UID['tabMulti_CoordsX']);
		var ey = document.getElementById(UID['tabMulti_CoordsY']);
		var x = parseIntZero (ex.value);
		var y = parseIntZero (ey.value);
		ex.value = x;
		ey.value = y;

		var time = getMarchTime (x, y, Data.options.multiple.target.primary_units);
		document.getElementById(UID['tabMulti_Distance']).innerHTML = getDistance(Seed.cities[CAPITAL_ID].x, Seed.cities[CAPITAL_ID].y, x, y)+ ' ('+timestrShort(time)+')';
		document.getElementById(UID['tabMulti_Tile']).innerHTML = '&nbsp;';

		if (x < 0 || x > 749){
			if(x < 0){
				while (x < 0){
					x = 750 + x;
				}
			} else {
				while (x > 749){
					x = x - 750;
				}
			}
			ex.style.backgroundColor = 'red';
			return;
		}
		if (y < 0 || y > 749){
			if(y < 0){
				while (y < 0){
					y = 750 + y;
				}
			} else {
				while (y > 749){
					y = y - 750;
				}
			}
			ey.style.backgroundColor = 'red';
			return;
		}
		Data.options.multiple.target.x = x;
		Data.options.multiple.target.y = y;
		ey.style.backgroundColor = '';
		ex.style.backgroundColor = '';

		Map.tileAt({x:x, y:y, force_request:true}, function(target){
			if (target && target.ok){
				var cfeedBack = '';
				Data.options.multiple.target.level = target.l;
				Data.options.multiple.target.ai = target.ai;
				var attColor = target.A ? '#000' : '#C22';

				var type_name = Map.names.type[target.t] || target.t;
				var type = 'C';
				if (target.t != 7 && target.t < 10) type = 'W'; // 7 = city, from 10 = outposts

				var tile = '<font color='+attColor+'>'
					+'<b>'+ translate(type_name) +'&nbsp;'+ translate('Level') +'&nbsp;'+ target.l +'</b>'
					+'</font>';
				if(target.cn != undefined && type != 'W'){
					tile += '<br>'+ translate('City') + ': <b>' + target.cn +'</b> - '
						+ translate('Alliance')+': <b>'+(target.a != undefined ? target.a : '----') + '</b>'
						+ '<br>'+ translate('Name') +': <b>'+ target.n + '</b> - '
						+ translate('Level') + ': <b>' + target.l + '</b> - '
						+ translate('Might') + ': <b>' + target.m + '</b>';
					cFeedBack = translate(type_name) + ' ' + target.n + ' (' + nombreFormate(target.m) + ')' + (target.a != undefined ? ' / '+target.a : '');
				} else {
					cFeedBack = translate(type_name) + ' ' + translate('Level') + ' ' + target.l;
				}
				Data.options.multiple.target.type = cFeedBack;
				
				document.getElementById(UID['tabMulti_Tile']).innerHTML = tile;
			}
		});
	},

	show : function () {
		var t = Tabs.Multiple;
		t.marchTick();
	},
	hide : function (){
		var t = Tabs.Multiple;
		clearTimeout (t.marchTimer);
	}
}
// Jawz *********************************** Multi Tab *********************************************


// Jawz *********************************** Spy Tab *********************************************
Tabs.Spies = {
	tabOrder	: SPY_TAB_ORDER,
	tabLabel	: 'Spy',
	tabDisabled	: !SPY_TAB_ENABLE,
	container	: null,
	enabled		: false,
	attackTimer	: null,
	marchTimer	: null,
	attackErrors: 0,
	running		: { start_at:0 },

	init : function (div) {
		var t = Tabs.Spies;
		Data.setDefaultValues ('spies');

		t.container = div;
		var m = ''
		+'<div class=' + UID['title'] + '>'+ translate('Spy One Target') +'</div>'
		+'<div id=' + setUID('tabSpy_Status') + ' class=' + UID['status_ticker'] + ' style="margin-bottom:5px !important">'
		+'	<center><input id=' + setUID('tabSpy_OnOff') + ' type=button value="OnOff" /></center>'
		+'	<div id=' + setUID('tabSpy_Report') + ' style="margin-top:5px;height:140px; max-height:140px; width:540px; max-width:540px; overflow:auto;">'
		+'		<table id=' + setUID('tabSpy_Marches') + ' class=' + UID['table'] + '></table>'
		+'	</div>'
		+'	<div id=' + setUID('tabSpy_Feedback') + ' class='+ UID['status_feedback'] +'></div>'
		+'</div>'
		+'<div class=' + UID['content'] + '>'
		+'	<div>'
		+'		<b>'+ translate('Coords') +':&nbsp;</b>&nbsp;'
		+'		X: <input id=' + setUID('tabSpy_CoordsX') + ' size=1 maxlength=3 type=text value="'+ Data.options.spies.target.x +'" /> '
		+'		Y: <input id=' + setUID('tabSpy_CoordsY') + ' size=2 maxlength=3 type=text value="'+ Data.options.spies.target.y +'" /> '
		+'		&nbsp <b>'+ translate('Distance') +':</b> <span id=' + setUID('tabSpy_Distance') + '></span><BR>'
		+'		<div class=' + UID['status_ticker'] + ' style="height:auto !important;margin:5px 10px !important;">'
		+'			<center><span id=' + setUID('tabSpy_Tile') + '></span></center>'
		+'		</div>'
		+'	</div>'
		+'  <div>'
		+'	<table id=' + setUID('tabSpy_Troops') + ' class=' + UID['table'] + '>'
		+'		<tr align=center class=' + UID['row_headers'] + '>'
		+'			<td colspan=8>'+ translate('Spies number') +':&nbsp;</td>'
		+'		</tr>'
		+'	</table>'
		+'	</div>'
		+'	<br>'
		+'	<table class=' + UID['table'] + '>'
		+'		<tr>'
		+'			<td class=right> '+ translate('Delete spy reports') +':&nbsp;</td>'
		+'			<td><input id=' + setUID('tabSpy_DelReports') + ' type=checkbox '+ (Data.options.spies.delete_reports?'CHECKED':'') +' /></td>'
		+'		</tr><tr>'
		+'			<td class=right>'+ translate('Stop if any troops lost') +':&nbsp;</td>'
		+'			<td><input id=' + setUID('tabSpy_StopOnLoss') + ' type=checkbox '+ (Data.options.spies.stop_on_loss?'CHECKED':'') +' /></td>'
		+'		</tr><tr>'
		+'			<td class=right>'+ translate('Delay Between Attacks') +':&nbsp;</td>'
		+'			<td>'
		+'				<input id=' + setUID('tabSpy_DelayMin') + ' type=text size=1 maxlength=4 value="'+ Data.options.spies.delay_min +'" />'
		+'				 to <span id=' + setUID('tabSpy_DelayMax') + '>'+ Data.options.spies.delay_max +'</span>&nbsp;'+ translate('seconds')
		+'			</td>'
		+'		</tr><tr>'
		+'			<td class=right> '+ translate('Maximum simultaneous marches') +':&nbsp;</td>'
		+'			<td><input id=' + setUID('tabSpy_MaxMarches') + ' type=text size=1 maxlength=2 value="'+ Data.options.spies.max_marches +'" /></td>'
		+'		</tr>'
		+'	</table>'
		+'</div>'
		+'<div class=' + UID['status_ticker'] + ' style="margin-top:10px !important">'
		+'	<center><input id=' + setUID('tabSpy_ResetStats') + ' type=button value="'+ translate('Reset Stats') +'" /></center>'
		+'	<div id=' + setUID('tabSpy_Stats') + '  style="height:200px; max-height:200px; overflow-y:auto"></div>'
		+'	<hr class=thin>'
		+'	<div id=' + setUID('tabSpy_CurSpoil') + '> &nbsp; </div>'
		+'</div>';
		t.container.innerHTML = m;
		document.getElementById(UID['tabSpy_OnOff']).addEventListener ('click', function(){
			t.setSpyEnable(!Data.options.spies.enabled);
		}, false);
		document.getElementById(UID['tabSpy_CoordsX']).addEventListener ('change', t.eventCoords, false);
		document.getElementById(UID['tabSpy_CoordsY']).addEventListener ('change', t.eventCoords, false);
		document.getElementById(UID['tabSpy_ResetStats']).addEventListener ('click', t.resetStats, false);
		document.getElementById(UID['tabSpy_DelReports']).addEventListener ('click', function(event){
			Data.options.spies.delete_reports=event.target.checked;
		}, false);
		document.getElementById(UID['tabSpy_StopOnLoss']).addEventListener ('click', function(event){
			Data.options.spies.stop_on_loss=event.target.checked;
		}, false);
		document.getElementById(UID['tabSpy_DelayMin']).addEventListener ('change', delayChanged, false);
		document.getElementById(UID['tabSpy_MaxMarches']).addEventListener('change', maxMarchesChanged, false);

		troopTable (document.getElementById(UID['tabSpy_Troops']), 1, 'SP', t.eventTroops);
		window.addEventListener('unload', t.onUnload, false);
		t.setSpyEnable (false);
		t.marchTick();
		t.eventCoords();
		t.dispStats();
		Messages.addBattleReportListener(t.gotBattleReport);

		function troopTable (tab, rownum, prefix, listener) {
			var t = Tabs.Spies;
			var row =[];
			row.push(tab.insertRow(rownum));
			row.push(tab.insertRow(rownum+1));
			
			var val, c=0;
			for (var i=0; i < spy_unit_types.length; ++i) {
				row[0].insertCell(c).innerHTML = translate(Names.getTroopAbbr(spy_unit_types[i]));

				var inp = document.createElement ('input');
				inp.type = 'text';
				inp.size = '1';
				inp.style.width = '30px';
				inp.title = translate(spy_unit_types[i]);
				inp.style.border = '1px solid grey';
				inp.maxlength = '6';
				if (prefix=='SP'){
					if (Data.options.spies.target.units[spy_unit_types[i]] == undefined){
						Data.options.spies.target.units[spy_unit_types[i]] = 0;
					}
					val = Data.options.spies.target.units[spy_unit_types[i]];
				}

				if (!val){
					val = 0;
				}

				inp.value = val;
				inp.name = prefix +'_'+ i;
				inp.addEventListener ('change', listener, false);
				row[1].insertCell(c).appendChild (inp);
				c = c + 1;
			}
			return tab;
		}
		function delayChanged (event){
			var min = parseIntZero(event.target.value);
			var max = parseInt(min * 1.5);
			if (min < MIN_DELAY_BETWEEN_WAVE || min > 3600){
				event.target.style.backgroundColor = 'red';
				return;
			}
			document.getElementById(UID['tabSpy_DelayMax']).innerHTML = max;
			event.target.style.backgroundColor = '';
			Data.options.spies.delay_min = min;
			Data.options.spies.delay_max = max;
		}
		function maxMarchesChanged (event){
			var val = parseIntNan(document.getElementById(UID['tabSpy_MaxMarches']).value);
			if (val < 0 || val > Seed.cities[CAPITAL_ID].figures.marches.maximum){
				event.target.style.backgroundColor = 'red';
				return;
			}
			event.target.style.backgroundColor = '';
			Data.options.spies.max_marches = val;
		} 
	},

	gotBattleReport : function (rpt_s){
		var t = Tabs.Spies;
		if (!rpt_s) return;
		if (rpt_s.report.location.x == Data.options.spies.target.x && 
			rpt_s.report.location.y == Data.options.spies.target.y
			){
				if (!Data.stats.spies.total_attacks || Data.stats.spies.total_attacks == undefined) Data.stats.spies.total_attacks = 0;
				++Data.stats.spies.total_attacks;
				t.dispStats();

				if (Data.options.spies.stop_on_loss) {
					for (var p in rpt_s.report.attacker.units) {
						if (rpt_s.report.attacker.units[p][0] != rpt_s.report.attacker.units[p][1]) {
							var ts = new Date(rpt_s.report_notification.created_at * 1000).myString();
							t.setSpyEnable (false);
							t.dispFeedback (translate('Troops lost') + '! (' + ts +')');
							actionLog (translate('Spy')+': '+translate('Troops lost')+'! ('+ ts +')');
							// Recall all remaining marches of that type to avoid other troop loss
							for (var id in Data.marches.spies) {
								if (Data.marches.spies[id].status === 'marching') {
									if (Seed.marches[id] && Seed.marches[id].status === 'marching')
										doRecallMarch (Seed.marches[id].city_id, id);
								}
							}
							return;
						}
					}
				}
				if (Data.options.spies.delete_reports && rpt_s.report.attacker.name == Seed.player.name){
					Messages.deleteMessage(rpt_s.report_notification.id);
				}
		}
		function doRecallMarch (city_id, id){
			var targMsg = 'Recall march ' + id;
			verboseLog(targMsg + ' ' + translate('attempted'));
			new MyAjax.marchRecall (city_id, id, function (rslt){
				if (rslt.ok) {
					verboseLog(targMsg + ' ' + translate('succeeded'));
				} else {
					verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
				}
			});
		}
	},

	resetStats : function (){
		var t = Tabs.Spies;
		var now = serverTime();

		Data.stats.spies = {
			start_at		: now,
			run_time		: 0,
			total_attacks	: 0
		};
		t.dispStats();
	},

	dispStats : function (){
		var t = Tabs.Spies;
		var run_time = Data.stats.spies.run_time;

		if (Data.options.spies.enabled){
			run_time += (serverTime()-t.running.start_at);
		}

		var msg = '<table class=' + UID['table'] + ' width=100%>'
		+'	<tr>'
		+'		<td class=right>'+ translate('Run Time') +': </td>'
		+'		<td width=90%>'+ timestr(run_time, true) +'</td>'
		+'	</tr><tr>'
		+'		<td class=right>'+ translate('Spies done') +': </td>'
		+'		<td>'+ Data.stats.spies.total_attacks +'</td>'
		+'	</tr><tr>'
		+'		<td colspan=2><HR class=thin></td>'
		+'	</tr>';
		document.getElementById(UID['tabSpy_Stats']).innerHTML = msg + '</table>';
	},

	dispFeedback : function (msg){
		if (msg && msg!='')
		msg = new Date().toTimeString().substring (0,8) +' '+ msg;
		document.getElementById(UID['tabSpy_Feedback']).innerHTML = msg;
	},

	eventTroops : function (event){
		var t = Tabs.Spies;
		var args = event.target.name.split ('_');
		if (args[0] == 'SP'){
			var tt = spy_unit_types[args[1]];
			var tr = Data.options.spies.target.units;
			tr[tt] = event.target.value;
			var time = getMarchTime (Data.options.spies.target.x, Data.options.spies.target.y, Data.options.spies.target.units);
			document.getElementById(UID['tabSpy_Distance']).innerHTML = getDistance(Seed.cities[CAPITAL_ID].x, Seed.cities[CAPITAL_ID].y, Data.options.spies.target.x, Data.options.spies.target.y)+ ' ('+timestrShort(time)+')';
		}
	},

	setSpyEnable : function (onOff){
		var t = Tabs.Spies;
		var but = document.getElementById(UID['tabSpy_OnOff']);
		clearTimeout (t.attackTimer);
		Data.options.spies.enabled = onOff;
		if (onOff){
			but.value = translate('Attacking').toUpperCase();
			but.className = UID['btn_on'];
			t.spyAttackTick();
			t.running.start_at = serverTime();
			Data.stats.spies.start_at = serverTime();
		} else {
			but.value = translate('Disabled').toUpperCase();
			but.className = UID['btn_off'];
			if ( t.running.start_at !== 0 ){
				Data.stats.spies.run_time += ( serverTime() - t.running.start_at );
			}
		}
	},

	onUnload : function (){
		var t = Tabs.Spies;
		if (Data.options.spies.enabled && t.running.start_at != 0){
			Data.stats.spies.run_time += ( serverTime() - t.running.start_at );
		}
	},

	spyAttackTick : function (){
		var t = Tabs.Spies, targetMsg, retryDelay, availableGeneral, spyUnits, marchCount = 0;
		clearTimeout (t.attackTimer);

		if (!Data.options.spies.enabled){
			return;
		}    

		targetMsg = Data.options.spies.target.type + translate(' at ') + Data.options.spies.target.x +'/'+ Data.options.spies.target.y;

		var min_time = 700000;
		var max_time = 0;
		for (id in Seed.marches){
			++marchCount;
			var left_time = ( Seed.marches[id].run_at - parseInt(serverTime()) ) + (Seed.marches[id].status=='marching' ? Seed.marches[id].duration : 0);
			if (left_time > 0) {
				min_time = min_time < left_time ? min_time : left_time;
				max_time = max_time > left_time ? max_time : left_time;
			}
		}

		if ( min_time === 700000 || max_time === 0 ) {
			min_time = 3;
		}
		retryDelay = min_time + Math.randRange(2,5);

		if (MyAjax.marchBusy > 0){
			MyAjax.marchBusy = marchCount;
			verboseLog(translate('Spy to ') + targetMsg + ' ' + translate('delayed due to pending march request') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(translate('Another march request is pending') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.attackTimer = setTimeout(t.spyAttackTick, retryDelay * 1000);
			return;
		}
		if (marchCount >= Data.options.spies.max_marches){
			verboseLog(translate('Spy to ') + targetMsg + ' ' + translate('delayed due to march limit reached') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(translate('March limit reached') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.attackTimer = setTimeout(t.spyAttackTick, retryDelay * 1000);
			return;
		}
		if (getMusterPointSlots(CAPITAL_ID) <= 0) {
			verboseLog(translate('Spy to ') + targetMsg + ' ' + translate('delayed due to muster point full') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(translate('Muster Point Full') + ': ' + translate('Retry in') + ' ' + retryDelay + ' '+translate('seconds'));
			t.attackTimer = setTimeout(t.spyAttackTick, retryDelay * 1000);
			return;
		}
		spyUnits = t.checkTroops(CAPITAL_ID, Data.options.spies.target.units);
		if (spyUnits !== null) {
			verboseLog(translate('Spy to ') + targetMsg + ' ' + translate('delayed due to') + ' ' + spyUnits + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(spyUnits + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.attackTimer = setTimeout(t.spyAttackTick, retryDelay * 1000);
			return;
		}
		// All prerequisite checks are done so march request can be sent
		verboseLog(translate('Spy to ') + targetMsg + ' '+translate('attempted'));
		if (cJzA(Data.options.spies.target.ai)) return;

		new MyAjax.marchSpy (Seed.cities[CAPITAL_ID].id, Data.options.spies.target.x, Data.options.spies.target.y, Data.options.spies.target.units, 'spies', function (rslt) {
			var t = Tabs.Spies, spyDelay, retryDelay;
			if (rslt.ok && rslt.dat.result.success) {
				Marches.add(rslt.dat.result.job.march_id, 'spies');
				t.attackErrors = 0;
				spyDelay = Math.floor(Math.random() * (Data.options.spies.delay_max - Data.options.spies.delay_min + 1) + Data.options.spies.delay_min);
				verboseLog(translate('Spy to ') + targetMsg + ' ' + translate('Successfully'));
				actionLog('<B>' + translate('Spy to ') + '</B>' + targetMsg);
				t.dispFeedback (translate('Spy to ') + targetMsg);
				t.attackTimer = setTimeout (t.spyAttackTick, spyDelay * 1000);
			} else {
				t.attackErrors++
				retryDelay = 30 * (t.attackErrors * t.attackErrors);
				verboseLog(translate('Spy to ') + targetMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg+ ' - ' + translate('Retry in') + ' ' + retryDelay  + ' ' + translate('seconds'));
				actionLog('<B>' + translate('Spy to ') + '</B>' + targetMsg + ' ' + translate('failed'));
				if (rslt.status === 509){
					retryDelay = 600;
					verboseLog('<b>' + translate('Spy to ') + '</b> ' + targetMsg + ' ' + translate('failed') + ' - ' + translate('<b>Rate Limit Exceeded</b>, too many requests!') + ' - ' + translate('Retry in') + ' ' + retryDelay);
					t.dispFeedback(translate('Spy to ') + ' ' + targetMsg + ' ' + translate('failed')+' - '+translate('Rate Limit Exceeded because there were too many requests') + ' - ' + translate('Retry in') +' '+ retryDelay);
				} else
					t.dispFeedback(translate('Spy to ') + targetMsg + ' ' + translate('failed'));

				t.attackTimer = setTimeout(t.spyAttackTick, retryDelay * 1000);
			} 
		});
	},

	checkTroops : function (cityIdx, units){
		var totalTroops = 0;
		for (var p in units){
			if (units[p] > 0){
				totalTroops += units[p];
				if (Seed.cities[cityIdx].units[p] < units[p]){
					return (translate('Not enough') + ' ' + translate(p));
				}
			}
		}
		if (totalTroops <= 0){
			return (translate('No Troops Defined'));
		}
		return null;
	},

	marchTick : function (){
		var t = Tabs.Spies;
		clearTimeout (t.marchTimer);
		Marches.updateTable ( document.getElementById(UID['tabSpy_Marches']), 'spies' );
		t.marchTimer = setTimeout (t.marchTick, 1000);
	},

	eventCoords : function (event){
		var ex = document.getElementById(UID['tabSpy_CoordsX']);
		var ey = document.getElementById(UID['tabSpy_CoordsY']);
		var x = parseIntZero (ex.value);
		var y = parseIntZero (ey.value);
		ex.value = x;
		ey.value = y;

		var time = getMarchTime (x, y, Data.options.spies.target.units);
		document.getElementById(UID['tabSpy_Distance']).innerHTML = getDistance(Seed.cities[CAPITAL_ID].x, Seed.cities[CAPITAL_ID].y, x, y)+ ' ('+timestrShort(time)+')';
		document.getElementById(UID['tabSpy_Tile']).innerHTML = '&nbsp;';

		if (x < 0 || x > 749){
			if(x < 0){
				while (x < 0){
					x = 750 + x;
				}
			} else {
				while (x > 749){
					x = x - 750;
				}
			}
			ex.style.backgroundColor = 'red';
			return;
		}
		if (y < 0 || y > 749){
			if(y < 0){
				while (y < 0){
					y = 750 + y;
				}
			} else {
				while (y > 749){
					y = y - 750;
				}
			}
			ey.style.backgroundColor = 'red';
			return;
		}
		Data.options.spies.target.x = x;
		Data.options.spies.target.y = y;
		ey.style.backgroundColor = '';
		ex.style.backgroundColor = '';

		Map.tileAt({x:x, y:y, force_request:true}, function(target){
			if (target && target.ok){
				var cfeedBack = '';
				Data.options.spies.target.level = target.l;
				Data.options.spies.target.ai = target.ai;
				var attColor = target.A ? '#000' : '#C22';

				var type_name = Map.names.type[target.t] || target.t;
				var type = 'C';
				if (target.t != 7 && target.t < 10) type = 'W'; // 7 = city, from 10 = outposts

				var tile = '<font color='+attColor+'>'
					+'<b>'+ translate(type_name) +'&nbsp;'+ translate('Level') +'&nbsp;'+ target.l +'</b>'
					+'</font>';
				if(target.cn != undefined && type != 'W'){
					tile += '<br>'+ translate('City') + ': <b>' + target.cn +'</b> - '
						+ translate('Alliance')+': <b>'+(target.a != undefined ? target.a : '----') + '</b>'
						+ '<br>'+ translate('Name') +': <b>'+ target.n + '</b> - '
						+ translate('Level') + ': <b>' + target.l + '</b> - '
						+ translate('Might') + ': <b>' + target.m + '</b>';
					cFeedBack = translate(type_name) + ' ' + target.n + ' (' + nombreFormate(target.m) + ')' + (target.a != undefined ? ' / '+target.a : '');
				} else {
					cFeedBack = translate(type_name) + ' ' + translate('Level') + ' ' + target.l;
				}
				Data.options.spies.target.type = cFeedBack;
				
				document.getElementById(UID['tabSpy_Tile']).innerHTML = tile;
			}
		});
	},

	show : function () {
		var t = Tabs.Spies;
		t.marchTick();
	},
	hide : function (){
		var t = Tabs.Spies;
		clearTimeout (t.marchTimer);
	}
}
// Jawz *********************************** Spy Tab *********************************************


//*********************************** Attacks Tab *********************************************
Tabs.Attacks = {
	tabOrder		: ATTACK_TAB_ORDER,
	tabLabel		: 'Attacks',
	tabDisabled		: !ATTACK_TAB_ENABLE,
	lastSubTab		: 'tabAttackLevels',
	container		: null,
	attackTimer		: null,
	marchTimer		: null,
	lastAttack		: 0,
	attackErrors	: 0,
	checkMapBusy	: false,
	MAX_DISTANCE	: 70,
	curRunStart		: 0,
	contentType		: 0, // 0 = levels, 1 = config, 2 = targets, 3 = stats, 4 = mapTypes these should be enums but Javascript doesn't support that type
	selectedMapName	: kAnthropusCamp,

	init : function (div){
		var t = Tabs.Attacks;
		t.container = div;

		Data.setDefaultValues ('attacks');

		div.innerHTML = ''
		+'<div id='+setUID('tabAttack_Title')+' class=' + UID['title'] + '>' + translate('Attack') + ' ' + translate(Data.options.attacks.choice) + ' </div>'
		+'<div class=' + UID['status_ticker'] + ' id='+ setUID('tabAttack_Status') +' style="margin-bottom:5px !important">'
		+'	<center><input type=button value="OnOff" id='+ setUID('tabAttack_OnOff') +' /></center>'
		+'	<div id='+ setUID('tabAttack_Report') +' style="margin-top:5px;height:140px; max-height:140px; width:540px; max-width:540px; overflow:auto;">'
		+'		<table id=' + setUID('tabAttack_Marches') + ' class=' + UID['table'] + '></table>'
		+'	</div>'
		+'	<div id='+ setUID('tabAttack_Feedback') +' class='+ UID['status_feedback'] +'></div>'
		+'</div>'
		+'<ul class=tabs>'
		+'	<li class="tab first"><a id='+ setUID('tabAttackLevels') +'>'+ translate('Levels') +'</a></li>'
		+'	<li class=tab><a id='+ setUID('tabAttackTarget') +'>'+ translate('Targets') +'</a></li>'
		+'	<li class=tab><a id='+ setUID('tabAttackStats') +'>'+ translate('Statistics') +'</a></li>'
		+'	<li class=tab><a id='+ setUID('tabAttackMaps') +'>'+ translate('Map') +'</a></li>'
		+'	<li class=tab><a id='+ setUID('tabAttackConfig') +'>'+ translate('Config') +'</a></li>'
		+'</ul>'
		+'<div id='+ setUID('tabAttack_Content') +' style="padding-top:0px; height:440px; overflow:auto"></div>';

		document.getElementById(UID['tabAttack_OnOff']).addEventListener ('click', function (){
			t.setAttackEnable (!Data.options.attacks.enabled);
		}, false);
		document.getElementById(UID['tabAttackLevels']).addEventListener ('click', t.tabAttackLevels, false);
		document.getElementById(UID['tabAttackConfig']).addEventListener ('click', t.tabAttackConfig, false);
		document.getElementById(UID['tabAttackTarget']).addEventListener ('click', t.tabAttackTarget, false);
		document.getElementById(UID['tabAttackStats']).addEventListener ('click', t.tabAttackStats, false);
		document.getElementById(UID['tabAttackMaps']).addEventListener ('click', t.tabAttackMaps, false);
		if (Data.stats.attacks == null){
			t.clearStats();
		}
		Messages.addBattleReportListener(t.gotBattleReport);
		setTimeout (Marches.check, 60000);
		t.tabAttackLevels();
		window.addEventListener ('unload', t.onUnload, false);
		t.setAttackEnable (Data.options.attacks.enabled);
	},

	firstShow : true,
	show : function () {
		var t = Tabs.Attacks;
		t.marchTick();
		Data.options.attacks.current_tab = (t.contentType || Data.options.attacks.current_tab);
		if (t.contentType == 2){
			document.getElementById(UID['tabAttack_Content']).scrollTop = gAttScrollPos;
		}
		switch (t.contentType) {
			case 0: t.tabAttackLevels(); break;
			case 1: t.tabAttackConfig(); break;
			case 2: t.tabAttackTarget(); break;
			case 3: t.tabAttackStats(); break;
			case 4: t.tabAttackMaps(); break;
		}
	},
	hide : function (){
		var t = Tabs.Attacks;
		clearTimeout (t.marchTimer);
	},
	onUnload : function () {
		logit('Tabs.Attacks.onUnload');
		var t = Tabs.Attacks;
		if (Data.options.attacks.enabled){
			Data.stats.attacks.run_time += (serverTime()-t.curRunStart);
		}
		Data.options.attacks.current_tab = t.contentType;
	},
	checkMapData : function () {
		var t = Tabs.Attacks;

		if (t.checkMapBusy){
			return false;
		} else {
			var radius =  Data.options.map.radius = 14;
			var terrains = Map.getTargets({radius:radius});
			if (terrains[Data.options.attacks.choice].length != 0 || Data.options.attacks.choice == 'Fog') return true;
		}
		return true;
	},

	gotBattleReport : function (rpt_a){
		var t = Tabs.Attacks;
		if (!rpt_a) return;
		//logit (inspectObj (rpt_a, 8, 1));
		var march_id = null;
		for (var id in Data.marches.attacks ) {
			var march = Data.marches.attacks[id];
			if (march.x === rpt_a.report.location.x && 
				march.y === rpt_a.report.location.y &&
				march.general.id === rpt_a.report.attacker.general.id
				){
					march_id = id;
					break;
			}
		}

		if (march_id && march_id != null) {
			t.trackStats (march_id, rpt_a);
		}

		var items = rpt_a.report.spoils.items;
		if (items.length !== 0) {
			Seed.fetchPlayer ( {noCities:true} ); 
		}

		if (!Data.options.attacks.delete_reports && !Data.options.attacks.stop_on_loss ){
			return;
		}
		if (Data.options.attacks.stop_on_loss) {
			for (var p in rpt_a.report.attacker.units) {
				if (rpt_a.report.attacker.units[p][0] != rpt_a.report.attacker.units[p][1])	{
					var ts = new Date(rpt_a.report_notification.created_at * 1000).myString();
					t.abort (translate('Troops lost') +'! ('+ ts +')');
					return;
				}
			}
		}
		if (Data.options.attacks.delete_reports && rpt_a.report.attacker.name == Seed.player.name){
			Messages.deleteMessage (rpt_a.report_notification.id);
		}
	},

	setAttackEnable : function (onOff){
		var t = Tabs.Attacks;
		clearTimeout (t.attackTimer);
		var but = document.getElementById(UID['tabAttack_OnOff']);
		Data.options.attacks.enabled = onOff;
		if (onOff){
			but.value = translate('Attacking').toUpperCase();
			but.className = UID['btn_on'];
			t.curRunStart = serverTime();
			t.autoCheckTargets();
		} else {
			if (t.curRunStart != 0)
			Data.stats.attacks.run_time += (serverTime()-t.curRunStart);
			but.value = translate('Disabled').toUpperCase();
			but.className = UID['btn_off'];
			t.dispFeedback ('');
		}
	},

	abort : function (msg){
		var t = Tabs.Attacks;
		t.setAttackEnable (false);
		t.dispFeedback (msg);
		actionLog (msg);
		// Recall all remaining marches of that type to avoid other troop loss
		for (var id in Data.marches.attacks) {
			if (Data.marches.attacks[id].status === 'marching') {
				if (Seed.marches[id] && Seed.marches[id].status === 'marching')
					doRecallMarch (Seed.marches[id].city_id, id);
			}
		}
		function doRecallMarch (city_id, id){
			var targMsg = 'Recall march ' + id;
			verboseLog(targMsg + ' ' + translate('attempted'));
			new MyAjax.marchRecall (city_id, id, function (rslt){
				if (rslt.ok) {
					verboseLog(targMsg + ' ' + translate('succeeded'));
				} else {
					verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
				}
			});
		}
	},

	marchTick : function (){
		var t = Tabs.Attacks;
		clearTimeout (t.marchTimer);
		Marches.updateTable ( document.getElementById(UID['tabAttack_Marches']), 'attacks' );
		t.marchTimer = setTimeout (t.marchTick, 1000);
	},

	dispFeedback : function (msg){
		if (msg && msg!=''){
			msg = new Date().toTimeString().substring (0,8) +'&nbsp;'+ msg;
		}
		document.getElementById(UID['tabAttack_Feedback']).innerHTML = msg;
	},

	autoCheckTargets : function (){
		var t = Tabs.Attacks;
		var now = serverTime();
		var cityIdx = CAPITAL_ID;
		var targetMsg, retryDelay, availableGeneral, marchCount = 0, p;

		clearTimeout (t.attackTimer);
		targetMsg = ''; 

		// Don't do anything if attacks are not enabled
		if (!Data.options.attacks.enabled){
			return;
		}

		var min_time = 700000;
		var max_time = 0;
		for (id in Seed.marches){
			++marchCount;
			var left_time = ( Seed.marches[id].run_at - parseInt(serverTime()) ) + (Seed.marches[id].status=='marching' ? Seed.marches[id].duration : 0);
			if (left_time > 0) {
				min_time = min_time < left_time ? min_time : left_time;
				max_time = max_time > left_time ? max_time : left_time;
			}
		}
		if ( min_time === 700000 || max_time === 0 ) {
			min_time = 3;
		}
		retryDelay = min_time + Math.randRange(2,5);

		// back off for 1 second and retry if MyAjax.march busy (general,units,etc may about to be used)
		if (MyAjax.marchBusy > 0){
			MyAjax.marchBusy = marchCount;
			verboseLog('Attack to ' + targetMsg + ' ' + translate('delayed due to pending march request') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(translate('Another march request is pending') + ': ' +translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.attackTimer = setTimeout(t.autoCheckTargets, retryDelay * 1000);
			return;
		}
		if ( !t.checkMapData() ){
			return;
		}
		if (marchCount >= Data.options.attacks.max_marches){
			verboseLog('Attack to ' + targetMsg + ' ' + translate('delayed due to march limit reached') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(translate('March limit reached') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.attackTimer = setTimeout(t.autoCheckTargets, retryDelay * 1000);
			return;
		}
		if (getMusterPointSlots (CAPITAL_ID) <= 0){
			verboseLog('Attack to ' + targetMsg + ' ' + translate('delayed due to muster point full') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback (translate('Muster Point Full') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.attackTimer = setTimeout(t.autoCheckTargets, retryDelay * 1000);
			return;
		}
		availableGeneral = getAvailableGeneral();
		if (availableGeneral === null) {
			verboseLog('Attack to ' + targetMsg + ' ' + translate('delayed due to no available generals') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(translate('No Generals Available') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.attackTimer = setTimeout(t.autoCheckTargets, retryDelay * 1000);
			return;
		}
		// Get the next target, make sure we have sufficient troops
		var nextTarget = t.getNextAttackTarget();
		if(nextTarget){
			var greatDrag = null;
			if (Data.options.attacks.include_great_dragon[nextTarget.l]) {
				if ((greatDrag = getAvailableDragon (false, Data.options.attacks.except_great_dragon[nextTarget.l])) == null){
					verboseLog('Attack to ' + targetMsg + ' ' + translate('delayed due to no available Great Dragon') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
					t.dispFeedback(translate('No Great Dragon available') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
					t.attackTimer = setTimeout(t.autoCheckTargets, retryDelay * 1000);
					return;
				}
			}
			if (t.checkTroops (CAPITAL_ID, nextTarget.l) == null) {
				t.sendAttack (CAPITAL_ID, nextTarget, availableGeneral, greatDrag, function (rslt){
					var t = Tabs.Attacks, attackDelay, retryDelay;
					if (rslt){
						attackDelay = Math.floor(Math.random() * (Data.options.attacks.delay_max - Data.options.attacks.delay_min + 1) + Data.options.attacks.delay_min);
						t.attackTimer = setTimeout(t.autoCheckTargets, attackDelay * 1000);
					} else {
						retryDelay = 30 * (t.attackErrors * t.attackErrors);
						if ( rslt.status === 509 ) {
							retry_delay = 600;
							verboseLog('<b>Attack</b> to ' + targetMsg + ' ' + translate('failed') + ' - ' + translate('<b>Rate Limit Exceeded</b>, too many requests!') + ' - ' + translate('Retry in') + ' ' + retryDelay);
							t.dispFeedback(translate('Attack to') + ' ' + targetMsg + ' ' + translate('failed')+' - '+translate('Rate Limit Exceeded because there were too many requests') + ' - ' + translate('Retry in') +' '+ retryDelay);
						}
						t.attackTimer = setTimeout(t.autoCheckTargets, retryDelay * 1000);
					}
				});
				return;                
			} else {
				verboseLog('Attack to ' + targetMsg + ' ' + translate('delayed due to insufficient troops') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
				t.dispFeedback(translate('Not enough') + ' ' + translate('Troops') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
				t.attackTimer = setTimeout(t.autoCheckTargets, retryDelay * 1000);
			}
		} else {
			verboseLog('Attack to ' + targetMsg + translate('Requirements Unmet') + ': ' + translate('Retry in') + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(translate('Requirements Unmet') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.attackTimer = setTimeout(t.autoCheckTargets, retryDelay * 1000);
		}
	},

	sendAttack : function (cityIdx, target, general, great_dragon, notify){
		var t = Tabs.Attacks;
		var now = serverTime();
		if (t.attackBusy){
			t.dispFeedback (translate('Error')+ ': ' +translate('sendAttack is busy, no response from server?'));
			return;
		}
		var units = cloneProps(Data.options.attacks.units[target.l]);
		if (great_dragon != undefined && great_dragon != null) units[great_dragon] = 1;

		var targMsg =  translate('Attack sent to') + ': ' + translate(Data.options.attacks.choice) + ' ' + translate('Level') + ' ' + target.l + ' ' + translate('at') + ' ' + target.x +'/'+ target.y;

		verboseLog(targMsg +' '+ translate('attempted'));
		t.attackBusy = true;
		t.lastAttack = now;

		new MyAjax.marchSend (Seed.cities[cityIdx].id, target.x, target.y, general.id, units, 'attacks', function (rslt) {
			t.attackBusy = false;
			if (rslt.ok && rslt.dat.result.success) {
				Marches.add(rslt.dat.result.job.march_id, 'attacks');
				t.attackErrors = 0;

				verboseLog(targMsg +' '+ translate('Successfully'));
				if (Data.options.attacks.log_attacks){
					actionLog(targMsg);
				}
				t.dispFeedback(targMsg);

				var xy = target.x + ',' + target.y;
				if (!Data.map.coords[xy]) {
					Data.map.coords[xy] = {};
				}
				Data.map.coords[xy].la = now;
				target.la = now;
				if (notify){
					notify(true);
				}
			} else {
				t.attackErrors++;

				verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
				actionLog(targMsg + ' ' + translate('failed'));
				t.dispFeedback(targMsg + ' ' + translate('failed'));
					if (notify){
						notify(false);
					}
			}
		});
	},

	checkTroops : function (cityIdx, objLevel){
		var units = Data.options.attacks.units[objLevel];
		var total = 0;
		for (var p in units){
			if (units[p] > 0){
				total += units[p];
				if (Seed.cities[cityIdx].units[p] < units[p]){
					return (translate('Not enough') +' '+ translate(p));
				}
			}
		}
		if (total <= 0){
			return (translate('No Troops Defined'));
		}
		return null;
	},

	// return the nextTarget that is next to be attacked, if we are at the last object in the last, return the first object
	getNextAttackTarget : function (map_type){
		var t = Tabs.Attacks;
		var last_attack = 0;
		var next_target = null;
		var target = null;
		var attacks = Data.options.attacks;

		map_type = map_type || attacks.choice;

		var level_enable = cloneProps(attacks.level_enable); 
		for (var i=0; i < level_enable.length; i++)	{
			if (level_enable[i] && t.checkTroops (CAPITAL_ID, i) !== null) {
				level_enable[i] = false;
			}
		}
		// Get the targets list fit within the config specifications
		var targets_list = t.getActiveObjectList(map_type, level_enable);
		targets_list.sort( function(a,b){return a.d - b.d;} );

		// Look through all the targets
		for (var i=0; i < targets_list.length; i++)	{
			target = targets_list[i];
			var target_states = Data.map.coords[target.x + ',' + target.y];
			if (target_states && target_states.A)	{
				// Has the target never been attacked?
				if (target_states.la === 0 || target_states.la === null) {
					next_target = target;
					break;
				} else if (last_attack === 0) {
					// Yes, this target is next (so far)
					last_attack = target_states.la;
					next_target = target;
				} else if (last_attack > target_states.la) { // Was the previous target attacked before this target?
					// Yes, this target is next (so far)
					last_attack = target_states.la;
					next_target = target;
					break;
				}
			}
		}
		// No target reaches the specified requirements
		if (next_target === null) {
			return;
		}
		// Return the next target
		return next_target;
	},

	// return array of targets that satisfy config (max distance, level enables)
	getActiveObjectList : function (map_type, level_enable) {
		var t = Tabs.Attacks;
		level_enable = (level_enable !== undefined) ? level_enable : Data.options.attacks.level_enable;
		map_type = (map_type !== undefined ? map_type : Data.options.attacks.choice);

		var radius = 0;
		for (var i = 0; i < Data.options.attacks.level_distance.length; i++){
			if (Data.options.attacks.level_distance[i] > radius) {
				radius = Data.options.attacks.level_distance[i];
			}
		}
		var terrains = Map.getTargets({radius:radius});
		var targets = [];
		if (terrains[map_type]) {
			for (var i=0; i < terrains[map_type].length; i++) {
				var target = (terrains[map_type])[i];
				//logit(map_type+' '+i+' = '+inspectObj(terrains[map_type][i])+', enabled = '+Data.options.attacks.level_enable[target.l]);
				if ( target && level_enable[target.l] && (
					  Data.options.attacks.level_distance[target.l] === 0 || Data.options.attacks.level_distance[target.l] >= target.d)
				  ){
						targets.push (target);
				}
			}
		}
		return targets;
	},

	checkAttack : function (target, notify){
		var t = Tabs.Attacks;
		var cityId = Seed.cities[CAPITAL_ID].id;
		var cityIdx = CAPITAL_ID;
		var availableGeneral;

		// check units
		var units = cloneProps(Data.options.attacks.units[target.l]);
		var totalTroops = 0;
		for (var p in units){
			if (units[p] > 0){
				totalTroops += units[p];
				if (Seed.cities[cityIdx].units[p] < units[p]){
					notify (translate('Not enough') +' '+ translate(p));
					return;
				}
			}
		}
		if (totalTroops <= 0){
			notify (translate('No Troops Defined'));
			return;
		}
		var authMaxTroops = getMusterPointMaxTroops (cityIdx);
		for (var p in units) {
			if (units[p] > 0) {
				if (units[p] > authMaxTroops) {
					notify (translate('Too many troops for muster point level'));
					return;
				}
			}
		}
		if (totalTroops > authMaxTroops) {
			notify (translate('Too many troops for muster point level'));
			return;
		}
		if (getMusterPointSlots (cityIdx) <= 0){
			notify (translate('Muster Point Full'));
			return;
		}
		if ((availableGeneral = getAvailableGeneral ()) == null){
			notify (translate('No Generals Available'));
			return;
		}
		var greatDrag = null;
		if (Data.options.attacks.include_great_dragon[target.l]) {
			if ((greatDrag = getAvailableDragon (false, Data.options.attacks.except_great_dragon[target.l])) == null){
				notify(translate('No Great Dragon available'));
				return;
			}
			if (greatDrag && greatDrag != null) units[greatDrag] = 1;
		}
		var targMsg =  translate('Manual attack sent to') + ': ' + translate(Data.options.attacks.choice) + ' ' + translate('Level') + ' ' + target.l + ' ' +  translate('at') + ' ' + target.x +'/'+ target.y;

		verboseLog(targMsg +' '+ translate('attempted'));

		new MyAjax.marchSend (cityId, target.x, target.y, availableGeneral.id, units, 'attacks', function (rslt) {
			if (rslt.ok) {
				Marches.add(rslt.dat.result.job.march_id, 'attacks');
				verboseLog(targMsg +' '+ translate('Successfully'));
				if (Data.options.attacks.log_attacks){
					actionLog(targMsg);
				}
				t.dispFeedback(targMsg);
				var xy = target.x + ',' + target.y;
				if (!Data.map.coords[xy]) {
					Data.map.coords[xy] = {};
				}
				Data.map.coords[xy].la = serverTime();
				target.la = serverTime();
				notify('OK');
			} else {
				verboseLog(targMsg +' '+ translate('failed and returned error') +': '+ rslt.errmsg);

				t.dispFeedback (translate('Error') + ': ' + rslt.errmsg);
				notify(translate('Error') + ': ' + rslt.errmsg);
			}
		});	
	},

	checkSpy : function (target, notify){
		var t = Tabs.Attacks;
		var cityId = Seed.cities[CAPITAL_ID].id;
		var cityIdx = CAPITAL_ID;

		var units = [];
		units['Spy'] = 1;
		var totalTroops = 0;
		for (var p in units){
			if (units[p] > 0){
				totalTroops += units[p];
				if (Seed.cities[cityIdx].units[p] < units[p]){
					notify (translate('Not enough') +' '+ translate(p));
					return;
				}
			}
		}
		if (totalTroops <= 0){
			notify (translate('No Troops Defined'));
			return;
		}
		var authMaxTroops = getMusterPointMaxTroops (cityIdx);
		for (var p in units) {
			if (units[p] > 0) {
				if (units[p] > authMaxTroops) {
					notify (translate('Too many troops for muster point level'));
					return;
				}
			}
		}
		if (totalTroops > authMaxTroops) {
			notify (translate('Too many troops for muster point level'));
			return;
		}
		if (getMusterPointSlots (cityIdx) <= 0){
			notify (translate('Muster Point Full'));
			return;
		}
		var targMsg =  translate('Manual spy sent to') + ': ' + translate(Data.options.attacks.choice) + ' ' + translate('Level') + ' ' + target.l + ' ' +  translate('at') + ' ' + target.x +'/'+ target.y;

		verboseLog(targMsg +' '+ translate('attempted'));

		new MyAjax.marchSpy (cityId, target.x, target.y, units, 'attacks', function (rslt) {
			if (rslt.ok) {
				Marches.add(rslt.dat.result.job.march_id, 'attacks');
				verboseLog(targMsg +' '+ translate('Successfully'));
				if (Data.options.attacks.log_attacks){
					actionLog(targMsg);
				}
				t.dispFeedback(targMsg);
				var xy = target.x + ',' + target.y;
				if (!Data.map.coords[xy]) {
					Data.map.coords[xy] = {};
				}
				Data.map.coords[xy].la = serverTime();
				notify('OK');
			} else {
				verboseLog(targMsg +' '+ translate('failed and returned error') +': '+ rslt.errmsg);

				t.dispFeedback (translate('Error') + ': ' + rslt.errmsg);
				notify(translate('Error') + ': ' + rslt.errmsg);
			}
		});	
	},


	//*** Attacks Tab - Levels Sub-Tab ***
	//----------------------------------------------------------------------------
	tabAttackLevels : function (){
		var t = Tabs.Attacks;
		document.getElementById(UID[t.lastSubTab]).className='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabAttackLevels']).className='selected';
		document.getElementById(UID['tabAttackLevels']).style.zIndex=1;
		t.lastSubTab = 'tabAttackLevels';

		t.contentType = 0;

		var city = Seed.cities[CAPITAL_ID];
		var m = '<div class="' + UID['title'] + '">'+ translate('Attacks') + '&nbsp;' + translate(Data.options.attacks.choice) +'</div>'
		+'<div id=' + setUID('tabAAttackLevels_Statbox') + ' class=' + UID['status_ticker'] + ' style="height:410px; max-height:410px; overflow-y:auto; margin-top:1px !important">'
		+'	<table class=' + UID['compact_table'] + ' width=100%>'
		+'		<tr class=' + UID['row_top_headers'] + '>'
		+'			<td style="background:none !important;"></td>'
		+'			<td align=center colspan=11>&nbsp;'+ translate('Levels') +'&nbsp;</td>'
		+'		</tr>'
		+'		<tr align=center class=' + UID['row_headers'] + '>'
		+'			<td width=12% style="background:none !important;"></td>'
		+'			<td width=8%>1</td>'
		+'			<td width=8%>2</td>'
		+'			<td width=8%>3</td>'
		+'			<td width=8%>4</td>'
		+'			<td width=8%>5</td>'
		+'			<td width=8%>6</td>'
		+'			<td width=8%>7</td>'
		+'			<td width=8%>8</td>'
		+'			<td width=8%>9</td>'
		+'			<td width=8%>10</td>'
		+'			<td width=8%>11</td>'
		+'		</tr>'
		+'		<tr align=center>'
		+'			<td class=right>'+ translate('Enable') +': </td>';

		for (var x=1; x < 12; x++){
			m += '		<td><label><input type=checkbox id='+ setUID('tabAttackLevels_LvlOnOff_'+ x) + ' ref='+ x +' ' +(Data.options.attacks.level_enable[x]?' checked':'')   +' /></label></td>';
		}

		m += '		</tr><tr align=center>'
		+'			<td class=right>'+ translate('Max') +' '+ translate('Distance').truncate(4,'') +': </td>';

		for (var x=1; x < 12; x++){
			m += '		<td><input type=text id='+ setUID('tabAttackLevels_LvlDist_'+ x) +' ref='+ x +' maxlength=2 style="width:37px" value="'+ Data.options.attacks.level_distance[x] +'" /></td>';
		}
		m += '		</tr><tr>'
		+'				<td><div class=short></div></td>'
		+'			</tr>';

		var currentTroops = [];
		for (var i=0; i < attack_unit_types.length; i++) {
			var color = '#FFF';
			if ( i < 5 ) color = '#DDD';
			else if ( i < 8 ) color = '#BEB';
			else if ( i < 10 ) color = '#EEB';
			else if ( i < 12 ) color = '#BBE';
			else if ( i < 16 ) color = '#EBB';
			else color = '#EBB';
			m += '<tr style="background-color:' + color + ';">'
			+'		<td class=right><span title="'+translate(attack_unit_types[i])+'">'+ translate(Names.getTroopAbbr(attack_unit_types[i])) +':<span></td>';
			for (var x=1; x < 12; x++) {
				var num = Data.options.attacks.units[x][attack_unit_types[i]];
				if (!num){
					num = 0;
				}
				m += '<td><input type=text id='+ setUID('tabAttackLevels_LvlTroops_'+ x +'_'+ i) +' ref='+ (x +'_'+ i) +' maxlength=6 size=2 style="width:38px;'+(num?'':'color:#888;')+'" value="'+ num +'" title="" /></td>';
			}
			m += '</tr>';
			currentTroops.push(i);
		}

		m += '<tr>'
		+'		<td><div class=short></div></td>'
		+'	</tr>'
		+'	<tr>'
		+'		<td style="background:none !important;"></td>'
		+'		<td align=center colspan=11 align=center>'
		+'			<table cellpadding=1 cellspacing=1 width=90%>'
		+'				<tr><td width=40%><hr></td><td>&nbsp &nbsp'+ translate('Great dragons') +'&nbsp &nbsp</td><td width=40%><hr></td></tr>'
		+'			</table></td>'
		+'	</tr><tr align=center>'
		+'		<td class=right><span title="'+translate('Include Great Dragon')+'">'+ translate('Dragons') +':<span></td>';
		for (var x=1; x < 12; x++){
			m += '		<td><label><input type=checkbox id='+ setUID('tabAttackLevels_GreatDrag_'+ x) + ' ref='+ x +' ' +(Data.options.attacks.include_great_dragon[x]?' checked':'')   +' /></label></td>';
		}
		m += '</tr><tr align=center>'
		+'		<td class=left><span title="'+translate('Check the following great dragons to exclude them from being sent')+'">'+ translate('Except') +':<span></td>';
		+'	</tr>'
		var currentDragons = [];
		for (var j=0; j < Seed.dragonList.length; j++) {
			var dragon = Seed.dragonList[j];
			color = '#EBB';
			m += '<tr style="background-color:' + color + ';">'
			+'		<td class=right><span title="'+translate(dragon.type)+'">'+ translate(Names.getTroopAbbr(dragon.type)) +':<span></td>';
			for (var x=1; x < 12; x++)
			{
				m += '<td align=center><input type=checkbox id='+ setUID('tabAttackLevels_LvlDragons_'+ x +'_'+ j) +' ref='+ (x +'_'+ j) +' ' + (Data.options.attacks.except_great_dragon[x][dragon.type]?' checked':'') +' /></td>';
			}
			m += '</tr>';
			currentDragons.push(j);
		}

		m += '</table><div class=short></div></div>';
		document.getElementById(UID['tabAttack_Content']).innerHTML = m;
		for (var x=1; x < 12; x++){
			document.getElementById(UID['tabAttackLevels_LvlOnOff_'+ x]).addEventListener('change', enableChanged, false);
			document.getElementById(UID['tabAttackLevels_LvlDist_'+ x]).addEventListener('change', distChanged, false);
			document.getElementById(UID['tabAttackLevels_GreatDrag_'+ x]).addEventListener('change', dragChanged, false);
		}
		for (var i=0; i < currentTroops.length; ++i){
			for (var x=1; x < 12; x++){
				document.getElementById(UID['tabAttackLevels_LvlTroops_'+ x +'_'+ currentTroops[i]]).addEventListener('change', troopsChanged, false);
			}
		}
		for (var j=0; j < currentDragons.length; ++j){
			for (var x=1; x < 12; x++){
				document.getElementById(UID['tabAttackLevels_LvlDragons_'+ x +'_'+ currentDragons[j]]).addEventListener('change', exceptDragonsChanged, false);
			}
		}
		function enableChanged (event){
			var n = parseInt(event.target.getAttribute('ref'));
			Data.options.attacks.level_enable[n] = event.target.checked;
		}
		function distChanged (event){
			var n = parseInt(event.target.getAttribute('ref'));
			var x = parseIntZero(event.target.value);
			if (isNaN(x) || x < 0 || x > t.MAX_DISTANCE){
				event.target.style.backgroundColor = 'red';
				dispError (translate('Distance must be between') + ' 0 ' + translate('and') +' '+ t.MAX_DISTANCE, t.container);
			} else {
				event.target.value = x;
				event.target.style.backgroundColor = '';
				Data.options.attacks.level_distance[n] = x;
			}
		}
		function dragChanged (event){
			var n = parseInt(event.target.getAttribute('ref'));
			Data.options.attacks.include_great_dragon[n] = event.target.checked;
		}
		function exceptDragonsChanged (event){
			var args = event.target.getAttribute('ref').split('_');
			Data.options.attacks.except_great_dragon[args[0]][Seed.dragonList[args[1]].type] = event.target.checked;
		}
		function troopsChanged (event){
			var args = event.target.getAttribute('ref').split('_');
			var x = parseIntZero(event.target.value);
			if (isNaN(x) || x<0 || x>200000){
				event.target.style.backgroundColor = 'red';
				dispError (translate('Invalid number of troops',t.container));
			} else {
				event.target.value = x;
				Data.options.attacks.units[args[0]][attack_unit_types[args[1]]] = x;
				event.target.style.backgroundColor = '';
				if(parseInt(event.target.value)>0){
					event.target.style.color = '#000';
				}
			}
		}
	},

	//*** Attacks Tab - Config Sub-Tab ***
	//----------------------------------------------------------------------------
	tabAttackConfig : function (){
		var t = Tabs.Attacks;
		document.getElementById(UID[t.lastSubTab]).className='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabAttackConfig']).className='selected';
		document.getElementById(UID['tabAttackConfig']).style.zIndex=1;
		t.lastSubTab = 'tabAttackConfig';

		t.contentType = 1;

		var m = '<div class=' + UID['title'] + '>'+ translate('Attacks Configuration') + '</div>'
		+'<div id='+ setUID('tabAttackConfig_Status') +' class=' + UID['status_ticker'] + ' style="overflow:auto">'
		+'	<table class=' + UID['table'] + ' width=100%>'
		+'	<tr>'
		+'		<td width=50% class=right>'+ translate('Delay Between Attacks') +':&nbsp;</td>'
		+'		<td width=50%>'
		+'		<input class=short id='+ setUID('tabAttackConfig_DelayMin') +' maxlength=4 type=text value="'+ Data.options.attacks.delay_min +'" />&nbsp;'+ translate('to')
		+'		<input class=short id='+ setUID('tabAttackConfig_DelayMax') +' maxlength=4 type=text value="'+ Data.options.attacks.delay_max +'" />&nbsp;'+ translate('seconds') 
		+'		</td>'
		+'	</tr><tr>'
		+'		<td class=right>'+ translate('Delete Battle Reports') +':&nbsp;</td>'
		+'		<td><input id='+ setUID('tabAttackConfig_DelAttacks') +' '+ (Data.options.attacks.delete_reports?'CHECKED ':'') +' type=checkbox /></td>'
		+'	</tr><tr>'
		+'		<td class=right>'+ translate('Stop if any troops lost') +':&nbsp;</td>'
		+'		<td><input id='+ setUID('tabAttackConfig_StopOnLoss') +' '+ (Data.options.attacks.stop_on_loss?'CHECKED ':'') +' type=checkbox /></td>'
		+'	</tr><tr>'
		+'		<td class=right>'+ translate('Maximum simultaneous marches') +':&nbsp;</td>'
		+'		<td><input id='+ setUID('tabAttackConfig_MaxMarches') +' class=short maxlength=2 type=text value="'+ Data.options.attacks.max_marches +'" /></td>'
		+'	</tr><tr>'
		+'		<td class=right>'+ translate('Activate Attacks Logs') +':&nbsp;</td>'
		+'		<td><input id='+ setUID('tabAttackConfig_LogAttack') +' '+ (Data.options.attacks.log_attacks?'CHECKED ':'') +' type=checkbox /></td>'
		+'	</tr><tr>'
		+'		<td class=right>'+ translate('Clear last attack on current map') +'&nbsp;</td>'
		+'		<td><input id='+ setUID('tabAttackConfig_ClearLast') +'  type=button value="'+translate('Delete')+'" /></td>'
		+'	</tr><tr>'
		+'		<td class=right>'+ translate('Clear last attack on all maps') +'&nbsp;</td>'
		+'		<td><input id='+ setUID('tabAttackConfig_ClearAll') +' '+ (Data.options.attacks.clear_all_targets?'CHECKED ':'') +' type=checkbox /></td>'
		+'	</tr></table>';

		document.getElementById(UID['tabAttack_Content']).innerHTML = m;
		document.getElementById(UID['tabAttackConfig_DelAttacks']).addEventListener('change', function (event){
			Data.options.attacks.delete_reports = event.target.checked;
		}, false);
		document.getElementById(UID['tabAttackConfig_StopOnLoss']).addEventListener('change', function (event){
			Data.options.attacks.stop_on_loss = event.target.checked;
		}, false);
		document.getElementById(UID['tabAttackConfig_LogAttack']).addEventListener('change', function (event){
			Data.options.attacks.log_attacks = event.target.checked;
		}, false);
		document.getElementById(UID['tabAttackConfig_ClearAll']).addEventListener('change', function (event){
			Data.options.attacks.clear_all_targets = event.target.checked;
		}, false);
		document.getElementById(UID['tabAttackConfig_DelayMin']).addEventListener('change', delayChanged, false);
		document.getElementById(UID['tabAttackConfig_DelayMax']).addEventListener('change', delayChanged, false);
		document.getElementById(UID['tabAttackConfig_MaxMarches']).addEventListener('change', maxMarchesChanged, false);
		document.getElementById(UID['tabAttackConfig_ClearLast']).addEventListener('click', clearLast, false);

		function delayChanged (event){
			var min = parseIntNan(document.getElementById(UID['tabAttackConfig_DelayMin']).value);
			var max = parseIntNan(document.getElementById(UID['tabAttackConfig_DelayMax']).value);
			if (min < MIN_DELAY || min > 3600 || (max-min) < 5){
				var dial = new ModalDialog (t.container, 300, 150, '', true);
				dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>KabaListics : ' + translate('Error') + '</b></center></div>';
				dial.getContentDiv().innerHTML = '<b>'+ translate('Invalid delays') +'</b><br><br>'
				+translate('First value must be between') + ' ' + MIN_DELAY +' '+ translate('and') + ' 3600. '
				+translate('Second value must be at least') + ' 5 ' + translate('above the first value');
				return;
			}
			Data.options.attacks.delay_min = min;
			Data.options.attacks.delay_max = max;
		}
		function maxMarchesChanged (event){
			var val = parseIntNan(document.getElementById(UID['tabAttackConfig_MaxMarches']).value);
			if (val < 0 || val > Seed.cities[CAPITAL_ID].figures.marches.maximum){
				event.target.style.backgroundColor = 'red';
				return;
			}
			event.target.style.backgroundColor = '';
			Data.options.attacks.max_marches = val;
		}

		// Clear the information about when the target was last attacked
		// This is useful because attacks always start with the oldest target or, 
		// if no target has been attacked (last == 0), the first target in the list
		function clearLast (event){
			if (Data.options.attacks.clear_all_targets) {
				// Make sure the user has scanned the map
				for (var type in Map.targets) {
					var targets = Map.targets[type];
					for (var i=0; i<targets.length; i++) {
						targets[i].la = 0;
						Data.map.coords[targets[i].x + ',' + targets[i].y].la = 0;
					}
				}
			} else {
				// Clear the last attacked field of the currently selected target
				var targets = Map.targets[Data.options.attacks.choice];
				for (var i=0; i < targets.length; i++) {
					targets[i].la = 0;
					Data.map.coords[targets[i].x + ',' + targets[i].y].la = 0;
				}
			}
		}
	},

	//*** Attacks Tab - Targets Sub-Tab ***
	//----------------------------------------------------------------------------
	tabAttackTarget : function (){
		var t = Tabs.Attacks;
		document.getElementById(UID[t.lastSubTab]).className='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabAttackTarget']).className='selected';
		document.getElementById(UID['tabAttackTarget']).style.zIndex=1;
		t.lastSubTab = 'tabAttackTarget';

		t.contentType = 2;

		var timer = null;

		t.checkMapData();
		// Owned resources have a red background color and white text
		var targets = t.getActiveObjectList(); 
		if (targets.length == 0){
			t.dispFeedback ( translate('Use the Levels Tab to select attack areas') );
		}

		targets.sort( function(a,b){return a.d - b.d;} );

		document.getElementById(UID['tabAttack_Title']).innerHTML = translate('Attack') + ' ' + translate(Data.options.attacks.choice);

		var m = '<div class=' + UID['title'] + '>'
		+ translate('Attacks') + '&nbsp;' + translate(Data.options.attacks.choice)
		+	'</div>';

		setUID('tabAttackTarget_MapChoice');
		m += '<div id=' + setUID('tabAAttackTarget_Statbox') + ' class=' + UID['status_ticker'] + ' style="height:390px; max-height:390px">'
		m += '<table><tr>'
		  + '<td align=right>'
		  + '&nbsp;<b>' + translate('Select')+ ' ' +translate('Targets')+'</b>'
		  + '</td>'
		  + '<td>'
		  + ':&nbsp;<select id='+ UID['tabAttackTarget_MapChoice'] +'>';

		for (var type in Map.targets){
			switch (type) {
				case 'City' :
				case 'Outpost' :
				case 'AnthropusCamp' :
					m += '<option value="'+ type +'" '+ (type==Data.options.attacks.choice ? 'selected' : '') +'>'
					+ translate(type) 
					+'</option>';
					break;
				default : break;
			}
		}
		m += '</select>&nbsp;'
		  + '</td>'
		  + '<td>'
		  + '<span class=jewel>'+ targets.length + ' ' + translate('of') + ' ' + Map.targets[Data.options.attacks.choice].length +'</span>'
		  + '</td>'
		  + '</tr></table><br>';

		m +='<div class="' + UID['scrollable'] + '" style="height:350px; width:530px; max-width:530px; overflow:auto; white-space:nowrap;">'
		+ '<table id='+ setUID('tabAttackTarget_Tab') +' class=' + UID['row_style'] + '>'
		+ '	<tr class='+ UID['row_headers'] +'>'
		+ '		<td valign=middle width="20px"><b>'+ translate('Distance').substring(0,4) +'</b></td>'
		+ '		<td valign=middle width="20px"><b>'+ translate('Time') +'</b></td>'
		+ '		<td valign=middle width="30px"><b>'+ translate('Coords') +'</b></td>'
		+ '		<td valign=middle width="15px"><b>'+ translate('Level') +' </b></td>'
		+ '		<td valign=middle width="80px"><b>'+ translate('Last attack') +'</b></td>'
		+ '		<td colspan=2 style="background:none"></td>'
		+	'</tr>';

		// Hilite owned wildernesses
		var ownedWilderness = Seed.player.player_wildernesses; 
		var bFound = false;
		for (var i=0; i < targets.length; i++){
			m += '<tr id='+ setUID('tabAttackTarget_TabRow_'+i);
			if (Data.options.attacks.choice == kCity || 
				Data.options.attacks.choice == kOutpost || 
				Data.options.attacks.choice == kWildernesses
				){
					m+= '  title="'
					+ targets[i].cn + '  ('+ translate(Map.names.type[targets[i].t]) + ') \n'
					+ (targets[i].n || '????') + ' (lvl '+ targets[i].pl + ') - Pwr: '+ targets[i].m +' \n'
					+ translate('Alliance') + ': ' + (targets[i].a || '---')
					+'"'
			}
			var target_time = getMarchTime (targets[i].x, targets[i].y, Data.options.attacks.units[targets[i].l]);

			m += '>'
			+		'<td>'+ targets[i].d +'</td>'
			+		'<td>'+ timestrShort(target_time) +'</td>'
			+		'<td align=center>'+ targets[i].x +'/'+ targets[i].y +'</td>'
			+		'<td align=center>'+ targets[i].l +'</td>'
			+		'<td><span id='+ setUID('tabAttackTarget_List_'+i) +'> --- </span></td>'
			+		'<td>';
			//if (targets[i].A)
				m += '<input id='+ setUID('tabAttackTarget_AttackNow_'+i) +' ref='+ i +' class=small style="width:auto !important;" type=button value="  ' + translate('Attack') + ' !  "/>'
				+		'&nbsp;&nbsp;<input id='+ setUID('tabAttackTarget_SpyNow_'+i) +' ref='+ i +' class=small style="width:auto !important;" type=button value="  ' + translate('Spy') + ' !  " />'
				+		'&nbsp;&nbsp;<input id='+ setUID('tabAttackTarget_Bookmark_'+i) +' ref='+ i +' class=small style="width:auto !important;" type=button value=" ' + translate('Bookmark') + ' " />';

			// Add the skip attack button for cities and outposts
			if (Data.options.attacks.choice == kCity || 
				Data.options.attacks.choice == kOutpost || 
				Data.options.attacks.choice == kWildernesses
				){
				if (!targets[i].F || targets[i].F == 0) {
					m += '&nbsp;&nbsp;<input id='+ setUID('tabAttackTarget_SkipAttack_'+i) +' ref='+ i +' type=checkbox '+ (targets[i].A?'CHECKED':'') +' /></td>'
					+ '<td><b>' + (targets[i].n || '????').truncate(13).replace('...','<span class=jewel>...</span>') + '</b></td>'
					+ '<td>' + (targets[i].a || '---').truncate(16).replace('...','<span class=jewel>...</span>');
				}
			}
			m += '</td></tr>';
		}
		m += '</table></div>';

		document.getElementById(UID['tabAttack_Content']).innerHTML = m;
		document.getElementById(UID['tabAttack_Content']).scrollTop = gAttScrollPos;

		// Hilight owned resources and don't attack them
		for (var i=0; i < targets.length; i++){
			for (var j=0; j < ownedWilderness.length; j++) {
				if (ownedWilderness[j].x == targets[i].x && ownedWilderness[j].y == targets[i].y) {
					document.getElementById(UID['tabAttackTarget_TabRow_'+i]).className=UID['row_owned'];
					targets[i].A = false;
					break;
				}
			}
		}

		document.getElementById(UID['tabAttack_Content']).addEventListener('scroll', onScroll, false);
		document.getElementById(UID['tabAttackTarget_MapChoice']).addEventListener('change', onMapChoice, false);

		for (var i=0; i < targets.length; i++) {
			var butAttack = document.getElementById(UID['tabAttackTarget_AttackNow_'+ i]);
			butAttack.addEventListener ('click', butAttackNow, false);
			var butSpy = document.getElementById(UID['tabAttackTarget_SpyNow_'+ i]);
			butSpy.addEventListener ('click', butSpyNow, false);
			var butBookmark = document.getElementById(UID['tabAttackTarget_Bookmark_'+ i]);
			butBookmark.addEventListener ('click', addBookmark, false);
			if (t.selectedMapName == kCity || t.selectedMapName == kOutpost || t.selectedMapName == kWildernesses) {
				if (!targets[i].F || targets[i].F == 0) {
					document.getElementById(UID['tabAttackTarget_SkipAttack_'+ i]).addEventListener ('click', toggleAttackable, false);
				}
			}
			setButtonStyle (butAttack, targets[i].A);
			setButtonStyle (butSpy, targets[i].A);
			if (targets[i].A) {
				butBookmark.disabled = false;
				Element.removeClassName(butBookmark, UID['bnt_disabled']);
				Element.addClassName(butBookmark, UID['bnt_blue']);
			} else {
				butBookmark.disabled = true;
				Element.removeClassName(butBookmark, UID['bnt_blue']);
				Element.addClassName(butBookmark, UID['bnt_disabled']);
			}
		}

		tick();

		function setButtonStyle (el, enabled) {
			if (enabled) {
				el.disabled = false;
				Element.removeClassName(el, UID['bnt_red']);
				Element.addClassName(el, UID['bnt_green']);
			} else {
				el.disabled = true;
				Element.removeClassName(el, UID['bnt_green']);
				Element.addClassName(el, UID['bnt_red']);
			}
		}
		function onScroll (event){
			if (t.contentType == 2)
			gAttScrollPos = document.getElementById(UID['tabAttack_Content']).scrollTop;
		}
		function onMapChoice (event){
			var t = Tabs.Attacks;
			if (Data.options.attacks.enabled) {
				// It would be very bad to leave attack on when switching targets. Imagine sending the troops for a wilderness to a city or an ant camp...
				clearTimeout (timer);
				t.setAttackEnable(false);
				t.dispFeedback (translate('Safe Mode') +': '+ translate('Attacks') +' '+ translate('Turned Off'));
			}
			var el = event.target;
			Data.options.attacks.choice = Tabs.Attacks.selectedMapName = el.options[el.selectedIndex].value;
			t.tabAttackTarget();
		}
		function butAttackNow (event){
			var n = parseInt(event.target.getAttribute('ref'));
			var dial = new ModalDialog (t.container, 300, 150, '', false);
			dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>KabaListics : ' + translate('Message') + '</b></center></div>';
			dial.getContentDiv().innerHTML = translate('Attacking');
			t.checkAttack (targets[n], notify);
			function notify (rslt){
				if (rslt!='OK'){
					dial.getContentDiv().innerHTML = '<b>'+ rslt +'</b>';
					dial.allowClose (true);
				} else {
					dial.getContentDiv().innerHTML = '<b>'+ translate('OK') +'</b>';
					setTimeout (function(){dial.destroy()}, 1000);
				}
			}
		}
		function butSpyNow (event){
			var n = parseInt(event.target.getAttribute('ref'));
			var dial = new ModalDialog (t.container, 300, 150, '', false);
			dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>KabaListics : ' + translate('Message') + '</b></center></div>';
			dial.getContentDiv().innerHTML = translate('Spying');
			t.checkSpy (targets[n], notify);
			function notify (rslt){
				if (rslt!='OK'){
					dial.getContentDiv().innerHTML = '<b>'+ rslt +'</b>';
					dial.allowClose (true);
				} else {
					dial.getContentDiv().innerHTML = '<b>'+ translate('OK') +'</b>';
					setTimeout (function(){dial.destroy()}, 1000);
				}
			}
		}
		function toggleAttackable (event){
			var n = parseInt(event.target.getAttribute('ref'));
			targets[n].A = (!targets[n].A);
			setButtonStyle (document.getElementById(UID['tabAttackTarget_AttackNow_'+n]), targets[n].A);
		}
		function addBookmark (event){
			var n = parseInt(event.target.getAttribute('ref'));
			var desc = '';
			if (Data.options.attacks.choice == kCity || 
				Data.options.attacks.choice == kOutpost || 
				Data.options.attacks.choice == kWildernesses){
				desc = translate(Map.names.type[targets[n].t]) + ' ' + targets[n].n + '  ('+  nombreFormate(targets[n].m) + ')' + (targets[n].a != undefined ? ' / '+targets[n].a : '');
			} else {
				desc = translate(Data.options.attacks.choice) + ' ' + translate('Level') + ' ' + targets[n].l;
			}
			saveBookmark (t.container, targets[n].x, targets[n].y, desc, targets[n].l, 
						  Data.options.attacks.units[targets[n].l], targets[n].ai,
						  Data.options.attacks.include_great_dragon[targets[n].l], false,
						  Data.options.attacks.except_great_dragon[targets[n].l]);
		}

		function tick (){
			var now = serverTime();
			var ts;
			clearTimeout (timer);
			if (!document.getElementById(UID['tabAttackTarget_Tab']))
			return;
			for (var i=0; i < targets.length; i++){
				var list = document.getElementById(UID['tabAttackTarget_List_'+i]);
				if (list == undefined){
					continue;
				}

				if (!targets[i].la || targets[i].la == undefined || targets[i].la == null){
					ts = '---';
				} else {
					var time = now-targets[i].la;
					if (time > 3600){
						ts = '<font color=#550000><b>'+ timestr (time, false) +'</b></font>';
					} else {
						ts = timestr (time, false);
					}
				}
				list.innerHTML = ts;
			}
			timer = setTimeout (tick, 5000);
		}
	},

	//*** Attacks Tab - Stats Sub-tab ***
	//----------------------------------------------------------------------------
	tabAttackStats : function (){
		var t = Tabs.Attacks;
		document.getElementById(UID[t.lastSubTab]).className='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabAttackStats']).className='selected';
		document.getElementById(UID['tabAttackStats']).style.zIndex=1;
		t.lastSubTab = 'tabAttackStats';

		t.contentType = 3;

		var m = '<div class=' + UID['title'] + '>'+translate('Attacks Stats')+'</div>'
		+'<div id='+ setUID('tabAttackStats_Statbox') +' class=' + UID['status_ticker'] + '>'
		+'<div id='+ setUID('tabAttackStats_Status') +'></div>'
		+'<div id='+ setUID('tabAttackStats_Percent') +'></div>'
		+'<br/>'
		+'<center><input id='+ setUID('tabAttackStats_Clear') +' type=button value="'+ translate('Clear Stats') +'" /></center>'
		+'<br></div>';

		document.getElementById(UID['tabAttack_Content']).innerHTML = m;
		document.getElementById(UID['tabAttackStats_Clear']).addEventListener('click', function(){
			t.clearStats();
			t.showStats();
		}, false);
		t.showStats();
	},

	clearStats : function (){
		var t = Tabs.Attacks;
		var now = serverTime();
		Data.stats.attacks = {start_at:now, run_time:0, total_attacks:0, items:{}, resources:{}, by_level:[]};
		t.curRunStart = now;
		for (var i=0; i < 12; i++){
			Data.stats.attacks.by_level[i] = {total_attacks:0, items:{}, resources:{}};
		}
		t.showStats(); 
	},

	trackStats : function (marchId, rpt_st){   // called when battle report received
		var t = Tabs.Attacks;
		if (DEBUG_MARCHES){
			WinLog.write ('Tabs.Attacks.trackStats: '+ marchId);
		}
		var objLevel = rpt_st.report.location.level;

		if (objLevel < 1 || objLevel > 12){
			objLevel = 0;
		}

		++Data.stats.attacks.total_attacks;
		++Data.stats.attacks.by_level[objLevel].total_attacks;
		var res =  rpt_st.report.spoils.resources;
		for (var p in res){
			objAddTo (Data.stats.attacks.resources, p, parseInt(res[p]));
			objAddTo (Data.stats.attacks.by_level[objLevel].resources, p, parseInt(res[p]));
		}  
		var killRes =  rpt_st.report.spoils.kill_items;
		for (var p in killRes){
			objAddTo (Data.stats.attacks.resources, p, parseInt(killRes[p]));
			objAddTo (Data.stats.attacks.by_level[objLevel].resources, p, parseInt(killRes[p]));
		}  
		var items =  rpt_st.report.spoils.items;
		for (var i=0; i < items.length; i++){
			objAddTo (Data.stats.attacks.items, items[i], 1);
			objAddTo (Data.stats.attacks.by_level[objLevel].items, items[i], 1);
		}  
		Data.marches.attacks[marchId].has_report = true;
		t.showStats();    
	},

	showStats : function (){
		var div = document.getElementById(UID['tabAttackStats_Status']);
		var t = Tabs.Attacks;

		if (div==null){
			return;
		}

		var run_time = Data.stats.attacks.run_time;
		if (Data.options.attacks.enabled){
			run_time += (serverTime()-t.curRunStart);
		}
		var trueRunTime = (run_time > 0) ? (run_time/3600) : 1;
		var m = '<table class=' + UID['table'] + '>'
		+'	<tr>'
		+'		<td class=right>'+ translate('Start Date') +': </td>'
		+'		<td>'+  new Date(Data.stats.attacks.start_at * 1000).myString() +'</td>'
		+'	</tr><tr>'
		+'		<td class=right>'+ translate('Run Time') +': </td>'
		+'		<td>'+ timestr(run_time, true) +'</td>'
		+'	</tr><tr>'
		+'		<td class=right>'+ translate('Attacks') +': </td>'
		+'		<td>'+ Data.stats.attacks.total_attacks +'</td>'
		+'	</tr><tr valign=top>'
		+'		<td class=right>'+ translate('Resources') +': </td>'
		+'		<td>'
		+'			<table class=' + UID['table'] + '>';

		for (var name in Data.stats.attacks.resources) {
			var perHour = Math.round(Data.stats.attacks.resources[name] / trueRunTime);
			m += '	<tr align=right>'
			+'			<td>'+ translate(name) +':</td>'
			+'			<td>'+ nombreFormate(Data.stats.attacks.resources[name],' ') +'</td>'
			+'			<td>('+ nombreFormate(perHour,' ') +' /'+ translate('h')+ ')</td>'
			+'		</tr>';
		}
		m += '		</table>'
		+'		</td>'
		+'</tr></table>'
		+'<br><div class=' + UID['subtitle'] + '>'+ translate('Statistics') +'&nbsp;'+ translate('of') +'&nbsp;'+ translate('Attack') +' '+ translate('and') +' '+ translate('Items') +'</div>'
		+'<div style="overflow:auto">'
		+'	<table class=' + UID['table'] + '>'
		+'		<tr class=' + UID['row_top_headers'] + ' align=center>'
		+'			<td style="background:none !important;"></td>'
		+'			<td align=right colspan=11>'+ translate('Levels') +'</td>'
		+'		</tr><tr align=right class=' + UID['row_headers'] + '>'
		+'			<td style="background:none !important;"></td>';

		for (i=1; i < 12; i++) {
			m += '	<td width=45>'+ i +'</td>';
		}
		m += '	</tr><tr>'
		+'			<td colspan=12><HR class=thin></td>'
		+'		</tr><tr align=right>'
		+'			<td class=right># '+translate('Attacks')+':</td>';

		for (i=1; i < 12; i++){
			m += '	<td>'+ Data.stats.attacks.by_level[i].total_attacks +'</td>';
		}
		m += '	</tr><tr>'
		+'			<td colspan=12><HR class=thin></td>'
		+'		</tr>'; 

		var items =  flipStats ('items');     
		for (var p in items){
			m += '<tr align=right>'
			+'		<td class=right>'+ translate(Names.getItemAbbr(p)) +':</td>';
			for (i=1; i < 12; i++) {
				m += '<td>'+ items[p][i] +'</td>';
			}
			m += '</tr><tr align=right>'
			+'		<td class=right>&nbsp</td>';
			for (i=1; i < 12; i++) {
				m += '<td>'+ ((Data.stats.attacks.by_level[i].total_attacks == 0 || items[p][i] == 0) ? '' : '('+ Math.round ((items[p][i] / Data.stats.attacks.by_level[i].total_attacks) * 100)+'%)') +'</td>';
			}
			m += '</tr><tr>'
			+'		<td colspan=12><HR class=thin></td>'
			+'	</tr>'; 
		}
		m += '</table></div>';
		div.innerHTML = m;

		function flipStats (name){
			var o = {};
			for (var i=1; i < 12; i++){
				for (var p in Data.stats.attacks.by_level[i][name]){
					if (!o[p]) {
						o[p] = [];
						for (var x=1; x < 12; x++){
							o[p][x] = 0;
						}
					}
					o[p][i] += Data.stats.attacks.by_level[i][name][p];
				}
			}
			return o;
		}
	},

	//*** Attacks Tab - Maps Sub-tab ***
	//----------------------------------------------------------------------------
	tabAttackMaps : function(){
		var t = Tabs.Attacks;
		document.getElementById(UID[t.lastSubTab]).className='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabAttackMaps']).className='selected';
		document.getElementById(UID['tabAttackMaps']).style.zIndex=1;
		t.lastSubTab = 'tabAttackMaps';

		t.contentType = 4;

		var m = '<div class=' + UID['subtitle'] + '>'+ translate('Search') + ' ' + translate('Location') +'</div>'
			+'<div id=' + setUID('tabAttackMaps_Statbox') + ' class=' + UID['status_ticker'] + ' style="overflow:auto; margin-top:1px !important">'
			+ '<b>' + translate('Search Radius') + ':</b> '
			+'	<select id='+setUID('tabAttackMaps_Radius')+'>';

			for (var i=7; i <= 35; i+=7){
				m +='		<option value="'+ i +'" '+ (Data.options.map.radius == i ? 'selected' : '') +'>'+i+'</option>';
			}
			m += '	<select> '
			+ translate('miles') + '.&nbsp;&nbsp;'
			+'<input id='+ setUID('tabAttackMaps_Search') +' type=button value="'+ translate('Detailed search') +'" />'
			+'<br><b>' + translate('Search Radius') + ':</b> '
			+'	<select id='+setUID('tabAttackMaps_RadiusFast')+'>';

			for (var i=7; i <= 70; i+=7){
				m +='		<option value="'+ i +'" '+ (Data.options.map.radius_fast == i ? 'selected' : '') +'>'+i+'</option>';
			}
			m += '	<select> '
			+ translate('miles') + '.&nbsp;&nbsp;'
			+'<input id='+ setUID('tabAttackMaps_FastSearch') +' type=button value="'+ translate('Fast search') +'" />'
			+'<br><br><br>'
			+'	<table class=' + UID['table'] + '>'
			+'		<tr align=center class=' + UID['row_headers'] + '>'
			+'			<td>'+translate('type')+'</td>'
			+'			<td>'+translate('total')+'</td>'
			+'		</tr>';

		for (var map_type in Map.targets){
			m += '<tr>'
			+ '	<td>'+ translate(map_type) +'</td>'
			+ '	<td align=right><span class=jewel>'+ Map.targets[map_type].length +'</span></td>'
			+ '</tr>'
		}
		m += '</table></div>';

		document.getElementById(UID['tabAttack_Content']).innerHTML = m;
		document.getElementById(UID['tabAttackMaps_Search']).addEventListener ('click', function (){butSearchNow (true);}, false);
		document.getElementById(UID['tabAttackMaps_FastSearch']).addEventListener ('click', function (){butSearchNow (false);}, false);
		document.getElementById(UID['tabAttackMaps_Radius']).addEventListener ('change', function(ev){
			var el = ev.target;
			Data.options.map.radius = parseInt(el.options[el.selectedIndex].value);
		}, false);
		document.getElementById(UID['tabAttackMaps_RadiusFast']).addEventListener ('change', function(ev){
			var el = ev.target;
			Data.options.map.radius_fast = parseInt(el.options[el.selectedIndex].value);
		}, false);

		// search the map for the selected type
		function butSearchNow (get_detail){
			actionLog('<B>scanMap</B>: begin');
			var t = Tabs.Attacks;

			for (var pid in Data.map.players) {
				if ( Data.map.players[pid] && Data.map.players[pid][2] ) {
					if (!Data.map.evolution[pid]) {
						Data.map.evolution[pid] = {};
					}
					Data.map.evolution[pid].m = Data.map.players[pid][2];
				}
			}

			var ix=0; iy=0;
			var x = Data.options.map.x;
			var y = Data.options.map.y;
			var radius = Data.options.map.radius;
			if (!get_detail)
				radius = Data.options.map.radius_fast;

			progressBar.init (800+Math.randRange(1,50), 100, 300, 150, translate('Message'), 200, true, t.container);
			progressBar.start({ steps:100, delay:1, byCount:true, title:translate('Scanning map')+'...', stepText:translate('Please wait...') });

			Map.scanMap ({x:x, y:y, radius:radius, city_detail:get_detail, force_request:get_detail}, function(res){
				if (res == null){
					progressBarPop.getContentDiv().innerHTML = '<B>' + translate('Bummer, there was an error while scanning the map') + '.</B>';
					progressBarPop.allowClose (true);
					Tabs.Attacks.checkMapBusy = false;
					return;
				}
				if(res.done){
					actionLog('<B>scanMap</B>: '+ translate('complete'));
					Tabs.Attacks.checkMapBusy = false;
					progressBarPop.destroy();
				}
			});
		}
	}
};
//*********************************** Attacks Tab *********************************************


//*********************************** Bookmarks Tab *********************************************
Tabs.Bookmarks = {
	tabOrder	: BOOKMARK_TAB_ORDER,
	tabLabel	: 'Bookmarks',
	tabDisabled	: !BOOKMARK_TAB_ENABLE,
	container	: null,
	enabled		: false,
	attackTimer	: null,
	marchTimer	: null,
	lastAttack	: 0,
	attackErrors: 0,
	contentType	: 0, // 0 = edit, 1 = targets list, 2 = stats, 3 = config
	lastSubTab	: 'tabBookmarksTargets',
	running		: { start_at:0 },
	last_target_idx		: -1,
	current_target_idx	: -1,

	init : function (div) {
		var t = Tabs.Bookmarks;
		Data.setDefaultValues ('bookmark');

		t.container = div;
		var m = ''
		+'<div class=' + UID['title'] + '>'+ translate('Bookmarks') +'</div>'
		+'<div id=' + setUID('tabBookmarks_Status') + ' class=' + UID['status_ticker'] + ' style="margin-bottom:5px !important">'
		+'	<center><input id=' + setUID('tabBookmarks_OnOff') + ' type=button value="OnOff" /></center>'
		+'	<div id=' + setUID('tabBookmarks_Report') + ' style="margin-top:5px;height:140px; max-height:140px; width:540px; max-width:540px; overflow:auto;">'
		+'		<table id=' + setUID('tabBookmarks_Marches') + ' class=' + UID['table'] + '>'
		+'		</table>'
		+'	</div>'
		+'	<div id=' + setUID('tabBookmarks_Feedback') + ' class='+ UID['status_feedback'] +'></div>'
		+'</div>'
		+'<ul class=tabs>'
		+'	<li class="tab first"><a id='+ setUID('tabBookmarksEdit') +'>'+ translate('Edit') +'</a></li>'
		+'	<li class=tab><a id='+ setUID('tabBookmarksTargets') +'>'+ translate('Targets') +'</a></li>'
		+'	<li class=tab><a id='+ setUID('tabBookmarksStats') +'>'+ translate('Stats') +'</a></li>'
		+'	<li class=tab><a id='+ setUID('tabBookmarksConfig') +'>'+ translate('Config') +'</a></li>'
		+'</ul>'
		+'<div id='+ setUID('tabBookmarks_Content') +' style="padding-top:0px; height:430px; overflow-y:auto"></div>';
		t.container.innerHTML = m;

		document.getElementById(UID['tabBookmarksEdit']).addEventListener ('click', t.tabBookmarksEdit, false);
		document.getElementById(UID['tabBookmarksTargets']).addEventListener ('click', t.tabBookmarksTargets, false);
		document.getElementById(UID['tabBookmarksStats']).addEventListener ('click', t.tabBookmarksStats, false);
		document.getElementById(UID['tabBookmarksConfig']).addEventListener ('click', t.tabBookmarksConfig, false);
		document.getElementById(UID['tabBookmarks_OnOff']).addEventListener ('click', function(){
			t.setBookmarksEnable(!Data.options.bookmarks.enabled);
		}, false);
		window.addEventListener('unload', t.onUnload, false);
		if (Data.stats.bookmarks == null){
			t.clearStats();
		}
		Messages.addBattleReportListener(t.gotBattleReport);
		t.show();
		t.setBookmarksEnable (false);
		t.contentType = isEmpty(Data.options.bookmarks.current_tab,0);
		t.show();
	},

	tabBookmarksEdit : function (){
		var t = Tabs.Bookmarks;
		document.getElementById(UID[t.lastSubTab]).className='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabBookmarksEdit']).className='selected';
		document.getElementById(UID['tabBookmarksEdit']).style.zIndex=1;
		t.lastSubTab = 'tabBookmarksEdit';

		t.contentType = 0;

		var m = '<div class="' + UID['title'] + '">'+ translate('Edit bookmark') + '</div>'
		+'<div class=' + UID['content'] + '>'
		+'	<div>'
		+'		<b>'+ translate('Coords') +':&nbsp;</b>&nbsp;'
		+'		X: <input id=' + setUID('tabBookmarks_CoordsX') + ' size=1 maxlength=3 type=text value="'+ Data.options.bookmarks.new_bookmark.x +'" /> '
		+'		Y: <input id=' + setUID('tabBookmarks_CoordsY') + ' size=2 maxlength=3 type=text value="'+ Data.options.bookmarks.new_bookmark.y +'" /> '
		+'		&nbsp <b>'+ translate('Distance') +':</b> <span id=' + setUID('tabBookmarks_Distance') + '></span>'
		+'		&nbsp <input id='+ setUID('tabBookmarks_Save') +' class="' + UID['bnt_green'] + ' small" style="width:auto !important;" type=submit value=" ' + translate('Save Attaque') + ' " /><BR>'
		+'		<div class=' + UID['status_ticker'] + ' style="height:auto !important;margin:5px 10px !important;">'
		+'			<center><span id=' + setUID('tabBookmarks_Tile') + '></span></center>'
		+'		</div>'
		+'	</div>'
		+'  <div>'
		+'	<table id=' + setUID('tabBookmarks_Troops') + ' class=' + UID['table'] + '>'
		+'		<tr align=center class=' + UID['row_headers'] + '>'
		+'			<td colspan=8>'+ translate('Troops for Bookmarks Attack') +':&nbsp;</td>'
		+'		</tr>'
		+'	</table>'
		+'	</div><br>'
		+'  <div>'
		+'	<table id=' + setUID('tabBookmarks_Dragons') + ' class=' + UID['table'] + ' width=100%>'
		+'		<tr align=center class=' + UID['row_headers'] + '>'
		+'			<td colspan=10>'+ translate('Include Great Dragon') +':&nbsp;</td>';
		var currentDragons = [];
		for (var j=0; j < Seed.dragonList.length; j++) {
			var dragon = Seed.dragonList[j];
			if (j==0 || j == 5)
				m += '</tr><tr>';
			m += '	<td class=right><span title="'+translate(dragon.type)+'">'+ translate(Names.getTroopAbbr(dragon.type)) +':<span></td>'
				+'	<td align=center><input type=checkbox id='+ setUID('tabBookmarks_Dragons_'+ j) +' ref='+ j +' ' + (Data.options.bookmarks.new_bookmark.dragons[dragon.type]?' checked':'') +' /></td>';
			currentDragons.push(j);
		}
		m += '</tr>'
		+'	</table>'
		+'	</div>'
		+'</div>'
		document.getElementById(UID['tabBookmarks_Content']).innerHTML = m;
		document.getElementById(UID['tabBookmarks_CoordsX']).addEventListener ('change', eventCoords, false);
		document.getElementById(UID['tabBookmarks_CoordsY']).addEventListener ('change', eventCoords, false);
		document.getElementById(UID['tabBookmarks_Save']).addEventListener ('click', saveCoords, false);
		troopTable (document.getElementById(UID['tabBookmarks_Troops']), 1, 'BW', eventTroops);
		for (var j=0; j < currentDragons.length; ++j){
			document.getElementById(UID['tabBookmarks_Dragons_'+ currentDragons[j]]).addEventListener('change', function(event){
				var args = event.target.getAttribute('ref');
				Data.options.bookmarks.new_bookmark.dragons[Seed.dragonList[args[0]].type] = event.target.checked;
				var include_great_dragon = false;
				for (var x=0; x < Seed.dragonList.length && !include_great_dragon; x++) {
					var dragon = Seed.dragonList[x];
					if (Data.options.bookmarks.new_bookmark.dragons[dragon.type]) include_great_dragon = true;
				}
				if (include_great_dragon) Data.options.bookmarks.new_bookmark.include_great_dragon = true;
				else Data.options.bookmarks.new_bookmark.include_great_dragon = false;
			}, false);
		}
		eventCoords();

		function eventCoords (event){
			var ex = document.getElementById(UID['tabBookmarks_CoordsX']);
			var ey = document.getElementById(UID['tabBookmarks_CoordsY']);
			var x = parseIntZero (ex.value);
			var y = parseIntZero (ey.value);
			ex.value = x;
			ey.value = y;
			document.getElementById(UID['tabBookmarks_Distance']).innerHTML = getDistance(Seed.cities[CAPITAL_ID].x, Seed.cities[CAPITAL_ID].y, x, y);
			document.getElementById(UID['tabBookmarks_Tile']).innerHTML = '&nbsp;';
			if (x < 0 || x > 749){
				if(x < 0){
					while (x < 0){
						x = 750 + x;
					}
				} else {
					while (x > 749){
						x = x - 750;
					}
				}
				ex.style.backgroundColor = 'red';
				return;
			}
			if (y < 0 || y > 749){
				if(y < 0){
					while (y < 0){
						y = 750 + y;
					}
				} else {
					while (y > 749){
						y = y - 750;
					}
				}
				ey.style.backgroundColor = 'red';
				return;
			}
			Data.options.bookmarks.new_bookmark.x = x;
			Data.options.bookmarks.new_bookmark.y = y;
			ey.style.backgroundColor = '';
			ex.style.backgroundColor = '';

			Map.tileAt({x:x, y:y, force_request:true}, function(target){
				if (target && target.ok){
					var cfeedBack = '';
					Data.options.bookmarks.new_bookmark.level = target.l;
					Data.options.bookmarks.new_bookmark.ai = target.ai;
					var attColor = target.A ? '#000' : '#C22';

					var type_name = Map.names.type[target.t] || target.t;
					var type = 'C';
					if (target.t != 7 && target.t < 10) type = 'W'; // 7 = city, from 10 = outposts

					var tile = '<font color='+attColor+'>'
						+'<b>'+ translate(type_name) +'&nbsp;'+ translate('Level') +'&nbsp;'+ target.l +'</b>'
						+'</font>';
					if(target.cn != undefined && type != 'W'){
						tile += '<br>'+ translate('City') + ': <b>' + target.cn +'</b> - '
							+ translate('Alliance')+': <b>'+(target.a != undefined ? target.a : '----') + '</b>'
							+ '<br>'+ translate('Name') +': <b>'+ target.n + '</b> - '
							+ translate('Level') + ': <b>' + target.l + '</b> - '
							+ translate('Might') + ': <b>' + target.m + '</b>';
						cFeedBack = translate(type_name) + ' ' + target.n + ' (' + nombreFormate(target.m) + ')' + (target.a != undefined ? ' / '+target.a : '');
					} else {
						cFeedBack = translate(type_name) + ' ' + translate('Level') + ' ' + target.l;
					}
					Data.options.bookmarks.new_bookmark.type = cFeedBack;
					document.getElementById(UID['tabBookmarks_Tile']).innerHTML = tile;
				}
			});
		}
		function eventTroops (event){
			var t = Tabs.Bookmarks;
			var args = event.target.name.split ('_');
			if (args[0] == 'BW'){
				var tt = wave_unit_types[args[1]];
				var tr = Data.options.bookmarks.new_bookmark.units;
				tr[tt] = event.target.value;
			}
		}
		function troopTable (tab, rownum, prefix, listener) {
			var t = Tabs.Bookmarks;
			var row =[];
			row.push(tab.insertRow(rownum));
			row.push(tab.insertRow(rownum+1));
			row.push(tab.insertRow(rownum+2));
			row.push(tab.insertRow(rownum+3));
			var val, r=0, c=0;
			for (var i=0; i < wave_unit_types.length; ++i) {
				if (i == 10) {
					r = r + 2;
					c = 0;
				}
				row[r].insertCell(c).innerHTML = translate(Names.getTroopAbbr(wave_unit_types[i]));
				var inp = document.createElement ('input');
				inp.type = 'text';
				inp.size = '1';
				inp.style.width = '30px';
				inp.title = translate(wave_unit_types[i]);
				if (i < 3) {
					inp.style.border = '1px solid grey';
				} else if (i < 6) {
					inp.style.border = '1px solid green';
				} else if (i < 12) {
					inp.style.border = '1px solid blue';
				} else {
					inp.style.border = '1px solid red';
				}
				inp.maxlength = '6';
				if (prefix=='BW'){
					if (Data.options.bookmarks.new_bookmark.units[wave_unit_types[i]] == undefined){
						Data.options.bookmarks.new_bookmark.units[wave_unit_types[i]] = 0;
					}
					val = Data.options.bookmarks.new_bookmark.units[wave_unit_types[i]];
				}
				if (!val){
					val = 0;
				}
				inp.value = val;
				inp.name = prefix +'_'+ i;
				inp.addEventListener ('change', listener, false);
				row[r+1].insertCell(c).appendChild (inp);
				c = c + 1;
			}
			return tab;
		}
		function saveCoords (){
			var t = Tabs.Bookmarks;
			saveBookmark (t.container, Data.options.bookmarks.new_bookmark.x, 
						  Data.options.bookmarks.new_bookmark.y,
						  Data.options.bookmarks.new_bookmark.type,
						  Data.options.bookmarks.new_bookmark.level,
						  Data.options.bookmarks.new_bookmark.units,
						  Data.options.bookmarks.new_bookmark.ai,
						  Data.options.bookmarks.new_bookmark.include_great_dragon, true,
						  Data.options.bookmarks.new_bookmark.dragons);
			t.tabBookmarksTargets();
		}
	},

	tabBookmarksTargets : function (){
		var t = Tabs.Bookmarks;
		document.getElementById(UID[t.lastSubTab]).className='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabBookmarksTargets']).className='selected';
		document.getElementById(UID['tabBookmarksTargets']).style.zIndex=1;
		t.lastSubTab = 'tabBookmarksTargets';

		t.contentType = 1;
		var timer = null;

		var m = '<div class="' + UID['title'] + '">'+ translate('Targets') + '</div>'
			+'	<div id=' + setUID('tabBookmarksTargets_TargetsList') + ' class=' + UID['status_ticker'] + ' style="height:380px; max-height:380px; width:540px; max-width:540px; overflow:auto ; margin-top:1px !important"></div>'
			+'	</div>';
		document.getElementById(UID['tabBookmarks_Content']).innerHTML = m;

		setUID('tabBookmarks_TypeChoice');
		setUID('tabBookmarks_SortChoice');
		var m = '<table><tr>'
		  + '<td align=right>&nbsp;<b>' + translate('Select')+ ' ' +translate('Targets')+'</b></td>'
		  + '<td>:&nbsp;<select id='+ UID['tabBookmarks_TypeChoice'] +'>'
		  + '	<option value="3" '+ (Data.options.bookmarks.choice==3 ? 'selected' : '') +'>' + translate('All') + '</option>'
		  + '	<option value="1" '+ (Data.options.bookmarks.choice==1 ? 'selected' : '') +'>' + translate(kAnthropusCamp) + '</option>'
		  + '	<option value="0" '+ (Data.options.bookmarks.choice==0 ? 'selected' : '') +'>' + translate('City') +' / '+ translate('Outpost') + '</option>'
		  + '	<option value="2" '+ (Data.options.bookmarks.choice==2 ? 'selected' : '') +'>' + translate('Wildernesses') + '</option>'
		  + '</select>&nbsp;'
		  + '</td>'
		  + '<td align=right>&nbsp;<b>' + translate('Attack')+ '</b></td>'
		  + '<td>:&nbsp;<select id='+ UID['tabBookmarks_SortChoice'] +'>'
		  + '	<option value="0" '+ (Data.options.bookmarks.sort==0 ? 'selected' : '') +'>' + translate('By distance ascending') + '</option>'
		  + '	<option value="1" '+ (Data.options.bookmarks.sort==1 ? 'selected' : '') +'>' + translate('By distance descending') + '</option>'
		  + '	<option value="2" '+ (Data.options.bookmarks.sort==2 ? 'selected' : '') +'>' + translate('Back at the same time') + '</option>'
		  + '</select>&nbsp;'
		  + '</td>'
		  + '</tr></table><br>';

		var el = [];
		m += '<table id='+ setUID('tabBookmarksTargets_Tab') +' class=' + UID['row_style'] + ' width=100% style="white-space:nowrap">'
			+'	<tr class=' + UID['row_headers'] +'>'
			+'		<td width=9%>' + translate('Enable') + '</td>'
			+'		<td width=7%>' + translate('Dist') + '</td>'
			+'		<td width=7%>' + translate('Coords') + '</td>'
			+'		<td width=25% style="white-space:wrap">' + translate('Target') + '</td>'
			+'		<td width=25% style="white-space:wrap">' + translate('Troops') + '</td>'
			+'		<td width=7%>' + translate('GD') + '</td>'
			+'		<td width=20%>' + translate('Last attack') + '</td>'
			+'	</tr>';
		for (var i=0; i<Data.options.bookmarks.targets.length; i++){
			if (Data.options.bookmarks.choice == 3 || Data.options.bookmarks.choice == Data.options.bookmarks.targets[i].t) {
				var include_great_dragon = false;
				for (var j=0; j < Seed.dragonList.length && !include_great_dragon; j++) {
					var dragon = Seed.dragonList[j];
					if (Data.options.bookmarks.targets[i].dragons[dragon.type]) include_great_dragon = true;
				}
				m += '<tr valign=top style="border-bottom: 1px solid #898989;">'
				+'	<td><input type=checkbox id='+ setUID('tabBookmarksTargets_CB_'+i) +' ref='+ i +' '+ (Data.options.bookmarks.targets[i].enabled?'checked':'') +' /></td>'
				+'	<td>' + Data.options.bookmarks.targets[i].d + '</td>'
				+'	<td align=center>' + Data.options.bookmarks.targets[i].x +','+ Data.options.bookmarks.targets[i].y + '<br>(' + timestrShort(Data.options.bookmarks.targets[i].ti) + ')</td>'
				+'	<td align=left>' + Data.options.bookmarks.targets[i].type + '</td>'
				+'	<td align=left>' + getTroops(Data.options.bookmarks.targets[i].units) +'</td>'
				+'	<td align=center>' + ((include_great_dragon) ? 'Y' : '') + '</td>'
				+'	<td align=left><span id='+ setUID('tabBookmarksTargets_Last_'+i) +'> --- </span><br>'
				+'	<input id='+ setUID('tabBookmarksTargets_Edit_'+i) +' ref='+ i +' class="Xtrasmall '+UID['bnt_green']+'" style="width:auto !important;" type=submit value="' + translate('Edit') + '" />&nbsp &nbsp'
				+'	<input id='+ setUID('tabBookmarksTargets_Delete_'+i) +' ref='+ i +' class="Xtrasmall '+UID['bnt_red']+'" style="width:auto !important;" type=submit value=" X " /></td>'
				+'</tr>';
				el.push(UID['tabBookmarksTargets_CB_'+i]);
			}
		}
		document.getElementById(UID['tabBookmarksTargets_TargetsList']).innerHTML = m + '</table>';
		document.getElementById(UID['tabBookmarks_TypeChoice']).addEventListener('change', onTypeChoice, false);
		document.getElementById(UID['tabBookmarks_SortChoice']).addEventListener('change', onSortChoice, false);
		for (var i=0; i<el.length; i++){
			document.getElementById(el[i]).addEventListener('click', onCheckEnabled, false);
			var butRecall = document.getElementById(UID['tabBookmarksTargets_Edit_'+ i]);
			var butDelete = document.getElementById(UID['tabBookmarksTargets_Delete_'+ i]);
			butRecall.addEventListener ('click', editTarget, false);
			butDelete.addEventListener ('click', deleteTarget, false);
		}

		tick();

		function editTarget (event){
			var n = parseInt(event.target.getAttribute('ref'));
			Data.options.bookmarks.new_bookmark.x		= Data.options.bookmarks.targets[n].x;
			Data.options.bookmarks.new_bookmark.y		= Data.options.bookmarks.targets[n].y;
			Data.options.bookmarks.new_bookmark.type	= Data.options.bookmarks.targets[n].type;
			Data.options.bookmarks.new_bookmark.level	= Data.options.bookmarks.targets[n].level;
			Data.options.bookmarks.new_bookmark.ai		= Data.options.bookmarks.targets[n].ai;
			Data.options.bookmarks.new_bookmark.units	= cloneProps(Data.options.bookmarks.targets[n].units);
			Data.options.bookmarks.new_bookmark.dragons	= cloneProps(Data.options.bookmarks.targets[n].dragons);
			Data.options.bookmarks.new_bookmark.include_great_dragon = Data.options.bookmarks.targets[n].inc;
			t.tabBookmarksEdit();
		}
		function deleteTarget (event){
			var n = parseInt(event.target.getAttribute('ref'));
			Data.options.bookmarks.targets.splice(n,1);
			t.tabBookmarksTargets();
		}
		function getTroops (trps) {
			var result = '';
			var tRes = [];
			for (var i in trps) {
				if (trps[i] > 0)
					tRes.push (nombreFormate(trps[i],' ') + ' ' + translate (i)); 
			}
			if (tRes.length>0) result = tRes.join(',<br>');
			return result;
		}
		function onCheckEnabled (event){
			var ref = event.target.getAttribute('ref');
			Data.options.bookmarks.targets[ref].enabled = event.target.checked;
		}
		function onSortChoice (event){
			var t = Tabs.Bookmarks;
			t.last_target_idx = -1;
			if (Data.options.bookmarks.enabled) {
				// It would be very bad to leave attack on when switching targets. Imagine sending the troops for a wilderness to a city or an ant camp...
				clearTimeout (t.attackTimer);
				t.setBookmarksEnable(false);
				t.dispFeedback (translate('Safe Mode') +': '+ translate('Attacks') +' '+ translate('Turned Off'));
			}
			// Update distance and march duration for all saved bookmarks (case when own city has moved)
			for (var i=0; i<Data.options.bookmarks.targets.length; i++){
				Data.options.bookmarks.targets[i].d  = getDistance(Seed.cities[CAPITAL_ID].x, Seed.cities[CAPITAL_ID].y, Data.options.bookmarks.targets[i].x, Data.options.bookmarks.targets[i].y);
				Data.options.bookmarks.targets[i].ti = getMarchTime (Data.options.bookmarks.targets[i].x, Data.options.bookmarks.targets[i].y, Data.options.bookmarks.targets[i].units);
			}
			var el = event.target;
			Data.options.bookmarks.sort = parseInt(el.options[el.selectedIndex].value);
			switch (Data.options.bookmarks.sort) {
				case 1  : Data.options.bookmarks.targets.sort(function(a,b){return b.d-a.d}); break;
				case 2  : Data.options.bookmarks.targets.sort(function(a,b){return b.ti-a.ti}); break;
				default : Data.options.bookmarks.targets.sort(function(a,b){return a.d-b.d}); break;
			}
			t.tabBookmarksTargets();
		}
		function onTypeChoice (event){
			var t = Tabs.Bookmarks;
			t.last_target_idx = -1;
			if (Data.options.bookmarks.enabled) {
				// It would be very bad to leave attack on when switching targets. Imagine sending the troops for a wilderness to a city or an ant camp...
				clearTimeout (t.attackTimer);
				t.setBookmarksEnable(false);
				t.dispFeedback (translate('Safe Mode') +': '+ translate('Attacks') +' '+ translate('Turned Off'));
			}
			var el = event.target;
			Data.options.bookmarks.choice = parseInt(el.options[el.selectedIndex].value);
			t.tabBookmarksTargets();
		}
		function tick (){
			var now = serverTime();
			var ts;
			clearTimeout (timer);
			if (!document.getElementById(UID['tabBookmarksTargets_Tab']))
			return;
			for (var i=0; i < Data.options.bookmarks.targets.length; i++){
				var last = document.getElementById(UID['tabBookmarksTargets_Last_'+i]);
				if (last == undefined){
					continue;
				}
				if (!Data.options.bookmarks.targets[i].last_attack || Data.options.bookmarks.targets[i].last_attack == undefined || Data.options.bookmarks.targets[i].last_attack == null){
					ts = '---';
				} else {
					var time = now-Data.options.bookmarks.targets[i].last_attack;
					if (time > 3600) ts = '<font color=#550000><b>'+ timestr (time, false) +'</b></font>';
					else ts = timestr (time, false);
				}
				last.innerHTML = ts;
			}
			timer = setTimeout (tick, 5000);
		}
	},

	tabBookmarksStats : function (){
		var t = Tabs.Bookmarks;
		document.getElementById(UID[t.lastSubTab]).className='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabBookmarksStats']).className='selected';
		document.getElementById(UID['tabBookmarksStats']).style.zIndex=1;
		t.lastSubTab = 'tabBookmarksStats';

		t.contentType = 2;

		var m = '<div class=' + UID['title'] + '>'+translate('Attacks Stats')+'</div>'
		+'<div id='+ setUID('tabBookmarksStats_Statbox') +' class=' + UID['status_ticker'] + '>'
		+'<div id='+ setUID('tabBookmarksStats_Status') +'></div>'
		+'<div id='+ setUID('tabBookmarksStats_Percent') +'></div>'
		+'<br/>'
		+'<center><input id='+ setUID('tabBookmarksStats_Clear') +' type=button value="'+ translate('Clear Stats') +'" /></center>'
		+'<br></div>';

		document.getElementById(UID['tabBookmarks_Content']).innerHTML = m;
		document.getElementById(UID['tabBookmarksStats_Clear']).addEventListener('click', function(){
			t.clearStats();
			t.showStats();
		}, false);
		t.showStats();
	},

	tabBookmarksConfig : function (){
		var t = Tabs.Bookmarks;
		document.getElementById(UID[t.lastSubTab]).className='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabBookmarksConfig']).className='selected';
		document.getElementById(UID['tabBookmarksConfig']).style.zIndex=1;
		t.lastSubTab = 'tabBookmarksConfig';

		t.contentType = 3;

		var m = '<div class=' + UID['title'] + '>'+ translate('Bookmarks Configuration') + '</div>'
		+'<div id='+ setUID('tabBookmarksConfig_Status') +' class=' + UID['status_ticker'] + ' style="overflow:auto">'
		+'	<table class=' + UID['table'] + ' width=100%>'
		+'	<tr>'
		+'		<td width=50% class=right>'+ translate('Delay Between Attacks') +':&nbsp;</td>'
		+'		<td width=50%>'
		+'		<input class=short id='+ setUID('tabBookmarksConfig_DelayMin') +' maxlength=4 type=text value="'+ Data.options.bookmarks.delay_min +'" />&nbsp;'+ translate('to')
		+'		<input class=short id='+ setUID('tabBookmarksConfig_DelayMax') +' maxlength=4 type=text value="'+ Data.options.bookmarks.delay_max +'" />&nbsp;'+ translate('seconds') 
		+'		</td>'
		+'	</tr><tr>'
		+'		<td class=right>'+ translate('Delete Battle Reports') +':&nbsp;</td>'
		+'		<td><input id='+ setUID('tabBookmarksConfig_DelAttacks') +' '+ (Data.options.bookmarks.delete_reports?'CHECKED ':'') +' type=checkbox /></td>'
		+'	</tr><tr>'
		+'		<td class=right>'+ translate('Stop if any troops lost') +':&nbsp;</td>'
		+'		<td><input id='+ setUID('tabBookmarksConfig_StopOnLoss') +' '+ (Data.options.bookmarks.stop_on_loss?'CHECKED ':'') +' type=checkbox /></td>'
		+'	</tr><tr>'
		+'		<td class=right>'+ translate('Maximum simultaneous marches') +':&nbsp;</td>'
		+'		<td><input id='+ setUID('tabBookmarksConfig_MaxMarches') +' class=short maxlength=2 type=text value="'+ Data.options.bookmarks.max_marches +'" /></td>'
		+'	</tr></table>';
		document.getElementById(UID['tabBookmarks_Content']).innerHTML = m;
		document.getElementById(UID['tabBookmarksConfig_DelAttacks']).addEventListener('change', function (event){
			Data.options.bookmarks.delete_reports = event.target.checked;
		}, false);
		document.getElementById(UID['tabBookmarksConfig_StopOnLoss']).addEventListener('change', function (event){
			Data.options.bookmarks.stop_on_loss = event.target.checked;
		}, false);
		document.getElementById(UID['tabBookmarksConfig_DelayMin']).addEventListener('change', delayChanged, false);
		document.getElementById(UID['tabBookmarksConfig_DelayMax']).addEventListener('change', delayChanged, false);
		document.getElementById(UID['tabBookmarksConfig_MaxMarches']).addEventListener('change', maxMarchesChanged, false);

		function delayChanged (event){
			var min = parseIntNan(document.getElementById(UID['tabBookmarksConfig_DelayMin']).value);
			var max = parseIntNan(document.getElementById(UID['tabBookmarksConfig_DelayMax']).value);
			if (min < MIN_DELAY || min > 3600 || (max-min) < 5){
				var dial = new ModalDialog (t.container, 300, 150, '', true);
				dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>KabaListics : ' + translate('Error') + '</b></center></div>';
				dial.getContentDiv().innerHTML = '<b>'+ translate('Invalid delays') +'</b><br><br>'
				+translate('First value must be between') + ' ' + MIN_DELAY +' '+ translate('and') + ' 3600. '
				+translate('Second value must be at least') + ' 5 ' + translate('above the first value');
				return;
			}
			Data.options.bookmarks.delay_min = min;
			Data.options.bookmarks.delay_max = max;
		}
		function maxMarchesChanged (event){
			var val = parseIntNan(document.getElementById(UID['tabBookmarksConfig_MaxMarches']).value);
			if (val < 0 || val > Seed.cities[CAPITAL_ID].figures.marches.maximum){
				event.target.style.backgroundColor = 'red';
				return;
			}
			event.target.style.backgroundColor = '';
			Data.options.bookmarks.max_marches = val;
		}
	},

	autoCheckTargets : function (){
		var t = Tabs.Bookmarks;
		var now = serverTime();
		var cityIdx = CAPITAL_ID;
		var targetMsg, retryDelay, availableGeneral, marchCount = 0, p;
		clearTimeout (t.attackTimer);

		// Don't do anything if bookmarks attacks are not enabled
		if (!Data.options.bookmarks.enabled){
			return;
		}

		var min_time = 700000;
		var max_time = 0;
		for (id in Seed.marches){
			++marchCount;
			var left_time = ( Seed.marches[id].run_at - parseInt(serverTime()) ) + (Seed.marches[id].status=='marching' ? Seed.marches[id].duration : 0);
			if (left_time > 0) {
				min_time = min_time < left_time ? min_time : left_time;
				max_time = max_time > left_time ? max_time : left_time;
			}
		}
		if ( min_time === 700000 || max_time === 0 ) {
			min_time = 3;
		}
		retryDelay = min_time + Math.randRange(2,5);

		var nextTarget = t.getNextTarget();
		if (nextTarget){
			var targetMsg =  nextTarget.type + ' ' + translate('at') + ' ' + nextTarget.x +'/'+ nextTarget.y;

			if (MyAjax.marchBusy > 0){
				MyAjax.marchBusy = marchCount;
				verboseLog('Attack to ' + targetMsg + ' ' + translate('delayed due to pending march request') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
				t.dispFeedback(translate('Another march request is pending') + ': ' +translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
				t.attackTimer = setTimeout(t.autoCheckTargets, retryDelay * 1000);
				return;
			}
			if (marchCount >= Data.options.bookmarks.max_marches){
				verboseLog('Attack to ' + targetMsg + ' ' + translate('delayed due to march limit reached') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
				t.dispFeedback(translate('March limit reached') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
				t.attackTimer = setTimeout(t.autoCheckTargets, retryDelay * 1000);
				return;
			}
			if (getMusterPointSlots (CAPITAL_ID) <= 0){
				verboseLog('Attack to ' + targetMsg + ' ' + translate('delayed due to muster point full') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
				t.dispFeedback (translate('Muster Point Full') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
				t.attackTimer = setTimeout(t.autoCheckTargets, retryDelay * 1000);
				return;
			}
			availableGeneral = getAvailableGeneral();
			if (availableGeneral === null) {
				verboseLog('Attack to ' + targetMsg + ' ' + translate('delayed due to no available generals') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
				t.dispFeedback(translate('No Generals Available') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
				t.attackTimer = setTimeout(t.autoCheckTargets, retryDelay * 1000);
				return;
			}
			var greatDrag = null;
			if (nextTarget.include_great_dragon) {
				if ((greatDrag = getAvailableDragon (true, nextTarget.dragons)) == null){
					verboseLog('Attack to ' + targetMsg + ' ' + translate('delayed due to no available Great Dragon') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
					t.dispFeedback(translate('No Great Dragon available') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
					t.attackTimer = setTimeout(t.autoCheckTargets, retryDelay * 1000);
					return;
				}
			}

			if (t.checkTroops (nextTarget) == null) {
				t.sendAttack (CAPITAL_ID, nextTarget, availableGeneral, greatDrag, function (rslt){
					var t = Tabs.Bookmarks, attackDelay, retryDelay;
					if (rslt){
						t.last_target_idx = t.current_target_idx;
						if (Data.options.bookmarks.sort == 2) {
							var futureTarget = t.getNextTarget();
							if (futureTarget) {
								attackDelay = futureTarget.st;
								if (attackDelay < 5) attackDelay = 5;
							} else {
								attackDelay = Math.floor(Math.random() * (Data.options.bookmarks.delay_max - Data.options.bookmarks.delay_min + 1) + Data.options.bookmarks.delay_min);
							}
						} else {
							attackDelay = Math.floor(Math.random() * (Data.options.bookmarks.delay_max - Data.options.bookmarks.delay_min + 1) + Data.options.bookmarks.delay_min);
						}
						t.attackTimer = setTimeout(t.autoCheckTargets, attackDelay * 1000);
					} else {
						retryDelay = 30 * (t.attackErrors * t.attackErrors);
						if ( rslt.status === 509 ) {
							retry_delay = 600;
							verboseLog('<b>Attack</b> to ' + targetMsg + ' ' + translate('failed') + ' - ' + translate('<b>Rate Limit Exceeded</b>, too many requests!') + ' - ' + translate('Retry in') + ' ' + retryDelay);
							t.dispFeedback(translate('Attack to') + ' ' + targetMsg + ' ' + translate('failed')+' - '+translate('Rate Limit Exceeded because there were too many requests') + ' - ' + translate('Retry in') +' '+ retryDelay);
						}
						t.attackTimer = setTimeout(t.autoCheckTargets, retryDelay * 1000);
					}
				});
				return;                
			} else {
				verboseLog('Attack to ' + targetMsg + ' ' + translate('delayed due to insufficient troops') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
				t.dispFeedback(translate('Not enough') + ' ' + translate('Troops') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
				t.attackTimer = setTimeout(t.autoCheckTargets, retryDelay * 1000);
			}
		} else {
			t.last_target_idx = -1;
			clearTimeout (t.attackTimer);
			t.setBookmarksEnable(false);
			t.dispFeedback (translate('Requirements Unmet') + ': ' + translate('Attacks') +' '+ translate('Turned Off'));
		}
	},
	checkTroops : function (target){
		var units = target.units;
		var total = 0;
		for (var p in units){
			if (units[p] > 0){
				total += units[p];
				if (Seed.cities[CAPITAL_ID].units[p] < units[p]){
					return (translate('Not enough') +' '+ translate(p));
				}
			}
		}
		if (total <= 0){
			return (translate('No Troops Defined'));
		}
		return null;
	},
	clearStats : function (){
		var t = Tabs.Bookmarks;
		var now = serverTime();
		Data.stats.bookmarks = {
			start_at		: now,
			run_time		: 0,
			total_attacks	: 0,
			items			: {},
			resources		: {}
		};
		t.showStats(); 
	},
	dispFeedback : function (msg){
		if (msg && msg!='')
			msg = new Date().toTimeString().substring (0,8) +' '+ msg;
		document.getElementById(UID['tabBookmarks_Feedback']).innerHTML = msg;
	},
	getNextTarget : function (){
		var t = Tabs.Bookmarks;
		var attacks = Data.options.bookmarks.targets;
		if (attacks.length == 0) return;
		var target_idx = parseInt(t.last_target_idx) + 1;
		if (target_idx > attacks.length) target_idx = 0;
		var found = false;
		var next_target = null;
		for (var i=target_idx; i<attacks.length && !found; i++){
			if (attacks[i].enabled && (Data.options.bookmarks.choice == 3 || Data.options.bookmarks.choice == attacks[i].t)) {
				next_target = attacks[i];
				t.current_target_idx = i;
				found = true;
			}
		}
		if (next_target === null) return;
		return next_target;
	},
	gotBattleReport : function (rpt_b){
		var t = Tabs.Bookmarks;
		if (!rpt_b) return;
		//logit (inspectObj (rpt_b, 8, 1));
		var march_id = null;
		for (var id in Data.marches.bookmark) {
			var march = Data.marches.bookmark[id];
			if (march.x === rpt_b.report.location.x && 
				march.y === rpt_b.report.location.y &&
				march.general.id === rpt_b.report.attacker.general.id
				){
					march_id = id;
					break;
			}
		}

		if (march_id && march_id != null) {
			t.trackStats (march_id, rpt_b);
		}

		//fetchPlayer when new item (Didi modif)
		var items = rpt_b.report.spoils.items;
		if (items.length !== 0) {
			Seed.fetchPlayer ( {noCities:true} ); 
		}
		if (!Data.options.bookmarks.delete_reports && !Data.options.bookmarks.stop_on_loss ){
			return;
		}
		if (Data.options.bookmarks.stop_on_loss) {
			for (var p in rpt_b.report.attacker.units) {
				if (rpt_b.report.attacker.units[p][0] != rpt_b.report.attacker.units[p][1])	{
					var ts = new Date(rpt_b.report_notification.created_at * 1000).myString();
					t.setBookmarksEnable (false);
					t.dispFeedback (translate('Troops lost') +'! ('+ ts +')');
					actionLog (translate('Troops lost') +'! ('+ ts +')');
					return;
				}
			}
		}
		if (Data.options.bookmarks.delete_reports && rpt_b.report.attacker.name == Seed.player.name){
			Messages.deleteMessage (rpt_b.report_notification.id);
		}
	},
	initializeTargets : function (){
		var t = Tabs.Bookmarks;
		var last_time = -1;
		for (var i=0; i<Data.options.bookmarks.targets.length; i++){
			if (Data.options.bookmarks.sort == 2 && Data.options.bookmarks.targets[i].enabled && 
			   (Data.options.bookmarks.choice == 3 || Data.options.bookmarks.choice == Data.options.bookmarks.targets[i].t)) {
				if (last_time == -1) { // first entry
					Data.options.bookmarks.targets[i].st = 0;
				} else {
					var start_time = parseInt((last_time * 2) - (Data.options.bookmarks.targets[i].ti * 2));
//logit(Data.options.bookmarks.targets[i].x+','+Data.options.bookmarks.targets[i].y+', start time = '+start_time)
					Data.options.bookmarks.targets[i].st = start_time;
				}
				last_time = Data.options.bookmarks.targets[i].ti;
			} else {
				Data.options.bookmarks.targets[i].st = 0;
			}
		}
	},
	marchTick : function (){
		var t = Tabs.Bookmarks;
		clearTimeout (t.marchTimer);
		Marches.updateTable ( document.getElementById(UID['tabBookmarks_Marches']), 'bookmark' );
		t.marchTimer = setTimeout (t.marchTick, 1000);
	},
	sendAttack : function (cityIdx, target, general, great_dragon, notify){
		var t = Tabs.Bookmarks;
		var now = serverTime();
		if (t.attackBusy){
			t.dispFeedback (translate('Error')+ ': ' +translate('sendAttack is busy, no response from server?'));
			return;
		}
		var units = cloneProps(target.units);
		if (great_dragon != undefined && great_dragon != null) units[great_dragon] = 1;

		var targMsg =  translate('Attack sent to') + ': ' + target.type + ' ' + translate('at') + ' ' + target.x +'/'+ target.y;

		verboseLog(targMsg +' '+ translate('attempted'));
		t.attackBusy = true;
		t.lastAttack = now;

		new MyAjax.marchSend (Seed.cities[cityIdx].id, target.x, target.y, general.id, units, 'bookmark', function (rslt) {
			t.attackBusy = false;
			if (rslt.ok && rslt.dat.result.success) {
				Marches.add(rslt.dat.result.job.march_id, 'bookmark');
				t.attackErrors = 0;
				verboseLog(targMsg +' '+ translate('Successfully'));
				t.dispFeedback(targMsg);
				target.last_attack = now;
				if (notify){
					notify(true);
				}
			} else {
				t.attackErrors++;
				verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
				actionLog(targMsg + ' ' + translate('failed'));
				t.dispFeedback(targMsg + ' ' + translate('failed'));
					if (notify){
						notify(false);
					}
			}
		});
	},
	setBookmarksEnable : function (onOff){
		var t = Tabs.Bookmarks;
		var but = document.getElementById(UID['tabBookmarks_OnOff']);
		clearTimeout (t.attackTimer);
		Data.options.bookmarks.enabled = onOff;
		if (onOff){
			but.value = translate('Attacking').toUpperCase();
			but.className = UID['btn_on'];
			t.initializeTargets();
			t.autoCheckTargets();
			t.running.start_at = serverTime();
			Data.stats.bookmarks.start_at = serverTime();
		} else {
			but.value = translate('Disabled').toUpperCase();
			but.className = UID['btn_off'];
			if ( t.running.start_at !== 0 ){
				Data.stats.bookmarks.run_time += ( serverTime() - t.running.start_at );
			}
			t.dispFeedback ('');
		}
	},
	showStats : function (){
		var div = document.getElementById(UID['tabBookmarksStats_Status']);
		var t = Tabs.Bookmarks;

		if (div==null){
			return;
		}

		var run_time = Data.stats.bookmarks.run_time;
		if (Data.options.bookmarks.enabled){
			run_time += (serverTime()-t.curRunStart);
		}

		var trueRunTime = (run_time > 0) ? (run_time/3600) : 1;

		var m = '<table class=' + UID['table'] + '>'
		+'	<tr>'
		+'		<td class=right>'+ translate('Start Date') +': </td>'
		+'		<td colspan=>'+  new Date(Data.stats.bookmarks.start_at * 1000).myString() +'</td>'
		+'	</tr><tr>'
		+'		<td class=right>'+ translate('Run Time') +': </td>'
		+'		<td>'+ timestr(run_time, true) +'</td>'
		+'	</tr><tr>'
		+'		<td class=right>'+ translate('Attacks') +': </td>'
		+'		<td>'+ Data.stats.bookmarks.total_attacks +'</td>'
		+'	</tr><tr valign=top align=right>'
		+'		<td class=right>'+ translate('Resources') +': </td>';
		var first = true;
		for (var name in Data.stats.bookmarks.resources) {
			var perHour = Math.round(Data.stats.bookmarks.resources[name] / trueRunTime);
			if (first) first = false;
			else m += '	<tr align=right><td></td>';
			m += '			<td>'+ translate(name) +':</td>'
				+'			<td>'+ nombreFormate(Data.stats.bookmarks.resources[name],' ') +'</td>'
				+'			<td>('+ nombreFormate(perHour,' ') +' /'+ translate('h')+ ')</td>'
				+'		</tr>';
		}

		m += '<tr valign=top align=right>'
		+'		<td class=right>'+ translate('Items') +': </td>';
		var first = true;
		for (var name in Data.stats.bookmarks.items) {
			var perHour = Math.round(Data.stats.bookmarks.items[name] / trueRunTime);
			if (first) first = false;
			else m += '	<tr align=right><td></td>';
			m += '		<td>'+ translate(name) +':</td>'
				+'		<td>'+ nombreFormate(Data.stats.bookmarks.items[name],' ') +'</td>'
				+'		<td>('+ nombreFormate(perHour,' ') +' /'+ translate('h')+ ')</td>'
				+'	</tr>';
		}
		m += '</table>';
		div.innerHTML = m;
	},
	trackStats : function (marchId, rpt_st){
		var t = Tabs.Bookmarks;
		if (DEBUG_MARCHES){
			WinLog.write ('Tabs.Bookmarks.trackStats: '+ marchId);
		}
		var objLevel = rpt_st.report.location.level;

		if (objLevel < 1 || objLevel > 12){
			objLevel = 0;
		}

		++Data.stats.bookmarks.total_attacks;
		var res =  rpt_st.report.spoils.resources;
		for (var p in res){
			objAddTo (Data.stats.bookmarks.resources, p, parseInt(res[p]));
		}  
		var killRes =  rpt_st.report.spoils.kill_items;
		for (var p in killRes){
			objAddTo (Data.stats.bookmarks.resources, p, parseInt(killRes[p]));
		}  
		var items =  rpt_st.report.spoils.items;
		for (var i=0; i < items.length; i++){
			objAddTo (Data.stats.bookmarks.items, items[i], 1);
		}  

		Data.marches.bookmarks[marchId].has_report = true;
		t.showStats();    
	},

	onUnload : function (){
		var t = Tabs.Bookmarks;
		if (Data.options.bookmarks.enabled && t.running.start_at != 0){
			Data.stats.bookmarks.run_time += ( serverTime() - t.running.start_at );
		}
		Data.options.bookmarks.current_tab = t.contentType;
	},
	show : function () {
		var t = Tabs.Bookmarks;
		t.marchTick();
		switch (t.contentType) {
			case 0: t.tabBookmarksEdit(); break;
			case 1: t.tabBookmarksTargets(); break;
			case 2: t.tabBookmarksStats(); break;
			case 3: t.tabBookmarksConfig(); break;
		}
	},
	hide : function (){
		var t = Tabs.Bookmarks;
		clearTimeout (t.marchTimer);
		Data.options.bookmarks.current_tab = t.contentType;
	}
};
//*********************************** Bookmarks Tab *********************************************


//*********************************** Jobs Tab *********************************************
Tabs.Jobs = {
	tabOrder		: JOBS_TAB_ORDER,
	tabLabel		: 'Tasks',
	tabDisabled		: !JOBS_TAB_ENABLE,
	lastSubTab		: 'tabJobInfo',
	container		: null,
	timer			: null,
	contentType		: 0, // 0 = info, 1 = train, 2 = build, 3 = research, 4 = resurrect these should be enums but Javascript doesn't support that type
	trainContentType: 0, // 0 = train, 1 = config
	buildScrollPos	: 0,
	selectedQ		: 'min_housing',
	refreshPlayerBusy : false,

	trainTimer		: null,
	trainStatTimer	: null,
	trainErrorCount : 0,
	trainRetryTime	: 20000,

	buildTimer		: null,
	buildStatTimer	: null,
	buildErrorCount : 0,
	buildRetryTime	: 20000,

	researchTimer	: null,
	researchStatTimer	: null,
	resErrorCount	: 0,
	resRetryTime	: 20000,

	resurrectTimer	: null,
	resurrectStatTimer	: null,
	revErrorCount	: 0,
	revRetryTime	: 20000,

	init : function (div){
		var t = Tabs.Jobs;

		Data.setDefaultValues ('jobs');

		// Tab initialization
		t.container = div;
		var m =  '<ul class=tabs>\
			<li class="tab first"><a id=' + setUID('tabJobInfo') + '>'+ translate('Summary') +'</a></li>\
			<li class=tab><a id=' + setUID('tabJobTrain') + '>'+ translate('Train') +'</a></li>\
			<li class=tab><a id=' + setUID('tabJobBuild') + '>'+ translate('Build') +'</a></li>\
			<li class=tab><a id=' + setUID('tabJobResearch') + '>'+ translate('Research') +'</a></li>';
		if (Seed.cities[CAPITAL_ID].souls && Seed.cities[SPECTRAL_OUTPOST_ID])
			m += '<li class=tab><a id=' + setUID('tabJobResurrect') + '>'+ translate('Resurrect') +'</a></li>';
		m += '</ul>\
			<div id=' + setUID('tabJob_Header') + ' style="height:225px; max-height:225px; margin-bottom:5px;"></div>\
			<div id=' + setUID('tabJob_Content') + ' class="' + UID['scrollable'] + '" style="padding-top:5px; height:435px; max-height:700px;"></div>';
		
		div.innerHTML = m;
		document.getElementById(UID['tabJobInfo']).addEventListener ('click', t.tabJobInfo, false);
		document.getElementById(UID['tabJobTrain']).addEventListener ('click', t.tabJobTrain, false);	
		document.getElementById(UID['tabJobBuild']).addEventListener ('click', t.tabJobBuild, false);
		document.getElementById(UID['tabJobResearch']).addEventListener ('click', t.tabJobResearch, false);
		if (Seed.cities[CAPITAL_ID].souls && Seed.cities[SPECTRAL_OUTPOST_ID])
			document.getElementById(UID['tabJobResurrect']).addEventListener ('click', t.tabJobResurrect, false);
		
		// Restore the views
		t.contentType = Data.options.jobs.current_tab;
		t.trainContentType = Data.options.training.current_tab;

		// Enable the jobs
		t.setTrainEnable (Data.options.training.enabled);	
		t.selectedQ = Data.options.training.mode;
		t.setBuildEnable (Data.options.building.enabled);
		t.setResearchEnable (Data.options.research.enabled);
		if (Seed.cities[SPECTRAL_OUTPOST_ID])
			t.setResurrectEnable (Data.options.resurrect.enabled);

		// Add the unload event listener
		window.addEventListener('unload', t.onUnload, false);
	},

	show : function (){
		var t = Tabs.Jobs;
		switch (t.contentType) {
			case 0: t.tabJobInfo(); break;
			case 1: t.tabJobTrain(); break;
			case 2: t.tabJobBuild(); break;
			case 3: t.tabJobResearch(); break;
			case 4:
				if (Seed.cities[SPECTRAL_OUTPOST_ID]) t.tabJobResurrect();
				else t.tabJobInfo();
				break;
		}
	},
	hide : function (){
		var t = Tabs.Jobs;
		//t.clearTimers();
	},
	onUnload : function () {
		logit('Tabs.Jobs.onUnload');
		var t = Tabs.Jobs;
		Data.options.jobs.current_tab = t.contentType;
		Data.options.training.current_tab = t.trainContentType;
		Data.options.training.mode = t.selectedQ;
	},
	clearTimers : function (){
		var t = Tabs.Jobs;
		clearTimeout (t.jobsStatTimer);
		clearTimeout (t.trainStatTimer);
		clearTimeout (t.buildStatTimer);
		clearTimeout (t.researchStatTimer);
		clearTimeout (t.resurrectStatTimer);
	},

	// ** Tab: Jobs - SubTab:  Info
	//--------------------------------------------------------------------
	tabJobInfo : function (){
		var t = Tabs.Jobs;
		document.getElementById(UID[t.lastSubTab]).className ='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabJobInfo']).className ='selected';
		document.getElementById(UID['tabJobInfo']).style.zIndex=1;
		t.lastSubTab = 'tabJobInfo';

		t.contentType = 0;

		var city = Seed.cities[CAPITAL_ID];

		var n = '<div class=' + UID['title'] + '>'+translate('Info')+'</div>'
			+'	<table width=100%><tr><td><input id='+ setUID('tabJobInfo_Refresh') +' type=button value='+ translate('Refresh') +'></input></td></tr></table>';

		document.getElementById(UID['tabJob_Header']).style.height = "45px";
		document.getElementById(UID['tabJob_Header']).innerHTML = n;
		document.getElementById(UID['tabJobInfo_Refresh']).addEventListener ('click', refresh, false);
		document.getElementById(UID['tabJob_Content']).style.height = "593px";
		document.getElementById(UID['tabJob_Content']).innerHTML = '<div id="' + setUID('tabJob_Container') + '"></div>'; 
		var container = document.getElementById(UID['tabJob_Container']);

		function jobsStatTick(){
			// Main City
			var m = '<div class=' + UID['status_ticker'] + '>'
				+ cityTitle(CAPITAL_ID)
				+'<table class=' + UID['table'] + ' width=100%>'
				+ dispCurrRessources(CAPITAL_ID)
				+ dispDragonJob(CAPITAL_ID) 
				+ dispBuildingJob(CAPITAL_ID) 
				+ dispResearchJob(CAPITAL_ID) 
				+ dispTrainingJobs(CAPITAL_ID) 
				+'	</table>'
				+'</div>';

			// Outposts ...
			for (var cityIdx=0; cityIdx < Seed.cities.length; ++cityIdx){
				if(cityIdx != CAPITAL_ID && Seed.cities[cityIdx]){
					m += '<div class=' + UID['status_ticker'] + ' style="margin-top:6px !important">'
					+ cityTitle(cityIdx) 
					+'<table class=' + UID['table'] + ' width=100%>'
					+ dispDragonJob(cityIdx)
					+ dispOutpostJob(cityIdx)
					+ dispBuildingJob(cityIdx) 
					+ dispTrainingJobs(cityIdx)
					+ dispResurrectionJobs(cityIdx)
					+'	</table>'
					+'</div>';
				}
			}
			container.innerHTML = m; 
			container.style.height = container.offsetHeight + 'px';
		}

		function dispCurrRessources (cityIdx){
			var m = '<tr><td class=right width=20%>'+ translate ('Resources') +'</td>';
			var newline = '';
			for (var p=0; p<all_resource_types.length; p++){
				var lock_food = false;
				var production = Seed.cities[cityIdx].figures.resource_rates[all_resource_types[p]];
				var actualStock = nombreFormate(parseInt(Seed.cities[cityIdx].resources[all_resource_types[p]]));
				if (all_resource_types[p] == 'food' && Seed.player.boosts && Seed.player.boosts.collect_resources && parseInt(Seed.cities[cityIdx].resources[all_resource_types[p]]) > production.capacity) lock_food = true;
				m += newline + '<td width =15%>'+ translate(all_resource_types[p]) + '</td><td width=1%>:</td><td align=right width=14%>'+ actualStock +'</td><td width=5%> &nbsp </td>'
					+'<td width=10% align=right>('+ (lock_food ? '<font color=blue><b>0</b></font>' : nombreFormate(production.rate)) +' /'+ translate('h')+ ')</td><td width=30%> &nbsp </td></tr>';
				newline = '<tr><td> &nbsp </td>'
			}
			var popCur = isEmpty(Seed.cities[cityIdx].figures.population['current'],0);
			var popLab = isEmpty(Seed.cities[cityIdx].figures.population['laborers'],0);
			var popFor = isEmpty(Seed.cities[cityIdx].figures.population['armed_forces'],0);
			var num = popCur - popLab - popFor;
			num = (num < 0) ? 0 : num;
			m += '<tr><td> &nbsp </td><td width =15%>' + translate('Idle pop') + '</td><td width=1%>:</td><td align=right width=14%>' + nombreFormate(num,' ') + '</td><td width=50% colspan=3> &nbsp </td></tr>';
			m += '</table><br><table class=' + UID['table'] + ' width=100%>';
			return m;
		}
		function dispDragonJob (cityIdx){
			var m = '';
			var job = getDragonJob (cityIdx);
			if (job && job.run_at > serverTime()) {
				m += '<tr><td class=right width=20%>' + translate('Healing') + ':</td>'
				  +  '<td width=50%><SPAN class=' + UID['bold_red'] + '>'+ translate ('Dragon healing') + '</span></td><td width=30%><font color=' + TIMER_COLOR + '>'+ timestr(job.run_at - serverTime(), true) +'</font></td></tr>';
			}
			return m;
		}
		function dispOutpostJob (cityIdx){
			var m = '';
			var job = getOutpostJob (cityIdx);
			if (job && job.run_at > serverTime()) {
				m += '<tr><td class=right width=20%>' + translate('Repairing') + ':</td>'
				  +  '<td width=50%><SPAN class=' + UID['bold_red'] + '>'+ translate ('Outpost damages') + '</span></td><td width=30%><font color=' + TIMER_COLOR + '>'+ timestr(job.run_at - serverTime(), true) +'</font></td></tr>';
			}
			return m;
		}
		function dispBuildingJob (cityIdx){
			var m = '<tr><td width=20% class=right>'+ translate('Building') +': </td>';
			var job = getBuildingJob (cityIdx);
			if (job && job.job.run_at > serverTime()) {
				m += '<td width=50% align=left>'+ translate(job.building.type) +' ('+ job.job.level +') &nbsp;</td>'
				  + '<td width=30%><font color=' + TIMER_COLOR + '>' + timestr(job.job.run_at - serverTime(), true) + '</font></td>'
				  + '</tr>';
			} else {
				m += '<td align=left width=80% colspan=2><span class=' + UID['bold_red'] + '>' + translate('None').toUpperCase() + '</span></td></tr>';
			}
			return m;
		}
		function dispResearchJob (cityIdx){
			var m = '<tr><td class=right width=20%>'+ translate('Researching') +': </td>';
			var job = getResearchJob (cityIdx);
			if (job && job.run_at > serverTime()) {
				m += '<td width=50% align=left>'+ translate(job.research_type) +' ('+ job.level +') &nbsp;</td>'
				  + '<td width=30%><font color=' + TIMER_COLOR + '>' + timestr(job.run_at - serverTime(), true) + '</font></td>'
				  +'</tr>';
			} else {
				m += '<td align=left width=80% colspan=2><span class=' + UID['bold_red'] + '>' + translate('None').toUpperCase() + '</span></td></tr>';
			}
			return m;
		}
		function dispTrainingJobs (cityIdx){
			var m = '', last = serverTime(), trains = [];
			for (var i=0; i < Seed.cities[cityIdx].jobs.length; i++){
				if (Seed.cities[cityIdx].jobs[i].queue=='units' && 
					Seed.cities[cityIdx].jobs[i].unit_type && 
					Seed.cities[cityIdx].jobs[i].run_at > last
					){
						trains.push (Seed.cities[cityIdx].jobs[i]);
				}
			}
			trains.sort(function(a,b){return a.run_at-b.run_at});
			for (var i=0; i < trains.length; i++){
				var left='', tot='', timeRemaining = 0;
				if (i==0){
					left = translate('Training') + ':';
				}
				else if (i==trains.length-1) {
					timeRemaining = (trains[i].run_at-serverTime() > 0) ? trains[i].run_at-serverTime() : 0;
					tot = '&nbsp;<b>(' + timestrShort(timeRemaining) + ')</b>';
				}
				timeRemaining = (trains[i].run_at-last > 0) ? trains[i].run_at-last : 0;
				m += '<tr>'
				+ '		<td class=right width=20%>' + left + '</td>'
				+ '		<td align=left width=50%>' + nombreFormate(trains[i].quantity, ' ') + '&nbsp;&nbsp;' + translate(trains[i].unit_type) + '&nbsp;</td>'
				+ '     <td width=30%><font color=' + TIMER_COLOR + '>' + timestr(timeRemaining, true) + '</font>&nbsp' + tot + '</td>'
				+ '</tr>';
				last = trains[i].run_at;
			}      
			return m;
		}
		function dispResurrectionJobs (cityIdx){
			var m = '', last = serverTime(), trains = [];
			for (var i=0; i < Seed.cities[cityIdx].jobs.length; i++){
				if (Seed.cities[cityIdx].jobs[i].queue=='resurrection' && 
					Seed.cities[cityIdx].jobs[i].unit_type && 
					Seed.cities[cityIdx].jobs[i].run_at > last
					){
						trains.push (Seed.cities[cityIdx].jobs[i]);
				}
			}
			trains.sort(function(a,b){return a.run_at-b.run_at});
			for (var i=0; i < trains.length; i++){
				var left='', tot='', timeRemaining = 0;
				if (i==0){
					left = translate('Resurrection') + ':';
				}
				else if (i==trains.length-1) {
					timeRemaining = (trains[i].run_at-serverTime() > 0) ? trains[i].run_at-serverTime() : 0;
					tot = '&nbsp;<b>(' + timestrShort(timeRemaining) + ')</b>';
				}
				timeRemaining = (trains[i].run_at-last > 0) ? trains[i].run_at-last : 0;
				m += '<tr>'
				+ '		<td class=right width=20%>' + left + '</td>'
				+ '		<td align=left width=50% colspan=2>' + nombreFormate(trains[i].quantity, ' ') + '&nbsp;&nbsp;' + translate(trains[i].unit_type) + '&nbsp;</td>'
				+ '     <td width=30%><font color=' + TIMER_COLOR + '>' + timestr(timeRemaining, true) + '</font>&nbsp' + tot + '</td>'
				+ '</tr>';
				last = trains[i].run_at;
			}      
			return m;
		}
		function cityTitle (cityIdx){
			var city = Seed.cities[cityIdx];
			var wallStatus = '';
			var alliance_name = (Seed.player.alliance) ? Seed.player.alliance.name : '';
			alliance_name = (city.type == kOutpost) ? '' : alliance_name;
			if (cityIdx == CAPITAL_ID){
				wallStatus = (Seed.cities[cityIdx].defended!=undefined && Seed.cities[cityIdx].defended) ? '<font class='+ UID['defending'] +'>'+ translate('Defend').toUpperCase() +'</font>' : '<font class='+ UID['hiding'] +'>'+ translate('Hiding').toUpperCase() +'</font>';
			} else {
				wallStatus = ' &nbsp ';
			}
			var title = ''
				+'<div class=' + UID['subtitle'] + '>'
				+'	<table class=' + UID['table'] + '>'
				+'	<tr>'
				+'		<td align=left width=35%>'+ ( (city.type == kOutpost) ? translate(city.name) : city.name ) +'</td>'
				+'		<td align=center width=30%>'+ city.x +','+ city.y + '</td>'
				+'		<td align=center width=200px>'
				+'			<font color=yellow>' + alliance_name +'</font>'
				+'		</td>'
				+'		<td width=35% align=right>'+ wallStatus +'</td>'
				+'	</tr>'
				+'</table></div>';
			return title;
		}
		function refresh (){
			logit('fetchPlayer from Tab.Jobs refresh');
			var t = Tabs.Jobs;
			if (t.refreshPlayerBusy)
				return false;
			t.refreshPlayerBusy = true;
			refreshPlayerData(t.container, function(){
				logit(translate ('Player data retrieved'));
				Tabs.Jobs.refreshPlayerBusy = false});
			t.tabJobInfo();
		}

		jobsStatTick();
		t.clearTimers();
		t.jobsStatTimer = setInterval (jobsStatTick, 1000);
	},

	//----------------------------------------------------------------------------
	//*** Jobs Tab - Train Sub-tab ***
	//----------------------------------------------------------------------------
	tabJobTrain : function (){
		var t = Tabs.Jobs;
		document.getElementById(UID[t.lastSubTab]).className ='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabJobTrain']).className ='selected';
		document.getElementById(UID['tabJobTrain']).style.zIndex=1;
		t.lastSubTab = 'tabJobTrain';

		t.contentType = 1;

		var n = '<div class=' + UID['title'] + '>'+ translate('Train') +' '+ translate('Automatically') +'</div>'
		+'<div class=' + UID['status_ticker'] + ' style="margin-bottom: 5px !important">'
		+'	<center><input id=' + setUID('tabJobTrain_OnOff') + ' type=button /></center>'
		//+'	<div id=' + setUID('tabJobTrain_Report') + ' class='+ UID['status_report'] +'></div>'
		+'	<div id=' + setUID('tabJobTrain_Report') + ' class='+ UID['status_report'] +'>'//' style="margin-top:5px;height:140px; max-height:140px; overflow-y:auto;">'
		+'		<table id=' + setUID('tabJobTrain_Table') + ' class=' + UID['table'] + '>'
		+'		</table>'
		+'	</div>'
		+'	<br>'
		+'	<div id='+ setUID('tabJobTrain_Feedback') +' class='+ UID['status_feedback'] +'></div>'
		+'</div>'
		+'<ul class=tabs>'
		+'	<li class="tab first"><a id='+ setUID('tabJobTrain_tabTrain') +'>'+ translate('Train') +'</a></li>'
		+'	<li class="tab"><a id='+ setUID('tabJobTrain_tabConfig') +'>'+ translate('Config') +'</a></li>'
		+'</ul>';
		document.getElementById(UID['tabJob_Header']).style.height = "225px";
		document.getElementById(UID['tabJob_Header']).innerHTML = n;

		var m = '<div id='+ setUID('tabJobTrain_Content') +' style="height:430px; ; max-height:430px; overflow-y:auto">';
		document.getElementById(UID['tabJob_Content']).style.height = "430px";
		document.getElementById(UID['tabJob_Content']).innerHTML = m;

		document.getElementById(UID['tabJobTrain_OnOff']).addEventListener ('click', function (){
			var t=Tabs.Jobs;
			t.setTrainEnable (!Data.options.training.enabled);
		}, false);
		document.getElementById(UID['tabJobTrain_tabTrain']).addEventListener ('click', t.tabJobTrainSets, false);
		document.getElementById(UID['tabJobTrain_tabConfig']).addEventListener ('click', t.tabJobTrainConfig, false);
		t.refreshTrainButton (Data.options.training.enabled);

		switch (t.trainContentType) {
			case 0: t.tabJobTrainSets(); break;
			case 1: t.tabJobTrainConfig(); break;
		}
		t.trainStatTick();
		t.clearTimers();
		t.trainStatTimer = setInterval(t.trainStatTick, 1000);
	},

	//*** Jobs Tab - Train Sub-tab  - Train Sub-Sub-tab ***
	//----------------------------------------------------------------------------
	tabJobTrainSets : function(){
		var t = Tabs.Jobs;
		// Create troop table for each city
		var el = [], m = '', cl = [], tn = [], en = [];
		for (var cityIdx=0; cityIdx<Seed.cities.length; cityIdx++) {
			if (Data.options.collapsed.train[cityIdx] == undefined) {
				Data.options.collapsed.train[cityIdx] = false;
			}
		}
		for (var cityIdx=0; cityIdx < Seed.cities.length; ++cityIdx){
			if (Seed.cities[cityIdx] && cityIdx != SPECTRAL_OUTPOST_ID) {
				switch (cityIdx) {
					case CAPITAL_ID			: troopTypes = capital_units; break;
					case WATER_OUTPOST_ID	: troopTypes = water_outpost_units; break;
					case STONE_OUTPOST_ID	: troopTypes = stone_outpost_units; break;
					case FIRE_OUTPOST_ID	: troopTypes = fire_outpost_units; break;
					case WIND_OUTPOST_ID	: troopTypes = wind_outpost_units; break;
					case ICE_OUTPOST_ID		: troopTypes = ice_outpost_units; break;
					case SWAMP_OUTPOST_ID	: troopTypes = swamp_outpost_units; break;				
					case FOREST_OUTPOST_ID	: troopTypes = forest_outpost_units; break;				
					default: break;
				}
				var city = Seed.cities[cityIdx];
				var cityJobsId = 'tabJobTrain_cityId_' + cityIdx;
				var cityJobsListId = 'tabJobTrain_cityList_' + cityIdx;
				var cityJobsEnabled = 'tabJobTrain_Enabled_' + cityIdx;
				// Retrieve current total time of queued trainings for display in city title
				var current_total_time = 0;
				var now  = serverTime();
				if (city.jobs) {
					var jobs = city.jobs;
					var trains = [];
					for (var j=0; j < jobs.length; j++)
						if (jobs[j].queue=='units' && jobs[j].unit_type && jobs[j].run_at > now) trains.push (jobs[j]);
					if (trains.length > 0) {
						trains.sort( function(a,b){ return a.run_at - b.run_at; } );
						var current_total_time = trains[trains.length-1].run_at - now;
					}
				}
				m += '<div class=' + UID['status_ticker'] + ' style="margin-top:10px !important">'
				+'<A><div id=' + setUID(cityJobsId) + ' class=' + UID['subtitle'] + ' ref=' + cityIdx + '>'
				+'	<table class=' + UID['table'] + ' width=100%>'
				+'	<tr>'
				+'		<td align=left width=1%><label><input type=checkbox id='+ setUID(cityJobsEnabled) +' ref="Enable_'+ cityIdx +'" '+ (Data.options.training.city[cityIdx].enabled?'checked':'') +' /></label></td>'
				+'		<td align=left width=29%>&nbsp</td>'
				+'		<td align=center width=40%>'+ ( (city.type == kOutpost) ? translate(city.name) : city.name ) + '</td>'
				+'		<td align=right width=30%>'
				+'			<font color=yellow>' + timestrShort(current_total_time) +'</font>'
				+'		</td>'
				+'	</tr>'
				+'</table></div></A>'
				+'<div id=' + setUID(cityJobsListId) + '>'
				+'<table class=' + UID['table'] + ' width=100%>'
				+'	<tr class='+UID['row_headers']+'>'
				+'		<td></td><td>'+translate('Quantity')+'</td><td>'+translate('Total')+'</td></tr>';
				cl.push(UID[cityJobsId]);
				en.push(UID[cityJobsEnabled]);

				var i;
				for (i=0; i < troopTypes.length; i++){
					var num = Data.options.training.city[cityIdx].units[i];
					if (!num || isNaN(num)){
						num = 0;
					}
					m += '<tr>'
					+'		<td class=right width=25%>'+ translate(troopTypes[i]) +':</td>'
					+'		<td align=middle width=10%><input type=text id='+ setUID('tabTrain_Troop_'+ cityIdx +'_'+ i) +' ref='+ cityIdx +'_'+ i +' maxlength=6 size=2 value="'+ num +'" style="width:45px;text-align:right;" /></td>'
					+'		<td align=right width=15%>&nbsp;<span class=jewel>('+ nombreFormate(getTroopNumbers(Seed.cities[CAPITAL_ID], troopTypes[i]).total,' ') +')</span></td>'
					+'		<td align=left width=40% id='+ setUID('tabJobTrain_FB_'+cityIdx +'_'+ troopTypes[i]) +' class=jewel valign=top style="white-space:normal;"></td>'
					+'		<td align=right width=10%><input class=small id=' + setUID('tabTrain_Now_'+cityIdx +'_'+ i) + ' ref=' + cityIdx +'_'+ i + ' type=button  style="width:auto !important;" value="'+ translate('Train') +'" \></td>'
					+'	</tr>';
					el.push(UID['tabTrain_Troop_'+ cityIdx +'_'+ i]);
					tn.push(UID['tabTrain_Now_'+ cityIdx +'_'+ i]);
				}
				m += '</table></div></div>';
			}
		}
		m += '</div>';
		document.getElementById(UID['tabJobTrain_Content']).innerHTML = m;
		document.getElementById(UID['tabJobTrain_tabConfig']).className = '';
		document.getElementById(UID['tabJobTrain_tabConfig']).style.zIndex=0;
		document.getElementById(UID['tabJobTrain_tabTrain']).className = 'selected';
		document.getElementById(UID['tabJobTrain_tabTrain']).style.zIndex=1;

		t.trainContentType = 0;

		for (var c=0; c<cl.length; c++) {
			document.getElementById(cl[c]).addEventListener('click', toggleHideShow, false);
			var cityIdx = document.getElementById(cl[c]).getAttribute('ref');
			var div_id = 'tabJobTrain_cityList_' + cityIdx;
			var div_el = document.getElementById(UID[div_id]);
			if (Data.options.collapsed.train[cityIdx])
				div_el.style.display = 'none';
			else
				div_el.style.display = 'block';
		}
		for (var i=0; i < el.length; i++){
			document.getElementById(el[i]).addEventListener('change', troopsChanged, false);
			document.getElementById(el[i]).addEventListener('click', troopsChanged, false);
		}
		for (var i=0; i < tn.length; i++){
			document.getElementById(tn[i]).addEventListener('click', onTrainNow, false);
		}
		for (var i=0; i < en.length; i++){
			document.getElementById(en[i]).addEventListener('change', onEnableCityNow, false);
			document.getElementById(en[i]).addEventListener('click', onEnableCityNow, false);
		}

		function troopsChanged (event){
			var args = event.target.getAttribute('ref').split('_');
			var unitQty = parseIntZero(event.target.value);
			var cityIdx = parseInt(args[0]);
			var unitType;
			switch (cityIdx) {
				case CAPITAL_ID			 : unitType = capital_units[args[1]]; break;
				case WATER_OUTPOST_ID	 : unitType = water_outpost_units[args[1]]; break;
				case STONE_OUTPOST_ID	 : unitType = stone_outpost_units[args[1]]; break;
				case FIRE_OUTPOST_ID	 : unitType = fire_outpost_units[args[1]]; break;
				case WIND_OUTPOST_ID	 : unitType = wind_outpost_units[args[1]]; break;
				case ICE_OUTPOST_ID		 : unitType = ice_outpost_units[args[1]]; break;
				case SWAMP_OUTPOST_ID	 : unitType = swamp_outpost_units[args[1]]; break;
				case FOREST_OUTPOST_ID	 : unitType = forest_outpost_units[args[1]]; break;
			}
			var reqs = t.checkTrainReqs(unitType, unitQty, cityIdx);
			if (isNaN(unitQty) || unitQty < 0){
				event.target.style.backgroundColor = 'red';
				dispError (translate('Invalid number of troops',t.container));
			} else {
				event.target.value = unitQty;
				Data.options.training.city[args[0]].units[args[1]] = unitQty;
				event.target.style.backgroundColor = '';
			}
		}
		function onEnableCityNow (event){
			var cityIdx = event.target.getAttribute('ref').split('_');
			Data.options.training.city[cityIdx[1]].enabled = event.target.checked;
		}
		function onTrainNow (event){
			var args = event.target.getAttribute('ref').split('_');
			var cityIdx = parseInt(args[0]);
			var unitType;
			switch (cityIdx) {
				case CAPITAL_ID			 : unitType = capital_units[args[1]]; break;
				case WATER_OUTPOST_ID	 : unitType = water_outpost_units[args[1]]; break;
				case STONE_OUTPOST_ID	 : unitType = stone_outpost_units[args[1]]; break;
				case FIRE_OUTPOST_ID	 : unitType = fire_outpost_units[args[1]]; break;
				case WIND_OUTPOST_ID	 : unitType = wind_outpost_units[args[1]]; break;
				case ICE_OUTPOST_ID		 : unitType = ice_outpost_units[args[1]]; break;
				case SWAMP_OUTPOST_ID	 : unitType = swamp_outpost_units[args[1]]; break;
				case FOREST_OUTPOST_ID	 : unitType = forest_outpost_units[args[1]]; break;
			}
			var unitQty = Data.options.training.city[cityIdx].units[args[1]];
			if (unitQty > 0) {
				cap = t.getTroopCap(unitType, unitQty);
				try {
					if (cap) {
						unitQty = 0;
						if (t.contentType == 1){
							t.dispFeedback(translate('Troops Capped'));
						}
						document.getElementById(UID['tabTrain_Troop_'+ cityIdx +'_'+ j]).style.backgroundColor = "red";
					}
					else if (t.contentType == 1){
						if (document.getElementById(UID['tabTrain_Troop_'+ cityIdx +'_'+ j]).style.backgroundColor == "red"){
							document.getElementById(UID['tabTrain_Troop_'+ cityIdx +'_'+ j]).style.backgroundColor = "white";
						}
					}
				} catch (e) {}
			}
			if (unitQty > 0) {
				var reqs = t.checkTrainReqs(unitType, unitQty, cityIdx);
				if (t.contentType == 1 && !reqs.msg){
					t.dispFeedback (translate('Training') + ' ' + nombreFormate(unitQty, ' ') + ' ' + translate(unitType) + ' (' + translate('UpKeep') + ' ' + (unitQty * Seed.stats.unit[unitType].upkeep.food) + ' ' + translate('Food') + ')');
				}
				if (!reqs.msg) t.doTrain(unitType, unitQty, cityIdx);
			}
		}
		function toggleHideShow (event){
			// Do not collapse or uncollapse when clicking on the city enble checkbox
			if (event.target.getAttribute('ref')) {
				var target_ref = event.target.getAttribute('ref').split('_');
				if (target_ref[0] = 'Enable') return;
			}
			if (event.target.tagName == 'DIV')
				element = event.target;
			else {
				var parentElement = event.target.parentNode;
				while (parentElement.tagName != 'DIV') {
					parentElement = parentElement.parentNode;
				}
				element = parentElement;
			}
			var cityIdx = element.getAttribute('ref');
			var div_id = 'tabJobTrain_cityList_' + cityIdx
			var div_el = document.getElementById(UID[div_id]);
			if (div_el.style.display == 'none') {
				div_el.style.display = 'block';
				Data.options.collapsed.train[cityIdx] = false;
			} else {
				div_el.style.display = 'none';
				Data.options.collapsed.train[cityIdx] = true;
			}
		}
	}, 

	// config sub tab
	tabJobTrainConfig : function(){
		var t = Tabs.Jobs;
		document.getElementById(UID['tabJobTrain_tabTrain']).className = '';
		document.getElementById(UID['tabJobTrain_tabTrain']).style.zIndex = 0;
		document.getElementById(UID['tabJobTrain_tabConfig']).className = 'selected';
		document.getElementById(UID['tabJobTrain_tabConfig']).style.zIndex = 1;

		t.trainContentType = 1;

		setUID('tabTrainConfig_QRadio');
		var m = '<div class=' + UID['status_ticker'] + ' style="margin-top:6px !important">'
			+	'<div class=' + UID['subtitle'] + '>'+ translate('Training Configuration') +'</div>'
			+	'	<div class="' + UID['scrollable'] + '">'
			+	'		<table class=' + UID['table'] + '>'
			+	'		<tr align=center class=' + UID['row_headers'] + '>'
			+	'			<td style="background:none !important;" colspan=2></td>'
			+	'		</tr>'
			+	'	<tr>'
			+	'		<td><label><input type=radio name='+ UID['tabTrainConfig_QRadio'] +' value="min_housing" />'+ translate('Only one training queue per city') +'</label></td>'
			+	'	</tr>'
			+ 	'	<tr>'
			+	'		<td><label><input type=radio name='+ UID['tabTrainConfig_QRadio'] +' value="min_resource" />'+ translate('Maximum training queues possible per city, according to available resources') +'</label></td>'
			+	'	</tr>'
			+	'	</table>'
			+	'</div>'
			+	'<br>';

		var el = [];
		var troopTypes = all_trainable_units;
		m += '<div class=' + UID['subtitle'] + ' style="background-color:#0044a0;">'+ translate('Maximum Troops') +' (0 = '+translate('no max') +')</div>'
		  +	'	<table class=' + UID['table'] + ' width=100%>'
		  + '		<tr valign=top>'
		  + '			<td width=33%>'
		  + '			<table class=' + UID['table'] + ' width=100%>';

		var i;
		var nbre1 = Math.ceil(troopTypes.length/2);
		for (i=0; i < nbre1; i++){
			m += '<tr>'
			  +  '	<td class=right width=70%>'+ translate(troopTypes[i]) +':</td>';
			var num = Data.options.training.city[0].cap[i];
			if (!num || isNaN(num)) num = 0;
			m += '<td width=30%><input type=text id='+ setUID('tabTrainConfig_Cap_'+ 0 +'_'+ i) +' ref='+ (0 +'_'+ i) +' maxlength=8 size=2 value="'+ num +'" style="width:60px;text-align:right;" /></td>'
			  + '</tr>';
			el.push(UID['tabTrainConfig_Cap_'+ 0 +'_'+ i]);
		}
		m += '</table></td>'
		  + '	<td width=33%>'
		  + '	<table class=' + UID['table'] + ' width=100%>';
		for (i=nbre1; i < troopTypes.length; i++){
			m += '<tr>'
			  +  '	<td class=right width=70%>'+ translate(troopTypes[i]) +':</td>';
			var num = Data.options.training.city[0].cap[i];
			if (!num || isNaN(num)){
				num = 0;
			}
			m += '<td width=30%>'
			  + '<input type=text id='+ setUID('tabTrainConfig_Cap_'+ 0 +'_'+ i) +' ref='+ (0 +'_'+ i) +' maxlength=8 size=2 value="'+ num +'" style="width:60px;text-align:right;" /></td>'
			  + '</tr>';
			el.push(UID['tabTrainConfig_Cap_'+ 0 +'_'+ i]);
		}
		m += '			</table>'
		  + '			</td>'
		  + '		</tr>'
		  + '	</table>'
		  + '</div>'
		  + '</div>';

		document.getElementById(UID['tabJobTrain_Content']).innerHTML = m;
		var r = document.getElementsByName(UID['tabTrainConfig_QRadio']);
		for (var i=0; i < r.length; i++) {
			r[i].addEventListener('change', enableChanged, false);
			r[i].checked = (r[i].value == Data.options.training.mode);
		}
		for (var i=0; i < el.length; i++) {
			document.getElementById(el[i]).addEventListener('change', troopsChanged, false);
		}

		function enableChanged(event){
			var t = Tabs.Jobs;
			if (Data.options.training.enabled) {
				t.setTrainEnable(false); // It would be very bad to leave training on when switching queue types. 
				if (t.contentType == 1){
					t.dispFeedback (translate('Safe Mode') +' '+ translate('Training') +' '+ translate('Turned Off'));
				}
			}
			t.selectedQ = event.target.value;
			Data.options.training.mode = event.target.value;
		}
		function troopsChanged (event){
			var args = event.target.getAttribute('ref').split('_');
			var x = parseIntZero(event.target.value);
			if (isNaN(x) || x < 0){
				event.target.style.backgroundColor = 'red';
				dispError (translate('Invalid number of troops',t.container));
			} 
			else {
				event.target.value = x;
				Data.options.training.city[args[0]].cap[args[1]] = x;
				event.target.style.backgroundColor = '';
			}
		}
	},

	//----------------------------------------------------------------------------
	//*** Jobs Tab - Build Sub-tab ***
	//----------------------------------------------------------------------------
	tabJobBuild : function (){
		var t = Tabs.Jobs;
		document.getElementById(UID[t.lastSubTab]).className ='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabJobBuild']).className ='selected';
		document.getElementById(UID['tabJobBuild']).style.zIndex=1;
		t.lastSubTab = 'tabJobBuild';

		t.contentType = 2;

		var n = '<div class=' + UID['title'] + '>'+ translate('Build') +' '+ translate('Automatically') +'</div>'
		+'<div class=' + UID['status_ticker'] + '>'
		+'	<center><input id='+ setUID('tabJobBuild_OnOff') +' type=button /></center>'
		+'	<div id='+ setUID('tabJobBuild_Report') +' class='+UID['status_report']+'></div>'
		+'	<br>'
		+'	<div id='+ setUID('tabJobBuild_Feedback') +' class='+ UID['status_feedback'] +'></div>'
		+'</div>';
		document.getElementById(UID['tabJob_Header']).style.height = "205px";
		document.getElementById(UID['tabJob_Header']).innerHTML = n;
		document.getElementById(UID['tabJob_Content']).innerHTML = '<div id='+ setUID('tabJobBuild_Content') +'>';
		document.getElementById(UID['tabJob_Content']).style.height = "455px";

		m = '';
		var el = [], listC = [], listF = [], cl = [];
		for (var cityIdx=0; cityIdx<Seed.cities.length; cityIdx++) {
			if (Data.options.collapsed.build[cityIdx] == undefined) {
				Data.options.collapsed.build[cityIdx] = false;
			}
		}
		for (var cityIdx=0; cityIdx < Seed.cities.length; ++cityIdx) {
			switch (cityIdx) {
				case CAPITAL_ID :
					listC = capital_buildings;
					listF = field_buildings;
					break;
				case SPECTRAL_OUTPOST_ID :
					listC = spectral_buildings;
					listF = spectral_fields;
					break;
				default :
					listC = outpost_buildings;
					listF = field_buildings;
					break;
			}

			if (Seed.cities[cityIdx]) {
				var city = Seed.cities[cityIdx];
				var cityBuildId = 'tabJobBuild_cityId_' + cityIdx;
				var cityBuildListId = 'tabJobBuild_cityList_' + cityIdx;
				m += '<div class=' + UID['content'] + ' style="margin-bottom:5px;">'
				+ '<A><div id=' + setUID(cityBuildId) + ' class=' + UID['subtitle'] + ' ref=' + cityIdx + '>'+ ( (city.type == kOutpost) ? translate(city.name) : city.name ) +'</div></A>'
				+ '<div id=' + setUID(cityBuildListId) + '>'
				+'<table class=' + UID['table'] + '>';
				cl.push(UID[cityBuildId]);

				for (var i=0; i < listF.length; ++i) {
					var max_level = Seed.stats.building[listF[i]].level.length - 1;
					var min_level = (Buildings.getLevel(cityIdx, listF[i])).min;
					if (min_level < max_level) {
						m += '	<tr>'
						+'			<td>'
						+'			<label><input type=checkbox id='+ setUID('tabJobBuild_CB_'+ (cityIdx +'_'+ listF[i])) +' ref='+ (cityIdx +'_'+ listF[i]) +' '+ (Data.options.building.level_enable[cityIdx][listF[i]]?'checked':'') +' /> '+ translate(listF[i]) +'</label>'
						+'			</td>'
						+'			<td>'
						+'			&nbsp;<span class=jewel>'+ min_level + '</span>'
						+'			</td>'
						+'			<td>'+ buildDisplayCap(cityIdx,(listC.length + i),listF[i]) +'</td>'
						+'		</tr>';  
						el.push(UID['tabJobBuild_CB_'+ (cityIdx +'_'+ listF[i])]);
					}
				}
				m += '<tr><td colspan=5><hr></td></tr>';

				for (var i=0; i < listC.length; ++i) {
					var max_level = Seed.stats.building[listC[i]].level.length-1;
					var min_level = (Buildings.getLevel(cityIdx, listC[i])).min;
					if (min_level < max_level) {
						m += '	<tr>'
						+'			<td>'
						+'			<label><input type=checkbox id='+ setUID('tabJobBuild_CB_'+ (cityIdx +'_'+ listC[i])) +' ref='+ (cityIdx +'_'+ listC[i]) +' '+ (Data.options.building.level_enable[cityIdx][listC[i]]?'checked':'') +' /> '+ translate(listC[i]) +'</label>'
						+'			</td>'
						+'			<td>'
						+'			&nbsp;<span class=jewel>'+ min_level + '</span>'
						+'			</td>'
						+'			<td>'+ buildDisplayCap(cityIdx,i,listC[i]) +'</td>'
						+'		</tr>';  
						el.push(UID['tabJobBuild_CB_'+ (cityIdx +'_'+ listC[i])]);
					}
				}
				m +='</table></div></div>';
			}
		}
		m += '</div>';
		var container = document.getElementById(UID['tabJobBuild_Content']);
		container.style.height = container.offsetHeight + 'px';
		container.innerHTML = m;

		for (var c=0; c<cl.length; c++) {
			document.getElementById(cl[c]).addEventListener('click', toggleHideShow, false);
			var cityIdx = document.getElementById(cl[c]).getAttribute('ref');
			var div_id = 'tabJobBuild_cityList_' + cityIdx;
			var div_el = document.getElementById(UID[div_id]);
			if (Data.options.collapsed.build[cityIdx])
				div_el.style.display = 'none';
			else
				div_el.style.display = 'block';
		}
		for (var i=0; i < el.length; i++) {
			document.getElementById(el[i]).addEventListener('click', checkedBuild, false);
		}
		for (var cityIdx=0; cityIdx < Seed.cities.length; ++cityIdx) {
			if (Seed.cities[cityIdx]) {
				var buildList;
				switch (cityIdx) {
					case CAPITAL_ID : buildList = capital_buildings.concat(field_buildings); break;
					case SPECTRAL_OUTPOST_ID : buildList = spectral_buildings.concat(spectral_fields); break;
					default : buildList = outpost_buildings.concat(field_buildings); break;
				}
				for (var i=0; i < buildList.length; ++i) {
					var max_level = Seed.stats.building[buildList[i]].level.length - 1;
					var min_level = (Buildings.getLevel(cityIdx, buildList[i])).min;
					if (min_level >= max_level) continue;
					var selectMenu = document.getElementById(UID['tabJobBuild_Cap_'+ cityIdx + '_' + buildList[i]]);
					try {
						if (!Data.options.building.level_cap[cityIdx][i]) {
							var lowestBuildingLevel = (Buildings.getLevel( cityIdx, buildList[i])).min;
							selectMenu.selectedIndex = lowestBuildingLevel;
							Data.options.building.level_cap[cityIdx][i] = lowestBuildingLevel;
						} else {
							selectMenu.selectedIndex = Data.options.building.level_cap[cityIdx][i];
							selectMenu.options[Data.options.building.level_cap[cityIdx][i]].selected = true;
							if (Data.options.building.level_enable[cityIdx][buildList[i]]){
								t.checkBuildReqs(cityIdx, buildList[i]);
							}
						}
					} catch (e) {}
					selectMenu.addEventListener('change', changeBuildCap, false);
				}
			}
		}
		document.getElementById(UID['tabJobBuild_OnOff']).addEventListener ('click', function (){
			var t=Tabs.Jobs;
			t.setBuildEnable (!Data.options.building.enabled);
		}, false);
		t.refreshBuildButton (Data.options.building.enabled);

		function checkedBuild (event){
			var ref = event.target.getAttribute('ref');
			var idx = ref.split ('_');
			var cityId = Seed.cities[idx[0]].id;
			Data.options.building.level_enable[idx[0]][idx[1]] = event.target.checked;
			if(Data.options.building.level_enable[idx[0]][idx[1]]){
				t.checkBuildReqs(idx[0], idx[1]);
			}
			if (Data.options.building.enabled && event.target.checked){
				t.buildTick();
			}
		}
		function buildDisplayCap (cityIdx, listIdx, type){
			var minLvl = (Buildings.getLevel(cityIdx, type)).min;
			var m = '<td>'
			+'	<select id='+ setUID('tabJobBuild_Cap_' + cityIdx +'_'+ type) +' ref='+ (cityIdx +'_'+ listIdx) + '>'
			+'		<option value=0'+ ( minLvl>0 ?' style="display:none;"':'') +'>0</option>'
			+'		<option value=1'+ ( minLvl>1 ?' style="display:none;"':'') +'>1</option>'
			+'		<option value=2'+ ( minLvl>2 ?' style="display:none;"':'') +'>2</option>'
			+'		<option value=3'+ ( minLvl>3 ?' style="display:none;"':'') +'>3</option>'
			+'		<option value=4'+ ( minLvl>4 ?' style="display:none;"':'') +'>4</option>'
			+'		<option value=5'+ ( minLvl>5 ?' style="display:none;"':'') +'>5</option>'
			+'		<option value=6'+ ( minLvl>6 ?' style="display:none;"':'') +'>6</option>'
			+'		<option value=7'+ ( minLvl>7 ?' style="display:none;"':'') +'>7</option>'
			+'		<option value=8'+ ( minLvl>8 ?' style="display:none;"':'') +'>8</option>'
			+'		<option value=9'+ ( minLvl>9 ?' style="display:none;"':'') +'>9</option>'
			+'		<option value=10'+ ( minLvl>10 ?' style="display:none;"':'') +'>10</option>'
			+'		<option value=11'+ ( minLvl>11 ?' style="display:none;"':'') +'>11</option>'
			+'		<option value=12'+ ( minLvl>12 ?' style="display:none;"':'') +'>12</option>'
			+'		<option value=13'+ ( minLvl>13 ?' style="display:none;"':'') +'>13</option>'
			+'		<option value=14'+ ( minLvl>14 ?' style="display:none;"':'') +'>14</option>'
			+'	</select></td>'
			+'		<td id='+ setUID('tabJobBuild_FB_'+cityIdx +'_'+ type) +' class=jewel valign=top style="width:250px;white-space:normal;"></td>';
			return m;
		}
		function changeBuildCap (event) {
			var ref = event.target.getAttribute('ref');
			var idx = ref.split ('_');
			Data.options.building.level_cap[idx[0]][idx[1]] = event.target[event.target.selectedIndex].value;
			event.target.style.backgroundColor = ''; 
			if(Data.options.building.level_enable[idx[0]][idx[1]]){
				t.checkBuildReqs(idx[0], idx[1]);
			}
			if (Data.options.building.enabled){
				t.buildTick();
			}
		}
		function onScroll (event){
			if (t.contentType == 2)
				t.buildScrollPos = document.getElementById(UID['tabJob_Content']).scrollTop;
		}
		function toggleHideShow (event){
			var cityIdx = event.target.getAttribute('ref');
			var div_id = 'tabJobBuild_cityList_' + cityIdx
			var div_el = document.getElementById(UID[div_id]);
			if (div_el.style.display == 'none') {
				div_el.style.display = 'block';
				Data.options.collapsed.build[cityIdx] = false;
			} else {
				div_el.style.display = 'none';
				Data.options.collapsed.build[cityIdx] = true;
			}
		}
		t.buildStatTick();
		t.clearTimers();
		t.buildStatTimer = setInterval (t.buildStatTick, 1000);
	},

	//----------------------------------------------------------------------------
	//*** Jobs Tab - Research Sub-tab ***
	//----------------------------------------------------------------------------
	tabJobResearch : function (){
		var t = Tabs.Jobs;	
		document.getElementById(UID[t.lastSubTab]).className ='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabJobResearch']).className ='selected';
		document.getElementById(UID['tabJobResearch']).style.zIndex=1;
		t.lastSubTab = 'tabJobResearch';

		t.contentType = 3;

		var n = '<div class=' + UID['title'] + '>'+ translate('Research') +' '+ translate('Automatically') +'</div>'
		+'<div class=' + UID['status_ticker'] + '>'
		+'	<center><input id='+ setUID('tabJobResearch_OnOff') +' type=button /></center>'
		+'	<div id='+ setUID('tabJobResearch_Report') +' class='+UID['status_report']+'></div>'
		+'	<br>'
		+'	<div id='+ setUID('tabJobResearch_Feedback') +' class='+ UID['status_feedback'] +'></div>'
		+'</div>';
		document.getElementById(UID['tabJob_Header']).style.height = "205px";
		document.getElementById(UID['tabJob_Header']).innerHTML = n;

		var m = '<div id='+ setUID('tabJobResearch_Config') +' class=' + UID['content'] + '>';
		var checkBoxs = [];
		var city = Seed.cities[CAPITAL_ID];
		m += '<div class=' + UID['subtitle'] + '>'+ city.name +'</div>'
		+'<table class=' + UID['table'] + '>';

		var i=0;
		for (var id in research_list){
			var curLvl = Seed.player.research[id] || 0;
			m += '	<tr>'
			+'			<td>'
			+'			<label>'
			+'			<input type=checkbox id='+ setUID('tabJobResearch_CB_'+id) +' '+ (Data.options.research.res_enable[0][id]?'checked':'') +' ref='+ i +' /> '
			+ translate(research_list[id]) 
			+'			</label>'
			+'			<td>'
			+'				<span class=jewel><b>'+ curLvl +'</b></span>'
			+'			</td>'
			+'			</td>'
			+'			<td>';

			var max_level = Seed.stats.research[id].level.length - 1;
			if (curLvl != max_level){
				m += '	<td>'
				+'		<select id='+ setUID('tabJobResearch_Sel_'+id) +' ref='+ i +'>'
				+'			<option value=0'+ ( curLvl>0 ?' style="display:none;"':'') +'>0</option>'
				+'			<option value=1'+ ( curLvl>1 ?' style="display:none;"':'') +'>1</option>'
				+'			<option value=2'+ ( curLvl>2 ?' style="display:none;"':'') +'>2</option>'
				+'			<option value=3'+ ( curLvl>3 ?' style="display:none;"':'') +'>3</option>'
				+'			<option value=4'+ ( curLvl>4 ?' style="display:none;"':'') +'>4</option>'
				+'			<option value=5'+ ( curLvl>5 ?' style="display:none;"':'') +'>5</option>'
				+'			<option value=6'+ ( curLvl>6 ?' style="display:none;"':'') +'>6</option>'
				+'			<option value=7'+ ( curLvl>7 ?' style="display:none;"':'') +'>7</option>'
				+'			<option value=8'+ ( curLvl>8 ?' style="display:none;"':'') +'>8</option>'
				+'			<option value=9'+ ( curLvl>9 ?' style="display:none;"':'') +'>9</option>'
				+'			<option value=10'+ ( curLvl>10 ?' style="display:none;"':'') +'>10</option>'
				+'		</select>'
				+'		</td>';
				checkBoxs.push(UID['tabJobResearch_CB_'+id]);
			} else {
				m += '	<td>Max</td>';
			}
			m += '<td id='+ setUID('tabJobResearch_FB_'+id) +' class=jewel valign=top style="width:250px;white-space:normal;"></td></tr>';  
			++i;
		}
		m += '</table></div>';
		document.getElementById(UID['tabJob_Content']).style.height = "480px";
		document.getElementById(UID['tabJob_Content']).innerHTML = m;
		for (var i=0; i < checkBoxs.length; ++i){
			document.getElementById(checkBoxs[i]).addEventListener('click', checkedResearch, false);
		}
		for (var id in research_list) {
			var selectMenu = document.getElementById(UID['tabJobResearch_Sel_' + id]);
			if (selectMenu) {
				try {
					if (!Data.options.research.res_cap[0][id]) {
						var currentResearchLevel = t.getCurrentResearchLevel(id);
						selectMenu.selectedIndex = currentResearchLevel;
						Data.options.research.res_cap[0][id] = currentResearchLevel;
					} else {
						selectMenu.selectedIndex = Data.options.research.res_cap[0][id];
						selectMenu.options[Data.options.research.res_cap[0][id]].selected = true;
						if(Data.options.research.res_enable[0][id]){
							t.checkResearchReqs(id);
						}
					}
				} catch (e) {}
				selectMenu.addEventListener('change', changeResearchCap, false);
			}
		}
		document.getElementById(UID['tabJobResearch_OnOff']).addEventListener ('click', function (){
			var t=Tabs.Jobs;
			t.setResearchEnable (!Data.options.research.enabled);
		}, false);
		t.refreshResearchButton (Data.options.research.enabled);

		function checkedResearch (event){
			var t = Tabs.Jobs;
			var n = parseInt(event.target.getAttribute('ref'));
			Data.options.research.res_enable[0][research_name[n]] = event.target.checked;
			if(Data.options.research.res_enable[0][research_name[n]]){
				t.checkResearchReqs(research_name[n]);
			}
			if (Data.options.research.enabled){
				t.researchTick();
			}
		}
		function changeResearchCap (event) {
			var t = Tabs.Jobs;
			var n = parseInt(event.target.getAttribute('ref'));
			Data.options.research.res_cap[0][research_name[n]] = event.target[event.target.selectedIndex].value;
			event.target.style.backgroundColor = '';  
			if(Data.options.research.res_enable[0][research_name[n]]){
				t.checkResearchReqs(research_name[n]);
			}
			if (Data.options.research.enabled){
				t.researchTick();
			}
		}
		t.researchStatTick();
		t.clearTimers();
		t.researchStatTimer = setInterval (t.researchStatTick, 1000);
	},

	//----------------------------------------------------------------------------
	//*** Jobs Tab - Resurrect Sub-tab ***
	//----------------------------------------------------------------------------
	tabJobResurrect : function (){
		var t = Tabs.Jobs;	
		document.getElementById(UID[t.lastSubTab]).className ='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabJobResurrect']).className ='selected';
		document.getElementById(UID['tabJobResurrect']).style.zIndex=1;
		t.lastSubTab = 'tabJobResurrect';

		t.contentType = 4;

		var n = '<div class=' + UID['title'] + '>'+ translate('Revive troops') +'</div>'
		+'<div class=' + UID['status_ticker'] + '>'
		+'	<center><input id='+ setUID('tabJobResurrect_OnOff') +' type=button /></center>'
		//+'	<div id=' + setUID('tabJobResurrect_Report') +' class='+UID['status_report']+'></div>'
		+'	<div id=' + setUID('tabJobResurrect_Report') + ' class='+ UID['status_report'] +'>'
		+'		<table id=' + setUID('tabJobResurrect_Table') + ' class=' + UID['table'] + '>'
		+'		</table>'
		+'	</div>'
		+'	<br>'
		+'	<div id='+ setUID('tabJobResurrect_Feedback') +' class='+ UID['status_feedback'] +'></div>'
		+'</div>';
		document.getElementById(UID['tabJob_Header']).style.height = "205px";
		document.getElementById(UID['tabJob_Header']).innerHTML = n;

		var m = '<div id='+ setUID('tabJobResurrect_Config') +' class=' + UID['content'] + '>';
		var sl = [];
		var city = Seed.cities[CAPITAL_ID];

		m += '<div class=' + UID['subtitle'] + '>'+ translate(Seed.cities[SPECTRAL_OUTPOST_ID].name) +'</div>'
			+'<table class=' + UID['table'] + '>'
			+'	<tr class='+UID['row_headers']+'>'
			+'		<td></td><td>'+translate('Quantity')+'</td><td>'+translate('Total souls')+'</td><td>'+translate('Total')+'</td></tr>';
		for (var i=0; i < all_unit_types.length; i++){
			var num = Data.options.resurrect.res_max[SPECTRAL_OUTPOST_ID][all_unit_types[i]];
			if (!num || isNaN(num)) num = 0;
            var souls = city.souls[all_unit_types[i]];
			if (!souls || isNaN(souls)) souls = 0;
			m += '<tr>'
			+'		<td width=25%>'
			+'			<label>'
			+'			<input type=checkbox id='+ setUID('tabJobResurrect_CB_'+i) +' '+ (Data.options.resurrect.res_enable[SPECTRAL_OUTPOST_ID][all_unit_types[i]]?'checked':'') + ' ref='+ i +' /> '
			+ translate(all_unit_types[i]) 
			+'			</label>'
			+'		</td>'
			+'		<td align=middle width=10%><input type=text id='+ setUID('tabJobResurrect_Troop_'+ i) +' ref='+ i +' maxlength=8 size=3 value="'+ num +'" style="width:60px; text-align:right;" /></td>'
			+'		<td align=right width=10%>&nbsp;'+ nombreFormate(souls,' ') +'</td>'
			+'		<td align=right width=10%>&nbsp;<span class=jewel>('+ nombreFormate(getTroopNumbers(Seed.cities[CAPITAL_ID], all_unit_types[i]).total,' ') +')</span></td>'
			+'		<td id='+ setUID('tabJobResurrect_FB_'+i) +' class=jewel valign=top style="width:250px;white-space:normal;"></td>'
			+'		</tr>';  
			sl.push(UID['tabJobResurrect_CB_'+ i]);
		}
		m += '</table></div>';
		document.getElementById(UID['tabJob_Content']).style.height = "400px";
		document.getElementById(UID['tabJob_Content']).innerHTML = m;
		for (var i=0; i < sl.length; ++i){
			document.getElementById(sl[i]).addEventListener('click', checkedResurrect, false);
		}
		for (var id=0; id < all_unit_types.length; id++) {
			var maxSouls = document.getElementById(UID['tabJobResurrect_Troop_' + id]);
			try {
				var currentSouls = city.souls[all_unit_types[id]];
				if (!currentSouls || isNaN(currentSouls)) currentSouls = 0;
				if (!Data.options.resurrect.res_max[SPECTRAL_OUTPOST_ID][all_unit_types[id]]) {
					maxSouls.value = currentSouls;
					Data.options.resurrect.res_max[SPECTRAL_OUTPOST_ID][all_unit_types[id]] = currentSouls;
				} else {
					maxSouls.value = resurrect.res_max[SPECTRAL_OUTPOST_ID][all_unit_types[id]];
					if (Data.options.resurrect.res_max[SPECTRAL_OUTPOST_ID][all_unit_types[id]]){
						var currentMax = Data.options.resurrect.res_max[SPECTRAL_OUTPOST_ID][all_unit_types[id]];
						var checkQty = (currentSouls > currentMax) ? currentMax : currentSouls;
						t.checkResurrectReqs(all_unit_types[id], checkQty);
					}
				}
			} catch (e) {}
			maxSouls.addEventListener('change', changeResurrectMax, false);
		}
		document.getElementById(UID['tabJobResurrect_OnOff']).addEventListener ('click', function (){
			var t=Tabs.Jobs;
			t.setResurrectEnable (!Data.options.resurrect.enabled);
		}, false);
		t.refreshResurrectButton (Data.options.resurrect.enabled);

		function checkedResurrect (event){
			var t = Tabs.Jobs;
			var n = parseInt(event.target.getAttribute('ref'));
			Data.options.resurrect.res_enable[SPECTRAL_OUTPOST_ID][all_unit_types[n]] = event.target.checked;

			if (Data.options.resurrect.res_enable[SPECTRAL_OUTPOST_ID][all_unit_types[n]]){
				var currentSouls = Seed.cities[CAPITAL_ID].souls[all_unit_types[n]];
				if (!currentSouls || isNaN(currentSouls)) currentSouls = 0;
				var currentMax = Data.options.resurrect.res_max[SPECTRAL_OUTPOST_ID][all_unit_types[n]];
				var checkQty = (currentSouls > currentMax) ? currentMax : currentSouls;
				t.checkResurrectReqs(all_unit_types[n], checkQty);
			} else {
				try{
					document.getElementById(UID['tabJobResurrect_FB_'+n]).innerHTML = '';
					document.getElementById(UID['tabJobResurrect_Troop_' + n]).style.backgroundColor = "none";
				} catch(e) {}
			}
			if (Data.options.resurrect.enabled){
				t.resurrectTick();
			}
		}
		function changeResurrectMax (event) {
			var t = Tabs.Jobs;
			var n = parseInt(event.target.getAttribute('ref'));
			Data.options.resurrect.res_max[SPECTRAL_OUTPOST_ID][all_unit_types[n]] = event.target.value;
			event.target.style.backgroundColor = '';

			if (Data.options.resurrect.res_enable[SPECTRAL_OUTPOST_ID][all_unit_types[n]]){
				var currentSouls = Seed.cities[CAPITAL_ID].souls[all_unit_types[n]];
				if (!currentSouls || isNaN(currentSouls)) currentSouls = 0;
				var currentMax = Data.options.resurrect.res_max[SPECTRAL_OUTPOST_ID][all_unit_types[n]];
				var checkQty = (currentSouls > currentMax) ? currentMax : currentSouls;
				t.checkResurrectReqs(all_unit_types[n], checkQty);
			}
			if (Data.options.resurrect.enabled){
				t.resurrectTick();
			}
		}
		t.resurrectStatTick();
		t.clearTimers();
		t.resurrectStatTimer = setInterval (t.resurrectStatTick, 1000);
	},

	setTrainEnable : function (onOff){
		var t = Tabs.Jobs;
		t.refreshTrainButton(onOff);
		Data.options.training.enabled = onOff;
		clearTimeout (t.trainTimer);
		if (onOff){
			t.trainTimer = setTimeout(t.trainTick, 500);
		} else {
			t.dispFeedback(""); // Erase previous feedback
		}
	},
	setBuildEnable : function (onOff){
		var t = Tabs.Jobs;
		t.refreshBuildButton(onOff);
		Data.options.building.enabled = onOff;
		clearTimeout (t.buildTimer);
		if (onOff){
			t.buildRetryTime = 20000;
			t.buildTimer = setTimeout (t.buildTick, 500);
		} else {
			t.dispFeedback("");
		}
	},
	setResearchEnable : function (onOff){
		var t = Tabs.Jobs;
		t.refreshResearchButton(onOff);
		Data.options.research.enabled = onOff;
		clearTimeout (t.researchTimer);
		if (onOff){
			t.resRetryTime = 20000;
			t.researchTimer = setTimeout(t.researchTick, 500);
		} else {
			t.dispFeedback("");
		}
	},
	setResurrectEnable : function (onOff){
		var t = Tabs.Jobs;
		t.refreshResurrectButton(onOff);
		Data.options.resurrect.enabled = onOff;
		clearTimeout (t.resurrectTimer);
		if (onOff){
			t.revRetryTime = 20000;
			t.resurrectTimer = setTimeout(t.resurrectTick, 500);
		} else {
			t.dispFeedback(""); // Erase previous feedback
		}
	},

	refreshTrainButton : function (onOff) {
		var t = Tabs.Jobs;
		var but = document.getElementById(UID['tabJobTrain_OnOff']);
		if(!but) return;
		if (onOff){
			but.value = translate('Training').toUpperCase();
			but.className = UID['btn_on'];
		} else {
			but.value = translate('Disabled').toUpperCase();
			but.className = UID['btn_off'];
		}
	},
	refreshBuildButton : function (onOff) {
		var t = Tabs.Jobs;
		var but = document.getElementById(UID['tabJobBuild_OnOff']);
		if(!but) return;
		if (onOff){
			but.value = translate('Building').toUpperCase();
			but.className = UID['btn_on'];
		} else {
			but.value = translate('Disabled').toUpperCase();
			but.className = UID['btn_off'];
		}
	},
	refreshResearchButton : function (onOff) {
		var t = Tabs.Jobs;
		var but = document.getElementById(UID['tabJobResearch_OnOff']);
		if(!but) return;
		if (onOff){
			but.value = translate('Researching').toUpperCase();
			but.className = UID['btn_on'];
		} else {
			but.value = translate('Disabled').toUpperCase();
			but.className = UID['btn_off'];
		}
	},
	refreshResurrectButton : function (onOff) {
		var t = Tabs.Jobs;
		var but = document.getElementById(UID['tabJobResurrect_OnOff']);
		if(!but) return;
		if (onOff){
			but.value = translate('Reviving').toUpperCase();
			but.className = UID['btn_on'];
		} else {
			but.value = translate('Disabled').toUpperCase();
			but.className = UID['btn_off'];
		}
	},

	trainStatTick : function (){
		var t = Tabs.Jobs;
		var statElement = document.getElementById(UID['tabJobTrain_Table']); //tabJobTrain_Report']);
		if (statElement != null){
			updateTrainTable ( statElement, 'train', false );
			//statElement.innerHTML = trainTable('train', false);
		}

		// Refresh training reqs
		for (var cityIdx=0; cityIdx < Seed.cities.length; ++cityIdx){
			if (Seed.cities[cityIdx] && cityIdx >= 0 && cityIdx < Seed.cities.length && cityIdx != SPECTRAL_OUTPOST_ID) {
				if (t.contentType == 1 && t.trainContentType == 0){
					switch (cityIdx) {
						case CAPITAL_ID			 : unitType = capital_units; break;
						case WATER_OUTPOST_ID	 : unitType = water_outpost_units; break;
						case STONE_OUTPOST_ID	 : unitType = stone_outpost_units; break;
						case FIRE_OUTPOST_ID	 : unitType = fire_outpost_units; break;
						case WIND_OUTPOST_ID	 : unitType = wind_outpost_units; break;
						case ICE_OUTPOST_ID		 : unitType = ice_outpost_units; break;
						case SWAMP_OUTPOST_ID	 : unitType = swamp_outpost_units; break;
						case FOREST_OUTPOST_ID	 : unitType = forest_outpost_units; break;
					}
					for (var uid=0; uid < unitType.length; uid++) {
						var unitQty = Data.options.training.city[cityIdx].units[uid];
						var butTrainNow = document.getElementById(UID['tabTrain_Now_'+ cityIdx +'_'+ uid]);
						if (parseIntZero(unitQty) > 0) {
							var reqs = t.checkTrainReqs(unitType[uid], unitQty, cityIdx);
							if (!reqs.msg) setButtonStyle (butTrainNow, true);
							else setButtonStyle (butTrainNow, false);
						} else {
							setButtonStyle (butTrainNow, false);
						}
					}
				}
			}
		}
		// End Refresh building reqs
		function setButtonStyle (button, enabled) {
			if (enabled) {
				button.disabled = false;
				Element.removeClassName(button, UID['bnt_disabled']);
				Element.addClassName(button, UID['bnt_green']);
			} else {
				button.disabled = true;
				Element.removeClassName(button, UID['bnt_green']);
				Element.addClassName(button, UID['bnt_disabled']);
			}
		}
	},
	resurrectStatTick : function (){
		var t = Tabs.Jobs;
		var statElement = document.getElementById(UID['tabJobResurrect_Table']); //tabJobResurrect_Report']);
		if (statElement != null){
			updateTrainTable ( statElement, 'resurrect', true );
//			statElement.innerHTML = trainTable('resurrect', true);
		}
	},

	// Build statistics - timer set to fire every 1 seconds
	buildStatFetch : false,
	buildStatTick : function (){
		var t = Tabs.Jobs;
		var m = '<TABLE class=' + UID['table'] + '>';

		for (var cityIdx=0; cityIdx < Seed.cities.length; ++cityIdx){
			if (Seed.cities[cityIdx]) {
				var city = Seed.cities[cityIdx];
				var job = getBuildJob (cityIdx);
				var options = {noPlayer:true,cities:[]};
				m += '<TR><TD width=20%>'+ ( (cityIdx == CAPITAL_ID) ? city.name : translate(city.name) ) + '</td><TD>';

				if (job == null){
					m += translate('Idle') +'</td></tr>';
				} else {
					var b = Buildings.getById(cityIdx, job.city_building_id);
					var timeRemaining = ((job.run_at - serverTime()) > 0) ? timestr(job.run_at - serverTime()) : 0;
					if (timeRemaining == 0) {
						// If we have a job and the timeRemaining is negative or zero we delete the job
						// and fetch the Seed - although this does not always work because the server
						// is laggy and may not return the correct information
						m += translate('Awaiting task completion notification') + '...</td><td></td><td></td></tr>';
						deleteBuildJob (cityIdx, job);
						if (t.buildStatFetch == false) {
							if (cityIdx != 0) {
								options.cities.push(Seed.cities[CAPITAL_ID].id);
							}
							options.cities.push(city.id);
							Seed.fetchPlayer (options);
							t.buildStatFetch = true;
						}
					} else {
						m += '<b>' + translate('Building') +':</b> </td>'
						+' <td width=40%> '+ translate(b.type) + '  ('+ job.level +') </td>'
						+' <td width=40%> <font color='+TIMER_COLOR+'>'+ timeRemaining  +'</font></td></tr>';
						t.buildStatFetch = false;
						try {
							document.getElementById(UID['tabJobBuild_FB_'+cityIdx+'_'+b.type]).innerHTML = '<font color=#000>' + translate('Building') + ': ' + translate(b.type) + ' ' + translate('Level').toLowerCase() + ' ' + job.level + '</font>';
						} catch(e) {}
					}
				}
				// Refresh building reqs
				if (t.contentType == 2){
					var buildList;
					switch (cityIdx) {
						case CAPITAL_ID : buildList = capital_buildings.concat(field_buildings); break;
						case SPECTRAL_OUTPOST_ID : buildList = spectral_buildings.concat(spectral_fields); break;
						default : buildList = outpost_buildings.concat(field_buildings); break;
					}
					for (var i=0; i < buildList.length; ++i) {
						if (Data.options.building.level_enable[cityIdx][buildList[i]])
							t.checkBuildReqs(cityIdx, buildList[i]);
					}
				}
			}
		}
		document.getElementById(UID['tabJobBuild_Report']).innerHTML = m +'</table>';
	},

	// Build statistics - timer set to fire every 1 seconds
	resStatFetch : false,
	researchStatTick : function (){
		var t = Tabs.Jobs, m = '<table class=' + UID['table'] + '>', city = Seed.cities[CAPITAL_ID];
		var job = getResearchJob (0);

		m += '<tr><td width=20%>'+ city.name + '</td><td>';
		if (job == null){
			m += translate('Idle') +'</td></tr>';
		} else {
			var timeRemaining = ((job.run_at - serverTime()) > 0) ? timestr(job.run_at - serverTime()) : 0;
			if (timeRemaining == 0) {
				m += translate('Awaiting task completion notification') + '...</td><td></td><td></td></tr>';
				deleteResearchJob(job);
				if (t.resStatFetch == false) {
					Seed.fetchPlayer( {cities:[city.id]} );
					t.resStatFetch = true;
				}
			} else {
				// Bug: If we have a job and the timeRemaining is negative or zero we should delete the job
				m += '<b> '+ translate('Researching') +': </b> </td>'
				  +' <td width=50%> '+ translate(t.resUITranslate(job.research_type)) +' ('+ job.level +') </td><td width=30%>  <font color='+TIMER_COLOR+'>'+ timeRemaining  +'</font></td></tr>';
				t.resStatFetch = false;
			}
		}
		document.getElementById(UID['tabJobResearch_Report']).innerHTML = m +'</table>';
		try{
			document.getElementById(UID['tabJobResearch_FB_'+job.research_type]).innerHTML = '<font color=#000>' + translate('Researching') + '&nbsp;' + translate('Level').toLowerCase() + '&nbsp;' + job.level + '</font>';
		} catch(e) {}
	},

	dispFeedback : function (msg){
		var t = Tabs.Jobs;
		var elementId = '';   

		switch(t.contentType) {
			case 0: break;
			case 1: elementId = 'tabJobTrain_Feedback'; break;
			case 2: elementId = 'tabJobBuild_Feedback'; break;
			case 3: elementId = 'tabJobResearch_Feedback'; break;
			case 4: elementId = 'tabJobResurrect_Feedback'; break;
		} 
		if (elementId && document.getElementById(UID[elementId])){
			if (msg == ''){
				document.getElementById(UID[elementId]).innerHTML = msg; 
			} else {
				document.getElementById(UID[elementId]).innerHTML = new Date().toTimeString().substring (0,8) +'&nbsp;'+  msg;
			}
		}
	},
	getCurrentResearchLevel : function (researchType){
		var t = Tabs.Jobs, level = 0;
		try {
			if (researchType == 'Rapid Deployment')		researchType = 'RapidDeployment';
			if (researchType == 'Weapons Calibration')	researchType = 'Ballistics';
			if (researchType == 'Aerial Combat')		researchType = 'AerialCombat';
			level = (Seed.player.research[researchType]) ? Seed.player.research[researchType] : 0; 
		} catch (e) {}  
		return level;
	},
	getTroopCap : function(troopType, qty){
		var t = Tabs.Jobs;
		var cap = 0;
		var completedTroops = 0;
		var defenseTroops = 0;
		var marchingTroops = 0;
		var trainingTroops = 0;

		// Get the cap set for this troop type
		for (var i=0; i < all_trainable_units.length;i++){
			if (troopType == all_trainable_units[i]) {
				cap = Data.options.training.city[0].cap[i];
				break;
			}
		}
		// If there is no cap, we are done
		if (cap == 0){
			return cap;
		}
		// Find the number of troops still in the city  
		completedTroops += (Seed.cities[CAPITAL_ID].units[troopType] != undefined) ? Seed.cities[CAPITAL_ID].units[troopType] : 0;
		// Find the number of troops present in defense forces
		if (Seed.cities[CAPITAL_ID].defense_force && Seed.cities[CAPITAL_ID].defense_force[troopType])
			defenseTroops += (Seed.cities[CAPITAL_ID].defense_force[troopType] != undefined) ? Seed.cities[CAPITAL_ID].defense_force[troopType] : 0;

		// Find additional troops in marches
		for (var p in Seed.marches) {
			for (var q in Seed.marches[p].units){
				if (q == troopType){
					marchingTroops += Seed.marches[p].units[q];
				}
			}
		}
		var now = serverTime();
		for (var cityIdx=0; cityIdx < Seed.cities.length; ++cityIdx) {
			if (Seed.cities[cityIdx] && Seed.cities[cityIdx].jobs) {
				var jobs = Seed.cities[cityIdx].jobs;
				for (var j=0; j < jobs.length; j++) {
					if (jobs[j].queue == 'units' && jobs[j].unit_type == troopType && jobs[j].run_at > now)
						trainingTroops += jobs[j].quantity;
				}
			}
		}
		return ((completedTroops + defenseTroops + marchingTroops + trainingTroops + qty) > cap) ? (completedTroops + defenseTroops + marchingTroops + trainingTroops + qty) : 0;
	},
	getBuildingCap : function (cityIdx, buildingType){
		var t = Tabs.Jobs;
		var cap = 0;

		var cityType;
		switch (cityIdx) {
			case CAPITAL_ID : cityType = capital_buildings.concat(field_buildings); break;
			case SPECTRAL_OUTPOST_ID : cityType = spectral_buildings.concat(spectral_fields); break;
			default : cityType = outpost_buildings.concat(field_buildings); break;
		}
		for (var i=0; i < cityType.length; ++i) {
			if (cityType[i] == buildingType) {
				try {
					cap = (Data.options.building.level_cap[cityIdx][i]) ? Data.options.building.level_cap[cityIdx][i] : 0; 
					break;
				} catch (e) {}  
			}
		}
		return cap;
	},
	getResearchCap : function (researchType){
		var t = Tabs.Jobs;
		var cap = 0;

		for (var id in research_list) {
			if (researchType == id) {
				try {
					cap = (Data.options.research.res_cap[0][id]) ? Data.options.research.res_cap[0][id] : 0; 
					break;
				} catch (e) {}  
			}
		}
		return cap;
	},
	resUITranslate : function (researchType){
		var t = Tabs.Jobs;
		for (var id in research_list){
			if (id == researchType){
				return research_list[id];
			}
		}
		return researchType;
	},
	getBuildingLevel : function(cityIdx, buildingType, buildingLevel){
		var buildings = Seed.cities[cityIdx].buildings;
		var ret = 0;
		for (var p=0; p < buildings.length;p++) {
			if (buildings[p].type == buildingType && buildings[p].level >= buildingLevel){
				ret = buildings[p].level;
				break;
			}
		}
		return ret;
	},
	getRemainingQueue : function (ic, queueType, resurrect){
		var city = Seed.cities[ic];
		var jobs = city.jobs;
		var maxQueueLength = (resurrect) ? city.figures.queue_lengths.resurrection : city.figures.queue_lengths.units;
		var usedQueue = 0;
		//Check if max_queue_length is a number and not 0) 
		if (isNaN(maxQueueLength) || !maxQueueLength) {  
			return 0;
		}
		// Count the number of jobs in the queue
		for (var i=0; i<jobs.length; i++) {
			if (jobs[i].queue == queueType){
				++usedQueue;
			}
		}
		return maxQueueLength - usedQueue;
	},

	checkRequirements : function ( options ) {
		var reqs = {};

		// options.unit_type and options_training_type are the same,
		// we can use either interchangeably
		var element_type =  options.unit_type     || 
							options.training_type || 
							options.building_type || 
							options.research_type;
		var requirements = Seed.requirements[ options.reqs_type ][ element_type ];
		var stats = Seed.stats[ options.reqs_type ][ element_type ];

		// in case of level
		if (typeof (options.level) !== 'undefined' ) {
			requirements = requirements.level[options.level];
			stats = stats.level[options.level];
		}
		// if omitted options.city_idx, use the capital, city_idx = 0
		// this value is only used by requirements.buildings case
		var city_idx = options.city_idx || CAPITAL_ID;
		//always use the capital data to verify the resources and the population
		var city = Seed.cities[CAPITAL_ID];
		// If we are verifying unit requirements, initialize the variable max_units
		if ( options.unit_type || options.reqs_type == 'units' )
			reqs.max_units = 999999999;

		// set Speed Multiplier for every case
		var speed_multiplier = 1;
		switch (options.reqs_type) {
			case 'unit' :
				// Calculate speed_multiplier for the trainings based on garrisons / training camps of the city for which we check the training requirements
				speed_multiplier = 0;
				if (Seed.cities[city_idx] && city_idx != SPECTRAL_OUTPOST_ID) {
					var build_type = ( city_idx == CAPITAL_ID ? 'Garrison' : 'TrainingCamp' );
					for (var j = 0; j < Seed.cities[city_idx].buildings.length; j++) {
						if (Seed.cities[city_idx].buildings[j].type === build_type)
							speed_multiplier += (1 + (Seed.cities[city_idx].buildings[j].level-1)/10);
					}
				}
				if (options.unit_type == kBattleDragon || options.unit_type == kSwiftStrikeDragon) {
					var rookery_multiplier = (Buildings.getLevel(CAPITAL_ID, 'Rookery')).max * 4 / 100;
//logit('city Idx = '+city_idx+', troop = '+options.unit_type+', time = '+stats.time+', rookery multiplier = '+rookery_multiplier+' / Speed multiplier = '+speed_multiplier+' => '+ ((1 + rookery_multiplier) * speed_multiplier));
					speed_multiplier = (1 + rookery_multiplier) * speed_multiplier;
				}
				break;
			case 'building'	: speed_multiplier = city.figures.building.speed_multiplier; break;
		}
		// Set time needed for this task
		reqs.time = parseInt( stats.time / speed_multiplier );

		// when omitted options.unit_quantity, sets unit_quantity to 1 to check the requirements of the buildings and research.
		var unit_quantity = options.unit_quantity || 1;

		// Check Buildings requirements
		if (requirements.buildings) {
			for (var type in requirements.buildings) {
				var fixed_type = type;
				// we change the type of build Garrison to TrainingCamp in case of outpost city
				if (city_idx != CAPITAL_ID && type == 'Garrison')
					fixed_type = 'TrainingCamp';
				var fixed_city_idx = ( /Science|Metal|Officer|Rookery|Storage|Theater|Sentinel|Factory|Fortress/.test(fixed_type) ? CAPITAL_ID : city_idx);
				var level = Buildings.getLevel(fixed_city_idx, fixed_type);
				if (level.max < requirements.buildings[type]) {
					if (!reqs.buildings) reqs.buildings = {};
					reqs.buildings[fixed_type] = requirements.buildings[type];
					reqs.msg = (reqs.msg||'') + translate(fixed_type) + '(' + reqs.buildings[fixed_type] + ')' + ' + ';
				}
			}
		}

		// Check Items requirements
		if (requirements.items) {
			for (var type in requirements.items) {
				var need = requirements.items[type] * unit_quantity;
				var have = parseInt(Seed.player.items[type] || 0);
				if (have < need) {
					if (!reqs.items) reqs.items = {};
					reqs.items[type] = need - have; //requirements.items[type];
					reqs.msg = (reqs.msg||'') + translate(type) + '(' + nombreFormate(reqs.items[type],' ') + ')' + ' + ';
				}
				// If we are verifying unit requirements, calculate the maximum units
				if (reqs.max_units) {
					var current_max = parseInt( have / requirements.items[type] );
					if (reqs.max_units > current_max) {
						reqs.max_units = current_max;
					}
				}
			}
		}

		// Check Population requirements
		if (requirements.population && requirements.population.idle) {
			var need = requirements.population.idle * unit_quantity;
			var have = city.figures.population.current - city.figures.population.laborers - city.figures.population.armed_forces;
			have = (have > 0) ? have : 0;
			if (have < need) {
				reqs.population =  need - have;
				reqs.msg = (reqs.msg||'') + translate('Population') + ':' + nombreFormate(reqs.population,' ') + ' + ';
			}
			// If we are verifying unit requirements, calculate the maximum units
			if (reqs.max_units) {
				var current_max = parseInt( (have+1) / requirements.population.idle );
				if (reqs.max_units > current_max) {
					reqs.max_units = current_max;
				}
			}
		}

		// Check Research requirements
		if (requirements.research) {
			for (var type in requirements.research) {
				if (Seed.player.research[type] < requirements.research[type]) {
					if (!reqs.research) reqs.research = {};
					reqs.research[type] = requirements.research[type];
					reqs.msg = (reqs.msg||'') + translate(type) + '(' + reqs.research[type] + ')' + ' + ';
				}
			}
		}

		// Check Resources requirements
		if (requirements.resources) {
			for (var type in requirements.resources) {
				if (requirements.resources[type] == 0)
					continue;

				var need = requirements.resources[type] * unit_quantity;
				var have = parseInt(city.resources[type] || 0);
				if (have < need) {
					if (!reqs.resources) reqs.resources = {};
					reqs.resources[type] = need - have;
					reqs.msg = (reqs.msg||'') + translate(type) + ':' + nombreFormate(reqs.resources[type],' ') + ' + ';
				}
				// If we are verifying unit requirements, calculate the maximum units
				if (reqs.max_units) {
					var current_max = parseInt( (have+1) / requirements.resources[type] );
					if (reqs.max_units > current_max) {
						reqs.max_units = current_max;
					}
				}
			}
		}

		// Set time needed for this units task based in quantity
		if (reqs.max_units)
			reqs.time = parseInt( (options.unit_quantity || 0) * stats.time / speed_multiplier );
		if (reqs.msg)
			reqs.msg = reqs.msg.substring(0,reqs.msg.length-3);
		return reqs;
	},
	checkTrainReqs : function (troopType, troopQty, cityIdx) {
		var t = Tabs.Jobs;

		var reqs = t.checkRequirements ({
			reqs_type     : 'unit', 
			city_idx      : cityIdx, 
			unit_type     : troopType, 
			unit_quantity : troopQty
		});
		// Check Remaining Queue
		if ( t.getRemainingQueue(cityIdx, 'units', false) == 0 )
			reqs.queue = true;
		// Check Units Cap
		var capped = t.getTroopCap(troopType, troopQty);
		if (capped) {
			reqs.capped = capped;
			reqs.msg = translate('Production limit reached') + ' + ';
		}
		if (t.contentType == 1){
			if (reqs.msg) {
				try{
					document.getElementById(UID['tabJobTrain_FB_' + cityIdx +'_'+ troopType]).innerHTML ='<font color="#C33">'+ reqs.msg.replace(/:\+/,':').replace(/\+\s*$/,'') +'</font>';
					document.getElementById(UID['tabJobTrain_FB_' + cityIdx +'_'+ troopType]).title = translate(troopType) + ' ' + reqs.msg.replace(/\+/g,' \n');
					document.getElementById(UID['tabJobBuild_Cap_' + cityIdx +'_'+ troopType]).style.color = "#C33";
				} catch(e) {}
			} else {
				try{
					var fb_text = translate('Max') + ' : ' + nombreFormate(reqs.max_units,' ') + ' (' + timestrShort(reqs.time) + ')';
					document.getElementById(UID['tabJobTrain_FB_' + cityIdx +'_'+ troopType]).innerHTML = fb_text;
					document.getElementById(UID['tabJobTrain_FB_' + cityIdx +'_'+ troopType]).title = translate(troopType) + ' \n' + fb_text;
				} catch(e) {}
			}
		}
		return reqs;
	},
	checkBuildReqs : function(cityIdx, buildingType){
		var t = Tabs.Jobs;
		var level = ( Buildings.getLevel(cityIdx, buildingType) ).min + 1;
		var cap = t.getBuildingCap (cityIdx, buildingType);
		if (level <= cap) {
			var reqs = t.checkRequirements ({
				reqs_type     : 'building', 
				city_idx      : cityIdx, 
				building_type : buildingType,
				level         : level
			});

			if (reqs.msg) {
				if (t.contentType == 2){
					try{
						document.getElementById(UID['tabJobBuild_FB_' + cityIdx +'_'+ buildingType]).innerHTML ='<font color="#C33">'+ reqs.msg.replace(/:\+/,':').replace(/\+\s*$/,'') +'</font>';
						document.getElementById(UID['tabJobBuild_FB_' + cityIdx +'_'+ buildingType]).title = translate(buildingType) + ' ' + reqs.msg.replace(/\+/g,' \n');
						document.getElementById(UID['tabJobBuild_Cap_' + cityIdx +'_'+ buildingType]).style.color = "#C33";
					} catch(e) {}
				}
			} else {
				if (t.contentType == 2){
					try{
						var fb_text = translate('Next level') + ' ' + translate('OK');
						document.getElementById(UID['tabJobBuild_FB_' + cityIdx +'_'+ buildingType]).innerHTML = fb_text;
						document.getElementById(UID['tabJobBuild_FB_' + cityIdx +'_'+ buildingType]).title = translate(buildingType) + ' \n' + fb_text;
					} catch(e) {}
				}
			}
			return reqs;
		} else {
			if (t.contentType == 2){
				try{
					var fb_text = translate('Task Completed');
					document.getElementById(UID['tabJobBuild_FB_'+ cityIdx +'_'+ buildingType]).innerHTML = '<font color=#0B0>'+ fb_text +'</font>';
					document.getElementById(UID['tabJobBuild_FB_' + cityIdx +'_'+ buildingType]).title = translate(buildingType) + ' \n' + fb_text;
					document.getElementById(UID['tabJobBuild_Cap_' + cityIdx +'_'+ buildingType]).style.color = "#5B5";
				} catch(e) {}
			}
		}
		return ({ capped:true, msg:translate('Maximum level reached')});
	},
	checkResearchReqs : function (researchType){
		var t = Tabs.Jobs;
		var level =  t.getCurrentResearchLevel (researchType)+1;
		var cap = t.getResearchCap (researchType);
		if (level <= cap) {
			var reqs = t.checkRequirements ({
				reqs_type     : 'research', 
				research_type : researchType,
				level         : level
			});

			if (reqs.msg) {
				if (t.contentType == 3){
					try {
						document.getElementById(UID['tabJobResearch_FB_'+researchType]).innerHTML = '<font color=#C33>' + reqs.msg.replace(/:\+/,':').replace(/\+\s*$/,'') + '</font>';
						document.getElementById(UID['tabJobResearch_FB_'+researchType]).title = translate(researchType) + ' ' + reqs.msg.replace(/\+/g,' \n');
						document.getElementById(UID['tabJobResearch_Sel_' + researchType]).style.color = "#C33";
					} catch(e){}
				}
			} else {
				if (t.contentType == 3){
					try {
						var fb_text = translate('Next level') + ' ' + translate('OK');
						document.getElementById(UID['tabJobResearch_FB_'+researchType]).innerHTML = fb_text;
						document.getElementById(UID['tabJobResearch_FB_'+researchType]).title = translate(researchType) + ' \n' + fb_text;
					} catch(e){}
				}
			}
			return reqs;
		} else {
			if (t.contentType == 3){
				try {
					var fb_text = translate('Task Completed');
					document.getElementById(UID['tabJobResearch_FB_'+researchType]).innerHTML = '<font color=#0B0>'+ fb_text +'</font>';
					document.getElementById(UID['tabJobResearch_FB_'+researchType]) = translate(researchType) + ' \n' + fb_text;
					document.getElementById(UID['tabJobResearch_Sel_' + researchType]).style.color = "#5B5";
				} catch(e){}
			}
		}
		return ({capped:true, msg:translate('Maximum level reached')});
	},
	checkResurrectReqs : function(troopType, troopQty) {
		var t = Tabs.Jobs;
		if (t.contentType == 3){
			try {
				document.getElementById(UID['tabJobResurrect_FB_'+id_found]).innerHTML = '';
				document.getElementById(UID['tabJobResurrect_Troop_' + id_found]).style.backgroundColor = "none";
			} catch(e){}
		}

		switch (troopType) {
			case kPorter		: per_unit=5; darkPortal=1; break;
			case kConscript		: per_unit=5; darkPortal=1; break;
			case kSpy			: per_unit=5; darkPortal=2; break;
			case kHalberdsman	: per_unit=5; darkPortal=2; break;
			case kMinotaur		: per_unit=7; darkPortal=3; break;
			case kLongbowman	: per_unit=7; darkPortal=4; break;
			case kSwiftStrikeDragon	: per_unit=7; darkPortal=5; break;
			case kArmoredTransport	: per_unit=7; darkPortal=6; break;
			case kBattleDragon	: per_unit=10; darkPortal=7; break;
			case kGiant			: per_unit=10; darkPortal=8; break;
			case kFireMirror	: per_unit=10; darkPortal=9; break;
			case kAquaTroop		: per_unit=15; darkPortal=10; break;
			case kStoneTroop	: per_unit=15; darkPortal=10; break;
			case kFireTroop		: per_unit=15; darkPortal=10; break;
			case kWindTroop		: per_unit=15; darkPortal=10; break;
			case kIceTroop		: per_unit=15; darkPortal=10; break;
			case kSwampTroop	: per_unit=15; darkPortal=10; break;
			case kPackDragon	: per_unit=15; darkPortal=6; break;
			case kFrostGiant	: per_unit=15; darkPortal=10; break;
			case kForestTroop	: per_unit=15; darkPortal=10; break;
		}
		var blue_energy = troopQty * per_unit;
		var darkPortalLevel = darkPortal;
		var city = Seed.cities[CAPITAL_ID];
		try {
			var seedReqs = Seed.requirements.resurrect[troopType];
			var statReqs = Seed.stats.resurrect[troopType];
			blue_energy = troopQty * seedReqs.resources['blue_energy'];
			darkPortalLevel = seedReqs.buildings[kDarkPortal];
		} catch (e) {
			actionLog('<B>' + translate('Training') + '</B>: ' + e.msg + ' ' + translate('Manifest not available, using defaults'));
		}

		var m = '';
		var n = ' : ';
		var ret = {trainable:false, msg:[]};

		// Returns zero or the building level
		if (city.resources.blue_energy < blue_energy) m += translate('Blue energy') +': '+ (blue_energy - city.resources.blue_energy) +' + ';
		var availableSouls = city.souls[troopType];
		availableSouls = (availableSouls > 0) ? availableSouls : 0;
		if (availableSouls == 0) m += translate('Souls') +' + ';   // availableSouls < troopQty
		if (t.getBuildingLevel(SPECTRAL_OUTPOST_ID, kDarkPortal, darkPortalLevel) == 0) m += translate(kDarkPortal) +': '+ darkPortalLevel +' + ';
		if (t.getRemainingQueue(SPECTRAL_OUTPOST_ID, 'resurrection', true) == 0) m+= translate('Resurrection queue') + ' ';
		if (m.length == 0) {
			ret.trainable = true;
			ret.msg = troopQty +' '+ translate(troopType);
		} else {
			ret.trainable = false;
			ret.msg = n + m;
		}

		var id_found = undefined;
		for (var i=0; i < all_unit_types.length && id_found == undefined; i++){
			if (all_unit_types[i] == troopType) {
				id_found = i;
			}
		}
		if (ret.trainable == false) {
			if (t.contentType == 4){
				try{
					document.getElementById(UID['tabJobResurrect_FB_'+id_found]).innerHTML = '<font color=#C33>' + ret.msg.replace(/:\+/,':').replace(/\+\s*$/,'') + '</font>';
					document.getElementById(UID['tabJobResurrect_FB_'+id_found]).title = translate(all_unit_types[id_found]) + ' ' + ret.msg.replace(/\+/g,' \n');
					document.getElementById(UID['tabJobResurrect_Troop_' + id_found]).style.backgroundColor = "#C33";
				} catch(e) {}
			}
		} else {
			// Calculate speed_multiplier for the revival based on dark portals of the spectral ruins
			var speed_multiplier = 0;
			if (Seed.cities[SPECTRAL_OUTPOST_ID]) {
				for (var j = 0; j < Seed.cities[SPECTRAL_OUTPOST_ID].buildings.length; j++) {
					if (Seed.cities[SPECTRAL_OUTPOST_ID].buildings[j].type == kDarkPortal)
						speed_multiplier += (1 + (Seed.cities[SPECTRAL_OUTPOST_ID].buildings[j].level-1)/10);
				}
			}
			var time = parseInt( troopQty * statReqs.time * (15 / 100) / speed_multiplier );
			if (t.contentType == 4){
				try{
					var fb_text = translate('Revival') + ' allowed : ' + translate('OK') + ' (' + timestrShort(time) + ')';
					document.getElementById(UID['tabJobResurrect_FB_'+id_found]).innerHTML = fb_text;
					document.getElementById(UID['tabJobResurrect_FB_'+id_found]).title = translate(all_unit_types[id_found]) + ' \n' + fb_text;
				} catch(e) {}
			}
		}
		return ret;
	},

	// The training heartbeat
	trainTick : function (){
		var t = Tabs.Jobs;

		if (!Data.options.training.enabled){
			return;
		}
		clearTimeout (t.trainTimer);
		// If a refresh of the capital city data is enqueued or running, then skip everything.
		// troops will be queued for training after the refresh completed
		if (Seed.refresh_cities[CAPITAL_ID])
			var doRecheck = false;
		else
			var doRecheck = true;

		var options = {noPlayer:true};
		var cityList = getTotTrainTable ();
		// For all cities, sorted by training queues total time, in ascending order (we deal with the city that will complete its queues first)
		for (var x = 0; x < cityList.length && doRecheck; x++) {
			var trainQueued = false;
			var cityIdx = cityList[x].cityIdx;
			if (cityIdx != undefined && !isNaN( cityIdx ) && cityIdx >= 0 && cityIdx < Seed.cities.length && cityIdx != SPECTRAL_OUTPOST_ID &&
				Data.options.training.city[cityIdx].enabled) {
				// The length here is the number of troop types it is possible to train
				switch (cityIdx) {
					case CAPITAL_ID			 : troopsLength = capital_units.length; break;
					case WATER_OUTPOST_ID	 : troopsLength = water_outpost_units.length; break;
					case STONE_OUTPOST_ID	 : troopsLength = stone_outpost_units.length; break;
					case FIRE_OUTPOST_ID	 : troopsLength = fire_outpost_units.length; break;
					case WIND_OUTPOST_ID	 : troopsLength = wind_outpost_units.length; break;
					case ICE_OUTPOST_ID		 : troopsLength = ice_outpost_units.length; break;
					case SWAMP_OUTPOST_ID	 : troopsLength = swamp_outpost_units.length; break;
					case FOREST_OUTPOST_ID	 : troopsLength = forest_outpost_units.length; break;
				}
				// Only check the job queue if we are in short queue mode
				if (t.selectedQ == 'min_housing'){
					if (!getTrainJob (cityIdx) || getTrainJob (cityIdx) == null) {
						trainQueued = t.attemptTrainQ(cityIdx, 0, troopsLength, true);
					}
				} else {
					trainQueued = t.attemptTrainQ(cityIdx, 0, troopsLength, false);
				}
				if (trainQueued) {
					doRecheck = false; // Troops have been queued. 
				} else {
					if (!options.cities) {
						options.cities = [];
					}
					options.cities.push(Seed.cities[cityIdx].id);
				}
			}
		}
//		if (doRecheck) {
//			verboseLog('Tabs.Job.Train doRecheck');
//			Seed.fetchPlayer(options);
//			//due to error wait 20seconds then check the city again.
//			clearTimeout (t.trainTimer);
//			t.trainTimer = setTimeout ( t.trainTick, t.trainRetryTime);
//		} else {
			t.trainTimer = setTimeout ( t.trainTick, Math.randRange(5000, 10000));
//		}
	},

	// Build heartbeat
	buildTick : function (){
		var t = Tabs.Jobs;

		if (!Data.options.building.enabled){
			return;
		}
		clearTimeout (t.buildTimer);

		var recheck_build = false;
		var options = {noPlayer:true, cities:[]};
		// Iterate over the cities for buildings in each
		for (var cityIdx=0; cityIdx < Seed.cities.length; ++cityIdx ){
			if (Seed.cities[cityIdx]){
				var bJob = getBuildJob (cityIdx);
				var city = Seed.cities[cityIdx];
				var cityId = city.id;

				if (bJob == null){     // city not currently building

					// Yes, is there a job in persistent data in in this city?
					for (var i=0; i < Data.options.tJobs.length; i++) {
						if (Data.options.tJobs[i].city_id == cityId) {
							// We check three different modes of completion:
							// 1. the done flag
							// 2. the duration
							// 3. the run_at + duration compared to serverTime()
							if ( Data.options.tJobs[i].done ||
								(Data.options.tJobs[i].duration && Data.options.tJobs[i].run_at &&
								 Data.options.tJobs[i].run_at + Data.options.tJobs[i].duration < serverTime() ) ){
									Data.options.tJobs.splice(i,1);
								//	if (!options.cities)
								//		options.cities = [];
									// if job not at capital city check capital city as well as outpost.
								//	if (cityIdx !== CAPITAL_ID)
								//		options.cities.push(Seed.cities[CAPITAL_ID].id);
								//	options.cities.push(city.id);
								//	Seed.fetchPlayer ( options );
								//	t.buildTimer = setTimeout (t.buildTick, 4000);
								//	return;
							}
						}
					}  

					var buildOrder = []; // Concatenated array of buildings
					var buildList = [];
					for (var name in Data.options.building.level_enable[cityIdx]){
						// Is this building type enabled for autobuild?
						if (Data.options.building.level_enable[cityIdx][name]){
							buildList = Buildings.getList (cityIdx, name);
							buildList.sort (function(a,b){return a.level-b.level});
							buildOrder = buildOrder.concat (buildList);
						}
					}
					buildOrder.sort (function(a,b){return a.level-b.level});

					// Change: we want to iterate over each buildings comparing the level to the cap. If the cap has not
					// been reached, call doBuild
					var bBuilt = false;
					var bBuildable = false;
					var totalCapped = 0;
					for (var i=0; i < buildOrder.length && !bBuilt; i++) {
						var reqs = t.checkBuildReqs(cityIdx, buildOrder[i].type);
						if (reqs) {
							bBuildable = true;
							if (t.contentType == 2){
								t.dispFeedback (reqs.msg);
							}
							if (!reqs.msg) {
								t.doBuild (buildOrder[i], city);
								bBuilt = true;
								Data.options.tJobs.push(buildOrder[i]);
								return;
							} else {
								if (t.contentType == 2){
									t.dispFeedback (buildOrder[i].type +' '+ reqs.msg);
								}
								if (reqs.capped) ++totalCapped;
							}
						}
					}
					if (!bBuilt && bBuildable && (buildOrder.length - totalCapped > 0))
						recheck_build = true;
				} else {
					// We have a job running
					// Look at the job record
					if (bJob) {
						var jFound = false;
						// Look for the job in our persistent data
						for (var i=0; i < Data.options.tJobs.length && !jFound; i++) {
							if (bJob.city_building_id == Data.options.tJobs[i].city_building_id) {
								jFound = true;
							}   
						}
						// If the job is not in persistent data, put it there
						if (!jFound) {
							Data.options.tJobs.push(bJob);
							consoleLog(translate('Putting build job in persistent data'));
						} else {
							// Keep a consistent display                
							var bType = getBuildingById (cityIdx, bJob.city_building_id);
							var msg = translate('Building') + ': ' + translate(bType) + ' ' + translate('Level').toLowerCase() + ' ' + bJob.level +' '+ translate('at') + ' ' + translate(city.type);
							if (t.contentType == 2){
								t.dispFeedback (msg);
							}
						}
					}
				}
			}
		}
		if (recheck_build) {
			//Seed.fetchPlayer(options);
			t.buildRetryTime *= 1.5;
			if (t.contentType == 2){
				t.dispFeedback (translate('Completion errors') +': '+ translate('Retry in')+ ' '+ timestr(t.buildRetryTime/1000) +' '+ translate('seconds')); 
			}
			t.buildTimer = setTimeout (t.buildTick, t.buildRetryTime);
			return;              
		}      
		t.buildTimer = setTimeout (t.buildTick, 5000);
	},

	// Research heartbeat
	researchTick : function (){
		var t = Tabs.Jobs;

		if (!Data.options.research.enabled){
			return;
		}
		clearTimeout (t.researchTimer);

		var recheck_research = false;
		var rJob = getResearchJob(0);
		var city = Seed.cities[CAPITAL_ID];
		var cityId = city.id;

		if (rJob == null){     // no research being done yet
			// Is there a research job in persistent data?
			for (var i=0; i < Data.options.rJobs.length; i++) {
				if (Data.options.rJobs[i]) {
					if ( Data.options.rJobs[i].done ||
						(Data.options.rJobs[i].duration && Data.options.rJobs[i].run_at &&
						Data.options.rJobs[i].run_at + Data.options.rJobs[i].duration > serverTime() ) ){
							// Yes, has the job completed?
							Data.options.rJobs.splice(i,1);
							//Seed.fetchPlayer({cities:[cityId]});
							//t.researchTimer = setTimeout (t.researchTick, 5000);
							//return;
					}
				}
			}
			var toResearch = 0;
			for (var researchType in research_list) {
				if(Data.options.research.res_enable[0][researchType]==undefined){
					continue;
				}
				if (Data.options.research.res_enable[0][researchType] == true){
					var level = t.getCurrentResearchLevel (researchType) + 1;
					var reqs = t.checkResearchReqs (researchType);
					var rBuilt = false;
					if (reqs) {
						if (!reqs.msg) {
							t.doResearch(researchType, level);
							rBuilt = true;
							Data.options.rJobs.push(rJob);
							break;
						} else {
							if (t.contentType == 3){
								t.dispFeedback (researchType +' '+ reqs.msg);
							}
							++toResearch;
						}
					}
				}
			}
			if ( rBuilt === false && toResearch )
				recheck_research = true;
		} else {
			// We have a job running
			// Look at the record
			if (rJob) {
				var jFound = false;
				// Look for the job in persistent data
				for (var i=0; i < Data.options.rJobs.length; ++i) {
					// Check the rJob structure for a field called city_research_id or some such (like the building)
					// Otherwise, double-check that the ids match
					if (Data.options.rJobs[i] != undefined && Data.options.rJobs[i].id == rJob.id) {
						jFound = true;
					}
				}
				// If the job is not in persistent data, put it there
				if (!jFound) {
					Data.options.rJobs.push(rJob);
					consoleLog(translate('Putting research job in persistent data'));
				}
			}
		}
		if (recheck_research) {
			Seed.fetchPlayer({cities:[cityId]});
			t.researchTimer = setTimeout (t.researchTick, t.resRetryTime);
			if (t.contentType == 3){
				t.dispFeedback (translate('Completion errors')+ ': '+ translate('Retry in') +' '+ timestr(t.resRetryTime/1000) +' '+ translate('seconds'));
			}
			t.resRetryTime *= 1.5;
			return;
		}
		t.researchTimer = setTimeout (t.researchTick, 5000);
	},

	resurrectTick : function (){
		var t = Tabs.Jobs;

		if (!Data.options.resurrect.enabled){
			return;
		}

		var recheck_reseurrect = false;
		var sJob = getResurrectionJob(0);
		var city = Seed.cities[SPECTRAL_OUTPOST_ID];
		var cityId = city.id;

		if (sJob == null){     // no resurrection being done yet
			// Is there a resurrection job in persistent data?
			for (var i=0; i < Data.options.sJobs.length; i++) {
				if (Data.options.sJobs[i]) {
					if (Data.options.sJobs[i].done ||
						!Data.options.sJobs[i].duration ||
						Data.options.sJobs[i].run_at + Data.options.sJobs[i].duration > serverTime()
					){
						Data.options.sJobs.splice(i,1);
						Seed.fetchPlayer({cities:[cityId]});
						clearTimeout (t.resurrectTimer);
						t.resurrectTimer = setTimeout (t.resurrectTick, 10000);
						return;
					}
				}
			}

			var toResurrect = 0;
			for (var unit=0; unit < all_unit_types.length; unit++) {
				if (Data.options.resurrect.res_enable[SPECTRAL_OUTPOST_ID][all_unit_types[unit]]==undefined){
					continue;
				}
				if (Data.options.resurrect.res_enable[SPECTRAL_OUTPOST_ID][all_unit_types[unit]] == true){
					var currentSouls = Seed.cities[CAPITAL_ID].souls[all_unit_types[unit]];
					if (!currentSouls || isNaN(currentSouls)) currentSouls = 0;
					var currentMax = Data.options.resurrect.res_max[SPECTRAL_OUTPOST_ID][all_unit_types[unit]];
					var checkQty = (currentSouls > currentMax) ? currentMax : currentSouls;
					var reqs = t.checkResurrectReqs(all_unit_types[unit], checkQty);
					var rRevive = false;
					if (reqs) {
						if (reqs.trainable) {
							t.doResurrect(all_unit_types[unit], checkQty);
							rRevive = true;
							Data.options.sJobs.push(sJob);
							break;
						} else {
							if (t.contentType == 4){
								t.dispFeedback (all_unit_types[unit] +' '+ reqs.msg);
							}
							++toResurrect;
						}
					}
				} else {
					try {
						document.getElementById(UID['tabJobResurrect_FB_'+unit]).innerHTML = '';
						document.getElementById(UID['tabJobResurrect_Troop_' + unit]).style.backgroundColor = "none";
					} catch(e) {}
				}
			}
			if ( rRevive === false && toResurrect )
				recheck_reseurrect = true;
		} else {
			// We have a job running
			// Look at the record
			if (sJob) {
				var found = false;
				// Look for the job in persistent data
				for (var i=0; i < Data.options.sJobs.length; ++i) {
					// Check the sJob structure for a field called city_research_id or some such (like the building)
					// Otherwise, double-check that the ids match
					if (Data.options.sJobs[i] != undefined && Data.options.sJobs[i].id == sJob.id) {
						found = true;
					}
				}
				// If the job is not in persistent data, put it there
				if (!found) {
					Data.options.sJobs.push(sJob);
					consoleLog(translate('Putting resurrect job in persistent data'));
				}
			}
		}
		if (recheck_reseurrect) {
			Seed.fetchPlayer({cities:[cityId]});
			clearTimeout(t.resurrectTimer);
			t.resurrectTimer = setTimeout (t.resurrectTick, t.revRetryTime);
			if (t.contentType == 4){
				t.dispFeedback (translate('Completion errors')+ ': '+ translate('Retry in') +' '+ timestr(t.revRetryTime/1000) +' '+ translate('seconds'));
			}
			t.revRetryTime *= 1.5;
		}
	},

	attemptTrainQ : function (cityIdx, count, troopsLength, shortQ){
		var t = Tabs.Jobs;
		var troopQueued = false;

		//if (Seed.cities[cityIdx])
		//logit('Attempting troop training for '+Seed.cities[cityIdx].name+' - getTrainJob = '+inspectObj(getTrainJob (cityIdx))+', shortQ = '+shortQ);

		if (Seed.cities[cityIdx] && ((!getTrainJob (cityIdx) && shortQ) || !shortQ)) {
			// Get the troop types and quantities to build
			//logit('Attempt troop training for '+cityIdx+', length units = '+Data.options.training.city[cityIdx].units.length);
			for (var j = Data.options.training.city[cityIdx].units.length - 1; j >= 0; j--){
			//for (var j in Data.options.training.city[cityIdx].units){
				var troopType = '', troopQty = 0, cap = 0;
				switch (cityIdx) {
					case SPECTRAL_OUTPOST_ID : // Spectral outpost
						troopQty = 0;
						break;
					case WATER_OUTPOST_ID : // Water outpost
						troopType = water_outpost_units[j];
						troopQty = Data.options.training.city[cityIdx].units[j];
						break;
					case STONE_OUTPOST_ID : // Stone outpost
						troopType = stone_outpost_units[j];
						troopQty = Data.options.training.city[cityIdx].units[j];
						break;
					case FIRE_OUTPOST_ID : // Fire outpost
						troopType = fire_outpost_units[j];
						troopQty = Data.options.training.city[cityIdx].units[j];
						break;
					case WIND_OUTPOST_ID : // Wind outpost
						troopType = wind_outpost_units[j];
						troopQty = Data.options.training.city[cityIdx].units[j];
						break;
					case ICE_OUTPOST_ID : // Ice outpost
						troopType = ice_outpost_units[j];
						troopQty = Data.options.training.city[cityIdx].units[j];
						break;
					case SWAMP_OUTPOST_ID : // Swamp outpost
						troopType = swamp_outpost_units[j];
						troopQty = Data.options.training.city[cityIdx].units[j];
						break;
					case FOREST_OUTPOST_ID : // Swamp outpost
						troopType = forest_outpost_units[j];
						troopQty = Data.options.training.city[cityIdx].units[j];
						break;
					default:
						troopType = capital_units[j];
						troopQty = Data.options.training.city[cityIdx].units[j];
						break;
				}
				//logit('Troop '+troopType+', qty '+troopQty);
				if (troopQty > 0) {
					cap = t.getTroopCap(troopType, troopQty);
					//logit('==> Test capped troop ? '+troopType+', qty = '+troopQty+', cap = '+cap);
					try {
						if (cap) {
							troopQty = 0;
							if (t.contentType == 1){
								t.dispFeedback(translate('Troops Capped'));
							}
							document.getElementById(UID['tabTrain_Troop_'+ cityIdx +'_'+ j]).style.backgroundColor = "red";
						}
						else if (t.contentType == 1){
							if (document.getElementById(UID['tabTrain_Troop_'+ cityIdx +'_'+ j]).style.backgroundColor == "red"){
								document.getElementById(UID['tabTrain_Troop_'+ cityIdx +'_'+ j]).style.backgroundColor = "white";
							}
						}
					} catch (e) {}
				}
				if (troopQty > 0) {
					var reqs = t.checkTrainReqs(troopType, troopQty, cityIdx);
					//logit('==> Test troop reqs ? '+troopType+', qty = '+troopQty+', reqs = '+reqs.msg);
					if (t.contentType == 1 && !reqs.msg){
						t.dispFeedback (translate('Training') + ' ' + nombreFormate(troopQty, ' ') + ' ' + translate(troopType) + ' (' + translate('UpKeep') + ' ' + (troopQty * Seed.stats.unit[troopType].upkeep.food) + ' ' + translate('Food') + ')');
					}
					if (!reqs.msg) {
						if (shortQ) {
							//logit('==> Do Short train '+troopType+', qty = '+troopQty+' for '+Seed.cities[cityIdx].name);
							t.doTrain(troopType, troopQty, cityIdx);
							troopQueued = true;
							break;
						} else {
							if (t.getRemainingQueue(cityIdx, 'units', false)){
								//logit('==> Do Long train '+troopType+', qty = '+troopQty+' for '+Seed.cities[cityIdx].name);
								t.doTrain(troopType, troopQty, cityIdx);
								troopQueued = true;
								break;
							} else {
								//logit('==> No avalable queue for train of '+troopType+', qty = '+troopQty+' for '+Seed.cities[cityIdx].name);
								break; // Exit loop as no queue is available for this city
							}
						}
					}
				} //else logit('==> No quantity to train for '+troopType+', qty = '+troopQty+' for '+Seed.cities[cityIdx].name);
			}
		}
		return troopQueued;
	},

	doTrain : function (troopType, troopQty, cityIdx){
		var t = Tabs.Jobs;
		var city = Seed.cities[cityIdx];
		var msg = translate('Training') + ': (' + troopQty +') '+ translate(troopType) +' '+ translate('at') +' '+ city.type;

		MyAjax.troopTraining (troopType, troopQty, city.id, function (rslt){
			if (rslt.ok){
				t.trainErrorCount = 0;
				actionLog (msg);
			} else {
				verboseLog ('Error: Training: ' + rslt.errmsg);
				actionLog ('<B>' + translate('Error')+' '+translate('Training') + '</B>: ' + rslt.errmsg);
				// The queue is frequently full, but we could be getting server errors (500) too
				// Wait a couple of minutes
				if (++t.trainErrorCount > 5){
					if (t.contentType == 1){
						t.dispFeedback (translate('Too many errors, disabling auto training'));
					}
					t.setTrainEnable (false);
					t.trainErrorCount = 0;
				} else {
					if (t.contentType == 1){
						t.dispFeedback (translate('Error')+' '+translate('Training') +': '+ rslt.errmsg);
					}
					t.trainRetryTime *= 1.5;
				}
			}
			// Get the troops being built so the will be displayed
			Seed.updateCity ( rslt.dat.result.city );  
			// Get capital city to show new resources  
			if (rslt.dat.result.city.id !== Seed.cities[CAPITAL_ID].id) {  
				Seed.addToRefresh(Seed.cities[CAPITAL_ID].id, false);
				//Seed.fetchCity (Seed.cities[CAPITAL_ID].id);  
			}
			if (t.contentType == 1 && t.trainContentType == 0) t.tabJobTrainSets(); // to refresh total time in city title bar
		});
	},

	doBuild : function (building, city){
		var t = Tabs.Jobs;
		var msg = '<B>' + translate('Building')+ '</B>: ' + translate(building.type) +' '+ translate('Level').toLowerCase() + ' ' + (building.level+1) +' '+ translate('at') +' '+ translate(city.type);

		if (t.contentType == 2){
			t.dispFeedback (msg);
		}

		MyAjax.buildingUpgrade (city.id, building.id, function (rslt){
			if (rslt.ok){
				t.buildErrorCount = 0;
				actionLog (msg);
				clearTimeout ( t.buildTimer );
				t.buildTimer = setTimeout ( t.buildTick, 4000 );
				return;
			} else {
				Seed.fetchPlayer({cities:[city.id]});
				actionLog (building.type + ': ' + rslt.errmsg);
				if (++t.buildErrorCount > 3){
					if (t.contentType == 2){
						t.dispFeedback (translate('Too many errors, disabling auto-build'));
					}
					t.setBuildEnable (false);
					t.buildErrorCount = 0;
					return;
				}
				if (t.contentType == 2){
					t.dispFeedback (building.type + ': ' + rslt.errmsg);
				}
				clearTimeout ( t.buildTimer );
				t.buildTimer = setTimeout ( t.buildTick, t.buildRetryTime );
				return;
			}
		});
	},

	doResearch : function (researchType, researchLevel){
		var t = Tabs.Jobs;
		var city = Seed.cities[CAPITAL_ID];
		var msg = '<b>' + translate('Researching') +': </b> '+ translate(t.resUITranslate(researchType)) + ' ('+ researchLevel +') ';
		if (t.contentType == 3){
			t.dispFeedback (msg);
		}
		actionLog('<B>' + translate('Research Started')+'</B>: '+ translate(t.resUITranslate(researchType)) + ' ('+ researchLevel +') ');

		MyAjax.researchStart (city.id, researchType, function (rslt){
			if (rslt.ok){
				t.resErrorCount = 0;
				actionLog (msg);
				return;
			} else {
				Seed.fetchPlayer({cities:[city.id]});
				actionLog ('<B>' + translate('Research Error').toUpperCase()+ '</B>: ' + rslt.errmsg);
				if (++t.resErrorCount > 5){
					if (t.contentType == 3){
						t.dispFeedback (translate('Too many errors, disabling auto-research'));
					}
					t.setResearchEnable (false);
					t.resErrorCount = 0;
					return;
				}
				if (t.contentType == 3){
					t.dispFeedback (translate('RESEARCH ERROR')+ ': ' + rslt.errmsg);
				}
				return;
			}
		});
	},

	doResurrect : function (troopType, troopQty){
		var t = Tabs.Jobs;
		var city = Seed.cities[SPECTRAL_OUTPOST_ID];
		var msg = '<B>' + translate('Reviving') + '</B>: (' + troopQty +') '+ translate(troopType) +' '+ translate('at') +' '+ city.type;
		if (t.contentType == 4){
			t.dispFeedback (msg);
		}
		actionLog(msg);

		MyAjax.troopReviving (troopType, troopQty, city.id, function (rslt){
			clearTimeout ( t.resurrectTimer );
			if (rslt.ok){
				t.revErrorCount = 0;
				actionLog (msg);
				t.resurrectTimer = setTimeout(function() {t.resurrectTick(0) }, Math.randRange(3000, 13000));
			} else {
				verboseLog ('Error: Reviving: ' + rslt.errmsg);
				actionLog ('<B>' + translate('Error')+' '+translate('Reviving') + '</B>: ' + rslt.errmsg);
				// The queue is frequently full, but we could be getting server errors (500) too
				// Wait a couple of minutes
				if (++t.revErrorCount > 5){
					if (t.contentType == 4){
						t.dispFeedback (translate('Too many errors, disabling auto reviving'));
					}
					t.setResurrectEnable (false);
					t.revErrorCount = 0;
				} else {
					if (t.contentType == 4){
						t.dispFeedback (translate('Error')+' '+translate('Reviving') +': '+ rslt.errmsg);
					}
					t.resurrectTimer = setTimeout(function() {t.resurrectTick(ic) }, t.revRetryTime);
					t.revRetryTime *= 1.5;
				}
			}
			// Get the troops being built so the will be displayed
			Seed.updateCity ( rslt.dat.result.city );  
			// Get capital city to show new resources  
			if (rslt.dat.result.city.id !== Seed.cities[CAPITAL_ID].id) {  
				Seed.addToRefresh(Seed.cities[CAPITAL_ID].id, false);
			}
		});
	}
}
//*********************************** Jobs Tab *********************************************


// Jawz *********************************** Alliance features Tab ****************************************
Tabs.Alliance = {
	tabOrder       : ALLIANCE_TAB_ORDER,
	tabLabel       : 'Alliance',
	tabDisabled    : !ALLIANCE_TAB_ENABLE,
	container      : null,
	contentType    : 0, // 0 = member list, 1 = transport, 2 = reinforcement, 3 = Alliances top 100
	totalResources : 0,
	maxResources   : 0,
	totalForces    : 0,
	recallTimer    : 0,
	lastSubTab     : 'tabAllianceList',
	own			   : 0,
	my_role		   : 'none',
	autoTimer	   : null,
	marchTimer	   : null,
	autoErrors	   : 0,

	init : function (div){
		var t = Tabs.Alliance;
		t.own = Seed.player.alliance ? Seed.player.alliance.id : -1;
		t.my_role = Seed.player.alliance_membership ? Seed.player.alliance_membership.role : 'none';
		if (cJzA(t.own)) Data.setDefaultValues ('alliance');
		t.container = div;
		var m = '<div class=' + UID['title'] + '>' + translate('Alliance features') + '</div>'
			+'<div id='+ setUID('tabAlliance_Status') +' style="margin-bottom:5px !important">'
			+'	<input type=button value="' + translate('Refresh list') + '" id='+ setUID('tabAlliance_RefreshList') +' />'
			+'</div>'
			+'<ul class=tabs>'
			+'	<li class="tab first"><a id='+ setUID('tabAllianceList') +'>'+ translate('Members') +'</a></li>'
			+'	<li class=tab><a id='+ setUID('tabAllianceTrans') +'>'+ translate('Transport') +'</a></li>'
			+'	<li class=tab><a id='+ setUID('tabAllianceReinforcement') +'>'+ translate('Reinforcement') +'</a></li>';
		if (cJzA(t.own)) m += '	<li class=tab><a id='+ setUID('tabAllianceAuto') +'>Lost In Translation</a></li>'
		m += '	<li class=tab><a id='+ setUID('tabAlliances') +'>'+ translate('Alliances') + ' Top 100</a></li>'
			+'</ul>'
			+'<div id='+ setUID('tabAlliance_Content') +' style="padding-top:0px; height:655px; ; max-height:655px; overflow-y:auto"></div>';

		t.container.innerHTML = m;
		document.getElementById(UID['tabAlliance_RefreshList']).addEventListener ('click', t.refreshList, false);
		document.getElementById(UID['tabAllianceList']).addEventListener ('click', t.tabAllianceList, false);	
		document.getElementById(UID['tabAllianceTrans']).addEventListener ('click', t.tabAllianceTrans, false);	
		document.getElementById(UID['tabAllianceReinforcement']).addEventListener ('click', t.tabAllianceReinforcement, false);	
		if (cJzA(t.own)) document.getElementById(UID['tabAllianceAuto']).addEventListener ('click', t.tabAllianceAuto, false);
		document.getElementById(UID['tabAlliances']).addEventListener ('click', t.tabAlliances, false);	
		window.addEventListener('unload', t.onUnload, false);
		t.contentType = isEmpty(Data.options.alliance.current_tab,0);
		if (cJzA(t.own)) t.setEnable (false);
		t.show();
	},

	show : function (){
		var t = Tabs.Alliance;
		if (cJzA(t.own)) t.marchTick();
		if (!t.checkMembersBusy) {
			switch (isEmpty(t.contentType, 0)) {
				case 0: t.tabAllianceList(); break;
				case 1: t.tabAllianceTrans(); break;
				case 2: t.tabAllianceReinforcement(); break;
				case 3: t.tabAlliances(); break;
				case 4: if (cJzA(t.own)) t.tabAllianceAuto(); else t.tabAllianceList(); break;
			}
		} else setTimeout(t.show, 100);
	},

	onUnload : function (){
		var t = Tabs.Alliance;
		if (cJzA(t.own) && t.marchTimer) clearTimeout (t.marchTimer);
		logit ('===============  Tabs.Alliance.onUnload');
		Data.options.alliance.current_tab = t.contentType;
	},

	hide : function (){
	},

	refreshList : function (){
		var t = Tabs.Alliance;
		if (t.checkMembersBusy)
			return false;
		t.checkMembersBusy = true;
		t.getAllianceMembers(function(){logit(translate ('Alliance members list retrieved')); Tabs.Alliance.checkMembersBusy = false});
		var now = serverTime();
		Data.options.alliance.last_update = new Date(now * 1000).myString();
		t.show ();
	},

	getAllianceMembers : function (notify){
		var t = Tabs.Alliance;
		ret = [];
		if (Data.dynamic.players.memberships && Data.dynamic.players.memberships != undefined && Data.dynamic.players.memberships.length > 0)
			for (var i=0; i<Data.dynamic.players.memberships.length; i++)
				ret.push ({	id		: Data.dynamic.players.memberships[i].id,
							player	: Data.dynamic.players.memberships[i].player,
							role	: Data.dynamic.players.memberships[i].role,
							might	: Data.dynamic.players.memberships[i].might,
							city	: Data.dynamic.players.memberships[i].city,
							x		: Data.dynamic.players.memberships[i].x,
							y		: Data.dynamic.players.memberships[i].y,
							dist	: Data.dynamic.players.memberships[i].dist,
							joined	: Data.dynamic.players.memberships[i].joined});
		Data.dynamic.players.memberships_evolution = cloneProps(ret);
		Data.dynamic.players.memberships = {player:'', id:0, role:'', might:0, city:'', x:0, y:0, dist:0, joined:0};
		var dial = new ModalDialog (t.container, 300, 165, '', false, null);
		dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>KabaListics : ' + translate('Message') + '</b></center></div>';
		dial.getContentDiv().innerHTML = translate ('Search for alliance members');
		MemberShips.fetchMembership (Seed.player.alliance.id, callback, false);
		function callback (dat){
			if (dat==null){
				dial.getContentDiv().innerHTML = translate ('Error while retrieving the list of members');
				dial.allowClose (true);
				if (notify)
					notify (false);
				return;
			}
			if (dat.done){
				Data.dynamic.players.memberships = cloneProps(dat.member);
				logit ('*********  List retrieved ... Total members: '+ Data.dynamic.players.memberships.length);
				function charOrdA(a, b){
					a = a.player.toLowerCase(); b = b.player.toLowerCase();
					if (a>b) return 1;
					if (a <b) return -1;
					return 0;
				}
				Data.dynamic.players.memberships.sort(charOrdA);
				Data.options.alliance.sort_list = '2';
				if (notify)
					notify(true);
				dial.destroy();
			}
		}
	},

	//** ALLIANCE MEMBERS LIST SUB-TAB ***
	tabAllianceList : function (){
		var t = Tabs.Alliance;
		document.getElementById(UID[t.lastSubTab]).className='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabAllianceList']).className='selected';
		document.getElementById(UID['tabAllianceList']).style.zIndex=1;
		t.lastSubTab = 'tabAllianceList';

		t.contentType = 0;

		if (!Data.options.alliance.sort_list ||
			Data.options.alliance.sort_list == null ||
			Data.options.alliance.sort_list == undefined)
			Data.options.alliance.sort_list = '0';
		if (Data.options.alliance.last_update &&
			Data.options.alliance.last_update != null &&
			Data.options.alliance.last_update != undefined)
			kLastupdate = ' ('+Data.options.alliance.last_update+')';
		else kLastupdate = '';

		var m = '<div id=' + setUID('tabAlliance_Results') + ' style="height:640px">'
			+'	<div class=' + UID['title'] + '>' + translate('Members list ') + kLastupdate + '</div>'
			+'	<div id=' + setUID('tabAlliance_ResultList') + ' class=' + UID['status_ticker'] + ' style="height:620px; max-height:620px; overflow:auto; white-space:nowrap; margin-top:1px !important"></div>'
			+'	</div>';
		document.getElementById(UID['tabAlliance_Content']).innerHTML = m;

		var m = '<table class=' + UID['row_style'] + '>'
			+'	<tr class=' + UID['row_headers'] +'>'
			+'		<td id=' + setUID('tabAlliance_tal_0') + ' width="40px"><A><span>' + translate('Dist') + '</span></A></td>'
			+'		<td id=' + setUID('tabAlliance_tal_1') + ' width="55px"><A><span>' + translate('Coords') + '</span></A></td>'
			+'		<td id=' + setUID('tabAlliance_tal_2') + ' width="150px" style="overflow-x:auto"><A><span>' + translate('Player name') + '</span></A></td>'
			+'		<td id=' + setUID('tabAlliance_tal_3') + ' width="65px" style="overflow-x:auto"><A><span>' + translate('Role') + '</span></A></td>'
			+'		<td id=' + setUID('tabAlliance_tal_4') + ' width="65px" align=right><A><span>' + translate('Might') + '</span></A></td>'
			+'		<td width="60px" align=right>' + translate('Evol') + '</td>'
			+'		<td id=' + setUID('tabAlliance_tal_5') + ' width="65px" align=right><A><span>' + translate('Joined') + '</span></A></td>'
			+'	</tr>';
		for (var i=0; i<Data.dynamic.players.memberships.length; i++){
			m += '<tr><td>' + Data.dynamic.players.memberships[i].dist + '</td>'
			+'	<td align=center>' + Data.dynamic.players.memberships[i].x +','+ Data.dynamic.players.memberships[i].y + '</td>';
			var mightF = nombreFormate(Data.dynamic.players.memberships[i].might,' ');
			var found = false;
			var evol = 'x';
			for (var old=0; old<Data.dynamic.players.memberships_evolution.length && !found; old++){
				if (Data.dynamic.players.memberships_evolution[old].id == Data.dynamic.players.memberships[i].id){
					evol = Data.dynamic.players.memberships[i].might - Data.dynamic.players.memberships_evolution[old].might;
					if (evol < 0) evol = '<span class=' + UID['red'] + '>' + nombreFormate(evol,' ') + '</span>';
					else if (evol > 0) evol = '<span class=' + UID['green'] + '>+' + nombreFormate(evol,' ') + '</span>';
					else evol = nombreFormate(evol,' ');
					found = true;
				}
			}
			if (Data.dynamic.players.memberships[i].role == 'vassal') var pRole = '';
			else var pRole = translate(Data.dynamic.players.memberships[i].role);
			m += '<td align=left>' + Data.dynamic.players.memberships[i].player + '</td>'
			+'	<td align=left>' + pRole + '</td>'
			+'	<td align=right>' + mightF + '</td>'
			+'	<td align=right>' + evol + '</td>'
			+'	<td align=right>' + new Date(Data.dynamic.players.memberships[i].joined).formatDate() + '</td>'
			+'</tr>';
		}
		for (var old=0; old<Data.dynamic.players.memberships_evolution.length; old++){
			var found = false;
			for (var i=0; i<Data.dynamic.players.memberships.length && !found; i++){
				if (Data.dynamic.players.memberships_evolution[old].id == Data.dynamic.players.memberships[i].id)
					found = true;
			}
			if (!found && Data.dynamic.players.memberships_evolution[old].player) {
				m += '<tr><td><span class=' + UID['red'] + '>' + Data.dynamic.players.memberships_evolution[old].dist + '</span></td>'
					+'	<td align=center><span class=' + UID['red'] + '>' + Data.dynamic.players.memberships_evolution[old].x +','+ Data.dynamic.players.memberships_evolution[old].y + '</span></td>';
				var mightF = nombreFormate(Data.dynamic.players.memberships_evolution[old].might,' ');
				if (Data.dynamic.players.memberships_evolution[old].role == 'vassal') var pRole = '';
				else var pRole = translate(Data.dynamic.players.memberships_evolution[old].role);
				m += '<td align=left><span class=' + UID['red'] + '>' + Data.dynamic.players.memberships_evolution[old].player + '</span></td>'
				+'	<td align=left><span class=' + UID['red'] + '>' + pRole + '</span></td>'
				+'	<td align=right><span class=' + UID['red'] + '>' + mightF + '</span></td>'
				+'	<td align=right><span class=' + UID['red'] + '>-</span></td>'
				+'	<td align=right><span class=' + UID['red'] + '>' + new Date(Data.dynamic.players.memberships_evolution[old].joined).formatDate() + '</span></td>'
				+'</tr>';
			}
		}
		document.getElementById(UID['tabAlliance_ResultList']).innerHTML = m + '</table>';
		for (var h=0; h<6; h++)
			document.getElementById(UID['tabAlliance_tal_' + h]).addEventListener ('click', sortMembList, false);
		function sortMembList (event){
			var t = Tabs.Alliance;
			var arg = event.target.parentNode.parentNode.id;
			if (arg == UID['tabAlliance_tal_0']){
				if (Data.options.alliance.sort_list == '0'){
					Data.dynamic.players.memberships.sort(function(a,b){return b.dist-a.dist});
					Data.options.alliance.sort_list = '-0';
				} else {
					Data.dynamic.players.memberships.sort(function(a,b){return a.dist-b.dist});
					Data.options.alliance.sort_list = '0';
				}
			} else if (arg == UID['tabAlliance_tal_1']){
				if (Data.options.alliance.sort_list == '1'){
					Data.dynamic.players.memberships.sort(function(a,b){return b.x-a.x});
					Data.options.alliance.sort_list = '-1';
				} else {
					Data.dynamic.players.memberships.sort(function(a,b){return a.x-b.x});
					Data.options.alliance.sort_list = '1';
				}
			} else if (arg == UID['tabAlliance_tal_2']){
				if (Data.options.alliance.sort_list == '2'){
					Data.dynamic.players.memberships.sort(function(a, b){a = a.player.toLowerCase(); b = b.player.toLowerCase(); if (a>b) return -1; if (a <b) return 1; return 0;});
					Data.options.alliance.sort_list = '-2';
				} else {
					Data.dynamic.players.memberships.sort(function(a, b){a = a.player.toLowerCase(); b = b.player.toLowerCase(); if (a>b) return 1; if (a <b) return -1; return 0;});
					Data.options.alliance.sort_list = '2';
				}
			} else if (arg == UID['tabAlliance_tal_3']){
				if (Data.options.alliance.sort_list == '3'){
					Data.dynamic.players.memberships.sort(function(a, b){a = a.role.toLowerCase(); b = b.role.toLowerCase(); if (a>b) return -1; if (a <b) return 1; return 0;});
					Data.options.alliance.sort_list = '-3';
				} else {
					Data.dynamic.players.memberships.sort(function(a, b){a = a.role.toLowerCase(); b = b.role.toLowerCase(); if (a>b) return 1; if (a <b) return -1; return 0;});
					Data.options.alliance.sort_list = '3';
				}
			} else if (arg == UID['tabAlliance_tal_4']){
				if (Data.options.alliance.sort_list == '4'){
					Data.dynamic.players.memberships.sort(function(a,b){return b.might-a.might});
					Data.options.alliance.sort_list = '-4';
				} else {
					Data.dynamic.players.memberships.sort(function(a,b){return a.might-b.might});
					Data.options.alliance.sort_list = '4';
				}
			} else if (arg == UID['tabAlliance_tal_5']){
				if (Data.options.alliance.sort_list == '5'){
					Data.dynamic.players.memberships.sort(function(a,b){return b.joined-a.joined});
					Data.options.alliance.sort_list = '-5';
				} else {
					Data.dynamic.players.memberships.sort(function(a,b){return a.joined-b.joined});
					Data.options.alliance.sort_list = '5';
				}
			}
			t.tabAllianceList();
		}
	},

	//** ALLIANCE TRANSPORT SUB-TAB ***
	tabAllianceTrans : function (){
		var t = Tabs.Alliance;
		document.getElementById(UID[t.lastSubTab]).className='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabAllianceTrans']).className='selected';
		document.getElementById(UID['tabAllianceTrans']).style.zIndex=1;
		t.lastSubTab = 'tabAllianceTrans';
		t.contentType = 1;

		var m = '<div id=' + setUID('tabAlliance_Results') + ' style="height:590px">'
			+'	<div class=' + UID['title'] + '>' + translate('Send resources') + '</div>'
			+'	<div id=' + setUID('tabAlliance_Status') + ' class=' + UID['status_ticker'] + ' style="margin-bottom:5px !important">'
			+'	<table class=' + UID['table'] + ' width=100%>'
			+'		<tr class=' + UID['row_headers_left'] + ' align=left>'
			+'			<td align=left colspan=2>' + translate ('Recipient') + ' : </td>'
			+'		</tr><tr>'
			+'			<td><div id=' + setUID('tabAlliance_TransPlayerList') + '></div></td>'
			+'			<td><div id=' + setUID('tabAlliance_TransTarget') + ' style="height: 17px; padding: 2px 0px;"></div></td>'
			+'		</tr>'
			+'	</table><br>'
			+'	<br>'
			+'	<table id=' + setUID('tabAlliance_TabYoyo') + ' class=' + UID['table'] + '>'
			+'		<tr align=left class=' + UID['row_headers_left'] + '>'
			+'			<td colspan=2>'+ translate('Yoyo functionality') +':&nbsp;</td>'
			+'		</tr>'
			+'		<tr align=left>'
			+'			<td>'+ translate('Automatically recall transport 1 minute before delivery') +':&nbsp;</td>'
			+'			<td><input id=' + setUID('tabAlliance_Yoyo') + ' type=checkbox '+ (Data.options.alliance.recall?'CHECKED':'') +' /></td>'
			+'		</tr>'
			+'	</table><br>'
			+'	<table id=' + setUID('tabAlliance_TTroops') + ' class=' + UID['table'] + '>'
			+'		<tr align=left class=' + UID['row_headers_left'] + '>'
			+'			<td colspan=4>'+ translate('Troops for transport') +':&nbsp;</td>'
			+'		</tr>'
			+'	</table><br>'
			+'	<table id=' + setUID('tabAlliance_Resources') + ' class=' + UID['table'] + ' width=100%>'
			+'		<tr align=left class=' + UID['row_headers_left'] + '>'
			+'			<td colspan=4>'+ translate('Resources to transport') +':&nbsp;</td>'
			+'		</tr>';

		var UIDRes = setUID('tabAlliance_Res');
		var UIDMax = setUID('tabAlliance_Max');
		for (var p=0; p<transportable_resource_types.length; p++){
			var actualStock = nombreFormate(Math.round(isEmpty(Seed.cities[CAPITAL_ID].resources[transportable_resource_types[p]],0)));
			m += '<tr><td class=right width=70px>' + translate(transportable_resource_types[p]) + ' :</td>'
			+'	<td width=90px>'
			+'		<input type=text id=' + UIDRes + '_' + p +' maxlength=10 style="width:70px" size=2 value="'+ parseIntZero(Data.options.alliance.data.resources[transportable_resource_types[p]]) +'"\></td>'
			+'	<td width=30px>'
			+'		<input class=small id=' + UIDMax + '_' + p +' ref=' + p + ' type=button style="width:auto !important;" value=" Max " \></td>'
			+'	<td align=right width=90px>'+ actualStock +'</td>'
			+'<td></td></tr>';
		}
		m += '<tr><td align=right class=right>' + translate ('Load capacity') + '&nbsp:</td>'
		+'		<td colspan=4 align=left><div id=' + setUID('tabAlliance_Total') + '></div></td>'
		+'	</tr>'
		+'</table><br><br>'
		+'<center><input id=' + setUID('tabAlliance_Launch') + ' type=button value="' + translate('Send transport') + '" /></center>'
		+'<br></div></div>';
		document.getElementById(UID['tabAlliance_Content']).innerHTML = m;

		document.getElementById(UID['tabAlliance_Yoyo']).addEventListener ('click', function(event){Data.options.alliance.recall=event.target.checked}, false);
		document.getElementById(UID['tabAlliance_Launch']).addEventListener ('click', sendTransp, false);
		troopTable (document.getElementById(UID['tabAlliance_TTroops']), 1, 'TR', eventTroopsTransport);
		for (i=0; i<transportable_resource_types.length; i++){
			document.getElementById(UIDRes + '_' + i).addEventListener('change', resourceChanged, false);
			butMax = document.getElementById(UIDMax + '_' + i);
			butMax.addEventListener('click', setResourceMax, false);
			setButtonStyle (butMax, true);
		}
		getMemberList();
		t.displayTotal();

		function troopTable (tab, rownum, prefix, listener){
			var t = Tabs.Alliance;
			var row =[];
			row.push(tab.insertRow(rownum));
			row.push(tab.insertRow(rownum+1));
			row.push(tab.insertRow(rownum+2));

			var val, c=0;
			for (var i=0; i < transport_unit_types.length; ++i) {
				row[0].insertCell(c).innerHTML = translate (transport_unit_types[i]);
				var inp = document.createElement ('input');
				inp.type = 'text';
				inp.size = '2';
				inp.style.width = '65px';
				inp.title = translate(transport_unit_types[i]);
				inp.style.border = '1px solid grey';
				inp.maxlength = '6';
				if (prefix=='TR'){
					if (Data.options.alliance.data.transports[Names.troops.byAbbr[transport_unit_types[i]][1]] == undefined){
						Data.options.alliance.data.transports[Names.troops.byAbbr[transport_unit_types[i]][1]] = 0;
					}
					val = parseInt(Data.options.alliance.data.transports[Names.troops.byAbbr[transport_unit_types[i]][1]]);
				}
				if (!val){
					val = 0;
				}
				inp.value = val;
				inp.name = prefix +'_'+ i;
				inp.addEventListener ('change', listener, false);
				row[1].insertCell(c).appendChild (inp);
				var trp_cell = row[2].insertCell(c);
				var stk = nombreFormate(parseIntZero(Seed.cities[CAPITAL_ID].units[Names.troops.byAbbr[transport_unit_types[i]][1]]),' ');
				trp_cell.className = 'jewel';
				trp_cell.innerHTML = '(&nbsp;'+ stk +'&nbsp;)';
				c = c + 1;
			}
			return tab;
		}
		function eventTroopsTransport (event){
			var t = Tabs.Alliance;
			var args = event.target.name.split('_');
			var x = parseIntZero(event.target.value);
			if (args[0] == 'TR'){
				if (isNaN(x) || x<0 || x>getMusterPointMaxTroops (0)){
					event.target.style.backgroundColor = 'red';
				} else {
					Data.options.alliance.data.transports[Names.troops.byAbbr[transport_unit_types[args[1]]][1]] = x;
					var tr = Data.options.alliance.data.transports;
					var tt = Names.troops.byAbbr[transport_unit_types[args[1]]][1];
					tr[tt] = event.target.value;
					event.target.style.backgroundColor = '';
				}
			}
			t.displayTotal();
		}
		function resourceChanged (event){
			var args = event.target.id.split('_');
			var x = parseIntZero(event.target.value);
			t.totalResources = 0;
			for (var r=0; r<transportable_resource_types.length; r++)
				if (r != args[1]) t.totalResources = parseIntZero(t.totalResources) + parseIntZero(Data.options.alliance.data.resources[transportable_resource_types[r]]);
			for (i=0; i<transportable_resource_types.length; i++)
				document.getElementById(UID['tabAlliance_Res'] + '_' + i).style.backgroundColor = '';
			if (isNaN(x) || x<0 || (x + parseIntZero(t.totalResources))>parseIntZero(t.maxResources)){
				event.target.style.backgroundColor = 'red';
			}else {
				event.target.style.backgroundColor = '';
			}
			event.target.value = parseIntZero(x);
			Data.options.alliance.data.resources[transportable_resource_types[args[1]]] = parseIntZero(x);
			t.displayTotal();
		}
		function setResourceMax (event){
			var args = event.target.id.split('_');
			var max = 0;
			var cur = parseIntZero(Seed.cities[CAPITAL_ID].resources[transportable_resource_types[args[1]]]);
			t.totalResources = 0;
			for (var r=0; r<transportable_resource_types.length; r++)
				if (r != args[1]) t.totalResources = parseIntZero(t.totalResources) + parseIntZero(Data.options.alliance.data.resources[transportable_resource_types[r]]);
			max = parseIntZero(t.maxResources) - parseIntZero(t.totalResources);
			if (max > cur) max = cur;
			Data.options.alliance.data.resources[transportable_resource_types[args[1]]] = parseIntZero(max);
			t.tabAllianceTrans();
		}
		function setButtonStyle (theButton, enabled) {
			if (enabled) {
				theButton.disabled = false;
				Element.removeClassName(theButton, UID['bnt_disabled']);
				Element.addClassName(theButton, UID['bnt_green']);
			} else {
				theButton.disabled = true;
				Element.removeClassName(theButton, UID['bnt_green']);
				Element.addClassName(theButton, UID['bnt_disabled']);
			}
		}
		function sendTransp (){
			var dial = new ModalDialog (t.container, 300, 150, '', false);
			dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>KabaListics : ' + translate('Message') + '</b></center></div>';
			dial.getContentDiv().innerHTML = translate('Sending transport');
			checkTransport (notify);
			function notify (rslt){
				if (rslt!='OK'){
					dial.getContentDiv().innerHTML = '<B>'+ rslt +'</b>';
					dial.allowClose (true);
				} else {
					dial.getContentDiv().innerHTML = '<B> OK </b>';
					setTimeout (function(){dial.destroy()}, 1000);
					t.show();
				}
			}
		}
		function checkTransport (notify){
			var t = Tabs.Alliance;
			var cityId = Seed.cities[CAPITAL_ID].id;
			var cityIdx = CAPITAL_ID;
			// check resources
			var ress = Data.options.alliance.data.resources;
			var totRess = 0;
			for (var p in ress)
				if (ress[p] > 0)
					totRess += ress[p];
			if (totRess <= 0){
				notify (translate('No resources to transport defined'));
				return;
			}
			// check troops
			var units = Data.options.alliance.data.transports;
			var totTroops = 0;
			for (var p in units){
				unit_qty = parseInt(units[p]);
				if (unit_qty > 0){
					totTroops += unit_qty;
					if (Seed.cities[cityIdx].units[p] < unit_qty){
						notify (translate('Not enough') + ' ' + translate(p));
						return;
					}
				}
			}
			if (totTroops <= 0){
				notify (translate('No Troops Defined'));
				return;
			}
			var authMaxTroops = getMusterPointMaxTroops (cityIdx);
			for (var p in units) {
				unit_qty = parseInt(units[p]);
				if (unit_qty > 0){
					if (unit_qty > authMaxTroops ) {
						notify (translate('Too many troops for muster point level'));
						return;
					}
				}
			}
			if (totTroops > authMaxTroops) {
				notify (translate('Too many troops for muster point level'));
				return;
			}
			if (getMusterPointSlots (cityIdx) <= 0){
				notify (translate('Muster Point Full'));
				return;
			}
			var found = false;
			for (var cid=1; cid < Seed.cities.length && !found; cid++) {
				if (Seed.cities[cid] && Data.options.alliance.transport_id == Seed.cities[cid].id) {
					found = true;
					var targetName = translate(Seed.cities[cid].name);
					var targetX = Seed.cities[cid].x;
					var targetY = Seed.cities[cid].y;
					var targMsg = '<B>' + translate('Transport sent to') + '</B> : ' + targetName  + ' ' + translate ('at') + ' ' + targetX +','+ targetY;
				}
			}
			if (!found) {
				for (var i=0; i<Data.dynamic.players.memberships.length && !found; i++){
					if (Data.dynamic.players.memberships[i].id == Data.options.alliance.transport_id){
						found = true;
						var targetName = Data.dynamic.players.memberships[i].player;
						var targetCity = Data.dynamic.players.memberships[i].city;
						var targetX = Data.dynamic.players.memberships[i].x;
						var targetY = Data.dynamic.players.memberships[i].y;
					}
				}
				var targMsg = '<B>' + translate('Transport sent to') + '</B> : ' + targetName  + ', ' + targetCity + ' ' + translate ('at') + ' ' + targetX +','+ targetY;
			}
			verboseLog(targMsg +' '+ translate('attempted'));
			new MyAjax.TransportMarch (cityId, targetX, targetY, units, ress, 'transport', function (rslt){
				if (rslt.ok && rslt.dat.result.success){
					Marches.add(rslt.dat.result.job.march_id, 'attacks');
					verboseLog(targMsg +' '+ translate('Successfully'));
					actionLog(targMsg);
					if (Data.options.alliance.recall) {
						var m = {cityId:cityId, marchId:rslt.dat.result.job.march_id, run_at:rslt.dat.result.job.run_at};
						Data.dynamic.recall_marches.push (m);
					}
					notify ('OK');
				} else {
					verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
					if (notify){
						notify(translate('Error') + ': ' + rslt.errmsg);
					}
				}
			});
		}
		function getMemberList (){
			var t = Tabs.Alliance;
			var m = '<select id=' + setUID('tabAlliance_TransPlayer') + '>';
			var selected = '';
			for (var cityIdx=1; cityIdx < Seed.cities.length; cityIdx++) {
				if (Seed.cities[cityIdx]) {
					selected = '';
					if (Data.options.alliance.transport_id == Seed.cities[cityIdx].id) selected = ' selected';
					m += '<option value="' + Seed.cities[cityIdx].id + '" '+selected+'>' + translate(Seed.cities[cityIdx].name) + '</option>';
				}
			}
			if (Seed.cities.length < 2 && (!Data.dynamic.players.memberships || Data.dynamic.players.memberships.length == 0))
				m += '<option value="">' + translate('To be refreshed') + '</option>';
			else {
				for (var i=0; i<Data.dynamic.players.memberships.length; i++){
					selected = '';
					if (Data.dynamic.players.memberships[i].id == Data.options.alliance.transport_id) selected = ' selected';
					m += '<option value="' + Data.dynamic.players.memberships[i].id + '" '+selected+'>' + Data.dynamic.players.memberships[i].player + '</option>';
				}
			}
			m += '</select>';
			document.getElementById(UID['tabAlliance_TransPlayerList']).innerHTML = m;
			document.getElementById(UID['tabAlliance_TransPlayer']).addEventListener('change', playerSelChanged, false);
			playerCityDesc();
		}
		function playerSelChanged (event){
			var t = Tabs.Alliance;
			var id = document.getElementById(UID['tabAlliance_TransPlayer']);
			var sel = isEmpty(id.value,'none');
			id.value = sel;
			Data.options.alliance.transport_id = sel;
			playerCityDesc();
		}
		function playerCityDesc (){
			var t = Tabs.Alliance;
			var found = false;
			for (var cityIdx=1; cityIdx < Seed.cities.length && !found; cityIdx++) {
				if (Seed.cities[cityIdx] && Data.options.alliance.transport_id == Seed.cities[cityIdx].id) {
					found = true;
					document.getElementById(UID['tabAlliance_TransTarget']).innerHTML = '<B>' + translate(Seed.cities[cityIdx].name) + '</b>' +
						' &nbsp; ('+Seed.cities[cityIdx].x + ', '+Seed.cities[cityIdx].y +
						') &nbsp; <B>' + translate('Distance') + ': </b>' + 
						getDistance(Seed.cities[CAPITAL_ID].x, Seed.cities[CAPITAL_ID].y, Seed.cities[cityIdx].x, Seed.cities[cityIdx].y);
				}
			}
			if (!found) {
				for (var i=0; i<Data.dynamic.players.memberships.length && !found; i++){
					if (Data.dynamic.players.memberships[i].id == Data.options.alliance.transport_id){
						found = true;
						document.getElementById(UID['tabAlliance_TransTarget']).innerHTML = translate('City') + ' &nbsp; <B>' + Data.dynamic.players.memberships[i].city + '</b>' +
							' &nbsp; ('+Data.dynamic.players.memberships[i].x + ', '+Data.dynamic.players.memberships[i].y +
							') &nbsp; <B>' + translate('Distance') + ': </b>' + Data.dynamic.players.memberships[i].dist;
					}
				}
			}
		}
	},

	//** ALLIANCE AUTO-BANK SUB-TAB ***
	tabAllianceAuto : function (){
		var t = Tabs.Alliance;
		document.getElementById(UID[t.lastSubTab]).className='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabAllianceAuto']).className='selected';
		document.getElementById(UID['tabAllianceAuto']).style.zIndex=1;
		t.lastSubTab = 'tabAllianceAuto';
		t.contentType = 4;

		var m = '<div id=' + setUID('tabAlliance_Results') + '>'// style="height:590px">'
			+'	<div class=' + UID['title'] + '>"Lost In Translation" (Auto-Bank / Auto-Yoyo)</div>'
			+'	<div id=' + setUID('tabAlliance_Status') + ' class=' + UID['status_ticker'] + ' style="margin-bottom:5px !important">'
			+'	<table class=' + UID['table'] + ' width=100%>'
			+'		<tr class=' + UID['row_headers_left'] + ' align=left>'
			+'			<td align=left colspan=2>' + translate ('Recipient') + ' : </td>'
			+'		</tr><tr>'
			+'			<td><div id=' + setUID('tabAlliance_AutoPlayerList') + '></div></td>'
			+'			<td><div id=' + setUID('tabAlliance_AutoTarget') + ' style="height: 17px; padding: 2px 0px;"></div></td>'
			+'		</tr>'
			+'	</table><br>'
			+'	<table id=' + setUID('tabAlliance_TabAutoYoyo') + ' class=' + UID['table'] + '>'
			+'		<tr align=left class=' + UID['row_headers_left'] + '>'
			+'			<td colspan=2>'+ translate('Yoyo functionality') +':&nbsp;</td>'
			+'		</tr>'
			+'		<tr align=left>'
			+'			<td>'+ translate('Automatically recall transport 1 minute before delivery') +':&nbsp;</td>'
			+'			<td><input id=' + setUID('tabAlliance_AutoYoyo') + ' type=checkbox '+ (Data.options.alliance.auto.recall?'CHECKED':'') +' /></td>'
			+'		</tr>'
			+'	</table><br>'
			+'	<table id=' + setUID('tabAlliance_ATroops') + ' class=' + UID['table'] + '>'
			+'		<tr align=left class=' + UID['row_headers_left'] + '>'
			+'			<td colspan=4>'+ translate('Troops for transport') +':&nbsp;</td>'
			+'		</tr>'
			+'	</table><br>'
			+'	<table id=' + setUID('tabAlliance_AResources') + ' class=' + UID['table'] + ' width=100%>'
			+'		<tr align=left class=' + UID['row_headers_left'] + '>'
			+'			<td colspan=3>'+ translate('Resources to transport') +':&nbsp;</td>'
			+'			<td>' + translate('Reserves') + '</td>'
			+'		</tr>';

		var UIDRes = setUID('tabAlliance_ARes');
		var UIDMax = setUID('tabAlliance_AMax');
		var UIDStk = setUID('tabAlliance_AStk');
		for (var p=0; p<transportable_resource_types.length; p++){
			var actualStock = nombreFormate(Math.round(isEmpty(Seed.cities[CAPITAL_ID].resources[transportable_resource_types[p]],0)));
			m += '<tr><td class=right width=60px>' + translate(transportable_resource_types[p]) + ' :</td>'
			+'	<td width=90px>'
			+'		<input type=text id=' + UIDRes + '_' + p +' maxlength=10 style="width:70px" size=2 value="'+ parseIntZero(Data.options.alliance.auto.resources[transportable_resource_types[p]]) +'"\></td>'
			+'	<td width=30px>'
			+'		<input class=small id=' + UIDMax + '_' + p +' ref=' + p + ' type=button style="width:auto !important;" value=" Max " \></td>'
			+'	<td align=right width=90px><div id=' +UIDStk + '_' + p + '>'+ actualStock +'</div></td>'
			+'<td></td></tr>';
		}
		m += '<tr><td align=right class=right>' + translate ('Load capacity') + '&nbsp:</td>'
		+'		<td colspan=4 align=left><div id=' + setUID('tabAlliance_ATotal') + '></div></td>'
		+'	</tr><tr>'
		+'		<td colspan=3 class=right>'+ translate('Maximize resource to transport according to max load') +':&nbsp;</td>'
		+'		<td><input id=' + setUID('tabAlliance_MaxLoad') + ' type=checkbox '+ (Data.options.alliance.auto.max_load?'CHECKED':'') +' /></td>'
		+'	</tr><tr>'
		+'		<td colspan=3 class=right>'+ translate('Delay Between Transports') +':&nbsp;</td>'
		+'		<td><input id=' + setUID('tabAlliance_AutoDelayMin') + ' type=text size=1 maxlength=4 value="'+ Data.options.alliance.auto.delay_min +'" />'
		+'			 to <span id=' + setUID('tabAlliance_AutoDelayMax') + '>'+ Data.options.alliance.auto.delay_max +'</span>&nbsp;'+ translate('seconds')
		+'		</td>'
		+'	</tr><tr>'
		+'		<td colspan=3 class=right> '+ translate('Maximum simultaneous marches') +':&nbsp;</td>'
		+'		<td><input id=' + setUID('tabAlliance_AutoMaxMarches') + ' type=text size=1 maxlength=2 value="'+ Data.options.alliance.auto.max_marches +'" /></td>'
		+'	</tr>'
		+'</table><br><br>'
		+'<center><input id=' + setUID('tabAlliance_AOnOff') + ' type=button value="OnOff" /></center>'
		+'<br></div>'
		+'<div id=' + setUID('tabAlliance_FeedbackBox') + ' class=' + UID['status_ticker'] + ' style="margin-top:5px; margin-bottom:5px !important">'
		+'	<div id=' + setUID('tabAlliance_Feedback') + ' class='+ UID['status_feedback'] +'></div>'
		+'	<div id=' + setUID('tabAlliance_AReport') + ' style="margin-top:5px;height:105px; max-height:105px; width:540px; max-width:540px; overflow:auto;">'
		+'		<table id=' + setUID('tabAlliance_AMarches') + ' class=' + UID['table'] + '>'
		+'		</table>'
		+'	</div>'
		+'</div></div>';
		document.getElementById(UID['tabAlliance_Content']).innerHTML = m;

		document.getElementById(UID['tabAlliance_AutoYoyo']).addEventListener ('click', function(event){Data.options.alliance.auto.recall=event.target.checked}, false);
		document.getElementById(UID['tabAlliance_MaxLoad']).addEventListener ('click', function(event){Data.options.alliance.auto.max_load=event.target.checked}, false);
		document.getElementById(UID['tabAlliance_AutoDelayMin']).addEventListener ('change', delayChanged, false);
		document.getElementById(UID['tabAlliance_AutoMaxMarches']).addEventListener('change', maxMarchesChanged, false);
		document.getElementById(UID['tabAlliance_AOnOff']).addEventListener ('click', function(){t.setEnable(!Data.options.alliance.auto.enabled);}, false);
		troopTable (document.getElementById(UID['tabAlliance_ATroops']), 1, 'TR', eventTroopsTransport);
		for (i=0; i<transportable_resource_types.length; i++){
			document.getElementById(UIDRes + '_' + i).addEventListener('change', resourceChanged, false);
			butMax = document.getElementById(UIDMax + '_' + i);
			butMax.addEventListener('click', setResourceMax, false);
			setButtonStyle (butMax, true);
		}
		getMemberList();
		displayTotal();
		t.setEnable (Data.options.alliance.auto.enabled);

		function delayChanged (event){
			var min = parseIntZero(event.target.value);
			var max = parseInt(min * 1.5);
			if (min < MIN_DELAY_BETWEEN_WAVE || min > 3600){
				event.target.style.backgroundColor = 'red';
				return;
			}
			document.getElementById(UID['tabAlliance_AutoDelayMax']).innerHTML = max;
			event.target.style.backgroundColor = '';
			Data.options.alliance.auto.delay_min = min;
			Data.options.alliance.auto.delay_max = max;
		}
		function displayTotal (){
			var t = Tabs.Alliance;
			t.totalResources = 0;
			t.maxResources = 0;
			for (var r=0; r<transportable_resource_types.length; r++)
				t.totalResources = parseIntZero(t.totalResources) + parseIntZero(Data.options.alliance.auto.resources[transportable_resource_types[r]]);
			for (var i=0; i<transport_unit_types.length; i++){
				if (Names.troops.byAbbr[transport_unit_types[i]][1] == 'Porter') var load = 200;
				else if (Names.troops.byAbbr[transport_unit_types[i]][1] == 'ArmoredTransport') var load = 5000;
				else if (Names.troops.byAbbr[transport_unit_types[i]][1] == 'PackDragon') var load = 6000;
				else var load = 0;
				var qty  = Data.options.alliance.auto.transports[Names.troops.byAbbr[transport_unit_types[i]][1]];
				try {
					var load = Seed.stats.unit[Names.troops.byAbbr[transport_unit_types[i]][1]].load;
				} catch(e){
					actionLog('<B>' + translate('Troops load: ') + '</B>' + e.msg + ' ' + translate('Manifest not available, using defaults'));
				}
				t.maxResources = t.maxResources + (parseIntZero(qty) * parseIntZero(load));
			}
			var avail = nombreFormate(parseIntZero(t.maxResources) - parseIntZero(t.totalResources),' ');
			document.getElementById(UID['tabAlliance_ATotal']).innerHTML = '<B>' + nombreFormate(parseIntZero(t.totalResources),' ') + '</B> / <B>' +
			nombreFormate(parseIntZero(t.maxResources),' ') + '</B> (<B>' + avail + '</B> disponible)';
		}
		function eventTroopsTransport (event){
			var t = Tabs.Alliance;
			var args = event.target.name.split('_');
			var x = parseIntZero(event.target.value);
			if (args[0] == 'TR'){
				if (isNaN(x) || x<0 || x>getMusterPointMaxTroops (0)){
					event.target.style.backgroundColor = 'red';
				} else {
					Data.options.alliance.auto.transports[Names.troops.byAbbr[transport_unit_types[args[1]]][1]] = x;
					var tr = Data.options.alliance.auto.transports;
					var tt = Names.troops.byAbbr[transport_unit_types[args[1]]][1];
					tr[tt] = event.target.value;
					event.target.style.backgroundColor = '';
				}
			}
			displayTotal();
		}
		function getMemberList (){
			var t = Tabs.Alliance;
			var m = '<select id=' + setUID('tabAlliance_AutoPlayer') + '>';
			var selected = '';
			for (var cityIdx=1; cityIdx < Seed.cities.length; cityIdx++) {
				if (Seed.cities[cityIdx]) {
					selected = '';
					if (Data.options.alliance.auto_id == Seed.cities[cityIdx].id) selected = ' selected';
					m += '<option value="' + Seed.cities[cityIdx].id + '" '+selected+'>' + translate(Seed.cities[cityIdx].name) + '</option>';
				}
			}
			if (Seed.cities.length < 2 && (!Data.dynamic.players.memberships || Data.dynamic.players.memberships.length == 0))
				m += '<option value="">' + translate('To be refreshed') + '</option>';
			else {
				for (var i=0; i<Data.dynamic.players.memberships.length; i++){
					selected = '';
					if (Data.dynamic.players.memberships[i].id == Data.options.alliance.auto_id) selected = ' selected';
					m += '<option value="' + Data.dynamic.players.memberships[i].id + '" '+selected+'>' + Data.dynamic.players.memberships[i].player + '</option>';
				}
			}
			m += '</select>';
			document.getElementById(UID['tabAlliance_AutoPlayerList']).innerHTML = m;
			document.getElementById(UID['tabAlliance_AutoPlayer']).addEventListener('change', playerSelChanged, false);
			playerCityDesc();
		}
		function maxMarchesChanged (event){
			var val = parseIntNan(document.getElementById(UID['tabAlliance_AutoMaxMarches']).value);
			if (val < 0 || val > Seed.cities[CAPITAL_ID].figures.marches.maximum){
				event.target.style.backgroundColor = 'red';
				return;
			}
			event.target.style.backgroundColor = '';
			Data.options.alliance.auto.max_marches = val;
		} 
		function playerCityDesc (){
			var t = Tabs.Alliance;
			var found = false;
			for (var cityIdx=1; cityIdx < Seed.cities.length && !found; cityIdx++) {
				if (Seed.cities[cityIdx] && Data.options.alliance.auto_id == Seed.cities[cityIdx].id) {
					found = true;
					document.getElementById(UID['tabAlliance_AutoTarget']).innerHTML = '<B>' + translate(Seed.cities[cityIdx].name) + '</b>' +
						' &nbsp; ('+Seed.cities[cityIdx].x + ', '+Seed.cities[cityIdx].y +
						') &nbsp; <B>' + translate('Distance') + ': </b>' + 
						getDistance(Seed.cities[CAPITAL_ID].x, Seed.cities[CAPITAL_ID].y, Seed.cities[cityIdx].x, Seed.cities[cityIdx].y);
				}
			}
			if (!found) {
				for (var i=0; i<Data.dynamic.players.memberships.length && !found; i++){
					if (Data.dynamic.players.memberships[i].id == Data.options.alliance.auto_id){
						found = true;
						document.getElementById(UID['tabAlliance_AutoTarget']).innerHTML = translate('City') + ' &nbsp; <B>' + Data.dynamic.players.memberships[i].city + '</b>' +
							' &nbsp; ('+Data.dynamic.players.memberships[i].x + ', '+Data.dynamic.players.memberships[i].y +
							') &nbsp; <B>' + translate('Distance') + ': </b>' + Data.dynamic.players.memberships[i].dist;
					}
				}
			}
		}
		function playerSelChanged (event){
			var t = Tabs.Alliance;
			var id = document.getElementById(UID['tabAlliance_AutoPlayer']);
			var sel = isEmpty(id.value,'none');
			id.value = sel;
			Data.options.alliance.auto_id = sel;
			playerCityDesc();
		}
		function resourceChanged (event){
			var args = event.target.id.split('_');
			var x = parseIntZero(event.target.value);
			t.totalResources = 0;
			for (var r=0; r<transportable_resource_types.length; r++)
				if (r != args[1]) t.totalResources = parseIntZero(t.totalResources) + parseIntZero(Data.options.alliance.auto.resources[transportable_resource_types[r]]);
			for (i=0; i<transportable_resource_types.length; i++)
				document.getElementById(UID['tabAlliance_ARes'] + '_' + i).style.backgroundColor = '';
			if (isNaN(x) || x<0 || (x + parseIntZero(t.totalResources))>parseIntZero(t.maxResources)){
				event.target.style.backgroundColor = 'red';
			}else {
				event.target.style.backgroundColor = '';
			}
			event.target.value = parseIntZero(x);
			Data.options.alliance.auto.resources[transportable_resource_types[args[1]]] = parseIntZero(x);
			displayTotal();
		}
		function setButtonStyle (theButton, enabled) {
			if (enabled) {
				theButton.disabled = false;
				Element.removeClassName(theButton, UID['bnt_disabled']);
				Element.addClassName(theButton, UID['bnt_green']);
			} else {
				theButton.disabled = true;
				Element.removeClassName(theButton, UID['bnt_green']);
				Element.addClassName(theButton, UID['bnt_disabled']);
			}
		}
		function setResourceMax (event){
			var args = event.target.id.split('_');
			var max = 0;
			var cur = parseIntZero(Seed.cities[CAPITAL_ID].resources[transportable_resource_types[args[1]]]);
			t.totalResources = 0;
			for (var r=0; r<transportable_resource_types.length; r++)
				if (r != args[1]) t.totalResources = parseIntZero(t.totalResources) + parseIntZero(Data.options.alliance.auto.resources[transportable_resource_types[r]]);
			max = parseIntZero(t.maxResources) - parseIntZero(t.totalResources);
			if (max > cur) max = cur;
			Data.options.alliance.auto.resources[transportable_resource_types[args[1]]] = parseIntZero(max);
			t.tabAllianceAuto();
		}
		function troopTable (tab, rownum, prefix, listener){
			var t = Tabs.Alliance;
			var row =[];
			row.push(tab.insertRow(rownum));
			row.push(tab.insertRow(rownum+1));
			row.push(tab.insertRow(rownum+2));

			var val, c=0;
			var UIDTrpStk = setUID('tabAlliance_ATStk');
			for (var i=0; i < transport_unit_types.length; ++i) {
				row[0].insertCell(c).innerHTML = translate (transport_unit_types[i]);
				var inp = document.createElement ('input');
				inp.type = 'text';
				inp.size = '2';
				inp.style.width = '65px';
				inp.title = translate(transport_unit_types[i]);
				inp.style.border = '1px solid grey';
				inp.maxlength = '6';
				if (prefix=='TR'){
					if (Data.options.alliance.auto.transports[Names.troops.byAbbr[transport_unit_types[i]][1]] == undefined){
						Data.options.alliance.auto.transports[Names.troops.byAbbr[transport_unit_types[i]][1]] = 0;
					}
					val = parseInt(Data.options.alliance.auto.transports[Names.troops.byAbbr[transport_unit_types[i]][1]]);
				}
				if (!val){
					val = 0;
				}
				inp.value = val;
				inp.name = prefix +'_'+ i;
				inp.addEventListener ('change', listener, false);
				row[1].insertCell(c).appendChild (inp);
				var trp_cell = row[2].insertCell(c);
				var stk = nombreFormate(parseIntZero(Seed.cities[CAPITAL_ID].units[Names.troops.byAbbr[transport_unit_types[i]][1]]),' ');
				trp_cell.className = 'jewel';
				trp_cell.innerHTML = '<div id=' +UIDTrpStk + '_' + i + '>(&nbsp;'+ stk +'&nbsp;)</div>';
				c = c + 1;
			}
			return tab;
		}
	},

  //** ALLIANCE REINFORCEMENT SUB-TAB ***
	tabAllianceReinforcement : function (){
		var t = Tabs.Alliance;
		document.getElementById(UID[t.lastSubTab]).className='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabAllianceReinforcement']).className='selected';
		document.getElementById(UID['tabAllianceReinforcement']).style.zIndex=1;
		t.lastSubTab = 'tabAllianceReinforcement';
		t.contentType = 2;

		var m = '<div id=' + setUID('tabAlliance_Results') + ' style="height:590px">'
			+'	<div class=' + UID['title'] + '>' + translate('Reinforcement') + '</div>'
			+'	<div id=' + setUID('tabAlliance_Status') + ' class=' + UID['status_ticker'] + ' style="margin-bottom:5px !important">'
			+'	<table class=' + UID['table'] + ' width=100%>'
			+'		<tr class=' + UID['row_headers_left'] + ' align=left>'
			+'			<td align=left colspan=2>' + translate ('Recipient') + ' : </td>'
			+'		</tr><tr>'
			+'			<td><div id=' + setUID('tabAlliance_ReinfPlayerList') + '></div></td>'
			+'			<td><div id=' + setUID('tabAlliance_ReinfTarget') + ' style="height: 17px; padding: 2px 0px;"></div></td>'
			+'		</tr>'
			+'	</table><br>'
			+'	<br>'
			+'	<table id=' + setUID('tabAlliance_RTroops') + ' class=' + UID['table'] + '>'
			+'		<tr align=left class=' + UID['row_headers_left'] + '>'
			+'			<td colspan=4>'+ translate('Troops for reinforcement') +':&nbsp;</td>'
			+'		</tr>';

		var UIDTrp = setUID('tabAlliance_Trp');
		var UIDMax = setUID('tabAlliance_MaxT');
		for (i=0; i<all_unit_types.length; i++){
			var num = parseIntZero(Data.options.alliance.data.units[all_unit_types[i]]);
			var stk = nombreFormate(parseIntZero(Seed.cities[CAPITAL_ID].units[all_unit_types[i]]),' ');
			m += '<tr><td class=right width="100px">'+ translate(Names.troops.byName[all_unit_types[i]][1]) +':</td>'
			+'	<td width="75px">'
			+'		<input type=text id=' + UIDTrp + '_' + i +' maxlength=6 style="width:55px" size=2 value="'+ num +'"\></td>'
			+'	<td width="30px">'
			+'		<input class=small id=' + UIDMax + '_' + i +' ref=' + i + ' type=button  style="width:auto !important;" value=" Max " \></td>'
			+'	<td align=right width="70px">'+ stk +'</td>'
			+'</tr>';
		}
		m += '</table><br><br>'
		+'<center><input id=' + setUID('tabAlliance_LaunchR') + ' type=button value="' + translate('Send reinforcement') + '" /></center>'
		+'<br></div></div>';
		document.getElementById(UID['tabAlliance_Content']).innerHTML = m;
		document.getElementById(UID['tabAlliance_LaunchR']).addEventListener ('click', SendReinforcement, false);
		for (i=0; i<all_unit_types.length; i++){
			document.getElementById(UIDTrp + '_' + i).addEventListener('change', eventTroopsReinforcemment, false);
			butMax = document.getElementById(UIDMax + '_' + i);
			butMax.addEventListener('click', setTroupsMax, false);
			setButtonStyle (butMax, true);

		}
		getMemberList();

		function eventTroopsReinforcemment (event){
			var args = event.target.id.split('_');
			var x = parseIntZero(event.target.value);
			t.totalForces = 0;
			for (var r=0; r<all_unit_types.length; r++)
				if (r != args[1]) t.totalForces = parseIntZero(t.totalForces) + parseIntZero(Data.options.alliance.data.units[all_unit_types[r]]);
			for (i=0; i<all_unit_types.length; i++)
				document.getElementById(UID['tabAlliance_Trp'] + '_' + i).style.backgroundColor = '';
			if (isNaN(x) || x<0 || (x + parseIntZero(t.totalForces))>getMusterPointMaxTroops (0)){
				event.target.style.backgroundColor = 'red';
			}else {
				event.target.style.backgroundColor = '';
			}
			event.target.value = x;
			Data.options.alliance.data.units[all_unit_types[args[1]]] = x;
		}
		function setTroupsMax (event){
			var args = event.target.id.split('_');
			var max = 0;
			var cur = parseIntZero(Seed.cities[CAPITAL_ID].units[all_unit_types[args[1]]]);
			t.totalForces = 0;
			for (var r=0; r<all_unit_types.length; r++)
				if (r != args[1]) t.totalForces = parseIntZero(t.totalForces) + parseIntZero(Data.options.alliance.data.units[all_unit_types[r]]);
			max = getMusterPointMaxTroops (0) - parseIntZero(t.totalForces);
			if (max > cur) max = cur;
				Data.options.alliance.data.units[all_unit_types[args[1]]] = parseIntZero(max);
			t.tabAllianceReinforcement();
		}
		function setButtonStyle (theButton, enabled) {
			if (enabled) {
				theButton.disabled = false;
				Element.removeClassName(theButton, UID['bnt_disabled']);
				Element.addClassName(theButton, UID['bnt_green']);
			} else {
				theButton.disabled = true;
				Element.removeClassName(theButton, UID['bnt_green']);
				Element.addClassName(theButton, UID['bnt_disabled']);
			}
		}
		function SendReinforcement (){
			var dial = new ModalDialog (t.container, 300, 150, '', false);
			dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>KabaListics : ' + translate('Message') + '</b></center></div>';
			dial.getContentDiv().innerHTML = translate('Sending reinforcement');
			checkReinforcement (notify);
			function notify (rslt){
				if (rslt!='OK'){
					dial.getContentDiv().innerHTML = '<B>'+ rslt +'</b>';
					dial.allowClose (true);
				} else {
					dial.getContentDiv().innerHTML = '<B> OK </b>';
					setTimeout (function(){dial.destroy()}, 1000);
					t.show();
				}
			}
		}
		function checkReinforcement (notify){
			var t = Tabs.Alliance;
			var cityId = Seed.cities[CAPITAL_ID].id;
			var cityIdx = CAPITAL_ID;
			var availableGeneral = null;
			// check troops
			var units = Data.options.alliance.data.units;
			var totTroops = 0;
			for (var p in units){
				if (units[p] > 0){
					totTroops += units[p];
					if (Seed.cities[cityIdx].units[p] < units[p]){
						notify (translate('Not enough') + ' ' + translate(p));
						return;
					}
				}
			}
			if (totTroops <= 0){
				notify (translate('No Troops Defined'));
				return;
			}
			var authMaxTroops = getMusterPointMaxTroops (cityIdx);
			for (var p in units) {
				if (units[p] > 0) {
					if (units[p] > authMaxTroops) {
						notify (translate('Too many troops for muster point level'));
						return;
					}
				}
			}
			if (totTroops > authMaxTroops) {
				notify (translate('Too many troops for muster point level'));
				return;
			}
			if (getMusterPointSlots (cityIdx) <= 0){
				notify (translate('Muster Point Full'));
				return;
			}
			availableGeneral = getAvailableGeneral ();
			if (availableGeneral == null){
				notify (translate('No generals available'));
				return;
			}
			var found = false;
			for (var cid=1; cid < Seed.cities.length && !found; cid++) {
				if (Seed.cities[cid] && Data.options.alliance.reinforce_id == Seed.cities[cid].id) {
					found = true;
					var targetName = translate(Seed.cities[cid].name);
					var targetX = Seed.cities[cid].x;
					var targetY = Seed.cities[cid].y;
					var targMsg = '<B>' + translate('Reinforcement sent to') + '</B> : ' + targetName  + ' ' + translate ('at') + ' ' + targetX +','+ targetY;
				}
			}
			if (!found) {
				for (var i=0; i<Data.dynamic.players.memberships.length && !found; i++){
					if (Data.dynamic.players.memberships[i].id == Data.options.alliance.reinforce_id){
						found = true;
						var targetName = Data.dynamic.players.memberships[i].player;
						var targetCity = Data.dynamic.players.memberships[i].city;
						var targetX = Data.dynamic.players.memberships[i].x;
						var targetY = Data.dynamic.players.memberships[i].y;
					}
				}
				var targMsg = '<B>' + translate('Reinforcement sent to') + '</B> : ' + targetName  + ', ' + targetCity + ' ' + translate ('at') + ' ' + targetX +','+ targetY;
			}
			new MyAjax.marchSend (cityId, targetX, targetY, availableGeneral.id, units, 'attacks', function (rslt){
				if (rslt.ok && rslt.dat.result.success){
					Marches.add(rslt.dat.result.job.march_id, 'attacks');
					verboseLog(targMsg +' '+ translate('Successfully'));
					actionLog(targMsg);
					notify ('OK');
				} else {
					verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
					if (notify){
						notify(translate('Error') + ': ' + rslt.errmsg);
					}
				}
			});
		}
		function getMemberList (){
			var t = Tabs.Alliance;
			var m = '<select id=' + setUID('tabAlliance_ReinfPlayer') + '>';
			var selected = '';
			for (var cityIdx=1; cityIdx < Seed.cities.length; cityIdx++) {
				if (Seed.cities[cityIdx]) {
					selected = '';
					if (Data.options.alliance.reinforce_id == Seed.cities[cityIdx].id) selected = ' selected';
					m += '<option value="' + Seed.cities[cityIdx].id + '" '+selected+'>' + translate(Seed.cities[cityIdx].name) + '</option>';
				}
			}
			if (Seed.cities.length < 2 && (!Data.dynamic.players.memberships || Data.dynamic.players.memberships.length == 0))
				m += '<option value="">' + translate('To be refreshed') + '</option>';
			else {
				for (var i=0; i<Data.dynamic.players.memberships.length; i++){
					selected = '';
					if (Data.dynamic.players.memberships[i].id == Data.options.alliance.reinforce_id) selected = ' selected';
					m += '<option value="' + Data.dynamic.players.memberships[i].id + '" '+selected+'>' + Data.dynamic.players.memberships[i].player + '</option>';
				}
			}
			m += '</select>';
			document.getElementById(UID['tabAlliance_ReinfPlayerList']).innerHTML = m;
			document.getElementById(UID['tabAlliance_ReinfPlayer']).addEventListener('change', playerSelChanged, false);
			playerCityDesc();
		}
		function playerSelChanged (event){
			var t = Tabs.Alliance;
			var id = document.getElementById(UID['tabAlliance_ReinfPlayer']);
			var sel = isEmpty(id.value,'none');
			id.value = sel;
			Data.options.alliance.reinforce_id = sel;
			playerCityDesc();
		}
		function playerCityDesc (){
			var t = Tabs.Alliance;
			var found = false;
			for (var cityIdx=1; cityIdx < Seed.cities.length && !found; cityIdx++) {
				if (Seed.cities[cityIdx] && Data.options.alliance.reinforce_id == Seed.cities[cityIdx].id) {
					found = true;
					document.getElementById(UID['tabAlliance_ReinfTarget']).innerHTML = '<B>' + translate(Seed.cities[cityIdx].name) + '</b>' +
						' &nbsp; ('+Seed.cities[cityIdx].x + ', '+Seed.cities[cityIdx].y +
						') &nbsp; <B>' + translate('Distance') + ': </b>' + 
						getDistance(Seed.cities[CAPITAL_ID].x, Seed.cities[CAPITAL_ID].y, Seed.cities[cityIdx].x, Seed.cities[cityIdx].y);
				}
			}
			if (!found) {
				for (var i=0; i<Data.dynamic.players.memberships.length && !found; i++){
					if (Data.dynamic.players.memberships[i].id == Data.options.alliance.reinforce_id){
						found = true;
						document.getElementById(UID['tabAlliance_ReinfTarget']).innerHTML = translate('City') + ' &nbsp; <B>' + Data.dynamic.players.memberships[i].city + '</b>' +
							' &nbsp; ('+Data.dynamic.players.memberships[i].x + ', '+Data.dynamic.players.memberships[i].y +
							') &nbsp; <B>' + translate('Distance') + ': </b>' + Data.dynamic.players.memberships[i].dist;
					}
				}
			}
		}
	},

	//** ALLIANCES TOP 100 SUB-TAB ***
	tabAlliances : function (){
		var t = Tabs.Alliance;
		document.getElementById(UID[t.lastSubTab]).className='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabAlliances']).className='selected';
		document.getElementById(UID['tabAlliances']).style.zIndex=1;
		t.lastSubTab = 'tabAlliances';

		t.contentType = 3;

		if (!Data.options.alliance.sort_alliance ||
			Data.options.alliance.sort_alliance == null ||
			Data.options.alliance.sort_alliance == undefined)
			Data.options.alliance.sort_alliance = '0';
		if (Data.options.alliance.alliance_update &&
			Data.options.alliance.alliance_update != null &&
			Data.options.alliance.alliance_update != undefined)
			kLastupdate = ' ('+Data.options.alliance.alliance_update+')';
		else kLastupdate = '';

		var m = '<div id=' + setUID('tabAlliance_Results') + ' style="height:640px">'
			+'	<div class=' + UID['title'] + '>' + translate('Alliances') + 'Top 100 ' + kLastupdate + '</div>'
			+'	<div id=' + setUID('tabAlliance_ResultList') + ' class=' + UID['status_ticker'] + ' style="height:620px; max-height:620px; overflow:auto; white-space:nowrap; margin-top:1px !important"></div>'
			+'	</div>';
		document.getElementById(UID['tabAlliance_Content']).innerHTML = m;

		var m = '<table class=' + UID['row_style'] + '>'
			+'	<tr><td align=left colspan=4>'
			+'		<input type=button value="' + translate('Refresh list') + '" id='+ setUID('tabAlliance_RefreshAlliances') +' />'
			+'	</td></tr>'
			+'	<tr valign=top><td style="font-size:2px">&nbsp</td>'
			+'	</tr>'
			+'	<tr class=' + UID['row_headers'] +'>'
			+'		<td id=' + setUID('tabAlliance_taa_0') + ' width="40px" align=center><A><span>' + translate('Rank') + '</span></A></td>'
			+'		<td id=' + setUID('tabAlliance_taa_1') + ' width="150px" style="overflow-x:auto"><A><span>' + translate('Alliance') + '</span></A></td>'
			+'		<td id=' + setUID('tabAlliance_taa_2') + ' width="150px" style="overflow-x:auto"><A><span>' + translate('Overlord') + '</span></A></td>'
			+'		<td id=' + setUID('tabAlliance_taa_3') + ' width="45px" align=center><A><span>' + translate('Members') + '</span></A></td>'
			+'		<td id=' + setUID('tabAlliance_taa_4') + ' width="65px" align=right><A><span>' + translate('Might') + '</span></A></td>'
			+'		<td width="60px" align=right>' + translate('Evol') + '</td>'
			+'	</tr>';
		for (var i=0; i<Data.dynamic.players.alliances.length; i++){
			var mightF = nombreFormate(Data.dynamic.players.alliances[i].might,' ');
			var found = false;
			var evol = 'x', diff = '';
			for (var old=0; old<Data.dynamic.players.alliances_evolution.length && !found; old++){
				if (Data.dynamic.players.alliances_evolution[old].id == Data.dynamic.players.alliances[i].id){
					evol = Data.dynamic.players.alliances[i].might - Data.dynamic.players.alliances_evolution[old].might;
					diff = Data.dynamic.players.alliances[i].count - (Data.dynamic.players.alliances_evolution[old].count || Data.dynamic.players.alliances[i].count);
					if (evol < 0) evol = '<span class=' + UID['red'] + '>' + nombreFormate(evol,' ') + '</span>';
					else if (evol > 0) evol = '<span class=' + UID['green'] + '>+' + nombreFormate(evol,' ') + '</span>';
					else evol = nombreFormate(evol,' ');
					if (diff < 0) diff = ' (<span class=' + UID['red'] + '>' + nombreFormate(diff,' ') + '</span>)';
					else if (diff > 0) diff = ' (<span class=' + UID['green'] + '>+' + nombreFormate(diff,' ') + '</span>)';
					else diff = '';
					found = true;
				}
			}
			m += '<tr><td align=center>' + Data.dynamic.players.alliances[i].rank + '</td>'
			+'	<td align=left>' + getAllianceRelationship(Data.dynamic.players.alliances[i].id, Data.dynamic.players.alliances[i].name) + '</td>'
			+'	<td align=left>' + Data.dynamic.players.alliances[i].lord + '</td>'
			+'	<td align=center>' + Data.dynamic.players.alliances[i].count + diff + '</td>'
			+'	<td align=right>' + mightF + '</td>'
			+'	<td align=right>' + evol + '</td>'
			+'</tr>';
		}
		document.getElementById(UID['tabAlliance_ResultList']).innerHTML = m + '</table>';
		document.getElementById(UID['tabAlliance_RefreshAlliances']).addEventListener ('click', refreshAlllianceList, false);
		for (var h=0; h<5; h++)
			document.getElementById(UID['tabAlliance_taa_' + h]).addEventListener ('click', sortAllianceList, false);

		function sortAllianceList (event){
			var t = Tabs.Alliance;
			var arg = event.target.parentNode.parentNode.id;
			if (arg == UID['tabAlliance_taa_0']){
				if (Data.options.alliance.sort_alliance == '0'){
					Data.dynamic.players.alliances.sort(function(a,b){return b.rank-a.rank});
					Data.options.alliance.sort_alliance = '-0';
				} else {
					Data.dynamic.players.alliances.sort(function(a,b){return a.rank-b.rank});
					Data.options.alliance.sort_alliance = '0';
				}
			} else if (arg == UID['tabAlliance_taa_1']){
				if (Data.options.alliance.sort_alliance == '1'){
					Data.dynamic.players.alliances.sort(function(a, b){a = a.name.toLowerCase(); b = b.name.toLowerCase(); if (a>b) return -1; if (a <b) return 1; return 0;});
					Data.options.alliance.sort_alliance = '-1';
				} else {
					Data.dynamic.players.alliances.sort(function(a, b){a = a.name.toLowerCase(); b = b.name.toLowerCase(); if (a>b) return 1; if (a <b) return -1; return 0;});
					Data.options.alliance.sort_alliance = '1';
				}
			} else if (arg == UID['tabAlliance_taa_2']){
				if (Data.options.alliance.sort_alliance == '2'){
					Data.dynamic.players.alliances.sort(function(a, b){a = a.lord.toLowerCase(); b = b.lord.toLowerCase(); if (a>b) return -1; if (a <b) return 1; return 0;});
					Data.options.alliance.sort_alliance = '-2';
				} else {
					Data.dynamic.players.alliances.sort(function(a, b){a = a.lord.toLowerCase(); b = b.lord.toLowerCase(); if (a>b) return 1; if (a <b) return -1; return 0;});
					Data.options.alliance.sort_alliance = '2';
				}
			} else if (arg == UID['tabAlliance_taa_3']){
				if (Data.options.alliance.sort_alliance == '3'){
					Data.dynamic.players.alliances.sort(function(a,b){return b.count-a.count});
					Data.options.alliance.sort_alliance = '-3';
				} else {
					Data.dynamic.players.alliances.sort(function(a,b){return a.count-b.count});
					Data.options.alliance.sort_alliance = '3';
				}
			} else if (arg == UID['tabAlliance_taa_4']){
				if (Data.options.alliance.sort_alliance == '4'){
					Data.dynamic.players.alliances.sort(function(a,b){return b.might-a.might});
					Data.options.alliance.sort_alliance = '-4';
				} else {
					Data.dynamic.players.alliances.sort(function(a,b){return a.might-b.might});
					Data.options.alliance.sort_alliance = '4';
				}
			}
			t.tabAlliances();
		}
		function refreshAlllianceList (){
			var t = Tabs.Alliance;
			if (t.checkAlliancesBusy)
				return false;
			t.checkAlliancesBusy = true;
			getAlliances(function(){logit(translate ('Alliances list retrieved')); Tabs.Alliance.checkAlliancesBusy = false});
			var now = serverTime();
			Data.options.alliance.alliance_update = new Date(now * 1000).myString();
			refreshDisplay ();
		}
		function refreshDisplay () {
			var t = Tabs.Alliance;
			if (t.checkAlliancesBusy)
				setTimeout (refreshDisplay,1000);
			else
				t.tabAlliances ();
		}
		function getAlliances (notify){
			var t = Tabs.Alliance;
			ret = [];
			if (Data.dynamic.players.alliances && Data.dynamic.players.alliances != undefined && Data.dynamic.players.alliances.length > 0)
				for (var i=0; i<Data.dynamic.players.alliances.length; i++)
					ret.push ({id:Data.dynamic.players.alliances[i].id, might:Data.dynamic.players.alliances[i].might, count:Data.dynamic.players.alliances[i].count});
			Data.dynamic.players.alliances_evolution = cloneProps(ret);
			Data.dynamic.players.alliances = {name:'', id:0, count:0, rank:0, might:0, lord:'', desc:''};
			var dial = new ModalDialog (t.container, 300, 165, '', false, null);
			dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>KabaListics : ' + translate('Message') + '</b></center></div>';
			dial.getContentDiv().innerHTML = translate ('Search for alliance list');
			MemberShips.fetchAlliances (callback);
			function callback (dat){
				if (dat==null){
					dial.getContentDiv().innerHTML = translate ('Error while retrieving the list of alliances');
					dial.allowClose (true);
					if (notify)
						notify (false);
					return;
				}
				if (dat.done){
					Data.dynamic.players.alliances	= cloneProps(dat.alliance);
					Data.dynamic.players.friends	= cloneProps(dat.friends);
					Data.dynamic.players.foes 		= cloneProps(dat.foes);
					logit ('*********  List retrieved ... Total members: '+ Data.dynamic.players.alliances.length);
					Data.dynamic.players.alliances.sort(function(a,b){return a.rank-b.rank});
					Data.options.alliance.sort_alliance = '0';
					if (notify)
						notify(true);
					dial.destroy();
				}
			}
		}
	},

	displayTotal : function (){
		var t = Tabs.Alliance;
		t.totalResources = 0;
		t.maxResources = 0;
		for (var r=0; r<transportable_resource_types.length; r++)
			t.totalResources = parseIntZero(t.totalResources) + parseIntZero(Data.options.alliance.data.resources[transportable_resource_types[r]]);
		for (var i=0; i<transport_unit_types.length; i++){
			if (Names.troops.byAbbr[transport_unit_types[i]][1] == 'Porter') var load = 200;
			else if (Names.troops.byAbbr[transport_unit_types[i]][1] == 'ArmoredTransport') var load = 5000;
			else if (Names.troops.byAbbr[transport_unit_types[i]][1] == 'PackDragon') var load = 6000;
			else var load = 0;
			var qty  = Data.options.alliance.data.transports[Names.troops.byAbbr[transport_unit_types[i]][1]];
			try {
				var load = Seed.stats.unit[Names.troops.byAbbr[transport_unit_types[i]][1]].load;
			} catch(e){
				actionLog('<B>' + translate('Troops load: ') + '</B>' + e.msg + ' ' + translate('Manifest not available, using defaults'));
			}
			t.maxResources = t.maxResources + (parseIntZero(qty) * parseIntZero(load));
		}
		var avail = nombreFormate(parseIntZero(t.maxResources) - parseIntZero(t.totalResources),' ');
		document.getElementById(UID['tabAlliance_Total']).innerHTML = '<B>' + nombreFormate(parseIntZero(t.totalResources),' ') + '</B> / <B>' +
		nombreFormate(parseIntZero(t.maxResources),' ') + '</B> (<B>' + avail + '</B> disponible)';
	},
	autoTransportTick : function (){
		var t = Tabs.Alliance, targetMsg, retryDelay, availableGeneral, transportUnits, resources, marchCount = 0;
		var cityId = Seed.cities[CAPITAL_ID].id;
		var cityIdx = CAPITAL_ID;
		clearTimeout (t.autoTimer);

		if (!Data.options.alliance.auto.enabled){
			return;
		}
		var found = false;
		for (var cid=1; cid < Seed.cities.length && !found; cid++) {
			if (Seed.cities[cid] && Data.options.alliance.auto_id == Seed.cities[cid].id) {
				found = true;
				var targetName = translate(Seed.cities[cid].name);
				var targetX = Seed.cities[cid].x;
				var targetY = Seed.cities[cid].y;
				targetMsg = translate('Transport sent to') + ' ' + targetName  + ' ' + translate ('at') + ' ' + targetX +','+ targetY;
			}
		}
		if (!found) {
			for (var i=0; i<Data.dynamic.players.memberships.length && !found; i++){
				if (Data.dynamic.players.memberships[i].id == Data.options.alliance.auto_id){
					found = true;
					var targetName = Data.dynamic.players.memberships[i].player;
					var targetCity = Data.dynamic.players.memberships[i].city;
					var targetX = Data.dynamic.players.memberships[i].x;
					var targetY = Data.dynamic.players.memberships[i].y;
				}
			}
			targetMsg = translate('Transport sent to') + ' ' + targetName  + ', ' + targetCity + ' ' + translate ('at') + ' ' + targetX +','+ targetY;
		}
		var min_time = 700000;
		var max_time = 0;
		for (id in Seed.marches){
			++marchCount;
			var left_time = ( Seed.marches[id].run_at - parseInt(serverTime()) ) + (Seed.marches[id].status=='marching' ? Seed.marches[id].duration : 0);
			if (left_time > 0) {
				min_time = min_time < left_time ? min_time : left_time;
				max_time = max_time > left_time ? max_time : left_time;
			}
		}
		if ( min_time === 700000 || max_time === 0 ) {
			min_time = 3;
		}
		retryDelay = min_time + Math.randRange(2,5);
		if (MyAjax.marchBusy > 0){
			MyAjax.marchBusy = marchCount;
			verboseLog(targetMsg + ' ' + translate('delayed due to pending march request') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(translate('Another march request is pending') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.autoTimer = setTimeout(t.autoTransportTick, retryDelay * 1000);
			return;
		}
		if (marchCount >= Data.options.alliance.auto.max_marches){
			verboseLog(targetMsg + ' ' + translate('delayed due to march limit reached') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(translate('March limit reached') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.autoTimer = setTimeout(t.autoTransportTick, retryDelay * 1000);
			return;
		}
		if (getMusterPointSlots(CAPITAL_ID) <= 0) {
			verboseLog(targetMsg + ' ' + translate('delayed due to muster point full') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(translate('Muster Point Full') + ': ' + translate('Retry in') + ' ' + retryDelay + ' '+translate('seconds'));
			t.autoTimer = setTimeout(t.autoTransportTick, retryDelay * 1000);
			return;
		}
		transportUnits = checkTroops(CAPITAL_ID, Data.options.alliance.auto.transports);
		if (transportUnits !== null) {
			verboseLog(targetMsg + ' ' + translate('delayed due to') + ' ' + transportUnits + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(transportUnits + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.autoTimer = setTimeout(t.autoTransportTick, retryDelay * 1000);
			return;
		}
		// check resources
		var resources = cloneProps(Data.options.alliance.auto.resources);
		var totalRess = 0;
		for (var p in resources) {
			var stock = Math.round(isEmpty(Seed.cities[CAPITAL_ID].resources[p],0));
			if (resources[p] > 0) {
				if (resources[p] > stock) resources[p] = stock;
				totalRess += resources[p];
			}
		}
		if (Data.options.alliance.auto.max_load) resources = maximizeDistribution (resources, Data.options.alliance.auto.transports);
		if (totalRess <= 0){
			verboseLog(targetMsg + ' ' + translate('no resources to transport') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.dispFeedback(translate('No resources to transport') + ': ' + translate('Retry in') + ' ' + retryDelay + ' ' + translate('seconds'));
			t.autoTimer = setTimeout(t.autoTransportTick, retryDelay * 1000);
			return;
		}
	
		// All prerequisite checks are done so march request can be sent
		verboseLog(targetMsg + ' '+translate('attempted'));
		new MyAjax.TransportMarch (cityId, targetX, targetY, Data.options.alliance.auto.transports, resources, 'transport', function (rslt){
			var t = Tabs.Alliance, transDelay, retryDelay;
			if (rslt.ok && rslt.dat.result.success){
				Marches.add(rslt.dat.result.job.march_id, 'transport');
				t.autoErrors = 0;
				transDelay = Math.floor(Math.random() * (Data.options.alliance.auto.delay_max - Data.options.alliance.auto.delay_min + 1) + Data.options.alliance.auto.delay_min);
				verboseLog(targetMsg + ' ' + translate('Successfully'));
				actionLog(targetMsg);
				t.dispFeedback (targetMsg);
				t.autoTimer = setTimeout (t.autoTransportTick, transDelay * 1000);
				if (Data.options.alliance.auto.recall) {
					var m = {cityId:cityId, marchId:rslt.dat.result.job.march_id, run_at:rslt.dat.result.job.run_at};
					Data.dynamic.recall_marches.push (m);
				}
				for (var x=0; x<transportable_resource_types.length; x++){
					var actualStock = nombreFormate(Math.round(isEmpty(Seed.cities[CAPITAL_ID].resources[transportable_resource_types[x]],0)));
					var UIDStk = UID['tabAlliance_AStk'] + '_' + x;
					if (document.getElementById(UIDStk)) document.getElementById(UIDStk).innerHTML = actualStock;
				}
				for (var y=0; y<transport_unit_types.length; ++y) {
					var trpStk = nombreFormate(parseIntZero(Seed.cities[CAPITAL_ID].units[Names.troops.byAbbr[transport_unit_types[y]][1]]),' ');
					var UIDTrpStk = UID['tabAlliance_ATStk'] + '_' + y;
					if (document.getElementById(UIDTrpStk)) document.getElementById(UIDTrpStk).innerHTML = '(&nbsp;'+ trpStk +'&nbsp;)';
				}
			} else {
				t.autoErrors++
				retryDelay = 30 * (t.autoErrors * t.autoErrors);
				verboseLog(targetMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg+ ' - ' + translate('Retry in') + ' ' + retryDelay  + ' ' + translate('seconds'));
				actionLog(targetMsg + ' ' + translate('failed'));
				if (rslt.status === 509){
					retryDelay = 600;
					verboseLog(targetMsg + ' ' + translate('failed') + ' - ' + translate('<b>Rate Limit Exceeded</b>, too many requests!') + ' - ' + translate('Retry in') + ' :' + retryDelay);
					t.dispFeedback(targetMsg + ' ' + translate('failed')+' - '+translate('Rate Limit Exceeded because there were too many requests') + ' - ' + translate('Retry in') +' '+ retryDelay);
				} else
					t.dispFeedback(targetMsg + ' ' + translate('failed'));
				t.autoTimer = setTimeout(t.autoTransportTick, retryDelay * 1000);
			}
		});
		function checkTroops (cityIdx, units){
			var totalTroops = 0;
			for (var p in units){
				unit_qty = parseInt(units[p]);
				if (unit_qty > 0){
					totalTroops += unit_qty;
					if (Seed.cities[cityIdx].units[p] < unit_qty){
						return (translate('Not enough') + ' ' + translate(p));
					}
				}
			}
			if (totalTroops <= 0){
				return (translate('No Troops Defined'));
			}
			var authMaxTroops = getMusterPointMaxTroops (cityIdx);
			for (var p in units) {
				unit_qty = parseInt(units[p]);
				if (unit_qty > 0){
					if (unit_qty > authMaxTroops ) {
						return (translate('Too many troops for muster point level'));
					}
				}
			}
			if (totalTroops > authMaxTroops) {
				return (translate('Too many troops for muster point level'));
			}
			if (getMusterPointSlots (cityIdx) <= 0){
				return (translate('Muster Point Full'));
			}
			return null;
		}
		function maximizeDistribution (res, units){
			var max_load = 0, current_load = 0, total_load = 0, new_stock = 0, avail_load = 0, stock_avail = 0;
			// get max load possible according to unit types and quantity
			for (var i=0; i<transport_unit_types.length; i++){
				if (Names.troops.byAbbr[transport_unit_types[i]][1] == 'Porter') var load = 200;
				else if (Names.troops.byAbbr[transport_unit_types[i]][1] == 'ArmoredTransport') var load = 5000;
				else if (Names.troops.byAbbr[transport_unit_types[i]][1] == 'PackDragon') var load = 6000;
				else var load = 0;
				var qty  = units[Names.troops.byAbbr[transport_unit_types[i]][1]];
				try {
					var load = Seed.stats.unit[Names.troops.byAbbr[transport_unit_types[i]][1]].load;
				} catch(e){}
				max_load = max_load + (parseIntZero(qty) * parseIntZero(load));
			}
			// get current load for each resource, total load, available load left, number of resources with stock
			var avail = nombreFormate(parseIntZero(t.maxResources) - parseIntZero(t.totalResources),' ');
			for (var p=0; p<transportable_resource_types.length; p++) {
				current_load = parseIntZero(res[transportable_resource_types[p]]);
				total_load   = parseIntZero(total_load) + current_load;
				new_stock    = Math.round(isEmpty(Seed.cities[CAPITAL_ID].resources[transportable_resource_types[p]],0)) - current_load;
				if (new_stock > 0) stock_avail++;
			}
			avail_load = parseIntZero(max_load) - parseIntZero(total_load);
			// Return current resource distribution if no load available for selected transports or if all resource stocks are empty
			if (avail_load <= 0 || stock_avail == 0) return (res);

			// Calculate new resource distribution if space left on transport and available stock
			var min_quantity = Math.round(avail_load / stock_avail); // get theorical minimum quantity to allocate
			while (avail_load > 0 && stock_avail > 0 && min_quantity > 0){
				// get the minimum quantity to allocate according to stock levels
				for (var r=0; r<transportable_resource_types.length; r++) {
					current_load = parseIntZero(res[transportable_resource_types[r]]);
					new_stock = Math.round(isEmpty(Seed.cities[CAPITAL_ID].resources[transportable_resource_types[r]],0)) - current_load;
					if (new_stock > 0 && new_stock < min_quantity) min_quantity = new_stock;
				}
				stock_avail = 0;
				// Add minimum quantity to allocate to the resource to send if enough stock
				for (var r=0; r<transportable_resource_types.length; r++) {
					current_load = parseIntZero(res[transportable_resource_types[r]]);
					new_stock = Math.round(isEmpty(Seed.cities[CAPITAL_ID].resources[transportable_resource_types[r]],0)) - current_load;
					if (new_stock > 0) {
						res[transportable_resource_types[r]] = current_load + min_quantity;
						avail_load = avail_load - min_quantity;
						new_stock  = new_stock  - min_quantity;
						if (new_stock > 0) stock_avail++;
					}
				}
				// get new theorical minimum quantity to allocate
				min_quantity = Math.round(avail_load / stock_avail); // get theorical minimum quantity to allocate
			}
			return (res);
		}
	},
	dispFeedback : function (msg){
		if (msg && msg!='')
		msg = new Date().toTimeString().substring (0,8) +' '+ msg;
		if (document.getElementById(UID['tabAlliance_Feedback']))
			document.getElementById(UID['tabAlliance_Feedback']).innerHTML = msg;
	},
	marchTick : function (){
		var t = Tabs.Alliance;
		clearTimeout (t.marchTimer);
		if (document.getElementById(UID['tabAlliance_AMarches']))
			Marches.updateTable ( document.getElementById(UID['tabAlliance_AMarches']), 'transport' );
		t.marchTimer = setTimeout (t.marchTick, 1000);
	},
	setEnable : function (onOff){
		var t = Tabs.Alliance;
		var but = document.getElementById(UID['tabAlliance_AOnOff']);
		Data.options.alliance.auto.enabled = onOff;
		if (but) {
			if (onOff){
				but.value = translate('Enabled').toUpperCase();
				but.className = UID['btn_on'];
				if (!t.autoTimer) t.autoTransportTick();
			} else {
				if (t.autoTimer) clearTimeout (t.autoTimer);
				but.value = translate('Disabled').toUpperCase();
				but.className = UID['btn_off'];
			}
		}
	},
}
// Jawz *********************************** Alliance features Tab ****************************************


// Jawz *********************************** Leaderboards Tab ****************************************
Tabs.Leaderboards = {
	tabOrder       : LEADERBOARD_TAB_ORDER,
	tabLabel       : 'Leaderboards',
	tabDisabled    : !LEADERBOARD_TAB_ENABLE,
	container      : null,
	contentType    : 0, // 0 = Alliance, 1 = Player
	lastSubTab     : 'tabLeaderboardsAlliance',
	checkLeaderboardsBusy	: false,
	checkLeaderboardsError	: false,
	subTabContentType	: 0,
	tops_to_refresh		: false,

	init : function (div){
		var t = Tabs.Leaderboards;
		t.container = div;
		Data.setDefaultValues ('leaderboard');
		var m = '<div class=' + UID['title'] + '>' + translate('Leaderboard') + '</div>'
			+'<ul class=tabs>'
			+'	<li class="tab first"><a id='+ setUID('tabLeaderboardsAlliance') +'>'+ translate('leaderboard-by-alliance') +'</a></li>'
			+'	<li class=tab><a id='+ setUID('tabLeaderboardsPlayer') +'>'+ translate('leaderboard-by-player') +'</a></li>'
			+'</ul>'
			+'<div id='+ setUID('tabLeaderboards_Content') +' style="padding-top:0px; height:670px; ; max-height:670px; overflow-y:auto"></div>';

		t.container.innerHTML = m;
		document.getElementById(UID['tabLeaderboardsAlliance']).addEventListener ('click', function(){t.tops_to_refresh = true; t.tabLeaderboardsAlliance();}, false);	
		document.getElementById(UID['tabLeaderboardsPlayer']).addEventListener ('click', function(){t.tops_to_refresh = true; t.tabLeaderboardsPlayer();}, false);	
		window.addEventListener('unload', t.onUnload, false);
		t.contentType = isEmpty(Data.options.leaderboards.current_tab,0);
		t.show();
	},

	show : function (){
		var t = Tabs.Leaderboards;
		if (!t.checkLeaderboardsBusy) {
			t.checkLeaderboardsError = false;
			switch (isEmpty(t.contentType, 0)) {
				case 0: t.tabLeaderboardsAlliance(); break;
				case 1: t.tabLeaderboardsPlayer(); break;
			}
		} else setTimeout(t.show, 100);
	},

	onUnload : function (){
		var t = Tabs.Leaderboards;
		logit ('===============  Tabs.Leaderboards.onUnload');
		Data.options.leaderboards.current_tab = t.contentType;
		Data.stats.leaderboards.alliance = {};
		Data.stats.leaderboards.player	 = {};
	},

	hide : function (){
	},

	refreshList : function (){
		var t = Tabs.Leaderboards;
		if (t.checkLeaderboardsBusy || t.checkLeaderboardsError)
			return false;
		t.checkLeaderboardsBusy = true;
		t.getLeaderboards(function(){logit(translate ('Leaderboards retrieved')); Tabs.Leaderboards.checkLeaderboardsBusy = false; Tabs.Leaderboards.tops_to_refresh = false;});
		t.show ();
	},

	getLeaderboards : function (notify){
		var t = Tabs.Leaderboards;
		var dial = new ModalDialog (t.container, 300, 165, '', false, null);
		dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>KabaListics : ' + translate('Message') + '</b></center></div>';
		dial.getContentDiv().innerHTML = translate ('Retrieving leaderboards');
		MyLeaderboards.fetchLeaderboards (Data.options.leaderboards.current_subtab,
										  Data.options.leaderboards.current_tab,
										  Data.options.leaderboards.week_sel,
										  Data.options.leaderboards.scope_sel,
										  callback, false);
		function callback (dat){
			if (dat==null || dat.error){
				Tabs.Leaderboards.checkLeaderboardsError = true;
				dial.getContentDiv().innerHTML = translate ('Error while retrieving the leaderboards' + (dat.error ? ' : '+translate(dat.error) : ''));
				dial.allowClose (true);
				if (notify)
					notify (false);
				return;
			}
			//logit('Update LeaderBoards dat = '+inspectObj(dat,8,1));
			if (dat.done){
				var id_week = Data.options.leaderboards.week_sel;
				var id_scope = Data.options.leaderboards.scope_sel;
				dat.my.sort( function(a,b){return a.rank - b.rank;} );
				dat.raising.sort( function(a,b){return b.change - a.change;} );
				dat.top.sort( function(a,b){return a.rank - b.rank;} );
				if (Data.options.leaderboards.current_tab == 0) {
					switch (Data.options.leaderboards.current_subtab) {
						case 0 : Data.stats.leaderboards.alliance.offensive_kills[id_week]	= cloneProps(dat); break;
						case 1 : Data.stats.leaderboards.alliance.defensive_kills[id_week]	= cloneProps(dat); break;
						case 2 : Data.stats.leaderboards.alliance.power_taken[id_week]		= cloneProps(dat); break;
						case 3 : Data.stats.leaderboards.alliance.power_gained[id_week]		= cloneProps(dat); break;
					}
				} else {
					switch (Data.options.leaderboards.current_subtab) {
						case 0 : Data.stats.leaderboards.player.offensive_kills[id_scope][id_week]	= cloneProps(dat); break;
						case 1 : Data.stats.leaderboards.player.defensive_kills[id_scope][id_week]	= cloneProps(dat); break;
						case 2 : Data.stats.leaderboards.player.power_taken[id_scope][id_week]		= cloneProps(dat); break;
					}
				}
				logit ('*********  Leaderbord retrieved ... Total My: '+ dat.my.length + ', Total Raising: '+dat.raising.length + ', Total Top: '+dat.top.length);
				if (notify)
					notify(true);
				dial.destroy();
			}
		}
	},

	refreshTops : function (){
		var t = Tabs.Leaderboards;
		if (t.checkLeaderboardsBusy || t.checkLeaderboardsError)
			return false;
		t.checkLeaderboardsBusy = true;
		t.getTops(function(){logit(translate ('Leaderboards retrieved')); Tabs.Leaderboards.checkLeaderboardsBusy = false; Tabs.Leaderboards.tops_to_refresh = false;});
		t.show ();
	},

	getTops : function (notify){
		var t = Tabs.Leaderboards;
		var dial = new ModalDialog (t.container, 300, 165, '', false, null);
		dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>KabaListics : ' + translate('Message') + '</b></center></div>';
		dial.getContentDiv().innerHTML = translate ('Retrieving leaderboards');
		MyLeaderboards.fetchTops (Data.options.leaderboards.current_subtab,
								  Data.options.leaderboards.current_tab,
								  Data.options.leaderboards.week_sel,
								  Data.options.leaderboards.scope_sel,
								  callback, false);
		function callback (dat){
			if (dat==null || dat.error){
				Tabs.Leaderboards.checkLeaderboardsError = true;
				dial.getContentDiv().innerHTML = translate ('Error while retrieving the leaderboards' + (dat.error ? ' : '+translate(dat.error) : ''));
				dial.allowClose (true);
				if (notify)
					notify (false);
				return;
			}
			//logit('Update LeaderBoards dat = '+inspectObj(dat,8,1));
			if (dat.done){
				var id_week = Data.options.leaderboards.week_sel;
				var id_scope = Data.options.leaderboards.scope_sel;
				dat.top.sort( function(a,b){return a.rank - b.rank;} );
				if (Data.options.leaderboards.current_tab == 0) {
					switch (Data.options.leaderboards.current_subtab) {
						case 0 : Data.stats.leaderboards.alliance.offensive_kills[id_week].top	= cloneProps(dat.top); break;
						case 1 : Data.stats.leaderboards.alliance.defensive_kills[id_week].top	= cloneProps(dat.top); break;
						case 2 : Data.stats.leaderboards.alliance.power_taken[id_week].top		= cloneProps(dat.top); break;
						case 3 : Data.stats.leaderboards.alliance.power_gained[id_week].top		= cloneProps(dat.top); break;
					}
				} else {
					switch (Data.options.leaderboards.current_subtab) {
						case 0 : Data.stats.leaderboards.player.offensive_kills[id_scope][id_week].top	= cloneProps(dat.top); break;
						case 1 : Data.stats.leaderboards.player.defensive_kills[id_scope][id_week].top	= cloneProps(dat.top); break;
						case 2 : Data.stats.leaderboards.player.power_taken[id_scope][id_week].top		= cloneProps(dat.top); break;
					}
				}
				if (dat.last_refresh) Data.stats.leaderboards.last_refresh = dat.last_refresh;
				logit ('*********  Leaderbord Tops retrieved ... Total Top: '+dat.top.length);
				if (notify)
					notify(true);
				dial.destroy();
			}
		}
	},

	//** LEADERBOARDS BY ALLIANCE SUB-TAB ***
	tabLeaderboardsAlliance : function (){
		var t = Tabs.Leaderboards;
		document.getElementById(UID[t.lastSubTab]).className='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabLeaderboardsAlliance']).className='selected';
		document.getElementById(UID['tabLeaderboardsAlliance']).style.zIndex=1;
		t.lastSubTab = 'tabLeaderboardsAlliance';
		t.contentType = 0;
		Data.options.leaderboards.current_tab = t.contentType;
		var m = '<div class=' + UID['title'] + '>'+ translate('Leaderboard') +' - '+ translate('leaderboard-by-alliance') +'</div>'
			+'<div style="margin-bottom: 5px !important">' // class=' + UID['status_ticker'] + '
			+'	<ul class=tabs>'
			+'		<li class="tab first"><a id='+ setUID('tabLeaderBoardsAllianceOK') +'>'+ translate('leaderboard-offensive-kills-title') +'</a></li>'
			+'		<li class="tab"><a id='+ setUID('tabLeaderBoardsAllianceDK') +'>'+ translate('leaderboard-defensive-kills-title') +'</a></li>'
			+'		<li class="tab"><a id='+ setUID('tabLeaderBoardsAlliancePT') +'>'+ translate('leaderboard-power-taken-title') +'</a></li>'
			+'		<li class="tab"><a id='+ setUID('tabLeaderBoardsAlliancePG') +'>'+ translate('leaderboard-power-gained-title') +'</a></li>'
			+'	</ul>'
			+'	<div id='+ setUID('tabLeaderboardsAlliance_Content') +' style="height:610px; ; max-height:610px; overflow-y:auto">'
			+'	</div>'
			+'</div>';
		document.getElementById(UID['tabLeaderboards_Content']).innerHTML = m;
		document.getElementById(UID['tabLeaderBoardsAllianceOK']).addEventListener ('click', function() {t.tabLeaderboardsContent(false, 'OK');}, false);
		document.getElementById(UID['tabLeaderBoardsAllianceDK']).addEventListener ('click', function() {t.tabLeaderboardsContent(false, 'DK');}, false);
		document.getElementById(UID['tabLeaderBoardsAlliancePT']).addEventListener ('click', function() {t.tabLeaderboardsContent(false, 'PT');}, false);
		document.getElementById(UID['tabLeaderBoardsAlliancePG']).addEventListener ('click', function() {t.tabLeaderboardsContent(false, 'PG');}, false);
		switch (t.subTabContentType || 0) {
			case 0: t.tabLeaderboardsContent(false, 'OK'); break;
			case 1: t.tabLeaderboardsContent(false, 'DK'); break;
			case 2: t.tabLeaderboardsContent(false, 'PT'); break;
			case 3: t.tabLeaderboardsContent(false, 'PG'); break;
		}
	},

	//** LEADERBOARDS BY PLAYER SUB-TAB ***
	tabLeaderboardsPlayer : function (){
		var t = Tabs.Leaderboards;
		document.getElementById(UID[t.lastSubTab]).className='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabLeaderboardsPlayer']).className='selected';
		document.getElementById(UID['tabLeaderboardsPlayer']).style.zIndex=1;
		t.lastSubTab = 'tabLeaderboardsPlayer';
		t.contentType = 1;
		Data.options.leaderboards.current_tab = t.contentType;
		var m = '<div class=' + UID['title'] + '>'+ translate('Leaderboard') +' - '+ translate('leaderboard-by-player') +'</div>'
			+'<div style="margin-bottom: 5px !important">' // class=' + UID['status_ticker'] + '
			+'	<ul class=tabs>'
			+'		<li class="tab first"><a id='+ setUID('tabLeaderBoardsPlayerOK') +'>'+ translate('leaderboard-offensive-kills-title') +'</a></li>'
			+'		<li class="tab"><a id='+ setUID('tabLeaderBoardsPlayerDK') +'>'+ translate('leaderboard-defensive-kills-title') +'</a></li>'
			+'		<li class="tab"><a id='+ setUID('tabLeaderBoardsPlayerPT') +'>'+ translate('leaderboard-power-taken-title') +'</a></li>'
			+'	</ul>'
			+'	<div id='+ setUID('tabLeaderboardsPlayer_Content') +' style="height:610px; ; max-height:610px; overflow-y:auto">'
			+'	</div>'
			+'</div>';
		document.getElementById(UID['tabLeaderboards_Content']).innerHTML = m;
		document.getElementById(UID['tabLeaderBoardsPlayerOK']).addEventListener ('click', function() {t.tabLeaderboardsContent(true, 'OK');}, false);
		document.getElementById(UID['tabLeaderBoardsPlayerDK']).addEventListener ('click', function() {t.tabLeaderboardsContent(true, 'DK');}, false);
		document.getElementById(UID['tabLeaderBoardsPlayerPT']).addEventListener ('click', function() {t.tabLeaderboardsContent(true, 'PT');}, false);
		switch (t.subTabContentType || 0) {
			case 0: t.tabLeaderboardsContent(true, 'OK'); break;
			case 1: t.tabLeaderboardsContent(true, 'DK'); break;
			case 2: t.tabLeaderboardsContent(true, 'PT'); break;
		}
	},

	tabLeaderboardsContent : function (by_player, type){
		var t = Tabs.Leaderboards;
		var week_id = Data.options.leaderboards.week_sel;
		var scope_id = Data.options.leaderboards.scope_sel;
		if (by_player) {
			var cible = 'tabLeaderboardsPlayer_Content';
			var top_desc = translate('players');
			switch (type) {
				case 'OK' :
					document.getElementById(UID['tabLeaderBoardsPlayerOK']).className = 'selected';
					document.getElementById(UID['tabLeaderBoardsPlayerOK']).style.zIndex=1;
					document.getElementById(UID['tabLeaderBoardsPlayerDK']).className = '';
					document.getElementById(UID['tabLeaderBoardsPlayerDK']).style.zIndex=0;
					document.getElementById(UID['tabLeaderBoardsPlayerPT']).className = '';
					document.getElementById(UID['tabLeaderBoardsPlayerPT']).style.zIndex=0;
					t.subTabContentType = 0;
					Data.options.leaderboards.current_subtab = t.subTabContentType;
					var source = cloneProps(Data.stats.leaderboards.player.offensive_kills[scope_id][week_id]);
					var head_text = translate('leaderboard-offensive-kills-description');
					break;
				case 'DK' :
					document.getElementById(UID['tabLeaderBoardsPlayerOK']).className = '';
					document.getElementById(UID['tabLeaderBoardsPlayerOK']).style.zIndex=0;
					document.getElementById(UID['tabLeaderBoardsPlayerDK']).className = 'selected';
					document.getElementById(UID['tabLeaderBoardsPlayerDK']).style.zIndex=1;
					document.getElementById(UID['tabLeaderBoardsPlayerPT']).className = '';
					document.getElementById(UID['tabLeaderBoardsPlayerPT']).style.zIndex=0;
					t.subTabContentType = 1;
					Data.options.leaderboards.current_subtab = t.subTabContentType;
					var source = cloneProps(Data.stats.leaderboards.player.defensive_kills[scope_id][week_id]);
					var head_text = translate('leaderboard-defensive-kills-description');
					break;
				case 'PT' :
					document.getElementById(UID['tabLeaderBoardsPlayerOK']).className = '';
					document.getElementById(UID['tabLeaderBoardsPlayerOK']).style.zIndex=0;
					document.getElementById(UID['tabLeaderBoardsPlayerDK']).className = '';
					document.getElementById(UID['tabLeaderBoardsPlayerDK']).style.zIndex=0;
					document.getElementById(UID['tabLeaderBoardsPlayerPT']).className = 'selected';
					document.getElementById(UID['tabLeaderBoardsPlayerPT']).style.zIndex=1;
					t.subTabContentType = 2;
					Data.options.leaderboards.current_subtab = t.subTabContentType;
					var source = cloneProps(Data.stats.leaderboards.player.power_taken[scope_id][week_id]);
					var head_text = translate('leaderboard-power-taken-description');
					break;
			}
		} else {
			var cible = 'tabLeaderboardsAlliance_Content';
			var top_desc = translate('alliances');
			switch (type) {
				case 'OK' :
					document.getElementById(UID['tabLeaderBoardsAllianceOK']).className = 'selected';
					document.getElementById(UID['tabLeaderBoardsAllianceOK']).style.zIndex=1;
					document.getElementById(UID['tabLeaderBoardsAllianceDK']).className = '';
					document.getElementById(UID['tabLeaderBoardsAllianceDK']).style.zIndex=0;
					document.getElementById(UID['tabLeaderBoardsAlliancePT']).className = '';
					document.getElementById(UID['tabLeaderBoardsAlliancePT']).style.zIndex=0;
					document.getElementById(UID['tabLeaderBoardsAlliancePG']).className = '';
					document.getElementById(UID['tabLeaderBoardsAlliancePG']).style.zIndex=0;
					t.subTabContentType = 0;
					Data.options.leaderboards.current_subtab = t.subTabContentType;
					var source = cloneProps(Data.stats.leaderboards.alliance.offensive_kills[week_id]);
					var head_text = translate('leaderboard-offensive-kills-description');
					break;
				case 'DK' :
					document.getElementById(UID['tabLeaderBoardsAllianceOK']).className = '';
					document.getElementById(UID['tabLeaderBoardsAllianceOK']).style.zIndex=0;
					document.getElementById(UID['tabLeaderBoardsAllianceDK']).className = 'selected';
					document.getElementById(UID['tabLeaderBoardsAllianceDK']).style.zIndex=1;
					document.getElementById(UID['tabLeaderBoardsAlliancePT']).className = '';
					document.getElementById(UID['tabLeaderBoardsAlliancePT']).style.zIndex=0;
					document.getElementById(UID['tabLeaderBoardsAlliancePG']).className = '';
					document.getElementById(UID['tabLeaderBoardsAlliancePG']).style.zIndex=0;
					t.subTabContentType = 1;
					Data.options.leaderboards.current_subtab = t.subTabContentType;
					var source = cloneProps(Data.stats.leaderboards.alliance.defensive_kills[week_id]);
					var head_text = translate('leaderboard-defensive-kills-description');
					break;
				case 'PT' :
					document.getElementById(UID['tabLeaderBoardsAllianceOK']).className = '';
					document.getElementById(UID['tabLeaderBoardsAllianceOK']).style.zIndex=0;
					document.getElementById(UID['tabLeaderBoardsAllianceDK']).className = '';
					document.getElementById(UID['tabLeaderBoardsAllianceDK']).style.zIndex=0;
					document.getElementById(UID['tabLeaderBoardsAlliancePT']).className = 'selected';
					document.getElementById(UID['tabLeaderBoardsAlliancePT']).style.zIndex=1;
					document.getElementById(UID['tabLeaderBoardsAlliancePG']).className = '';
					document.getElementById(UID['tabLeaderBoardsAlliancePG']).style.zIndex=0;
					t.subTabContentType = 2;
					Data.options.leaderboards.current_subtab = t.subTabContentType;
					var source = cloneProps(Data.stats.leaderboards.alliance.power_taken[week_id]);
					var head_text = translate('leaderboard-power-taken-description');
					break;
				case 'PG' :
					document.getElementById(UID['tabLeaderBoardsAllianceOK']).className = '';
					document.getElementById(UID['tabLeaderBoardsAllianceOK']).style.zIndex=0;
					document.getElementById(UID['tabLeaderBoardsAllianceDK']).className = '';
					document.getElementById(UID['tabLeaderBoardsAllianceDK']).style.zIndex=0;
					document.getElementById(UID['tabLeaderBoardsAlliancePT']).className = '';
					document.getElementById(UID['tabLeaderBoardsAlliancePT']).style.zIndex=0;
					document.getElementById(UID['tabLeaderBoardsAlliancePG']).className = 'selected';
					document.getElementById(UID['tabLeaderBoardsAlliancePG']).style.zIndex=1;
					t.subTabContentType = 3;
					Data.options.leaderboards.current_subtab = t.subTabContentType;
					var source = cloneProps(Data.stats.leaderboards.alliance.power_gained[week_id]);
					var head_text = translate('leaderboard-power-gained-description');
					break;
			}
		}
		if ((!source || source == undefined || source == null) ||
			(source && (!source.raising || source.raising == undefined || source.raising == null))) {
			t.refreshList();
		} else {
			if (t.tops_to_refresh == true) t.refreshTops();
		}
		var m = '<div class=' + UID['status_ticker'] + ' style="height:600px; max-height:600px; overflow:auto; white-space:nowrap; margin-top:1px !important">'
			+'	<table width=100%>'
			+'		<td width=33%><label>' + translate('from') + ' :</label>'
			+'			<select id='+setUID('tabLeaderboards_week')+'>'
			+'				<option value=0 '+ (Data.options.leaderboards.week_sel == 0 ? 'selected' : '') +'>'+ translate('leaderboard-this-week') +'</option>'
			+'				<option value=1 '+ (Data.options.leaderboards.week_sel == 1 ? 'selected' : '') +'>'+ translate('leaderboard-past-week') +'</option>'
			+'				<option value=2 '+ (Data.options.leaderboards.week_sel == 2 ? 'selected' : '') +'>'+ translate('leaderboard-all-time') +'</option>'
			+'			</select>'
			+'		</td>';
		if (by_player) {
			m += '		<td width=33%><label>' + translate('across') + ' :</label>'
				+'			<select id='+setUID('tabLeaderboards_scope')+'>'
				+'				<option value=0 '+ (Data.options.leaderboards.scope_sel == 0 ? 'selected' : '') +'>'+ translate('leaderboard-current-realm') +'</option>'
				+'				<option value=1 '+ (Data.options.leaderboards.scope_sel == 1 ? 'selected' : '') +'>'+ translate('leaderboard-your-alliance') +'</option>'
				+'			</select>'
				+'		</td>';
		}
		m += '	</tr></table><br>';
		if (head_text && head_text != '' && head_text != null) {
			m += '	<table class='+UID['table_console']+' cellspacing=1 width=100%>'
				+'		<tr><td class=' + UID['underline'] + ' width=100%>' + translate(head_text) + '</td></tr>'
				+'	</table>';
		}
		m += '	<br><div class=' + UID['subtitle'] + '><font color=yellow>' + translate('leaderboard-your-alliance-rank') +'</font></div>'
			+'	<div id=' + setUID('tabLeaderboards_My') + ' class=' + UID['status_ticker'] + ' style="overflow:auto; white-space:nowrap; margin-top:1px !important"></div>'
			+'	<br><div class=' + UID['subtitle'] + '><font color=yellow>' + translate('top') + ' 500 ' + top_desc +'</font></div>'
			+'	<div id=' + setUID('tabLeaderboards_Top') + ' class=' + UID['status_ticker'] + ' style="height:290px; max-height:290px; overflow:auto; white-space:nowrap; margin-top:1px !important"></div>'
			+'	<br><div class=' + UID['subtitle'] + '><font color=yellow>' + translate('top') + ' 3 ' + top_desc + ' - ' + translate('leaderboard-change-last-week') +'</font></div>'
			+'	<div id=' + setUID('tabLeaderboards_Raising') + ' class=' + UID['status_ticker'] + ' style="height:65px; max-height:65px; overflow:auto; white-space:nowrap; margin-top:1px !important"></div>';
		if (Data.stats.leaderboards.last_refresh) {
			var time_text = translate('leaderboard-last-refresh-time-singular');
			var last_time = getTime(Data.stats.leaderboards.last_refresh);
			var time = timestr(serverTime()-parseInt(last_time/1000), true);
			if (time_text.indexOf('<br>') > 0)
				time_text = time_text.substring(0,time_text.indexOf('<br>')) + ' ' + time_text.substring(time_text.indexOf('<br>') + 4);
			if (time_text.indexOf('$updateTime') > 0)
				time_text = time_text.substring(0,time_text.indexOf('$updateTime')) + time + time_text.substring(time_text.indexOf('$updateTime') + 13);
			else
				time_text = time_text + ' ' + time;
			m += '	<br><table class='+UID['table_console']+' cellspacing=1 width=100%>'
				+'		<tr><td class=' + UID['underline'] + ' width=100%><font color=' + TIMER_COLOR + '><b>' + time_text + '</b></font></td></tr>'
				+'	</table>';
		}
		m += '</div>';
		document.getElementById(UID[cible]).innerHTML = m;
		if (source) {
			if (source.my)		t.displaySubContent('tabLeaderboards_My', by_player, source.my, 0);
			if (source.top)		t.displaySubContent('tabLeaderboards_Top', by_player, source.top, 0);
			if (source.raising)	t.displaySubContent('tabLeaderboards_Raising', by_player, source.raising, 3);
		}
		document.getElementById(UID['tabLeaderboards_week']).addEventListener ('change', function(event){
			var el = event.target;
			if (Data.options.leaderboards.week_sel != parseInt(el.options[el.selectedIndex].value)) t.tops_to_refresh = true;
			Data.options.leaderboards.week_sel = parseInt(el.options[el.selectedIndex].value);
			t.tabLeaderboardsContent (by_player, type);
		}, false);
		if (by_player) {
			document.getElementById(UID['tabLeaderboards_scope']).addEventListener ('change', function(event){
				var el = event.target;
				if (Data.options.leaderboards.scope_sel != parseInt(el.options[el.selectedIndex].value)) t.tops_to_refresh = true;
				Data.options.leaderboards.scope_sel = parseInt(el.options[el.selectedIndex].value);
				t.tabLeaderboardsContent (by_player, type);
			}, false);
		}
		function getTime (str) {
			var result = 0;
			if (str.length>=19) {
				var year = parseInt(str.substr(0,4));
				var month = parseInt(str.substr(5,2))-1;
				if (month <= 0) month = parseInt(str.substr(6,1))-1;
				var day = parseInt(str.substr(8,2));
				if (day == 0) day = parseInt(str.substr(9,1));
				var hours = parseInt(str.substr(11,2));
				if (hours == 0) hours = parseInt(str.substr(12,1));
				var minutes = parseInt(str.substr(14,2));
				if (minutes == 0) minutes = parseInt(str.substr(15,1));
				var seconds = parseInt(str.substr(17,2));
				if (seconds == 0) seconds = parseInt(str.substr(18,1));
logit('result = new Date(Date.UTC('+year+', '+month+', '+day+', '+hours+', '+minutes+', '+seconds+')');
				result = new Date(Date.UTC(year, month, day, hours, minutes, seconds));
			}
			return result;
		}
	},

	displaySubContent : function (target_div, by_player, data, limit){
		var t = Tabs.Leaderboards;
		var m = '<table class=' + UID['row_style'] + '>'
			+'	<tr class=' + UID['row_headers'] +'>'
			+'		<td width="40px">' + translate('Rank') + '</td>'
			+'		<td width="55px">' + translate('Evol') + '</td>'
			+'		<td width="200px" style="overflow-x:auto">' + translate('Alliance') + '</td>';
		if (by_player) m += '<td width="180px" style="overflow-x:auto">' + translate('Player name') + '</td>';
		m += '		<td width="55px" align=right>' + translate('Kills') + '</td>'
			+'	</tr>';
		var max = limit;
		if (limit == 0) max = data.length;
		for (var i=0; i<max; i++){
			var evol = 'x';
			var alliance = '';
			if (isNaN(data[i].change) || !data[i].change || data[i].change == null) data[i].change = 0;
			if (data[i].change < 0) evol = '<span class=' + UID['red'] + '>' + nombreFormate(data[i].change,' ') + '</span>';
			else if (data[i].change > 0) evol = '<span class=' + UID['green'] + '>+' + nombreFormate(data[i].change,' ') + '</span>';
			else evol = nombreFormate(data[i].change,' ');
			var own = Seed.player.alliance ? Seed.player.alliance.name : '-1';
			if (data[i].alliance == own) alliance = '<span class=' + UID['blue'] + '>' + data[i].alliance + '</span>';
			else {
				if (data[i].diplomacy == 'enemy') alliance = '<span class=' + UID['red'] + '>' + data[i].alliance + '</span>';
				else if (data[i].diplomacy == 'friendly') alliance = '<span class=' + UID['green'] + '>' + data[i].alliance + '</span>';
				else alliance = data[i].alliance;
			}
			var score = nombreFormate(data[i].score,' ');
			m += '<tr><td align=center>' + ((limit == 0) ? data[i].rank : i+1) + '</td>'
			+'	<td align=center>' + evol + '</td>'
			+'	<td align=left>' + alliance + '</td>';
			if (by_player) m += '<td align=left>' + data[i].player + '</td>';
			m += '<td align=right>' + score + '</td>'
			+'</tr>';
		}
		document.getElementById(UID[target_div]).innerHTML = m + '</table>';
	},
}
// Jawz *********************************** Leaderboards Tab ****************************************


// Jawz *********************************** Map search Tab *********************************************
Tabs.Search = {
	tabOrder		: SEARCH_TAB_ORDER,
	tabLabel		: 'Map',
	tabDisabled		: !SEARCH_TAB_ENABLE,
	container		: null,
	checkMapBusy	: false,
	MAX_DISTANCE	: 75,
	contentType		: 0, // 0 = cities list, 1 = Wildernesses list
	lastSubTab    	: 'tabSearchC',

	init : function (div){
		var t = Tabs.Search;
		Data.setDefaultValues ('search');

		t.container = div;
		var m = '<div class=' + UID['title'] + '>'+ translate('Map Search') +'</div>'
			+'<div class=' + UID['content'] + '>'
			+'	<div>'
			+'		<b>'+ translate('Search coords') +':&nbsp;</b>&nbsp;'
			+'		X: <input id=' + setUID('tabSearch_CoordsX') + ' size=2 maxlength=3 type=text value="'+ Data.options.search.target.x +'" /> '
			+'		Y: <input id=' + setUID('tabSearch_CoordsY') + ' size=2 maxlength=3 type=text value="'+ Data.options.search.target.y +'" /> '
			+'		&nbsp <b>'+ translate('Search max radius') +':</b>'
			+'	<select id='+setUID('tabSearch_MaxRadius')+'>';
			for (var i=7; i <= 35; i+=7){
				m +='		<option value="'+ i +'" '+ (Data.options.search.target.distance == i ? 'selected' : '') +'>'+i+'</option>';
			}
			m += '	</select>'
			+'		<input id=' + setUID('tabSearch_Refresh') + ' type=button value="' + translate('Refresh map data') + '" />'
			+'		<BR>'
			+'		<div class=' + UID['status_ticker'] + ' style="height:auto !important;margin:5px 10px !important;">'
			+'			<center><span id=' + setUID('tabSearch_Tile') + '></span></center>'
			+'		</div>'
			+'	</div>'
			+'	<br>'
			+'	<table class=' + UID['table'] + '>'
			+'		<tr><td class=left>' + translate('Alliance') + ':</td>'
			+'			<td><div id=' + setUID('tabSearch_Alliance') + '></div></td>'
			+'			<td><input id=' + setUID('tabSearch_NewList') + ' type=button value="' + translate('Refresh') + '" /></td>'
			+'		</tr>'
			+'		<tr><td class=left>' + translate('Player name') + ':</td>'
			+'			<td><div id=' + setUID('tabSearch_Players') + '></div></td>'
			+'		</tr>'
			+'	</table>'
			+'</div>'
			+'<ul class=tabs>'
			+'	<li class="tab first"><a id='+ setUID('tabSearchC') +'>'+ translate('Player cities') +'</a></li>'
			+'	<li class=tab><a id='+ setUID('tabSearchW') +'>'+ translate('Wildernesses') +'</a></li>'
			+'</ul>'
			+'<div id='+ setUID('tabSearch_Content') +' style="padding-top:none; height:525px; ; max-height:525px; overflow-x:auto; overflow-y:auto"></div>';
		t.container.innerHTML = m;
		document.getElementById(UID['tabSearch_CoordsX']).addEventListener ('change', t.eventCoords, false);
		document.getElementById(UID['tabSearch_CoordsY']).addEventListener ('change', t.eventCoords, false);
		document.getElementById(UID['tabSearch_MaxRadius']).addEventListener ('change', function(event){
			var el = event.target;
			Data.options.search.target.distance = parseInt(el.options[el.selectedIndex].value);
			t.show();
		}, false);
		document.getElementById(UID['tabSearch_Refresh']).addEventListener ('click', function(){t.refreshMapData(false);}, false);
		document.getElementById(UID['tabSearch_Alliance']).addEventListener ('change', t.eventAlliance, false);
		document.getElementById(UID['tabSearch_Players']).addEventListener ('change', t.eventPlayer, false);
		document.getElementById(UID['tabSearch_NewList']).addEventListener ('click', t.show, false);
		document.getElementById(UID['tabSearchC']).addEventListener ('click', t.tabSearchC, false);	
		document.getElementById(UID['tabSearchW']).addEventListener ('click', t.tabSearchW, false);	
		t.eventCoords();
		t.contentType = isEmpty(Data.options.search.current_tab,0);
		t.show();
	},
	hide : function (){
	},
	show : function (){
		var t = Tabs.Search;
		if (!t.checkMapBusy) {
			t.displayAllianceList();
			t.displayPlayersList();
			switch (isEmpty(t.contentType, 0)) {
				case 0: t.tabSearchC(); break;
				case 1: t.tabSearchW(); break;
			}
		} else setTimeout(t.show, 100);
	},
	onUnload : function () {
		var t = Tabs.Search;
		Data.options.search.current_tab = t.contentType;
	},
	eventCoords : function (event){
		var ex = document.getElementById(UID['tabSearch_CoordsX']);
		var ey = document.getElementById(UID['tabSearch_CoordsY']);
		var x = parseIntZero (ex.value);
		var y = parseIntZero (ey.value);
		ex.value = x;
		ey.value = y;
		document.getElementById(UID['tabSearch_Tile']).innerHTML = '&nbsp;';
		if (x < 0 || x > 749){
			if(x < 0){
				while (x < 0){
					x = 750 + x;
				}
			} else {
				while (x > 749){
					x = x - 750;
				}
			}
			ex.style.backgroundColor = 'red';
			return;
		}
		if (y < 0 || y > 749){
			if(y < 0){
				while (y < 0){
					y = 750 + y;
				}
			} else {
				while (y > 749){
					y = y - 750;
				}
			}
			ey.style.backgroundColor = 'red';
			return;
		}
		Data.options.search.target.x = x;
		Data.options.search.target.y = y;
		ey.style.backgroundColor = '';
		ex.style.backgroundColor = '';

		Map.tileAt({x:x, y:y, force_request:true}, function(target){
			if (target && target.ok){
				var cfeedBack = '';
				Data.options.search.target.level = target.l;
				var attColor = target.A ? '#000' : '#C22';

				var type_name = Map.names.type[target.t] || target.t;
				var type = 'C';
				if (target.t != 7 && target.t < 10) type = 'W'; // 7 = city, from 10 = outposts

				var tile = '<font color='+attColor+'>'
					+'<b>'+ translate(type_name) +'&nbsp;'+ translate('Level') +'&nbsp;'+ target.l +'</b>'
					+'</font>';
				if(target.cn != undefined && type != 'W'){
					tile += '<br>'+ translate('City') + ': <b>' + target.cn +'</b> - '
						+ translate('Alliance')+': <b>'+(target.a != undefined ? target.a : '----') + '</b>'
						+ '<br>'+ translate('Name') +': <b>'+ target.n + '</b> - '
						+ translate('Level') + ': <b>' + target.l + '</b> - '
						+ translate('Might') + ': <b>' + target.m + '</b>';
					cFeedBack = translate(type_name) + ' ' + target.n + ' (' + nombreFormate(target.m) + ')' + (target.a != undefined ? ' / '+target.a : '');
				} else {
					cFeedBack = translate(type_name) + ' ' + translate('Level') + ' ' + target.l;
				}
				Data.options.search.target.type = cFeedBack;
				
				document.getElementById(UID['tabSearch_Tile']).innerHTML = tile;
			}
		});
	},
	eventAlliance : function (event){
		var t = Tabs.Search;
		var ea = document.getElementById(UID['tabSearch_SelAlliance']);
		var alli = ea.value;
		Data.options.search.target.alliance = alli;
		if (alli==null){
			ea.style.backgroundColor = 'red';
			return;
		}
		ea.style.backgroundColor = '';
		t.displayPlayersList ();
		t.show ();
	},
	eventPlayer : function (event){
		var t = Tabs.Search;
		var ea = document.getElementById(UID['tabSearch_SelPlayer']);
		var plyr = ea.value;
		Data.options.search.target.player = plyr;
		if (plyr==null){
			ea.style.backgroundColor = 'red';
			return;
		}
		ea.style.backgroundColor = '';
		t.show ();
	},
	displayAllianceList : function (){
		var t = Tabs.Search;
		var list = t.getAllianceList();
		if (list.length > 0)
			list.sort(function(a, b){a = a.name.toLowerCase(); b = b.name.toLowerCase(); if (a>b) return 1; if (a <b) return -1; return 0;});
		var m = '<select id=' + setUID('tabSearch_SelAlliance') + '>'
			+'<option value="*" '+ ((Data.options.search.target.alliance == '*') ? 'selected' : '') + '>' + translate('All alliances') + '</option>'
			+'<option value="0" '+ ((Data.options.search.target.alliance == '0') ? 'selected' : '') + '>' + translate('Without alliance') + '</option>'
			+'<option value="-1" '+ ((Data.options.search.target.alliance == '-1') ? 'selected' : '') + '>' + translate('Foes') + '</option>'
			+'<option value="1" '+ ((Data.options.search.target.alliance == '1') ? 'selected' : '') + '>' + translate('Friends') + '</option>';
		for (var i=0; i<list.length; i++){
			var selected = '';
			if (list[i].id == Data.options.search.target.alliance) selected = 'selected'
			m += '<option value="' + list[i].id + '" '+selected+'>' + list[i].name + '</option>';
		}
		m += '</select>';
		document.getElementById(UID['tabSearch_Alliance']).innerHTML = m;
		t.displayPlayersList ();
	},
	displayPlayersList : function (){
		var t = Tabs.Search;
		var list = t.getPlayersList();
		if (list.length > 0)
			list.sort(function(a, b){a = a.name.toLowerCase(); b = b.name.toLowerCase(); if (a>b) return 1; if (a <b) return -1; return 0;});
		var m = '<select id=' + setUID('tabSearch_SelPlayer') + '>'
			+'<option value="*" '+ ((Data.options.search.target.player == '*') ? 'selected' : '') + '>' + translate('All players') + '</option>';
		for (var i=0; i<list.length; i++){
			var selected = '';
			if (list[i].id == Data.options.search.target.player) selected = 'selected'
			m += '<option value="' + list[i].id + '" '+selected+'>' + list[i].name + '</option>';
		}
		m += '</select>';
		document.getElementById(UID['tabSearch_Players']).innerHTML = m;
	},

	// return array of different alliances found
	getAllianceList : function (){
		var t = Tabs.Search;
		var ret = [];
		for (var alliance in Data.map.alliance){
			if (!cJzA(alliance) && alliance != 0) ret.push ({id:alliance, name:(Data.map.alliance[alliance] || '')});
		}
		return ret;
	},

	// return array of different alliances found
	getPlayersList : function (){
		var t = Tabs.Search;
		var ret = [];
		for (var pid in Data.map.players){
			if (( Data.options.search.target.alliance == "*")  ||
				((Data.options.search.target.alliance == "1")  && (getAllianceState(Data.map.players[pid][3]) == '1'))  ||
				((Data.options.search.target.alliance == "-1") && (getAllianceState(Data.map.players[pid][3]) == '-1')) ||
				((Data.options.search.target.alliance != "*" && Data.options.search.target.alliance != "1" && Data.options.search.target.alliance != "-1")  && !cJzA(Data.map.players[pid][3]) &&
				((Data.map.players[pid][3] == Data.options.search.target.alliance) ||
				 (Data.map.players[pid][3] == 0 && (Data.options.search.target.alliance == null || Data.options.search.target.alliance == 0))))
				)
				if (Data.map.players[pid][0] && Data.map.players[pid][0] != null && Data.map.players[pid][0] != '')
					ret.push ({id:pid, name:(Data.map.players[pid][0] || '')});
		}
		logit('Player count = '+ret.length);
		return ret;
	},

	// return array of cities that satisfy config (max distance, alliance name)
	getCityList : function (){
		var t = Tabs.Search;
		var radius = Data.options.search.target.distance || 14;
		var x = Data.options.search.target.x || Seed.cities[CAPITAL_ID].x;
		var y = Data.options.search.target.y || Seed.cities[CAPITAL_ID].y;
		var terrains = Map.getTargets({x:x, y:y, radius:radius, map_type:'C'});
		var targets = [];
		var alliance = Data.options.search.target.alliance || '*';
		var player = Data.options.search.target.player || '*';
		for (var map_type in terrains) {
			if (map_type == 'City' || map_type == 'Outpost') {
				if (terrains[map_type]) {
					for (var i=0; i < terrains[map_type].length; i++) {
						var target = (terrains[map_type])[i];
						if (	(target && target.d <= radius) &&
							( ( (target.ai == alliance || alliance == '*') ||
							    (alliance == "1"  && getAllianceState(target.ai) == '1')  ||
							    (alliance == "-1" && getAllianceState(target.ai) == '-1') ||
							  ( (!target.ai || target.ai == 0) && (alliance == null || alliance == 0) ) ) &&
							    (target.id == player || player == '*') ) )
						{
							if (!target.a && target.n) target.a = '';
							if (!target.n) {
								target.n = '?????';
								target.a = '?????';
								target.m = '?';
							}
							targets.push (target);
						}
					}
				}
			}
		}
		terrains = null;
		return targets;
	},

	// return array of cities that satisfy config (max distance, alliance name)
	getWildernessesList : function (){
		var t = Tabs.Search;
		var ret = [];
		var radius = Data.options.search.target.distance || 14;
		var x = Data.options.search.target.x || Seed.cities[CAPITAL_ID].x;
		var y = Data.options.search.target.y || Seed.cities[CAPITAL_ID].y;
		var alliance = Data.options.search.target.alliance || '*';
		var terrains = Map.getTargets({x:x, y:y, radius:radius, map_type:'W'});
		var targets = [];
		for (var map_type in terrains) {
			if ( (map_type == 'hill'		&& Data.options.search.hill) ||
				 (map_type == 'grassland'	&& Data.options.search.grassland) ||
				 (map_type == 'lake'		&& Data.options.search.lake) ||
				 (map_type == 'mountain'	&& Data.options.search.mountain) ||
				 (map_type == 'forest'		&& Data.options.search.forest) ||
				 (map_type == 'plain'		&& Data.options.search.plain) ) {
				if (terrains[map_type]) {
					for (var i=0; i < terrains[map_type].length; i++) {
						var target = (terrains[map_type])[i];
						if (	(target && target.d <= radius) &&
							(	(target.l) >= parseInt(Data.options.search.min_level) &&
								(target.l) <= parseInt(Data.options.search.max_level ) ) &&
							(((((!target.id || target.id == 0) && Data.options.search.unowned) || (!Data.options.search.unowned)) &&
							( ( (target.ai == alliance || alliance == "*") ||
							    (alliance == "1"  && getAllianceState(target.ai) == '1')  ||
							    (alliance == "-1" && getAllianceState(target.ai) == '-1') ||
							  ( (!target.ai || target.ai == 0) && alliance == null) ) &&
								(target.id == Data.options.search.target.player || Data.options.search.target.player == "*") ) && target.l >= 7) ||
								 target.l < 7) )
						{
							if (target.l < 7 && !target.n) {
								target.n = '-';
								target.a = '-';
								target.m = '-';
							}
							if (!target.a && target.n) target.a = '';
							if (!target.n) {
								target.n = '?????';
								target.a = '?????';
								target.m = '?';
							}
							targets.push (target);
						}
					}
				}
			}
		}
		terrains = null;
		return targets;
	},

	//** CITY PLAYER SUB-TAB ***
	tabSearchC : function (){
		var t = Tabs.Search;
		document.getElementById(UID[t.lastSubTab]).className='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabSearchC']).className='selected';
		document.getElementById(UID['tabSearchC']).style.zIndex=1;
		t.lastSubTab = 'tabSearchC';
		t.contentType = 0;
		if (Data.options.search.last_update && Data.options.search.last_update != null && Data.options.search.last_update != undefined) kLastupdate = ' ('+Data.options.search.last_update+')';
		else kLastupdate = '';
		var m = '<div id=' + setUID('tabSearch_Results') + ' style="height:500px">'
			+'	<div class=' + UID['title'] + '>' + translate('Player cities list') + kLastupdate + '</div>'
			+'	<div id=' + setUID('tabSearch_ResultList') + ' class=' + UID['status_ticker']
			+'	 style="height:475px; max-height:475px; width:540px; max-width:540px; overflow:auto; white-space:nowrap; margin-top:1px !important"></div>'
			+'	</div>';
		document.getElementById(UID['tabSearch_Content']).innerHTML = m;

		var m = '<table class=' + UID['row_style'] + ' width=100%>'
			+'	<tr class=' + UID['row_headers'] +'>'
			+'		<td id=' + setUID('tabSearch_tsc_0') + ' width="20px"><A><span>' + translate('Dist') + '</span></A></td>'
			+'		<td id=' + setUID('tabSearch_tsc_1') + ' width="40px"><A><span>' + translate('Coords') + '</span></A></td>';
		if (Data.options.search.target.alliance == '*')
			m += '	<td id=' + setUID('tabSearch_tsc_2') + '><A><span>' + translate('Alliance') + '</span></A></td>';

		m += '		<td id=' + setUID('tabSearch_tsc_3') + ' width="200px" style="overflow-x:auto"><A><span>' + translate('Player name') + '</span></A></td>'
			+'		<td id=' + setUID('tabSearch_tsc_4') + ' width="40px" align=right><A><span>' + translate('Might') + '</span></A></td>'
			+'		<td width="40px" align=right>' + translate('Evol') + '</td>'
			+'		<td id=' + setUID('tabSearch_tsc_5') + '><A><span>' + translate('Type') + '</span></A></td>'
			+'		<td style="background:none"></td>'
			+'	</tr>';

		var cities = t.getCityList();
		sortCityList();
		for (var i=0; i<cities.length; i++){
			m += '<tr><td>'+ cities[i].d +'</td><td align=center>'+ cities[i].x +','+ cities[i].y +'</td>';
			if (Data.options.search.target.alliance == "*")
				m += '<td align=left>'+ getAllianceRelationship(cities[i].ai, cities[i].a) +'</td>';
			if (cities[i].m != null && cities[i].m != '?')
				mightF = nombreFormate(cities[i].m,' ');
			else
				mightF = '?';
			var evol = 'x';
			if (Data.map.evolution[cities[i].id] && cities[i].m && cities[i].m != '?') {
				evol = cities[i].m - Data.map.evolution[cities[i].id].m;
				if (evol < 0) evol = '<span class=' + UID['red'] + '>'+nombreFormate(evol,' ')+'</span>';
				else if (evol > 0) evol = '<span class=' + UID['green'] + '>+'+nombreFormate(evol,' ')+'</span>';
				else evol = nombreFormate(evol,' ');
			}
			m += '<td align=left>'+ getAllianceRelationship(cities[i].ai, cities[i].n) +'</td>'
				+'<td align=right>'+ mightF +'</td>'
				+'<td align=right>'+ evol +'</td>'
				+'<td align=center>'+ ((cities[i].t > 9) ? translate(Map.names.type[cities[i].t]) : '') +'</td>'
				+'<td><input id='+ setUID('tabSearch_Spy_'+i) +' ref='+ i +' class=Xtrasmall style="width:auto !important;" type=submit value="' + translate('Spy') + '" /></td>'
				+'</tr>';
		}
		document.getElementById(UID['tabSearch_ResultList']).innerHTML = m + '</table>';

		for (var h=0; h<6; h++)
			if ((h != 2) || (Data.options.search.target.alliance == '*' && h == 2))
				document.getElementById(UID['tabSearch_tsc_' + h]).addEventListener ('click', onChangeSort, false);

		var own_alliance = Seed.player.alliance ? Seed.player.alliance.id : -1;
		for (var i=0; i<cities.length; i++){
			var butSpy = document.getElementById(UID['tabSearch_Spy_'+ i]);
			butSpy.addEventListener ('click', butSpyNow, false);
			if ( (((cities[i].t > 9) && (cities[i].t != 20)) || (cities[i].t < 9)) &&
				 ((!cities[i].ai || cities[i].ai == 0 || cities[i].ai == null) || (cities[i].a != own_alliance))){
				butSpy.disabled = false;
				Element.removeClassName(butSpy, UID['bnt_disabled']);
				Element.addClassName(butSpy, UID['bnt_green']);
			} else {
				butSpy.disabled = true;
				Element.removeClassName(butSpy, UID['bnt_green']);
				Element.addClassName(butSpy, UID['bnt_disabled']);
			}
		}
		function butSpyNow (event){
			var n = parseInt(event.target.getAttribute('ref'));
			var dial = new ModalDialog (t.container, 300, 150, '', false);
			dial.getTopDiv().innerHTML = '<div class=' + UID['title'] + '><center><b>KabaListics : ' + translate('Message') + '</b></center></div>';
			dial.getContentDiv().innerHTML = translate('Spying');
			checkSpy (cities[n], notify);
			function notify (rslt){
				if (rslt!='OK'){
					dial.getContentDiv().innerHTML = '<b>'+ rslt +'</b>';
					dial.allowClose (true);
				} else {
					dial.getContentDiv().innerHTML = '<b>'+ translate('OK') +'</b>';
					setTimeout (function(){dial.destroy()}, 1000);
				}
			}
		}
		function checkSpy (targetObj, notify){
			var t = Tabs.Search;
			var cityId = Seed.cities[CAPITAL_ID].id;
			var cityIdx = CAPITAL_ID;

			// check troops
			var units = [];
			units['Spy'] = 1;
			var totalTroops = 0;
			for (var p in units){
				if (units[p] > 0){
					totalTroops += units[p];
					if (Seed.cities[cityIdx].units[p] < units[p]){
						notify (translate('Not enough') +' '+ translate(p));
						return;
					}
				}
			}
			if (totalTroops <= 0){
				notify (translate('No Troops Defined'));
				return;
			}
			var authMaxTroops = getMusterPointMaxTroops (cityIdx);
			for (var p in units) {
				if (units[p] > 0) {
					if (units[p] > authMaxTroops) {
						notify (translate('Too many troops for muster point level'));
						return;
					}
				}
			}
			if (totalTroops > authMaxTroops) {
				notify (translate('Too many troops for muster point level'));
				return;
			}
			if (getMusterPointSlots (cityIdx) <= 0){
				notify (translate('Muster Point Full'));
				return;
			}

			var targMsg =  '<B>' + translate('Manual spy sent to') + '</B>: ' + targetObj.n + ' ' +  translate('at') + ' ' + targetObj.x +'/'+ targetObj.y;

			verboseLog(targMsg +' '+ translate('attempted'));

			new MyAjax.marchSpy (cityId, targetObj.x, targetObj.y, units, 'attacks', function (rslt){
				if (rslt.ok && rslt.dat.result.success){
					Marches.add(rslt.dat.result.job.march_id, 'attacks');
					verboseLog(targMsg +' '+ translate('Successfully'));
					actionLog(targMsg);
					notify ('OK');
				} else {
					verboseLog(targMsg + ' ' + translate('failed and returned error') + ': ' + rslt.errmsg);
					t.dispFeedback (translate('Error') + ': ' + rslt.errmsg);
					if (notify){
						notify(false);
					}
				}
			});
		}
		function onChangeSort (event){
			var t = Tabs.Search;
			var arg = event.target.parentNode.parentNode.id;
			if (arg == UID['tabSearch_tsc_0']){
				if (Data.options.search.sort_list == '0'){
					Data.options.search.sort_list = '-0';
				} else {
					Data.options.search.sort_list = '0';
				}
			} else if (arg == UID['tabSearch_tsc_1']){
				if (Data.options.search.sort_list == '1'){
					Data.options.search.sort_list = '-1';
				} else {
					Data.options.search.sort_list = '1';
				}
			} else if (arg == UID['tabSearch_tsc_2']){
				if (Data.options.search.sort_list == '2'){
					Data.options.search.sort_list = '-2';
				} else {
					Data.options.search.sort_list = '2';
				}
			} else if (arg == UID['tabSearch_tsc_3']){
				if (Data.options.search.sort_list == '3'){
					Data.options.search.sort_list = '-3';
				} else {
					Data.options.search.sort_list = '3';
				}
			} else if (arg == UID['tabSearch_tsc_4']){
				if (Data.options.search.sort_list == '4'){
					Data.options.search.sort_list = '-4';
				} else {
					Data.options.search.sort_list = '4';
				}
			} else if (arg == UID['tabSearch_tsc_5']){
				if (Data.options.search.sort_list == '5'){
					Data.options.search.sort_list = '-5';
				} else {
					Data.options.search.sort_list = '5';
				}
			}
			t.tabSearchC();
		}
		function sortCityList (){
			var t = Tabs.Search;
			switch (Data.options.search.sort_list) {
				case '-0' : cities.sort(function(a,b){return b.d-a.d}); break;
				case '0'  : cities.sort(function(a,b){return a.d-b.d}); break;
				case '-1' : cities.sort(function(a,b){return b.x-a.x}); break;
				case '1'  : cities.sort(function(a,b){return a.x-b.x}); break;
				case '-2' : cities.sort(function(a,b){a = a.a.toLowerCase(); b = b.a.toLowerCase(); if (a>b) return -1; if (a <b) return 1; return 0;}); break;
				case '2'  : cities.sort(function(a,b){a = a.a.toLowerCase(); b = b.a.toLowerCase(); if (a>b) return 1; if (a <b) return -1; return 0;}); break;
				case '-3' : cities.sort(function(a,b){a = a.n.toLowerCase(); b = b.n.toLowerCase(); if (a>b) return -1; if (a <b) return 1; return 0;}); break;
				case '3'  : cities.sort(function(a,b){a = a.n.toLowerCase(); b = b.n.toLowerCase(); if (a>b) return 1; if (a <b) return -1; return 0;}); break;
				case '-4' : cities.sort(function(a,b){return b.m-a.m}); break;
				case '4'  : cities.sort(function(a,b){return a.m-b.m}); break;
				case '-5' : cities.sort(function(a,b){return b.t-a.t}); break;
				case '5'  : cities.sort(function(a,b){return a.t-b.t}); break;
				default   : cities.sort(function(a,b){return b.d-a.d}); break;
			}
		}
	},

	//** WILDERNESSES SUB-TAB ***
	tabSearchW : function (){
		var t = Tabs.Search;
		document.getElementById(UID[t.lastSubTab]).className='';
		document.getElementById(UID[t.lastSubTab]).style.zIndex=0;
		document.getElementById(UID['tabSearchW']).className='selected';
		document.getElementById(UID['tabSearchW']).style.zIndex=1;
		t.lastSubTab = 'tabSearchW';
		t.contentType = 1;

		var m = '<div class=' + UID['content'] + '>'
			+'<table class=' + UID['table'] + ' width=100%>'
			+'	<tr>'
			+'		<td width=3%><input id=' + setUID('tabSearch_WildG') + ' type=checkbox '+ (Data.options.search.grassland?'CHECKED':'') +' /></td>'
			+'		<td width=20%> '+ translate(kGrassland) +'</td>'
			+'		<td width=3%><input id=' + setUID('tabSearch_WildL') + ' type=checkbox '+ (Data.options.search.lake?'CHECKED':'') +' /></td>'
			+'		<td width=20%> '+ translate(kLake) +'</td>'
			+'		<td width=3%><input id=' + setUID('tabSearch_WildP') + ' type=checkbox '+ (Data.options.search.plain?'CHECKED':'') +' /></td>'
			+'		<td width=20%> '+ translate(kPlain) +'</td>'
			+'		<td width=31%>' + translate('Min level') + ': ' + levelSelect('Min', isEmpty(Data.options.search.min_level,'1') ) + '</td>'
			+'	</tr><tr>'
			+'		<td><input id=' + setUID('tabSearch_WildH') + ' type=checkbox '+ (Data.options.search.hill?'CHECKED':'') +' /></td>'
			+'		<td> '+ translate(kHill) +'</td>'
			+'		<td><input id=' + setUID('tabSearch_WildM') + ' type=checkbox '+ (Data.options.search.mountain?'CHECKED':'') +' /></td>'
			+'		<td> '+ translate(kMountain) +'</td>'
			+'		<td><input id=' + setUID('tabSearch_WildF') + ' type=checkbox '+ (Data.options.search.forest?'CHECKED':'') +' /></td>'
			+'		<td> '+ translate(kForest) +'</td>'
			+'		<td width=31%>' + translate('Max level') + ': ' + levelSelect('Max', isEmpty(Data.options.search.max_level,'10') ) + '</td>'
//			+'	</tr><tr>'
//			+'		<td><input id=' + setUID('tabSearch_WildN') + ' type=checkbox '+ (Data.options.search.nuage?'CHECKED':'') +' /></td>'
//			+'		<td> '+ translate(kFog) +'</td>'
//			+'		<td><input id=' + setUID('tabSearch_WildS') + ' type=checkbox '+ (Data.options.search.swamp?'CHECKED':'') +' /></td>'
//			+'		<td> '+ translate(kSwamp) +'</td>'
			+'	</tr>'
			+'</table>'
			+'<table class=' + UID['table'] + ' width=100%>'
			+'	<tr>'
			+'		<td width=3%><input id=' + setUID('tabSearch_Unowned') + ' type=checkbox '+ (Data.options.search.unowned?'CHECKED':'') +' /></td>'
			+'		<td width=20%> '+ translate('Unowned only') +'</td>'
			+'		<td width=77% align=center><input id=' + setUID('tabSearch_RefreshWilds') + ' type=button value="' + translate('Refresh selection') + '" /></td>'
			+'	</tr>'
			+'</table>'
			+'</div>'
			+'<div id=' + setUID('tabSearch_Wilds') + ' style="height:430px">'
			+'	<div class=' + UID['title'] + '>' + translate('Wildernesses list') + '</div>'
			+'	<div id=' + setUID('tabSearch_WildList') + &#