Skip to content

Instantly share code, notes, and snippets.

@ob-ivan
Forked from jeresig/cookiebot.js
Last active August 19, 2024 03:29
Show Gist options
  • Save ob-ivan/6800011 to your computer and use it in GitHub Desktop.
Save ob-ivan/6800011 to your computer and use it in GitHub Desktop.
A little bit intelligent Cookie Clicker bot.
CookieBot = {
// Inner-use enum constants //
INTERVAL_BAKE : 0,
INTERVAL_GOLDEN : 1,
INTERVAL_PRODUCT : 2,
INTERVAL_UPGRADE : 3,
INTERVAL_DRAGON : 4,
INTERVAL_SANTA : 5,
// Game constants and variables mixed together //
// TODO: Split them to clarify their purposes.
intervals : [],
priceIncrease : 1.15,
products : [
{ name : 'cursor', eff : null },
{ name : 'grandma', eff : null },
{ name : 'farm', eff : null },
{ name : 'mine', eff : null },
{ name : 'factory', eff : null },
{ name : 'bank', eff : null },
{ name : 'temple', eff : null },
{ name : 'wizard_tower', eff : null },
{ name : 'shipment', eff : null },
{ name : 'alchemy_lab', eff : null },
{ name : 'portal', eff : null },
{ name : 'time_machine', eff : null },
{ name : 'antimatter', eff : null },
{ name : 'prism', eff : null }
],
// DOM access //
getProductCount : function (id) {
return Game.ObjectsById[id].amount;
},
getProductStoredCps : function (id) {
return Game.ObjectsById[id].storedCps;
},
getMultiplier : function () {
return Game.globalCpsMult;
},
getProductBasePrice : function (id) {
return Game.ObjectsById[id].basePrice;
},
getProductBulkPrice : function (id) {
return Game.ObjectsById[id].bulkPrice;
},
isProductEnabled : function (id) {
return !!$('div#product' + i + '.enabled');
},
clickProduct : function (id) {
$('div#product' + id).click();
},
// 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 () {
for (var i = 0; i < this.products.length; ++i) {
// Calculate efficiency of _one more unit_, if we are to buy it.
// efficiency = baseCpS * multilpier / (basePrice * priceIncrease ^ count)
this.products[i].eff =
this.getProductStoredCps(i) *
this.getMultiplier() / this.getProductBulkPrice(i);
}
},
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.getProductCount(i) > 0) {
maxOwnIndex = i;
}
if (this.isProductEnabled(i)) {
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) {
if (this.products[i].eff > bestEfficiency) {
bestEfficiency = this.products[i].eff;
bestIndex = i;
}
}
if (bestIndex >= 0) {
this.clickProduct(bestIndex);
}
},
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 #69: One Mind, enables wrinklers.
// skip #84 & #85: Elder Covenant switches (by dieseltravis)
// skip #182-185 & #209: Season event switches.
// skip #331 & #332: Golden switch, should be operated manually.
// skip #333: Milk selector, should be operated manually.
if (/Game\.UpgradesById\[(69|8[45]|18[2-5]|209|33[123])\]/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();
// Click a season event popup.
$("#seasonPopup").click();
},
upgradeDragon : function () {
Game.UpgradeDragon();
},
upgradeSanta : function () {
Game.UpgradeSanta();
},
// 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);
},
startDragon : function () {
this.startInterval(this.INTERVAL_DRAGON, this.upgradeDragon, 1000);
},
stopDragon : function () {
this.stopInterval(this.INTERVAL_DRAGON);
},
startSanta : function () {
this.startInterval(this.INTERVAL_SANTA, this.upgradeSanta, 1000);
},
stopSanta : function () {
this.stopInterval(this.INTERVAL_SANTA);
},
// General controls //
startAll : function() {
this.startBake();
this.startGolden();
this.startProduct();
this.startUpgrade();
this.startDragon();
this.startSanta();
},
stopAll : function() {
for (var i = 0; i < this.intervals.length; ++i) {
this.stopInterval(i);
}
}
};
@ob-ivan
Copy link
Author

ob-ivan commented Oct 3, 2013

Run the whole code in the console, then CookieBot.startAll() to begin madness, and CookieBot.stopAll() to give it a rest.

There are some more control methods, you can try the ones you prefer: st(art|op)(Bake|Golden|Product|Upgrade).

@ob-ivan
Copy link
Author

ob-ivan commented Oct 3, 2013

Efficiency may be not the best means to measure product's quality. If you have a goal you'd like to achieve and it's got a fixed price, you can calculate the best way to achieve that in terms of "if I buy this thing, how much time will it take to achieve the goal?" Minimal time = best choice.

@ob-ivan
Copy link
Author

ob-ivan commented Feb 10, 2016

[x] Update products info.
[x] Fix bot does not buy a product unless you buy one manually.
[x] Extract DOM access and fix queries.

@ob-ivan
Copy link
Author

ob-ivan commented Feb 19, 2016

[ ] Automate wrinkler popping
[ ] Re-enable One mind upgrade and automate "yes" in popup.
[ ] When on a frenzy, don't click golden cookie as soon as it appears. Wait until it starts disappearing, whis will make frenzy last longer.
[x] Don't autoclick milk selector.
[ ] Enable buying products in batches of 10.
[x] Don't autoclick season switch.
[x] Automate Santa evolution.
[ ] Automate Dragon aura selection.
[ ] Automate buying cheap buildings for achievements.

@Dariahn
Copy link

Dariahn commented May 17, 2018

Hello! I'm pants at coding. Console is showing errors when I run the bot o.o

cookiebot:101 Uncaught ReferenceError: $ is not defined
at Object.bake (:101:9)

cookiebot:57 Uncaught ReferenceError: $ is not defined
at Object.isProductEnabled (:57:9)
at Object.buyProduct (:117:22)

and so forth.. what am I doing wrong?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment