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("./index.js").NS } ns */ export async function main(ns) { ns.disableLog('ALL'); const doc = eval('document'); const serverCostThreshold = 0.2; const serverMaxRAM = 128; const nodeCostThreshold = 0.2; const upgradeCostThreshold = 0.1; const upgradeCount = 1; const nodeCap = 24; const levelCap = 200; const ramCap = 64; const coreCap = 16; let factionProgress; if (ns.fileExists('@factionProgress.script')) { factionProgress = JSON.parse(ns.read('@factionProgress.script')); } else { // factionProgress = updateFactionProgress(); } ns.singularity.getAugmentationsFromFaction(faction); const currentMoney = function () { return ns.getServerMoneyAvailable("home"); }; const currentHacking = function () { return ns.getHackingLevel(); }; function updateFactionProgress() { ns.write('@factionProgress.script', JSON.stringify(factionProgress), 'w'); } 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); 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; } function numberToUnits(number) { let numberString = Math.floor(number); if (Math.abs(number) / 1000 >= 1) { numberString = Math.floor(number / 1000) + 'k'; } if (Math.abs(number) / 1000000 >= 1) { numberString = Math.floor(number / 1000000) + 'm'; } if (Math.abs(number) / 1000000000 >= 1) { numberString = Math.floor(number / 1000000000) + 'b'; } if (Math.abs(number) / 1000000000000 >= 1) { numberString = Math.floor(number / 1000000000000) + 't'; } return numberString; } // if new game, buy TOR router, start hack course if (currentHacking() == 1) { } let prevMaxMoneyHost = ''; ns.write('$autoHack.js', '', 'w'); let lastMoney = ns.getServerMoneyAvailable('home'); let lastTime = Date.now(); const firstMoney = ns.getServerMoneyAvailable('home'); const firstTime = Date.now(); while (true) { // // Money stats // const moneyDiff = currentMoney() - lastMoney; const currentTime = Date.now(); const timeDiff = (currentTime - lastTime) / 1000; const moneyPerSecond = moneyDiff / timeDiff; const moneyDiffLife = currentMoney() - firstMoney; const timeDiffLife = (currentTime - firstTime) / 1000; const moneyPerSecondLife = moneyDiffLife / timeDiffLife; const moneyString = `${numberToUnits(Math.floor(moneyPerSecond))} | ${numberToUnits(Math.floor(moneyPerSecondLife))} $/s`; ns.print(`${lastMoney} ${currentMoney()} ${moneyDiff} ${numberToUnits(Math.floor(moneyPerSecondLife))}\n ${currentTime} ${currentTime} ${timeDiff}`); doc.querySelector("#root > div.react-draggable > div.drag.MuiBox-root > div > p").innerText = moneyString; ns.write('$moneyStats.js', moneyString + '\n', 'a'); lastMoney = currentMoney(); lastTime = currentTime; // // Factions // // // Programs // if (ns.singularity.purchaseTor()) { ns.singularity.purchaseProgram('BruteSSH.exe'); ns.singularity.purchaseProgram('FTPCrack.exe'); ns.singularity.purchaseProgram('relaySMTP.exe'); ns.singularity.purchaseProgram('HTTPWorm.exe'); ns.singularity.purchaseProgram('SQLInject.exe'); } // // Hacknet // let nodeCount = ns.hacknet.numNodes(); if (nodeCount < nodeCap && ns.hacknet.getPurchaseNodeCost() < nodeCostThreshold * currentMoney()) { ns.hacknet.purchaseNode(); nodeCount = ns.hacknet.numNodes(); } for (let index = 0; index < nodeCount; ++index) { let nodeStats = ns.hacknet.getNodeStats(index); if (nodeStats.level < levelCap && ns.hacknet.getLevelUpgradeCost(index, upgradeCount) < upgradeCostThreshold * currentMoney()) { ns.hacknet.upgradeLevel(index, upgradeCount); } if (nodeStats.ram < ramCap && ns.hacknet.getRamUpgradeCost(index, upgradeCount) < upgradeCostThreshold * currentMoney()) { ns.hacknet.upgradeRam(index, upgradeCount); } if (nodeStats.cores < coreCap && ns.hacknet.getCoreUpgradeCost(index, upgradeCount) < upgradeCostThreshold * currentMoney()) { ns.hacknet.upgradeCore(index, upgradeCount); } } // // Buy more servers // let serverRAM = 8; if (ns.getPurchasedServerCost(serverRAM) < ns.getServerMoneyAvailable('home') * serverCostThreshold) { ns.purchaseServer('home', serverRAM); } // // Upgrade RAM // for (const server of ns.getPurchasedServers()) { const serverStats = analyzeServer(server); if (serverStats.RAM < serverMaxRAM) { if (ns.getPurchasedServerUpgradeCost(serverStats.name, serverStats.RAM * 2) < ns.getServerMoneyAvailable('home') * upgradeCostThreshold) { ns.upgradePurchasedServer(serverStats.name, serverStats.RAM * 2); } } } // // Analyze all available hosts // let network = scanServer('home'); network.sort((a, b) => b.maxMoney - a.maxMoney); // // 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); } } // // Backdoor factions // // TODO: convert to global RAM usage, steal 50%, regrow, weaken // // Hack servers // for (let i = 0; i < network.length; i++) { const moneyHost = network[i]; if (moneyHost.maxMoney > 0) { let securityDecrease = 0; let weakenThreads = 0; while (moneyHost.currentSecurity - securityDecrease > moneyHost.minSecurity) { securityDecrease = ns.weakenAnalyze(++weakenThreads); } ns.growthAnalyze(moneyHost.name, 2); ns.hackAnalyze(moneyHost.name); for (const host of network) { if (!ns.scriptRunning('grow.js', host.name) && !ns.scriptRunning('weaken.js', host.name) && !ns.scriptRunning('hack.js', host.name) && host.rootAccess && host.RAM > 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 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.js', 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.js', 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); } }