import { EXPLOITS, DARKWEB_EXPLOITS } from "./constants.js"; /** * remove write log ✓ * loop * get all servers * nuke if possible * send scripts hack, grow weaken * backdoor factions * buy grow servers * start helpers if not running include home //remove from hacknet * grow if needed * weaken if needed * hack if no grow or weaken * do simple hack * check if money available * check threads * run hack * run grow to recover * run weaken if security too high * buy hack tools */ /** @param {import(".").NS } ns */ export async function main(ns) { ns.disableLog('ALL'); const doc = eval('document'); function terminalCommand(command) { const terminalInput = doc.getElementById("terminal-input"); if (terminalInput != null && terminalInput != undefined) { const handler = Object.keys(terminalInput)[1]; terminalInput.value = command; terminalInput[handler].onChange({ target: terminalInput }); terminalInput[handler].onKeyDown({ key: 'Enter', preventDefault: () => null }); } } function maxPortsToHack() { let maxPorts = 0; EXPLOITS.forEach(exploit => { if (ns.fileExists(exploit.name)) ++maxPorts; }); // ns.tryWritePort(2, `Max ports for hacking ${maxPorts}`); return maxPorts; } function analyzeServer(server) { let requiredHacking = ns.getServerRequiredHackingLevel(server); let requiredPorts = ns.getServerNumPortsRequired(server); let currentHacking = ns.getHackingLevel(); return { name: server, rootAccess: ns.hasRootAccess(server), requiredHacking: requiredHacking, requiredPorts: requiredPorts, nukeAvailable: (currentHacking >= requiredHacking && maxPortsToHack() >= requiredPorts), currentMoney: ns.getServerMoneyAvailable(server), maxMoney: ns.getServerMaxMoney(server), currentSecurity: ns.getServerSecurityLevel(server), minSecurity: ns.getServerMinSecurityLevel(server), RAM: ns.getServerMaxRam(server), }; } function scanServer(currentServer, previousServer = currentServer, network = []) { let availableServers = ns.scan(currentServer); network.push(analyzeServer(currentServer)); for (let i = 0; i < availableServers.length; ++i) { let nextServer = availableServers[i]; if (nextServer != currentServer && nextServer != previousServer) { scanServer(nextServer, currentServer, network); } } return network; } // if new game, buy TOR router, start hack course if (ns.getHackingLevel() == 1) { let terminal; let city; let travel; for (const elem of doc.querySelectorAll('div.MuiDrawer-root.MuiDrawer-docked p')) { if (elem.textContent == 'Terminal') { terminal = elem; } if (elem.textContent == 'City') { city = elem; } if (elem.textContent == 'Travel') { travel = elem; } } city.click(); await ns.sleep(200); for (const alphaEnt of doc.querySelectorAll('div#root p')) { if (alphaEnt.textContent == ' o-----+---x----o 4 T [alpha ent.] o-------o /') { alphaEnt.querySelector('span').click(); await ns.sleep(200); break; } } for (const TOR of doc.querySelectorAll('div#root button')) { if (TOR.textContent == 'Purchase TOR router - $200.000k') { TOR.click(); await ns.sleep(200); break; } } travel.click(); await ns.sleep(200); for (const aevum of doc.querySelectorAll('div#root span')) { if (aevum.textContent == 'A') { aevum.click(); await ns.sleep(200); break; } } for (const travelConfirm of doc.querySelectorAll('div[role="presentation"] p')) { if (travelConfirm.textContent == 'Travel') { travelConfirm.click(); await ns.sleep(200); break; } } try { doc.querySelector('div[role="presentation"] button').click(); } catch (error) { } city.click(); await ns.sleep(200); for (const uni of doc.querySelectorAll('div#root span')) { if (uni.textContent == 'U') { uni.click(); await ns.sleep(200); break; } } for (const course of doc.querySelectorAll('div#root button')) { if (course.textContent == 'Take Algorithms course ($-1.280k / sec)' || course.textContent == 'Take Algorithms course($ - 960.000 / sec)') { course.click(); await ns.sleep(200); break; } } for (const closeCourse of doc.querySelectorAll('div#root button')) { if (closeCourse.textContent == 'Do something else simultaneously') { closeCourse.click(); await ns.sleep(200); break; } } } let buyCounter = 120; let prevMaxMoneyHost = ''; ns.write('autoHack.txt', '', 'w'); while (true) { // Buy all available exploits // if (buyCounter == 120) { // terminalCommand("buyAll"); // buyCounter = 0; // } // ++buyCounter; // Buy more servers let serverRAM = 8; if (ns.getPurchasedServerCost(serverRAM) < ns.getServerMoneyAvailable('home') * 0.2) { ns.purchaseServer('home', serverRAM); } // Upgrade RAM for (const server of ns.getPurchasedServers()) { const serverStats = analyzeServer(server); if (serverStats.RAM < 128) { if (ns.getPurchasedServerUpgradeCost(serverStats.name, serverStats.RAM * 2) < ns.getServerMoneyAvailable('home') * 0.2) { ns.upgradePurchasedServer(serverStats.name, serverStats.RAM * 2); } } } // Analyze all available hosts let network = scanServer('home'); // NUKE if possible for (let host of network) { ns.scp(['grow.js', 'weaken.js', 'hack.js'], host.name, 'home'); if (!host.rootAccess && host.nukeAvailable) { for (const exploit of EXPLOITS) { if (ns.fileExists(exploit.name)) eval(`${exploit.function}('${host.name}')`); } ns.nuke(host.name); host = analyzeServer(host.name); } } // Find host with most money let maxMoneyHost = network[1]; for (const host of network) { if (host.name != 'home' && host.rootAccess) { if (host.maxMoney > maxMoneyHost.maxMoney && host.currentMoney > 0 && host.requiredHacking < ns.getHackingLevel() / 3) { maxMoneyHost = host; } } } // clear log file if max money host changed if (maxMoneyHost.name != prevMaxMoneyHost) { ns.write('autoHackMax.txt', '', 'w'); prevMaxMoneyHost = maxMoneyHost.name; } // TODO: convert to global RAM usage, steal 50%, regrow, weaken // Hack servers for (let i = 1; i < network.length; i++) { const host = network[i]; if (!ns.scriptRunning('grow.js', host.name) && !ns.scriptRunning('weaken.js', host.name) && !ns.scriptRunning('hack.js', host.name) && host.rootAccess && host.RAM > 0) { if (host.name != 'home' && host.currentMoney > 0) { const freeRAM = ns.getServerMaxRam(host.name) - ns.getServerUsedRam(host.name); const hackRAM = ns.getScriptRam('hack.js', host.name); const growRAM = ns.getScriptRam('grow.js', host.name); const weakenRAM = ns.getScriptRam('weaken.js', host.name); const hackTime = ns.getHackTime(host.name); const growTime = ns.getGrowTime(host.name); const weakenTime = ns.getWeakenTime(host.name); const hackWait = hackTime <= growTime ? growTime - hackTime + 50 : 0; const hackAnalyze = ns.hackAnalyze(host.name); const growThreadsNeededPerHack = Math.ceil(ns.growthAnalyze(host.name, 1 + hackAnalyze)); let hackThreads = Math.floor(freeRAM / (hackRAM + growRAM * growThreadsNeededPerHack)); hackThreads = hackThreads == 0 ? 1 : hackThreads; const growThreads = Math.floor((freeRAM - hackThreads * hackRAM) / growRAM); const growLoops = Math.ceil(growThreadsNeededPerHack / growThreads); const weakenThreads = Math.floor(freeRAM / weakenRAM); const log = `host:${host.name} target:${host.name} | security:${(host.currentSecurity / host.minSecurity * 100).toFixed(0)}% | money:${(host.currentMoney / host.maxMoney * 100).toFixed(0)}% | hThreads:${hackThreads} hTime:${((growTime * (growLoops - 1) + hackWait + hackTime) / 60000).toFixed(2)}m | gThreads:${growThreads} gLoops:${growLoops} gTime:${(growTime * growLoops / 60000).toFixed(2)}m`; ns.print(log); ns.write('autoHack.txt', log + '\n', 'a'); if (host.currentSecurity / host.minSecurity > 2) { if (weakenThreads > 0) { ns.exec('weaken.js', host.name, weakenThreads, host.name); } } else { ns.exec('grow.js', host.name, growThreads, host.name, growLoops); ns.exec('hack.js', host.name, hackThreads, host.name, growTime * (growLoops - 1) + hackWait); } } else { const freeRAM = ns.getServerMaxRam(host.name) - ns.getServerUsedRam(host.name) - (host.name == 'home' ? 1.8 : 0); const hackRAM = ns.getScriptRam('hack.js', host.name); const growRAM = ns.getScriptRam('grow.js', host.name); const weakenRAM = ns.getScriptRam('weaken.js', host.name); const hackTime = ns.getHackTime(maxMoneyHost.name); const growTime = ns.getGrowTime(maxMoneyHost.name); const weakenTime = ns.getWeakenTime(maxMoneyHost.name); const hackWait = hackTime <= growTime ? growTime - hackTime + 50 : 0; const hackAnalyze = ns.hackAnalyze(maxMoneyHost.name); const growThreadsNeededPerHack = Math.ceil(ns.growthAnalyze(maxMoneyHost.name, 1 + hackAnalyze)); let hackThreads = Math.floor(freeRAM / (hackRAM + growRAM * growThreadsNeededPerHack)); hackThreads = hackThreads == 0 ? 1 : hackThreads; const growThreads = Math.floor((freeRAM - hackThreads * hackRAM) / growRAM); // ns.tprint(`Math.floor((${freeRAM} - ${hackThreads} * ${hackRAM}) / ${growRAM}) = ${growThreads}`); const growLoops = Math.ceil(growThreadsNeededPerHack / growThreads); const weakenThreads = Math.floor(freeRAM / weakenRAM); const log = `host:${host.name} target:${maxMoneyHost.name} | security:${(maxMoneyHost.currentSecurity / maxMoneyHost.minSecurity * 100).toFixed(0)}% | money:${(maxMoneyHost.currentMoney / maxMoneyHost.maxMoney * 100).toFixed(0)}% | hThreads:${hackThreads} hTime:${((growTime * (growLoops - 1) + hackWait + hackTime) / 60000).toFixed(2)}m | gThreads:${growThreads} gLoops:${growLoops} gTime:${(growTime * growLoops / 60000).toFixed(2)}m`; // | wThreads:${weakenThreads} wTime:${(weakenTime / 60000).toFixed(2)}m`; ns.print(log); ns.write('autoHackMax.txt', log + '\n', 'a'); // ns.tprint(`${maxMoneyHost.currentSecurity} / ${maxMoneyHost.minSecurity} > 5 = ${maxMoneyHost.currentSecurity / maxMoneyHost.minSecurity > 5}`) if (maxMoneyHost.currentSecurity / maxMoneyHost.minSecurity > 5) { if (weakenThreads > 0) { ns.exec('weaken.js', host.name, weakenThreads, maxMoneyHost.name); } } else { if (maxMoneyHost.currentMoney / maxMoneyHost.maxMoney < 0.2) { ns.exec('grow.js', host.name, Math.floor(freeRAM / growRAM), maxMoneyHost.name); } else { ns.exec('grow.js', host.name, growThreads, maxMoneyHost.name, growLoops); ns.exec('hack.js', host.name, hackThreads, maxMoneyHost.name, growTime * (growLoops - 1) + hackWait); } } } } } // Sleep before next loop await ns.sleep(1000); } }