Last active
April 22, 2024 15:06
-
-
Save Column01/c674139c3dfd6709807e030f64170605 to your computer and use it in GitHub Desktop.
Batch miner for the bitburner game
This file contains 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
// | |
//Main script for batch mining | |
// | |
/** @param {NS} ns */ | |
export async function main(ns) { | |
ns.disableLog("sleep"); | |
var target = ns.args[0]; | |
if (target && ns.serverExists(target)) { | |
ns.tprint("Targetting server: " + target); | |
if (ns.getServerRequiredHackingLevel(target) <= ns.getHackingLevel()) { | |
// Gain access to the server if we can | |
ns.run("hackServer.js", 1, target); | |
// Actual loop that hacks the server | |
while (true) { | |
await ns.sleep(5); | |
// Get the server and player for calculations | |
var server = ns.getServer(target); | |
var player = ns.getPlayer(); | |
// Calculate how much we can actually steal per thread | |
var percentPerThread = ns.formulas.hacking.hackPercent(server, player); | |
// Gather the times required to perform hacks, grows and weakens | |
var timeToHack = ns.getHackTime(target); | |
var timeToGrow = ns.getGrowTime(target); | |
var timeToWeaken = ns.getWeakenTime(target); | |
// Calculate the times for each operation so they line up properly | |
// (all should trigger 500ms apart) | |
var whenToHack = (timeToWeaken - timeToHack) - 500; | |
var whenToFirstWeaken = 0; | |
var whenToGrow = (timeToWeaken - timeToGrow) + 500; | |
var whenToSecondWeaken = 1000; | |
// Output calculated timings for each operation | |
ns.print("Timings calculated for each operation:"); | |
ns.print(`Hack: ${whenToHack}\nWeaken 1: ${whenToFirstWeaken}\nGrow: ${whenToGrow}\nWeaken 2: ${whenToSecondWeaken}`); | |
ns.print(`Attempt to hack could yield ${ns.formatPercent(percentPerThread)}% of the total money from the target`); | |
// Stagger the timing of each operation to ensure they execute in the correct order | |
var numThreads = await calculateThreadCounts(ns, target); | |
var numHackThreads = numThreads["hackThreads"]; | |
var numGrowThreads = numThreads["growThreads"]; | |
var numFirstWeakenThreads = numThreads["firstWeakenThreads"]; | |
var numSecondWeakenThreads = numThreads["secondWeakenThreads"]; | |
ns.print(`Starting the weaken process. Ends in ${timeToWeaken}s`); | |
var firstWeakenPid = await weakenTarget(ns, whenToFirstWeaken, target, numFirstWeakenThreads); | |
var secondWeakenPid = await weakenTarget(ns, whenToSecondWeaken, target, numSecondWeakenThreads); | |
var growPid = await growTarget(ns, whenToGrow, target, numGrowThreads); | |
var hackPid = await hackTarget(ns, whenToHack, target, numHackThreads); | |
if (firstWeakenPid == 0 || secondWeakenPid == 0 || growPid == 0 || hackPid == 0) { | |
ns.tprint("Failed to start a process! Something bad happened..."); | |
ns.tprint(`Weaken PIDs: ${firstWeakenPid} ${secondWeakenPid}`); | |
ns.tprint(`Grow PID: ${growPid}`); | |
ns.tprint(`Hack PID: ${hackPid}`); | |
ns.exit(); | |
} | |
ns.print("Waiting for all threads to finish and then starting over!"); | |
// Wait for the second weaken to finish which indicates a batch is done | |
do { | |
await ns.sleep(100); | |
} while (ns.isRunning(secondWeakenPid)); | |
ns.print("All threads have compelted. Starting over in one second..."); | |
await ns.sleep(1000); | |
} | |
} else { | |
ns.tprint("Server's hacking level is more than we can hack. Git gud first"); | |
} | |
} else { | |
ns.tprint("Specified target does not exist! A target is required to batch mine!"); | |
} | |
} | |
async function weakenTarget(ns, timeToWait, target, numThreads) { | |
// Weaken target security | |
return ns.run("weakenTarget.js", numThreads, target, timeToWait); | |
} | |
async function growTarget(ns, timeToWait, target, numThreads) { | |
// Grow target money | |
return ns.run("growTarget.js", numThreads, target, timeToWait); | |
} | |
async function hackTarget(ns, timeToWait, target, numThreads) { | |
// Hack target money | |
return ns.run("hackTarget.js", numThreads, target, timeToWait); | |
} | |
async function calculateThreadCounts(ns, target) { | |
var server = ns.getServer(target); | |
var player = ns.getPlayer(); | |
// Gather some memory usage info | |
const hackRam = ns.getScriptRam("hackTarget.js"); | |
const growRam = ns.getScriptRam("growTarget.js"); | |
const weakenRam = ns.getScriptRam("weakenTarget.js"); | |
const managerRam = ns.getScriptRam("batchMine.js"); | |
const serverRam = ns.getServerMaxRam(ns.getHostname()); | |
const maxMoney = ns.getServerMaxMoney(target) | |
// Calculate how much we can actually steal per thread | |
var percentPerThread = ns.formulas.hacking.hackPercent(server, player); | |
// Initialize thread counts to one | |
var numHackThreads = 1; | |
var numGrowThreads = 1; | |
var numFirstWeakenThreads = 1; | |
var numSecondWeakenThreads = 1; | |
// Calculate the max whole number of threads we can use | |
const maxThreads = Math.floor((serverRam - managerRam) / growRam); | |
// Initialize required ram value | |
var requiredRam = 0; | |
// Calculate how much we could steal, increasing the value each time until we hit 85% of the free RAM on the server | |
for (var percentToSteal = 0.01; requiredRam < (serverRam - managerRam) * 0.85; percentToSteal += 0.01) { | |
// Calculate how many threads we need to steal x% of the funds of the server | |
var numHackThreads = Math.floor(percentToSteal / percentPerThread); | |
// Set number of hack threads to 1 if it is 0 | |
if (numHackThreads == 0) numHackThreads = 1; | |
// Analyze the hack impact on security and gather the correct number of threads to weaken it | |
var hackImpact = ns.hackAnalyzeSecurity(numHackThreads, target); | |
var numFirstWeakenThreads = Math.ceil(hackImpact / 0.05); | |
// Set number of weaken threads to 1 if it is 0 | |
if (numFirstWeakenThreads == 0) numFirstWeakenThreads = 1; | |
var moneyToSteal = (percentPerThread * maxMoney) * numHackThreads; | |
// Calculate the growth threads required to grow the funds back to max | |
server.moneyAvailable = server.moneyAvailable - moneyToSteal; | |
var numGrowThreads = ns.formulas.hacking.growThreads(server, player, maxMoney); | |
// Set the num of threads for growth 1 if its 0 | |
if (numGrowThreads == 0) numGrowThreads = 1; | |
// Analyze the hack impact on security and gather the correct number of threads to weaken it | |
var growImpact = ns.growthAnalyzeSecurity(numGrowThreads, target); | |
var numSecondWeakenThreads = Math.ceil(growImpact / 0.05); | |
// Set number of weaken threads to 1 if it is 0 | |
if (numSecondWeakenThreads == 0) numSecondWeakenThreads = 1; | |
// Calcluate required ram. If it hits 80% of the free ram, the for loop will break, resulting in our thread counts | |
requiredRam = (numHackThreads * hackRam) + (numGrowThreads * growRam) + ((numFirstWeakenThreads + numSecondWeakenThreads) * weakenRam); | |
await ns.sleep(5); | |
} | |
return { | |
hackThreads: numHackThreads, | |
growThreads: numGrowThreads, | |
firstWeakenThreads: numFirstWeakenThreads, | |
secondWeakenThreads: numSecondWeakenThreads | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment