Skip to content

Instantly share code, notes, and snippets.

@ChrisLHall
Last active August 29, 2015 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ChrisLHall/e9d2acd0482d0fe9d3ae to your computer and use it in GitHub Desktop.
Save ChrisLHall/e9d2acd0482d0fe9d3ae to your computer and use it in GitHub Desktop.
Tampermonkey bot for http://choppin-wood.com/
// ==UserScript==
// @name Superchop
// @namespace http://chrislhall.net/
// @author Christopher L. Hall
// @version 1.2
// @description Autoclicker script for Choppin' Wood
// @match http://choppin-wood.com/
// @copyright 2015+, Christopher L Hall
// ==/UserScript==
function WoodPants() {
this.LOOP = 10;
this.counter = 0;
this.lumberRows = ["lumberjackRow", "loggingTruckRow", "loggingHeliRow", "loggingCampRow", "lumberMillRow", "logBoomRow", "clearCutterRow", "oldGrowthRow", "stolenLandRow"];
this.lumberUpgrades = ["lumberjackUpgrade", "loggingTruckUpgrade", "loggingHeliUpgrade", "loggingCampUpgrade", "lumberMillUpgrade", "logBoomUpgrade", "clearCutterUpgrade", "oldGrowthUpgrade", "stolenLandUpgrade"];
this.oilRows = ["oilWorkerRow", "drillingRigRow", "tankerTruckRow", "oilPlatformRow", "oilPipelineRow", "oilRefineryRow", "oilTankerRow", "oilDictatorRow", "politicianRow"];
this.oilUpgrades = ["oilWorkerUpgrade", "drillingRigUpgrade", "tankerTruckUpgrade", "oilPlatformUpgrade", "oilPipelineUpgrade", "oilRefineryUpgrade", "oilTankerUpgrade", "oilDictatorUpgrade", "politicianUpgrade"];
this.RATES = [1, 8, 50, 250, 2300, 15000, 250000, 1500000, 10000000];
this.ROWS = this.lumberRows.length;
this.LOGCONST = 0.15;
this.NUMTARGETS = 3;
this.targetRow = 0;
this.targetLogs = true;
this.targetUpgrade = -1;
this.rawTarget = 0;
this.TAU = 120; // Time const in seconds
this.targetCredit = false;
this.CREDITINCREMENT = 1000 / this.LOOP * 300;
this.TINYCREDITINCREMENT = 1000 / this.LOOP * 10;
this.creditGrowthCounter = 1;
this.justLoggedCredit = false;
}
WoodPants.prototype = {
start: function() {
console.log("WoodPants STARTING UP!");
this.main();
},
main: function() {
setTimeout(this.main.bind(this), this.LOOP);
this.counter++;
this.creditGrowthCounter--;
if (this.counter % this.CREDITINCREMENT == 0) {
var creditSeconds = 100000000 / this.moneyPerSecond();
if (creditSeconds < 60) {
this.targetCredit = true;
if (!this.justLoggedCredit) {
console.log("Targeting carbon credit");
}
}
} else if (this.counter % this.TINYCREDITINCREMENT == 0) {
var creditSeconds = 100000000 / this.moneyPerSecond();
if (creditSeconds < 1) {
this.targetCredit = true;
if (!this.justLoggedCredit) {
console.log("Targeting carbon credit");
}
}
} else if (this.creditGrowthCounter <= 0) {
if (this.moneyPerSecond() != 0) {
var creditSeconds = 100000000 / this.moneyPerSecond();
if (creditSeconds < 60) {
this.targetCredit = true;
if (!this.justLoggedCredit) {
console.log("Targeting carbon credit");
}
}
this.creditGrowthCounter = Math.min(this.CREDITINCREMENT, Math.max(1, creditSeconds * 10 * (1000 / this.LOOP)));
}
}
this.targetLogs = (this.oilPerSecond() > this.logsPerSecond());
var newTargetScore = this.targetRow;
var newUpgradeScore = [-1, 0];
if (this.targetLogs) {
newTargetScore = this.findTargetRow(this.lumberRows, this.lumberUpgrades, this.logsPerSecond());
newUpgradeScore = this.findTargetUpgrade(this.lumberRows, this.lumberUpgrades, this.logsPerSecond());
} else {
newTargetScore = this.findTargetRow(this.oilRows, this.oilUpgrades, this.oilPerSecond());
newUpgradeScore = this.findTargetUpgrade(this.oilRows, this.oilUpgrades, this.oilPerSecond());
}
if (newTargetScore[0] != this.targetRow) {
console.log("Targeting row " + newTargetScore[0] + " (" + (this.targetLogs ? this.lumberRows[newTargetScore[0]] : this.oilRows[newTargetScore[0]]) + ")");
this.justLoggedCredit = false;
}
this.targetRow = newTargetScore[0];
if (newTargetScore[1] < newUpgradeScore[1] && newUpgradeScore[0] != -1) {
if (newUpgradeScore[0] != this.targetUpgrade && newUpgradeScore[0] != -1) {
console.log("Targeting upgrade " + " (" + (this.targetLogs ? this.lumberUpgrades[newUpgradeScore[0]] : this.oilUpgrades[newUpgradeScore[0]]) + ")");
this.justLoggedCredit = false;
}
this.targetUpgrade = newUpgradeScore[0];
} else {
this.targetUpgrade = -1;
}
if (this.targetCredit) {
this.processCredit();
} else if (this.targetLogs) {
if (this.targetUpgrade != -1) {
this.processUpgrade(this.lumberUpgrades[this.targetUpgrade]);
} else {
this.processRow(this.lumberRows[this.targetRow]);
}
} else {
if (this.targetUpgrade != -1) {
this.processUpgrade(this.oilUpgrades[this.targetUpgrade]);
} else {
this.processRow(this.oilRows[this.targetRow]);
}
}
this.clickButton("chopWood");
this.clickButton("pumpOil");
},
findTargetRow: function(rows, upgrades, currentCapacity) {
var target = -1;
var maxScore = 0;
for (var j = 0; j < 9; j += 1) {
if (!this.isEnabled(rows[j])) {
continue;
}
var capIncrease = this.RATES[j] * Math.pow(2, this.upgradeCount(upgrades[j])) / currentCapacity;
var waitTime = Math.max(this.logCost(rows[j]) / this.logsPerSecond(), this.oilCost(rows[j]) / this.oilPerSecond());
var discount = Math.exp(-waitTime / this.TAU);
var score = capIncrease / waitTime * discount;
if (score > maxScore) {
maxScore = score;
target = j;
}
}
if (target == -1) {
// Randomize everything if no suitable target was found. Might mess up upgrades :)
target = Math.floor(Math.random() * 9);
if (Math.random() > 0.5) {
this.targetLogs = true;
} else {
this.targetLogs = false;
}
}
return [target, maxScore];
},
findTargetUpgrade: function(rows, upgradeRows, currentCapacity) {
var target = -1;
var maxScore = 0;
for (var j = 0; j < 9; j += 1) {
if (!this.upgradeEnabled(upgradeRows[j])) {
continue;
}
var capIncrease = (this.RATES[j] * this.count(rows[j]) * (Math.pow(2, this.upgradeCount(upgradeRows[j]) + 1) - 1)) / currentCapacity;
var waitTime = Math.max(this.upgradeCost(upgradeRows[j]) / (this.logsPerSecond() + this.oilPerSecond()));
var discount = Math.exp(-waitTime / this.TAU);
var score = capIncrease / waitTime * discount;
if (score > maxScore) {
maxScore = score;
target = j;
}
}
return [target, maxScore];
},
/** Process the row called ROWNAME. If this returns true, skip processing the lower rows. */
processRow: function(rowName) {
if (this.isEnabled(rowName) && this.canAffordLogs(rowName) && this.canAffordOil(rowName)) {
if (this.canAffordMoney(rowName)) {
console.log("Buying " + rowName);
this.buy(rowName);
} else {
this.sell();
return true;
}
}
return false;
},
processUpgrade: function(upgradeName) {
if (this.upgradeEnabled(upgradeName)) {
if (money > this.upgradeCost(upgradeName)) {
console.log("Buying " + upgradeName);
this.buy(upgradeName + "Row");
this.targetUpgrade = -1;
} else {
this.clickButton("sellEighthLumber");
this.clickButton("sellEighthOil");
}
}
},
processCredit: function() {
if (money > 100000000) {
if (!this.justLoggedCredit) {
console.log("Buying carbon credit");
this.justLoggedCredit = true;
}
// Prevent roundoff errors from freezing the bot
var oldMoney = money;
this.clickButton("buyCarbonCredit");
if (money == oldMoney) {
this.clickButton("sellEighthLumber");
this.clickButton("sellEighthOil");
} else {
this.targetCredit = false;
}
} else {
this.clickButton("sellEighthLumber");
this.clickButton("sellEighthOil");
}
},
sell: function() {
var rowBuying = this.lumberRows[0]; //Default
if (this.targetLogs) {
rowBuying = this.lumberRows[this.targetRow];
} else {
rowBuying = this.oilRows[this.targetRow];
}
if (lumber / this.logCost(rowBuying) > oil / this.oilCost(rowBuying)) {
this.clickButton("sellEighthLumber");
} else {
this.clickButton("sellEighthOil");
}
},
isEnabled: function(name) {
return ($("#" + name)[0].style.cssText.indexOf("none") == -1);
},
canAffordMoney: function(name) {
return $("#" + name).find(".infoRown").last().children()[0].style.cssText == "color: rgb(0, 0, 0);";
},
canAffordLogs: function(name) {
return $("#" + name).find(".lumberStoren").last().children()[0].style.cssText == "color: rgb(0, 0, 0);";
},
canAffordOil: function(name) {
return $("#" + name).find(".oilStoren").last().children()[0].style.cssText == "color: rgb(0, 0, 0);";
},
moneyCost: function(name) {
return this.parseNumber($("#" + name).find(".infoRown").last().children().text());
},
logCost: function(name) {
return this.parseNumber($("#" + name).find(".lumberStoren").last().children().text());
},
oilCost: function(name) {
return this.parseNumber($("#" + name).find(".oilStoren").last().children().text());
},
count: function(name) {
name = name.substring(0, name.length - 3) + "Count";
return parseInt($("#" + name).text());
},
upgradeEnabled: function(name) {
var text = $("#" + name + "Row")[0].style.cssText;
return (text.indexOf("none") == -1);
},
upgradeCost: function(name) {
return this.parseNumber($("#" + name + "Cost").text());
},
upgradeCount: function(name) {
return parseInt($("#" + name + "Count").text());
},
buy: function(name) {
// This is used to prevent the roundoff errors from freezing the bot
var oldMoney = money;
$("#" + name).find("button").click();
if (money == oldMoney) {
this.clickButton("sellEighthLumber");
this.clickButton("sellEighthOil");
}
},
clickButton: function(buttonId) {
$("#" + buttonId).click();
},
logsPerSecond: function() {
var logsText = $("#lumberCount").text();
return this.parseNumber(logsText.substring(logsText.indexOf("(") + 1, logsText.indexOf("/")));
},
oilPerSecond: function() {
var oilText = $("#oilCount").text();
return this.parseNumber(oilText.substring(oilText.indexOf("(") + 1, oilText.indexOf("/")));
},
moneyPerSecond: function() {
var logPriceText = $("#lumberPrice").text();
var logPrice = this.parseNumber(logPriceText.substring(logPriceText.indexOf("$") + 1));
var oilPriceText = $("#lumberPrice").text();
var oilPrice = this.parseNumber(logPriceText.substring(logPriceText.indexOf("$") + 1));
return logPrice * this.logsPerSecond() + oilPrice * this.oilPerSecond();
},
parseNumber: function(stringy) {
var l = stringy.length;
suffix = stringy.substring(l-1);
prefix = stringy.substring(0, l-1);
if (suffix == "k") {
return parseFloat(prefix) * 1000;
} else if (suffix == "m") {
return parseFloat(prefix) * 1000000;
} else if (suffix == "b") {
return parseFloat(prefix) * 1000000000;
} else if (suffix == "t") {
return parseFloat(prefix) * 1000000000000;
} else {
return parseFloat(stringy);
}
},
};
// array last utility function
if (!Array.prototype.last){
Array.prototype.last = function(){
return this[this.length - 1];
};
};
console._logger = console.log;
console.log = function(text) {
if(arguments.length) {
var ts = '[' + (new Date()).toLocaleString() + ']';
this._logger(ts,arguments)
}
}
wp = new WoodPants();
wp.start();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment