Skip to content

Instantly share code, notes, and snippets.

@kenzik
Forked from ob-ivan/cookiebot.js
Created October 16, 2013 16:34
Show Gist options
  • Save kenzik/7010825 to your computer and use it in GitHub Desktop.
Save kenzik/7010825 to your computer and use it in GitHub Desktop.
CookieBot = {
// Inner-use enum constants //
INTERVAL_BAKE : 0,
INTERVAL_GOLDEN : 1,
INTERVAL_PRODUCT : 2,
INTERVAL_UPGRADE : 3,
// Game constants and variables mixed together //
// TODO: Split them to clarify their purposes.
intervals : [],
multiplier : null,
priceIncrease : 1.15,
products : [
// baseCpS is recalculated with respect to purchased upgrades.
{ name : 'cursor', baseCpS : 0.1, basePrice : 15, limit : 200, count : null, eff : null },
{ name : 'grandma', baseCpS : 0.5, basePrice : 100, limit : 200, count : null, eff : null },
{ name : 'farm', baseCpS : 2, basePrice : 500, limit : 100, count : null, eff : null },
{ name : 'factory', baseCpS : 10, basePrice : 3000, limit : 100, count : null, eff : null },
{ name : 'mine', baseCpS : 40, basePrice : 10000, limit : 100, count : null, eff : null },
{ name : 'shipment', baseCpS : 100, basePrice : 40000, limit : 100, count : null, eff : null },
{ name : 'alchemy_lab', baseCpS : 400, basePrice : 200000, limit : 100, count : null, eff : null },
{ name : 'portal', baseCpS : 6666, basePrice : 1666666, limit : 100, count : null, eff : null },
{ name : 'time_machine', baseCpS : 98765, basePrice : 123456789, limit : 100, count : null, eff : null },
{ name : 'antimatter', baseCpS : 999999, basePrice : 4999999999, limit : 100, count : null, eff : null }
],
// Calculcations and helpers //
// Calculates at memoizes exponents of priceIncrease.
priceExponentCache : [],
priceExponent : function (count) {
if (typeof this.priceExponentCache[count] === 'undefined') {
this.priceExponentCache[count] = Math.pow(this.priceIncrease, count);
}
return this.priceExponentCache[count];
},
// Reads input values from page and calculates dependent values.
updateParams : function () {
// I. Read multiplier.
// Multiplier is only available when Stats panel is open.
for (var small, i = 0; ! small && i < 10; small = $('div.listing small'), ++i) {
// Click enough times to make it open, but don't click too much,
// 'cause infinite loops are no fun at all.
$('#statsButton').click();
}
// Oh noes you are hardcoding a locale issue here aren't you!
this.multiplier = parseInt(
small.textContent
.replace(/^.* ([\d,.]+)%.*$/, '$1')
.replace(/,/g, ''),
10
) / 100;
for (var i = 0; i < this.products.length; ++i) {
// II. Read product counts.
// TODO: Move product element access to a single point in code.
var owned = $('div#product' + i + ' div.owned');
if (owned) {
this.products[i].count = parseInt(owned.textContent, 10);
} else {
this.products[i].count = 0;
}
// III. Read CpS.
if (this.products[i].count > 0) {
var rowInfoContent = $('div#rowInfoContent' + i);
if (rowInfoContent) {
var totalCpS = parseFloat(
rowInfoContent.textContent
.replace(/^.*producing ([\d,.]+) cookie.*$/, '$1')
.replace(/,/g, ''),
10
)
if (totalCpS) {
this.products[i].baseCpS = totalCpS / this.products[i].count;
}
}
}
// IV. Calculate efficiency of _one more unit_, if we are to buy it.
// efficiency = baseCpS * multilpier / (basePrice * priceIncrease ^ count)
this.products[i].eff =
this.products[i].baseCpS *
this.multiplier / (
this.products[i].basePrice *
this.priceExponent(this.products[i].count)
);
}
},
startInterval : function (id, callback, ms) {
this.stopInterval(id);
this.intervals[id] = setInterval(callback.bind(this), ms);
},
stopInterval : function (id) {
if (typeof this.intervals[id] !== 'undefined') {
clearInterval(this.intervals[id]);
}
},
// Actions //
bake : function () {
// Click the large cookie.
$("#bigCookie").click();
},
buyProduct : function () {
// Attempt to buy the most efficient product.
// If it is not available, don't buy it.
this.updateParams();
// Limit products in the pricelist to those you already own plus one,
// and include any products you can afford.
var maxOwnIndex = -1;
var maxAffordableIndex = -1;
for (var i = 0; i < this.products.length; ++i) {
if (this.products[i].count > 0) {
maxOwnIndex = i;
}
// TODO: Move product element access to a single point in code.
if ($('div#product' + i + '.enabled')) {
maxAffordableIndex = i;
}
}
var maxInterestedIndex = Math.min(
Math.max(maxOwnIndex + 1, maxAffordableIndex),
this.products.length - 1
);
var bestIndex = -1;
var bestEfficiency = -1;
for (var i = 0; i <= maxInterestedIndex; ++i) {
// Don't buy more than needed for achievements.
if (this.products[i].count >= this.products[i].limit) {
continue;
}
if (this.products[i].eff > bestEfficiency) {
bestEfficiency = this.products[i].eff;
bestIndex = i;
}
}
if (bestIndex >= 0) {
// TODO: Move product element access to a single point in code.
$('div#product' + bestIndex).click();
}
},
buyUpgrade : function () {
// Always appease grandmatriarchs (by dieseltravis).
var pact = $$("#upgrade0.enabled[onclick*='[74]']");
if (pact && pact.length > 0) {
pact[0].click();
}
// Except some grandmatriarchs stuff any upgrade worth buying it.
// Some upgrades give the same effect (like grandmas are twice as efficient),
// though cost different prices.
// It is reasonable to start buying with the cheapest ones.
var upgrades = $$('div#store div.upgrade.enabled');
for (var i = 0; i < upgrades.length; ++i) {
// skip #84 & #85: Elder Covenant switches (by dieseltravis)
if (/Game\.UpgradesById\[8[45]\]/g.test("" + upgrades[i].onclick)) {
continue;
}
upgrades[i].click();
}
},
clickGolden : function () {
// Sometimes a golden cookie will appear to give you a bonus.
var golden = $("#goldenCookie");
// Don't click angry grandmas' wrath cookies.
if (/wrath/.test(golden.style.background)) {
return;
}
// Click a yummy cookie.
golden.click();
},
// Controls //
// Clicks the large cookie as fast as possible.
startBake : function () {
this.startInterval(this.INTERVAL_BAKE, this.bake, 1);
},
stopBake : function () {
this.stopInterval(this.INTERVAL_BAKE);
},
startGolden : function () {
this.startInterval(this.INTERVAL_GOLDEN, this.clickGolden, 1000);
},
stopGolden : function () {
this.stopInterval(this.INTERVAL_GOLDEN);
},
startProduct : function () {
this.startInterval(this.INTERVAL_PRODUCT, this.buyProduct, 1000);
},
stopProduct : function () {
this.stopInterval(this.INTERVAL_PRODUCT);
},
startUpgrade : function () {
this.startInterval(this.INTERVAL_UPGRADE, this.buyUpgrade, 1000);
},
stopUpgrade : function () {
this.stopInterval(this.INTERVAL_UPGRADE);
},
// General controls //
startAll : function() {
this.startBake();
this.startGolden();
this.startProduct();
this.startUpgrade();
},
stopAll : function() {
for (var i = 0; i < this.intervals.length; ++i) {
this.stopInterval(i);
}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment