Last active
October 1, 2019 21:52
-
-
Save Eibwen/e05f0e38f9fad1753ae4b06bedd4a6fb to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* This is designed to (semi-)passively help with https://gzgreg.github.io/DerivativeClicker/ | |
* The main function is to only keep a baseline of count for all Buildings | |
* it does this by buying any buildings which 1 second worth of time will pay for | |
* By doing that it still allows your base money to continue growing constantly | |
* | |
* NEW ADDED: Which doesn't fully follow that. Is auto-buying any TierUpgrades possible as soon as you can afford it | |
* NEW ADDED: Also not following that. If it reaches the point where your cash-on-hand can buy all the highest tier items, it will buy those for you, so that the rewards trickle down even if you're AFK | |
* | |
* | |
* TODO: Do I want this to be semi-passive still, or just have it trying to be optimized, especially as you progress to higher tiers | |
* | |
* TO USE: | |
* Just open your debugging console, and paste this in | |
*/ | |
// Update scripts | |
(function() { | |
if (boughtRecently) console.log("Updated Script: Auto-Bought", boughtRecently); | |
if (autoRunTimeout) clearTimeout(autoRunTimeout); | |
if (statsTimeout) { | |
clearTimeout(statsTimeout); | |
statsTimeout = null; | |
} | |
})(); | |
function calculateMoneyPerSecond() { | |
var autoClickRate = player.upgrades[0] / player.autoclickInterval; | |
var netPossibleChange = player.netMoneyPerSecond + (autoClickRate * player.moneyPerAutoclick); | |
// Negative income, doesn't mean negative purchase power | |
var incomePerSecond = (netPossibleChange > 0) ? netPossibleChange : 0; | |
// Don't claim we can purchase INTO negative either | |
return Math.min(incomePerSecond, player.money); | |
} | |
var boughtRecently = {}; | |
function autoBuy() { | |
// Upgrades are top-priority | |
autoBuyTierUpgrades(); | |
var maxIndex = (tierUnlockLevel() + 1) * 5; | |
var purchasableItems = player.buildings.map((x, i) => | |
({ | |
index: i, | |
priority: i, | |
moneyCostFunc: () => player.buildings[i].moneyCost, | |
proofCostFunc: () => player.buildings[i].proofCost, | |
purchaseFunc: () => buyBuilding(i) | |
})) | |
.filter(x => x.moneyCostFunc() <= calculateMoneyPerSecond() && x.proofCostFunc() <= player.proofsPerSecond && x.index < maxIndex) | |
// If don't have any auto-clicker, don't buy those buildings | |
.filter(x => (x.index % 5) != 3 || player.moneyPerAutoclick > 0); | |
if (player.upgradeCosts[0] < calculateMoneyPerSecond()) { | |
// Include Autoclicker | |
purchasableItems.push({ | |
index: "upgrade0", | |
priority: 9, | |
moneyCostFunc: () => player.upgradeCosts[0], | |
proofCostFunc: () => 0, | |
purchaseFunc: () => buyUpgrade(0) | |
}); | |
} | |
if (purchasableItems.length == 0) { | |
// Check the trickleDown instead | |
trickleDown(); | |
return false; | |
} | |
// Reverse sort by priority (higher priority first) | |
purchasableItems.sort((a, b) => b.priority - a.priority); | |
var countLimit = 0; | |
// Fast-catch-up logic. Try to spend all of what we made in the second on this building | |
var moneySpent = -1; | |
var proofsSpent = -1; | |
while (moneySpent < calculateMoneyPerSecond() && proofsSpent < player.proofsPerSecond) { | |
var building = purchasableItems[0]; | |
moneySpent += building.moneyCostFunc(); | |
proofsSpent += building.proofCostFunc(); | |
building.purchaseFunc() | |
boughtRecently[building.index] = boughtRecently[building.index]+1 || 1; | |
if (++countLimit >= 500) { | |
console.log("Hit Limit!!"); | |
console.log("building", building); | |
console.log("location, col", building.index % 5, "row", Math.floor(building.index / 5)); | |
break; | |
} | |
} | |
} | |
function tierUnlockLevel() { | |
return 3 + (player.currBuyables[0].owned && 1) + (player.currBuyables[1].owned && 1) + (player.currBuyables[2].owned && 1); | |
} | |
// Buy Tier Upgrades as soon as you can afford it, from max to min (as the optimal will trend that way) | |
function autoBuyTierUpgrades() { | |
var maxTier = tierUnlockLevel(); | |
var purchasable = []; | |
for (var i = maxTier; i >= 0; --i) { | |
if (player.tierUpgradeCosts[i] < player.money) { | |
purchasable.push(i); | |
} | |
} | |
if (purchasable.length == 0) { | |
return; | |
} | |
var buildingLevelCount = player.buildings.reduce((acc, cur, i) => { acc[~~(i / 5)] += cur.manual; return acc;}, | |
{ 0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0 }); | |
const boostPerLevel = [ 0.0005, 0.002, 0.005, 0.01, 0.02, 0.04, NaN ]; | |
var afterPurchase = purchasable.map((i) => { | |
var after = player.mult[i] + (buildingLevelCount[i] * boostPerLevel[i]); | |
return { | |
index: i, | |
multBefore: player.mult[i], | |
multAfter: after, | |
percentIncrease: after/player.mult[i] | |
}; | |
}); | |
console.log("TIERPURCHASE_DATA", afterPurchase); | |
// Assuming the gains are semi-leveled out... Don't want to figure out all the math needed for a more accurate calculation (TODO) | |
var bestPurchase = afterPurchase.reduce((prev, current) => { | |
return (prev.percentIncrease > current.percentIncrease) ? prev : current | |
}); | |
buyTierUpgrade(bestPurchase.index); | |
boughtRecently["tier"+bestPurchase.index] = boughtRecently["tier"+bestPurchase.index]+1 || 1; | |
console.log("TIERPERCENT_AFTER", player.mult); | |
} | |
// Idea being, overnight or whatever, don't just build up infinite money (as its mostly pointless in this clicker) | |
// So if we can afford the most expensive of: [ auto-click upgrade, maxTierBuildings ] | |
// Switch a state machine to "purchase mode", and buy up all of those from most expensive to cheapest? | |
// Until can't buy any, and switch back to a "passive state" | |
// TODO risk, how this plays with the upgrades might be interesting to see | |
function trickleDown() { | |
var maxTier = tierUnlockLevel(); | |
var money = player.money; | |
var proofs = player.proofs; | |
var purchaseConsideration = player.buildings.map((x, i) => ( | |
{ | |
name: 'building' + i, | |
canAfford: x.moneyCost < money && x.proofCost <= proofs, | |
moneyCost: x.moneyCost, | |
proofCost: x.proofCost, | |
purchaseFunc: () => { buyBuilding(i) } | |
})) | |
.slice(maxTier*5, maxTier*5+5); | |
purchaseConsideration.push({ | |
name: 'auto-click', | |
canAfford: player.upgradeCosts[0] < money, | |
moneyCost: player.upgradeCosts[0], | |
proofCost: 0, | |
purchaseFunc: () => { buyUpgrade(0) } | |
}) | |
if (expensiveBuyMode === 'passive') { | |
// Check if we can buy all the target things | |
if (purchaseConsideration.every(x => x.canAfford) | |
// wait 60 cycles before changing modes --TODO revisit this idea? | |
&& ++expensiveBuyCounter == 60) { | |
console.log('=== MOVING TO PURCHASE STATE ==='); | |
expensiveBuyMode = 'purchase'; | |
} | |
} | |
else if (expensiveBuyMode === 'purchase') { | |
// how to compare Proofs cost vs Money Cost?? Or just always buy proofs first/last, no big deal really!!! | |
// Find most expensive that is purchasable | |
var toPurchase = purchaseConsideration.reduce((acc, cur, i) => (cur.canAfford && (!acc || cur.moneyCost > acc.moneyCost)) ? cur : acc, null); | |
console.log("TRICKLE_DOWN_DEBUG", purchaseConsideration); | |
if (toPurchase) { | |
console.log("TRICKLE_DOWN_BUY", toPurchase); | |
toPurchase.purchaseFunc(); | |
// Reset counter | |
expensiveBuyCounter = 0; | |
} else if (++expensiveBuyCounter >= 30) { | |
// wait 30 cycles before changing modes --TODO revisit this idea? | |
// Nothing left to buy, switch back to passive mode | |
console.log('--- ENDING TO PURCHASE STATE ---'); | |
expensiveBuyMode = 'passive' | |
expensiveBuyCounter = 0; | |
} | |
} | |
else { | |
// Default to passive in an error state | |
expensiveBuyMode = 'passive' | |
} | |
expensiveBuyCounter %= 60; | |
} | |
var expensiveBuyCounter = 0; | |
var expensiveBuyMode = 'passive'; | |
function dumpStats() { | |
// Do not print nor reset the object if nothing was bought | |
if (JSON.stringify(Object.getOwnPropertyNames(boughtRecently)) !== '["date","loopticks"]') { | |
console.log("Auto-Bought", boughtRecently); | |
boughtRecently = { date: new Date() }; | |
} | |
statsTimeout = null; | |
} | |
var autoRunTimeout = undefined; | |
var statsTimeout = null; | |
function autoRunAutoBuy() { | |
boughtRecently["loopticks"] = boughtRecently["loopticks"]+1 || 1; | |
autoRunTimeout = setTimeout(() => { autoBuy(); autoRunAutoBuy(); }, 1000); | |
if (!statsTimeout) statsTimeout = setTimeout(dumpStats, 60000); | |
} | |
autoRunAutoBuy(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment