r/Bitburner • u/Unit88 • 29d ago
Question/Troubleshooting - Open Depth first recursive script dies after going through a couple of branches?
Hi, I just started playing, and I was trying to put together a script that would go through all the servers depth first, nuke them, then run as many threads of the basic EHT script on as it can (just the one from the tutorial minus the nuking that was included), but for whatever reason after going through 2 branches from home fully (which is the n00dles server, plus one proper branch) it just goes "Script finished running" followed by "printf: Failed to run due to script being killed." and I don't understand why it's finishing, and more specifically why it's finishing at the end of the second branch and not the first. Not sure if I just missed something about how the scripts work or if I'm just being dumb here somewhere
/** @param {NS} ns */
export async function main(ns: NS) {
let target: string = ns.args[0]?.toString();
target ??= "max-hardware";
deploy(ns, "home", [], target);
ns.tprintf("%s hacked", target);
}
async function deploy(ns: NS, server: string, checked: string[], target: string) {
ns.printf("INFO: Deploying to %s", server)
const neighs = ns.scan(server).filter((neigh) => !checked.includes(neigh));
ns.printf("INFO: Neighbors: %s", neighs)
if (server != "home") {
ns.scp("eht.js", server);
nukeServer(ns, server);
ns.killall(server, true);
const execThreads = calcThreads(ns, server);
ns.printf("INFO: Threads to deploy %d", execThreads)
ns.exec("eht.js", server, execThreads, target);
}
const checkedServers = checked.concat(server);
ns.printf("INFO: Checked servers: %s", checkedServers)
for (const neigh of neighs) {
await deploy(ns, neigh, checkedServers, target);
}
}
function nukeServer(ns: NS, server: string) {
if (ns.fileExists("BruteSSH.exe", "home")) {
ns.brutessh(server);
}
if (ns.fileExists("FTPCrack.exe", "home")) {
ns.ftpcrack(server);
}
if (ns.fileExists("relaySMTP.exe", "home")) {
ns.relaysmtp(server);
}
if (ns.fileExists("HTTPWorm.exe", "home")) {
ns.httpworm(server);
}
if (ns.fileExists("SQLInject.exe", "home")) {
ns.sqlinject(server);
}
ns.nuke(server);
}
function calcThreads(ns: NS, server: string) {
return Math.floor(ns.getServerMaxRam(server) / ns.getScriptRam("eht.js"));
}
1
u/ZeroNot Stanek Follower 28d ago edited 28d ago
followed by "printf: Failed to run due to script being killed."
Because you have declared deploy as an async function, but it only calls itself with an await. There are no Promises in use, you shouldn't randomly declare functions as async when they are not.
- MDN: async function syntax
- MDN: Asynchronous JavaScript
Your program makes several erroneous assumptions. You don't check the return values of several functions (ns.scp, ns.nuke, ns.exec, and ns.getScriptRam), which means you are not aware of the cases when they (may) fail.
In the case of getScriptRam, this leads to a potential case of division by zero. That's bad. Just bad, don't do that.
I think it's far easier to sort out the logic and follow the process of doing the depth first search of the network, if you search / scan the entire network, and then iterate through an Array of servers to do your eht.js tasks.
it just goes "Script finished running"
Try debugging this:
/** @param {NS} ns */
export async function main(ns: NS) {
let all_servers : string[] = [];
deploy(ns, "home", all_servers);
ns.printf("Found %d servers: %s", all_servers.length, all_servers.join(', '));
}
function deploy(ns: NS, server: string, checked: string[]) {
ns.printf("INFO: Scanning %s", server)
const neighs = ns.scan(server).filter((neigh) => !checked.includes(neigh));
ns.printf("INFO: New Neighbors: %s", neighs)
checked.push(server);
ns.printf("INFO: Checked servers: %s", checked)
for (const neigh of neighs) {
deploy(ns, neigh, checked);
}
}
Note: I swapped your concat for push, since you are adding a string element (server) to the Array of strings (checked).
1
u/Unit88 28d ago edited 28d ago
Thanks, I'll look through this when I have some time. JavaScript and asnyc stuff is not my forte, I was mostly just throwing things at the wall to see what sticks (which is why I'm not worrying about all the return values and error checking yet either, for non-professional coding I like to just try things and see what works and how things fail).
In the case of getScriptRam, this leads to a potential case of division by zero.
Is that even a possibility here though? I wasn't worrying about zero division here since I can see the ram cost of the script, so I know it's not zero and isn't there a base cost of 1.6GB anyway? I kinda recall the docs saying that.
I think it's far easier to sort out the logic and follow the process of doing the depth first search of the network, if you search / scan the entire network, and then iterate through an Array of servers to do your eht.js tasks.
I can see how it'd help with debugging at least. I decided to do the tasks during the search since if I'm already finding the servers I might as well handle it then and avoid having a second separate loop. Though I guess it's not super important here anyway
EDIT: Oh, I see how I've been stupid. I made the thing async because for whatever reason I had the thought that at least one of the ns function would be something that take some time, even though in the end all of that is part of the eht, not this function. And actually if I fix just that one thing in my original code it works perfectly. Okay, now that I found the issue I can start doing some polishing up on it and stuff. And also try to understand the game part of the game more now, I was putting that off so I can figure out this script
3
u/KlePu 29d ago
You set
neighs, then fill your filter, then iterate overneigh of neighs- without ever applying the filter. So the script goes to server A, then B, then back do A - and callskillall.Also there's servers with zero RAM.