Skip to content

Instantly share code, notes, and snippets.

@dubslow
Last active February 21, 2016 20: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 dubslow/afcb08a9d3e11baa77d2 to your computer and use it in GitHub Desktop.
Save dubslow/afcb08a9d3e11baa77d2 to your computer and use it in GitHub Desktop.
A simple JS script to make purchasing decisions easier in CookieClicker
/* This is a small addon script for CookieClicker to display building purchase efficiencies, in a
manner similar to FrozenCookie (though several orders of magnitude more primitive). No decisions
or playing is done on behalf of the player, this is merely some extra passive calculations. */
// first a small helper
function guardedSave(obj, funcname)
{ // if obj.oldfuncname exists, do nothing
// else: save the funcname to oldfuncname, so that funcname may be overwritten
// this protects against crashing after accidentally running this js twice
var oldfuncname = 'old' + funcname;
if (typeof obj[oldfuncname] === "undefined")
{
obj[oldfuncname] = obj[funcname];
}
}
var inverselog10 = 1/Math.log(10);
Game.RecalcEfficiencies = function(recalcScale)
{
var recalcGains = Game.recalculateGains;
var curCps = Game.cookiesPs;
var effLogSum = 0;
for (var i in Game.Objects)
{
var me = Game.Objects[i];
// get the new hypothetical cps if this object is purchased
me.amount++;
// below, we replace CalculateGains with a version that also calls RefreshStore, which we specifically
// don't want to do in this case
Game.oldCalculateGains();
var newCps = Game.cookiesPs;
me.amount--;
me.efficiency = (newCps - curCps) / me.getPrice();
//console.log(me.name, me.efficiency)
effLogSum += -Math.log(me.efficiency) * inverselog10;
//console.log(me.name, effLogSum)
}
Game.oldCalculateGains();
// reset back to actual cps rather than hypothetical
Game.recalculateGains = recalcGains;
if (recalcScale) // do not change scale for frenzies (passed as an arg)
{
var effLogAvg = effLogSum / Game.ObjectsN;
var effLog = Math.ceil(effLogAvg + 2.1); // we want things to be 3 digit efficiencies on average
// (and slightly biased to 4 digits instead of 2)
Game.EffScale = Math.pow(10, effLog);
}
//console.log(effLogAvg, effLog, Game.EffScale);
for (var i in Game.Objects)
{
var me = Game.Objects[i];
me.scaledEfficiency = me.efficiency * Game.EffScale;
}
}
for (var i in Game.Objects)
{
var me = Game.Objects[i];
/*
me.ChocEggRecovAmnt = function()
{ // it will take time for the newly bought building to pay for itself relative to using the price towards the chocolate egg bonus
// figure that out here. total recovery amount = price*5%*1/2 (since you sell all the buildings before popping)
// use that to get an ETA, but then figure out what your total cookie count would be at the ETA, and if
// that amount is more than you plan to reset with, then you shouldn't buy the building.
var recovAmount = this.getPrice() * 0.5 * 0.05;
var eta = recovAmount/this.getAddedCPS();
var togo = Game.cookiesPs*eta;
return togo + Game.cookiesEarned+Game.cookiesReset; // if this amount is higher than your reset target, don't buy, just save.
}
*/
// ^^^ I don't think this is actually useful because it doesn't account for future cps mult upgrades
guardedSave(me, 'rebuild');
me.rebuild = function()
{
this.oldrebuild();
l('productPrice'+this.id).innerHTML += '<br/> (Eff ' + Beautify(this.scaledEfficiency, 0) + ')';
/*+ ', CERA ' + Beautify(this.ChocEggRecovAmnt()+Game.cookiesReset) */
}
}
// call Game.RefreshStore whenver we recalc efficiencies, which is whenever cps is changed
guardedSave(Game, 'CalculateGains');
Game.CalculateGains = function()
{
Game.oldCalculateGains();
Game.RecalcEfficiencies(!(Game.frenzy>0)); // arg is whether or not to recalc scale, which we don't during frenzies
Game.RefreshStore();
}
// and away we go!
Game.RecalcEfficiencies(1); // always recalc scale when initializing
Game.RefreshStore();
/*
////////////////////////////////////////////////////////////////////////////////
// add dumb ETA to 1k yottacookies
// this is presented in the stats menu, whose html is unfortunately not id'd, so
// search for the proper divs by hand
// http://stackoverflow.com/a/26595625/1497645
function findElemByContent(content, cls)
{
var textProp = 'textContent' in document ? 'textContent' : 'innerText';
var elems = [].slice.call(document.querySelectorAll('div'), 0);
var found = elems.filter(function(e){return e.className == cls && e[textProp].indexOf(content) > -1;});
return found.length ? found : false;
}
Game.CountWrinklers = function()
{
var n = 0;
for (var i in Game.wrinklers)
{
if (Game.wrinklers[i].phase==2)
n++;
}
return n;
}
Game.WrinklerMult = function(n)
{
// http://cookieclicker.wikia.com/wiki/Wrinkler#CPS_multiplier
if (Game.Has('Wrinklerspawn'))
return 1 - 0.05*n + 0.05775*n*n;
else
return 1 - 0.05*n + 0.055*n*n;
}
Game.EffectiveRate = function()
{
var rate = Game.cookiesPs;
if (Game.elderWrath > 0)
rate *= Game.WrinklerMult(10) * 0.9; // assume that maximum wrinkler efficiency is unobtainable
return rate;
}
Game.LinearETA = function()
{
// now uses wrinkler count!
var current = Game.cookiesEarned + Game.cookiesReset;
var remaining = 1E27 - current; // 1 octillion cookies is the goal
return remaining/Game.EffectiveRate();
}
Game.CurrentQuadraticETA = function()
{
// slightly less dumb ETA. heavenly chips, i.e. cookie rate, go as square root of cookies,
// so cookie increase is approximately quadratic
var currentTime = (new Date().getTime() - Game.fullDate);
var totalCookies = Game.cookiesEarned + Game.cookiesReset;
// y = k t^2 => k = y/t^2
// 1E27 = k t^2 => t = sqrt(1E27/k) = sqrt(1E27*t^2/y)
// sqrt(1E27) = 10^13*sqrt(10)
var finalTime = Math.sqrt(currentTime*(currentTime/totalCookies)) * 1E13 * 3.1622776601683795;
return (finalTime - currentTime)/1000;
}
Game.insertBefore = function(content, cls, newnode)
{
// find the div containing the given content, then insert the new node before it
var elems = findElemByContent(content, cls);
if (elems != false)
{
var elem = elems[0];
var rent = elem.parentNode;
rent.insertBefore(newnode, elem);
}
}
guardedSave(Game, 'UpdateMenu');
Game.UpdateMenu = function()
{
Game.oldUpdateMenu();
var eta1 = Game.sayTime(Game.LinearETA()*Game.fps);
var eta2 = Game.sayTime(Game.CurrentQuadraticETA()*Game.fps);
// I don't know why Game.sayTime requires a factor of Game.fps
var newdiv = document.createElement("div");
newdiv.className = "listing";
newdiv.innerHTML = '<b>1kYcookies ETAs :</b> linear: ' + eta1 + ', quadratic: ' + eta2;
// SI prefixes end at septillion
Game.insertBefore('Session started :', 'listing', newdiv);
newdiv = document.createElement("div");
newdiv.className = "listing";
newdiv.innerHTML = '<b>Price to 400 cursors :</b> <div class="price plain">'+Game.tinyCookie()+Beautify(Game.FourHundredCursors())+'</div>';
Game.insertBefore('Legacy started :', 'listing', newdiv);
}
Game.UpdateMenu();
*/
javascript:function guardedSave(e,a){var i="old"+a;"undefined"==typeof e[i]&&(e[i]=e[a])}var inverselog10=1/Math.log(10);Game.RecalcEfficiencies=function(e){var a=Game.recalculateGains,i=Game.cookiesPs,c=0;for(var f in Game.Objects){var l=Game.Objects[f];l.amount++,Game.oldCalculateGains();var n=Game.cookiesPs;l.amount--,l.efficiency=(n-i)/l.getPrice(),c+=-Math.log(l.efficiency)*inverselog10}if(Game.oldCalculateGains(),Game.recalculateGains=a,e){var r=c/Game.ObjectsN,t=Math.ceil(r+2.1);Game.EffScale=Math.pow(10,t)}for(var f in Game.Objects){var l=Game.Objects[f];l.scaledEfficiency=l.efficiency*Game.EffScale}};for(var i in Game.Objects){var me=Game.Objects[i];guardedSave(me,"rebuild"),me.rebuild=function(){this.oldrebuild(),l("productPrice"+this.id).innerHTML+="<br/> (Eff "+Beautify(this.scaledEfficiency,0)+")"}}guardedSave(Game,"CalculateGains"),Game.CalculateGains=function(){Game.oldCalculateGains(),Game.RecalcEfficiencies(!(Game.frenzy>0)),Game.RefreshStore()},Game.RecalcEfficiencies(1),Game.RefreshStore();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment