Trimps tools

Trimps tools (visual)

目前為 2017-06-15 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Trimps tools
// @namespace    trimps.github.io
// @version      1.229
// @description  Trimps tools (visual)
// @author       Anton
// @match        https://trimps.github.io
// @require      http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
// ==/UserScript==

(function () {
	'use strict';

	var tAutoBuy, tStyleFix, tPassiveWatcher, $ = jQuery, isStarted = false,
		version = typeof GM_info == 'function' ? GM_info().script.version :
			(typeof GM_info == 'object' ? GM_info.script.version : '?');

	var _isPortal = function () {
		return portalWindowOpen;
	};

	var _getJobPrice = function (jobName, resource) {
		return game.jobs[jobName].cost[resource][0] * Math.pow(game.jobs[jobName].cost[resource][1], game.jobs[jobName].owned);
	};

    var _hasFormation = function(what) {
        if (!game.global.preMapsActive && !game.global.lockTooltip) {
    		if (game.upgrades.Formations.done && what === 0) return true;
    		if (game.upgrades.Formations.done && what == 1) return true;
    		if (game.upgrades.Dominance.done && what == 2) return true;
    		if (game.upgrades.Barrier.done && what == 3) return true;
    		if (game.upgrades.Formations.done && game.global.highestLevelCleared >= 180 && what == 4) return true;
        }
        return false;
    };

    var _getEnemyAttack = function() {
        var cellNum, cell;
        if (game.global.mapsActive) {
            cellNum = game.global.lastClearedMapCell + 1;
            cell = game.global.mapGridArray[cellNum];
        } else {
            cellNum = game.global.lastClearedCell + 1;
            cell = game.global.gridArray[cellNum];
        }
        return calculateDamage(cell.attack, false, false, false, cell);
    };

    var _middleGameStrategy = function() {
        if (game.global.world < 60) return;
        
        if (game.global.formation === 0) {
            if (_hasFormation(1)) setFormation('1');
        }
        
        var enemy = _getEnemyAttack();
        var me = game.global.soldierCurrentBlock + game.global.soldierHealthMax;
        if (enemy >= me && game.global.formation != 1) {
            if (_hasFormation(1)) setFormation('1');
        }
        
        if (game.global.formation != 2 && _hasFormation(2)) {
            var formation2health = game.global.soldierHealthMax / 8;
            var me2 = formation2health + game.global.soldierCurrentBlock;
            if (me2 > enemy) {
                setFormation('2');
            }
        }
    };

	var _log = function (mes, type) {
		if (typeof type === 'undefined') type = "Story";
		message("BOT: " + mes, type);
	};

	var _getBreedingBaseSpeed = function () {
		if (game.global.challengeActive == "Trapper") return 0;
		var trimps = game.resources.trimps;
		var base = 0.0085;
		var breeding = trimps.owned - trimps.employed;
		var currentCalc = breeding * base;
		if (game.upgrades.Potency.done > 0) {
			var potencyStrength = Math.pow(1.1, game.upgrades.Potency.done);
			currentCalc *= potencyStrength;
		}
		return currentCalc;
	};

	var _autoEquipment = function () {
		var maxEquipLevel = game.global.challengeActive=='Frugal' ? 10000 : 7;
		for (var x in game.equipment) {
			if (game.equipment.hasOwnProperty(x) && game.equipment[x].locked === 0) {
				var maxLevel = game.equipment[x].prestige > maxEquipLevel ? 1 : (maxEquipLevel + 1 - game.equipment[x].prestige) * 2;
				if (game.equipment[x].level < maxLevel && canAffordBuilding(x, null, null, true)) {
					buyEquipment(x, true, true);
					_log('Upgrading equipment ' + x);
				}
			}
		}
	};

	var _getMinimumBreeding = function () {
		if (game.resources.trimps.maxSoldiers < 5) return 5; else return game.resources.trimps.maxSoldiers + 1;
	};

	var _buyStorage = function () {
		var barnThreshold = 0.8;
		/*percentage at which minimum*/
		var shedThreshold = 0.8;
		/*to buy storage*/
		var forgeThreshold = 0.8;
		/*from 0 (min) to 1 (max)*/
		var canAfford;

		if (game.resources.food.owned / (game.resources.food.max * (1 + game.portal.Packrat.level * (game.portal.Packrat.modifier * 100) / 100)) >= barnThreshold) {
			canAfford = canAffordBuilding("Barn", false, false, false, true);
			if (canAfford) {
				buyBuilding("Barn", true, true);
				_log('Building Barn');
			}
		}
		if (game.resources.wood.owned / (game.resources.wood.max * (1 + game.portal.Packrat.level * (game.portal.Packrat.modifier * 100) / 100)) >= shedThreshold) {
			canAfford = canAffordBuilding("Shed", false, false, false, true);
			if (canAfford) {
				buyBuilding("Shed", true, true);
				_log('Building Shed');
			}
		}
		if (game.resources.metal.owned / (game.resources.metal.max * (1 + game.portal.Packrat.level * (game.portal.Packrat.modifier * 100) / 100)) >= forgeThreshold) {
			canAfford = canAffordBuilding("Forge", false, false, false, true);
			if (canAfford) {
				buyBuilding("Forge", true, true);
				_log('Building Forge');
			}
		}
	}

	var _hasInQueue = function (item) {
		for (var x in game.global.buildingsQueue) {
			var queueItem = game.global.buildingsQueue[x].split('.')[0];
			if (queueItem == item) {
				return true;
			}
		}
		return false;
	};

	var _earlyGameStrategy = function () {
		if (_isPortal()) return;

		var playerStrength = getPlayerModifier();
		var minimumSpeedToHelp = 1 + playerStrength;

		if (game.global.eggLoc != -1) {
			_log('Destroying Easter Egg');
			easterEggClicked();
		}

		_buyStorage();
		_autoJobs();

		var trimps = game.resources.trimps;
		var breeding = game.global.challengeActive == "Trapper" ? 0 : trimps.owned - trimps.employed;
		var unemployed = Math.ceil(game.resources.trimps.realMax() / 2) - game.resources.trimps.employed;

		if (game.buildings.Trap.owned >= 1 && game.resources.trimps.owned < game.resources.trimps.realMax() &&
			(breeding < _getMinimumBreeding() || unemployed > 0) &&
			_getBreedingBaseSpeed() < 1) {
			setGather('trimps');
			return;
		}

		var canGetScience = game.global.challengeActive != "Scientist";

		var hasTrap = _hasInQueue('Trap');
		var cnt = game.global.challengeActive == "Trapper" ? 100 : (breeding < unemployed ? 25 : 1);
		if (!hasTrap && game.buildings.Trap.owned < 1 && game.resources.food.owned >= 10 && game.resources.wood.owned >= 10) {
			buyBuilding('Trap', true, true, cnt);
			return;
		}

		if ((game.global.buildingsQueue.length > 0 && game.global.autoCraftModifier < 1) || (game.global.buildingsQueue.length > 5)) {
			setGather('buildings');
			return;
		}

		if (getPsString('food', true) < minimumSpeedToHelp && game.resources.food.owned < 10) {
			setGather('food');
			return;
		}

		if (getPsString('wood', true) < minimumSpeedToHelp && game.resources.wood.owned < 10) {
			setGather('wood');
			return;
		}

		if (canGetScience && getPsString('science', true) < minimumSpeedToHelp && game.resources.science.owned < 10) {
			setGather('science');
			return;
		}

		if (getPsString('metal', true) < minimumSpeedToHelp && game.resources.metal.owned < 100) {
			setGather('metal');
			return;
		}

		var needScientist = game.upgrades.Scientists.done === 0 && game.upgrades.Scientists.allowed === 1;
		if (canGetScience && getPsString('science', true) < minimumSpeedToHelp && (game.resources.science.owned < 60 || needScientist)) {
			setGather('science');
			return;
		}

		if ((game.global.playerGathering == 'trimps' && (game.buildings.Trap.owned === 0 || _getBreedingBaseSpeed() > 1)) ||
			(game.global.playerGathering == 'buildings' && game.global.buildingsQueue.length === 0)) {
			_selectAutoJob();
		}
	}

	var _selectAutoJob = function () {
		var canGetScience = game.global.challengeActive != "Scientist";
		var upgradePrice = _getMaximumResourceUpgradePrice();
		var scienceNeeded = _getUpgradePriceSumForRes('science');
		if (scienceNeeded > game.resources.science.owned && canGetScience) {
			setGather('science');
		} else {
			if (upgradePrice !== false) {
				for (var x in upgradePrice) {
					if (upgradePrice.hasOwnProperty(x)) {
						if (x == 'wood' || x == 'metal' || x == 'science' || x == 'food') {
							setGather(x);
						} else {
							if (canGetScience) {
								setGather('science');
							} else {
								setGather('food');
							}
						}
						break;
					}
				}
			} else {
				if (canGetScience) {
					setGather('science');
				} else {
					setGather('food');
				}
			}
		}
	}

	var _passiveWatcher = function () {
		if (_isPortal()) return;

		_earlyGameStrategy();

		var canAfford = canAffordBuilding("Tribute", false, false, false, true);
		if (canAfford && game.buildings.Tribute.locked !== 1) {
			buyBuilding("Tribute", true, true);
			_log('Building ' + "Tribute");
		}

		canAfford = canAffordBuilding("Gym", false, false, false, true);
		if (canAfford && game.buildings.Gym.locked !== 1) {
			buyBuilding("Gym", true, true);
			_log('Building ' + "Gym");
		}
		
		_middleGameStrategy();
	}

	var _needAttackCurrentMap = function () {
		return (typeof game.mapsAttacked[game.global.world] === 'undefined');
	};
	
	var _hasMapOfCurrentLevel = function () {
		for (var x in game.global.mapsOwnedArray) {
			if (game.global.mapsOwnedArray.hasOwnProperty(x)) {
				var mapObj = game.global.mapsOwnedArray[x];
				if (mapObj.level == game.global.world) return true;
			}
		}
		return false;
	};

	var _mapAttackStrategy = function () {
		if (game.global.world < 6) return;
		if (game.global.preMapsActive) return;
		//if (!game.global.mapsUnlocked) return;
		if (game.global.pauseFight) {
			_log('Enabling auto attack!');
			fightManual();
			game.global.pauseFight = false;
			pauseFight(true); // update only
		} else {
			if (_needAttackCurrentMap()) {
				document.getElementById("mapLevelInput").value = game.global.world;
				var currentMapPrice = updateMapCost(true);
				var money = game.resources.fragments.owned;
				if (!_hasMapOfCurrentLevel()) {
					if (money >= currentMapPrice) {
						var result = buyMap();
						if (result == 1) {
							_log('Bought new map level ' + game.global.world);
						} else {
							console.log('Buy map result = ' + result);
						}
					} else {
						console.log('No fragments (' + money + ') to buy map for ' + currentMapPrice);
					}
				}

				if (_hasMapOfCurrentLevel()) {
					game.global.lookingAtMap = '';
					for (var x in game.global.mapsOwnedArray) {
						if (game.global.mapsOwnedArray.hasOwnProperty(x)) {
							var mapObj = game.global.mapsOwnedArray[x];
							if (mapObj.level == game.global.world) {
								game.global.lookingAtMap = mapObj.id;
								break;
							}
						}
					}

					if (game.global.lookingAtMap !== '') {
						_log('Attacking map ' + game.global.lookingAtMap);
						game.options.menu.alwaysAbandon.enabled = 1; // GO TO MAPS!
						mapsClicked(true);
						game.mapsAttacked[game.global.world] = true;
						game.global.repeatMap = true; // REPEAT
						repeatClicked(true);
						runMap();
						var breeding = trimps.owned - trimps.employed;
		                if (breeding < (_getMinimumBreeding() + 1)) fightManual();
					} else {
						console.log('where is my map?');
					}
				} else {
					console.log('no map of current level ' + game.global.world);
				}
			} else {
				if (_hasMapOfCurrentLevel() && game.global.currentMapId === '') {
					game.global.lookingAtMap = '';
					var map_id, map_name = '';
					for (var x in game.global.mapsOwnedArray) {
						if (game.global.mapsOwnedArray.hasOwnProperty(x)) {
							var mapObj = game.global.mapsOwnedArray[x];
							if (mapObj.level <= game.global.world && mapObj.noRecycle === true && mapObj.clears === 0) {
								game.global.lookingAtMap = mapObj.id;
								map_id = x;
								map_name = mapObj.name;
								break;
							}
						}
					}
					if (game.global.lookingAtMap !== '' && typeof map_id !== 'undefined') {
						_log('Attacking prestige map ' + map_name + ' level (' + game.global.mapsOwnedArray[map_id].level + ')');
						game.options.menu.alwaysAbandon.enabled = 1; // GO TO MAPS!
						mapsClicked(true);
						game.global.repeatMap = true; // REPEAT
						repeatClicked(true);
						game.global.mapsOwnedArray[map_id].clears = 1;
						runMap();
						var breeding = trimps.owned - trimps.employed;
		                if (breeding < (_getMinimumBreeding() + 1)) fightManual();
					}
				} else {
				    if (game.global.currentMapId !== '') {
				        var lastMapCell = game.global.mapGridArray[game.global.mapGridArray.length - 1];
				        var specialGift = '';
				        if (lastMapCell.special !== '') {
				            specialGift = game.mapUnlocks[lastMapCell.special];
				        }
				        if (specialGift === '' || specialGift.prestige !== true) {
				            mapsClicked(true); // go to maps
				            mapsClicked(); // go to world
				        }
				    }
				}
			}
		}
	};

    var _mapDeleter = function() {
        for (var x in game.global.mapsOwnedArray) {
            var map = game.global.mapsOwnedArray[x];
            if (map.level < (game.global.world - 10) && map.noRecycle !== true) {
                game.global.lookingAtMap = map['id'];
            	_log('Deleting map ' + map.name + ' (' + map.level + ')');
                recycleMap(-1, true);
                break;
            }
        }
    }

	var _auto = function () {
		if (_isPortal()) return;
		_earlyGameStrategy();
		_autoUpgrade();
		_autoBuy();
		_autoEquipment();
		_mapAttackStrategy();
		_middleGameStrategy();
		_mapDeleter();
	};

	var _onStartButton = function () {
		if (isStarted) {
			_stop();
			_log('Stop.');
			isStarted = false;
		} else {
			_start();
			_log('Started!');
			isStarted = true;
		}
	};

	var _styleUpdate = function () {
		// remove counts
		$('head').append('<style type="text/css">' +
			'span.thingName{font-size:85%;}.queueItem,.btn{padding:0}' +
			'.thingColorCanNotAfford.upgradeThing{background-color:#530053;}' +
			'#battleSideTitle{padding:0}' +
			'.battleSideBtnContainer{margin-top:0;}' +
			'#logBtnGroup{display:none}' +
			'#log{height:100%;}' +
			'.glyphicon-apple{color:orangered;}' +
			'.glyphicon-tree-deciduous{color:limegreen;}'+
			'.icomoon.icon-cubes{color:silver;}'+
			'.icomoon.icon-diamond{color:white;'+
			'</style>');
		// remove tabs
		$('#buyTabs').hide();
		filterTabs('all');
		// remove captions
		$('#buildingsTitleDiv,#upgradesTitleDiv,#equipmentTitleDiv').hide();
		// fix height
		$('#topRow,#queueContainer').css('margin-bottom', '0');
		$('#jobsTitleDiv').css('padding', '0').css('font-size', 'smaller');
		$('#buyHere').css('margin', '0').css('padding', '0').css('overflow-x', 'hidden');
		$('#queueContainer').css('height', '70px');
		$('#numTabs').css('margin', '0');
		$('#buyContainer').css('height', 'calc(99vh - 20vw - 96px)');
		// add button
		$('#settingsTable tr').append('<td class="btn btn-info" id="botStart" title="' + version + '">Bot start</td>');
		$('#botStart').click(_onStartButton);
		// add grid
		var $grid = $('<table style="width:100%;margin-top:4px;font-size:smaller;"><tr>' +
			'<td id="magnimp-cell"><span class="glyphicon glyphicon-magnet"></span><label style="margin-left:4px" title="Magimp">...</label></td>' +
			'<td id="venimp-cell"><span class="glyphicon glyphicon-glass"></span><label style="margin-left:4px" title="Venimp">...</label></td>' +
			'</tr><tr>' +
			'<td id="whipimp-cell"><span class="glyphicon glyphicon-star"></span><label style="margin-left:4px" title="Whipimp">...</label></td>' +
			'<td id="titimp-cell"><span class="icomoon icon-hammer"></span><label style="margin-left:4px" title="Titimp">' + prettify(game.global.titimpLeft) + '</label></td>' +
			'</tr></table>');
		$('#battleBtnsColumn').append($grid);
		_updateSuperTrimps();
	}

	var _autoUpgrade = function () {
		for (var item in game.upgrades) {
			var upgrade = game.upgrades[item];
			if (upgrade.locked == 1) continue;
			var canAfford = canAffordTwoLevel(upgrade);
			if (canAfford) {
				if (item == "Coordination") {
					if (!canAffordCoordinationTrimps()) continue;
				}
				if (item == "Gigastation") {
				    var minAddon = Math.floor(game.global.highestLevelCleared / 6);
				    var minWaprstation = Math.floor(game.global.world / 6) + minAddon;
				    if (minWaprstation < 6 + minAddon) minWaprstation = 6 + minAddon;
					if (game.buildings.Warpstation.owned < minWaprstation) continue;
				}
				buyUpgrade(item, true, true);
				_log('Upgrading ' + item);
				_selectAutoJob();
				return 1;
			}
		}
		return 0;
	};

	var getUpgradePrice = function (upgradeObject) {
		var price, result = {};
		for (var cost in upgradeObject.cost) {
			if (typeof upgradeObject.cost[cost] === 'object' && typeof upgradeObject.cost[cost][1] === 'undefined') {
				var costItem = upgradeObject.cost[cost];
				for (var item in costItem) {
					price = costItem[item];
					if (upgradeObject.prestiges && (item == "metal" || item == "wood")) {
						if (game.global.challengeActive == "Daily" && typeof game.global.dailyChallenge.metallicThumb !== 'undefined') {
							price *= dailyModifiers.metallicThumb.getMult(game.global.dailyChallenge.metallicThumb.strength);
						}
						price *= Math.pow(1 - game.portal.Artisanistry.modifier, game.portal.Artisanistry.level);
					}
					if (typeof price === 'function') price = price();
					if (typeof price[1] !== 'undefined') price = resolvePow(price, upgradeObject);
					result[item] = price;
				}
			}
		}
		return result;
	};

	var _getAllUpgradePrice = function () {
		var totalPrice = {};
		for (var item in game.upgrades) {
			var upgrade = game.upgrades[item];
			if (upgrade.locked == 1) continue;
			var price = getUpgradePrice(upgrade);
			for (var res in price) {
				if (price.hasOwnProperty(res)) {
					if (typeof totalPrice[res] === 'undefined') totalPrice[res] = 0;
					totalPrice[res] += price[res];
				}
			}
		}
		return totalPrice;
	};

	var _getUpgradePriceSumForRes = function (res) {
		var totalPrice = _getAllUpgradePrice();
		if (typeof totalPrice[res] !== 'undefined') {
			return totalPrice[res];
		} else {
			return 0;
		}
	};

	var _getMaximumResourceUpgradePrice = function () {
		var totalPrice = _getAllUpgradePrice(), maxPriceName = '', maxPrice = 0;
		for (var res in totalPrice) {
			if (totalPrice.hasOwnProperty(res)) {
				if (totalPrice[res] > maxPrice) {
					maxPrice = totalPrice[res];
					maxPriceName = res;
				}
			}
		}
		var result = {};
		if (maxPriceName !== '') {
			result[maxPriceName] = maxPrice;
			return result;
		} else {
			return false;
		}
	};

	var _autoBuy = function () {
		var toBuy;
		for (var item in game.buildings) {
			if (item == 'Barn' || item == 'Shed' || item == 'Forge' || item == 'Wormhole' || item == 'Trap') continue;
			if (!game.buildings.Collector.locked &&
				(item == 'Mansion' || item == 'Hotel' || item == 'Resort' || item == 'House' || item == 'Hut')) continue;
			building = game.buildings[item];
			if (building.locked == 1) continue;
			var canAfford = canAffordBuilding(item, false, false, false, true);
			if (canAfford) {
				if (item == 'Nursery') {
				    var isElectro = game.global.challengeActive == "Electricity";
				    var mult = game.global.brokenPlanet ? (game.global.world >= 80 ? 2 : 1.5) : 1;
				    
					if (!isElectro && (game.buildings.Nursery.owned >= (game.buildings.Tribute.owned * mult) ||
						game.buildings.Nursery.owned >= (game.buildings.Gym.owned * mult)))
					{
						continue;
					} else {
						if (!_hasInQueue('Nursery')) {
							toBuy = item;
						} else {
							continue;
						}
					}
				} else {
					toBuy = item;
				}
			}
		}
		if (typeof toBuy !== 'undefined') {
			buyBuilding(toBuy, true, true);
			_log('Building ' + toBuy);
			return 1;
		} else {
			return 0;
		}
	}

	var needFarmer = 25, needLumber = 25, needMiner = 25, needScientist = 1;
	var needAllMax = needFarmer + needLumber + needMiner + needScientist;

	var _buyJobs = function ($obj, unemployed, objName, jobId) {
		if ($obj.length > 0) {
			var trimps = game.resources.trimps;
			var breeding = game.global.challengeActive == "Trapper" ? unemployed : trimps.owned - trimps.employed;
			var cnt = 1;
			var minBreeding = _getMinimumBreeding();
			if (unemployed > needAllMax * 100000 && (breeding - 1000000 > minBreeding)) {
				game.global.buyAmt = 1000000;
				cnt = 1000000;
			}
			else if (unemployed > needAllMax * 10000 && (breeding - 100000 > minBreeding)) {
				game.global.buyAmt = 100000;
				cnt = 100000;
			}
			else if (unemployed > needAllMax * 1000 && (breeding - 10000 > minBreeding)) {
				game.global.buyAmt = 10000;
				cnt = 10000;
			}
			else if (unemployed > needAllMax * 100 && (breeding - 1000 > minBreeding)) {
				game.global.buyAmt = 1000;
				cnt = 1000;
			}
			else if (unemployed > needAllMax * 10 && (breeding - 100 > minBreeding)) {
				numTab(4);
				cnt = 100;
			}
			else if (unemployed > needAllMax * 2.5 && (breeding - 25 > minBreeding)) {
				numTab(3);
				cnt = 25;
			}
			else if (unemployed > needAllMax && (breeding - 10 > minBreeding)) {
				numTab(2);
				cnt = 10;
			}
			else {
				numTab(1);
				cnt = 1;
			}
			buyJob(jobId, true, true); // confirmed, noTip
			numTab(1); // +1
			_log('New ' + objName + (cnt > 1 ? " x" + cnt : ''), 'Combat');
			return cnt;
		} else {
			return 0;
		}
	};

	var _autoJobs = function () {
		var trimps = game.resources.trimps;
		var breeding = trimps.owned - trimps.employed;
		if (breeding < (_getMinimumBreeding() + 1) && game.global.challengeActive !== 'Trapper') return;

		var jobsTotal =
			game.jobs.Farmer.owned +
			game.jobs.Lumberjack.owned +
			game.jobs.Miner.owned +
			game.jobs.Scientist.owned;

		var unemployed = Math.ceil(game.resources.trimps.realMax() / 2) - game.resources.trimps.employed;

		var trainerCost = _getJobPrice('Trainer', 'food');
		if ((trainerCost < game.resources.food.owned) && unemployed <= 0 && game.jobs.Farmer.owned > 1 && game.jobs.Trainer.locked === 0) {
			game.global.firing = true;
			_log('Fire farmer, sorry');
			buyJob('Farmer', true, true);
			game.global.firing = false;
		}

		if (unemployed <= 0) return;

		if (trainerCost <= game.resources.food.owned && game.jobs.Trainer.locked === 0) {
			buyJob('Trainer', true, true);
			_log('New trainer');
			return 1;
		}

		var cnt = 0;

		var $explorer = $('#jobsHere').find('.thingColorCanAfford[id=Explorer]');
		if ($explorer.length > 0) {
			buyJob('Explorer', true, true);
			_log('New explorer');
			return ++cnt;
		}

		var hasFarmer = game.jobs.Farmer.locked === 0;
		var hasLumber = game.jobs.Lumberjack.locked === 0;
		var hasMiner = game.jobs.Miner.locked === 0;
		var hasScientist = game.jobs.Scientist.locked === 0;
		var needAll =
			(hasFarmer ? needFarmer : 0) +
			(hasLumber ? needLumber : 0) +
			(hasMiner ? needMiner : 0) +
			(hasScientist ? needScientist : 0);
		if (needAll < 1) needAll = 1;

		var minOwned = Math.min(
			game.jobs.Farmer.owned,
			game.jobs.Lumberjack.owned,
			game.jobs.Miner.owned);
		if (minOwned > 30) minOwned = 30; // for science

		if (hasScientist && game.jobs.Scientist.owned < minOwned) {
			var $science = $('#jobsHere').find('.thingColorCanAfford[id=Scientist]');
			cnt += _buyJobs($science, unemployed, 'scientist', 'Scientist');
		} else if (hasFarmer && game.jobs.Farmer.owned < (jobsTotal * needFarmer / needAll)) {
			var $farmer = $('#jobsHere').find('.thingColorCanAfford[id=Farmer]');
			cnt += _buyJobs($farmer, unemployed, 'farmer', 'Farmer');
		} else if (hasLumber && game.jobs.Lumberjack.owned < (jobsTotal * needLumber / needAll)) {
			var $lumber = $('#jobsHere').find('.thingColorCanAfford[id=Lumberjack]');
			cnt += _buyJobs($lumber, unemployed, 'lumberjack', 'Lumberjack');
		} else if (hasMiner && game.jobs.Miner.owned < (jobsTotal * needMiner / needAll)) {
			var $miner = $('#jobsHere').find('.thingColorCanAfford[id=Miner]');
			cnt += _buyJobs($miner, unemployed, 'miner', 'Miner');
		} else if (hasScientist && game.jobs.Scientist.owned < (jobsTotal * needScientist / needAll)) {
			var $science = $('#jobsHere').find('.thingColorCanAfford[id=Scientist]');
			cnt += _buyJobs($science, unemployed, 'scientist', 'Scientist');
		}

		if (unemployed > 0 && cnt === 0) {
			var $farmer = $('#jobsHere').find('.thingColorCanAfford[id=Farmer]');
			cnt += _buyJobs($farmer, unemployed, 'farmer', 'Farmer');
		}

		return cnt;
	};

	var _styleFix = function () {
		_disableLog();

		$('.buyBox').find('.thing').find('br').remove();
		$('.buyBox').find('.thing').find('.thingOwned').css('margin-left', '4px');
		$('#buyHere').find('.alert.badge').text('');
		$('#buildingsQueue').css('height', '30px');
		for (var x in game.upgrades) if (game.upgrades[x].alert && game.upgrades[x].locked === 0) game.upgrades[x].alert = false;
		for (x in game.buildings) if (game.buildings[x].alert && game.buildings[x].locked === 0) game.buildings[x].alert = false;
		for (x in game.jobs) if (game.jobs[x].alert && game.jobs[x].locked === 0) game.jobs[x].alert = false;

		if (typeof game.passedMaps === 'undefined') game.passedMaps = {};
		if (typeof game.mapsAttacked === 'undefined') game.mapsAttacked = {};

		for (x in game.passedMaps) if (x > game.global.world) {
			// Game restart?
			game.passedMaps = {};
			game.mapsAttacked = {};
			$('#venimp-cell').find('label').text('...');
			$('#magnimp-cell').find('label').text('...');
			$('#whipimp-cell').find('label').text('...');
			$('#buildingsTitleDiv,#upgradesTitleDiv,#equipmentTitleDiv').hide(); // remove captions
			break;
		}

		var hasItem = false;
		if (typeof game.mapUnlocks === 'undefined') {
			clearInterval(tStyleFix);
			tStyleFix = setInterval(_styleFix, 2000);
		} else {
			for (x in game.mapUnlocks) {
				var notPass = game.mapUnlocks[x].startAt <= game.global.world && (typeof game.passedMaps[game.mapUnlocks[x].startAt] === 'undefined' || game.passedMaps[game.mapUnlocks[x].startAt] < 1);
				if (notPass) {
					$('#battleSideTitle').css('background-color', notPass ? '#A00' : '#600');
					hasItem = true;
					break;
				}
			}
		}
		if (!hasItem) {
			$('#battleSideTitle').css('background-color', 'transparent');
		}
		game.passedMaps[game.global.world] = game.global.mapBonus;
		if (game.global.mapBonus > 0) {
			for (x in game.mapUnlocks) {
				if (game.mapUnlocks[x].startAt < game.global.world) {
					game.passedMaps[game.mapUnlocks[x].startAt] = 1;
				}
			}
		}
	};

	var _start = function () {
		_log('Passive watcher stop');
		clearInterval(tPassiveWatcher);

		_log('BOT start version ' + version);
		tAutoBuy = setInterval(_auto, 1000);

		$('#botStart').text('Bot stop');
	};

	var _stop = function () {
		_log('BOT stop');
		clearInterval(tAutoBuy);

		tPassiveWatcher = setInterval(_passiveWatcher, 1000);
		_log('Passive watcher started');

		$('#botStart').text('Bot start');
	};

	var logEnabled = true, $oldLog, tTitimp;

	var _updateSuperTrimps = function () {
		var whipStrength = Math.pow(1.003, game.unlocks.impCount.Whipimp);
		whipStrength = prettify((whipStrength - 1) * 100) + "%";
		var magimpStrength = Math.pow(1.003, game.unlocks.impCount.Magnimp);
		magimpStrength = prettify((magimpStrength - 1) * 100) + "%";
		var venimpStrength = Math.pow(1.003, game.unlocks.impCount.Venimp);
		venimpStrength = prettify((venimpStrength - 1) * 100) + "%";

		var mag = $('#magnimp-cell').find('label');
		if (mag.text() != magimpStrength) mag.text(magimpStrength);
		var whip = $('#whipimp-cell').find('label');
		if (whip.text() != whipStrength) whip.text(whipStrength);
		var ven = $('#venimp-cell').find('label');
		if (ven.text() != venimpStrength) ven.text(venimpStrength);
	};

	var _disableLog = function () {
		if (logEnabled) {
			message = function (messageString, type, lootIcon, extraClass, extraTag, htmlPrefix) {
				if (type == 'Loot' && lootIcon === null) return;
				if (type == 'Combat' && (lootIcon === null || typeof lootIcon === 'undefined')) return;
				if (type == 'Loot' &&
					(messageString.indexOf('You just found') > -1 ||
						messageString.indexOf('You found') > -1 ||
						messageString.indexOf('That guy just left') > -1 ||
						(messageString.indexOf(' dropped ') > -1 && messageString.indexOf('That ') > -1) ||
						messageString.indexOf(' manage to ') > -1 ||
						messageString.indexOf('Then he died') > -1 ||
						messageString.indexOf(' popped out!') > -1 ||
						messageString.indexOf('That Feyimp gave you') > -1 ||
						messageString.indexOf('in that dead Tauntimp') > -1 ||
						messageString.indexOf('fragments from that Flutimp') > -1 ||
						messageString.indexOf('That Jestimp gave you') > -1 ||
						messageString.indexOf('That Titimp made your Trimps super strong') > -1 ||
						messageString.indexOf('You scored ') > -1
					)) return;
				if (type == 'Story' && typeof lootIcon === 'undefined' &&
					messageString.indexOf('BOT: New ') > -1) return;
				if (type == 'Notices' && messageString == 'Game Saved!') {
					var t = ((game.options.menu.timestamps.enabled == 1) ? getCurrentTime() : updatePortalTimer(true));
					$('#saveIndicator').find('.autosaving').text(t);
					return;
				}
				if (messageString.indexOf('The ground up Venimp now increases your Trimps') > -1) {
					_updateSuperTrimps();
					return;
				}
				if (messageString.indexOf('You killed a Magnimp! The strong magnetic forces now increase your loot by') > -1) {
					_updateSuperTrimps();
					return;
				}
				if (messageString.indexOf('Seeing the Whipimps fall is causing all of your Trimps to work') > -1) {
					_updateSuperTrimps();
					return;
				}

				var log = document.getElementById("log");
				var displayType = "block";
				var prefix = "";
				var addId = "";
				if (messageString == "Game Saved!" || extraClass == 'save') {
					addId = " id='saveGame'";
					if (document.getElementById('saveGame') !== null) {
						log.removeChild(document.getElementById('saveGame'));
					}
				}
				if (game.options.menu.timestamps.enabled) {
					messageString = ((game.options.menu.timestamps.enabled == 1) ? getCurrentTime() : updatePortalTimer(true)) + " " + messageString;
				}
				if (!htmlPrefix) {
					if (lootIcon && lootIcon.charAt(0) == "*") {
						lootIcon = lootIcon.replace("*", "");
						prefix = "icomoon icon-";
					}
					else prefix = "glyphicon glyphicon-";
					if (type == "Story") messageString = "<span class='glyphicon glyphicon-star'></span> " + messageString;
					if (type == "Combat") messageString = "<span class='glyphicon glyphicon-flag'></span> " + messageString;
					if (type == "Loot" && lootIcon) messageString = "<span class='" + prefix + lootIcon + "'></span> " + messageString;
					if (type == "Notices") {
						messageString = "<span class='glyphicon glyphicon-off'></span> " + messageString;
					}
				} else {
					messageString = htmlPrefix + " " + messageString;
				}
				var messageHTML = "<span" + addId + " class='" + type + "Message message" + " " + extraClass + "' style='display: " + displayType + "'>" + messageString + "</span>";
				pendingLogs.all.push(messageHTML);
				postMessages();

				var $allLogs = $('#log').find('span');
				$allLogs.slice(0, -30).remove();
			};
			logEnabled = false;
		}
	};

	var _titimpUpdate = function () {
		$('#titimp-cell').find('label').text(prettify(game.global.titimpLeft > 0 ? game.global.titimpLeft : 0));
	};

	setTimeout(function () {

		_log('Trimps BOT version ' + version);

		tStyleFix = setInterval(_styleFix, 2000);
		tTitimp = setInterval(_titimpUpdate, 500);

		_styleUpdate();
		_styleFix();

		_disableLog();

		_stop(); // start passive watcher

	}, 1000);

})();