Skip to content

Instantly share code, notes, and snippets.

@thexa4
Last active August 15, 2025 21:03
Show Gist options
  • Select an option

  • Save thexa4/58c10a43d8daffbae7bfd79bfee0e9bd to your computer and use it in GitHub Desktop.

Select an option

Save thexa4/58c10a43d8daffbae7bfd79bfee0e9bd to your computer and use it in GitHub Desktop.
Idle managers
// https://play.elevatorsaga.com
class Manager {
constructor(elevators, floors) {
this.elevators = elevators
this.floors = floors
var obj = this
var id = 0
for(var e of elevators) {
e.id = id++
let elevator = e
elevator.on("idle", function() { obj.onElevatorIdle(elevator) })
elevator.on("passing_floor", function(floorId, direction) { obj.onElevatorPassingFloor(elevator, floorId, direction) })
elevator.on("stopped_at_floor", function(floorId) { obj.onElevatorStoppedAtFloor(elevator, floorId) })
elevator.on("floor_button_pressed", function(floorId) { obj.onElevatorFloorButtonPressed(elevator, floorId) })
this.initElevator(e)
}
for (var f of floors) {
var floor = f
floor.on("up_button_pressed", function(flr) { obj.onFloorUpButtonPressed(flr) })
floor.on("down_button_pressed", function(flr) { obj.onFloorDownButtonPressed(flr) })
this.initFloor(f)
}
this.configure()
for (var e of elevators) {
this.onElevatorIdle(e)
}
}
configure() {
this.pickupsUp = []
this.pickupsDown = []
}
initElevator(elevator) {
elevator.goingUpIndicator(true)
elevator.goingDownIndicator(true)
elevator.destinations = []
}
initFloor(floor) {
}
update(dt, elevators, floors) {
}
onElevatorIdle(elevator) {
console.log("Idle on floor " + elevator.currentFloor())
if (elevator.getPressedFloors().length != 0)
{
if (elevator.destinations.length != 0)
return
console.log(elevator)
console.log(elevator.getPressedFloors())
console.log(elevator.destinations)
console.log("crash()")
return
}
if (elevator.id <= -1 || (this.pickupsUp.length == 0 && this.pickupsDown.length == 0)) {
elevator.goingUpIndicator(true)
elevator.goingDownIndicator(true)
let idleFloor = Math.floor((this.floors.length / this.elevators.length) * elevator.id)
elevator.goToFloor(idleFloor)
console.log("Idle: idleFloor")
return
}
let pivot = elevator.currentFloor()
let pickupsUp = this.pickupsUp.filter(f => f >= pivot)
let pickupsDown = this.pickupsDown.filter(f => f <= pivot)
if (pickupsUp.length > 0 || pickupsDown.length > 0)
{
if (pickupsUp.length > pickupsDown.length) {
elevator.destinations = [pickupsUp[0]]
console.log("Idle, multiple up: " + pickupsUp)
this.pickupsUp = this.pickupsUp.filter(f => f != pickupsUp[0])
} else {
elevator.destinations = [pickupsDown[0]]
console.log("Idle, multiple down: " + pickupsDown)
this.pickupsDown = this.pickupsDown.filter(f => f != pickupsDown[0])
}
this.updateElevatorQueue(elevator)
} else {
let closestUp = this.pickupsUp.sort((a, b) => Math.abs(a - pivot) > Math.abs(b - pivot))
let closestDown = this.pickupsDown.sort((a, b) => Math.abs(a - pivot) < Math.abs(b - pivot))
var upDist = closestUp.length > 0 ? Math.abs(closestUp[0] - pivot) : 100000
var downDist = closestDown.length > 0 ? Math.abs(closestDown[0] - pivot) : 100000
console.log("Idle dists: " + upDist + ", " + downDist)
if (upDist < downDist) {
console.log("Idle: single up at " + closestUp[0])
elevator.destinations = [closestUp[0]]
elevator.destinationQueue = [closestUp[0]]
elevator.checkDestinationQueue()
elevator.goingUpIndicator(true)
elevator.goingDownIndicator(false)
//pickupsUp = pickupsUp.filter(f => f != closestUp[0])
} else {
console.log("Idle: single down at " + closestDown[0])
elevator.destinations = [closestDown[0]]
elevator.destinationQueue = [closestDown[0]]
elevator.checkDestinationQueue()
elevator.goingUpIndicator(false)
elevator.goingDownIndicator(true)
//pickupsDown = pickupsDown.filter(f => f != closestDown[0])
}
}
}
onElevatorPassingFloor(elevator, floorId, direction) {
console.log("Passing floor " + floorId + " with elevator " + elevator.id + " dir " + direction)
if (elevator.loadFactor() >= 0.55)
{
return
}
if (direction == "up") {
if (this.pickupsUp.includes(floorId))
{
elevator.goToFloor(floorId, true)
}
} else {
if (this.pickupsDown.includes(floorId))
{
elevator.goToFloor(floorId, true)
}
}
}
onElevatorStoppedAtFloor(elevator, floorId) {
elevator.destinations = elevator.destinations.filter(a => a != floorId)
this.updateElevatorQueue(elevator)
if (elevator.destinations.length == 0) {
elevator.goingUpIndicator(true)
elevator.goingDownIndicator(true)
} else {
if (elevator.destinations[0] < elevator.currentFloor()) {
elevator.goingUpIndicator(false)
elevator.goingDownIndicator(true)
} else {
elevator.goingUpIndicator(true)
elevator.goingDownIndicator(false)
}
}
if (elevator.goingUpIndicator()) {
this.pickupsUp = this.pickupsUp.filter(f => f != floorId)
}
if (elevator.goingDownIndicator()) {
this.pickupsDown = this.pickupsDown.filter(f => f != floorId)
}
}
onElevatorFloorButtonPressed(elevator, floorId) {
if (elevator.destinations.includes(floorId))
return
elevator.destinations.push(floorId)
this.updateElevatorQueue(elevator)
}
onFloorDownButtonPressed(floor) {
console.log("Down requested at " + floor.floorNum())
this.pickupsDown.push(floor.floorNum())
}
onFloorUpButtonPressed(floor) {
console.log("Up requested at " + floor.floorNum())
this.pickupsUp.push(floor.floorNum())
}
updateElevatorQueue(elevator) {
var pivot = elevator.currentFloor()
var reverse = false
if (elevator.destinationDirection() == "up") {
pivot++
}
if (elevator.destinationDirection() == "down") {
pivot--
reverse = true
}
elevator.destinations = elevator.destinations.sort()
let greater = elevator.destinations.filter(f => f >= pivot)
let lesser = elevator.destinations.filter(f => f < pivot)
var result = []
if (reverse) {
result = lesser.concat(greater.reverse())
} else {
result = greater.concat(lesser.reverse())
}
if (result.length == 0) {
this.onElevatorIdle(elevator)
return
}
let desiredNextFloor = result[0]
if (elevator.destinationQueue.length == 0 || elevator.destinationQueue[0] != desiredNextFloor) {
elevator.destinationQueue = [desiredNextFloor]
elevator.checkDestinationQueue()
}
}
}
({
init: function(elevators, floors) {
Manager.instance = new Manager(elevators, floors)
},
update: function(dt, elevators, floors) {
Manager.instance.update(dt, elevators, floors)
}
})
// https://kittensgame.com/web/
var astronomyButton = document.getElementById("observeButton");
var lastTabSwitch = 0;
var switchTodo = [];
document.isSwitching = 1;
window.automationPaused = false;
window.lastReligionPost = -1
if (window.tradeAlways === undefined)
window.tradeAlways = false
function isSpaceBuildingAvailable(name)
{
return game.space.metaCache[name].unlocked
}
function canBuildSpaceBuilding(name)
{
game.space
}
function isBuildingAvailable(name)
{
let buttons = gamePage.bldTab.children;
for (var b of buttons) {
if (b.model.options.name.startsWith(name)) {
return true;
}
}
return false;
}
function canBuild(name)
{
let buttons = gamePage.bldTab.children;
for (var b of buttons) {
//console.log([name, b.model.options.name])
if (b.model.options.name.startsWith(name)) {
if(b.model.enabled && b.controller.hasResources(b.model)) {
return true;
}
}
}
return false;
}
function buildBuilding(name) {
console.log("Building " + name);
let buttons = gamePage.bldTab.children;
for (var b of buttons) {
if (b.model.options.name.startsWith(name)) {
if(b.model.enabled && b.controller.hasResources(b.model)) {
//b.model.prices = b.controller.getPrices(b.model);
//b.controller.payPrice(b.model);
//b.controller.incrementValue(b.model);
b.onClick();
gamePage.console.msg("Built a new " + name, "", "", false);
return true;
}
}
}
return false;
}
function resourceAvailable(name, tresh) {
let resource = gamePage.resPool.get(name);
let limit = resource.maxValue * tresh;
if (limit <= resource.value + 1)
return Math.floor(resource.value - limit);
return 0;
}
function resourcePercentage(name)
{
let resource = gamePage.resPool.get(name);
return resource.value / resource.maxValue;
}
function craftItem(item, num, divisor = 1) {
var amount = Math.max(1, Math.floor(num / divisor));
//let ratio = gamePage.getResCraftRatio(name);
//amount = parseFloat((amount * (1 + ratio)).toFixed(2));
gamePage.craft(item, amount);
//if (item == 'wood')
// console.log(["craft", item, amount]);
return amount;
}
function autoCraft(item, desiredRatio = 1, treshold = 0.92, capTreshold = 0.92)
{
let itemPool = gamePage.resPool.get(item);
let currentCount = itemPool.value;
let craft = game.workshop.getCraft(item);
if (craft == null || craft.unlocked == false)
return null;
let ratio = 1 + gamePage.getResCraftRatio(item);
// Figure out how many times we can press the button at best
var maxTimesPressable = null;
var realLimit = null;
for (var ingredient of craft.prices)
{
let ingredientPool = gamePage.resPool.get(ingredient.name);
if (!ingredientPool.unlocked)
return null;
let curMaxTimesPressable = Math.floor(ingredientPool.value / ingredient.val);
if (realLimit == null || curMaxTimesPressable < realLimit)
realLimit = curMaxTimesPressable;
if (ingredientPool.maxValue != 0 && ingredientPool.value > capTreshold * ingredientPool.maxValue)
{
var tighterLimit = (ingredientPool.value - capTreshold * ingredientPool.maxValue) / ingredient.val;
if (tighterLimit < realLimit)
realLimit = tighterLimit
// This ingredient is full, skip
continue;
}
// if (item == 'manuscript')
// console.log([ingredient.name, curMaxTimesPressable])
if (maxTimesPressable == null || curMaxTimesPressable * desiredRatio < maxTimesPressable)
maxTimesPressable = curMaxTimesPressable * desiredRatio;
}
if (maxTimesPressable == null)
maxTimesPressable = 0;
let maxResultingAddition = maxTimesPressable * ratio;
let currentItems = itemPool.value
let desiredDelta = (maxResultingAddition - currentItems) / 2;
let desiredClickCount = Math.min(Math.floor(desiredDelta / ratio), realLimit);
// if (item == 'manuscript')
// console.log([desiredClickCount, maxTimesPressable, realLimit, desiredDelta]);
// Figure out if all resources are capped, if so, make lowest one uncapped.
var isCapped = true;
var capTimesPressable = null;
for (var ingredient of craft.prices)
{
let ingredientPool = gamePage.resPool.get(ingredient.name);
if (ingredientPool.maxValue == 0)
continue;
let excess = ingredientPool.value - ingredientPool.maxValue * treshold;
if (excess < 0)
{
isCapped = false;
break;
}
let maxTimesPressable = Math.floor(excess / ingredient.val);
if (capTimesPressable == null || maxTimesPressable < capTimesPressable)
capTimesPressable = maxTimesPressable;
}
var timesToPress = desiredClickCount;
if (isCapped)
timesToPress = Math.max(timesToPress, capTimesPressable);
// if (item == 'beam')
// console.log([item, normalDelta, capped, capAmount, lowestAmount, itemPool.value])
if (timesToPress <= 0)
return 0;
gamePage.craft(item, timesToPress);
return timesToPress;
}
function doLoop() {
if (window.automationPaused)
return;
let ticksPerSeason = 1000;
// Observation
if (astronomyButton.children.length > 0)
astronomyButton.children[0].click();
// Catnip management
let catnip = gamePage.resPool.get('catnip');
let calendar = gamePage.calendar;
var kittens = gamePage.resPool.get('kittens');
if (calendar.season == 0 || kittens.value == 0) // spring
{
let field = gamePage.bld.get('field');
let fieldPrice = gamePage.bld.getPrices('field')[0].val;
if (catnip.perTickCached > 0.1 && fieldPrice < catnip.value)
if (field.unlocked)
buildBuilding('Catnip Field');
if (canBuild('Pasture') && gamePage.resPool.get('kittens').value > 0)
buildBuilding('Pasture');
}
var spaceAutoBuild = [
'orbitalLaunch',
'moonMission',
'duneMission',
'sattelite',
'spaceElevator',
'piscineMission',
'heliosMission',
'hydrofracturer',
'spiceRefinery',
]
// Huts
if (calendar.season == 3) // winter
{
if (kittens.value == kittens.maxValue && kittens.value > 0)
{
var depletionRate = catnip.value / -catnip.perTickCached;
if (catnip.perTickCached > 0 || depletionRate > ticksPerSeason * 2.5)
{
if (canBuild('Hut'))
buildBuilding('Hut');
else
{
if (canBuild('Log House'))
{
buildBuilding('Log House')
} else {
if (canBuild('Mansion')) {
buildBuilding('Mansion')
} else {
spaceAutoBuild.push('spaceStation')
}
}
}
}
}
}
// Always build:
var autoBuild = [
'Library',
'Unic. Pasture',
'Barn',
'Mine',
'Workshop',
'Academy',
'Warehouse',
'Aqueduct',
'Amphitheatre',
'Temple',
'Tradepost',
'Observatory',
'Harbour',
'Ziggurat',
'Oil Well',
'Chapel',
'Quarry',
'Mint',
'Lumber Mill',
'Bio Lab',
'Broadcast Tower',
'Hydro Plant',
'Reactor',
'Accelerator',
'Spaceport',
//'Chronosphere',
'Zebra Outpost',
'Zebra Workshop',
'Zebra Forge',
'Ivory Temple',
]
if (gamePage.bld.get('field').val == 0)
autoBuild.push('Catnip Field')
let energyLeft = gamePage.resPool.energyProd - gamePage.resPool.energyCons * 1.1;
// Power buildings
if (isBuildingAvailable('Magneto'))
{
var oilGeneratedPerTick = gamePage.resPool.get('oil').perTickCached
var calcinerUsage = gamePage.bld.get('calciner').totalEffectsCached.oilPerTickCon;
oilGeneratedPerTick += calcinerUsage;
let magnetoInfo = gamePage.bld.get('magneto')
if (energyLeft <= 0 && magnetoInfo.val == magnetoInfo.on)
{
if (oilGeneratedPerTick > 0.05)
autoBuild.push('Magneto')
}
autoBuild.push('Steamworks')
let calcinerInfo = gamePage.bld.get('calciner')
if (calcinerInfo.on == calcinerInfo.val && energyLeft > 0 && oilGeneratedPerTick > 0.024)
autoBuild.push('Calciner')
if (energyLeft > 0)
{
autoBuild.push('Factory')
}
}
if (energyLeft > 0)
autoBuild.push('Data Center')
if (energyLeft <= 0)
autoBuild.push('Solar Farm')
// Smelters
{
let woodRate = gamePage.resPool.get('wood').perTickCached / 0.05;
let mineralRate = gamePage.resPool.get('wood').perTickCached / 0.1;
let percentage = 0.2;
let lowestRate = Math.min(woodRate, mineralRate);
let currentAmount = gamePage.bld.get('smelter').val;
if (lowestRate > 0)
{
let desiredCount = Math.floor(lowestRate / (1 - percentage) * percentage);
let smelterInfo = gamePage.bld.get('smelter')
if (smelterInfo.on == smelterInfo.val && desiredCount >= currentAmount + 1)
autoBuild.push('Smelter')
}
}
for (var building of autoBuild)
if (canBuild(building))
buildBuilding(building);
let autoCraftItems = [
'slab',
'plate',
'wood',
'scaffold',
'beam',
'parchment',
'gear',
'megalith',
'ship',
'alloy',
'concrete',
'tanker',
'kerosene',
'thorium',
'eludium',
'tMythril',
];
for (var item of autoCraftItems)
autoCraft(item, 3);
// lower treshold so it can compete with plates
autoCraft('steel', 3, 0.90, 0.90)
// don't autocraft when science is full
autoCraft('compedium', 3, 10);
autoCraft('blueprint', 1, 10);
// don't autocraft when culture is full
autoCraft('manuscript', 3, 10);
// Promotion
if (game.resPool.get('kittens').value > 0 && resourceAvailable('gold', 0.95) > 0)
gamePage.village._promoteKittensInternal()
let goldAvailable = resourceAvailable('gold', 0.95);
let slabAvailable = gamePage.resPool.get('slab').value;
// Embassy
for (var racePanel of gamePage.diplomacyTab.racePanels)
{
if (!racePanel.visible)
continue;
if (racePanel.embassyButton === null)
continue
let prices = racePanel.embassyButton.controller.getPrices(racePanel.embassyButton.model);
var canPay = true;
for (var item of prices)
{
var itemPool = gamePage.resPool.get(item.name);
if (itemPool.value < item.val)
{
canPay = false;
break;
}
}
if (canPay)
racePanel.embassyButton.domNode.click();
}
{
let tradeSeasons = {
'lizards': 1,
'sharks': 0,
'griffins': 2,
'nagas': undefined,
'zebras': 3,
'spiders': 2,
'dragons': 2,
'leviathans': undefined,
}
for (var race of gamePage.diplomacy.races)
{
if (!race.pinned || Math.random() > 0.3)
continue;
let desiredSeason = tradeSeasons[race.name];
if (window.tradeAlways)
desiredSeason = undefined
if (desiredSeason !== undefined && desiredSeason != calendar.season)
continue;
let costs = race.buys.concat([
{"name": 'gold', "val": gamePage.diplomacy.getGoldCost()},
{"name": 'manpower', "val": gamePage.diplomacy.getManpowerCost()},
])
let gains = []
for (var item of race.sells)
{
if (race.embassyLevel <= (item.minLevel || 0))
continue;
gains.push({"name": item.name, "val": item.value * item.chance})
}
let minPercentage = 0.25
var haveResources = true
var maxTradeCount = null
for (var cost of costs)
{
if (cost.val < 0.0001)
continue
let pool = gamePage.resPool.get(cost.name);
var limit = 1000;
if (pool.maxValue != 0)
limit = pool.maxValue * minPercentage;
let tradeItemsAvailable = pool.value - limit;
if (tradeItemsAvailable < 0)
{
haveResources = false;
break;
}
let tradeCount = Math.floor(tradeItemsAvailable / cost.val)
if (maxTradeCount == null || tradeCount < maxTradeCount)
maxTradeCount = tradeCount;
}
for (var gain of gains)
{
let pool = gamePage.resPool.get(cost.name);
if (pool.maxValue == 0)
continue;
let tradeItemsAvailable = pool.maxValue - pool.Value;
let tradeCount = Math.floor(tradeItemsAvailable / cost.val)
if (maxTradeCount == null || tradeCount < maxTradeCount)
maxTradeCount = tradeCount;
}
if (!haveResources || maxTradeCount <= 0)
continue;
gamePage.diplomacy.tradeMultiple(race, maxTradeCount);
}
}
// Hunting
var catpowerAvailable = resourceAvailable('manpower', 0.95);
if (catpowerAvailable > 0)
gamePage.village.huntAll();
// Faith
if (game.religionTab.domNode !== null)
{
var faithAvailable = resourceAvailable('faith', 0.99);
let adoreCap = 10 + game.getEffect("solarRevolutionLimit")
let adoreRatio = game.religion.getSolarRevolutionRatio() / adoreCap
if (faithAvailable > 1 && adoreRatio < 0.95)
gamePage.religion.praise();
if (calendar.year > window.lastReligionPost)
{
window.lastReligionPost = calendar.year
let transcendRatio = game.religion.faithRatio / game.religion._getTranscendNextPrice()
if (transcendRatio > 1.75)
{
gamePage.console.msg("Religion: Please transcend at your leisure", "alert", "", false);
} else {
if ( adoreRatio >= 0.95) {
let faith = gamePage.resPool.get('faith')
let faithRatio = faith.value / faith.maxValue
if (faithRatio > 0.99) {
gamePage.console.msg("Religion: Please Adore the Galaxy at your leisure", "alert", "", false);
} else {
gamePage.console.msg("Religion: Saving up for an Adore the Galaxy action", "", "", false);
}
} else {
gamePage.console.msg("Religion: Transcendance ratio: " + transcendRatio.toFixed(2), "", "", false);
gamePage.console.msg("Religion: Adore ratio: " + adoreRatio.toFixed(2), "", "", false);
}
}
}
// Order of the sun buildings
for (var button of game.religionTab.rUpgradeButtons)
{
if (!button.controller.hasResources(button.model))
continue
button.controller.buyItem(button.model)
}
// Unicorns
{
let alicorns = gamePage.resPool.get('alicorn')
if (alicorns.value >= 26) {
game.religionTab.sacrificeAlicornsBtn.controller.buyItem(game.religionTab.sacrificeAlicornsBtn.model, null)
}
let unicorns = gamePage.resPool.get('unicorns')
let tears = gamePage.resPool.get('tears')
let zigguratCount = game.bld.get('ziggurat').val
let desiredRatio = 2500 / zigguratCount
if (unicorns.value > tears.value * desiredRatio) {
let sacrificeButton = game.religionTab.sacrificeBtn
let amount = Math.floor((unicorns.value - tears.value * desiredRatio) / 2500)
while (amount-- > 0) {
sacrificeButton.controller.buyItem(sacrificeButton.model, null)
}
}
for (var button of game.religionTab.zgUpgradeButtons)
{
if (!button.controller.hasResources(button.model))
continue
button.controller.buyItem(button.model)
}
let sorrow = gamePage.resPool.get('sorrow')
if (sorrow.value < 17)
{
if (game.religionTab.refineBtn !== null)
{
if (game.religionTab.refineBtn.controller.hasResources(game.religionTab.refineBtn.model))
{
game.religionTab.refineBtn.controller.buyItem(game.religionTab.refineBtn.model, null)
}
}
}
let timeCrystals = game.resPool.get('timeCrystal')
let relics = game.resPool.get('relic')
if ((relics.value + 1) * 25 < timeCrystals.value)
{
if (game.religionTab.refineTCBtn !== null)
{
if (game.religionTab.refineTCBtn.hasResources(game.religionTab.refineTCBtn.model)) {
game.religionTab.refineTCBtn.buyItem(game.religionTab.refineTCBtn.model)
}
}
}
}
}
let spaceAutobuy = [
'sattelite',
'spaceElevator',
'planetCracker',
'hydrofracturer',
'researchVessel',
'sunlifter',
'cryostation',
'spaceBeacon'
]
if (energyLeft > 0) {
if (kittens.value == kittens.maxValue && kittens.value > 0)
spaceAutobuy.push('spaceStation')
spaceAutobuy.push('moonBase')
let uranium = gamePage.resPool.get('uranium')
if (uranium.perTickCached > 0.35)
spaceAutobuy.push('moonOutpost')
spaceAutobuy.push('orbitalArray')
}
// Space
if (gamePage.spaceTab.planetPanels !== null)
{
for (var planetPanel of gamePage.spaceTab.planetPanels)
{
for (var structure of planetPanel.children)
{
if (!spaceAutobuy.includes(structure.id))
continue
if (!structure.controller.hasResources(structure.model))
continue
let result = structure.controller.buyItem(structure.model, null, "1")
if (result.itemBought)
{
gamePage.console.msg("Built a new " + structure.id, "", "", false);
}
}
}
}
// Switch tabs every so often
let switchInterval = 1117;
if (document.isSwitching && lastTabSwitch + switchInterval < gamePage.ticks)
{
if (switchTodo.length == 0)
{
switchTodo = [gamePage.ui.activeTabId, 'Bonfire', 'Science', 'Trade', 'Religion', 'Space'];
window.nextTab = gamePage.ui.activeTabId
} else {
if (window.nextTab != gamePage.ui.activeTabId)
{
switchTodo[0] = gamePage.ui.activeTabId
}
}
let nextTab = switchTodo.pop()
for(var tab of game.tabs) {
if (tab.tabId == nextTab) {
if (tab.domNode !== null)
{
gamePage.ui.activeTabId = nextTab
window.nextTab = nextTab
}
}
}
if (switchTodo.length == 0)
{
gamePage.ui.render();
lastTabSwitch = gamePage.ticks;
}
}
}
if (document.loopTimer != undefined) clearInterval(document.loopTimer);
document.loopTimer = setInterval(doLoop, 500);
// https://www.decisionproblem.com/paperclips/index2.html
document.nextPriceChange = Date.now();
document.nextInvestmentChange = Date.now();
document.nextFactory = Date.now();
document.nextProbeRole = Date.now();
document.nextTournament = Date.now();
document.nextSyncSwarm = null;
document.nextEntertainSwarm = null;
//document.nextProbeRoleButton = window.btnRaiseProbeFacElement;
document.maxProduction ||= 0;
document.pricePID ||= {
P: 0.2,
I: 0.01,
D: 0.1,
Last: null,
Sum: 0,
LastSample: Date.now(),
}
var body = document.getElementsByTagName('body')[0];
body.style.color = "#eee8d5";
body.style.background = "#002b36";
document.getElementById("giftShopDiv").style.display = "none";
function doLoop() {
let makeClipButton = window.btnMakePaperclip;
let buyWireButton = window.btnBuyWire;
let wireCost = window.wireCost;
let clipmakerRate = window.clipRate;
document.maxProduction = (9 * document.maxProduction + clipmakerRate) / 10;
if (document.maxProduction > clipmakerRate)
clipmakerRate = document.maxProduction;
let unsoldClips = window.unsoldClips;
let btnLowerPrice = window.btnLowerPrice;
let btnRaisePrice = window.btnRaisePrice;
let btnExpandMarketing = window.btnExpandMarketing;
let btnMakeClipper = window.btnMakeClipper;
let projectButtons = document.getElementsByClassName("projectButton");
let processors = window.processors;
let memory = window.memory;
let optics = window.btnQcomputeElement;
let chips = window.qChipsElements;
let btnMakeMegaClipper = window.btnMakeMegaClipper;
let stratPicker = window.stratPickerElement;
let btnNewTournament = window.btnNewTournament;
let btnRunTournament = window.btnRunTournament;
let btnImproveInvestments = window.btnImproveInvestments;
let investmentLevelLabel = window.investmentLevelElement;
let investmentLevel = investmentLevelLabel ? parseInt(investmentLevelLabel.innerHTML) : 0;
let btnInvest = window.btnInvest;
let btnWithdraw = window.btnWithdraw;
let investmentTotalValueLabel = window.portValue;
let investmentTotalValue = investmentTotalValueLabel ? parseFloat(investmentTotalValueLabel.innerHTML.replaceAll(',','')) : 0;
let investmentCashValueLabel = window.investmentBankroll;
let investmentCashValue = investmentCashValueLabel ? parseFloat(investmentCashValueLabel.innerHTML.replaceAll(',','')) : 0;
let fundsLabel = window.fundsElement;
let funds = fundsLabel ? parseFloat(fundsLabel.innerHTML.replaceAll(',','')) : 0;
let autoClipperCountLabel = window.clipmakerLevel2;
let autoClipperCount = autoClipperCountLabel ? parseInt(autoClipperCountLabel.innerHTML) : 0;
let megaClipperCountLabel = window.megaClipperLevelElement;
let megaClipperCount = megaClipperCountLabel ? parseInt(megaClipperCountLabel.innerHTML) : 0;
let marketingLevelLabel = window.marketingLvlElement;
let marketingLevel = marketingLevelLabel ? parseInt(marketingLevelLabel.innerHTML) : 0;
let investStrat = window.investStratElement;
let btnAddProc = window.btnAddProcElement;
let btnAddMem = window.btnAddMemElement;
let batteryCountLabel = window.batteryLevelElement;
let batteryCount = batteryCountLabel ? parseInt(batteryCountLabel.innerHTML.replaceAll(",","")) : 0;
let powerConsumptionLabel = window.powerConsumptionRateElement;
let powerConsumption = powerConsumptionLabel ? parseInt(powerConsumptionLabel.innerHTML.replaceAll(",", "")) : 0;
let solarCountLabel = window.farmLevelElement;
let solarCount = solarCountLabel ? parseInt(solarCountLabel.innerHTML.replaceAll(",","")) : 0;
let availableMatterDisplay = window.availableMatterDisplayElement;
let availableMatter = availableMatterDisplay ? availableMatterDisplay.innerHTML : "0";
let acquiredMatterDisplay = window.acquiredMatterDisplayElement;
let acquiredMatter = acquiredMatterDisplay ? acquiredMatterDisplay.innerHTML : "0";
let nanoWireDisplay = window.nanoWireElement;
let nanoWire = nanoWireDisplay ? nanoWireDisplay.innerHTML : "0";
let btnMakeFarm = window.btnMakeFarmElement;
let btnFarmx10 = window.btnFarmx10Element;
let btnMakeBattery = window.btnMakeBatteryElement;
let btnBatteryx10 = window.btnBatteryx10Element;
var btnMakeHarvester = window.btnMakeHarvesterElement;
let btnHarvesterx10 = window.btnHarvesterx10Element;
let btnHarvesterx100 = window.btnHarvesterx100Element;
let btnHarvesterx1000 = window.btnHarvesterx1000Element;
var btnMakeWireDrone = window.btnMakeWireDroneElement;
let btnWireDronex10 = window.btnWireDronex10Element;
let btnWireDronex100 = window.btnWireDronex100Element;
let btnWireDronex1000 = window.btnWireDronex1000Element;
let btnMakeFactory = window.btnMakeFactoryElement;
let workSlider = window.sliderElement;
let yomiDisplay = window.yomiDisplayElement;
let yomi = yomiDisplay ? parseInt(yomiDisplay.innerHTML.replaceAll(",","")) : 0;
let btnMakeProbe = window.btnMakeProbeElement;
if (btnMakeHarvester) {
if (btnHarvesterx10 && !btnHarvesterx10.disabled)
btnMakeHarvester = btnHarvesterx10;
if (btnHarvesterx100 && !btnHarvesterx100.disabled)
btnMakeHarvester = btnHarvesterx100;
if (btnHarvesterx1000 && !btnHarvesterx1000.disabled)
btnMakeHarvester = btnHarvesterx1000;
}
if (btnMakeWireDrone) {
if (btnWireDronex10 && !btnWireDronex10.disabled)
btnMakeWireDrone = btnWireDronex10;
if (btnWireDronex100 && !btnWireDronex100.disabled)
btnMakeWireDrone = btnWireDronex100;
if (btnWireDronex1000 && !btnWireDronex1000.disabled)
btnMakeWireDrone = btnWireDronex1000;
}
if (window.humanFlag && buyWireButton && !buyWireButton.disabled) {
let wireLabel = window.wireElement;
let wire = parseInt(wireLabel.innerHTML.replace(",",""));
let wireSeconds = wire / clipmakerRate;
if (wireCost <= 16 && wireSeconds < 600 || wire == 0) {
buyWireButton.click();
return;
}
}
if (window.humanFlag && document.nextPriceChange < Date.now()) {
let inventorySeconds = unsoldClips / document.maxProduction;
let target = 30;
let error = (target - inventorySeconds) / 30;
let deltaT = (Date.now() - document.pricePID.LastSample) / 100;
if (deltaT > 5 || deltaT < 0.01) {
document.pricePID.Last = error;
document.pricePID.LastSample = Date.now();
} else {
document.pricePID.Sum += error / deltaT;
if (document.pricePID.Sum > 100)
document.pricePID.Sum = 100;
if (document.pricePID.Sum < -100)
document.pricePID.Sum = -100;
var outcome = 0;
outcome += error * document.pricePID.P;
outcome += document.pricePID.Sum * document.pricePID.I;
if (document.pricePID.Last != null) {
outcome += (error - document.pricePID.Last) * document.pricePID.D / deltaT;
}
/*console.log({
seconds: inventorySeconds,
P: error * document.pricePID.P,
I: document.pricePID.Sum * document.pricePID.I,
D: (error - document.pricePID.Last) * document.pricePID.D,
"=": outcome
});*/
//console.log({seconds: inventorySeconds, unsold: unsoldClips, rate: clipmakerRate})
document.pricePID.Last = error;
document.pricePID.LastSample = Date.now();
let desiredPriceChange = (outcome - window.margin) * 100;
if (desiredPriceChange < -0.5 && !btnLowerPrice.disabled) {
//document.nextPriceChange = Date.now() + 1 * 1000;
btnLowerPrice.click();
return;
}
if (desiredPriceChange > 0.5 && !btnRaisePrice.disabled) {
//document.nextPriceChange = Date.now() + 1 * 1000;
btnRaisePrice.click();
return;
}
}
}
if (window.humanFlag && marketingLevel < 18 && btnExpandMarketing && !btnExpandMarketing.disabled) {
btnExpandMarketing.click();
return;
}
for (var project of projectButtons) {
if (project.disabled)
continue;
if (project.textContent.includes("The Universe Next Door")) {
if (Math.random() < 0.5)
continue; // Try to reach 1:1 sim, universe ratio
}
if (project.textContent.includes("Algorithmic Trading")) {
if (strategyEngineFlag == 0)
continue;
}
console.log("Bought project: " + project.textContent);
project.click();
return;
}
if (window.humanFlag && (megaClipperCount < marketingLevel * 4 || window.funds > 128e6) && !btnMakeMegaClipper.disabled) {
btnMakeMegaClipper.click();
return;
}
if (window.humanFlag && (autoClipperCount < marketingLevel * 6 || window.funds > 128e6) && !btnMakeClipper.disabled) {
btnMakeClipper.click();
return;
}
if (btnAddProc && btnAddMem && !btnAddProc.disabled) {
if (memory < 70) {
if (processors < 10) {
if (processors < memory) {
btnAddProc.click();
return;
} else {
btnAddMem.click();
return;
}
} else {
btnAddMem.click();
return;
}
} else {
if (memory < 300) {
if (processors * 2 < memory) {
btnAddProc.click();
return;
} else {
btnAddMem.click();
return;
}
} else {
btnAddProc.click();
return;
}
}
}
if (window.autoTourneyFlag && window.autoTourneyStatus) {
let tourneyButton = window.btnToggleAutoTourneyElement;
if (!tourneyButton.disabled) {
tourneyButton.click();
return;
}
}
if (stratPicker && strategyEngineFlag == 1 && !btnNewTournament.disabled && yomi < 128000 && document.nextTournament < Date.now()) {
document.nextTournament = Date.now() + 30 * 1000;
stratPicker.selectedIndex = stratPicker.children.length - 1;
btnNewTournament.click();
return;
}
if (btnRunTournament && strategyEngineFlag == 1 && !btnRunTournament.disabled) {
btnRunTournament.click();
return;
}
if (window.humanFlag && window.investmentEngineFlag == 1 && btnImproveInvestments && !btnImproveInvestments.disabled) {
btnImproveInvestments.click();
return;
}
if (window.humanFlag && window.investmentEngineFlag == 1 && document.nextInvestmentChange < Date.now()) {
document.nextInvestmentChange = Date.now() + 30 * 1000;
if (investStrat)
investStrat.selectedIndex = 1;
if (investmentLevel > 3 && btnInvest) {
if (funds > investmentTotalValue)
{
document.nextInvestmentChange = Date.now() + 30 * 1000;
btnInvest.click();
return;
}
}
if (btnWithdraw) {
if (investmentCashValue > funds && investmentCashValue / investmentTotalValue < 0.5) {
btnWithdraw.click();
return;
}
}
}
if (!window.spaceFlag && !window.humanFlag && window.project127.flag && !btnMakeFarm.disabled) {
desired = Math.floor(powerConsumption / 50 * 1.3 + 1)
if (solarCount < desired) {
//let delta = desired - solarCount;
if (!btnFarmx10.disabled) {
btnFarmx10.click();
} else {
btnMakeFarm.click();
}
return;
}
}
if (!window.spaceFlag && !window.humanFlag && window.project127.flag && !btnMakeBattery.disabled) {
desired = Math.floor(powerConsumption / 500 * 8 + 1)
if (batteryCount < desired) {
let delta = desired - batteryCount;
if (delta > 10)
btnBatteryx10.click();
else
btnMakeBattery.click();
return;
}
}
if (memory < 300) {
if (workSlider && workSlider.value != "140") {
workSlider.value = "140";
return;
}
} else {
if (workSlider && workSlider.value != "80") {
workSlider.value = "80";
return;
}
}
if (!window.spaceFlag && !window.humanFlag && window.factoryFlag && !btnMakeFactory.disabled && document.nextFactory < Date.now()) {
if (nanoWire != "0") {
document.nextFactory = Date.now() + 2 * 1000;
btnMakeFactory.click();
return;
}
}
if (window.spaceFlag) {
if (!window.btnIncreaseProbeTrustElement.disabled) {
window.btnIncreaseProbeTrustElement.click();
return;
}
if (!window.btnEntertainSwarmElement.disabled && window.entertainButtonDivElement.style.display != "none") {
if (document.nextEntertainSwarm == null) {
document.nextEntertainSwarm = Date.now() + 2 * 60 * 1000;
} else {
if (document.nextEntertainSwarm < Date.now()) {
console.log("Entertained swarm")
document.nextEntertainSwarm = null;
window.btnEntertainSwarmElement.click();
return;
}
}
}
if (!window.btnSynchSwarmElement.disabled && window.synchButtonDivElement.style.display != "none") {
if (document.nextSyncSwarm == null) {
document.nextSyncSwarm = Date.now() + 2 * 60 * 1000;
} else {
if (document.nextSyncSwarm < Date.now()) {
console.log("Synchronizing swarm")
document.nextSyncSwarm = null;
window.btnSynchSwarmElement.click();
return;
}
}
}
if (!window.btnIncreaseMaxTrustElement.disabled) {
window.btnIncreaseMaxTrustElement.click();
return;
}
if (window.probeUsedTrust < window.probeTrust - 1) {
//window.probeSpeed
//window.probeNav
//window.probeRep
//window.probeHaz
//window.probeFac
//window.probeHarv
//window.probeWire
if (window.project131.flag == 1 && window.probeCombat < 6 && !window.btnRaiseProbeCombatElement.disabled) {
window.btnRaiseProbeCombatElement.click();
return;
}
if (window.probeHaz < 4 && !window.btnRaiseProbeHazElement.disabled) {
window.btnRaiseProbeHazElement.click();
return;
}
if (window.probeRep < 6 && !window.btnRaiseProbeRepElement.disabled) {
window.btnRaiseProbeRepElement.click();
return;
}
if (window.probeSpeed <= window.probeNav && !window.btnRaiseProbeSpeedElement.disabled) {
if (window.probeSpeed < 4) {
window.btnRaiseProbeSpeedElement.click();
return;
} else {
if (!window.btnRaiseProbeRepElement.disabled) {
window.btnRaiseProbeRepElement.click();
return;
}
}
} else if(!window.btnRaiseProbeNavElement.disabled) {
if (window.probeNav < 4) {
window.btnRaiseProbeNavElement.click();
return;
} else {
if (!window.btnRaiseProbeRepElement.disabled) {
window.btnRaiseProbeRepElement.click();
return;
}
}
}
}
if (window.project131.flag == 1 && window.probeCombat < 6) {
if (window.probeSpeed >= window.probeNav && !window.btnLowerProbeSpeedElement.disabled) {
window.btnLowerProbeSpeedElement.click();
return;
}
if (window.probeNav >= window.probeSpeed && !window.btnLowerProbeNavElement.disabled) {
window.btnLowerProbeNavElement.click();
return;
}
}
if (window.probeFac + window.probeHarv + window.probeWire < 1) {
let mdpsLabel = window.mdpsElement;
let mapsLabel = window.mapsElement;
let mdbsUnit = mdpsLabel.innerHTML.split(' ')[1];
let mapsUnit = mapsLabel.innerHTML.split(' ')[1];
let mdbsValue = parseFloat(mdpsLabel.innerHTML.split(' ')[0]);
let mapsValue = parseFloat(mapsLabel.innerHTML.split(' ')[0]);
if (window.availableMatter > 0 && window.acquiredMatter == 0 && (mdbsUnit != mapsUnit || mdbsValue > 2 * mapsValue)) {
if (!window.btnRaiseProbeHarvElement.disabled) {
window.btnRaiseProbeHarvElement.click();
return;
}
} else if(window.acquiredMatter > 0 && window.wire == 0) {
if (!window.btnRaiseProbeWireElement.disabled) {
window.btnRaiseProbeWireElement.click();
return;
}
} else if(window.wire > 0) {
if (!window.btnRaiseProbeFacElement.disabled) {
window.btnRaiseProbeFacElement.click();
return;
}
}
}
if (document.nextProbeRole < Date.now() && window.probeTrust > 5) {
document.nextProbeRole = Date.now() + 10 * 1000;
if (window.probeFac > 0 && !window.btnLowerProbeFacElement.disabled) {
window.btnLowerProbeFacElement.click();
//document.nextProbeRoleButton = window.btnRaiseProbeHarvElement;
return;
}
if (window.probeHarv > 0 && !window.btnLowerProbeHarvElement.disabled) {
window.btnLowerProbeHarvElement.click();
//document.nextProbeRoleButton = window.btnRaiseProbeWireElement;
return;
}
if (window.probeWire > 0 && !window.btnLowerProbeWireElement.disabled) {
window.btnLowerProbeWireElement.click();
//document.nextProbeRoleButton = window.btnRaiseProbeFacElement;
return;
}
}
if (window.probeCount == 0 && !btnMakeProbe.disabled) {
btnMakeProbe.click();
return;
}
}
if (optics && !optics.disabled) {
var sum = 0;
for (var chip of chips) {
sum += parseFloat(chip.style.opacity);
}
if (sum > 0 && window.operations < 1000 * memory) {
optics.click();
return;
}
}
if (makeClipButton && !makeClipButton.disabled) {
makeClipButton.click();
return;
}
if (!window.spaceFlag && !window.humanFlag && window.harvesterFlag && !btnMakeHarvester.disabled) {
if (acquiredMatter == "0") {
btnMakeHarvester.click();
return;
}
}
if (!window.spaceFlag && !window.humanFlag && window.wireDroneFlag && !btnMakeWireDrone.disabled && acquiredMatter != "0") {
if (nanoWire == "0") {
btnMakeWireDrone.click();
return;
}
}
}
var apm = 120;
if (document.loopTimer != undefined) clearInterval(document.loopTimer);
document.loopTimer = setInterval(doLoop, 60000 / apm);
@thexa4
Copy link
Author

thexa4 commented Nov 27, 2022

It's meant to be pasted in your developer console, can you retry it there instead of in tampermonkey?

@thexa4
Copy link
Author

thexa4 commented Nov 28, 2022

Sorry, I looked at the wrong script. I fixed the syntax error. Thanks for checking in the console.

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