Skip to content

Instantly share code, notes, and snippets.

@KrunoSaho
Last active June 30, 2023 04:16
Show Gist options
  • Save KrunoSaho/c88d10c662c772bacb3010c296bf1004 to your computer and use it in GitHub Desktop.
Save KrunoSaho/c88d10c662c772bacb3010c296bf1004 to your computer and use it in GitHub Desktop.
Bitburner batcher
import { NS } from "../NetscriptDefinitions";
import { getThreadCount, getAllServers, breakServers, ColorsForPrint } from "./Util";
type SubscriptPaths = { Path: string; Cost: number };
type ScriptInformation = { Hack: SubscriptPaths; Grow: SubscriptPaths; Weaken: SubscriptPaths };
type Operations = "hack" | "grow" | "weaken";
type Operation = (
operation: Operations,
srcServer: string,
targetServer: string,
threads: number,
sleepTime: number
) => void;
enum WorkerTypes {
AnyThreads,
HighThreads,
}
enum ScriptTypes {
Hack = "hacks/SimpleHack.js",
Grow = "hacks/SimpleGrow.js",
Weaken = "hacks/SimpleWeaken.js",
}
export async function main(ns: NS) {
ns.disableLog("ALL");
// Log
ns.tail();
ns.resizeTail(350, 700);
ns.moveTail(2200, 600);
ns.clearLog();
const scriptData = {
Hack: {
Path: "hacks/SimpleHack.js",
Cost: 1.7,
} as SubscriptPaths,
Grow: {
Path: "hacks/SimpleGrow.js",
Cost: 1.75,
} as SubscriptPaths,
Weaken: {
Path: "hacks/SimpleWeaken.js",
Cost: 1.75,
} as SubscriptPaths,
} as ScriptInformation;
const scripts = getScriptRunner(ns, scriptData);
while (true) {
const [myNodes, otherNodes] = prepare(ns);
await mastermindTheWork(ns, scripts, myNodes, otherNodes);
await ns.sleep(20);
}
}
///////////////////////////////////////////
// The Workhorse
///////////////////////////////////////////
async function mastermindTheWork(
ns: NS,
script: Operation,
myNodes: string[],
targetNodes: string[]
) {
const doOp = (operation: Operations, worker: string, targetServer: string, time: number) => {
let maxThreads = getThreadCount(ns, worker, ScriptTypes.Grow, worker);
script(operation, worker, targetServer, maxThreads, time);
};
const servers = targetNodes.map(ns.getServer).sort((a, b) => {
return (b.moneyMax as number) - (a.moneyMax as number);
});
// choose most profitable server
const server = servers[0];
const targetServer = server.hostname;
for (const worker of myNodes) {
// I made this change now after leaving this script going for 7 hours of disappointment
// const server = servers[Math.floor(Math.random() * servers.length)];
// const targetServer = server.hostname;
if (!ns.hasRootAccess(targetServer)) continue;
const [weakenTime, growTime, hackTime] = [
Math.ceil(ns.formulas.hacking.weakenTime(server, ns.getPlayer())),
Math.ceil(ns.formulas.hacking.growTime(server, ns.getPlayer())),
Math.ceil(ns.formulas.hacking.hackTime(server, ns.getPlayer())),
];
doOp("hack", worker, targetServer, 0);
doOp("weaken", worker, targetServer, hackTime);
doOp("grow", worker, targetServer, weakenTime);
doOp("weaken", worker, targetServer, growTime);
}
}
///////////////////////////////////////////
// Prep. Work
///////////////////////////////////////////
function prepare(ns: NS) {
const myServers = ns.getPurchasedServers();
copyHackFilesToServers(ns, myServers);
// myServers.push("home");
const baseCostScript = 1.75; // TODO: Make this dynamic
const allServers = getAllServers(ns.scan, "home", [])
.filter((s) => !myServers.includes(s) && s != "home")
.filter((s) => ns.getServerSecurityLevel(s) <= 100)
.filter((s) => Math.floor(ns.getServerMaxRam(s)) >= baseCostScript)
.filter((s) => ns.getServerRequiredHackingLevel(s) <= ns.getHackingLevel())
.filter((s) => ns.getServerMaxMoney(s) > 0)
.sort((_) => Math.random() - Math.random());
// Break security on all servers
breakServers(ns, "home", allServers);
// Newly broken servers can be added here
const backDooredServers = allServers.filter((s) => ns.hasRootAccess(s));
copyHackFilesToServers(ns, backDooredServers);
myServers.push(...backDooredServers);
myServers.sort((a, b) => Math.random() - Math.random());
// The workhorse
return [myServers, allServers];
}
function copyHackFilesToServers(ns: NS, backDooredServers: string[]) {
const files = ["hacks/SimpleHack.js", "hacks/SimpleGrow.js", "hacks/SimpleWeaken.js"];
for (const server of backDooredServers) {
if (!ns.scp(files, server, "home")) {
ns.print(`ERROR: copyHackFilesToServers => Failed to copy files to ${server}`);
}
}
}
function getScriptRunner(ns: NS, scriptData: ScriptInformation) {
const basicFn = (scriptPath: string) => {
return (node: string, threads: number, target: string, sleepTime: number) => {
if (threads === 0) return;
ns.exec(scriptPath, node, threads, target, sleepTime);
};
};
const [weaken, grow, hack] = [
basicFn(scriptData.Weaken.Path),
basicFn(scriptData.Grow.Path),
basicFn(scriptData.Hack.Path),
];
return (
operation: Operations,
myServer: string,
targetServer: string,
threads: number,
sleepTime: number
) => {
const opGrow = operation === "grow";
const opHack = operation === "hack";
const op = opGrow ? grow : opHack ? hack : weaken;
if (threads > 0) {
let colour = ColorsForPrint.Cyan;
if (opGrow) {
colour = ColorsForPrint.Yellow;
}
if (opHack) {
colour = ColorsForPrint.Red;
}
ns.print(
`${colour}${operation}${ColorsForPrint.Default} on ${
ColorsForPrint.Yellow
}${myServer}${ColorsForPrint.Default} -> ${ColorsForPrint.Yellow}${targetServer}${
ColorsForPrint.Default
} with ${ColorsForPrint.Cyan}${threads}${ColorsForPrint.Default} threads\ntime: ${
ColorsForPrint.Quest
}${Math.floor(sleepTime / (1000 * 60))}${ColorsForPrint.Default} minutes.`
);
op(myServer, threads, targetServer, sleepTime);
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment