diff --git a/local/path/home/Backdoor.js b/local/path/home/Backdoor.js deleted file mode 100644 index 77ff641..0000000 --- a/local/path/home/Backdoor.js +++ /dev/null @@ -1,97 +0,0 @@ -/** @param {NS} ns */ -export async function main(ns, allServers) { - ns.tail(); - await scanRecursiveWrapper(ns); - let currentHackingLevel = ns.getHackingLevel(); - let currentArray = []; - let currentHop = ""; - let serverRoutes = JSON.parse(ns.read("ServerRouteList.txt")); - let allPaths = getPaths(serverRoutes); - let checkAll = ns.args[0]; - for (const entry of allPaths) { - for (const name of entry) { - if (ns.singularity.connect(name) === false) { - ns.tprint("Error when trying to connect to: " + currentHop); - return - } - - if (ns.getServer(name).hostname === "CSEC" || ns.getServer(name).hostname === "avmnite-02h" || ns.getServer(name).hostname === "I.I.I.I" || ns.getServer(name).hostname === "run4theh111z" || ns.getServer(name).hostname === "The-Cave" || checkAll === true ) { - if (!ns.getServer(name).backdoorInstalled) { - if (ns.getServerRequiredHackingLevel(name) < currentHackingLevel && ns.hasRootAccess(name) === true) { - ns.print("Trying to backdoor " + name) - await ns.singularity.installBackdoor(name); - ns.print("Success on " + name) - } - } else { continue } - } - } - } - ns.singularity.connect("home"); -} - -function getPaths(obj, path = []) { - const paths = []; - for (const key in obj) { - const newPath = [...path, key]; - paths.push(newPath); - if (typeof obj[key] === 'object' && obj[key] !== null) { - paths.push(...getPaths(obj[key], newPath)); - } - } - return paths; -} - -/** @param {NS} ns */ -async function scanRecursiveWrapper(ns) { - ns.rm("ServerRouteList.txt"); - const home = "home"; - let serverRouteList = { home: {} }; - let knownServers = []; - let unscanned = []; - unscanned.push(home); - knownServers.push(home); - while (unscanned.length > 0) { - let currentServer = unscanned.pop(); - let currentChildren = ns.scan(currentServer).filter(element => !knownServers.includes(element)); - knownServers = knownServers.concat(currentChildren); - let keyPath = findKeyPath(serverRouteList, currentServer); - let childrenObject = currentChildren.reduce((a, v) => ({ ...a, [v]: {} }), {}); - writeValueToPath(serverRouteList, keyPath, childrenObject); - for (let i = 0; i < currentChildren.length; i++) { - let child = currentChildren[i]; - unscanned.push(child); - } - } - ns.write("ServerRouteList.txt", JSON.stringify(serverRouteList), "w"); -} - -function findKeyPath(json, key) { - if (typeof json !== 'object' || json === null) { - return null; - } - if (key in json) { - return key; - } - for (const property in json) { - if (json.hasOwnProperty(property)) { - const path = findKeyPath(json[property], key); - if (path !== null) { - return property + '*' + path; - } - } - } - return null; -} - -function writeValueToPath(json, path, value) { - const parts = path.split('*'); - let currentObject = json; - for (let i = 0; i < parts.length - 1; i++) { - const part = parts[i]; - if (currentObject[part] === undefined) { - currentObject[part] = {}; - } - currentObject = currentObject[part]; - } - currentObject[parts[parts.length - 1]] = value; -} diff --git a/local/path/home/CorpControl.js b/local/path/home/CorpControl.js deleted file mode 100644 index 4ed2131..0000000 --- a/local/path/home/CorpControl.js +++ /dev/null @@ -1,14 +0,0 @@ -/** @param {NS} ns */ -export async function main(ns) { - let cities = ["Sector-12", "Aevum", "Volhaven", "Chongqing", "New Tokyo", "Ishima"]; - let corpName = "AgraNeo"; - //ns.tprint(ns.corporation.getConstants()) - //ns.corporation.getMaterial(); - //ns.corporation.buyMaterial(); - for (let city of cities) { - await ns.run("/corp/Smart.js",1,corpName,city); - await ns.tprint(ns.run("/corp/UpgradeOffice.js",1,corpName,city)); - await ns.sleep(1000) - } - -} \ No newline at end of file diff --git a/local/path/home/CrackAndRootAll.js b/local/path/home/CrackAndRootAll.js deleted file mode 100644 index 719803d..0000000 --- a/local/path/home/CrackAndRootAll.js +++ /dev/null @@ -1,8 +0,0 @@ - -import { getCracks, scanServerList, findBestTarget, crackingAndRooting, copyAndRunScript } from "/RamsesUtils.js"; -/** @param {NS} ns */ -export async function main(ns) { - let cracks = {}; - cracks = getCracks(ns); - crackingAndRooting(ns, cracks, "", false); -} \ No newline at end of file diff --git a/local/path/home/EveryServerRun.js b/local/path/home/EveryServerRun.js new file mode 100644 index 0000000..143ab09 --- /dev/null +++ b/local/path/home/EveryServerRun.js @@ -0,0 +1,88 @@ +import { getGrowThreads } from "myLibrary.js"; + +/** @param {NS} ns */ +export async function main(ns) { + //ns.tail(); + const sOverrideTarget = ns.args[0]; // run on this target instead of best + let serverList = JSON.parse(ns.read("serverList.txt")); + let bestTarget = JSON.parse(ns.read("bestTarget.txt")); + let sTarget; + + if (sOverrideTarget !== undefined) { + sTarget = sOverrideTarget; + } + else { + sTarget = bestTarget.serverName; + } + + let sScript = "batch.js"; + const sShareScript = "factionboost.js"; + const sWeakenScript = "RMweaken.js"; + const sGrowScript = "RMgrow.js"; + const sHackScript = "RMhack.js"; + + const nWeakenThreads = 1; //5 + const nHackThreads = 1; //1 + const nGrowThreads = getGrowThreads(ns, sTarget, nHackThreads); + //ns.tprint("nGrowThreads = " + nGrowThreads); + + const nWeakenScriptRAM = 1.75 * nWeakenThreads; + const nHackScriptRAM = 1.75 * nHackThreads; + const nGrowScriptRAM = 1.7 * nGrowThreads; + //ns.tprint("nGrowScriptRAM = " + nGrowScriptRAM); + + const nFrequency = 50; + let nScriptsRAM; + let nMaxRam; + let nScripts; + + for (const [name, entry] of Object.entries(serverList)) { + //let rootAccess = ns.hasRootAccess(currentServer); + + //ns.tprint(entry.serverName + " sTarget = " + sTarget); + + nMaxRam = ns.getServerMaxRam(entry.serverName); + //ns.tprint(entry.serverName + " nMaxRam = " + nMaxRam); + + //nScriptsRAM = ns.getScriptRam(sScript, "home") + Math.max(nWeakenScriptRAM, nGrowScriptRAM, nHackScriptRAM); + //ns.tprint("nScriptsRAM = " + nScriptsRAM); + if (entry.maxRam >= 64 && serverList[name].rootAccess === true) { + + if (sOverrideTarget !== undefined) { + sTarget = sOverrideTarget; + } + else { + sTarget = bestTarget.serverName; + } + + //ns.tprint("sTarget = " + sTarget); + //ns.tprint("entry.serverName = " + entry.serverName); + + ns.scriptKill(sScript, entry.serverName); + ns.scriptKill(sShareScript, entry.serverName); + ns.scp("myLibrary.js", entry.serverName, "home"); + ns.scp(sScript, entry.serverName, "home"); + ns.scp(sWeakenScript, entry.serverName, "home"); + ns.scp(sGrowScript, entry.serverName, "home"); + ns.scp(sHackScript, entry.serverName, "home"); + ns.exec(sScript, entry.serverName, 1, sTarget, nFrequency, true, false); + await ns.sleep(1); + } + else if (entry.maxRam < 64 && entry.maxRam > 0 && serverList[name].rootAccess === true) { + ns.scriptKill(sScript, entry.serverName); + ns.scriptKill(sShareScript, entry.serverName); + ns.scriptKill(sWeakenScript, entry.serverName); + ns.scriptKill(sGrowScript, entry.serverName); + ns.scriptKill(sHackScript, entry.serverName); + + ns.scp(sShareScript, entry.serverName); + + let nShare = Math.floor(((ns.getServerMaxRam(entry.serverName) - ns.getServerUsedRam(entry.serverName)) / ns.getScriptRam(sShareScript))); + ns.tprint(entry.serverName + " nShare = " + nShare * ns.getScriptRam(sShareScript)); + ns.exec(sShareScript, entry.serverName, nShare); + } + + + } + //ns.exec("serverlister.js", "home", 1); +} diff --git a/local/path/home/FactionBoost.js b/local/path/home/FactionBoost.js deleted file mode 100644 index 9045a44..0000000 --- a/local/path/home/FactionBoost.js +++ /dev/null @@ -1,6 +0,0 @@ -/** @param {NS} ns */ -export async function main(ns) { - while (true) { - await ns.share(); - } -} \ No newline at end of file diff --git a/local/path/home/FactionRAMShare.js b/local/path/home/FactionRAMShare.js deleted file mode 100644 index bb51dcb..0000000 --- a/local/path/home/FactionRAMShare.js +++ /dev/null @@ -1,16 +0,0 @@ -/** @param {NS} ns */ -export async function main(ns) { -let serverList = JSON.parse(ns.read("serverList.txt")); -for (const [name, entry] of Object.entries(serverList)) { - if (entry.rootAccess === true) { - - ns.print("killed threads on: " + name + " " +ns.killall(name, true)); - //move script and run - let maxRam = ns.getServerMaxRam(name); - if (maxRam > 0) { - ns.scp("FactionBoost.js", name, "home"); - let maxProcesses = 1; - maxProcesses = Math.floor(maxRam / 4); - if (name === "home") maxProcesses = maxProcesses - 50; - ns.exec("FactionBoost.js", name, maxProcesses); -}}}} \ No newline at end of file diff --git a/local/path/home/HackingLog.txt b/local/path/home/HackingLog.txt new file mode 100644 index 0000000..5570ebe --- /dev/null +++ b/local/path/home/HackingLog.txt @@ -0,0 +1,929 @@ +39474.13899141901539474.13899141901539474.13899141901539474.13899141901539475.7339705693439474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539475.7339705693439474.13899141901539474.13899141901539474.13899141901539474.13899141901539475.7339705693439474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539475.7339705693439474.13899141901539474.13899141901539474.13899141901539474.13899141901539475.7339705693439474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539475.7339705693439474.13899141901539474.13899141901539474.13899141901539474.13899141901539475.7339705693439474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539475.7339705693439474.13899141901539474.13899141901539474.13899141901539474.13899141901539475.7339705693439474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539475.7339705693439474.13899141901539474.13899141901539474.13899141901539474.13899141901539475.7339705693439474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539475.7339705693439474.13899141901539474.13899141901539474.13899141901539474.13899141901539475.7339705693439474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539475.7339705693439474.13899141901539474.13899141901539474.13899141901539474.13899141901539475.7339705693439474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539475.7339705693439474.13899141901539474.13899141901539474.13899141901539474.13899141901539475.7339705693439474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539475.7339705693439474.13899141901539474.13899141901539474.13899141901539474.13899141901539475.7339705693439474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539475.7339705693439474.13899141901539474.13899141901539474.13899141901539474.13899141901539475.7339705693439475.7339705693439474.13899141901539474.13899141901539474.13899141901539475.7339705693436820.8084699284839474.13899141901539474.13899141901539475.7339705693439474.13899141901539474.13899141901539474.13899141901539474.13899141901538937.5362797892339474.13899141901539474.13899141901539475.7339705693439474.13899141901539474.13899141901539474.13899141901539474.13899141901539471.74652269352439474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539475.7339705693439475.7339705693439474.13899141901539474.13899141901539474.13899141901537371.2852343816939475.7339705693439474.13899141901539474.13899141901539474.13899141901539474.13899141901539475.7339705693439474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.13899141901539474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +36856.42175232096 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +37338.67713462529 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +36820.81372704521 +39474.138991419015 +39474.138991419015 +38941.46976158333 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +38937.53627978923 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +37371.28523438169 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39475.73397056934 +38408.25982314148 +39474.138991419015 +39474.138991419015 +38400.9983274575 +38941.46976158333 +39475.73397056934 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +37338.67713462529 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +37371.28523438169 +39475.73397056934 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +36820.80846992848 +39474.138991419015 +39475.73397056934 +37374.790437726195 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +38407.20555259731 +39475.73397056934 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39471.746522693524 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39475.73397056934 +37338.67713462529 +39474.138991419015 +38937.53627978923 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +38937.53627978923 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +38937.53627978923 +39475.73397056934 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +36869.083861930114 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +38408.25982314148 +39474.138991419015 +39475.73397056934 +39474.138991419015 +37338.67713462529 +39474.138991419015 +39475.73397056934 +38937.53627978923 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +38937.53627978923 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +37371.28523438169 +39475.73397056934 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +36857.81038796931 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +38400.9983274575 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +37328.116700688224 +39474.138991419015 +38407.20555259731 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +36820.80846992848 +39474.138991419015 +39474.138991419015 +37374.790437726195 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +36857.80868272481 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +37381.85788105512 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +37338.67713462529 +39474.138991419015 +38941.46976158333 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +38937.53627978923 +39475.73397056934 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +38937.53627978923 +39475.73397056934 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +38396.93835470901 +39474.138991419015 +39475.73397056934 +39474.138991419015 +37338.67713462529 +39474.138991419015 +39474.138991419015 +38941.46976158333 +39475.73397056934 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +38937.53627978923 +38407.162377987515 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39475.73397056934 +39475.73397056934 +39474.138991419015 +37371.28523438169 +39475.73397056934 +38937.53627978923 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +38400.9983274575 +39475.73397056934 +39475.73397056934 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39471.746522693524 +39475.73397056934 +39474.138991419015 +37328.116700688224 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +37381.85788105512 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +36833.45834451145 +39474.138991419015 +39474.138991419015 +37374.790437726195 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39475.73397056934 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +37374.79216692549 +39475.73397056934 +39475.73397056934 +39474.138991419015 +39475.73397056934 +39475.73397056934 +39474.138991419015 +37338.67713462529 +39474.138991419015 +38937.53627978923 +38937.53627978923 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +37374.79130235312 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +36820.81372704521 +38408.25982314148 +39475.73397056934 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +38941.46976158333 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +38937.53627978923 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +37338.67713462529 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39464.56911651706 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +38937.53627978923 +38407.162377987515 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +37371.28523438169 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +38400.9983274575 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +35392.824515811844 +39472.544012268685 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +37364.22151863585 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +38414.46822204606 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +37338.67713462529 +39474.138991419015 +39474.138991419015 +38937.53627978923 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +37338.67713462529 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +37371.28523438169 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39475.73397056934 +39475.73397056934 +39475.73397056934 +39474.138991419015 +36820.80846992848 +39474.138991419015 +36833.46360343427 +36355.55335347026 +39474.138991419015 +39475.73397056934 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39471.746522693524 +38937.53627978923 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39475.73397056934 +39475.73397056934 +39474.138991419015 +39471.746522693524 +39474.138991419015 +38941.46976158333 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39472.64369846559 +39474.138991419015 +39474.138991419015 +38400.9983274575 +39475.73397056934 +39475.73397056934 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +38407.20555259731 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +38941.71801558968 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39475.73397056934 +37338.67713462529 +39474.138991419015 +39474.138991419015 +36355.55335347026 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +38937.53627978923 +39475.73397056934 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +38937.53627978923 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +36820.80846992848 +39474.138991419015 +39475.73397056934 +39475.73397056934 +39474.138991419015 +39475.73397056934 +39474.138991419015 +38937.53627978923 +38937.53627978923 +39474.138991419015 +38941.46976158333 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +37328.116700688224 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +35861.52213272931 +39472.544012268685 +39474.138991419015 +37371.28523438169 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +36820.81372704521 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39471.746522693524 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +38941.44817427843 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39475.73397056934 +36370.248403330195 +39474.138991419015 +39474.138991419015 +39474.138991419015 +38400.9983274575 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39475.73397056934 +38937.53627978923 +38407.20555259731 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39475.73397056934 +39474.138991419015 +39474.138991419015 +39474.138991419015 +39474.138991419015 +37360.65483616802 +39475.73397056934 +39475.73397056934 +39474.138991419015 +39474.138991419015 diff --git a/local/path/home/Minimum_Path_Sum_in_a_Triangle.js b/local/path/home/Minimum_Path_Sum_in_a_Triangle.js new file mode 100644 index 0000000..78b9bea --- /dev/null +++ b/local/path/home/Minimum_Path_Sum_in_a_Triangle.js @@ -0,0 +1,29 @@ +/** @param {NS} ns */ +export async function main(ns) { + //8,5,1,1,2,6,7,2,5,4 + //const sContractData = ns.codingcontract.getData(sContract, sTarget); + const sContractData = "8,5,1,1,2,6,7,2,5,4"; + /* + 8 + 5,1 + 1,2,6 + 7,2,5,4 + */ + //nArray[0[2]] + const sArray = sContractData.split(','); + ns.tprint(sArray); + let nArray = []; + //Number + for (let i = 0; i < sArray.length; i++) { + nArray[i] = Number(sArray[i]); + } + ns.tprint(nArray); + + let nLayers = []; + for (let l = 0; l < nArray.length; l++) { + + + } + + +} \ No newline at end of file diff --git a/local/path/home/RMbreach.js b/local/path/home/RMbreach.js index bf7395b..5cd5ced 100644 --- a/local/path/home/RMbreach.js +++ b/local/path/home/RMbreach.js @@ -9,37 +9,41 @@ export async function main(ns) { //declare variables const sWeakenScript = "RMweaken.js"; + const sGrowScript = "RMgrow.js"; const sBatch = "RMcontroller.js"; const nCores = oHome.cpuCores; let nSecurity = ns.getServerSecurityLevel(sTarget); const nMinSecurity = ns.getServerMinSecurityLevel(sTarget); + let nMoney = ns.getServerMoneyAvailable(sTarget); + const nMaxMoney = ns.getServerMaxMoney(sTarget); + const nWeakenSTR = ns.weakenAnalyze(1, nCores); - let nThreads = Math.ceil((nSecurity - nMinSecurity) / nWeakenSTR); + let nWeakenThreads = Math.ceil((nSecurity - nMinSecurity) / nWeakenSTR); let nFreeRam = ns.getServerMaxRam("home") - ns.getServerUsedRam("home"); - ns.tail("RMbreach.js", "home", sTarget); + ns.tail(ns.pid, oHome.hostname, sTarget); //ns.resizeTail(815, 395); //ns.moveTail(1925, 0); // crack target - // ns.run(sCrack, 1, sTarget); + //ns.run(sCrack, 1, sTarget); + const nDelay = ns.getWeakenTime(sTarget); + if (nWeakenThreads > 0 && nSecurity > nMinSecurity) { - if (nThreads > 0 && nSecurity > nMinSecurity) { - const nDelay = ns.getWeakenTime(sTarget); ns.tprint("current security is: " + nSecurity); ns.tprint("minimum security is: " + nMinSecurity); - ns.tprint("threads needed for weaken: " + nThreads); - ns.tprint(nThreads + " will reduce Security by " + ns.weakenAnalyze(nThreads, nCores)); + ns.tprint("threads needed for weaken: " + nWeakenThreads); + ns.tprint(nWeakenThreads + " will reduce Security by " + ns.weakenAnalyze(nWeakenThreads, nCores)); let nScriptRAM = ns.getScriptRam(sWeakenScript, "home"); - let nRequiredRAM = nScriptRAM * nThreads; - ns.tprint(nThreads + " of " + sWeakenScript + " requires " + nRequiredRAM + " GB of RAM"); + let nRequiredRAM = nScriptRAM * nWeakenThreads; + ns.tprint(nWeakenThreads + " of " + sWeakenScript + " requires " + nRequiredRAM + " GB of RAM"); ns.tprint("weakening will take " + (nDelay / 1000 / 60) + " minutes"); if (nFreeRam > nRequiredRAM) { - ns.run(sWeakenScript, nThreads, sTarget); + ns.run(sWeakenScript, nWeakenThreads, sTarget); - await ns.sleep(Math.ceil(nDelay)); + //await ns.sleep(Math.ceil(nDelay)); nSecurity = ns.getServerSecurityLevel(sTarget); ns.tprint("Breach complete, security level is now at: " + nSecurity); @@ -47,24 +51,58 @@ export async function main(ns) { } else { ns.print("not enough RAM to run all threads at once, splitting into smaller chunks..."); + + while (nSecurity > nMinSecurity) { - nThreads /= (1+(nRequiredRAM / nFreeRam)); + //nWeakenThreads /= (1+(nRequiredRAM / nFreeRam)); + nMaxThreads = Math.min( ); ns.print(Math.ceil(nRequiredRAM / nFreeRam)); - ns.print(nThreads); - ns.print(nThreads * nScriptRAM); - ns.run(sWeakenScript, Math.ceil(nThreads), sTarget); + ns.print(nWeakenThreads); + ns.print(nWeakenThreads * nScriptRAM); + ns.run(sWeakenScript, Math.ceil(nWeakenThreads), sTarget); await ns.sleep(Math.ceil(nDelay)); nSecurity = ns.getServerSecurityLevel(sTarget); } - } - } + /* + let nGrowMulti = 1; + ns.print("nGrowMulti = " + nGrowMulti); + let nGrowth = ns.growthAnalyze(sTarget, nGrowMulti, nCores); + ns.print("nGrowth = " + nGrowth); + */ + + //ns.growthAnalyzeSecurity(); + + + const startValue = nMoney; // First argument: starting value + const target = nMaxMoney; // Second argument: target value + let result = startValue; // Initialize result with the starting value + let n = 1; + // For loop that continues until the result exceeds or matches the target + for (; result < target; n++) { + result += 1; // Add 1 before multiplication + result *= n; // Multiply by the current step value + } + let nGrowThreadsNeeded = n * ns.growthAnalyze(sTarget, n, 1); + ns.print("nGrowThreadsNeeded = " + nGrowThreadsNeeded); + + while (nMoney < nMaxMoney) { + + let nFreeRam = ns.getServerMaxRam("home") - ns.getServerUsedRam("home"); + let nGrowPID = ns.run(sGrowScript, Math.min([Math.ceil(nGrowThreadsNeeded)], [Math.ceil(nFreeRam / ns.getScriptRam(sGrowScript, "home"))]), sTarget); + await ns.nextPortWrite(nGrowPID); + await ns.sleep(1000); + nMoney = ns.getServerMoneyAvailable(sTarget); + } + + await ns.sleep(Math.ceil(nDelay)); + //run batch const nBatchPID = ns.run(sBatch, 1, sTarget); ns.tail(nBatchPID, "home", sBatch, 1, sTarget); ns.resizeTail(815, 395, nBatchPID); ns.moveTail(1925, 0, nBatchPID); -} +} \ No newline at end of file diff --git a/local/path/home/RMcontroller.js b/local/path/home/RMcontroller.js index 39ecaf1..2d1bd36 100644 --- a/local/path/home/RMcontroller.js +++ b/local/path/home/RMcontroller.js @@ -20,7 +20,7 @@ export async function main(ns) { const nHomeMaxRAM = ns.getServerMaxRam("home"); let nHomeFreeRAM = nHomeMaxRAM - nHomeUsedRAM; - const nDelays = [0, 20, 40, 60]; + const nDelays = [0, 100, 200, 300]; //abort script if sTarget is undefined @@ -34,7 +34,7 @@ export async function main(ns) { const nMaxMoney = ns.getServerMaxMoney(sTarget); let nWeakenTime1 = ns.getWeakenTime(sTarget); - let nWeakenTime2 = nWeakenTime1; + let nWeakenTime2 = nWeakenTime1 + nDelays[3]; let nGrowTime = nWeakenTime1 * 0.8; let nHackTime = nWeakenTime1 / 4; @@ -51,7 +51,7 @@ export async function main(ns) { //let nGrowThreadsEstimate = Math.max(Math.floor(1 / nGrowSecurityGain),1); //ns.tprint("nGrowSecurityGain = " + nGrowSecurityGain); //ns.tprint("nGrowThreadsEstimate = " + nGrowThreadsEstimate); - const nGrowTotalRAM = nGrowRAM * 13; + const nGrowTotalRAM = nGrowRAM * 12.5; //let nWeakenSecurity = ns.weakenAnalyze(1, nCores); //let nWeakenSecurity = 0.05; @@ -65,7 +65,7 @@ export async function main(ns) { let nHackThreadsEstimate = nTotalBatches * 25; let nWeakenThreadsEstimate1 = nTotalBatches * 1; - let nGrowThreadsEstimate = nTotalBatches * 13; + let nGrowThreadsEstimate = nTotalBatches * 12.5; let nWeakenThreadsEstimate2 = nTotalBatches * 1; ns.tprint("RAM per Cycle = " + nTotalRAM); @@ -75,6 +75,7 @@ export async function main(ns) { let nGrowDelay = nWeakenTime1 - nGrowTime; let nHackDelay = nWeakenTime1 - nHackTime; + const nCycleDuration = nWeakenTime2 + nDelays[3]; ns.tprint("nCycleDuration = " + nCycleDuration); @@ -96,7 +97,7 @@ export async function main(ns) { //Calculate estimate time of completion nOffset = ns.getWeakenTime(sTarget); - let nSafeTime = nOffset + nDelays[3]+1000; + let nSafeTime = nOffset + nDelays[3] + 1000; let nWeakTime = new Date(currentDate.getTime() + nSafeTime); let sWeakTime = nWeakTime.toLocaleTimeString('sw-SV'); //swedish time @@ -108,7 +109,7 @@ export async function main(ns) { //ns.tail(nHackPID, "home", "home", nHackThreadsEstimate, sTarget, 0, nHackDelay + nDelays[0]); //weaken 1 - const nWeakenPID = ns.exec(sWeaken, "home", nWeakenThreadsEstimate1, sTarget, false, nDelays[1]); + const nWeakenPID1 = ns.exec(sWeaken, "home", nWeakenThreadsEstimate1, sTarget, false, nDelays[1]); //ns.tail(nWeakenPID, "home", "home", nWeakenThreadsEstimate, sTarget, 0, nDelays[1]); //grow @@ -119,8 +120,47 @@ export async function main(ns) { const nWeakenPID2 = ns.exec(sWeaken, "home", nWeakenThreadsEstimate2, sTarget, false, nDelays[3]); //ns.tail(nWeakenPID2, "home", "home", nWeakenThreadsEstimate, sTarget, 0, nDelays[3]); - await ns.sleep(nSafeTime); + //await ns.sleep(nSafeTime); + /* + await ns.nextPortWrite(nHackPID); + await ns.nextPortWrite(nWeakenPID1); + await ns.nextPortWrite(nGrowPID); + await ns.nextPortWrite(nWeakenPID2); + + ns.print("nHackPeek = " + nHackPeek); + ns.print("nWeaken1Peek = " + nWeaken1Peek); + ns.print("nGrowPeek = " + nGrowPeek); + ns.print("nWeaken2Peek = " + nWeaken2Peek); + */ + + + let nHackPeek = ns.peek(nHackPID); + let nWeaken1Peek = ns.peek(nWeakenPID1); + let nGrowPeek = ns.peek(nGrowPID); + let nWeaken2Peek = ns.peek(nWeakenPID2); + + + if (nHackPeek === true || nWeaken1Peek === true || nGrowPeek === true || nWeaken2Peek === true) { + ns.print("some of the ports are already written to..."); + ns.print("nHackPeek = " + nHackPeek); + ns.print("nWeaken1Peek = " + nWeaken1Peek); + ns.print("nGrowPeek = " + nGrowPeek); + ns.print("nWeaken2Peek = " + nWeaken2Peek); + } + + await Promise.all([ + ns.nextPortWrite(nHackPID), + ns.nextPortWrite(nWeakenPID1), + ns.nextPortWrite(nGrowPID), + ns.nextPortWrite(nWeakenPID2) + ]) + + + ns.print("hack: " + nHackPID + " completed at " + ns.readPort(nHackPID)); + ns.print("weaken1: " + nWeakenPID1 + " completed at " + ns.readPort(nWeakenPID1)); + ns.print("grow: " + nGrowPID + " completed at " + ns.readPort(nGrowPID)); + ns.print("weaken2: " + nWeakenPID2 + " completed at " + ns.readPort(nWeakenPID2)); + await ns.sleep(100); } - } \ No newline at end of file diff --git a/local/path/home/RMgrow.js b/local/path/home/RMgrow.js index 545e449..af66c8d 100644 --- a/local/path/home/RMgrow.js +++ b/local/path/home/RMgrow.js @@ -11,4 +11,5 @@ export async function main(ns) { await ns.grow(sTarget, { additionalMsec: nMsecDelay }); ns.print(Date.now()); + ns.writePort(ns.pid, Date.now()); } \ No newline at end of file diff --git a/local/path/home/RMhack.js b/local/path/home/RMhack.js index aed6f3f..bf297c9 100644 --- a/local/path/home/RMhack.js +++ b/local/path/home/RMhack.js @@ -8,7 +8,8 @@ export async function main(ns) { while (bRepeat === true) { await ns.hack(sTarget, { additionalMsec: nMsecDelay }); } - + await ns.hack(sTarget, { additionalMsec: nMsecDelay }); ns.print(Date.now()); + ns.writePort(ns.pid, Date.now()); } \ No newline at end of file diff --git a/local/path/home/RMweaken.js b/local/path/home/RMweaken.js index 58fd424..fe6e819 100644 --- a/local/path/home/RMweaken.js +++ b/local/path/home/RMweaken.js @@ -11,4 +11,5 @@ export async function main(ns) { await ns.weaken(sTarget, { additionalMsec: nMsecDelay }); ns.print(Date.now()); + ns.writePort(ns.pid, Date.now()); } \ No newline at end of file diff --git a/local/path/home/Ramses-grow.js b/local/path/home/Ramses-grow.js deleted file mode 100644 index 9d264c9..0000000 --- a/local/path/home/Ramses-grow.js +++ /dev/null @@ -1,5 +0,0 @@ -/** @param {NS} ns */ -export async function main(ns) { - const sServer = ns.args[0]; - await ns.grow(sServer); -} \ No newline at end of file diff --git a/local/path/home/Ramses-hack.js b/local/path/home/Ramses-hack.js deleted file mode 100644 index 7537711..0000000 --- a/local/path/home/Ramses-hack.js +++ /dev/null @@ -1,5 +0,0 @@ -/** @param {NS} ns */ -export async function main(ns) { - const sServer = ns.args[0]; - await ns.hack(sServer); -} \ No newline at end of file diff --git a/local/path/home/Ramses-weaken.js b/local/path/home/Ramses-weaken.js deleted file mode 100644 index 0c09963..0000000 --- a/local/path/home/Ramses-weaken.js +++ /dev/null @@ -1,5 +0,0 @@ -/** @param {NS} ns */ -export async function main(ns) { - const sServer = ns.args[0]; - await ns.weaken(sServer); -} \ No newline at end of file diff --git a/local/path/home/S2controller.js b/local/path/home/S2controller.js deleted file mode 100644 index 725de87..0000000 --- a/local/path/home/S2controller.js +++ /dev/null @@ -1,297 +0,0 @@ -/* -Welcome to part 2. I'll only be commenting on things that have changed from the previous part, so if there's something -confusing, be sure to go back and look at part 1 for more detailed explanations. - -For part 2, we'll be making a protobatcher. Essentially that means we'll be running our previous version in a constant loop. -To facilitate this, and because otherwise there wouldn't really be much to this part, we're going to refine the way our -scripts communicate with each other using ports. -*/ - -import { getServers, copyScripts, checkTarget, isPrepped, prep } from "/S2utils.js"; - -const TYPES = ["hack", "weaken1", "grow", "weaken2"]; -const WORKERS = ["S2tHack.js", "S2tWeaken.js", "S2tGrow.js"]; -const SCRIPTS = { hack: "S2tHack.js", weaken1: "S2tWeaken.js", grow: "S2tGrow.js", weaken2: "S2tWeaken.js" }; -const COSTS = { hack: 1.7, weaken1: 1.75, grow: 1.75, weaken2: 1.75 }; -const OFFSETS = { hack: 0, weaken1: 1, grow: 2, weaken2: 3 }; - -/* -Most of the changes are in the main function, so I've moved it up top. I generally prefer having the main function at the -top of the file anyway. -*/ -/** @param {NS} ns */ -export async function main(ns) { - await ns.sleep(500); - // Moving most of our active feeback to the tail window so that batches finishing don't get swept away. - ns.disableLog("ALL"); - ns.tail(); - - // Stick the whole script in a loop. That's it, see you in part 3. - // Just kidding, there's a bit more to it. - let batchCount = 0; - while (true) { - // Register a port using the script's unique handle. - // I like to keep ports strictly coupled to a specific script, but you can use whatever number you like. - const dataPort = ns.getPortHandle(ns.pid); - dataPort.clear() // Make sure there's no random data left in the port. - - let target = "n00dles"; - const servers = getServers(ns, (server) => { - // Don't worry if you don't have Formulas, it's not needed at all here. - target = checkTarget(ns, server, target, ns.fileExists("Formulas.exe", "home")); - copyScripts(ns, server, WORKERS, true); - return ns.hasRootAccess(server); - }); - //target = "n00dles"; - const ramNet = new RamNet(ns, servers); - const metrics = new Metrics(ns, target); - if (!isPrepped(ns, target)) await prep(ns, metrics, ramNet); - optimizeBatch(ns, metrics, ramNet); // The same optimization algorithm works just fine for protobatching. - metrics.calculate(ns); - - const batch = []; - batchCount++; - for (const type of TYPES) { - // We've removed the buffer. You'll see why later. - metrics.ends[type] = Date.now() + metrics.wTime + metrics.spacer * OFFSETS[type]; - const job = new Job(type, metrics); - job.batch = batchCount; // This is a bit of a hack. We'll do it better in the next part. - if (!ramNet.assign(job)) { - ns.print(`ERROR: Unable to assign ${type}. Dumping debug info:`); - ns.print(job); - ns.print(metrics); - ramNet.printBlocks(ns); - return; - } - batch.push(job); - } - - // We do a bit more during deployment now. - for (const job of batch) { - job.end += metrics.delay; - const jobPid = ns.exec(SCRIPTS[job.type], job.server, { threads: job.threads, temporary: true }, JSON.stringify(job)); - if (!jobPid) throw new Error(`Unable to deploy ${job.type}`); // If the exec fails for any reason, error out. - /* - If a worker deploys late, it will communicate back how late it was, so that the other scripts can adjust. - Note that for this we use the *worker's* port instead of our controller's port. It's good practice to make - sure your ports have a very narrow focus. - */ - const tPort = ns.getPortHandle(jobPid); - await tPort.nextWrite(); - metrics.delay += tPort.read(); - } - - const timer = setInterval(() => { - ns.clearLog(); - ns.print(`Hacking \$${ns.formatNumber(metrics.maxMoney * metrics.greed)} from ${metrics.target}`) - ns.print(`Running batch: ETA ${ns.tFormat(metrics.ends.weaken2 - Date.now())}`); - }, 1000); - ns.atExit(() => { - clearInterval(timer); - }); - // Wait for the weaken2 worker to report back. For now I've just hardcoded the Job class to tell only - // weaken2 to report. This behavior will change later. - await dataPort.nextWrite(); - dataPort.clear(); // For now we don't actually need the information here, we're just using it for timing. - clearInterval(timer); - } -} - -class Job { - constructor(type, metrics, server = "none") { - this.type = type; - this.end = metrics.ends[type]; - this.time = metrics.times[type]; - this.target = metrics.target; - this.threads = metrics.threads[type]; - this.cost = this.threads * COSTS[type]; - this.server = server; - this.report = this.type === "weaken2"; // For now, only w2 jobs report. - this.port = metrics.port; // This lets the workers know which port to write to. - this.batch = 0; // We'll keep track of how many we've run, just because we can. - } -} - -/** @param {NS} ns */ -class Metrics { - constructor(ns, server) { - this.target = server; - this.maxMoney = ns.getServerMaxMoney(server); - this.money = Math.max(ns.getServerMoneyAvailable(server), 1); - this.minSec = ns.getServerMinSecurityLevel(server); - this.sec = ns.getServerSecurityLevel(server); - this.prepped = isPrepped(ns, server); - this.chance = 0; - this.wTime = 0; - this.delay = 0; // The cumulative delays caused by late jobs. - this.spacer = 5; - this.greed = 0.1; - this.depth = 0; // Still not using this. - - this.times = { hack: 0, weaken1: 0, grow: 0, weaken2: 0 }; - this.ends = { hack: 0, weaken1: 0, grow: 0, weaken2: 0 }; - this.threads = { hack: 0, weaken1: 0, grow: 0, weaken2: 0 }; - - this.port = ns.pid; - } - - calculate(ns, greed = this.greed) { - const server = this.target; - const maxMoney = this.maxMoney; - this.money = ns.getServerMoneyAvailable(server); - this.sec = ns.getServerSecurityLevel(server); - this.wTime = ns.getWeakenTime(server); - this.times.weaken1 = this.wTime; - this.times.weaken2 = this.wTime; - this.times.hack = this.wTime / 4; - this.times.grow = this.wTime * 0.8; - this.depth = this.wTime / this.spacer * 4; - - const hPercent = ns.hackAnalyze(server); - const amount = maxMoney * greed; - const hThreads = Math.max(Math.floor(ns.hackAnalyzeThreads(server, amount)), 1); - const tGreed = hPercent * hThreads; - const gThreads = Math.ceil(ns.growthAnalyze(server, maxMoney / (maxMoney - maxMoney * tGreed))); - this.threads.weaken1 = Math.max(Math.ceil(hThreads * 0.002 / 0.05), 1); - this.threads.weaken2 = Math.max(Math.ceil(gThreads * 0.004 / 0.05), 1); - this.threads.hack = hThreads; - this.threads.grow = gThreads; - this.chance = ns.hackAnalyzeChance(server); - } -} - -/** @param {NS} ns */ -class RamNet { - #blocks = []; - #minBlockSize = Infinity; - #maxBlockSize = 0; - #totalRam = 0; - #maxRam = 0; - #prepThreads = 0; - #index = new Map(); - constructor(ns, servers) { - for (const server of servers) { - if (ns.hasRootAccess(server)) { - const maxRam = ns.getServerMaxRam(server); - const ram = maxRam - ns.getServerUsedRam(server); - if (ram >= 1.60) { - const block = { server: server, ram: ram }; - this.#blocks.push(block); - if (ram < this.#minBlockSize) this.#minBlockSize = ram; - if (ram > this.#maxBlockSize) this.#maxBlockSize = ram; - this.#totalRam += ram; - this.#maxRam += maxRam; - this.#prepThreads += Math.floor(ram / 1.75); - } - } - } - this.#sort(); - this.#blocks.forEach((block, index) => this.#index.set(block.server, index)); - } - - #sort() { - this.#blocks.sort((x, y) => { - if (x.server === "home") return 1; - if (y.server === "home") return -1; - - return x.ram - y.ram; - }); - } - - getBlock(server) { - if (this.#index.has(server)) { - return this.#blocks[this.#index.get(server)]; - } else { - throw new Error(`Server ${server} not found in RamNet.`); - } - } - - get totalRam() { - return this.#totalRam; - } - - get maxRam() { - return this.#maxRam; - } - - get maxBlockSize() { - return this.#maxBlockSize; - } - - get prepThreads() { - return this.#prepThreads; - } - - assign(job) { - const block = this.#blocks.find(block => block.ram >= job.cost); - if (block) { - job.server = block.server; - block.ram -= job.cost; - this.#totalRam -= job.cost; - return true; - } else return false; - } - - finish(job) { - const block = this.getBlock(job.server); - block.ram += job.cost; - this.#totalRam += job.cost; - } - - cloneBlocks() { - return this.#blocks.map(block => ({ ...block })); - } - - printBlocks(ns) { - for (const block of this.#blocks) ns.print(block); - } -} - -/** - * @param {NS} ns - * @param {Metrics} metrics - * @param {RamNet} ramNet - */ -export function optimizeBatch(ns, metrics, ramNet) { - const maxThreads = ramNet.maxBlockSize / 1.75; - const maxMoney = metrics.maxMoney; - const hPercent = ns.hackAnalyze(metrics.target); - - const minGreed = 0.001; - const stepValue = 0.001; - let greed = 0.99; - while (greed > minGreed) { - const amount = maxMoney * greed; - const hThreads = Math.max(Math.floor(ns.hackAnalyzeThreads(metrics.target, amount)), 1); - const tGreed = hPercent * hThreads; - const gThreads = Math.ceil(ns.growthAnalyze(metrics.target, maxMoney / (maxMoney - maxMoney * tGreed))); - - if (Math.max(hThreads, gThreads) <= maxThreads) { - const wThreads1 = Math.max(Math.ceil(hThreads * 0.002 / 0.05), 1); - const wThreads2 = Math.max(Math.ceil(gThreads * 0.004 / 0.05), 1); - - const threadCosts = [hThreads * 1.7, wThreads1 * 1.75, gThreads * 1.75, wThreads2 * 1.75]; - - const pRam = ramNet.cloneBlocks(); - let found; - for (const cost of threadCosts) { - found = false; - for (const block of pRam) { - if (block.ram < cost) continue; - found = true; - block.ram -= cost; - break; - } - if (found) continue; - break; - } - if (found) { - metrics.greed = greed; - metrics.threads = { hack: hThreads, weaken1: wThreads1, grow: gThreads, weaken2: wThreads2 }; - return true; - } - } - greed -= stepValue; - } - throw new Error("Not enough ram to run even a single batch. Something has gone seriously wrong."); -} \ No newline at end of file diff --git a/local/path/home/S2tGrow.js b/local/path/home/S2tGrow.js deleted file mode 100644 index 12ca93a..0000000 --- a/local/path/home/S2tGrow.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - Very little has changed in the workers. We uncommented a couple of parts to allow for the ping-pong deployment. - See the tWeaken.js for full comments. -*/ - -/** @param {NS} ns */ -export async function main(ns) { - const job = JSON.parse(ns.args[0]); - let delay = job.end - job.time - Date.now(); - if (delay < 0) { - ns.tprint(`WARN: Batch ${job.batch} ${job.type} was ${-delay}ms late. (${job.end})\n`); - ns.writePort(ns.pid, -delay); - delay = 0; - } else { - ns.writePort(ns.pid, 0); - } - await ns.grow(job.target, { additionalMsec: delay }); - const end = Date.now(); - ns.atExit(() => { - // if (job.report) ns.writePort(job.port, job.type + job.server); - ns.tprint(`Batch ${job.batch}: ${job.type} finished at ${end.toString().slice(-6)}/${Math.round(job.end).toString().slice(-6)}\n`); - }); -} \ No newline at end of file diff --git a/local/path/home/S2tHack.js b/local/path/home/S2tHack.js deleted file mode 100644 index f7e46ff..0000000 --- a/local/path/home/S2tHack.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - Very little has changed in the workers. We uncommented a couple of parts to allow for the ping-pong deployment. - See the tWeaken.js for full comments. -*/ - -/** @param {NS} ns */ -export async function main(ns) { - const job = JSON.parse(ns.args[0]); - let delay = job.end - job.time - Date.now(); - if (delay < 0) { - ns.tprint(`WARN: Batch ${job.batch} ${job.type} was ${-delay}ms late. (${job.end})\n`); - ns.writePort(ns.pid, -delay); - delay = 0; - } else { - ns.writePort(ns.pid, 0); - } - await ns.hack(job.target, { additionalMsec: delay }); - const end = Date.now(); - ns.atExit(() => { - // if (job.report) ns.writePort(job.port, job.type + job.server); - ns.tprint(`Batch ${job.batch}: ${job.type} finished at ${end.toString().slice(-6)}/${Math.round(job.end).toString().slice(-6)}\n`); - }); -} \ No newline at end of file diff --git a/local/path/home/S2tWeaken.js b/local/path/home/S2tWeaken.js deleted file mode 100644 index f762ad6..0000000 --- a/local/path/home/S2tWeaken.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - Very little has changed in the workers. We uncommented a couple of parts to allow for the ping-pong deployment. - See the tWeaken.js for full comments. -*/ - -/** @param {NS} ns */ -export async function main(ns) { - const job = JSON.parse(ns.args[0]); - - let delay = job.end - job.time - Date.now(); - if (delay < 0) { - // We now write back to the controller if jobs are delayed so that it can adjust the other jobs to match. - ns.tprint(`WARN: Batch ${job.batch} ${job.type} was ${-delay}ms late. (${job.end})\n`); - ns.writePort(ns.pid, -delay); - delay = 0; - } else { - ns.writePort(ns.pid, 0); - } - await ns.weaken(job.target, { additionalMsec: delay }); - const end = Date.now(); - - // Write back to let the controller know that we're done. The actual data is currently only used by the prep function. - ns.atExit(() => { - if (job.report) ns.writePort(job.port, job.type + job.server); - ns.tprint(`Batch ${job.batch}: ${job.type} finished at ${end.toString().slice(-6)}/${Math.round(job.end).toString().slice(-6)}\n`); - }); -} \ No newline at end of file diff --git a/local/path/home/S2utils.js b/local/path/home/S2utils.js deleted file mode 100644 index 573df08..0000000 --- a/local/path/home/S2utils.js +++ /dev/null @@ -1,218 +0,0 @@ -/* - The utility function library. This is almost entirely unchanged from part 1, aside from the prep function - printing to the log console instead of the terminal. -*/ - -/** @param {NS} ns */ -export async function main(ns) { - ns.tprint("This is just a function library, it doesn't do anything."); -} - -// The recursive server navigation algorithm. The lambda predicate determines which servers to add to the final list. -// You can also plug other functions into the lambda to perform other tasks that check all servers at the same time. -/** @param {NS} ns */ -export function getServers(ns, lambdaCondition = () => true, hostname = "home", servers = [], visited = []) { - if (visited.includes(hostname)) return; - visited.push(hostname); - if (lambdaCondition(hostname)) servers.push(hostname); - const connectedNodes = ns.scan(hostname); - if (hostname !== "home") connectedNodes.shift(); - for (const node of connectedNodes) getServers(ns, lambdaCondition, node, servers, visited); - return servers; -} - -// Here are a couple of my own getServers modules. -// This one finds the best target for hacking. It tries to balance expected return with time taken. -/** @param {NS} ns */ -export function checkTarget(ns, server, target = "n00dles", forms = false) { - if (!ns.hasRootAccess(server)) return target; - const player = ns.getPlayer(); - const serverSim = ns.getServer(server); - const pSim = ns.getServer(target); - let previousScore; - let currentScore; - if (serverSim.requiredHackingSkill <= player.skills.hacking / (forms ? 1 : 2)) { - if (forms) { - serverSim.hackDifficulty = serverSim.minDifficulty; - pSim.hackDifficulty = pSim.minDifficulty; - previousScore = pSim.moneyMax / ns.formulas.hacking.weakenTime(pSim, player) * ns.formulas.hacking.hackChance(pSim, player); - currentScore = serverSim.moneyMax / ns.formulas.hacking.weakenTime(serverSim, player) * ns.formulas.hacking.hackChance(serverSim, player); - } else { - previousScore = pSim.moneyMax / pSim.minDifficulty; - currentScore = serverSim.moneyMax / serverSim.minDifficulty; - } - if (currentScore > previousScore) target = server; - } - return target; -} - -// A simple function for copying a list of scripts to a server. -/** @param {NS} ns */ -export function copyScripts(ns, server, scripts, overwrite = false) { - for (const script of scripts) { - if ((!ns.fileExists(script, server) || overwrite) && ns.hasRootAccess(server)) { - ns.scp(script, server); - } - } -} - -// A generic function to check that a given server is prepped. Mostly just a convenience. -export function isPrepped(ns, server) { - const tolerance = 0.0001; - const maxMoney = ns.getServerMaxMoney(server); - const money = ns.getServerMoneyAvailable(server); - const minSec = ns.getServerMinSecurityLevel(server); - const sec = ns.getServerSecurityLevel(server); - const secFix = Math.abs(sec - minSec) < tolerance; - return (money === maxMoney && secFix) ? true : false; -} - -/* - This prep function isn't part of the tutorial, but the rest of the code wouldn't work without it. - I don't make any guarantees, but I've been using it and it's worked well enough. I'll comment it anyway. - The prep strategy uses a modified proto-batching technique, which will be covered in part 2. -*/ -/** @param {NS} ns */ -export async function prep(ns, values, ramNet) { - const maxMoney = values.maxMoney; - const minSec = values.minSec; - let money = values.money; - let sec = values.sec; - while (!isPrepped(ns, values.target)) { - const wTime = ns.getWeakenTime(values.target); - const gTime = wTime * 0.8; - const dataPort = ns.getPortHandle(ns.pid); - dataPort.clear(); - - const pRam = ramNet.cloneBlocks(); - const maxThreads = Math.floor(ramNet.maxBlockSize / 1.75); - const totalThreads = ramNet.prepThreads; - let wThreads1 = 0; - let wThreads2 = 0; - let gThreads = 0; - let batchCount = 1; - let script, mode; - /* - Modes: - 0: Security only - 1: Money only - 2: One shot - */ - - if (money < maxMoney) { - gThreads = Math.ceil(ns.growthAnalyze(values.target, maxMoney / money)); - wThreads2 = Math.ceil(ns.growthAnalyzeSecurity(gThreads) / 0.05); - } - if (sec > minSec) { - wThreads1 = Math.ceil((sec - minSec) * 20); - if (!(wThreads1 + wThreads2 + gThreads <= totalThreads && gThreads <= maxThreads)) { - gThreads = 0; - wThreads2 = 0; - batchCount = Math.ceil(wThreads1 / totalThreads); - if (batchCount > 1) wThreads1 = totalThreads; - mode = 0; - } else mode = 2; - } else if (gThreads > maxThreads || gThreads + wThreads2 > totalThreads) { - mode = 1; - const oldG = gThreads; - wThreads2 = Math.max(Math.floor(totalThreads / 13.5), 1); - gThreads = Math.floor(wThreads2 * 12.5); - batchCount = Math.ceil(oldG / gThreads); - } else mode = 2; - - // Big buffer here, since all the previous calculations can take a while. One second should be more than enough. - const wEnd1 = Date.now() + wTime + 1000; - const gEnd = wEnd1 + values.spacer; - const wEnd2 = gEnd + values.spacer; - - // "metrics" here is basically a mock Job object. Again, this is just an artifact of repurposed old code. - const metrics = { - batch: "prep", - target: values.target, - type: "none", - time: 0, - end: 0, - port: ns.pid, - log: values.log, - report: false - }; - - // Actually assigning threads. We actually allow grow threads to be spread out in mode 1. - // This is because we don't mind if the effect is a bit reduced from higher security unlike a normal batcher. - // We're not trying to grow a specific amount, we're trying to grow as much as possible. - for (const block of pRam) { - while (block.ram >= 1.75) { - const bMax = Math.floor(block.ram / 1.75) - let threads = 0; - if (wThreads1 > 0) { - script = "S2tWeaken.js"; - metrics.type = "pWeaken1"; - metrics.time = wTime; - metrics.end = wEnd1; - threads = Math.min(wThreads1, bMax); - if (wThreads2 === 0 && wThreads1 - threads <= 0) metrics.report = true; - wThreads1 -= threads; - } else if (wThreads2 > 0) { - script = "S2tWeaken.js"; - metrics.type = "pWeaken2"; - metrics.time = wTime; - metrics.end = wEnd2; - threads = Math.min(wThreads2, bMax); - if (wThreads2 - threads === 0) metrics.report = true; - wThreads2 -= threads; - } else if (gThreads > 0 && mode === 1) { - script = "S2tGrow.js"; - metrics.type = "pGrow"; - metrics.time = gTime; - metrics.end = gEnd; - threads = Math.min(gThreads, bMax); - metrics.report = false; - gThreads -= threads; - } else if (gThreads > 0 && bMax >= gThreads) { - script = "S2tGrow.js"; - metrics.type = "pGrow"; - metrics.time = gTime; - metrics.end = gEnd; - threads = gThreads; - metrics.report = false; - gThreads = 0; - } else break; - metrics.server = block.server; - const pid = ns.exec(script, block.server, { threads: threads, temporary: true }, JSON.stringify(metrics)); - if (!pid) throw new Error("Unable to assign all jobs."); - block.ram -= 1.75 * threads; - } - } - - // Fancy UI stuff to update you on progress. - const tEnd = ((mode === 0 ? wEnd1 : wEnd2) - Date.now()) * batchCount + Date.now(); - const timer = setInterval(() => { - ns.clearLog(); - switch (mode) { - case 0: - ns.print(`Weakening security on ${values.target}...`); - break; - case 1: - ns.print(`Maximizing money on ${values.target}...`); - break; - case 2: - ns.print(`Finalizing preparation on ${values.target}...`); - } - ns.print(`Security: +${ns.formatNumber(sec - minSec, 3)}`); - ns.print(`Money: \$${ns.formatNumber(money, 2)}/${ns.formatNumber(maxMoney, 2)}`); - const time = tEnd - Date.now(); - ns.print(`Estimated time remaining: ${ns.tFormat(time)}`); - ns.print(`~${batchCount} ${(batchCount === 1) ? "batch" : "batches"}.`); - }, 200); - ns.atExit(() => clearInterval(timer)); - - // Wait for the last weaken to finish. - do await dataPort.nextWrite(); while (!dataPort.read().startsWith("pWeaken")); - clearInterval(timer); - await ns.sleep(100); - - money = ns.getServerMoneyAvailable(values.target); - sec = ns.getServerSecurityLevel(values.target); - } - return true; -} \ No newline at end of file diff --git a/local/path/home/S4controller.js b/local/path/home/S4controller.js deleted file mode 100644 index 46bd6ae..0000000 --- a/local/path/home/S4controller.js +++ /dev/null @@ -1,491 +0,0 @@ -/* -Welcome to part 4. A continuous batcher is a major hurdle compared to everything we've done so far. The number -and complexity of the challenges increases drastically when trying to keep everything running indefinitely. -With luck, the overengineering we've done so far will have well prepared us for the challenges of a periodic -batcher. - -Technically, I use quite a few JIT techniques in this batcher, but I don't consider it a true JIT batcher -as it doesn't take full advantage of the potential RAM efficiency. Instead, I favor simpler logic, while still -allowing the batcher to make certain adjustments if it needs to. - -When it comes to continuous batchers, performance is king. We're going to aim for 5ms spacing as we have -throughout this guide so far, but there's a lot we need to do in those 5ms. As such, we need to make sure that -we choose which operations to do carefully, as well as when to do them and how to make sure they are as fast -as we can make them. -*/ - -// One new utility. A custom data structure for managing our schedule. You can see the details in utils.js -import { getServers, copyScripts, checkTarget, isPrepped, prep, Deque } from "/S4utils.js"; - -const TYPES = ["hack", "weaken1", "grow", "weaken2"]; -const WORKERS = ["S4tHack.js", "S4tWeaken.js", "S4tGrow.js"]; -const SCRIPTS = { hack: "S4tHack.js", weaken1: "S4tWeaken.js", grow: "S4tGrow.js", weaken2: "S4tWeaken.js" }; -const COSTS = { hack: 1.7, weaken1: 1.75, grow: 1.75, weaken2: 1.75 }; -// const OFFSETS = { hack: 0, weaken1: 1, grow: 2, weaken2: 3 }; - -// A new optional constant. The RamNet will attempt to reserve this much ram at home. -// You can set it to 0 if you don't want to reserve anything, and setting it too high will just reserve as much as possible. -const RESERVED_HOME_RAM = 0; - -// A brand new class to help keep our increasingly complex logic organized. -class ContinuousBatcher { - #ns; // The ns object. Stored as a class variable to save me the trouble of passing it all the time. - - // The usual data we've grown familiar with by now. - #metrics; - #ramNet; - #target; - #schedule; - #dataPort; - #batchCount = 0; - #desyncs = 0; // This is mostly used for logging purposes, since the batcher is self-correcting. - - // A capital M Map. We'll use this to keep track of active jobs. - #running = new Map(); - - constructor(ns, metrics, ramNet) { - this.#ns = ns; - this.#metrics = metrics; - this.#ramNet = ramNet; - this.#target = metrics.target; - this.#dataPort = ns.getPortHandle(ns.pid); - - // Seeding the first ending time. - this.#metrics.end = Date.now() + metrics.wTime - metrics.spacer; - - // The new schedule I promised. It's a double-ended queue, but we'll mostly just be using it as a normal queue. - // It has a static size, so we make sure it can accomodate all of our jobs. - this.#schedule = new Deque(metrics.depth * 4); - } - - // This is a function that can schedule a given number of batches. - // With no arguments, it just fills up the queue. - scheduleBatches(batches = this.#metrics.depth) { - while (this.#schedule.size < batches * 4) { - ++this.#batchCount; - for (const type of TYPES) { - this.#metrics.end += this.#metrics.spacer; - const job = new Job(type, this.#metrics, this.#batchCount); - - /* - We don't actually error out if a job can't be assigned anymore. Instead, we just assign as much - as we can. If it desyncs, the logic will correct it, and if a weaken2 gets cancelled then the actual - depth will naturally decrease below the target depth. Not a perfect fix, but better than breaking. - */ - if (!this.#ramNet.assign(job)) { - this.#ns.tprint(`WARN: Insufficient RAM to assign ${job.type}: ${job.batch}.`); - continue; - } - this.#schedule.push(job); - } - } - } - - // The function for deploying jobs. Very similar to the code from our shotgun batcher with some minor changes. - async deploy() { - // The for loop is replaced by a while loop, since our Deque isn't iterable. - while (!this.#schedule.isEmpty()) { - const job = this.#schedule.shift(); - job.end += this.#metrics.delay; - const jobPid = this.#ns.exec(SCRIPTS[job.type], job.server, { threads: job.threads, temporary: true }, JSON.stringify(job)); - if (!jobPid) throw new Error(`Unable to deploy ${job.type}`); - const tPort = this.#ns.getPortHandle(jobPid); - - // We save the pid for later. - job.pid = jobPid; - await tPort.nextWrite(); - - // Jobs can be late as long as the delay won't cause collisions. - this.#metrics.delay += Math.max(Math.ceil(tPort.read()) - this.#metrics.spacer, 0); - this.#running.set(job.id, job); - } - - // After the loop, we adjust future job ends to account for the delay, then discard it. - this.#metrics.end += this.#metrics.delay; - this.#metrics.delay = 0; - } - - // Our old timeout function is now a proper function of its own. A few extra baubles in the log, but nothing exciting. - /** @param {NS} ns */ - log() { - const ns = this.#ns; - const metrics = this.#metrics; - const ramNet = this.#ramNet; - ns.clearLog(); - ns.print(`Hacking ~\$${ns.formatNumber(metrics.maxMoney * metrics.greed * metrics.chance / (4 * metrics.spacer) * 1000)}/s from ${metrics.target}`); - ns.print(`Status: ${isPrepped(ns, this.#target) ? "Prepped" : "Desynced"}`); - ns.print(`Security: +${metrics.minSec - metrics.sec}`); - ns.print(`Money: \$${ns.formatNumber(metrics.money, 2)}/${ns.formatNumber(metrics.maxMoney, 2)}`); - ns.print(`Greed: ${Math.floor(metrics.greed * 1000) / 10}%`); - ns.print(`Ram available: ${ns.formatRam(ramNet.totalRam)}/${ns.formatRam(ramNet.maxRam)}`); - ns.print(`Active jobs: ${this.#running.size}/${metrics.depth * 4}`); - - // You'll see what this line's about in a moment. - if (this.#desyncs) ns.print(`Hacks cancelled by desync: ${this.#desyncs}`); - } - - // The core loop of our batcher logic. Quite lean with everything neatly divided into functions, but there's still - // plenty going on here. - async run() { - // First we do some initial setup, this is essentially firing off a shotgun blast to get us started. - const dataPort = this.#dataPort; - this.scheduleBatches(); - await this.deploy(); - await this.#ns.sleep(0); // This is probably pointless. I forget why I put it here. - this.log(); - while (true) { - // Wait for the nextWrite, as usual. - await dataPort.nextWrite(); - - // Sometimes there's a delay and more than one job writes to the port at once. - // We make sure to handle it all before we move on. - while (!dataPort.empty()) { - // Workers now report unique identifiers (type + batchnumber) used to find them on the map. - const data = dataPort.read(); - - // Free up the ram, them remove them from the active list. - // The check handles a corner case where a hack gets "cancelled" after it's already finished. - if (this.#running.has(data)) { - this.#ramNet.finish(this.#running.get(data)); - this.#running.delete(data); - } - - // If it's a W2, we've got an opening to do some work. - if (data.startsWith("weaken2")) { - // Recalculate times. Threads too, but only if prepped (the logic is in the function itself). - this.#metrics.calculate(this.#ns); - - /* - This is probably the most JIT-like aspect of the entire batcher. If the server isn't prepped, then - we cancel the next hack to let the server fix itself. Between this and the extra 1% grow threads, level - ups are completely handled. Rapid level ups can lead to a lot of lost jobs, but eventually the program - stabilizes. - - There are probably more efficient ways to do this. Heck, even this solution could be optimized better, - but for now, this is an adequate demonstration of a reasonable non-formulas solution to the level up - problem. It also lets us dip our toes into JIT logic in preparation for the final part. - */ - if (!isPrepped(this.#ns, this.#target)) { - const id = "hack" + (parseInt(data.slice(7)) + 1); - const cancel = this.#running.get(id); - // Just in case the hack was already aborted somehow. - if (cancel) { - this.#ramNet.finish(cancel); - this.#ns.kill(cancel.pid); - this.#running.delete(id); - ++this.#desyncs; // Just to keep track of how much we've lost keeping things prepped. - } - } - - // Then of course we just schedule and deploy a new batch. - this.scheduleBatches(1); - await this.deploy(); - this.log(); - } - } - } - } -} - -/* - Our poor "main" function isn't much more than a kickstart for our new batcher object. It's a bit weird having - it wedged between objects like this, but I wanted to have the new functionality up at the top since most of the - remaining code hasn't changed much. I'll comment the changes anyway. -*/ -/** @param {NS} ns */ -export async function main(ns) { - ns.disableLog("ALL"); - ns.tail(); - - /* - This commented out code is for a debugging tool that centralizes logs from the worker scripts into one place. - It's main advantage is the ability to write txt logs to file, which can be perused later to track down errors. - You can uncomment it if you'd like to see a live stream of workers finishing without flooding the terminal. - - If you do, make sure to search the file for -LOGGING and uncomment all relevant lines. - */ - // if (ns.isRunning("S4logHelper.js", "home")) ns.kill("S4logHelper.js", "home"); - // const logPort = ns.exec("S4logHelper.js", "home"); - // ns.atExit(() => ns.closeTail(logPort)); - - // Setup is mostly the same. - const dataPort = ns.getPortHandle(ns.pid); - dataPort.clear(); - let target = ns.args[0] ? ns.args[0] : "n00dles"; - while (true) { - const servers = getServers(ns, (server) => { - if (!ns.args[0]) target = checkTarget(ns, server, target, ns.fileExists("Formulas.exe", "home")); - copyScripts(ns, server, WORKERS, true); - return ns.hasRootAccess(server); - }); - const ramNet = new RamNet(ns, servers); - const metrics = new Metrics(ns, target); - // metrics.log = logPort; // Uncomment for -LOGGING. - if (!isPrepped(ns, target)) await prep(ns, metrics, ramNet); - ns.clearLog(); - ns.print("Optimizing. This may take a few seconds..."); - - // Optimizer has changed again. Back to being synchronous, since the performance is much better. - optimizePeriodic(ns, metrics, ramNet); - metrics.calculate(ns); - - // Create and run our batcher. - const batcher = new ContinuousBatcher(ns, metrics, ramNet); - await batcher.run(); - - /* - You might be wondering why I put this in a while loop and then just return here. The simple answer is that - it's because this is meant to be run in a loop, but I didn't implement the logic for it. This version of the - batcher is completely static once created. It sticks to a single greed value, and doesn't update if more - RAM becomes available. - - In a future version, you'd want some logic to allow the batcher to choose new targets, update its available RAM, - and create new batchers during runtime. For now, that's outside the scope of this guide, but consider this loop - as a sign of what could be. - */ - return; - } -} - -// The Job class, lean as it is, remains mostly unchanged. I got rid of the server argument since I wasn't using it -// and added a batch number instead. -class Job { - constructor(type, metrics, batch) { - this.type = type; - // this.end = metrics.ends[type]; - this.end = metrics.end; - this.time = metrics.times[type]; - this.target = metrics.target; - this.threads = metrics.threads[type]; - this.cost = this.threads * COSTS[type]; - this.server = "none"; - this.report = true; - this.port = metrics.port; - this.batch = batch; - - // The future is now. The status and id are used for interacting with the Deque and Map in our batcher class. - this.status = "active"; - this.id = type + batch; - // this.log = metrics.log; // -LOGGING - } -} - -// The only change to the metrics class is the calculate function skipping threadcounts if the server isn't prepped. -/** @param {NS} ns */ -class Metrics { - constructor(ns, server) { - this.target = server; - this.maxMoney = ns.getServerMaxMoney(server); - this.money = Math.max(ns.getServerMoneyAvailable(server), 1); - this.minSec = ns.getServerMinSecurityLevel(server); - this.sec = ns.getServerSecurityLevel(server); - this.prepped = isPrepped(ns, server); - this.chance = 0; - this.wTime = 0; - this.delay = 0; - this.spacer = 5; - this.greed = 0.01; - this.depth = 0; // The number of concurrent batches to run. Set by the optimizer. - - this.times = { hack: 0, weaken1: 0, grow: 0, weaken2: 0 }; - this.end = 0; // Slight change for the new timing. The old way in commented out in case I switch back later. - // this.ends = { hack: 0, weaken1: 0, grow: 0, weaken2: 0 }; - this.threads = { hack: 0, weaken1: 0, grow: 0, weaken2: 0 }; - - this.port = ns.pid; - } - - calculate(ns, greed = this.greed) { - const server = this.target; - const maxMoney = this.maxMoney; - this.money = ns.getServerMoneyAvailable(server); - this.sec = ns.getServerSecurityLevel(server); - this.wTime = ns.getWeakenTime(server); - this.times.weaken1 = this.wTime; - this.times.weaken2 = this.wTime; - this.times.hack = this.wTime / 4; - this.times.grow = this.wTime * 0.8; - // this.depth = this.wTime / this.spacer * 4; - - if (isPrepped(ns, server)) { // The only change. - const hPercent = ns.hackAnalyze(server); - const amount = maxMoney * greed; - const hThreads = Math.max(Math.floor(ns.hackAnalyzeThreads(server, amount)), 1); - const tGreed = hPercent * hThreads; - const gThreads = Math.ceil(ns.growthAnalyze(server, maxMoney / (maxMoney - maxMoney * tGreed)) * 1.01); - this.threads.weaken1 = Math.max(Math.ceil(hThreads * 0.002 / 0.05), 1); - this.threads.weaken2 = Math.max(Math.ceil(gThreads * 0.004 / 0.05), 1); - this.threads.hack = hThreads; - this.threads.grow = gThreads; - this.chance = ns.hackAnalyzeChance(server); - } - } -} - -// A few minor edits here. An unused "simulation" mode, and reserved RAM on home. -/** @param {NS} ns */ -class RamNet { - #blocks = []; - #minBlockSize = Infinity; - #maxBlockSize = 0; - #totalRam = 0; - #prepThreads = 0; - #maxRam = 0; - #index = new Map(); - - // Simulate mode ignores running scripts. Can be used to make calculations while the batcher is operating. - constructor(ns, servers, simulate = false) { - for (const server of servers) { - if (ns.hasRootAccess(server)) { - const maxRam = ns.getServerMaxRam(server); - // Save some extra ram on home. Clamp used ram to maxRam to prevent negative numbers. - const reserved = (server === "home") ? RESERVED_HOME_RAM : 0; - const used = Math.min((simulate ? 0 : ns.getServerUsedRam(server)) + reserved, maxRam); - const ram = maxRam - used; - if (maxRam > 0) { - const block = { server: server, ram: ram }; - this.#blocks.push(block); - if (ram < this.#minBlockSize) this.#minBlockSize = ram; - if (ram > this.#maxBlockSize) this.#maxBlockSize = ram; - this.#totalRam += ram; - this.#maxRam += maxRam; - this.#prepThreads += Math.floor(ram / 1.75); - } - } - } - this.#sort(); - this.#blocks.forEach((block, index) => this.#index.set(block.server, index)); - } - - #sort() { - this.#blocks.sort((x, y) => { - if (x.server === "home") return 1; - if (y.server === "home") return -1; - - return x.ram - y.ram; - }); - } - - get totalRam() { - return this.#totalRam; - } - - get maxRam() { - return this.#maxRam; - } - - get maxBlockSize() { - return this.#maxBlockSize; - } - - get prepThreads() { - return this.#prepThreads; - } - - getBlock(server) { - if (this.#index.has(server)) { - return this.#blocks[this.#index.get(server)]; - } else { - throw new Error(`Server ${server} not found in RamNet.`); - } - } - - assign(job) { - const block = this.#blocks.find(block => block.ram >= job.cost); - if (block) { - job.server = block.server; - block.ram -= job.cost; - this.#totalRam -= job.cost; - return true; - } else return false; - } - - finish(job) { - const block = this.getBlock(job.server); - block.ram += job.cost; - this.#totalRam += job.cost; - } - - cloneBlocks() { - return this.#blocks.map(block => ({ ...block })); - } - - printBlocks(ns) { - for (const block of this.#blocks) ns.print(block); - } - - testThreads(threadCosts) { - const pRam = this.cloneBlocks(); - let batches = 0; - let found = true; - while (found) { - for (const cost of threadCosts) { - found = false; - const block = pRam.find(block => block.ram >= cost); - if (block) { - block.ram -= cost; - found = true; - } else break; - } - if (found) batches++; - } - return batches; - } -} - -// Quite a bit has changed in this one. It's back to being synchronous, though it can still take a while. -/** - * @param {NS} ns - * @param {Metrics} metrics - * @param {RamNet} ramNet - */ -function optimizePeriodic(ns, metrics, ramNet) { - const maxThreads = ramNet.maxBlockSize / 1.75; - const maxMoney = metrics.maxMoney; - const hPercent = ns.hackAnalyze(metrics.target); - const wTime = ns.getWeakenTime(metrics.target); - - const minGreed = 0.001; - const maxSpacer = wTime; // This is more of an infinite loop safety net than anything. - const stepValue = 0.01; - let greed = 0.95; // Capping greed a bit lower. I don't have a compelling reason for this. - let spacer = metrics.spacer; // We'll be adjusting the spacer in low ram conditions to allow smaller depths. - - while (greed > minGreed && spacer < maxSpacer) { - // We calculate a max depth based on the spacer, then add one as a buffer. - const depth = Math.ceil(wTime / (4 * spacer)) + 1; - const amount = maxMoney * greed; - const hThreads = Math.max(Math.floor(ns.hackAnalyzeThreads(metrics.target, amount)), 1); - const tGreed = hPercent * hThreads; - const gThreads = Math.ceil(ns.growthAnalyze(metrics.target, maxMoney / (maxMoney - maxMoney * tGreed)) * 1.01); - if (Math.max(hThreads, gThreads) <= maxThreads) { - const wThreads1 = Math.max(Math.ceil(hThreads * 0.002 / 0.05), 1); - const wThreads2 = Math.max(Math.ceil(gThreads * 0.004 / 0.05), 1); - - const threadCosts = [hThreads * 1.7, wThreads1 * 1.75, gThreads * 1.75, wThreads2 * 1.75]; - - // Glad I kept these, they turned out to be useful after all. When trying to hit target depth, - // checking that there's actually enough theoretical ram to fit them is a massive boost to performance. - const totalCost = threadCosts.reduce((t, c) => t + c) * depth; - if (totalCost < ramNet.totalRam) { - // Double check that we can actually fit our threads into ram, then set our metrics and return. - const batchCount = ramNet.testThreads(threadCosts); - if (batchCount >= depth) { - metrics.spacer = spacer; - metrics.greed = greed; - metrics.depth = depth; - return - } - } - } - // await ns.sleep(0); // Uncomment and make the function async if you don't like the freeze on startup. - - // Decrement greed until we hit the minimum, then reset and increment spacer. We'll find a valid configuration eventually. - greed -= stepValue; - if (greed < minGreed && spacer < maxSpacer) { - greed = 0.99; - ++spacer; - } - } - throw new Error("Not enough ram to run even a single batch. Something has gone seriously wrong."); -} \ No newline at end of file diff --git a/local/path/home/S4logHelper.js b/local/path/home/S4logHelper.js deleted file mode 100644 index e1e8bdc..0000000 --- a/local/path/home/S4logHelper.js +++ /dev/null @@ -1,42 +0,0 @@ -/* - This script is completely unchanged from the last part. As a note, if you find that saves are taking a very long time - it may help to disable txt logging when you aren't actively debugging. The log files generated by this script - are quite big even when it's erasing the data on each new instance. -*/ - -/** @param {NS} ns */ -export async function main(ns) { - - const logFile = "S4log.txt"; - ns.clear(logFile); // Clear the previous log for each instance. - ns.disableLog("ALL"); - ns.tail(); - ns.moveTail(200, 200); // Move it out of the way so it doesn't cover up the controller. - const logPort = ns.getPortHandle(ns.pid); - logPort.clear(); - - // Pretty simple. Just wait until something writes to the log and save the info. - // Writes to its own console as well as a text file. - let max = 0; - let count = 0; - let total = 0; - let errors = 0; - while (true) { - await logPort.nextWrite(); - do { - const data = logPort.read(); - // if (data > max) max = data; - // if (data > 5) ++errors; - // total += data; - // ++count; - // ns.clearLog(); - // ns.print(`Max desync: ${max}`); - // ns.print(`Average desync: ${total / count}`); - // ns.print(`Errors: ${errors}`); - - // if (data.startsWith("WARN")) ns.print(data); - ns.print(data); - // ns.write(logFile, data); // Comment this line out to disable txt logging. - } while (!logPort.empty()); - } -} \ No newline at end of file diff --git a/local/path/home/S4tGrow.js b/local/path/home/S4tGrow.js deleted file mode 100644 index ad26af7..0000000 --- a/local/path/home/S4tGrow.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - A pretty big change this time. Well, big for workers anyway. I've tightened up the delay calculations - to be as perfect as I can get them. Full comments in weaken.js as usual. -*/ - -/** @param {NS} ns */ -export async function main(ns) { - const start = performance.now(); - const port = ns.getPortHandle(ns.pid); - const job = JSON.parse(ns.args[0]); - let tDelay = 0; - let delay = job.end - job.time - Date.now(); - if (delay < 0) { - ns.tprint(`WARN: Batch ${job.batch} ${job.type} was ${-delay}ms late. (${job.end})\n`); - tDelay = -delay - delay = 0; - } - const promise = ns.grow(job.target, { additionalMsec: delay }); - tDelay += performance.now() - start; - port.write(tDelay); - await promise; - - ns.atExit(() => { - const end = Date.now(); - if (job.report) ns.writePort(job.port, job.type + job.batch); - // Uncomment one of these if you want to log completed jobs. Make sure to uncomment the appropriate lines in the controller as well. - // ns.tprint(`Batch ${job.batch}: ${job.type} finished at ${end.toString().slice(-6)}/${Math.round(job.end).toString().slice(-6)}\n`); - // ns.writePort(job.log, `Batch ${job.batch}: ${job.type} finished at ${end.toString().slice(-6)}/${Math.round(job.end + tDelay).toString().slice(-6)}\n`); - }); -} \ No newline at end of file diff --git a/local/path/home/S4tHack.js b/local/path/home/S4tHack.js deleted file mode 100644 index a5ad51e..0000000 --- a/local/path/home/S4tHack.js +++ /dev/null @@ -1,30 +0,0 @@ -/* - A pretty big change this time. Well, big for workers anyway. I've tightened up the delay calculations - to be as perfect as I can get them. Full comments in weaken.js as usual. -*/ - -/** @param {NS} ns */ -export async function main(ns) { - const start = performance.now(); - const port = ns.getPortHandle(ns.pid); - const job = JSON.parse(ns.args[0]); - let tDelay = 0; - let delay = job.end - job.time - Date.now(); - if (delay < 0) { - ns.tprint(`WARN: Batch ${job.batch} ${job.type} was ${-delay}ms late. (${job.end})\n`); - tDelay = -delay - delay = 0; - } - const promise = ns.hack(job.target, { additionalMsec: delay }); - tDelay += performance.now() - start; - port.write(tDelay); - await promise; - - ns.atExit(() => { - const end = Date.now(); - if (job.report) ns.writePort(job.port, job.type + job.batch); - // Uncomment one of these if you want to log completed jobs. Make sure to uncomment the appropriate lines in the controller as well. - // ns.tprint(`Batch ${job.batch}: ${job.type} finished at ${end.toString().slice(-6)}/${Math.round(job.end).toString().slice(-6)}\n`); - // ns.writePort(job.log, `Batch ${job.batch}: ${job.type} finished at ${end.toString().slice(-6)}/${Math.round(job.end + tDelay).toString().slice(-6)}\n`); - }); -} \ No newline at end of file diff --git a/local/path/home/S4tWeaken.js b/local/path/home/S4tWeaken.js deleted file mode 100644 index b81ac60..0000000 --- a/local/path/home/S4tWeaken.js +++ /dev/null @@ -1,41 +0,0 @@ -/* - A pretty big change this time. Well, big for workers anyway. I've tightened up the delay calculations - to be as perfect as I can get them. Full comments in weaken.js as usual. -*/ - -/** @param {NS} ns */ -export async function main(ns) { - const start = performance.now(); - const port = ns.getPortHandle(ns.pid); // We have to define this here. You'll see why in a moment. - const job = JSON.parse(ns.args[0]); - let tDelay = 0; - let delay = job.end - job.time - Date.now(); - - // Don't report delay right away. - if (delay < 0) { - ns.tprint(`WARN: Batch ${job.batch} ${job.type} was ${-delay}ms late. (${job.end})\n`); - tDelay = -delay - delay = 0; - } - - // The actual function call can take some time, so instead of awaiting on it right away, we save the promise for later. - const promise = ns.weaken(job.target, { additionalMsec: delay }); - - // Then after calling the hack function, we calculate our final delay and report it to the controller. - tDelay += performance.now() - start; - - // The ns object is tied up by the promise, so invoking it now would cause a concurrency error. - // That's why we fetched this handle earlier. - port.write(tDelay); - - // Then we finally await the promise. This should give millisecond-accurate predictions for the end time of a job. - await promise; - - ns.atExit(() => { - const end = Date.now(); - if (job.report) ns.writePort(job.port, job.type + job.batch); - // Uncomment one of these if you want to log completed jobs. Make sure to uncomment the appropriate lines in the controller as well. - // ns.tprint(`Batch ${job.batch}: ${job.type} finished at ${end.toString().slice(-6)}/${Math.round(job.end).toString().slice(-6)}\n`); - // ns.writePort(job.log, `Batch ${job.batch}: ${job.type} finished at ${end.toString().slice(-6)}/${Math.round(job.end + tDelay).toString().slice(-6)}\n`); - }); -} \ No newline at end of file diff --git a/local/path/home/S4utils.js b/local/path/home/S4utils.js deleted file mode 100644 index e465b19..0000000 --- a/local/path/home/S4utils.js +++ /dev/null @@ -1,420 +0,0 @@ -/* - We've got a brand new class to look at, but the rest of the file remains unchanged. -*/ - -/** @param {NS} ns */ -export async function main(ns) { - ns.tprint("This is just a function library, it doesn't do anything."); -} - -/* - This is an overengineered abomination of a custom data structure. It is essentially a double-ended queue, - but also has a Map stapled to it, just in case we need to access items by id (we don't.) - - The idea is that it can fetch/peek items from the front or back with O(1) timing. This gets around the issue of - dynamic arrays taking O(n) time to shift, which is terrible behavior for very long queues like the one we're using. -*/ -export class Deque { - #capacity = 0; // The maximum length. - #length = 0; // The actual number of items in the queue - #front = 0; // The index of the "head" where data is read from the queue. - #deleted = 0; // The number of "dead" items in the queue. These occur when items are deleted by index. They are bad. - #elements; // An inner array to store the data. - #index = new Map(); // A hash table to track items by ID. Try not to delete items using this, it's bad. - - // Create a new queue with a specific capacity. - constructor(capacity) { - this.#capacity = capacity; - this.#elements = new Array(capacity); - } - - // You can also convert arrays. - static fromArray(array, overallocation = 0) { - const result = new Deque(array.length + overallocation); - array.forEach(item => result.push(item)); - return result; - } - - // Deleted items don't count towards length, but they still take up space in the array until they can be cleared. - // Seriously, don't use the delete function unless it's absolutely necessary. - get size() { - return this.#length - this.#deleted; - } - - isEmpty() { - return this.#length - this.#deleted === 0; - } - - // Again, "deleted" items still count towards this. Use caution. - isFull() { - return this.#length === this.#capacity; - } - - // The "tail" where data is typically written to. - // Unlike the front, which points at the first piece of data, this point at the first empty slot. - get #back() { - return (this.#front + this.#length) % this.#capacity; - } - - // Push a new element into the queue. - push(value) { - if (this.isFull()) { - throw new Error("The deque is full. You cannot add more items."); - } - this.#elements[this.#back] = value; - this.#index.set(value.id, this.#back); - ++this.#length; - } - - // Pop an item off the back of the queue. - pop() { - while (!this.isEmpty()) { - --this.#length; - const item = this.#elements[this.#back]; - this.#elements[this.#back] = undefined; // Free up the item for garbage collection. - this.#index.delete(item.id); // Don't confuse index.delete() with this.delete() - if (item.status !== "deleted") return item; // Clear any "deleted" items we encounter. - else --this.#deleted; // If you needed another reason to avoid deleting by ID, this breaks the O(1) time complexity. - } - throw new Error("The deque is empty. You cannot delete any items."); - } - - // Shift an item off the front of the queue. This is the main method for accessing data. - shift() { - while (!this.isEmpty()) { - // Our pointer already knows exactly where the front of the queue is. This is much faster than the array equivalent. - const item = this.#elements[this.#front]; - this.#elements[this.#front] = undefined; - this.#index.delete(item.id); - - // Move the head up and wrap around if we reach the end of the array. This is essentially a circular buffer. - this.#front = (this.#front + 1) % this.#capacity; - --this.#length; - if (item.status !== "deleted") return item; - else --this.#deleted; - } - throw new Error("The deque is empty. You cannot delete any items."); - } - - // Place an item at the front of the queue. Slightly slower than pushing, but still faster than doing it on an array. - unshift(value) { - if (this.isFull()) { - throw new Error("The deque is full. You cannot add more items."); - } - this.#front = (this.#front - 1 + this.#capacity) % this.#capacity; - this.#elements[this.#front] = value; - this.#index.set(value.id, this.#front); - ++this.#length; - } - - // Peeking at the front is pretty quick, since the head is already looking at it. We just have to clear those pesky "deleted" items first. - peekFront() { - if (this.isEmpty()) { - throw new Error("The deque is empty. You cannot peek."); - } - - while (this.#elements[this.#front].status === "deleted") { - this.#index.delete(this.#elements[this.#front]?.id); - this.#elements[this.#front] = undefined; - this.#front = (this.#front + 1) % this.#capacity; - --this.#deleted; - --this.#length; - - if (this.isEmpty()) { - throw new Error("The deque is empty. You cannot peek."); - } - } - return this.#elements[this.#front]; - } - - // Peeking at the back is ever so slightly slower, since we need to recalculate the pointer. - // It's a tradeoff for the faster push function, and it's a very slight difference either way. - peekBack() { - if (this.isEmpty()) { - throw new Error("The deque is empty. You cannot peek."); - } - - let back = (this.#front + this.#length - 1) % this.#capacity; - while (this.#elements[back].status === "deleted") { - this.#index.delete(this.#elements[back].id); - this.#elements[back] = undefined; - back = (back - 1 + this.#capacity) % this.#capacity; - --this.#deleted; - --this.#length; - - if (this.isEmpty()) { - throw new Error("The deque is empty. You cannot peek."); - } - } - - return this.#elements[back]; - } - - // Fill the queue with a single value. - fill(value) { - while (!this.isFull()) { - this.push(value); - } - } - - // Empty the whole queue. - clear() { - while (!this.isEmpty()) { - this.pop(); - } - } - - // Check if an ID exists. - exists(id) { - return this.#index.has(id); - } - - // Fetch an item by ID - get(id) { - let pos = this.#index.get(id); - return pos !== undefined ? this.#elements[pos] : undefined; - } - - // DON'T - delete(id) { - let item = this.get(id); - if (item !== undefined) { - item.status = "deleted"; - ++this.#deleted; - return item; - } else { - throw new Error("Item not found in the deque."); - } - } -} - -// The recursive server navigation algorithm. The lambda predicate determines which servers to add to the final list. -// You can also plug other functions into the lambda to perform other tasks that check all servers at the same time. -/** @param {NS} ns */ -export function getServers(ns, lambdaCondition = () => true, hostname = "home", servers = [], visited = []) { - if (visited.includes(hostname)) return; - visited.push(hostname); - if (lambdaCondition(hostname)) servers.push(hostname); - const connectedNodes = ns.scan(hostname); - if (hostname !== "home") connectedNodes.shift(); - for (const node of connectedNodes) getServers(ns, lambdaCondition, node, servers, visited); - return servers; -} - -// Here are a couple of my own getServers modules. -// This one finds the best target for hacking. It tries to balance expected return with time taken. -/** @param {NS} ns */ -export function checkTarget(ns, server, target = "n00dles", forms = false) { - if (!ns.hasRootAccess(server)) return target; - const player = ns.getPlayer(); - const serverSim = ns.getServer(server); - const pSim = ns.getServer(target); - let previousScore; - let currentScore; - if (serverSim.requiredHackingSkill <= player.skills.hacking / (forms ? 1 : 2)) { - if (forms) { - serverSim.hackDifficulty = serverSim.minDifficulty; - pSim.hackDifficulty = pSim.minDifficulty; - previousScore = pSim.moneyMax / ns.formulas.hacking.weakenTime(pSim, player) * ns.formulas.hacking.hackChance(pSim, player); - currentScore = serverSim.moneyMax / ns.formulas.hacking.weakenTime(serverSim, player) * ns.formulas.hacking.hackChance(serverSim, player); - } else { - const weight = (serv) => { - // Calculate the difference between max and available money - let diff = serv.moneyMax - serv.moneyAvailable; - - // Calculate the scaling factor as the ratio of the difference to the max money - // The constant here is just an adjustment to fine tune the influence of the scaling factor - let scalingFactor = diff / serv.moneyMax * 0.95; - - // Adjust the weight based on the difference, applying the scaling penalty - return (serv.moneyMax / serv.minDifficulty) * (1 - scalingFactor); - } - previousScore = weight(pSim) - currentScore = weight(serverSim) - } - if (currentScore > previousScore) target = server; - } - return target; -} - -// A simple function for copying a list of scripts to a server. -/** @param {NS} ns */ -export function copyScripts(ns, server, scripts, overwrite = false) { - for (const script of scripts) { - if ((!ns.fileExists(script, server) || overwrite) && ns.hasRootAccess(server)) { - ns.scp(script, server); - } - } -} - -// A generic function to check that a given server is prepped. Mostly just a convenience. -export function isPrepped(ns, server) { - const tolerance = 0.0001; - const maxMoney = ns.getServerMaxMoney(server); - const money = ns.getServerMoneyAvailable(server); - const minSec = ns.getServerMinSecurityLevel(server); - const sec = ns.getServerSecurityLevel(server); - const secFix = Math.abs(sec - minSec) < tolerance; - return (money === maxMoney && secFix) ? true : false; -} - -/* - This prep function isn't part of the tutorial, but the rest of the code wouldn't work without it. - I don't make any guarantees, but I've been using it and it's worked well enough. I'll comment it anyway. - The prep strategy uses a modified proto-batching technique, which will be covered in part 2. -*/ -/** @param {NS} ns */ -export async function prep(ns, values, ramNet) { - const maxMoney = values.maxMoney; - const minSec = values.minSec; - let money = values.money; - let sec = values.sec; - while (!isPrepped(ns, values.target)) { - const wTime = ns.getWeakenTime(values.target); - const gTime = wTime * 0.8; - const dataPort = ns.getPortHandle(ns.pid); - dataPort.clear(); - - const pRam = ramNet.cloneBlocks(); - const maxThreads = Math.floor(ramNet.maxBlockSize / 1.75); - const totalThreads = ramNet.prepThreads; - let wThreads1 = 0; - let wThreads2 = 0; - let gThreads = 0; - let batchCount = 1; - let script, mode; - /* - Modes: - 0: Security only - 1: Money only - 2: One shot - */ - - if (money < maxMoney) { - gThreads = Math.ceil(ns.growthAnalyze(values.target, maxMoney / money)); - wThreads2 = Math.ceil(ns.growthAnalyzeSecurity(gThreads) / 0.05); - } - if (sec > minSec) { - wThreads1 = Math.ceil((sec - minSec) * 20); - if (!(wThreads1 + wThreads2 + gThreads <= totalThreads && gThreads <= maxThreads)) { - gThreads = 0; - wThreads2 = 0; - batchCount = Math.ceil(wThreads1 / totalThreads); - if (batchCount > 1) wThreads1 = totalThreads; - mode = 0; - } else mode = 2; - } else if (gThreads > maxThreads || gThreads + wThreads2 > totalThreads) { - mode = 1; - const oldG = gThreads; - wThreads2 = Math.max(Math.floor(totalThreads / 13.5), 1); - gThreads = Math.floor(wThreads2 * 12.5); - batchCount = Math.ceil(oldG / gThreads); - } else mode = 2; - - // Big buffer here, since all the previous calculations can take a while. One second should be more than enough. - const wEnd1 = Date.now() + wTime + 1000; - const gEnd = wEnd1 + values.spacer; - const wEnd2 = gEnd + values.spacer; - - // "metrics" here is basically a mock Job object. Again, this is just an artifact of repurposed old code. - const metrics = { - batch: "prep", - target: values.target, - type: "none", - time: 0, - end: 0, - port: ns.pid, - log: values.log, - report: false - }; - - // Actually assigning threads. We actually allow grow threads to be spread out in mode 1. - // This is because we don't mind if the effect is a bit reduced from higher security unlike a normal batcher. - // We're not trying to grow a specific amount, we're trying to grow as much as possible. - for (const block of pRam) { - while (block.ram >= 1.75) { - const bMax = Math.floor(block.ram / 1.75) - let threads = 0; - if (wThreads1 > 0) { - script = "S4tWeaken.js"; - metrics.type = "pWeaken1"; - metrics.time = wTime; - metrics.end = wEnd1; - threads = Math.min(wThreads1, bMax); - if (wThreads2 === 0 && wThreads1 - threads <= 0) metrics.report = true; - wThreads1 -= threads; - } else if (wThreads2 > 0) { - script = "S4tWeaken.js"; - metrics.type = "pWeaken2"; - metrics.time = wTime; - metrics.end = wEnd2; - threads = Math.min(wThreads2, bMax); - if (wThreads2 - threads === 0) metrics.report = true; - wThreads2 -= threads; - } else if (gThreads > 0 && mode === 1) { - script = "S4tGrow.js"; - metrics.type = "pGrow"; - metrics.time = gTime; - metrics.end = gEnd; - threads = Math.min(gThreads, bMax); - metrics.report = false; - gThreads -= threads; - } else if (gThreads > 0 && bMax >= gThreads) { - script = "S4tGrow.js"; - metrics.type = "pGrow"; - metrics.time = gTime; - metrics.end = gEnd; - threads = gThreads; - metrics.report = false; - gThreads = 0; - } else break; - metrics.server = block.server; - const pid = ns.exec(script, block.server, { threads: threads, temporary: true }, JSON.stringify(metrics)); - if (!pid) throw new Error("Unable to assign all jobs."); - block.ram -= 1.75 * threads; - } - } - - // Fancy UI stuff to update you on progress. - const tEnd = ((mode === 0 ? wEnd1 : wEnd2) - Date.now()) * batchCount + Date.now(); - const timer = setInterval(() => { - ns.clearLog(); - switch (mode) { - case 0: - ns.print(`Weakening security on ${values.target}...`); - break; - case 1: - ns.print(`Maximizing money on ${values.target}...`); - break; - case 2: - ns.print(`Finalizing preparation on ${values.target}...`); - } - ns.print(`Security: +${ns.formatNumber(sec - minSec, 3)}`); - ns.print(`Money: \$${ns.formatNumber(money, 2)}/${ns.formatNumber(maxMoney, 2)}`); - const time = tEnd - Date.now(); - ns.print(`Estimated time remaining: ${ns.tFormat(time)}`); - ns.print(`~${batchCount} ${(batchCount === 1) ? "batch" : "batches"}.`); - }, 200); - ns.atExit(() => clearInterval(timer)); - - // Wait for the last weaken to finish. - do await dataPort.nextWrite(); while (!dataPort.read().startsWith("pWeaken")); - clearInterval(timer); - await ns.sleep(100); - - money = ns.getServerMoneyAvailable(values.target); - sec = ns.getServerSecurityLevel(values.target); - } - return true; -} - -// I don't actually use this anywhere it the code. It's a debugging tool that I use to test the runtimes of functions. -export function benchmark(lambda) { - let result = 0; - for (let i = 0; i <= 1000; ++i) { - const start = performance.now(); - lambda(i); - result += performance.now() - start; - } - return result / 1000; -} \ No newline at end of file diff --git a/local/path/home/ServerRouteList.txt b/local/path/home/ServerRouteList.txt index fd616ee..8a0de16 100644 --- a/local/path/home/ServerRouteList.txt +++ b/local/path/home/ServerRouteList.txt @@ -1 +1 @@ -{"home":{"n00dles":{},"foodnstuff":{},"sigma-cosmetics":{"zer0":{"omega-net":{"the-hub":{},"netlink":{"rothman-uni":{"rho-construction":{"aerocorp":{"unitalife":{"icarus":{"infocomm":{"titan-labs":{"fulcrumtech":{"omnitek":{},"4sigma":{"powerhouse-fitness":{}}}}}},"solaris":{"nova-med":{"run4theh111z":{}}}}}}},"catalyst":{}}}},"max-hardware":{}},"joesguns":{},"hong-fang-tea":{},"harakiri-sushi":{"nectar-net":{"neo-net":{"avmnite-02h":{}},"phantasy":{}},"CSEC":{"silver-helix":{"computek":{"zb-institute":{"lexo-corp":{"global-pharm":{"omnia":{"defcomm":{"zb-def":{"microdyne":{"vitalife":{"kuai-gong":{},".":{"b-and-a":{},"blade":{"fulcrumassets":{}},"nwo":{"The-Cave":{}},"clarkinc":{"ecorp":{},"megacorp":{}}}}}}}},"deltaone":{"univ-energy":{"taiyang-digital":{"applied-energetics":{"stormtech":{},"helios":{}}}},"zeus-med":{}}}},"alpha-ent":{"galactic-cyber":{}}}},"johnson-ortho":{"summit-uni":{"millenium-fitness":{}},"I.I.I.I":{"aevum-police":{"snap-fitness":{}}}},"crush-fitness":{"syscore":{}}}}},"iron-gym":{},"darkweb":{},"pserv-0":{},"pserv-1":{},"pserv-2":{},"pserv-3":{},"pserv-4":{},"pserv-5":{},"pserv-6":{},"pserv-7":{},"pserv-8":{},"pserv-9":{},"pserv-10":{},"pserv-11":{},"pserv-12":{},"pserv-13":{},"pserv-14":{},"pserv-15":{},"pserv-16":{},"pserv-17":{},"pserv-18":{},"pserv-19":{},"pserv-20":{},"pserv-21":{},"pserv-22":{},"pserv-23":{},"pserv-24":{}}} \ No newline at end of file +{"home":{"n00dles":{"nectar-net":{"neo-net":{"computek":{"summit-uni":{}}}}},"foodnstuff":{"zer0":{"silver-helix":{"the-hub":{"rothman-uni":{"millenium-fitness":{}}},"netlink":{"zb-institute":{"alpha-ent":{"galactic-cyber":{}}}},"johnson-ortho":{},"crush-fitness":{}}},"max-hardware":{"phantasy":{},"omega-net":{"avmnite-02h":{"syscore":{"rho-construction":{},"aevum-police":{"global-pharm":{"omnia":{"defcomm":{},"solaris":{}}}}},"catalyst":{},"I.I.I.I":{"lexo-corp":{"aerocorp":{"deltaone":{"icarus":{"infocomm":{"run4theh111z":{"helios":{}}},"taiyang-digital":{"titan-labs":{"vitalife":{"omnitek":{"nwo":{},"powerhouse-fitness":{"fulcrumassets":{},"The-Cave":{}}}}}},"zb-def":{"microdyne":{}}},"zeus-med":{}},"unitalife":{"univ-energy":{"nova-med":{"applied-energetics":{"fulcrumtech":{"4sigma":{},".":{"b-and-a":{"ecorp":{}}}},"stormtech":{"kuai-gong":{"blade":{},"clarkinc":{"megacorp":{}}}}}}}}},"snap-fitness":{}}}}}}},"sigma-cosmetics":{"CSEC":{}},"joesguns":{},"hong-fang-tea":{},"harakiri-sushi":{},"iron-gym":{},"darkweb":{},"pserv-01":{},"pserv-02":{},"pserv-03":{},"pserv-04":{},"pserv-05":{},"pserv-06":{},"pserv-07":{},"pserv-08":{},"pserv-09":{},"pserv-10":{},"pserv-11":{},"pserv-12":{},"pserv-13":{},"pserv-14":{},"pserv-15":{},"pserv-16":{},"pserv-17":{},"pserv-18":{},"pserv-19":{},"pserv-20":{},"pserv-21":{},"pserv-22":{},"pserv-23":{},"pserv-24":{},"pserv-25":{}}} \ No newline at end of file diff --git a/local/path/home/Serverlist.js b/local/path/home/Serverlist.js deleted file mode 100644 index 8b94568..0000000 --- a/local/path/home/Serverlist.js +++ /dev/null @@ -1,42 +0,0 @@ -import { getCracks, scanServerList, findBestTarget, crackingAndRooting, copyAndRunScript, purchaseAndUpgradeServers } from "/RamsesUtils.js"; - -/** @param {NS} ns */ -export async function main(ns) { - const funnyScript = ["batch.js", "Ramses-grow.js", "Ramses-weaken.js", "Ramses-hack.js"]; - //write function to purchase scripts from tor network and rerun getCracks() then recrack and reroot - let cracks = {}; - cracks = getCracks(ns); - let maxPorts = Object.keys(cracks).length; - scanServerList(ns); - let manualTargetOverride = ""; - if (ns.getHackingLevel() < 200) { - manualTargetOverride = "n00dles"; - }; - - findBestTarget(ns, 999, maxPorts, ns.getHackingLevel(), manualTargetOverride); - let bestTarget = ns.read("bestTarget.txt") - - ns.tprint("Best Target: " + bestTarget); - ns.tprint(Object.keys(JSON.parse(ns.read("serverList.txt"))).length); - crackingAndRooting(ns, cracks, funnyScript, true); - ns.exec(funnyScript[0], "home", 1, JSON.parse(bestTarget).serverName, 500, true); - let reset = ns.args[0]; - ns.print(reset); - if (reset === true) { - ns.tprint("reset === true") - findBestTarget(ns, 999, maxPorts, ns.getHackingLevel(), manualTargetOverride); - let serverList = JSON.parse(ns.read("serverList.txt")); - for (const [name, entry] of Object.entries(serverList)) { - - copyAndRunScript(ns, funnyScript, name); - } - } - /*let serverListForFiles = JSON.parse(ns.read("serverList.txt")); - for (const [name2, entry2] of Object.entries(serverListForFiles)) { - ns.tprint(name2 + " Files: " + entry2.serverFiles) - }*/ - //await ns.sleep(500000); - await purchaseAndUpgradeServers(ns); - -} - diff --git a/local/path/home/StartControllers.js b/local/path/home/StartControllers.js deleted file mode 100644 index dc0e8e8..0000000 --- a/local/path/home/StartControllers.js +++ /dev/null @@ -1,5 +0,0 @@ -import { getCracks, scanServerList, findBestTarget, crackingAndRooting, copyAndRunScript, runControllerOnPserv } from "/RamsesUtils.js"; -/** @param {NS} ns */ -export async function main(ns) { - await runControllerOnPserv(ns) -} \ No newline at end of file diff --git a/local/path/home/Startup.js b/local/path/home/Startup.js deleted file mode 100644 index d87191f..0000000 --- a/local/path/home/Startup.js +++ /dev/null @@ -1,14 +0,0 @@ -/** @param {NS} ns */ -export async function main(ns) { - let player = null; - player = ns.getPlayer(); - ns.tprint(player) - /* - while (true) { - - - ns.singularity. - - } -*/ -} \ No newline at end of file diff --git a/local/path/home/algorithm.js b/local/path/home/algorithm.js new file mode 100644 index 0000000..bd1002e --- /dev/null +++ b/local/path/home/algorithm.js @@ -0,0 +1,72 @@ +/** @param {NS} ns */ +export async function main(ns) { + const sNode = ns.args[0]; // target server + + //logs + ns.disableLog("getServerSecurityLevel"); + ns.disableLog("getServerMoneyAvailable"); + + //server info + const nMinSec = ns.getServerMinSecurityLevel(sNode); + const nMaxCash = ns.getServerMaxMoney(sNode); + while (true) { + + //timestamp + let currentDate = new Date(); + let ntimeStamp = currentDate.toLocaleTimeString('sw-SV') + " -"; + + const nCurrSec = ns.getServerSecurityLevel(sNode); + const nCurrCash = ns.getServerMoneyAvailable(sNode); + + ns.print(ntimeStamp + "---------------------------------------------------------------"); + ns.print("Cash: " + (Math.floor(nCurrCash * 1000) / 1000) + " / " + nMaxCash); + ns.print("Security: " + (Math.floor(nCurrSec * 1000) / 1000) + " / " + nMinSec); + + if (nCurrSec > (nMinSec + 1)) { + + //Calculate estimate time of completion + let nOffset = ns.getWeakenTime(sNode); + let nWeakTime = new Date(currentDate.getTime() + nOffset); + let sWeakTime = nWeakTime.toLocaleTimeString('sw-SV'); + + //Print estimated time of completion + ns.print("Weakening " + sNode + " Estimated complete at " + sWeakTime); + + //run weaken + await ns.weaken(sNode); + //ns.spawn(sWeakenScript, {threads: 1, spawnDelay: 0}); + ns.print("-------------------------------------------------------------------------"); + } + else if (nCurrCash < (nMaxCash * 0.9)) { + + //Calculate estimate time of completion + let nOffset = ns.getGrowTime(sNode); + let nGrowTime = new Date(currentDate.getTime() + nOffset); + let sGrowTime = nGrowTime.toLocaleTimeString('sw-SV'); + + //Print estimated time of completion + ns.print("Growing " + sNode + " Estimated complete at " + sGrowTime); + + //run grow + await ns.grow(sNode); + ns.print("-------------------------------------------------------------------------"); + } + else { + + + //Calculate estimate time of completion + let nOffset = ns.getHackTime(sNode); + let nHackTime = new Date(currentDate.getTime() + nOffset); + let sHackTime = nHackTime.toLocaleTimeString('sw-SV'); + + + //Print estimated time of completion + ns.print("Hacking " + sNode + " Estimated complete at " + sHackTime); + + //run hack + await ns.hack(sNode); + //await ns.singularity.manualHack(); + ns.print("-------------------------------------------------------------------------"); + } + } +} \ No newline at end of file diff --git a/local/path/home/ascii/detective.txt b/local/path/home/ascii/detective.txt new file mode 100644 index 0000000..bd744a5 --- /dev/null +++ b/local/path/home/ascii/detective.txt @@ -0,0 +1,82 @@ +$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$X$$$$$XX$$XXXXXXX$XXXXXXxxxxXXXXXxxxxXxXXXXXxxxxxXX$XXXXXXXXXXXXXX$$$$$$$$$$$XX$$$$$$$$$$$$$$$$$$$$$$$$X$$$$$$$$$X$$$$$ +$$$$$$$$$$$$$$$$$$$$XXXXX$$XX$XXXXXXXXX$$XXXXXX$XXXXXXXxxxxXXxXXxxxxxxxxxXXxxxxxxXXXXXXXXXXXXXXXXXXXX$XX$$$$$$$$$$$$$$$$$$$$$$$$$$$$XXX$$$$$$$$xx$$$$$ +$$$XXXX$XX$$X$$$$$$$$$$XX$XXX$$XXXXXXXXX$XXXXXXXXXXXXXXXxxxXXxXXxxxxxxxxxXXxxxx+xxxXXXXXxXXXXXXXXXXXXXXXXXXXXXXXXXX$XX$$$$$X$$XXX$$$XX$$$$$$$$$xxX$$$$ +XXX..;xX$XX$XX$$$$$$$$$XXXXXX$$XX$XXXXXXXXXXXXXXXXXXXxXxxxxxxxXXxxxxxxxxXXXxxxx+xxxxXXXXxXXXXXXXXXXXXXXXXXXXXXXXXXXXXX$X$XXX$$XXX$$$$$$$$$$$$$$xXX$$$$ +X$X:..xXXXX$XX$XX$$$$$$XXXXXX$$XXXXXXXXXXXXXXXXXXXXXXXXxxxxxx+xxxxxxxxxxxxxxxxx;x+xXXXXXxXXXXXXXXXXXXXXXXXXXXXXXXXXXXX$XXXXXXXXXX$$$XXXXX$$$$$$XxX$$$$ +$$XX$XXXXXXXXXXXXX$$XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXxxxxx++xxxxxxxxxxxxxxxxx;x+++XXXXxXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX$$XXXXXXXX$$$$$$XXX$X$$ +$$$X$XX$XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXxxxxxxxxxxxxxxxxxxxxxxx;x;++XXXXxXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXxXXXXXXXXXX+XXXXXX$$$$$$xXX$X$$ +XX$X$$X$XXX$XXX$XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXxxxxxxxxxxxx+xxxxxXxxxxx;x+;;XXXXxXXXXXXXXXxXXXX+;++xXXXXXXXXXXXxXXXXXXXXXX+xxxXXX$$X$$XXxXXxX$ +$$$$$$X$XXX$$XX$XXXX$XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXxxxxxxxXXxxx+xx+XXXXXx+x++;;;XXxxxXXXXXXXXXxXXXXx++++XxXXXXXXXXXxXXXXXXXXXXx;xxXXX$$XX$$X+xxXxX +$X$X$$X$XXX$$XX$XXXXXXXXXXXXXXXXXXXXXXXXXXX+;:xXXXXXXXXxxxxxxxxXx+++xx+XXXXXx++++;;+XXxxxXXXXxXXxX+xXXX+;;;+xxxxXXXxxXXxXXXxXXXXXXx;xxXXXX$XX$$XxxXXxX +$$$$$$$$$XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXxxxX$x;+++++xxxxxxxxxx++++x++xXXXX++++++;xXxxxxXXxxXxxxxxxXXX+;;;;xxxxxxxXxXXxxxxxXXXxXXx+xxxxXX$XX$$XxxXXxX +$$$$$$$$$XXXXXXXXXXXXXXXXXXXXXXXXxXXXXXXXXxX$$$$$$xxx++;+;;;;xxx++++xx+xXXXXx++++;;;xxxx+XXxxxxxxxxxXXXx;;:;xx+xxxxxxXXxxxxxXXXxXXxxxxXXXX$XX$XxxxxxXX +$$$$$$$$$XXXXXXXXXXXXXXXXXXXXXXXXxXXXXXXXxXX$$$$$$$$Xxx;:..:X+xx+xxxxx;+XXXXx+++;;::+xxx+XXxxxxxxxxxxxxxxx;xxx++xxxx+xxx+xxxXXXxXX+;+xxxXX$XXXXXxxxXXx +X$XXXX$$$XXXXXXXXXXXXXXXXXXXXXXXXxXxxXXX+xX$$$$$$$$$$$$Xx;;X+xxx+++xxx;xXXXxx+++;;;;+xxxxxxxxxxxx+xxxxx+++;xx++;++xx+xxx+xxxxXXxXX+:xxxXxX$XXx++xXXXX+ +XXXXXX$$$XXXXXXXXXXXXXXXXXXXXXXXXxxxxXXxXXX$$$$$$$$$$$$$$XX+$xxx+x+xxx+xxXxxx++++++++xxxxxxxxxx++x+xxx+++;;+++;;+++x+xxx+xxxxXX+Xxx+Xxxxxxx+++xXXXxxx+ +$$$$$$$$$XXXXXXXXXXXXXXXXXXXXxX++xxxxxxXxX$$$$$$$$$$$$$$$$XX$xxxxxxxxx+xxxxxxxxx+xxx+xxx+xxxxxx+++++x+++;;::;++:;;++++xxx+xxxXXx+x+XXXxx+;+xxXXx++;++; +$$$$$$$$$$XXXXXXXXXXXXXXXXXXXxXX+xx+++xxX$$$$$$$$$$$$$$$$$$xXxXxxxxxxxxxxxxxxxxx+xxx+xxx+xxx+++++++++++: :;+++xxx+xxxXXxxx+Xx+++xxXXx+;;;;;++x +$$$$$$$$$$$$XXXXXXXXXXXXXXXXXxXXXXx++;;;XX$$$$$$$$$$$$$$$$$XXxxxxxxxxxxxxxxxx+x++xx++xx+;++++++;;;;+++;: .;+++x+x+xxxxXx+++XxxXXXx+;;:;::;xXx+ +$$$$XX$$XXX$XXXXXXXXXXXXXXXXXxXXXXxXX+++x+xX$$$$$$$$$$$$$$$$x+xxxxxxxxx+xxxxx+++++++;+++;+++++;;;;;;+;;; ..;;+;x++++xxxxxxXx+XXx++;;;::+Xx+x$x+ +$$$$$X$$X$$$XXXXXXXXXXXXXXXXXxXXXXXXXX$xxx+xxX$$$$$$$$$$$$$$xXxx++xxxxx+xxxxx+++++++;+++;+;+++;;;;;;;;;:: ::;++;x++++xxxxxxxx;xX+;;;+xXXXX+;x$xx +XXX$$XX$X$$$XXXXxxXXXXXXXXXXXXXXXXXXXX$X$XxxxxxX$$$$$$$$$$$$$$$Xxx+;x+x+xxxxx;++; :+++;;;;;;;;::;;;;;;;. :::;++;+++xxxxxxx+;x+xX+xXXXXXXXXXxxXx+ +XXXX$XXXX$$XXXXXxxXXXXXXXXXXXXXXXx;$$X$$$$$$XXxXxX$$$$$$$$$$$$$$XXXxx+x+xxxxx;+++. :;+;:;;;;:::::;;;;;;;;;;+;:;;:++++xxxxx++;xX+;Xxx+;+xXXXXXx++x++X; +XXXXXXXXXXXXXXXXXxxXXXXxXXXXXXXXx;xXX$X$$$XXXX$$$XxXXX$$$$$$$$$$Xxx+x+x+xxxxx++++ .;;;:::::...::;;;;;;;;:+++;;+;++++x+;;;+x++xxXxx:;++xxXXXx+;;x:;X; +XXXXXXx+XXXXXXXXXx+XXXxxXXXXXxx;+:++$X$XXX$XXXXX$$$$$$$$$$$$$XXxxxx+xxx+xxxxx++;; :;:..:.. ..::;;;;;;++++x++++;++++++++++xXXxxXXx;+xxxxxXXx;+XX;:X: +XXXXX+;::;xXXXXXXxxXXXxxXXXXX:;++:x+$X$XXXXXXXXXXX$XX$$$Xxxxxxxxxxxxxxxxx++++++;;;;:::::.. ..:;;;;;;++++xx+++;+++++xxxxxxxXxxxXX;+x+;.:xXxx++X+;X; +XXXXXx+x;+xXXXXXXX+XXXXxXXx+:;++x;x$$X$XXXXXXXXXXXXXXX$xx+x+xxxxxxxxx+xxx++++++;;;;:;:. ..::;;;+;+;++xx++x;++xxxxxxxxxxXXXXXX;.;+; :x+. .;X; +XXXXXXX+xxxXXXXXXX+XXxx;;x+ ;+x+X$X$$$XXXXXXXXXXXXXX$Xx+xxxxx+x++++;+xx++;.++;;;;::.. ..::;;;;+++++Xx++x;xxxxxxxxXxXXXXXXXx;.:+: ;:: :X+ +$XXXXxx;+xxXXXXXXx+;+++;++;++;+xXxX$$X$$$$XXXXXXX$XXX$$$Xx+xxx+++++++;+xx++++++;;;:::::. .::;;;;++++++Xx++++xxxxxxxxXXXXXXXXXx;..+; . ;Xx +XXXXXxx;++xXXXx++++:;::;:++xxxxxXXX$$XX$$$$$XXXXXXXX$$$$$XXx+xxx+++++++xx++++;::;;;;;:::. .. ..::;;;+;+;++++XXx++xxxxxxxxxXXXXxXx;;:::.+; .;: :+Xx +XXXXXxx+++xX+;++;;::::;;xxxXxXXXXXX$$$XXXX$$$XXXXXXX$$$$$$XxX+x+++++xxxxx+;;;;++;;;;;:;:::::.:::;;;;;;;+++++XXx++xxxxxxxxxx+;::++:;++: ++ ;++xXXx+XX +xxXXXxXXXXxxXx++x+xx+++xXxXXXxx++;x$$$$XXXXX$$$$$$XX$$$$$$$$xX+++++++xxxx+;;+++++;;;;;;;;;;;:;:;;+;+++++++++XXx++xxxxxx;. ++:+xXxxxxx;;++ ;XXXXXXxXX +;+:;++XXXxxXXXXxxXxXxXXXXxxx;;+xX$$$$$$$XXXXXX$$$XXX$$$$$$$$XX$Xx;+++xxx++;+++++++;+;;;+;;;+;;;;;++++;+;++++XXxx+xxxxx+;++xx+xXXXxxxx+;xx; +XXXXxxxXX +:; +XXxXXXXXXxXXXXXXXXXX+x$$$X$XxX$X$$XXXXXX$$$$XX$$$$$$$$$xxXxX+++++++++++++x+;;;;;+;++++;+++;;+++;++++;;xXxxxxxxxxxxXXxX+++xx+++x++xx+.:+XXXXXXxXX +:;+++;xXXXXXX$$XXX$$$$XXX$XX$$Xx;;xX$$$$$XXXX$$$$X$X$$$$$$$$$X$xXxx++++++x++++xx+;;;;;+;+++x;;;+;+++++++++;;xx+:;xxxxXxxxxXx+++xx++++x+xxx;;xXXXXXXXXX +:+x+xxxxXXXXXX$XXX$$$$$XXX$$$$XXxXxXX$$$$$XX$$$$$$X$$$$$$$$$$$$X$xX++++++x++++++;;;;;;+++++x+++++++x++++:: .X;.;xxxXXxxxxXxx++xx++;+xxXxx;;xXXXXXXXXX +:+xx++xXXX$XX$$$XX$$$$$XXx$$$X$$$Xx+x$$$$$$XX$$$$$X$$$$$$$$$$$$XXXX+++++++++++;;;;;;;;+++++x++++++xxxxx; . :X+.;xxxXXxxxxxx+++xx;;;+xxXXX++xXXXXXXXXX +xxXxx+XXX$$$$$$$$X$$$$$$$X$$$$$XXX$$XX$$$$$$XX$$$$XX$$$$$$$$$$XXXXX;;+;;;+x+xx;;;;;;;;;++++xx++++xxxxxXX+;: ;X+:;xxxxXxxxxxxx++xx;;;+xxXXXx+xXXXXXXXXX +xxxxxxXX$$$$$$$$$X$$$$$$$$$$$$$XX$X$$$$$$$$$$$$$$$$X$$$$$$$$$$XXX$$;:;;;;+x+xx;:::::;;;;;;+xx+++++xxxxXXXx+:+Xx:;xxxxXXxxxx+;::;x;;;;+xXXXxxxXXXXXXXXX +xxXxxXXXXX$$$$$$$XX$$$$$$$$$$$$XXXX$$$$$$$$$$$$$$$$X$$$$$$$$$XXXXXXX;;;;;+xxxx;..::::;;::;+xx++++++x+xXXx++;xXX;+xxxxXXxxxxx+; :x;;x++xXXXXxXXXXXXXXXX +xxXXXXXXXX$$$$$$$X$$$$$$$$$$$$$$XX$$$$$$$$$$$$$$$$$$$$$$$$$$$XXxXXX$+;:::;xxxx;.. ..:;;;;:;xx++++++xXXXXXXx+XXXx+xxxxxXxxxxx;; ;x+xxxxXXXXXxXXXXXXXXX$ +.$XXXxX$XXX$$$$$$X$$$$$$X$$$$X$XXX$$$$$$$$$$$$$$$$$$$$$$$$$$$$X$X$XX+ :::;xxxx;....:;: ::xx+;;+xXXXXXXXXXXXXXxxxxxXXXxxxxx++++xxxxx+xxXXXxXX$XXXXXXX +xX$XXXXXXXxX$$$$$X$$$$$$$$$$$$X$XXX$$$$$$$$$$$$$$$$$$$$$$$$$$XXXX$XXx .: +xxx; ++::. ;;xx+;;+xXXXXXXXXXXXXXXXXxxXXXXx+xx++++xxxx++xXXXXXXX$$XXXXXX + :XXXXXX$XxX$$$$$XX$$$$$X$$$$$$$XX$X$$$$$$$$$$$$$$$$$$$$$$$$$$$XXX$XXx: +xxx+. +x;:: ;;xx++:xXXXXXXXXXXXXXXXxxXXXXXxxxxXxxxxxx++++xXXXXXXX$$XXXXXX +;:XXXX$X$$XxX$$$$$$$$$$$$$$$$$$$$X$$$$$$$$$$$$$$$$$$$$$$$$$$$X$XXXXXXX. +xxx+;+xxx+:. +xxxx+;xXXXXXXXXXXXXXXXxxxxxXxxxxxXxxxXxxxxxxxXXXXXXX$$XXXXXX +$+XXX$$$$$$XxX$$$$$$$$$$$$$$$$$$$XXX$$$$$$$$$$$$$$$$$$$$$$$$$$$XXX$$X$;...+xxx+;xxx+x;: ;+xxx+;XXxXXXXXXXXXXXXXXxxxxxx+;+xX$XXXXXXXXXxXXXXXX$XX$X$$X$ +$XXX$$$$$$$XXXX$$$$$$$$$$$$$$$$$$X$$X$$$$$$$$$$$$$$$$$$$$$$$$$$$XX$$XX+:..+xxx+;xxx+x+. ;+xxx+;XXxXXXXXXXXXXXXXXxxXXXXXX$XXXXXXXXXXXXxXXXXXX$XXXXXX$X +$$X$$XXXXxXX$$X$$$$$$$$$$$$$$$$$$X$$$$$$$$$$$$XX$$$$$$$$$$$$$$X$X$$$$$Xx;.+xxxx+xxxxxx;;;++xxx+;XxxXXXXXXXXXXXXXXXXXXXxxXXX$X$XXXXXXXXxXXXXXXxXX+xxxxX +$xXXxxxxXX$$$X$X$$$$$$$$$$$$$$$$$$$$$X$$$$X$$$X;X$$$$$$$$$$$$$$$X$$$$$$X$+;xxxx+xxxxxx+;++xxxx++xxXXXXXXXXXXXXXXXXXXXXXXXX$XXX$$$$X$XXxxxxxxXXXXxX$$$$ +$XxxXX$$x++xXX++xxx+X$$$$$$$$$$$$XX$$XX$$$XX$$$$x$$$$$$$$$$$$$$$X$$$XXXxxX+xxxxx+xx+xxx+++xxxxxxxxxXXXXXXXXXXXXXX$X$$XXXXX$$$$$XXXXXX$xXXXXXXX$$$$$$$$ +$XxX$X+++;;xXXXXx++xXX;xxXX;+;;:+;x++x+++X$::;:;;;;::x$$$$$$$$$$$$$XX$X+$X+xxxxxxxx;+xx+;+xxxxxxxxxXXXXX$XXXXXXXXX$$$XXXXXx$$$$$$$$$XXxXXXX$$XXXXX$$$$ +XX$$$Xx+X$X$XXx+xXXXxx++xX+x+.:::;;;::;+x. :xxXXXx+$$$$$$$$$$$$Xxx+XXXXxxxxxxx+;;+x+;;xXxXx++xxXXXXX$$XXXXXX$$$$$$$XXXX$$$$$$$X$xXxXXXXXXXXXXX$$$$ +X$$$$$$$$$XxxxXXXX$xXXXXx+xx+;:;;+;;;;x;:+;++xxXxx+++XXx$$$$$$x+++xxXXxxXXx+x+++xx++xxxxxxxXXXXxxxxXXXXXX$XXXXXXXX$$$$$$$$$$$$$$$XXXXXxXXXX$$XXXXX$$$$ +$$$$X$$$$$XX$$$$$XxX$$XXxxxxxxxX$XxxxXx+;;x+;;;++++XXxXx$$$$Xx++;:::::::+xxXXXXXxxxxxXXXx;+xxxXXXXXXXXXXX$XXXXXXX$$$$$$$XXX$$$$$$XXXXXXX$$$$$$$$$X$$$$ +$$XX$$$$$$$$$$$$xx$$$$XXXXXxXXX$XXXXXXXxxx;++xXXXXXX$$XXXx+;;;:.. :xXXXXxxxxx+xxxxxxXXXXXXXx++: ;XX+xX$XXXXXXXXXXXXXXXXX$$$$$$$XxxXXXxxXXXX$$$$$$$$$ +$X$$$$$$$$$$$$$XX$X$$$$$$$$XXXX$$XXXXX$XXXXxxxxxxXXx+:...::;;++xxxxXXXXXXX++xxxxxxXxXxxxx++++++xxXXXXXXXXXx+..:;;xxXX+:.+++XX$$$$XXxxxxXXxxXXXxXXXXXXX +$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$XX$XXXXx+;;;+xxxXXXXXXX$XXXXXXxXXXXXXxxxxxxxx++;:... .:;+xXX++XXXXXXX$$XXXxx++:+xxXxXXXXXXXXXXxXXxxxXxxXXXXXX +$$$$$$$$$$$$$$$$$$$$$$$$$$$X$$$$$$$$$X$$X+xXXX$$$$$$$$$$$$$$$XxXXxXXXXXXx::::;;:;;;;. . :xXXXxxx+xx++xXxXX$$$$$$$$XxxXX$$XXX$$$$$$$$$$$$$ +$$$$X$$$$$$$$$$$$$$$$$$$$X$$$$XX$$$$$X$$$$X$$$$$$X$$$$$$$$$$$$$XxXXXXX$$xxxxXxx+x;+++xxx;x +:: ... ;XXXXXX$$XXxXXXXXXXxxXXXX$$XXXX$$XX$$$$$$$$$$XX +$$$$xxXXXX:xXX$$$$$$$$$$$$$$$$$$$$$$$$$X$$$$$$$$$$$$$$$$$$$$$$$$$$X$xx+.:. ;;;;;;::. . .. :;::xxxx;++XXX$X$$$$$$$$XX+xX+xXXXX$$$$$$$$$$$Xx$X$x$ +$$$$xXXXXX;+XXX$$$$$$$$$$$$$$$$$$$$$$$$$$$XX$$X$$$$X$$$$$$$$$$$$$Xx;;+;:::;;+xXXXxXXXXxxxxXXXXXX+x;+x+;+;;;;;..+xxxxXXXXXXXX$$$XXXXxXXXXX$X$$$$$$X+x+: +$$$$XXXXXXXXXXX$$$$$$$$$$$$$$$$$$$$$$$$$$$XX$$$$$$X$$$$$$$$$$$$$$X$x+++xx+++++; +;xxx+:xx;:::..xxxxxxXXXXXXXX$X$$$$$$$$$$$xxXXXXXXXXXXxX$XX$$$$$$$$$XX +$$$$$$XXXXXXXXX$$$$$$$$$$$$$$$$$$$X$$$$$$$XX$$$$$$$$$$$$$$$$$$$$$X$::::;++xxXX; ;+XxXXxXx; .+xxxx;xxXXXXXXXXXXxXXXxxxx++xXXxXXXXX$XXX$$$$$$$$$$Xxx+:: +$X$$$XXXXXXXXXX$$$$$$$$$$$$$$$$$$XX$$$$$$$XX$$$$$$$$$$$$$$$$$$$$$XX+;;:...:;:xx:+xxxXXXXXXXXxxxxxXXxXXXXXXXXXx::;x;.::;x+xXXXXXX$XxxXXXXXX$$X$$$XX+;xX +$XXXxXxXX$$$xxX$$$$$$$$$$$$$$$$$$$X$$$$$$$$X$$$$$$$$$$$$$$$$$$$$$X$xxxXXxx;;;XXXxxXXXXXXXXXXXXXXXXXXXXXXXXXX$$$$XXx+:+++xXXX:XXXXXXX;xXX$$$$$$XX$$$xxX +$$$$X$XXxxX$$X$$$$$$$$$$$$$$$$$$$$$$$$$$$$$X$$$$$$$$$$$$$$$$$$$$$X$XXXXXXXxxXXxXXXXx+;+XXXXXXXXXXXXXXXXXXXXX$$$$$$$$$$X: +XXXX$x.+X$$$X$xx$$$$$$$x;;xx +XXxxX$x+++Xxxx$$$$$$$$$$$$$$$$$$$$$$$$$$$$$X$$$$$$$$$$$$$$$$$$$$$X$XXXXxxXXXXxxXxxXxxxxx+:.;xXxXXXXXXXXXXXXXX$$$$$$$$$$$$$xX$$XXX$X$Xx$$$$$$$$$$$+Xx;x +Xx+;X$$XX$XxxX$$$$$$$$$$$$$$$$$$$$$$$XXX$$$XXX$$$$$$$$$$$$$$$$$$$XXXXXXXXXXXXXxxxXXxxXX : .x+XXXXXXXXXXX$X$X$$$$$$$$$$$$$XX$$$$$$$$$$$$$$$$$$$$$x +XXxx$$XXXX$XxX$$$$$X$$$$$$$$$$$$$$$X$XXXX$$XXXX$$$$$$$$$$$$$$$$$$$$$XXXXXXXXXX;:+xxxx+++++++ ; .:;+ :x;;;+xXX$$$$$$$$$$$$$$$$$$$$X+$$$$$$$$$$$$$$$$$$ +Xxx$$XXXXXX$xX$$$$$$$$$$$$$$$$$$$$$$$$$$X$$$$$$$$$$$$$$$$$$$$$$$$$$$XXXXXXXXXXx+XX++:..:::;;:. . ..:. ..+ :.;xXX$$$$$$X$$$$$$$$$XXX$$$$$$$$$$$$$$$$$$ +$X$$Xx++xXXXXX$$$$$$$$$$$$$$$$$$$$$$$$$XXX$$X$X$$$$$$$$$$$$$$$$$$$$$XxXXxxXXXXx;X+;Xx++: ;+:: ::;;::;;::.:++xXXXX+X$$$$$XXXXXX$$XXX$XXX$$XX$XX$XXX +xx$$$X$X$X$XX$$$$$$$X$$$$$$$$$$$$$$$$$$$X$$$$$$$$$$$$$$$$$$$$$$$$$$$$XXxxxxxxxXXXxXXX+;xx+: ;+xx+.;:++;+++;;;;:;X;.;::.++;+XXX+xX$$$$XXXXxxxxxxxx +X$X$XXXxX$$$X$$$$$$$$$$$$$$$$$$$$$$$$$$$X$$$X$$$$$$$$$$$$$$$$$$$$$$$$xxxxxXxXXxXxXXXXxxxx . .:::++ ++xX:;XX+ ;;;;;;;x$x++X$XxxXXXXXxxxxxxxxXxXXX +$$xx++;+x$X$X$$$$$$$$$$$$$$$$$$$$$$$$$$$X$$$$$$$$$$$$$$$$$$$$$$$$$$$$XXXxxXXxXXxXXXXXXXx;:: .;$XxXXXXXx;;:::.:::::::::;;;++++xxXXXXX$$$$$$$$$$$$$ +$XXXXXxxX$$x$$$$$$$$$$$$$$$$$$$$$$$$$$$$$X$$$$$$$$$$$$$$$$$$$$$$$$$$$XxXXXXxXXXXXXXxx+x:+. : . . :..;Xx;::;++xx+ ::. ...:;x$$$$$$$$$$$$$$$$$$$ +$$$$$XxX$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$xXXxxxxxXXx.XXXXx++x ;x++xx:xXXxX+. :+xX$XX$$$$$$$$$$$$$$$X$XXXXxXX$$$$$$$$ +$$$$XXXX$$$XX$$$$$$$$$$$$$$$$$$$$$$$$$$$$$X$X$$$$$$$$$$$$$$$$$$$$$$$$$xXxXxxx:++ +XXXXXXXX+. .+XXXXXXXX$$$$X:x+++;xxXx +;xxXXX$$x+XxX$X$$$$$$$$$$$X +$$$$$xX$X$$X$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$XX$X$$$$$$$$$$$$$$$$$$$$$$$$X$$$X$$XXXXXXXXXXXXX: . .+XXXXX$XXXXXX$X$$X;;;+XXxXXXXXXXXXXx++xXXXXXXXXXXXXX$ +$$X$XXXXX$XXX$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$XXX$$$$$$$$$$$$$$$$$$$$$$$$$XXXXXXXXXXXXXXXXXXX+: .+xXXX$XXx+++;;+;x::+ . .+:X;+xXXX$$$$$$$XXXXXX$$ +$$$$$$$$X$XX$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$X$$$$$$$$$$$$$$$$$$$$$$$$$$$XXXXXXXXXXXXXX$$XXXXx: ;xXxXX$$X+;: ;;;;+. .:+xXXxXXX$$$XXXXX$XXXXXXXXX +XXXX$$$$X$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$X$$$$$$$$$$$$$$$$$$$$$$$$$XXXXX$$$X$$XX$$$$$$X$+:.:;. ;xx+XX$$Xx++;; .;:x++.+x .+xXXXXXXXX$$$$$$$$$$$$$$ +$$$$$$$$XXXXX$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$XXXXXXXXXXxXX$XXxx+;:+.;; +Xxx:.:+$$$$X+. .;+xXxXXXxXX$$$XXXXxxxxXXXXXXXXXXX$ +XXXX$X$$X$XX$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$XXXXXXxx; XXXxXXXxx..++XX$$+;x .x+XXX$$X+. ..:;;+;.; .;;++xX$X$$$$$$$$$$XX \ No newline at end of file diff --git a/local/path/home/ascii/detective2.txt b/local/path/home/ascii/detective2.txt new file mode 100644 index 0000000..a4f152d --- /dev/null +++ b/local/path/home/ascii/detective2.txt @@ -0,0 +1,55 @@ +$$$$$$$$$$$$$$$$$$$$X$$X$X$XXXXXXXXXXxxXXXXxxxxXXXxxxxXXXXXXXXXXXXX$$$$$XX$$$$$$$$$$$$$$$X$$$$$$X$$$ +$$X$X$$$$$$$$$$XXXXXXXXXXXXXXXXXXXXxXxxXXXxxxxxxxXxxxxxXXXXXXXXXXXXXXXXXXXXXXX$$$$$$$X$$XX$$$$$xx$$$ +Xx..xXXXX$$$$$$XXXX$$XXXXXXXXXXXXXXxXxxxxxxxxxxxxXxx+xxxXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX$$$X$$$$$XX$$$ +$XXXXXX$XXXX$XXXXXXXXXXXXXXXXXXXXXXXXxxx+xxxxxxxxxxx+x+xXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX$$$$XXX$$ +$$$$XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXxxxxxxxxxxxxxxx++++XXXXXXXXXXXXXxXXXXXXXXXXXXXXXXXxXXX$$$$XXX$$ +$$$$$$X$XXXXX$XXXXXXXXXXXXXXXXXXXXXXXxxxXXxxxx+xXXXx++;+XxxXXXXXXxXXX+++XXXXXXXXXXXXXXX+xxXX$X$XxxxX +$X$$$$XX$XXXXXXXXXXXXXXXXXXXx++xXXXXXxxxxxx++x+xXXX+++;+xxxXXXxXxxxXX;;;xxxXxxXXxXxXXXX+xxXX$X$XxXXX +$$$$$$XXXXXXXXXXXXXXXXXXXXXXxX$$Xx+++;;++xx++x+xXXX++;++xxxxxxxxxxxXx;::x+xxxxXxxxxXXXXxxxXX$XXXxxxX +$$$$$$XXXXXXXXXXXXXXXXXXXXXxX$$$$$$Xx;::x++xxx++XXx++;;:xxxxxxxxxxxxxx++x++xxxxxxxxXXXx++xxX$XXXxxXx +XXXX$$XXXXXXXXXXXXXXXXxXxXxxX$$$$$$$$Xxxxx+x+xx+xxxx+;++xxxxxxx+xxxxx+;++;;+++xxxxxXxXx+xxxXx++xXXX+ +$$$$$$XXXXXXXXXXXXXXx+xxxxxX$$$$$$$$$$$XXxxxxxxxxxxxx+xx+xxxxxx++++++;;:::;;++xxxxxxx++xXx++xxxx++++ +$$$$$$$XXXXXXXXXXXXXXXx;;;xX$$$$$$$$$$$XXxxxxxxxxxxxx+xx+x+++++;;+++; :;++x+xxxX++xxxxxx;;;;;xx +$$XX$$X$XXXXXXXXXXXXXXXXXx++XX$$$$$$$$$$xxxxxxx+xxx++++++++++++;;;+;;. :;+++++xxxxxxXx+;;;+x+xX+ +XX$XX$$$XXXxXXXXXXXXXXXXX$$XxxxX$$$$$$$$XXx+++x+xxx+++..;++;;+;;;;;;;: .:;++++xxxx++xx++xXXXXxxX+ +XXX$XX$XXXXxXXXXXXXXXX+x$X$$$XXXxX$$$$$$$$$XXx++xxx+++ :;;;;;:::;;;;;;;+;;;+++xxx++x++x+++XXXX+x+x+ +XXXXXXXXXXXxXXXxXXXXx+;xX$$$XXXX$XX$$$$$$XXxx++xxxx++; .;:::...:;;;;;;++++++++++;+xxxxx;+xxxX+;x+++ +XXXx+;+XXXXxXXXxXXX+++;xX$XXXXXXXXXX$Xxxxxxxxxxxx++++;;;::. ..:;;;+++x++++++xxxxxxxXx+++:;x+:;x+; +XXXXXXxXXXXXxXXx+;..;x+X$$XXXXXXXXXXXxxxxxxxxx+xx++++;;;:. .:;;;+++x+++xxxxxxxXXXXX:.+ ;;. ++ +XXXx+;xxXXXx+++++++++xXX$$$$XXXXXXX$$Xxx++++++;xx++++;;::: .::;;++++xx+xxxxxxxXXXXXx;.+ . +x +XXXx+++xXx++;::;+xxxXXXX$XXX$XXXXXX$$$Xxx+x+++xxx+;;;;;;;::.:..:;;;;;+++Xx+xxxxxxxxxx+::;.; .;.;xxx +xxxxXXxxX+xxx++xXXXxx++X$$XXXX$$$XX$$$$$Xx++++xxx;;+++;;;;;;;:;;;;++++++Xxxxxxx;:+;;xXxx+;+: :XXXxxX +: .+XXxXXXxXXXXXx++xX$XX$$$XXXX$$XX$$$$$XXxx+++x++++++;;;+;;+;;;;++;++++xxxxxxxxxxxxxXxx++x+ ;XXXXxX +:;;+xXXXX$XXX$$XX$X$x++XX$$XXX$$$X$$$$$$$XXX++++++++x+;;;+;+++;++++;++;.++;xxxxxxxx+xx++x+xx:+XXXXXX +:++xXXXX$$$X$$$$XX$$$XxxX$$$$X$$$X$$$$$$$XXXx+++++++;;;;;++++++++xxx+. :+:xxXXxxxx++x;;+xXx+xXXXXXX +xxx+XX$$$$$X$$$$X$$$XX$$X$$$$$$$$$$$$$$$$$XXx;+;+x++;;;;;;++xx++xxxxX+;.++:xxxXxxxx++x;;+xXXxxXXXXXX +xxxxXX$$$$$XX$$$$$$$$XX$$$$$$$$$$$$$$$$$$$XXX+;;;xx+;:::;;::+x++++xxXXx;xx;xxxXxxx+;:x;;+xXXxxXXXXXX +xXXXXXX$$$$$X$$$$$$$$XX$$$$$$$$$$$$$$$$$$XXXX+:::+xx;. .:;;:;x++++xXXXX+XXxxxxXXxx+;.x+xxxXXxXXXXXXX +;XXXXXxX$$$XX$$$$$$$$XX$$$$$$$$$$$$$$$$$$XXXXx ::+xx:.::: .;x+;+XXXXXXXXXxxxxXXxxx++xx+++XXXXX$XXXX +:+XXX$Xx$$$$X$$$$$$$$$X$$$$$$$$$$$$$$$$$$$XXXX; ;xx;.++:. :+x+;xXXXXXXXXXXxxXXxxxXxxxx+++XXXXX$XXXX +x+XX$$$XX$$$$$$$$$$$$$X$$$$$$$$$$$$$$$$$$$XX$Xx..;xx+xxx+. :xxx;XXXXXXXXXXXxxxx++xXXXXXXXxXXXXX$XXXX +$XX$$$$XXX$$$$$$$$$$$$XXX$$$$$$$$$$$$$$$$$XX$$X;.;xx+xxxx:.;xxx;XxXXXXXXXXXxxXXXXXXXXXXXXxXXXXXXXxXX +$XXxxxXX$X$$$$$$$$$$$$$$$$$$$$X+$$$$$$$$$X$X$$$X+;xxxxxxx+;+xxx+XxXXXXXXXXXXXXxXXX$$$XXX$X++++xxxXXX +XXxXXXxxXXxxxXX$$$$XX$$$$X$$XXXX+XX$$$$$$$$$$XXxx+xxx+xxxx;+xxxxxxXXXXXXXXXX$XXXXXX$$X$$XXXXXXX$X$$$ +XX$Xx+xXXXxxxXx++x+;::;+;;+x:.:+xx+xX$$$$$$$XXxxXXxxxxx++x+;xxx++xXXX$XXXXXX$$XXXX$$$$$$XXXXX$XXX$$$ +X$$$$$$XxxXXXXXXx+x;:;+;;+;;;;+xx++xXX$$$x++xXxxxx+x+xx++xxxxxXxxXXXX$$XXXXX$$$$$X$$$$XXXXXXXXX$$$$$ +$$$$$$$$$$$XX$$XXxxX$$XXXxxxx+xx++XXXX$X+;:::::;XXXXxxxxxXX++x++xxXXXXXXXXXX$$$$XX$$$$XXXXX$$$$$$$$$ +$X$$$$$$$$XX$$$$$$XX$XXXXXXXx+xx+x++;;;;;;++xXXXXx+xxxxxxxxxxxxxxXXxxXXx++++xx++x+xXX$XxxxxxXXXXXXXX +$$$$$$$$$$$$$$$$$$$$$$$$X$XXxxxxxXXXX$$$XXXXXXXXx+++++;;;. ::;;;+xxXX+x+xXXXXXXXXxXXXX$X+xXXXXXXXX +$$$$$$$$$$$$$$$$$$$XX$$$X$$$X$$$$$$$$$$$$XXXXXXXxxxx;;:;;;++ ;; .. :xXXX$XXXXXXXxXX$$XXX$XX$$$$$$XX +$$XxXXx:XX$$$$$$$$$$$$$$$$$$X$$$$$$$$$$$$$$$Xxx;;:;+++;;:;:..:. ::;;+;+xxXXXXXXXX+XxXXXXX$$$$$XXXxx +$$XXXXXXXX$$$$$$$$$$$$$$$$$$X$$$$$$$$$$$$$$XX++x+++x;;+xx:+;:::+xxxXXXXXXXXXXX$$$XxXXXXXXxX$$$$$$$$X +$$$XXXXXXX$$$$$$$$$$$$$$$$$$X$$$$$$$$$$$$$$Xx::.:;+x:.+xXXXx++xxxxxXXXXXxxxx;+XXxxxXXXX$X$$$$$$$x;x; +$XXXXX$XXX$$$$$$$$$$$$X$$$$$XX$$$$$$$$$$$$$XX++xx+;xxxxxXXXXXXXXXXXXXXXX$Xxxx++++XxxXXXXxXX$$$$$$X;; +$XXXXxx$XX$$$$$$$$$$$$$$$$$$XX$$$$$$$$$$$$$XXXXXXXxXxXX+::x+:+XXXXXXXXXX$$$$$$$xxX$$XxxXXXXX$$$$x++. +Xxx$$$$xX$$$$$$$$$$$$$$$$X$$XXX$$$$$$$$$$$$$XXXXXXXXxxXxXX::.. :xXXXXXXXXX$$$$$$$$$$X$$$$$$$$$$$$$$X +XXXXXXXXX$$$$$$$$$$$$$$$XXX$$XX$$$$$$$$$$$$$$XXXXXXX++xxx++++: :::;;;+xX$$$$$$$$$$$XXXX$$$$$$$$$$$ +$$$X+xXXX$$$$$$$$$$$$$$$$$XX$XX$$$$$$$$$$$$$$XxXxXXXxxx++:. +;: .:;::::.;+XX$x$$$$$XXXXXX$$$$$$X$XX +XXX+xxX$X$$$$$$$$$$$$$$$$$XX$$$$$$$$$$$$$$$$$$xXXXXxXXxXXxx+: +x+ :+:;;.:..x+++;xXXXXX$$$XXXxxxxx +XXX++x$$X$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$XXXXXXXXXXxx+;: :++:;;;+;.;:;;;;;;+++xxxxxxXXXX$$$$$ +$XXXXX$X$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$XXXXXXXXXXx+;::. ::;;++++++xx+xx++xxxxX$$$$$$$$$$$$$ +$$XXXX$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$XXXxXxx+xXXXXx; .xXXXXXXXx+;;;+X;+;xXX$XXXX$XX$$$$XX +$$$XXX$$$$$$$$$$$$$$$$$$$$$$$X$$$$$$$$$$$$$$$$$X$XXXXXXXXXXX:. :xXXXXXXXXXX+;:xxxxxXXxXxxXXXXXXXXXX +$$$$$$XX$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$XXXXXXXXXX$XXx: ;xXX$x;. .:;::. :+xxxXXXXX$$$XX$$X +XX$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$XXXXX$$XX$$$$Xx;.: :+;X$$X+; :;;+++: :xXX$$XX$$$$$$$$ +$XXX$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$XXxxXX++XXXXx;.xxx;::.xxX$Xx;::;:x+;::;+xXXXXX$$$$XX \ No newline at end of file diff --git a/local/path/home/ascii/detective3.txt b/local/path/home/ascii/detective3.txt new file mode 100644 index 0000000..9f6d021 --- /dev/null +++ b/local/path/home/ascii/detective3.txt @@ -0,0 +1,54 @@ +▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▓▒▒▓▓▓▒▒▒▒▒▒▒▓▒▒▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▓▓▓ +▓▒ ▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▓▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▒▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ +▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ +▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░▒▓▓▓▓▓▓▓▓▓▓▓▓▓▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▓▓▓▓▓▓▓▓▓▓▓▓ +▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▓▓▒▒▒▒▒▒▓▓▓▒▒▒░░▓▒▒▓▓▓▓▓▓▒▓▓▓▒░░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▓▓▓▓▓▓▒▒▒▓ +▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒░▒▒▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▓▓▓▒▒░░░▒▒▒▓▓▓▒▓▒▒▒▓▓░░░▒▒▒▓▒▒▓▓▒▓▒▓▓▓▓▒▒▒▓▓▓▓▓▓▒▓▓▓ +▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▓▓▓▓▒▒░░░░░▒▒▒▒▒▒▒▒▓▓▓▒░░░▒▒▒▒▒▒▒▒▒▒▒▒▓▒░ ▒▒▒▒▒▒▓▒▒▒▒▓▓▓▓▒▒▒▓▓▓▓▓▓▒▒▒▓ +▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▓▓▓▓▓▓▓▓▒░ ▒▒▒▒▒▒▒░▓▓▒▒▒░░ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓▓▒░▒▒▒▓▓▓▓▓▒▒▓▒ +▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▓▒▓▒▒▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░▒░░░▒▒▒▒▒▒▒▓▒▓▒░▒▒▒▓▒▒▒▒▓▓▓▒ +▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░░ ░░░░▒▒▒▒▒▒▒▒▒▒▓▒▒░▒▒▒▒░░▒░ +▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒░░░▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░░░░░ ░░▒▒▒▒▒▒▓▒▒▒▒▒▒▒▒░░░░░▒▒ +▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒░▒▒░▒░░░░░░░░░░░ ░░░▒▒▒▒▒▒▒▒▒▓▒▒░░░░▒▒▒▓▒ +▓▓▓▓▓▓▓▓▓▓▓▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▓▓▓▓▓▓▓▓▓▓▓▒▒░▒▒▒▒▒▒▒░░ ░▒░░░░░░░░░░░ ░░░▒▒▒▒▒▒▒▒▒▒▒░▒▓▓▓▓▒▒▓▒ +▓▓▓▓▓▓▓▓▓▓▓▒▓▓▓▓▓▓▓▓▓▓▒▒▓▓▓▓▓▓▓▓▒▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒░░ ░░░░░ ░░░░░░░░░░░░░░▒▒▒▒░▒▒░▒▒░▒▓▓▓▓▒▒▒▒░ +▓▓▓▓▓▓▓▓▓▓▓▒▓▓▓▒▓▓▓▓▒░░▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒░░ ░ ░░░░░░░▒░░░▒▒▒░░░░▒▒▒▒▒░▒▒▒▒▓▒░▒▒░░ +▓▓▓▒░░░▓▓▓▓▒▓▓▓▒▓▓▓░░▒░▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░░░ ░░░░░░▒▒░░▒░▒▒▒▒▒▒▒▒▓▒░▒▒ ░▒░ ░▒▒░ +▓▓▓▓▓▓▒▓▓▓▓▓▒▓▓▒▒░ ░▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒░▒▒░░░░░░░ ░░░░░▒▒▒▒░▒▒▒▒▒▒▒▓▓▓▓▓ ░ ░░ ░▒ +▓▓▓▒▒░▒▒▓▓▓▒▒░░░░░░░▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒░▒▒▒░░░░░ ░░░░▒▒▒▒▒▒▒▒▒▒▒▒▓▓▓▓▓▒░ ░ ░▒ +▓▓▓▒▒░▒▒▓▒▒░░ ░░▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒░░░░░░░░ ░░░░░░▒▒▓▒▒▒▒▒▒▒▒▒▒▒▒▒ ░ ░ ░ ░▒▒▒ +▒▒▒▒▓▓▒▒▓▒▒▒▒▒▒▒▓▓▓▒▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒░▒▒▒▒░░░▒▒░░░░░░░ ░░░░░░░▒▒▒▓▒▒▒▒▒▒░ ░░░▒▓▒▒▒░▒ ▓▓▓▒▒▓ + ░▓▓▒▓▓▓▒▓▓▓▓▓▒░▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒░▒▒▒░░▒▒▒░░░░░░░░░░░░░░░▒▒░▒▒▒▒▒▒▒▒▒▒▒▒▒▓▒▒▒░▒░ ░▓▓▓▓▒▓ + ░░▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░▒▒▒▒▒▒░░░░░░▒░░░░░▒░░▒░ ▒▒░▒▒▒▒▒▒▒▒▒▒▒░░▒▒▒▒ ▒▓▓▓▓▓▓ + ▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒░░░░▒▒░░░░░░░░░▒▒░▒▒▒▒▒▒ ░ ▒▒▓▓▒▒▒▒░▒▒░░▒▒▓▒░▒▓▓▓▓▓▓ +▒▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒░░░░▒▒▒░░░░░░░▒▒▒▒▒▒▒▒▒▓▒░ ░▒ ▒▒▒▓▒▒▒▒▒▒▒░░▒▒▓▓▒▒▓▓▓▓▓▓ +▒▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░▒▒▒░ ░░ ▒▒▒▒▒▒▒▒▓▓▒░▒▒░▒▒▒▓▒▒▒▒░ ▒░░░▒▓▓▒▒▓▓▓▓▓▓ +▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒ ▒▒▒░ ░░ ░▒▒▒▒▒▒▓▓▓▓▒▓▓▒▒▒▒▓▓▒▒▒░ ▒░▒▒▒▓▓▒▓▓▓▓▓▓▓ +░▓▓▓▓▓▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒ ░▒▒ ░▒░░▒▓▓▓▓▓▓▓▓▓▒▒▒▒▓▓▒▒▒▒░▒▒▒▒▒▓▓▓▓▓▓▓▓▓▓ + ▒▓▓▓▓▓▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░ ░▒▒░ ░░ ▒▒▒░▒▓▓▓▓▓▓▓▓▓▓▒▒▓▓▒▒▒▓▒▒▒▒▒▒░▓▓▓▓▓▓▓▓▓▓ +▒░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒ ░▒▒░▒▒▒▒ ▒▒▒░▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▓▓▓▓▓▓▓▒▓▓▓▓▓▓▓▓▓▓ +▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░ ░▒▒░▒▒▒▒ ░▒▒▒░▓▒▓▓▓▓▓▓▓▓▓▒▒▓▓▓▓▓▓▓▓▓▓▓▓▒▓▓▓▓▓▓▓▒▓▓ +▓▓▓▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒░▒▒▒▒▒▒▒░░░▒▒▒░▓▒▓▓▓▓▓▓▓▓▓▓▓▓▒▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▓▓▓ +▓▓▒▓▓▓▒▒▓▓▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒░▒▒▒▒░░▒▒▒▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ +▓▓▓▓▒▒▒▓▓▓▒▒▒▓▒▒▒▒▒░ ░░░░▒▒ ░▒▒▒▒▓▓▓▓▓▓▓▓▓▓▒▒▓▓▒▒▒▒▒░░▒░░▒▒▒▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ +▓▓▓▓▓▓▓▓▒▒▓▓▓▓▓▓▒▒▒░ ░░░░▒░░░░▒▒▒░▒▒▓▓▓▓▓▒▒▒▒▓▒▒▒▒▒▒▒▒▒░▒▒▒▒▒▒▓▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ +▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▓▓▓▓▓▓▒▒▒▒▒▒▒▒░▓▓▓▓▓▓▒░ ░▓▓▓▓▒▒▒▒▒▓▓▒▒▒▒▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ +▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒░░░░░░░░▒▒▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓▒▒▓▓▒░░░▒▒▒▒░▒▒▒▓▓▓▓▒▒▒▒▒▓▓▓▓▓▓▓▓ +▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒░░▒░░░░░ ░░░▒▒▒▓▓▒▒▒▒▓▓▓▓▓▓▓▓▒▓▓▓▓▓▓▒▒▓▓▓▓▓▓▓▓ +▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒░░ ░░░░░ ░░ ▒▓▓▓▓▓▓▓▓▓▓▓▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ +▓▓▓▒▓▓▒ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░ ░░▒▒░░ ░ ░░░░░▒▒▓▓▓▓▓▓▓▓▒▓▒▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒ +▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒░░░▒▒ ░░ ▒▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▓▓▓▓▓▓▒▓▓▓▓▓▓▓▓▓▓ +▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒ ░▒▒ ▒▒▓▓▓▒░░▒▒▒▒▒▓▓▓▓▓▒▒▒▒░░▓▓▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▒░▒░ +▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒░▒▒▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒░░░▓▒▒▓▓▓▓▒▓▓▓▓▓▓▓▓▓░░ +▓▓▓▓▓▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▓▒▓▓▒ ▒░ ▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▓▓▓▓▒▒▓▓▓▓▓▓▓▓▓▒▒░ +▓▒▒▓▓▓▓▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▓▒▓▓ ▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ +▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒ ░░░▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█▓▓ +▓▓▓▓▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▓▒▓▓▓▒▒▒▒░ ░░ ░ ░▒▓▓▓▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ +▓▓▓▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▓▓▓▓▒▓▓▒▓▓▒▒▒ ▒▒░ ░ ░░ ▒░▒▒░▒▓▓▓▓▓▓▓▓▓▓▓▒▒▒▒▒ +▓▓▓▒░▒▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░ ░▒ ░░░▒░ ░ ░░░░░░▒▒▒▒▒▒▒▒▒▓▓▓▓▓▓▓▓█ +▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒░ ░░░░▒▒▒▒▒▒▒▒▒░▒▒▒▒▒▓▓█▓▓▓▓▓▓▓▓▓▓▓ +▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█▓▓▓▓▓▓▒▓▒▒░▒▓▓▓▓▒░ ▒▓▓▓▓▓▓▓▒░░░░▒▓░░░▒▓▓▓▓▓▓▓▓▓▓▓▓█▓▓▓ +▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█▓▓▓▓▓▓▓▓██▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▒▓▓▓▓▓▓▓▓▓▓▒░ ▒▒▒▒▒▓▓▒▓▒▒▓▓▓▓▓▓▓▓▓▓ +▓▓▓▓▓▓▓▓▓▓█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓███▓▓▓▓▓▓██▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒ ░▒▓▓▓▒░ ░ ▒▒▒▒▓▓▓▓▓▓▓▓▓▓▓▓▓ +▓▓▓█▓▓▓▓▓▓██▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█▓▓▓▓▓▓▓▓██▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒░ ░░▓▓▓▓▒░ ░░▒░░ ▒▓▓▓▓▓▓██████▓▓ +▓▓▓▓▓▓▓▓▓▓███▓▓▓▓▓▓▓▓▓▓█▓▓▓▓▓▓▓█▓███▓▓▓▓███▓▓▓▓▓▓▓▒▒▓▓▒░▓▓▓▓▒░ ▒▒▒░ ▒▒▓▓▓▒░ ░ ▒▒░ ░▒▒▓▓▓▓▓▓▓▓▓▓▓ \ No newline at end of file diff --git a/local/path/home/ascii/hacker.txt b/local/path/home/ascii/hacker.txt new file mode 100644 index 0000000..91e5102 --- /dev/null +++ b/local/path/home/ascii/hacker.txt @@ -0,0 +1,33 @@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*-%@%: :%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+ *@@@= *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+ %@@@@@: =@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@# #@@@@#- =@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%.-@@#: *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+ =#%*+=-. #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%. +%@@@@@@@%. :@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@# *@@@@@@@@@@@@@@@* %@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@% @@@@@@@@@@@@@@@@@@@ -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ #@@@@@@@@@@@@@@@@@@ .%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@% :@@@@@@@@@@@@@@@+ =%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+ @@@@@@@@@@@@% :@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@= #@* #@@@@@@@@@% -+-. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@- @@@@@@@*:#@@@@@@@@=+@@@@@+ * .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@# @%@@@@@@@@@@@@@@@@@@@@@@@@@=%@@ =@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@% @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@% -@@@@@+====-----::::.... %@@% @@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@ :==@@@@ =##%%%%%%%%%%%%%%%%%%%%* %@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@= -@@@@@@ *@@@@@@@@@@@@@@@@@@@@@@# %@@@@@* @@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@ #@@@@@:*@@@@@@@@@@@@@@@@@@@@@@#.%@@@@@== *@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@*:=#%#-. :*%*+@@@@@@@@*: :#@@@@@@@@#=@@@=. ...:%@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#%@@@@@@+@@@@@@@@*. .*@@@@@@@@##%*+=. %@@#@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*@@@@@@@@@%##@@@@@@@@@@#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*@@@@@@@@@@@@@@@@@@@@@@%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ \ No newline at end of file diff --git a/local/path/home/ascii/judge.txt b/local/path/home/ascii/judge.txt new file mode 100644 index 0000000..b960409 --- /dev/null +++ b/local/path/home/ascii/judge.txt @@ -0,0 +1,21 @@ + ______ + ,-~ _ ^^~-., + ,^ -,____ ^, ,/\/\/\, + / (____) | S~ ~7 + ; .---._ | | || _| S I AM THE Z + | | ~-.,\ | |!/ | /_ LAW! _\ + ( | ~<-.,_^\|_7^ ,| _//_ _\ + | | ", 77> (T/| _/' \/\/\/ + | \_ )/<,/^\)i(| + ( ^~-, |________|| + ^!,_ / /, ,'^~^',!!_,..---. + \_ "-./ / (-~^~-))' =,__,..>-, + ^-,__/#w,_ '^' /~-,_/^\ ) + /\ ( <_ ^~~--T^ ~=, \ \_,-=~^\ + .-==, _,=^_,.-"_ ^~*.(_ /_) \ \,=\ ) + /-~; \,-~ .-~ _,/ \ ___[8]_ \ T_),--~^^) + _/ \,,..==~^_,.=,\ _.-~O ~ \_\_\_,.-=} + ,{ _,.-<~^\ \ \\ () .=~^^~=. \_\_,./ +,{ ^T^ _ / \ \ \ \ \) [| \oDREDD > + ^T~ ^ { \ \ _\.-|=-T~\\ () ()\<||>,' ) + + \ |=~T ! Y [|() \ ,' / -naughty \ No newline at end of file diff --git a/local/path/home/ascii/noir.txt b/local/path/home/ascii/noir.txt new file mode 100644 index 0000000..713a536 --- /dev/null +++ b/local/path/home/ascii/noir.txt @@ -0,0 +1,58 @@ +@@@@@@@@@@@@@%@@%%@%###(>{=*<[{%@@%@@@@%{#%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@%%#%@%#(^ ~ :<}@@@@@@@@@%@##@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@%#{#%%@@@% (#%%@@@@@@@@@@{{%%@@%%%%%%%%%%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@%{{%%#@@@@@( . <}@@@@@@@@@%%%%%%%%%%%%%%%%%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@%%}#%#@@@@@@@@. {@@@@@@@%%%%%%%%%%%%%%%%%%%%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@%%#{##%@@@@@@@%{ -] [%@@@@@@@%%%###%%%%%%%%%%%%%%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@%###@@@@@@@@@@@%%{ + @%%@@@@@@%%##############%%%%%%%@%%%%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@%#{#%@@@@@@@@@@@@%{({[~+@%%@@@@@%################%%%%%%%@%%%%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@%#{%@@@@@@@@@@@@@@@@%}%#(#%@@@@@@%%##{{{#{{{{{{{{#######%%%%%%%%%%%%%%%%%%%%%%@@@@@@@@@@@@@@@@@@ +@@%#{{%@@@@@@@@@@@@@@@@@@%%%#[%@@@@%%%##{{{{{{{{{{{{{#############%%%%%%%%%%%%%%%@@@@@@@@@@@@@@@@@@@ +@%#}[%@@@@@@@@@@@@@@@@@@@@@@#%%@@@@%%##{{}}}{{{{{{{{{{{{#######%##%%%%%%%%%%%%%%%%%%%@@@@@@@@@@@@@@@ +%#{}#@@@@@@@@@@@@@@@@@@@@@%%#%%@@@%%%{{{}[[}}{{{{{{{{{{{{{########[#%%%%%%%%%%%%%%%%%@@@@@@@@@@@@@@@ +{{}%@@@@@@@@@@@@@@@@@@@@@@@%%%%%@@%%#{}}[]][[[[[[[}}{{{{{{{{{{{{{}*}#%%%%%######%%%%%%%%%@@@@@@@@@@@ +][%%%@@@@@@@@@@@@@@@@@@@@@@%%%@@%%%##}}[[]]][[[[[[[[}}{{{{{{{{{{{{###############%%%%%%%%@@@@@@@@@@@ +#%%%%%%@@@@@@@@@@@@@@@@@@@@%##%%%##{{[[]]((]]]]][]]][}}}}}}{{{{{{{{{{{{{{{########%%%%%%%%%%@@@@@@@@ +@%%%%#%%%@@@@@@@@@@@@@@@@@@%##%###{{}]]]())((]]] (][[[[}}}}}{{{{{{{{{{{########%%%%%%%%%%@@@@@@@@ +#######%%%%%%%%%%%@@@@@@@@%#%{##%#{[])))))<)))((( ([[][[[[}}}}}}}{{{{{{{{{{{{{{##%%%%%%%%%@@@@@@@@ +{{{#{######%%%%%%%%@@@@%@(##)}{###{[(<<<<<><))))])><]]]]]]][[[[[[[}}}}{}}[{{{{{{{##%%%%%%%%%@@@@@@@@ +{{{{{{#############%%%%@@@@%{}{{{#}])>>>>>>>><<<))((((( >]]]]]]][[[}}}}}{{{{{####%%%%%%%%@@%%%@@@@ +{{{{{{{{{{{{{{{}{{####%%%@@%{}{{{}])>^^^^^^^><<<<))))))* =(((]]]][[[[}}}{{{{{####%%%%%%%%@@%%%@@@@ +{{{{{{{{{{}}}[[[[][}}}}{%%@%}[[[[[(>*++++***^>>>>>>><<<<)( >)([[[[[} >( [[{{{{######%%%%%%%@@@@ +}}}}}}}}}[[]]]]((((]]()]{%@%[]((](>+~=++++++**^^^^>>>>>><> =->- ))[]][[}]>]{}}{{}{{######%%%%%%%@@@@ +[[[}[[[[[]]]((()<>^<>+~^({%#<)(())*----~====+++++***^^^>><<<<<)))((]]][[[}}}}{{{{{{######%%%%%%%%%@@ +]]]]]]]]]]]()>^*+*^*~~=.*[%#- ]( :..:----~====+++**^^>>>><<<))(((]]][[[}}}}}{{{{######%%%%%%%%%@@ +)(]((((](<<<<<>==+=~-~+ >#{=%@@@. .::::--~~=+++**^^>>><<)))(((]]]][[[}}}{{{{{#####%%%%%%%%%@@ +)))(((()<>>=--=~~ .*%@%%@%}- .:-~=+++**^^>>><<)))(((]((]][[}}}{{{{{#####%%%%%%%%%@@ +)<<<)))<<>*+*=- ..~}#%@@{+ ==++**^^^>><<)))(((]]]]][[}}}{{{{######%%%%%%%%%%% +))<>><<<>*-. . : #%%%@@# -~=+++*^^^>><<)))(((]]]]][[}}}{{{{######%%%%%%%%%%% +)>>>>>>>>>*+~=~:: : }@@@%%@%= *] -++**^^^>><<))((((]][[[[[}}}{{{{{#####%%%%%%%%%@@ +)^^><<<>>>^~++~ . }@@@@@@%%{{# .**^^^>><<))((((][[[[[[}}}{{{{{#####%%%%%%%%%@@ +)>>>>><>^^*++*~: . . }%@@@@@@@@@% +*^^>>><<))(((]]][[[[[}}}{{{{{{####%%%%%%%%%%% +)<>>>>>>^^**=**++~::-. {#){%%%%%%%* ~+***^^>>><<))(((]]][[[[[}}}{{{{{{####%%%%%%%%%%% +()<)<<<>>^^^^^^*+~ ~- . #[ <@@@@@%) =++*^^^>>><<))((]]]][[[[[}}}{{{{{{{{{#%%%%%%%%%%@ +(((()<<<>>^*^^^^*++~ -:-::{[ (@@@@@@# :---~~==++*^^^>>><<))((((]][[[[[}}}{{{{{{{{{#%%%%%%%%%%@ +((]))>^>>>^**><^+*+++--=>^%%)]@@@@@@( - .:-~~===+++**^^>><<<))((]]]][[[[[}}}{{{{{{{{{####%%%%%%%% +](>^><)>++*+*^^^+=+++=~++)@%(<%@@@@@@]+:::----~=++**+**^^>><<<)))((]]]][[[[}}}}{{{{{{{{{####%%%%%%%% +{()^==***-==^~ - :-=**^*}%%(*)}#%@@@@@(-~~~-~===+++*^^^>><<)))))((]]][[[[}}}}{{{{{{{{{{####%%%%%%%% +([[(][)^+-: ::~.:=^>>*=[%%(++*)}{{#%%@#[+=++++++**^>>>><<<)))((((]]][[[[}}}}{{{{{{{{###%%%%%%%%%@@ +<][}[[]((^ -.=++~+*^>><><{@%[^*+>[##%%@@@#(*++****^^>><<<<)))))((((]]][[[}}}}}}{{{{{{{###%%%%%%%%%@@ +(]{}][})<>=-^)^>)<<<*^<)({@%[^**>[##%%%#}])>***^^^>>><<<)))))((((]]]]][[}}}{{{{{{{{{{{###%%%%%%%%@@@ +[-}{{}}]*=>)>++]]())<<^)]#@%[+>}{%%#[<<.(())<^*^>>><<<<<)))((((]][[[[}}}}}{{{{{{{##{{{#%%%%%%%%%%%%% +<+(^[{[}[>^<^([])(]]]((][#%#()}%##%%{))>(]]((<>*><<<<<<)))))(((]][[[[[[[[}}}}}}}}}}[(]][}}}}}}}}{{{{ +)*){])}[](+^^]]]>]}[[}]}[#%{)([]]{%%<=><>*+=~. ----~==++++***^>><<<))((((]]]][[[}}]**^><<<))(((]]][ ++~](})>[[(~*(>)())[[}}[[[#%}<^+~.^#%( >+++++**^^^^***^^^>>^^^>>>>>>>>^^^^+*= -~+*******^>>> ++[~<]}]<(]*^*^>>>*<>**+*=]{[>. ]%^ .:---= ....::-:-~~ +(^*=+==**+:- ~: =}(+ *%> *]]]])<<<<<<<)((((((]]]]](][[][[}[]][}}]] +===~- . [(~ (%% +=::. [): >} .-~=+*><)((]}}}[}}}}{{{{{{##{{#{#%> + . ])= }^ ))[#{#{{{}}}}[[[[]((<<<<<>^^>>><<))<))<<>^^*~: + <[] [{( + =[]= ]{} + ^###[ +{{{] .-=*^<<)))(][}}}{%#%%%%%@%%%%%%%@%) + [{{}~ <#%%# %%%@@@@@@@@@@@%%%%%%##%%%%%%%%%%%#@%@%%%%%%%%%%%%%#{( + ~++*+ + -^^*^*- =^^^^^^^^^^*===~~~~~--. :-:::--~:.. + + + + \ No newline at end of file diff --git a/local/path/home/ascii/sonic.js b/local/path/home/ascii/sonic.js new file mode 100644 index 0000000..5138053 --- /dev/null +++ b/local/path/home/ascii/sonic.js @@ -0,0 +1,56 @@ +/** @param {NS} ns */ +export async function main(ns) { +ns.tprint(" ...,?77??!~~~~!???77?<~.... "); +ns.tprint(" ..?7` `7!.. "); +ns.tprint(" .,=` ..~7^` I ?1. "); +ns.tprint(" ........ ..^ ?` ..?7!1 . ...??7 "); +ns.tprint(" . .7` .,777.. .I. . .! .,7! "); +ns.tprint(" .. .? .^ .l ?i. . .` .,^ "); +ns.tprint(" b .! .= .?7???7~. .>r . .= "); +ns.tprint(" .,.?4 , .^ 1 ` 4... "); +ns.tprint(" J ^ , 5 ` ?<. "); +ns.tprint(" .%.7; .` ., .; .=. "); +ns.tprint(" .+^ ., .% MML F ., ?, "); +ns.tprint(" P ,, J .MMN F 6 4. "); +ns.tprint(" l d, , .MMM! .t .. ,, "); +ns.tprint(" , JMa..` MMM` . .! .; "); +ns.tprint(" r .M# .M# .% . .~ ., "); +ns.tprint(" dMMMNJ..! .P7! .> . . ,, "); +ns.tprint(" .WMMMMMm ?^.. ..,?! .. .. , Z7` `?^.. ,, "); +ns.tprint(" ?THB3 ?77?! .Yr . .! ?, ?^C "); +ns.tprint(" ?, .,^.` .% .^ 5. "); +ns.tprint(" 7, .....?7 .^ ,` ?. "); +ns.tprint(" `<. .= .`' 1 "); +ns.tprint(" ....dn... ... ...,7..J=!7, ., "); +ns.tprint(" ..= G.,7 ..,o.. .? J. F "); +ns.tprint(" .J. .^ ,,,t ,^ ?^. .^ `?~. F "); +ns.tprint(" r %J. $ 5r J ,r.1 .=. .% "); +ns.tprint(" r .77=?4. ``, l ., 1 .. <. 4., "); +ns.tprint(" .$.. .X.. .n.. ., J. r .` J. `' "); +ns.tprint(" .?` .5 `` .% .% .' L.' t "); +ns.tprint(" ,. ..1JL ., J .$.?` . "); +ns.tprint(" 1. .=` ` .J7??7<.. .; "); +ns.tprint(" JS.. ..^ L 7.: "); +ns.tprint(" `> .. J. 4. "); +ns.tprint(" + r `t r ~=..G. "); +ns.tprint(" = $ ,. J "); +ns.tprint(" 2 r t .; "); +ns.tprint(" .,7! r t`7~.. j.. "); +ns.tprint(" j 7~L...$=.?7r r ;?1. "); +ns.tprint(" 8. .= j ..,^ .. "); +ns.tprint(" r G . "); +ns.tprint(" .,7, j, .>=. "); +ns.tprint(" .J??, `T....... % .. "); +ns.tprint(" ..^ <. ~. ,. .D "); +ns.tprint(" .?` 1 L .7.........?Ti..l "); +ns.tprint(" ,` L . .% .`! `j, "); +ns.tprint(" .^ . .. .` .^ .?7!?7+. 1 "); +ns.tprint(".` . .`..`7. .^ ,` .i.; "); +ns.tprint(".7<..........~<<3?7!` 4. r ` G% "); +ns.tprint(" J.` .! % "); +ns.tprint(" JiJ .` "); +ns.tprint(" .1. J "); +ns.tprint(" ?1. .' "); +ns.tprint(" 7<..% "); + +} \ No newline at end of file diff --git a/local/path/home/autoexec.js b/local/path/home/autoexec.js new file mode 100644 index 0000000..580f6a1 --- /dev/null +++ b/local/path/home/autoexec.js @@ -0,0 +1,298 @@ + +import { purchaseServers, listPurchasedServers, getSetting } from "myLibrary.js"; + + +/** @param {NS} ns */ +export async function main(ns) { + + ns.disableLog("ALL"); + + //host and script info + const sThisRunner = ns.getHostname(); + const sThisScript = ns.getScriptName(); + const nThisPID = ns.pid; + + // Custom color coding. + const cCyan = "\u001b[36m"; + const cGreen = "\u001b[32m"; + const cRed = "\u001b[31m"; + const cReset = "\u001b[0m"; + + //open log for this script + ns.tail(nThisPID, sThisRunner, ns.args); + + //scripts + const sGangScript = "gang/auto-gang2.js"; + const sServerLister = "serverlister.js"; + const sServerListFile = "serverList.txt"; + const sBestServerFile = "bestTarget.txt"; + const sBackdoorScript = "backdoor.js"; + + //settings + const nRefreshFrequency = 1000; //time in ms + + ns.exec(sServerLister, sThisRunner, 1, false, true); + + await ns.sleep(100); + let oBestTarget = JSON.parse(ns.read("bestTarget.txt")); + let sBestTarget; + while (true) { + ns.clearLog(); + + //Home Computer + let nHomeMaxRAM = ns.getServerMaxRam("home"); + let nHomeUsedRAM = ns.getServerUsedRam("home"); + let nHomeFreeRAM = nHomeMaxRAM - nHomeUsedRAM; + ns.print("Home Free RAM = " + cCyan + Math.floor(nHomeFreeRAM).toLocaleString() + cReset + " / " + cCyan + nHomeMaxRAM.toLocaleString() + cReset + " GB"); + let oHome = ns.getServer("home"); + let nCores = oHome.cpuCores; + ns.print("Home Cores = " + cCyan + Math.floor(nCores).toLocaleString() + cReset); + + + //Gang + ns.print("Karma = " + cCyan + Math.round(ns.heart.break()).toLocaleString() + cReset); + if (ns.gang.inGang()) { + if (!ns.getRunningScript(sGangScript)) { + ns.print("Gang found... running " + sGangScript); + ns.exec(sGangScript, sThisRunner, 1); + } + + } + else { + ns.print("Gang: " + cRed + "none" + cReset); + } + + //Best Target + + oBestTarget = JSON.parse(ns.read("bestTarget.txt")); + sBestTarget = oBestTarget.serverName; + ns.print("Best Target: " + cCyan + sBestTarget + cReset); + ns.print("Target Weakness: " + cCyan + Math.floor((ns.getServerMinSecurityLevel(sBestTarget) / ns.getServerSecurityLevel(sBestTarget)) * 100) + "%" + cReset); + ns.print("Target Money: " + cCyan + Math.floor((ns.getServerMoneyAvailable(sBestTarget) / ns.getServerMaxMoney(sBestTarget)) * 100) + "%" + cReset); + + let nPServs = listPurchasedServers(ns).length; + let aPserv; + + const oEXE = { + ssh: { name: "BruteSSH.exe", nHackingLevel: 50, cost: 500000 }, + ftp: { name: "FTPCrack.exe", nHackingLevel: 100, cost: 1500000 }, + smtp: { name: "relaySMTP.exe", nHackingLevel: 250, cost: 5000000 }, + http: { name: "HTTPWorm.exe", nHackingLevel: 500, cost: 30000000 }, + sql: { name: "SQLInject.exe", nHackingLevel: 750, cost: 250000000 }, + ds1: { name: "DeepscanV1.exe", nHackingLevel: 75, cost: 500000 }, + ds2: { name: "DeepscanV2.exe", nHackingLevel: 400, cost: 25000000 }, + sp: { name: "ServerProfiler.exe", nHackingLevel: 75, cost: 500000 }, + al: { name: "AutoLink.exe", nHackingLevel: 25, cost: 1000000 }, + form: { name: "Formulas.exe", nHackingLevel: 25, cost: 1000000000 } + }; + + let bBusy = ns.singularity.isBusy(); + let bBruteSSH = ns.fileExists(oEXE.ssh.name, "home"); + let bFTPCrack = ns.fileExists(oEXE.ftp.name, "home"); + let bRelaySMTP = ns.fileExists(oEXE.smtp.name, "home"); + let bHttpWorm = ns.fileExists(oEXE.http.name, "home"); + let bSqlInject = ns.fileExists(oEXE.sql.name, "home"); + + let bDeepscanV1 = ns.fileExists(oEXE.ds1.name, "home"); + let bDeepscanV2 = ns.fileExists(oEXE.ds2.name, "home"); + let bServerProfiler = ns.fileExists(oEXE.sp.name, "home"); + let bAutoLink = ns.fileExists(oEXE.al.name, "home"); + let bFormulas = ns.fileExists(oEXE.form.name, "home"); + + let nHackingLevel = ns.getHackingLevel(); + let nMoney = ns.getPlayer().money; + + //Home Upgrades + if (nMoney > ns.singularity.getUpgradeHomeRamCost()) { + ns.singularity.upgradeHomeRam(); + ns.tprint(cCyan + "Upgraded home RAM" + cReset); + } + else if (nCores < 8 && nMoney > ns.singularity.getUpgradeHomeCoresCost()) { + ns.singularity.upgradeHomeCores(); + ns.tprint(cCyan + "Upgraded home Cores" + cReset); + } + + + ns.print("Number of pservers = " + cCyan + nPServs + cReset); + + let sLowestPserv; + aPserv = listPurchasedServers(ns); + let nLowestRAM = 2 ** 21; + let nCurrentRAM = 0; + for (let i = 0; i < aPserv.length; i++) { + nCurrentRAM = ns.getServerMaxRam(aPserv[i]); + if (nCurrentRAM < nLowestRAM) { + nLowestRAM = nCurrentRAM + sLowestPserv = aPserv[i]; + } + } + if (nLowestRAM < 2 ** 21) { + ns.print("Smallest psserv = " + cCyan + sLowestPserv + " " + nLowestRAM.toLocaleString() + " GB" + cReset); + } + else { + ns.print("Smallest psserv = " + cRed + "none" + cReset); + } + + + + + //TOR + let bHasTOR = ns.hasTorRouter(); + if (bHasTOR === false && nMoney >= 2e+5) { + ns.singularity.purchaseTor(); + ns.tprint(cCyan + "Purchased TOR" + cReset); + ns.toast("Purchased " + "TOR Router", "info", 10000); + } + await ns.sleep(1); + if (bBruteSSH === false && bHasTOR && nMoney >= oEXE.ssh.cost) { + ns.singularity.purchaseProgram(oEXE.ssh.name); + ns.tprint(cCyan + "Purchased " + oEXE.ssh.name + cReset); + ns.toast("Purchased " + oEXE.ssh.name, "info", 10000); + ns.exec(sServerLister, sThisRunner, 1, false, true); + ns.exec(sBackdoorScript, sThisRunner, 1); + } + else if (bAutoLink === false && bHasTOR && nMoney >= oEXE.al.cost) { + ns.singularity.purchaseProgram(oEXE.al.name, false); + ns.tprint(cCyan + "Purchased " + oEXE.al.name + cReset); + ns.toast("Purchased " + oEXE.al.name, "info", 10000); + } + else if (bFTPCrack === false && bHasTOR && nMoney >= oEXE.ftp.cost) { + ns.singularity.purchaseProgram(oEXE.ftp.name, false); + ns.tprint(cCyan + "Purchased " + oEXE.ftp.name + cReset); + ns.toast("Purchased " + oEXE.ftp.name, "info", 10000); + ns.exec(sServerLister, sThisRunner, 1, false, true); + ns.exec(sBackdoorScript, sThisRunner, 1); + } + else if (bDeepscanV1 === false && bHasTOR && nMoney >= oEXE.ds1.cost) { + ns.singularity.purchaseProgram(oEXE.ds1.name, false); + ns.tprint(cCyan + "Purchased " + oEXE.ds1.name + cReset); + ns.toast("Purchased " + oEXE.ds1.name, "info", 10000); + } + else if (bRelaySMTP === false && bHasTOR && nMoney >= oEXE.smtp.cost) { + ns.singularity.purchaseProgram(oEXE.smtp.name, false); + ns.tprint(cCyan + "Purchased " + oEXE.smtp.name + cReset); + ns.toast("Purchased " + oEXE.smtp.name, "info", 10000); + ns.exec(sServerLister, sThisRunner, 1, false, true); + ns.exec(sBackdoorScript, sThisRunner, 1); + } + else if (bHttpWorm === false && bHasTOR && nMoney >= oEXE.http.cost) { + ns.singularity.purchaseProgram(oEXE.http.name, false); + ns.tprint(cCyan + "Purchased " + oEXE.http.name + cReset); + ns.toast("Purchased " + oEXE.http.name, "info", 10000); + ns.exec(sServerLister, sThisRunner, 1, false, true); + ns.exec(sBackdoorScript, sThisRunner, 1); + } + else if (bSqlInject === false && bHasTOR && nMoney >= oEXE.sql.cost) { + ns.singularity.purchaseProgram(oEXE.sql.name, false); + ns.tprint(cCyan + "Purchased " + oEXE.sql.name + cReset); + ns.toast("Purchased " + oEXE.sql.name, "info", 10000); + ns.exec(sServerLister, sThisRunner, 1, false, true); + ns.exec(sBackdoorScript, sThisRunner, 1); + } + else if (bDeepscanV2 === false && bHasTOR && nMoney >= oEXE.ds2.cost) { + ns.singularity.purchaseProgram(oEXE.ds2.name, false); + ns.tprint(cCyan + "Purchased " + oEXE.ds2.name + cReset); + ns.toast("Purchased " + oEXE.ds2.name, "info", 10000); + } + else if (getSetting(ns, "autoPurchaseServers") && nPServs < 25 && nMoney >= 5e+6) { //Purchased Servers + ns.tprint("purchasing servers "); + await purchaseServers(ns); + ns.exec(sServerLister, sThisRunner, 1, false, true); + } + else if (getSetting(ns, "autoUpgrades") && nLowestRAM < (2 ** 20) && !ns.scriptRunning("upgrade.js", sThisRunner) && nPServs >= 25 && nMoney >= 1e+6) { + ns.tprint("upgrading servers "); + ns.exec("upgrade.js", sThisRunner, 1); + + } + + //ns.tprint("autoPurchaseServers = " + getSetting(ns, "autoPurchaseServers")); + //ns.tprint("autoUpgrades = " + getSetting(ns, "autoUpgrades")); + + + //work on something + if (bBusy === false) { + if (bHasTOR === false) { + if (bBruteSSH === false && nHackingLevel >= 50) { + ns.singularity.createProgram("BruteSSH.exe", false); + } + else if (bFTPCrack === false && nHackingLevel >= 100) { + ns.singularity.createProgram("FTPCrack.exe", false); + } + else if (bRelaySMTP === false && nHackingLevel >= 250) { + ns.singularity.createProgram("relaySMTP.exe", false); + } + else if (bDeepscanV1 === false && nHackingLevel >= 75) { + ns.singularity.createProgram("DeepscanV1.exe", false); + } + } + if (nHackingLevel < 500) { + ns.singularity.universityCourse("rothman university", "study computer science", false); + } + } + + let nSharePower = Math.floor(ns.getSharePower() * 10000) / 100; + ns.print("Faction Reputation = " + cCyan + nSharePower + " %" + cReset); + + + if (bBusy) { + let oCurrentWork = ns.singularity.getCurrentWork(); + //ns.print("oCurrentWork = " + JSON.stringify(oCurrentWork)); + let bCanResume = false; + let nWorkCycles; + switch (oCurrentWork.type) { + case "CLASS": //Task = StudyTask + nWorkCycles = oCurrentWork.cyclesWorked; + ns.print("Working at: " + cCyan + oCurrentWork.location + cReset); + ns.print("Working with: " + cCyan + oCurrentWork.classType + cReset); + ns.print("Task Cycle: " + cCyan + nWorkCycles.toLocaleString() + cReset) + bCanResume = true; + break; + case "CREATE_PROGRAM": //Task = CreateProgramWorkTask + nWorkCycles = oCurrentWork.cyclesWorked; + ns.print("Creating Program: " + cCyan + oCurrentWork.programName + cReset); + ns.print("Task Cycle: " + cCyan + nWorkCycles.toLocaleString() + cReset) + bCanResume = true; + break; + case "FACTION": //Task = FactionWorkTask + nWorkCycles = oCurrentWork.cyclesWorked; + ns.print("Working at: " + cCyan + oCurrentWork.factionName + cReset); + ns.print("Working with: " + cCyan + oCurrentWork.factionWorkType + cReset); + ns.print("Task Cycle: " + cCyan + nWorkCycles.toLocaleString() + cReset) + bCanResume = true; + break; + case "CRIME": //Task = CrimeTask + nWorkCycles = oCurrentWork.cyclesWorked; + ns.print("Comitting crime: " + cCyan + oCurrentWork.crimeType + cReset); + ns.print("Crime Chance: " + cCyan + Math.floor(10000 * ns.singularity.getCrimeChance(oCurrentWork.crimeType)) / 100 + "%" + cReset); + ns.print("Task Cycle: " + cCyan + nWorkCycles.toLocaleString() + cReset) + bCanResume = true; + break; + case "COMPANY": //Task = CompanyWorkTask + nWorkCycles = oCurrentWork.cyclesWorked; + ns.print("Working at: " + cCyan + oCurrentWork.companyName + cReset); + ns.print("Task Cycle: " + cCyan + nWorkCycles.toLocaleString() + cReset) + bCanResume = true; + break; + case "GRAFTING": //Task = GraftingTask + nWorkCycles = oCurrentWork.cyclesWorked; + ns.print("Grafting: " + cCyan + oCurrentWork.augmentation + cReset); + ns.print("Task Cycle: " + cCyan + nWorkCycles.toLocaleString() + cReset) + bCanResume = false; + break; + + } + /* + if (bBusy && bCanResume === true && nWorkCycles >= 100) { + ns.singularity.stopAction(); + + + } + */ + } + + + + + await ns.sleep(nRefreshFrequency); + } +} \ No newline at end of file diff --git a/local/path/home/backup/batch2.js b/local/path/home/backup/batch2.js new file mode 100644 index 0000000..ac7041c --- /dev/null +++ b/local/path/home/backup/batch2.js @@ -0,0 +1,120 @@ +/** @param {NS} ns */ +export async function main(ns) { + //Arguments + const sTarget = ns.args[0]; // target server + + const oRunner = ns.getServer(); + const sRunner = oRunner.hostname; + + ns.tail("batch2.js", sRunner, sTarget); + + //Settings + //const oHome = ns.getServer("home"); + //const nCores = oHome.cpuCores; + + const sScript = ns.getScriptName(); + const sWeaken = "RMweaken.js"; + const sGrow = "RMgrow.js"; + const sHack = "RMhack.js"; + const nScriptRAM = ns.getScriptRam(sScript, sRunner); + const nWeakenRAM = ns.getScriptRam(sWeaken, sRunner); + const nGrowRAM = ns.getScriptRam(sGrow, sRunner); + const nHackRAM = ns.getScriptRam(sHack, sRunner); + const nHomeUsedRAM = ns.getServerUsedRam(sRunner); + const nHomeMaxRAM = ns.getServerMaxRam(sRunner); + let nHomeFreeRAM = nHomeMaxRAM - nHomeUsedRAM; + + const nDelays = [0, 20, 40, 60]; + + + //abort script if sTarget is undefined + if (sTarget === undefined) { + ns.tprint("1st arg sTarget is undefined"); + return false; + } + + //target server info + const nMinSecurity = ns.getServerMinSecurityLevel(sTarget); + const nMaxMoney = ns.getServerMaxMoney(sTarget); + + let nWeakenTime1 = ns.getWeakenTime(sTarget); + let nWeakenTime2 = nWeakenTime1; + let nGrowTime = nWeakenTime1 * 0.8; + let nHackTime = nWeakenTime1 / 4; + + //let nHackSecurityGain = ns.hackAnalyzeSecurity(1, sTarget); + let nHackSecurityGain = 0.002; + //let nHackThreadsEstimate = Math.floor(1 / nHackSecurityGain); + let nHackThreadsEstimate = 10; + ns.tprint("nHackSecurityGain = " + nHackSecurityGain); + ns.tprint("nHackThreadsEstimate = " + nHackThreadsEstimate); + const nHackTotalRAM = nHackRAM * nHackThreadsEstimate; + + //let nGrowSecurityGain = ns.growthAnalyzeSecurity(1, sTarget, nCores); + let nGrowSecurityGain = 0.004; + let nGrowThreadsEstimate = Math.floor(1 / nGrowSecurityGain); + ns.tprint("nGrowSecurityGain = " + nGrowSecurityGain); + ns.tprint("nGrowThreadsEstimate = " + nGrowThreadsEstimate); + const nGrowTotalRAM = nGrowRAM * nGrowThreadsEstimate; + + //let nWeakenSecurity = ns.weakenAnalyze(1, nCores); + let nWeakenSecurity = 0.05; + let nWeakenThreadsEstimate = Math.ceil(1 / nWeakenSecurity); + ns.tprint("nWeakenSecurity = " + nWeakenSecurity); + ns.tprint("nWeakenThreadsEstimate = " + nWeakenThreadsEstimate); + const nWeakenTotalRAM = nWeakenRAM * nWeakenThreadsEstimate; + + const nTotalRAM = nHackTotalRAM + nGrowTotalRAM + (nWeakenTotalRAM * 2) + const nTotalBatches = Math.floor(nHomeFreeRAM / (nTotalRAM - nScriptRAM)); + ns.tprint("RAM per Cycle = " + nTotalRAM); + ns.tprint("how many batches can i run at the same time? = " + nTotalBatches); + + let nGrowDelay = nWeakenTime1 - nGrowTime; + let nHackDelay = nWeakenTime1 - nHackTime; + + const nCycleDuration = nWeakenTime2 + nDelays[3]; + ns.tprint("nCycleDuration = " + nCycleDuration); + + const nBatchFrequency = Math.ceil(nCycleDuration / nTotalBatches); + ns.tprint("nBatchFrequency = " + nBatchFrequency); + + while (true) { + + //server stats + let nCurrentSecurity = ns.getServerSecurityLevel(sTarget); + let nCurrentMoney = ns.getServerMoneyAvailable(sTarget); + + //timestamp + let currentDate = new Date(); + let nOffset; + + ns.print("Cash: " + (Math.floor(nCurrentMoney * 1000) / 1000) + " / " + nMaxMoney); + ns.print("Security: " + (Math.floor(nCurrentSecurity * 1000) / 1000) + " / " + nMinSecurity); + + //Calculate estimate time of completion + nOffset = ns.getWeakenTime(sTarget); + let nWeakTime = new Date(currentDate.getTime() + nOffset); + let sWeakTime = nWeakTime.toLocaleTimeString('sw-SV'); //swedish time + + //Print estimated time of completion + ns.print("Weakening " + sTarget + " Estimated complete at " + sWeakTime); + + //hack + const nHackPID = ns.exec(sHack, sRunner, 10, sTarget, false, nHackDelay + nDelays[0]); + //ns.tail(nHackPID, "home", "home", nHackThreadsEstimate, sTarget, 0, nHackDelay + nDelays[0]); + + //weaken 1 + const nWeakenPID = ns.exec(sWeaken, sRunner, nWeakenThreadsEstimate, sTarget, false, nDelays[1]); + //ns.tail(nWeakenPID, "home", "home", nWeakenThreadsEstimate, sTarget, 0, nDelays[1]); + + //grow + const nGrowPID = ns.exec(sGrow, sRunner, nGrowThreadsEstimate, sTarget, false, nGrowDelay + nDelays[2]); + //ns.tail(nGrowPID, "home", "home", nGrowThreadsEstimate, sTarget, 0, nGrowDelay + nDelays[2]); + + //weaken 2 + const nWeakenPID2 = ns.exec(sWeaken, sRunner, nWeakenThreadsEstimate, sTarget, false, nDelays[3]); + //ns.tail(nWeakenPID2, "home", "home", nWeakenThreadsEstimate, sTarget, 0, nDelays[3]); + + await ns.sleep(nBatchFrequency); + } +} \ No newline at end of file diff --git a/local/path/home/backup/bitnodeStart.js b/local/path/home/backup/bitnodeStart.js new file mode 100644 index 0000000..ebe7daf --- /dev/null +++ b/local/path/home/backup/bitnodeStart.js @@ -0,0 +1,18 @@ +/** @param {NS} ns */ +export async function main(ns) { + + /* + goals + get money + upgrade home ram + /* + + let nPID = ns.run("serverlister.js"); + while (ns.getRunningScript(nPID)){ + ns.tprint("waiting for script to finish"); + await ns.sleep(100); + } + + + +} \ No newline at end of file diff --git a/local/path/home/backup/growrepeater.js b/local/path/home/backup/growrepeater.js new file mode 100644 index 0000000..7674063 --- /dev/null +++ b/local/path/home/backup/growrepeater.js @@ -0,0 +1,5 @@ +/** @param {NS} ns */ +export async function main(ns) { + const sTarget = ns.args[0]; // target server + while (true) { await ns.grow(sTarget); } +} \ No newline at end of file diff --git a/local/path/home/backup/maxGrow.js b/local/path/home/backup/maxGrow.js new file mode 100644 index 0000000..e9447bf --- /dev/null +++ b/local/path/home/backup/maxGrow.js @@ -0,0 +1,28 @@ +/** @param {NS} ns */ +export async function main(ns) { + //args + const sTarget = ns.args[0]; // target server + + ns.tail(ns.pid,"home",ns.args); + let nMoney = ns.getServerMoneyAvailable(sTarget); + const nMaxMoney = ns.getServerMaxMoney(sTarget); + + + + const startValue = nMoney; // First argument: starting value + const target = nMaxMoney; // Second argument: target value + let result = startValue; // Initialize result with the starting value + let n = 1; + // For loop that continues until the result exceeds or matches the target + for (; result < target; n++) { + result += 1; // Add 1 before multiplication + result *= n; // Multiply by the current step value + ns.print("result = "+result.toLocaleString() + " / "+ nMaxMoney.toLocaleString()); + ns.print("n = "+n); + } + let nGrowThreadsNeeded = n; + // * ns.growthAnalyze(sTarget, n, 1); + ns.print("nGrowThreadsNeeded = " + nGrowThreadsNeeded); + + +} \ No newline at end of file diff --git a/local/path/home/batch.js b/local/path/home/batch.js index 399435b..1c4a9b0 100644 --- a/local/path/home/batch.js +++ b/local/path/home/batch.js @@ -1,101 +1,137 @@ +import { getGrowThreads } from "myLibrary.js"; + /** @param {NS} ns */ export async function main(ns) { //Arguments + const nArgs = ns.args.length const sTarget = ns.args[0]; // target server let nFrequency = ns.args[1]; // frequency to run the Hack / Grow / Weaken const bIgnoreRAM = ns.args[2]; //if true the script will run even if estimated RAM is too low + const bTail = ns.args[3]; //if true the script will run even if estimated RAM is too low - //Settings - const sWeakenScript = "Ramses-weaken.js"; - const sGrowScript = "Ramses-grow.js"; - const sHackScript = "Ramses-hack.js"; - const nWeakenThreads = 5; - const nGrowThreads = 10; - const nHackThreads = 1; + //host and script info + //const sThisRunner = ns.getHostname(); + //const sThisScript = ns.getScriptName(); + if (bTail === true) { ns.tail(); } //logs - ns.disableLog("getServerMaxRam"); - ns.disableLog("getServerUsedRam"); - ns.disableLog("getServerMinSecurityLevel"); - ns.disableLog("getServerMaxMoney"); - ns.disableLog("getServerSecurityLevel"); - ns.disableLog("getServerMoneyAvailable"); + ns.disableLog("ALL"); + + //Settings + const sHackScript = "RMhack.js"; + const sGrowScript = "RMgrow.js"; + const sWeakenScript = "RMweaken.js"; + + const nHackThreads = 5; //1 + + const nHackScriptRAM = 1.75; + const nGrowScriptRAM = 1.7; + const nWeakenScriptRAM = 1.75; //abort script if sTarget is undefined - if (sTarget === undefined) { - ns.tprint("1st arg sTarget is undefined"); - return false; - } + if (sTarget === undefined) { ns.tprint("1st arg sTarget is undefined"); return false; } //how often do we run script in milliseconds - if (nFrequency === undefined) { - nFrequency = 20000; //run every 20 seconds unless defined as the 2nd argument when calling the script - } + if (nFrequency === undefined) { nFrequency = 1000; } //target server info const nMinSecurity = ns.getServerMinSecurityLevel(sTarget); const nMaxMoney = ns.getServerMaxMoney(sTarget); //abort script if sTarget cant have money - if (nMaxMoney <= 0) { - ns.tprint("sTarget (" + sTarget + ") has no nMaxMoney"); - return false; + if (nMaxMoney <= 0) { ns.tprint("sTarget (" + sTarget + ") has no nMaxMoney"); return false; } + + let nCurrentSecurity = ns.getServerSecurityLevel(sTarget); + let nCurrentMoney = ns.getServerMoneyAvailable(sTarget); + + let nBonusWeaken = 0; + let nBonusGrow = 0; + + /*if (nCurrentSecurity > nMinSecurity + 3) { + nBonusWeaken = 4; } + if (nCurrentMoney <= nMaxMoney * 0.8) { + nBonusGrow = 9; + }*/ + + let nGrowThreads = Math.max(12 + nBonusGrow, getGrowThreads(ns, sTarget, nHackThreads)); + let nGrowThreadsINT = Math.ceil(nGrowThreads); + + //25 hacks or 12.5 grows + let nWeakenThreads = Math.max(1 + nBonusWeaken, (nHackThreads / 25) + (nGrowThreads / 12.5)); + let nWeakenThreadsINT = Math.ceil(nWeakenThreads); //main variables const oRunner = ns.getServer(); //which server object is running this script const sRunner = oRunner.hostname; //hostname string of the server running the script - const nMaxRAM = ns.getServerMaxRam(sRunner); - const nUsedRAM = ns.getServerUsedRam(sRunner); - let nFreeRam = nMaxRAM - nUsedRAM; - const sScriptName = ns.getScriptName(); - const nScriptSize = ns.getScriptRam(sScriptName, sRunner); const nCores = oRunner.cpuCores; - const nWeakenScriptRAM = ns.getScriptRam(sWeakenScript, sRunner) * nWeakenThreads; - const nGrowScriptRAM = ns.getScriptRam(sGrowScript, sRunner) * nGrowThreads; - const nHackScriptRAM = ns.getScriptRam(sHackScript, sRunner) * nHackThreads; + //const sRunner = ns.getHostname(); //hostname string of the server running the script + let nMaxRAM = ns.getServerMaxRam(sRunner); + let nUsedRAM = ns.getServerUsedRam(sRunner); + let nFreeRam = nMaxRAM - nUsedRAM; + //const sScriptName = ns.getScriptName(); + //const nScriptSize = ns.getScriptRam(sScriptName, sRunner); + //let nMoney = ns.getServerMoneyAvailable(sTarget); + let nHomeServerReserve = Math.min(nMaxRAM / 8, 64); - const nWeakenTime = ns.getWeakenTime(sTarget); - const nGrowTime = ns.getGrowTime(sTarget); - const nHackTime = ns.getHackTime(sTarget); + if (sRunner !== "home") { + nHomeServerReserve = 0; + } - ns.tprint(sScriptName + " nScriptSize = " + nScriptSize+"GB"); +/* + let nWeakenPower = ns.weakenAnalyze(1, nCores); // default 0.05 (always?) + ns.tprint("nWeakenPower = " + nWeakenPower + " with " + nCores + " nCores"); - const nMaxWeakenRAM = Math.ceil(nWeakenScriptRAM * ((nWeakenTime / 1000) / (nFrequency / 1000))); - ns.tprint("nWeakenTime = " + nWeakenTime / 1000); - ns.tprint("nFrequency = " + nFrequency / 1000); - ns.tprint("nMaxWeakenRAM = " + nMaxWeakenRAM); + let nHackSecurity = ns.hackAnalyzeSecurity(1, sTarget); // default 0.002 + ns.tprint("nHackSecurity = " + nHackSecurity + " on " + sTarget + " sTarget"); - const nMaxGrowRAM = Math.ceil(nGrowScriptRAM * ((nGrowTime / 1000) / (nFrequency / 1000))); - ns.tprint("nGrowTime = " + nGrowTime / 1000); - ns.tprint("nFrequency = " + nFrequency / 1000); - ns.tprint("nMaxGrowRAM = " + nMaxGrowRAM); + let nGrowSecurity = ns.growthAnalyzeSecurity(1, "", nCores);// default 0.004 (always?) + ns.tprint("nGrowSecurity = " + nGrowSecurity + " on " + "_" + " sTarget" + " with " + nCores + " nCores"); +*/ + while (true) { - const nMaxHackRAM = Math.ceil(nHackScriptRAM * ((nHackTime / 1000) / (nFrequency / 1000))); - ns.tprint("nHackTime = " + nHackTime / 1000); - ns.tprint("nFrequency = " + nFrequency / 1000); - ns.tprint("nMaxHackRAM = " + nMaxHackRAM); + //server stats + nCurrentSecurity = ns.getServerSecurityLevel(sTarget); + nCurrentMoney = ns.getServerMoneyAvailable(sTarget); - const nTotalRAM = (nScriptSize + nMaxWeakenRAM + nMaxGrowRAM + nMaxHackRAM) * 1.07; - ns.tprint("Total estimated required RAM = " + nTotalRAM+"GB"); - ns.tprint("Available RAM: " + nFreeRam+" / "+nMaxRAM+"GB"); + nBonusWeaken = 0; + if (nCurrentSecurity > nMinSecurity + 3) { + nBonusWeaken = 4; + } + nBonusGrow = 0; + if (nCurrentMoney <= nMaxMoney * 0.8) { + nBonusGrow = 11; + } - if (nTotalRAM < nFreeRam || bIgnoreRAM === true) { - while (true) { - //server stats - let nCurrentSecurity = ns.getServerSecurityLevel(sTarget); - let nCurrentMoney = ns.getServerMoneyAvailable(sTarget); + nGrowThreads = Math.max(1 + nBonusGrow, getGrowThreads(ns, sTarget, nHackThreads)); + nGrowThreadsINT = Math.ceil(nGrowThreads); - //timestamp - let currentDate = new Date(); - let nOffset; + //25 hacks or 12.5 grows + nWeakenThreads = Math.max(1 + nBonusWeaken, (nHackThreads / 25) + (nGrowThreads / 12.5)); + nWeakenThreadsINT = Math.ceil(nWeakenThreads); - ns.print("Cash: " + (Math.floor(nCurrentMoney * 1000) / 1000) + " / " + nMaxMoney); - ns.print("Security: " + (Math.floor(nCurrentSecurity * 1000) / 1000) + " / " + nMinSecurity); + //timestamp + let currentDate = new Date(); + let nOffset; + ns.print("Cash: " + (Math.floor(nCurrentMoney * 1000) / 1000) + " / " + nMaxMoney); + ns.print("Security: " + (Math.floor(nCurrentSecurity * 1000) / 1000) + " / " + nMinSecurity); + + nMaxRAM = ns.getServerMaxRam(sRunner); + nUsedRAM = ns.getServerUsedRam(sRunner); + nFreeRam = nMaxRAM - nUsedRAM; + + while (nFreeRam <= (nWeakenScriptRAM * nWeakenThreads) + nHomeServerReserve + 6) { + await ns.sleep(100); + nMaxRAM = ns.getServerMaxRam(sRunner); + nUsedRAM = ns.getServerUsedRam(sRunner); + nFreeRam = nMaxRAM - nUsedRAM; + } + + if (nFreeRam > (nWeakenScriptRAM * nWeakenThreads) + nHomeServerReserve + 6) { //Calculate estimate time of completion nOffset = ns.getWeakenTime(sTarget); let nWeakTime = new Date(currentDate.getTime() + nOffset); @@ -103,45 +139,67 @@ export async function main(ns) { //Print estimated time of completion ns.print("Weakening " + sTarget + " Estimated complete at " + sWeakTime); + ns.print("Weakening with " + nWeakenThreadsINT + " threads on " + sTarget); + let nWeakenPID = ns.run(sWeakenScript, nWeakenThreadsINT, sTarget); + if (nWeakenPID === 0) { ns.print("Weaken Failed..."); } + } + + nMaxRAM = ns.getServerMaxRam(sRunner); + nUsedRAM = ns.getServerUsedRam(sRunner); + nFreeRam = nMaxRAM - nUsedRAM; + + while (nFreeRam <= (nGrowScriptRAM * nGrowThreads) + nHomeServerReserve + 6) { + await ns.sleep(100); + nMaxRAM = ns.getServerMaxRam(sRunner); + nUsedRAM = ns.getServerUsedRam(sRunner); + nFreeRam = nMaxRAM - nUsedRAM; + + } + + if (nCurrentSecurity <= (nMinSecurity + 1) && nFreeRam > (nGrowScriptRAM * nGrowThreads) + nHomeServerReserve + 6) { + + //Calculate estimate time of completion + nOffset = ns.getGrowTime(sTarget); + let nGrowTime = new Date(currentDate.getTime() + nOffset); + let sGrowTime = nGrowTime.toLocaleTimeString('sw-SV'); //swedish time + + //Print estimated time of completion + ns.print("Growing " + sTarget + " Estimated complete at " + sGrowTime); + ns.print("Growing with " + nGrowThreadsINT + " threads on " + sTarget); + let nGrowPID = ns.run(sGrowScript, nGrowThreadsINT, sTarget); + if (nGrowPID === 0) { ns.print("Grow Failed..."); } + nMaxRAM = ns.getServerMaxRam(sRunner); + nUsedRAM = ns.getServerUsedRam(sRunner); + nFreeRam = nMaxRAM - nUsedRAM; + while (nFreeRam <= (nHackScriptRAM * nHackThreads) + nHomeServerReserve + 6) { + await ns.sleep(100); + nMaxRAM = ns.getServerMaxRam(sRunner); + nUsedRAM = ns.getServerUsedRam(sRunner); + nFreeRam = nMaxRAM - nUsedRAM; - if (nCurrentSecurity <= (nMinSecurity + 5)) { + } + + if (nCurrentMoney >= nMaxMoney * 0.8 && nFreeRam > (nHackScriptRAM * nHackThreads) + nHomeServerReserve + 6) { //Calculate estimate time of completion - nOffset = ns.getGrowTime(sTarget); - let nGrowTime = new Date(currentDate.getTime() + nOffset); - let sGrowTime = nGrowTime.toLocaleTimeString('sw-SV'); //swedish time + nOffset = ns.getHackTime(sTarget); + let nHackTime = new Date(currentDate.getTime() + nOffset); + let sHackTime = nHackTime.toLocaleTimeString('sw-SV'); //swedish time //Print estimated time of completion - ns.print("Growing " + sTarget + " Estimated complete at " + sGrowTime); + ns.print("Hacking " + sTarget + " Estimated complete at " + sHackTime); + ns.print("Hacking with " + nHackThreads + " threads on " + sTarget); + let mHackPID = ns.run(sHackScript, nHackThreads, sTarget); + if (mHackPID === 0) { ns.print("Hack Failed..."); } - - - if (nCurrentMoney >= nMaxMoney * 0.8) { - - //Calculate estimate time of completion - nOffset = ns.getHackTime(sTarget); - let nHackTime = new Date(currentDate.getTime() + nOffset); - let sHackTime = nHackTime.toLocaleTimeString('sw-SV'); //swedish time - - //Print estimated time of completion - ns.print("Hacking " + sTarget + " Estimated complete at " + sHackTime); - - ns.run(sHackScript, 1, sTarget); - } - ns.run(sGrowScript, 10, sTarget); } - ns.run(sWeakenScript, 5, sTarget); - nFreeRam = ns.getServerMaxRam(sRunner) - ns.getServerUsedRam(sRunner); - await ns.sleep(nFrequency); - ns.print("-------------------------------------------------------------------------"); } - } - else { - ns.tprint("Insufficient estimated required RAM... no scripts were started..."); + await ns.sleep(nFrequency); + ns.print("-------------------------------------------------------------------------"); } } \ No newline at end of file diff --git a/local/path/home/bestTarget.txt b/local/path/home/bestTarget.txt index ef50055..55ddf0d 100644 --- a/local/path/home/bestTarget.txt +++ b/local/path/home/bestTarget.txt @@ -1 +1 @@ -{"serverName":"omega-net","maxRam":32,"maxMoney":69174578,"minSec":10,"minPorts":2,"minHackLvl":202,"rootAccess":true,"factorMoneyPerTime":0.0319075530954955,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js","the-new-god.lit"]} \ No newline at end of file +{"serverName":"the-hub","maxRam":32,"maxMoney":483168296.25,"minSec":13,"minPorts":2,"minHackLvl":318,"rootAccess":true,"factorMoneyPerTime":0.1841702873569451,"openPorts":0,"serverFiles":["factionboost.js"],"hackingChance":0.40919188586028893} \ No newline at end of file diff --git a/local/path/home/breach.js b/local/path/home/breach.js new file mode 100644 index 0000000..32fc888 --- /dev/null +++ b/local/path/home/breach.js @@ -0,0 +1,63 @@ +/** @param {NS} ns */ +export async function main(ns) { + //args + const sTarget = ns.args[0]; // target server + + // declare objects + const oHome = ns.getServer("home"); + //const oTarget = ns.getServer(sTarget); + + //declare variables + const sScriptName = ns.getScriptName(); + const sWeakenScript = "RMweaken.js"; + const nScriptRAM = ns.getScriptRam(sScriptName); + const sBatch = "EveryServerRun.js"; + const nCores = oHome.cpuCores; + let nSecurity = ns.getServerSecurityLevel(sTarget); + const nMinSecurity = ns.getServerMinSecurityLevel(sTarget); + const nWeakenSTR = ns.weakenAnalyze(1, nCores); + const nThreads = Math.ceil((nSecurity - nMinSecurity) / nWeakenSTR); + ns.tprint("nThreads = " + nThreads); + + + ns.tail(ns.pid, oHome.hostname, sTarget); + //ns.resizeTail(815, 395); + //ns.moveTail(1925, 0); + + if (nThreads > 0) { + const nDelay = ns.getWeakenTime(sTarget); + + ns.tprint("current security is: " + nSecurity); + ns.tprint("minimum security is: " + nMinSecurity); + ns.tprint("threads needed for weaken: " + nThreads); + ns.tprint(nThreads + " will reduce Security by " + ns.weakenAnalyze(nThreads, nCores)); + ns.tprint(nThreads + " of " + sWeakenScript + " requires " + (ns.getScriptRam(sWeakenScript, "home") * nThreads) + " GB of RAM"); + ns.tprint("weakening will take " + (nDelay / 1000 / 60) + " minutes"); + + if ((ns.getServerMaxRam(oHome.hostname) - ns.getServerUsedRam(oHome.hostname)) >= (ns.getScriptRam(sWeakenScript, "home") * nThreads)) { + + + + ns.run(sWeakenScript, nThreads, sTarget); + await ns.sleep(Math.ceil(nDelay)); + nSecurity = ns.getServerSecurityLevel(sTarget); + ns.tprint("Breach complete, security level is now at: " + nSecurity); + + //run batch + const nBatchPID = ns.run(sBatch, 1, sTarget); + ns.tail(nBatchPID, "home", sBatch, 1, sTarget); + ns.resizeTail(815, 395, nBatchPID); + ns.moveTail(1925, 0, nBatchPID); + } + else { + ns.tprint("try to loop untill finished"); + let nScripts = Math.ceil((ns.getServerMaxRam("home") - ns.getServerUsedRam("home")) / ns.getScriptRam(sWeakenScript, "home")-nScriptRAM); + ns.tprint("nScripts = " + nScripts); + ns.run(sWeakenScript, nScripts, sTarget); + await ns.sleep(Math.ceil(nDelay)); + } + } + + + +} \ No newline at end of file diff --git a/local/path/home/analyzeContract.js b/local/path/home/contract.js similarity index 100% rename from local/path/home/analyzeContract.js rename to local/path/home/contract.js diff --git a/local/path/home/controller.js b/local/path/home/controller.js deleted file mode 100644 index 3fc03eb..0000000 --- a/local/path/home/controller.js +++ /dev/null @@ -1,384 +0,0 @@ -/* -Welcome to part 3. I'll only be commenting on things that have changed from the previous parts, so if there's something -confusing, be sure to go back and look at parts 1 and 2 for more detailed explanations. - -This time we're going to make a shotgun batcher. In some ways this is really just a protobatcher that makes a -much larger batch. We're going to fill up ram with as many batches as we can manage, wait for them to finish, then -fire off another blast. - -Note that this is mainly written with the fact that I intend to adapt this into a continuous batcher later in mind. -There are far more optimal ways to run a shotgun-style batcher, but rather than make the best shotgun I could, -I aimed to make this an ideal stepping stone on the quest for a continuous batcher. -*/ - -import { getServers, copyScripts, checkTarget, isPrepped, prep } from "/utils.js"; - -const TYPES = ["hack", "weaken1", "grow", "weaken2"]; -const WORKERS = ["tHack.js", "tWeaken.js", "tGrow.js"]; -const SCRIPTS = { hack: "tHack.js", weaken1: "tWeaken.js", grow: "tGrow.js", weaken2: "tWeaken.js" }; -const COSTS = { hack: 1.7, weaken1: 1.75, grow: 1.75, weaken2: 1.75 }; -// We won't be using the offsets anymore, but I've left them here in case we bring them back for a later part. -// const OFFSETS = { hack: 0, weaken1: 1, grow: 2, weaken2: 3 }; - -/** @param {NS} ns */ -export async function main(ns) { - ns.disableLog("ALL"); - ns.tail(); - - while (true) { - // Setup is mostly the same. - const dataPort = ns.getPortHandle(ns.pid); - dataPort.clear(); - let target = "n00dles"; - const servers = getServers(ns, (server) => { - target = checkTarget(ns, server, target, ns.fileExists("Formulas.exe", "home")); - copyScripts(ns, server, WORKERS, true); - return ns.hasRootAccess(server); - }); - /* manual override */ - target = "max-hardware"; - const ramNet = new RamNet(ns, servers); - const metrics = new Metrics(ns, target); - if (!isPrepped(ns, target)) await prep(ns, metrics, ramNet); - ns.clearLog(); - ns.print("Optimizing. This may take a few seconds...") - /* - New optimizer is async because it can take upwards of 5 seconds to run. We can afford the heavy - computations because shotgun batchers are very front-loaded. In a "real" shotgun batcher, you'll want - to modify the ramnet so that you can do this during the downtime between mega-batches. - */ - await optimizeShotgun(ns, metrics, ramNet); // See the function below for details. - metrics.calculate(ns); - - // I've renamed the schedule array from "batch" to "jobs" just for clarity purposes. - // The batchCount declaration has also been moved down here because we use it for scheduling. - const jobs = []; - let batchCount = 0; - - // Another change. Instead of tracking the end times by type, I'm now using a unified end time. - // This makes the scheduling a bit simpler as long as we're always going in chronological order. - metrics.end = Date.now() + metrics.wTime - metrics.spacer; - - // Instead of one batch, we repeat the scheduling based on the depth calculated by the optimizer. - while (batchCount++ < metrics.depth) { - for (const type of TYPES) { - // As you can see, calculating the end time for each new job is much simpler this way. - // The rest of the scheduling is mostly unchanged. - metrics.end += metrics.spacer; - - // Batchcount is part of the constructor now. Yes I was that lazy in the last part. - const job = new Job(type, metrics, batchCount); - if (!ramNet.assign(job)) { - ns.print(`ERROR: Unable to assign ${type}. Dumping debug info:`); - ns.print(job); - ns.print(metrics); - ramNet.printBlocks(ns); - return; - } - jobs.push(job); - } - } - - /* - Deployment is completely unchanged. However, with the much larger batch sizes, you may find that - this can potentially freeze the game for minutes at a time. If it's too disruptive or triggers the - infinite loop failsafe, you can uncomment the sleep line. - - There's really no need to do this synchronously for our batcher, but in a "real" shotgun batcher, you wouldn't - use any spacers at all, and try to keep deployment time and execution time down to as little as possible in order - to minimize downtime. - */ - for (const job of jobs) { - job.end += metrics.delay; - const jobPid = ns.exec(SCRIPTS[job.type], job.server, { threads: job.threads, temporary: true }, JSON.stringify(job)); - if (!jobPid) throw new Error(`Unable to deploy ${job.type}`); - const tPort = ns.getPortHandle(jobPid); - await tPort.nextWrite(); - metrics.delay += tPort.read(); - } - - /* - This is a silly hack. Due to the way arrays work in JS, pop() is much faster than shift() and we're - going to be accessing these jobs in FIFO order in a moment (ie. a queue). Since we've got lots of downtime - and the jobs array can get really huge, I just reverse them now to save time later. - - We'll be implementing a more sophisticated schedule in the next part. - */ - jobs.reverse(); - - // I've stepped up the logging/feedback a bit here, but it's otherwise pretty much the same. - const timer = setInterval(() => { - ns.clearLog(); - ns.print(`Hacking ~\$${ns.formatNumber(metrics.maxMoney * metrics.greed * batchCount * metrics.chance)} from ${metrics.target}`); - ns.print(`Greed: ${Math.floor(metrics.greed * 1000) / 10}%`); - ns.print(`Ram available: ${ns.formatRam(ramNet.totalRam)}/${ns.formatRam(ramNet.maxRam)}`); - ns.print(`Total delay: ${metrics.delay}ms`); - ns.print(`Active jobs remaining: ${jobs.length}`); - ns.print(`ETA ${ns.tFormat(metrics.end - Date.now())}`); - }, 1000); - ns.atExit(() => { - clearInterval(timer); - }); - - /* - As each job finishes, we update the ramnet to reflect it. Once the queue is empty, we start over. - Updating the ramnet like this isn't really necessary since we're just going to rebuild it entirely in - the next iteration, but I wanted to demonstrate what it will look like in preparation for the next part. - */ - do { - await dataPort.nextWrite(); - dataPort.clear(); - - // It's technically possible that some of these might finish out of order due to lag or something. - // But it doesn't actually matter since we're not doing anything with this data yet. - ramNet.finish(jobs.pop()); - } while (jobs.length > 0); - clearInterval(timer); - } -} - -// The Job class, lean as it is, remains mostly unchanged. I got rid of the server argument since I wasn't using it -// and added a batch number instead. -class Job { - constructor(type, metrics, batch) { - this.type = type; - // this.end = metrics.ends[type]; // Left in for now, in case I decided to use it again later. - this.end = metrics.end; // Using the unified end time now. - this.time = metrics.times[type]; - this.target = metrics.target; - this.threads = metrics.threads[type]; - this.cost = this.threads * COSTS[type]; - this.server = "none"; - this.report = true; // All workers now report when they finish. - this.port = metrics.port; - this.batch = batch; - - // Future stuff. Ignore these. - // this.status = "active"; - // this.id = type + batch; - } -} - -// Almost entirely the same, aside from the changes to end time. -/** @param {NS} ns */ -class Metrics { - constructor(ns, server) { - this.target = server; - this.maxMoney = ns.getServerMaxMoney(server); - this.money = Math.max(ns.getServerMoneyAvailable(server), 1); - this.minSec = ns.getServerMinSecurityLevel(server); - this.sec = ns.getServerSecurityLevel(server); - this.prepped = isPrepped(ns, server); - this.chance = 0; - this.wTime = 0; - this.delay = 0; - this.spacer = 5; - this.greed = 0.1; - this.depth = 0; // The number of concurrent batches to run. Set by the optimizer. - - this.times = { hack: 0, weaken1: 0, grow: 0, weaken2: 0 }; - this.end = 0; // Slight change for the new timing. The old way in commented out in case I switch back later. - // this.ends = { hack: 0, weaken1: 0, grow: 0, weaken2: 0 }; - this.threads = { hack: 0, weaken1: 0, grow: 0, weaken2: 0 }; - - this.port = ns.pid; - } - - // Almost totally unchanged, except that I've commented out the default depth calculation, since it's done elsewhere. - calculate(ns, greed = this.greed) { - const server = this.target; - const maxMoney = this.maxMoney; - this.money = ns.getServerMoneyAvailable(server); - this.sec = ns.getServerSecurityLevel(server); - this.wTime = ns.getWeakenTime(server); - this.times.weaken1 = this.wTime; - this.times.weaken2 = this.wTime; - this.times.hack = this.wTime / 4; - this.times.grow = this.wTime * 0.8; - // this.depth = this.wTime / this.spacer * 4; - - const hPercent = ns.hackAnalyze(server); - const amount = maxMoney * greed; - const hThreads = Math.max(Math.floor(ns.hackAnalyzeThreads(server, amount)), 1); - const tGreed = hPercent * hThreads; - - // Okay I lied. We now overestimate grow threads by 1%. This helps prevent level ups from causing desyncs. - // Only a little, though. If you gain too many levels per shotgun blast, it will still have to re-prep the server. - const gThreads = Math.ceil(ns.growthAnalyze(server, maxMoney / (maxMoney - maxMoney * tGreed)) * 1.01); - this.threads.weaken1 = Math.max(Math.ceil(hThreads * 0.002 / 0.05), 1); - this.threads.weaken2 = Math.max(Math.ceil(gThreads * 0.004 / 0.05), 1); - this.threads.hack = hThreads; - this.threads.grow = gThreads; - this.chance = ns.hackAnalyzeChance(server); - } -} - -// Once again, not a whole lot of changes. I've added a new function in support of the optimizer. Details below. -/** @param {NS} ns */ -class RamNet { - #blocks = []; - #minBlockSize = Infinity; - #maxBlockSize = 0; - #totalRam = 0; - #maxRam = 0; - #prepThreads = 0; - #index = new Map(); - constructor(ns, servers) { - for (const server of servers) { - if (ns.hasRootAccess(server)) { - const maxRam = ns.getServerMaxRam(server); - const ram = maxRam - ns.getServerUsedRam(server); - if (ram >= 1.60) { - const block = { server: server, ram: ram }; - this.#blocks.push(block); - if (ram < this.#minBlockSize) this.#minBlockSize = ram; - if (ram > this.#maxBlockSize) this.#maxBlockSize = ram; - this.#totalRam += ram; - this.#maxRam += maxRam; - this.#prepThreads += Math.floor(ram / 1.75); - } - } - } - this.#sort(); - this.#blocks.forEach((block, index) => this.#index.set(block.server, index)); - } - - #sort() { - this.#blocks.sort((x, y) => { - if (x.server === "home") return 1; - if (y.server === "home") return -1; - - return x.ram - y.ram; - }); - } - - get totalRam() { - return this.#totalRam; - } - - get maxRam() { - return this.#maxRam; - } - - get maxBlockSize() { - return this.#maxBlockSize; - } - - get prepThreads() { - return this.#prepThreads; - } - - getBlock(server) { - if (this.#index.has(server)) { - return this.#blocks[this.#index.get(server)]; - } else { - throw new Error(`Server ${server} not found in RamNet.`); - } - } - - assign(job) { - const block = this.#blocks.find(block => block.ram >= job.cost); - if (block) { - job.server = block.server; - block.ram -= job.cost; - this.#totalRam -= job.cost; - return true; - } else return false; - } - - finish(job) { - const block = this.getBlock(job.server); - block.ram += job.cost; - this.#totalRam += job.cost; - } - - cloneBlocks() { - return this.#blocks.map(block => ({ ...block })); - } - - printBlocks(ns) { - for (const block of this.#blocks) ns.print(block); - } - - // This function takes an array of job costs and simulates assigning them to see how many batches it can fit. - testThreads(threadCosts) { - // Clone the blocks, since we don't want to actually change the ramnet. - const pRam = this.cloneBlocks(); - let batches = 0; - let found = true; - while (found) { - // Pretty much just a copy of assign(). Repeat until a batch fails to assign all it's jobs. - for (const cost of threadCosts) { - found = false; - const block = pRam.find(block => block.ram >= cost); - if (block) { - block.ram -= cost; - found = true; - } else break; - } - if (found) batches++; // If all of the jobs were assigned successfully, +1 batch and loop. - } - return batches; // Otherwise, we've found our number. - } -} - -// This one's got some pretty big changes, even if it doesn't look like it. For one, it's now async, and you'll see why. -/** - * @param {NS} ns - * @param {Metrics} metrics - * @param {RamNet} ramNet - */ -async function optimizeShotgun(ns, metrics, ramNet) { - // Setup is mostly the same. - const maxThreads = ramNet.maxBlockSize / 1.75; - const maxMoney = metrics.maxMoney; - const hPercent = ns.hackAnalyze(metrics.target); - const wTime = ns.getWeakenTime(metrics.target); // We'll need this for one of our calculations. - - const minGreed = 0.001; - const stepValue = 0.01; // Step value is now 10x higher. If you think that's overkill, it's not. - let greed = 0.99; - let best = 0; // Initializing the best value found. - - // This algorithm starts out pretty much the same. We begin by weeding out the obviously way too huge greed levels. - while (greed > minGreed) { - const amount = maxMoney * greed; - const hThreads = Math.max(Math.floor(ns.hackAnalyzeThreads(metrics.target, amount)), 1); - const tGreed = hPercent * hThreads; - // 1% overestimation here too. Always make sure your calculations match. - const gThreads = Math.ceil(ns.growthAnalyze(metrics.target, maxMoney / (maxMoney - maxMoney * tGreed)) * 1.01); - - if (Math.max(hThreads, gThreads) <= maxThreads) { - const wThreads1 = Math.max(Math.ceil(hThreads * 0.002 / 0.05), 1); - const wThreads2 = Math.max(Math.ceil(gThreads * 0.004 / 0.05), 1); - - const threadCosts = [hThreads * 1.7, wThreads1 * 1.75, gThreads * 1.75, wThreads2 * 1.75]; - - // These lines were supposed to help weed out a few more too-high values, but in my unit tests they never - // actually did anything. Uncomment them if you want. - // const totalCost = threadCosts.reduce((t, c) => t + c); - // if (totalCost > ramNet.totalRam) continue; - - /* - Here's where it all changes. First we calculate the number of batches we can fit into ram at the current - greed level. Then we calculate how much money that nets and how long it will take. If that income/time is - better than what we've found before, we update the metrics and then continue. - - Unlike the previous version, this one checks every value. Between that and the loop to simulate assigning - jobs, this is a very heavy algorithm that can take seconds to execute if done synchronously. To prevent it - from freezing the game, we run it asynchronously and sleep after checking each value. - */ - const batchCount = ramNet.testThreads(threadCosts); - const income = tGreed * maxMoney * batchCount / (metrics.spacer * 4 * batchCount + wTime); - if (income > best) { - best = income; - metrics.greed = tGreed; - metrics.depth = batchCount; - } - } - await ns.sleep(0); - greed -= stepValue; - } - // Added the check here to only throw an error if we failed to find any valid configurations. - if (best === 0) throw new Error("Not enough ram to run even a single batch. Something has gone seriously wrong."); -} \ No newline at end of file diff --git a/local/path/home/corp/Autosell.js b/local/path/home/corp/Autosell.js deleted file mode 100644 index ae30880..0000000 --- a/local/path/home/corp/Autosell.js +++ /dev/null @@ -1,7 +0,0 @@ -/** @param {NS} ns */ -export async function main(ns) { - let cities = ["Sector-12", "Aevum", "Volhaven", "Chongqing", "New Tokyo", "Ishima"]; - let corpName = "AgraNeo"; - ns.tprint(ns.corporation.getMaterial(corpName,cities[0],"Plants")) - ns.corporation.sellMaterial() -} \ No newline at end of file diff --git a/local/path/home/corp/HireWorkers.js b/local/path/home/corp/HireWorkers.js deleted file mode 100644 index 22fefa0..0000000 --- a/local/path/home/corp/HireWorkers.js +++ /dev/null @@ -1,16 +0,0 @@ -/** @param {NS} ns */ -export async function main(ns) { - let cities = ["Sector-12", "Aevum", "Volhaven", "Chongqing", "New Tokyo", "Ishima"]; - let corpName = "ChemNeo"; - let currentSize = 0; - for (let city of cities) { - - let currentOffice=(ns.corporation.getOffice(corpName, city)); - if (currentOffice.numEmployees < currentOffice.size) { - (currentOffice.employeeJobs.Operations < 1) ? ns.corporation.hireEmployee(corpName, city,"Operations") : ""; - (currentOffice.employeeJobs.Engineer < 1) ? ns.corporation.hireEmployee(corpName, city,"Engineer") : ""; - (currentOffice.employeeJobs.Business < 1) ? ns.corporation.hireEmployee(corpName, city,"Business") : ""; - (currentOffice.employeeJobs.Management < 1) ? ns.corporation.hireEmployee(corpName, city,"Management") : ""; - }; - } -} \ No newline at end of file diff --git a/local/path/home/corp/SetupExport.js b/local/path/home/corp/SetupExport.js deleted file mode 100644 index 69c0dd4..0000000 --- a/local/path/home/corp/SetupExport.js +++ /dev/null @@ -1,13 +0,0 @@ -/** @param {NS} ns */ -export async function main(ns) { - let cities = ["Sector-12", "Aevum", "Volhaven", "Chongqing", "New Tokyo", "Ishima"]; - let corpName1 = ["AgraNeo","Plants"]; - let corpName2 = ["ChemNeo","Chemicals"]; - let exportString = "IPROD*-1" - for (let city of cities) { - ns.corporation.cancelExportMaterial(corpName1[0],city,corpName2[0],city,corpName1[1]); - ns.corporation.cancelExportMaterial(corpName2[0],city,corpName1[0],city,corpName2[1]); - ns.corporation.exportMaterial(corpName1[0],city,corpName2[0],city,corpName1[1],exportString); - ns.corporation.exportMaterial(corpName2[0],city,corpName1[0],city,corpName2[1],exportString); - } -} \ No newline at end of file diff --git a/local/path/home/corp/Smart.js b/local/path/home/corp/Smart.js deleted file mode 100644 index e733958..0000000 --- a/local/path/home/corp/Smart.js +++ /dev/null @@ -1,6 +0,0 @@ -/** @param {NS} ns */ -export async function main(ns) { - let [corpName, city] = ns.args; - //ns.corporation.setSmartSupply(corpName, city, true); - return true; -} \ No newline at end of file diff --git a/local/path/home/corp/UpgradeOffice.js b/local/path/home/corp/UpgradeOffice.js deleted file mode 100644 index e811f44..0000000 --- a/local/path/home/corp/UpgradeOffice.js +++ /dev/null @@ -1,12 +0,0 @@ -/** @param {NS} ns */ -export async function main(ns) { - let cities = ["Sector-12", "Aevum", "Volhaven", "Chongqing", "New Tokyo", "Ishima"]; - let corpName = "ChemNeo"; - let currentSize = 0; - for (let city of cities) { - currentSize = ns.corporation.getOffice(corpName, city).size; - if (currentSize < 4) { - ns.corporation.upgradeOfficeSize(corpName, city, 4 - currentSize); - }; - } -} \ No newline at end of file diff --git a/local/path/home/fixpserv.js b/local/path/home/fixpserv.js new file mode 100644 index 0000000..6e11d95 --- /dev/null +++ b/local/path/home/fixpserv.js @@ -0,0 +1,46 @@ +/** @param {NS} ns */ +export async function main(ns) { + /* + ns.renamePurchasedServer("pserv-23", "pserv-24"); + ns.renamePurchasedServer("pserv-22", "pserv-23"); + ns.renamePurchasedServer("pserv-21", "pserv-22"); + ns.renamePurchasedServer("pserv-20", "pserv-21"); + ns.renamePurchasedServer("pserv-19", "pserv-20"); + ns.renamePurchasedServer("pserv-18", "pserv-19"); + ns.renamePurchasedServer("pserv-17", "pserv-18"); + ns.renamePurchasedServer("pserv-16", "pserv-17"); + ns.renamePurchasedServer("pserv-15", "pserv-16"); + ns.renamePurchasedServer("pserv-14", "pserv-15"); + ns.renamePurchasedServer("pserv-13", "pserv-14"); + ns.renamePurchasedServer("pserv-12", "pserv-13"); + ns.renamePurchasedServer("pserv-11", "pserv-12"); + ns.renamePurchasedServer("pserv-10", "pserv-11"); + ns.renamePurchasedServer("pserv-9", "pserv-10"); + ns.renamePurchasedServer("pserv-8", "pserv-9"); + ns.renamePurchasedServer("pserv-7", "pserv-8"); + ns.renamePurchasedServer("pserv-6", "pserv-7"); + ns.renamePurchasedServer("pserv-5", "pserv-6"); + ns.renamePurchasedServer("pserv-4", "pserv-5"); + ns.renamePurchasedServer("pserv-3", "pserv-4"); + ns.renamePurchasedServer("pserv-2", "pserv-3"); + ns.renamePurchasedServer("pserv-1-0", "pserv-2"); +*/ + ns.renamePurchasedServer("pserv-1", "pserv-01"); + ns.renamePurchasedServer("pserv-2", "pserv-02"); + ns.renamePurchasedServer("pserv-3", "pserv-03"); + ns.renamePurchasedServer("pserv-4", "pserv-04"); + ns.renamePurchasedServer("pserv-5", "pserv-05"); + ns.renamePurchasedServer("pserv-6", "pserv-06"); + ns.renamePurchasedServer("pserv-7", "pserv-07"); + ns.renamePurchasedServer("pserv-8", "pserv-08"); + ns.renamePurchasedServer("pserv-9", "pserv-09"); + + + + //const nServers = ns.getPurchasedServers(); + + //for (let i = 0; i < nServers; i++) + //let hostname = ns.purchaseServer("pserv-" + i, ram); + // ns.renamePurchasedServer(([i]), "pserv-" + i); + +} \ No newline at end of file diff --git a/local/path/home/gang/argFunctions.js b/local/path/home/gang/argFunctions.js new file mode 100644 index 0000000..928a340 --- /dev/null +++ b/local/path/home/gang/argFunctions.js @@ -0,0 +1,30 @@ +export function GetFlag(ns, flag) +{ + return ns.args.includes(flag); +} + +export function GetArg(ns, arg, def = null) +{ + for(var i = 0; i < ns.args.length - 1; i++) + { + if(ns.args[i] == arg) + { + return ns.args[i+1]; + } + } + + return def; +} + +export function GetIndex(ns, arg) +{ + for(var i = 0; i < ns.args.length; i++) + { + if(ns.args[i] == arg) + { + return i; + } + } + + return -1; +} \ No newline at end of file diff --git a/local/path/home/gang/auto-gang.js b/local/path/home/gang/auto-gang.js new file mode 100644 index 0000000..30be000 --- /dev/null +++ b/local/path/home/gang/auto-gang.js @@ -0,0 +1,114 @@ +/* + +A 'cycle' lasts 5 minutes and the current task for any given member on a cycle +is set by taking the cycle and their member index and modding by the number +of tasks in your list, so it should spread out tasks evenly among your members, +and each one should progress through the list of tasks, although when you start +only the first member will start on task 0. + +Set 'upgradeEquipmentNames' to a list of the gear you want to purchase, +currently it gets a list of all equipment by type and includes all types. + + + +Jobs are: + [ + "Unassigned", + "Mug People", + "Deal Drugs", + "Strongarm Civilians", + "Run a Con", + "Armed Robbery", + "Traffick Illegal Arms", + "Threaten & Blackmail", + "Human Trafficking", + "Terrorism", + "Vigilante Justice", + "Train Combat", + "Train Hacking", + "Train Charisma", + "Territory Warfare" +] + +*/ + +const DURATION = 5 * 60 * 1000 // 5 minutes + +const newMemberNames = ('General Kenobi,General Zod,Admiral Akbar,Admiral Thrawn' + + ',Colonel Duke,Colonel Nick Fury,Major Tom,Major Paine' + + ',Corporal Klinger,Corporal Barnes,Sergeant Slaughter,Sergeant Smith').split(',') + +/** @param {NS} ns */ +export async function main(ns) { + // // show list of job names + // ns.tprint(JSON.stringify(ns.gang.getTaskNames(), null, 2)) + // return + + ns.disableLog('ALL') + + // what gear will we buy after ascension? + let equipmentNames = ns.gang.getEquipmentNames() + let upgradeEquipmentNames = equipmentNames.filter(x => ['Weapon', 'Armor', 'Vehicle', 'Rootkit', 'Augmentation'].find(y => ns.gang.getEquipmentType(x) === y)) + + let cycle = 0 + + // with 6 jobs and 12 members, we should have two members on each + let cycleTasks = ['Train Combat', 'Train Combat', + 'Vigilante Justice', 'Terrorism', + 'Human Trafficking', 'Territory Warfare'] + + while (true) { + let memberNames = ns.gang.getMemberNames() + ns.print(`Cycle ${cycle} activating for ${memberNames.length} gang members`) + memberNames.forEach((name, index) => { + let taskIndex = (cycle + index) % cycleTasks.length + if (taskIndex === 0) { + let result = ns.gang.ascendMember(name) + if (result) ns.print(`INFO: Ascended gang member ${name}:\n Hack:${sf(result.hack)}, Str:${sf(result.str)}, Def:${sf(result.def)}, Dex:${sf(result.dex)}, Agi:${sf(result.agi)}`) + // if (result) ns.print(`INFO: Ascended gang member ${name}:\n ${JSON.stringify(result)}`) + purchaseEquipment(name) + } + ns.gang.setMemberTask(name, cycleTasks[taskIndex]) + }) + + // hire new members if possible and set them to first job for this cycle, + // should be training probably + if (ns.gang.canRecruitMember()) { + newMemberNames.forEach(name => { + if (ns.gang.recruitMember(name)) { + ns.print(`INFO: Recruited new gang member '${name}`) + ns.gang.setMemberTask(name, cycleTasks[0]) + purchaseEquipment() + } + }) + } + + let cycleEnd = new Date(new Date().valueOf() + DURATION).toLocaleTimeString() + ns.print(`Next cycle at ${cycleEnd}`) + await ns.sleep(DURATION) // wait 5 minutes + cycle++ + } + + /** + * Purchase equipment for a gang member if we have the money + * + * @param {string} memberName Name of the gang member to purchase equipment for + */ + function purchaseEquipment(memberName) { + let { money } = ns.getPlayer() + upgradeEquipmentNames.forEach(equipName => { + let cost = ns.gang.getEquipmentCost(equipName) + if (money >= cost && ns.gang.purchaseEquipment(memberName, equipName)) money -= cost + }) + } + + /** + * Simple format for stats + * + * @param {number} value + */ + function sf(value) { + if (typeof(value) !== 'number') return '???' + return Math.trunc(value * 1000) / 1000 + } +} \ No newline at end of file diff --git a/local/path/home/gang/auto-gang2.js b/local/path/home/gang/auto-gang2.js new file mode 100644 index 0000000..d35977e --- /dev/null +++ b/local/path/home/gang/auto-gang2.js @@ -0,0 +1,144 @@ +const TASK_TRAIN = "Train Combat"; +const TASK_VIGI = "Vigilante Justice"; +const TASK_NOOB = String.fromCharCode(77) + "ug People"; +const TASK_RESPECT = String.fromCharCode(84) + "errorism"; +const TASK_MONEY = "Human " + String.fromCharCode(84) + "rafficking"; +const TASK_WARFARE = "Territory Warfare"; +const TASK_NULL = "Unassigned"; +const TASK_MANUAL = "Manual/NotReallyTaskName"; + +const ASCEND_ON_MPL = 10; +const EQUIP_AFFORD_COEFF = 100; + +const STATS_TRESHOLD = 0.7; +const STATS_MIN = 4000; +const STATS_HARD_MIN = 200; +const TRAIN_CHANCE = 0.2; +const RESPECT_MIN = 2e+7; + +const WANTED_PENALTY_TRESHOLD = 0.99; +const WARFARE_TRESHOLD = 2; + +const MEMBERS_MIN = 6; +const MEMBERS_MAX = 12; + +const SLEEP_TIME = 10000; + +/** @param {NS} ns **/ +export async function main(ns) { + ns.tail(); + const gang = ns.gang; + // Get weighted stats sum (at this moment, sum of combat stats in eq proportions) + function getStatsSum(member) { + const info = gang.getMemberInformation(member); + return info.str + info.def + info.dex + info.agi; + } + // Find the best gang power except our gang + function maxEnemyPower(myGang) { + const others = ns.gang.getOtherGangInformation(); + let maxPower = 0; + for (let name in others) { + if (name === myGang.faction) continue; + maxPower = Math.max(maxPower, others[name].power); + } + return maxPower; + } + // Set a task or not to set (if manually overridden) + const autoTasks = {} + function setAutoTask(member, task) { + const info = gang.getMemberInformation(member); + const lastTask = info.task; + // Manual task: stored task mismatches real task and not unassigned + if (lastTask !== TASK_NULL && autoTasks.hasOwnProperty(member) && autoTasks[member] !== lastTask) { + autoTasks[member] = TASK_MANUAL; + return; + } + // Automatic task: set it if differs from real one + autoTasks[member] = task; + if (lastTask !== task) { + gang.setMemberTask(member, task); + } + } + // The script accepts argument for default task override (optional) + let defaultTask = null; + if (ns.args[0] && gang.getTaskNames().includes(ns.args[0])) { + defaultTask = ns.args[0]; + } + // Main loop + for (; ;) { + // Recruit any member possible + while (gang.canRecruitMember()) { + gang.recruitMember('member' + Math.random().toString().substr(2, 3)); + } + let bestStats = STATS_MIN / STATS_TRESHOLD; // minimum + const members = gang.getMemberNames(); + const info = gang.getGangInformation(); + // Ascend if good enough + for (let member of members) { + const r = gang.getAscensionResult(member); + if (!r) continue; + const mpl = r.agi * r.def * r.dex * r.str; + if (mpl > ASCEND_ON_MPL) { + gang.ascendMember(member); + ns.tprint(`Member ${member} ascended!`); + } + } + // Purchase equipment + const allEquip = gang.getEquipmentNames(); + let money = ns.getServerMoneyAvailable('home'); + for (let equip of allEquip) { + const cost = gang.getEquipmentCost(equip); + const amount = money / cost; + if (amount < EQUIP_AFFORD_COEFF) continue; + for (let member of members) { + const info = gang.getMemberInformation(member); + if (info.upgrades.includes(equip) || info.augmentations.includes(equip)) continue; + if (gang.purchaseEquipment(member, equip)) { + money -= cost; + } + } + } + // Find best stats + for (let member of members) { + let sum = getStatsSum(member); + if (sum > bestStats) bestStats = sum; + } + // Check if we are powerful enough + let powerfulEnough = info.power >= maxEnemyPower(info) * WARFARE_TRESHOLD; + gang.setTerritoryWarfare(powerfulEnough); + // Choose the default task for members + let task = defaultTask; + if (!defaultTask) { + // If gang isn't full - gain respect + if (members.length < MEMBERS_MAX) { + task = (members.length < MEMBERS_MIN) ? TASK_NOOB : TASK_RESPECT; + } else { + // if respect too low - gain it first, power second, money last + if (info.respect < RESPECT_MIN) { + task = TASK_RESPECT; + } else if (!powerfulEnough) { + task = TASK_WARFARE; + } else { + task = TASK_MONEY; + } + } + } + // Assign tasks + for (let member of members) { + let sum = getStatsSum(member); + // Train members, not acceptable in 'noob mode' + if (sum < STATS_HARD_MIN || (members.length >= MEMBERS_MIN && sum < bestStats * STATS_TRESHOLD)) { + setAutoTask(member, TASK_TRAIN); + continue; + } + // Vigi if wanted penalty too large + if (info.wantedLevel > 2 && info.wantedPenalty < WANTED_PENALTY_TRESHOLD) { + setAutoTask(member, TASK_VIGI); + continue; + } + // Do the default task (autoselected or called with args[0]) + setAutoTask(member, Math.random() < TRAIN_CHANCE ? TASK_TRAIN : task); + } + await ns.sleep(SLEEP_TIME); + } +} \ No newline at end of file diff --git a/local/path/home/gang/gangManager.js b/local/path/home/gang/gangManager.js new file mode 100644 index 0000000..36323aa --- /dev/null +++ b/local/path/home/gang/gangManager.js @@ -0,0 +1,219 @@ +import { GetFlag, GetArg } from "gang/argFunctions.js"; + +function getRandomInt(max) { + return Math.floor(Math.random() * Math.floor(max)); +} + +// 30 possible gang members +// create list of names +let memberNamePool = [ + "Thor", // 1 + "Iron Man", // 2 + "Starlord", // 3 + "Thanos", // 4 + "Groot", // 5 + "Ant-Man", // 6 + "Wasp", // 7 + "Spiderman", // 8 + "Loki", // 9 + "Gamora", // 10 + "Rocket Raccoon", // 11 + "T'Challa", // 12 + "Vision", // 13 + "Scarlet Witch", // 14 + "Winter Soldier", // 15 + "Black Widow", // 16 + "Hulk", // 17 + "Bruce Banner", // 18 + "Hawkeye", // 19 + "Captain Marvel", // 20 + "War Machine", // 21 + "Nick Fury", // 22 + "Nebula", // 23 + "Drax", // 24 + "Deadpool", // 25 + "Cable", // 26 + "Quicksilver", // 27 + "Wolverine", // 28 + "Adam Warlock", // 29 + "Yondu", // 30 +]; + +export async function main(ns) { + var buyAll = GetFlag(ns, "--buyAll"); + + var buyEquip = buyAll || GetFlag(ns, "--buyEquip"); + + var buyWeapon = buyAll || buyEquip || GetFlag(ns, "--buyWeapon"); + var buyArmor = buyAll || buyEquip || GetFlag(ns, "--buyArmor"); + var buyVehicle = buyAll || buyEquip || GetFlag(ns, "--buyVehicle"); + var buyRoot = buyAll || buyEquip || GetFlag(ns, "--buyRoot"); + + var buyAug = buyAll || GetFlag(ns, "--buyAug"); + + var myGang = ns.gang.getGangInformation(); + var possibleTasks = ns.gang.getTaskNames(); + var unassignedTask = possibleTasks.shift(); + + var territoryTask = possibleTasks.pop(); + var trainingTasks = possibleTasks.splice(possibleTasks.length - 3, 3); + var wantedLevelLowerTask = possibleTasks.pop(); + + var desirableAugs = []; + + if (myGang.isHacking) { + wantedLevelLowerTask = possibleTasks.pop(); + + // replace combat with hacking + trainingTasks.splice(0, 1, trainingTasks[1]); + + desirableAugs.push("BitWire"); + desirableAugs.push("Neuralstimulator"); + desirableAugs.push("DataJack"); + } + else { + // replace hacking with combat + trainingTasks.splice(1, 1, trainingTasks[0]); + + desirableAugs.push("Bionic Arms"); + desirableAugs.push("Bionic Legs"); + desirableAugs.push("Bionic Spine"); + desirableAugs.push("BrachiBlades"); + desirableAugs.push("Nanofiber Weave"); + desirableAugs.push("Synthetic Heart"); + desirableAugs.push("Synfibril Muscle"); + desirableAugs.push("Graphene Bone Lacings"); + } + + var ascensionCycles = GetArg(ns, "--asc", 600000); + var nextAscensionAttempt = 0; + var cycleMs = 1100; + var ascensionMultLimit = GetArg(ns, "--alim", 2); + + while (true) { + myGang = ns.gang.getGangInformation(); + var otherGangs = ns.gang.getOtherGangInformation(); + var buyableEquipment = ns.gang.getEquipmentNames().filter(e => { + return ns.gang.getEquipmentType(e) != "Augmentation" || desirableAugs.includes(e); + }); + + var members = ns.gang.getMemberNames(); + + while (ns.gang.canRecruitMember()) { + var possibleNames = memberNamePool.filter(name => !members.includes(name)); + var toRecruit = possibleNames[getRandomInt(possibleNames.length)]; + + ns.gang.recruitMember(toRecruit); + await ns.sleep(1); + } + + members = ns.gang.getMemberNames(); + var memInfo = null; + + members.sort((a, b) => { return Math.random() * 2 - 1; }); + members.forEach((m) => { + var didBuy = false; + var hadAll = true; + + memInfo = ns.gang.getMemberInformation(m); + + ns.gang.setMemberTask(m, unassignedTask); + + buyableEquipment.forEach((e) => { + if (memInfo.equipment.includes(e)) return; + if (memInfo.augmentations.includes(e)) return; + + hadAll = false; + + var type = ns.gang.getEquipmentType(e); + switch (type) { + case "Weapon": + if (buyWeapon) { + didBuy |= ns.gang.purchaseEquipment(m, e); + } + break; + case "Armor": + if (buyArmor) { + didBuy |= ns.gang.purchaseEquipment(m, e); + } + break; + case "Vehicle": + if (buyVehicle) { + didBuy |= ns.gang.purchaseEquipment(m, e); + } + break; + case "Rootkit": + if (buyRoot) { + didBuy |= ns.gang.purchaseEquipment(m, e); + } + break; + case "Augmentation": + if (buyAug) { + didBuy |= ns.gang.purchaseEquipment(m, e); + } + break; + default: + break; + } + }); + var wantsToAscend = hadAll; + + if (myGang.isHacking) { + wantsToAscend &= memInfo.hackingAscensionMult < ascensionMultLimit; + } + else { + wantsToAscend &= memInfo.hackingAscensionMult < ascensionMultLimit; + wantsToAscend &= memInfo.strengthAscensionMult < ascensionMultLimit; + wantsToAscend &= memInfo.agilityAscensionMult < ascensionMultLimit; + wantsToAscend &= memInfo.dexterityAscensionMult < ascensionMultLimit; + } + + if (wantsToAscend && nextAscensionAttempt <= 0) { + ns.gang.ascendMember(m); + } + }); + + if (nextAscensionAttempt <= 0) { + nextAscensionAttempt = ascensionCycles; + } + + var member = ""; + if (!myGang.isHacking) { + var memCount = members.length; + + while (members.length > (memCount / 2)) { + member = members.pop(); + ns.gang.setMemberTask(member, territoryTask); + } + } + + while (members.length > 0) { + var task = ""; + member = members.pop(); + memInfo = ns.gang.getMemberInformation(member); + + var statsTarget = 50; + + if ((myGang.isHacking && memInfo.hacking < statsTarget) || + (!myGang.isHacking && memInfo.strength < statsTarget && memInfo.agility < statsTarget && memInfo.charisma < statsTarget && memInfo.defense < statsTarget)) { + task = trainingTasks[getRandomInt(trainingTasks.length)]; + } + else if (myGang.wantedLevel > 1) { + task = wantedLevelLowerTask; + } + else { + if (Math.random() > 0.25) { + task = possibleTasks[possibleTasks.length - getRandomInt(2) - 1]; + } + else { + task = trainingTasks[getRandomInt(trainingTasks.length)]; + } + } + + ns.gang.setMemberTask(member, task); + } + + await ns.sleep(cycleMs); + nextAscensionAttempt -= cycleMs; + } +} \ No newline at end of file diff --git a/local/path/home/hacknetmanager.js b/local/path/home/hacknetmanager.js new file mode 100644 index 0000000..24db287 --- /dev/null +++ b/local/path/home/hacknetmanager.js @@ -0,0 +1,41 @@ +/** @param {NS} ns **/ +export async function main(ns) { + function myMoney() { + return ns.getServerMoneyAvailable("home"); + } + //this script is designed to manage the hacknet nodes + //to prevent excess spending i've limited it from spending + //more than half the players money + var nodes = 0; + var ref = 0; + ns.disableLog("ALL"); + while (true) { + //sleep for second to prevent the loop from crashing the game + await ns.sleep(50); + //buy a node if we have more than twice the money needed + if (ns.hacknet.getPurchaseNodeCost() < myMoney() / 10) { + ref = ns.hacknet.purchaseNode(); + ns.print("bought node hn-" + ref); + } + nodes = ns.hacknet.numNodes() + for (var i = 0; i < nodes; i++) { + //check if nodes level is a multiple of 10 + var mod = ns.hacknet.getNodeStats(i).level % 10; + //buy level node to the nearest multiple of 10 if we have double the money needed + if (ns.hacknet.getLevelUpgradeCost(i, 10 - mod) < myMoney() / 10) { + ns.hacknet.upgradeLevel(i, 10 - mod); + ns.print("node hn-" + i + " leveled up"); + } + //same for ram + if (ns.hacknet.getRamUpgradeCost(i) < myMoney() / 10) { + ns.hacknet.upgradeRam(i); + ns.print("node hn-" + i + " ram upgraded"); + } + //and cores + if (ns.hacknet.getCoreUpgradeCost(i) < myMoney() / 10) { + ns.hacknet.upgradeCore(i); + ns.print("node hn-" + i + " core upgraded"); + } + } + } +} \ No newline at end of file diff --git a/local/path/home/killAllScript.js b/local/path/home/killallall.js similarity index 99% rename from local/path/home/killAllScript.js rename to local/path/home/killallall.js index cc54271..601ae5b 100644 --- a/local/path/home/killAllScript.js +++ b/local/path/home/killallall.js @@ -5,4 +5,4 @@ export async function main(ns) { ns.killall(name, true) } -} +} \ No newline at end of file diff --git a/local/path/home/myLibrary.js b/local/path/home/myLibrary.js new file mode 100644 index 0000000..3374fe3 --- /dev/null +++ b/local/path/home/myLibrary.js @@ -0,0 +1,77 @@ +// Custom color coding. +const cCyan = "\u001b[36m"; +const cGreen = "\u001b[32m"; +const cRed = "\u001b[31m"; +const cReset = "\u001b[0m"; + +/** @param {NS} ns */ +export async function main(ns) { + ns.print("This script does nothing on its own, it contains functions for other scripts to use"); +} + + + + + + + + +/** @param {NS} ns */ +export async function purchaseServers(ns) { + + const ram = 64; + + let aServers = listPurchasedServers(ns); + let nServers = aServers.length; + if (nServers >= ns.getPurchasedServerLimit()) { + return nServers; + } + + if (ns.getServerMoneyAvailable("home") > ns.getPurchasedServerCost(ram)) { + let sFrontZero = "0"; + if (nServers >= 9) { + sFrontZero = ""; + } + let hostname = ns.purchaseServer("pserv-" + sFrontZero + (aServers.length + 1), ram); + + ns.tprint("Purchased " + cCyan + hostname + cReset); + ns.toast("Purchased " + hostname, "info", 10000); + } + + aServers = listPurchasedServers(ns); + return aServers.length; +} + + + + + +/** @param {NS} ns */ +export function listPurchasedServers(ns) { + return ns.getPurchasedServers(); +} + + + + + +/** @param {NS} ns */ +export function getSetting(ns, sSetting) { + let oSettings = JSON.parse(ns.read("settings.txt")); + let settingEntry = oSettings.setting[sSetting]; + //ns.tprint(oSettings.setting[sSetting]) + //ns.tprint("settingEntry = "+settingEntry); + return settingEntry; +} + + + + + + +/** @param {NS} ns */ +export function getGrowThreads(ns, sTarget, nHackThreads, nCores) { + let nHackAmountPercent = ns.hackAnalyze(sTarget) * nHackThreads; + let nGrowthThreads = ns.growthAnalyze(sTarget, 1 + nHackAmountPercent, nCores); + return nGrowthThreads; +} \ No newline at end of file diff --git a/local/path/home/newfile.js b/local/path/home/newfile.js deleted file mode 100644 index 71ee58f..0000000 --- a/local/path/home/newfile.js +++ /dev/null @@ -1,4 +0,0 @@ -/** @param {NS} ns */ -export async function main(ns) { - ns.tprint('success') -} \ No newline at end of file diff --git a/local/path/home/notes.txt b/local/path/home/notes.txt new file mode 100644 index 0000000..264a786 --- /dev/null +++ b/local/path/home/notes.txt @@ -0,0 +1,23 @@ +Karma loss per second by crime: +0.0500 Shoplifting +0.0083 Robbery +0.0625 Mugging +0.0167 Larceny +0.0500 Drug dealing +0.0003 Bond forgery +0.0250 Trafficking arms +1.0000 Homicide +0.0625 Grand theft auto +0.0500 Kidnapping +0.0333 Assassination +0.0250 The ultimate heist + + + + +cool functions +ns.singularity.getOwnedSourceFiles(); +ns.asleep(); +ns.atExit(); +ns.spawn(); +ns.toast(); \ No newline at end of file diff --git a/local/path/home/progress.js b/local/path/home/progress.js new file mode 100644 index 0000000..5f32724 --- /dev/null +++ b/local/path/home/progress.js @@ -0,0 +1,39 @@ +/** @param {NS} ns */ +export async function main(ns) { + const sMessage = ns.args[0]; // + const nCurrentProgress = ns.args[1]; // + const stest = ns.args[2]; + + const nPID = ns.pid; + const sFileName = "progress_" + nPID; + + + //ns.print("nPID = "+nPID); + const sProgress = [ + "░░░░░░░░░░", + "█░░░░░░░░░", + "██░░░░░░░░", + "███░░░░░░░", + "████░░░░░░", + "█████░░░░░", + "██████░░░░", + "███████░░░", + "████████░░", + "█████████░", + "██████████" + ]; + ns.tail(nPID); + + + while (nCurrentProgress < 100) { + ns.read(""filename""); + ns.print(sProgress[Math.floor(nCurrentProgress / (sProgress.length - 1))]); + + ns.write("filename", "text", "w"); + + } + if (nCurrentProgress >= 100) + ns.rm(sFileName); + return nPID; + +} \ No newline at end of file diff --git a/local/path/home/pserv.js b/local/path/home/pserv.js new file mode 100644 index 0000000..cbe2626 --- /dev/null +++ b/local/path/home/pserv.js @@ -0,0 +1,52 @@ +/** @param {NS} ns */ +export async function main(ns) { + + let aPservers = ns.getPurchasedServers(); + ns.tprint("aPservers = " + aPservers); + let nPservers = aPservers.length; + ns.tprint("nPservers = " + nPservers); + + let nCurrentRAM; + let nLowestRAM = 2 ** 21; + let nHighestRAM = 0; + let sLowestPserv; + let sHighestPserv; + let nTotalPServRAM = 0; + + + const oPservers = new Object(); + + +/* + const oPservers = { + pserv-01 : { name: "pserv-01" , ram: nRAM} + + }; +*/ + + + + + for (let i = 0; i < nPservers; i++) { + nCurrentRAM = ns.getServerMaxRam(aPservers[i]); + //ns.tprint("nTotalPServRAM = " + nTotalPServRAM + " + " + "nCurrentRAM = " + nCurrentRAM); + nTotalPServRAM += nCurrentRAM; + if (nCurrentRAM < nLowestRAM) { + nLowestRAM = nCurrentRAM + sLowestPserv = aPservers[i]; + } + + if (nCurrentRAM > nHighestRAM) { + nHighestRAM = nCurrentRAM + sHighestPserv = aPservers[i]; + } + } + ns.tprint("sLowestPserv = " + sLowestPserv); + ns.tprint("nLowestRAM = " + nLowestRAM); + + ns.tprint("sHighestPserv = " + sHighestPserv); + ns.tprint("nHighestRAM = " + nHighestRAM); + + ns.tprint("nTotalPServRAM = " + nTotalPServRAM); + +} \ No newline at end of file diff --git a/local/path/home/purchaseServers.js b/local/path/home/purchaseServers.js deleted file mode 100644 index e79b9cb..0000000 --- a/local/path/home/purchaseServers.js +++ /dev/null @@ -1,5 +0,0 @@ -import { getCracks, scanServerList, findBestTarget, crackingAndRooting, copyAndRunScript, purchaseAndUpgradeServers } from "/RamsesUtils.js"; -/** @param {NS} ns */ -export async function main(ns) { - await purchaseAndUpgradeServers(ns); -} \ No newline at end of file diff --git a/local/path/home/removefiles.js b/local/path/home/removefiles.js deleted file mode 100644 index c277928..0000000 --- a/local/path/home/removefiles.js +++ /dev/null @@ -1,164 +0,0 @@ -/** @param {NS} ns */ -export async function main(ns) { - let files = ["contract-115802.cct", -"contract-121862.cct", -"contract-124253.cct", -"contract-130050.cct", -"contract-132458.cct", -"contract-133951.cct", -"contract-137578.cct", -"contract-140971.cct", -"contract-141455.cct", -"contract-143455.cct", -"contract-160840.cct", -"contract-16178.cct", -"contract-166840.cct", -"contract-171215.cct", -"contract-173050.cct", -"contract-17770.cct", -"contract-18028.cct", -"contract-183510.cct", -"contract-195657.cct", -"contract-202801.cct", -"contract-204367.cct", -"contract-217301.cct", -"contract-221818.cct", -"contract-230038.cct", -"contract-236291.cct", -"contract-241097.cct", -"contract-242406.cct", -"contract-253624.cct", -"contract-25923.cct", -"contract-265811.cct", -"contract-267921.cct", -"contract-275503.cct", -"contract-278600.cct", -"contract-279485.cct", -"contract-280015.cct", -"contract-280601.cct", -"contract-286276.cct", -"contract-286508.cct", -"contract-298018.cct", -"contract-30149.cct", -"contract-302603.cct", -"contract-305569.cct", -"contract-322138.cct", -"contract-323283.cct", -"contract-328409.cct", -"contract-328979.cct", -"contract-334003.cct", -"contract-36206.cct", -"contract-375990.cct", -"contract-376805.cct", -"contract-410024.cct", -"contract-413055.cct", -"contract-423941.cct", -"contract-427686.cct", -"contract-441619.cct", -"contract-446103.cct", -"contract-448094.cct", -"contract-467871.cct", -"contract-480431.cct", -"contract-505241.cct", -"contract-516679.cct", -"contract-519369.cct", -"contract-529643.cct", -"contract-535021.cct", -"contract-535336.cct", -"contract-547419.cct", -"contract-560001.cct", -"contract-564079.cct", -"contract-570111.cct", -"contract-570844.cct", -"contract-573534.cct", -"contract-576739.cct", -"contract-580202.cct", -"contract-584555.cct", -"contract-586489.cct", -"contract-592906.cct", -"contract-599940.cct", -"contract-600802.cct", -"contract-603840.cct", -"contract-605640.cct", -"contract-6060.cct", -"contract-606205.cct", -"contract-610194.cct", -"contract-619856.cct", -"contract-631275.cct", -"contract-6317.cct", -"contract-653136.cct", -"contract-655415.cct", -"contract-658731.cct", -"contract-662427.cct", -"contract-663124.cct", -"contract-663518.cct", -"contract-669853.cct", -"contract-671683.cct", -"contract-676164.cct", -"contract-677643.cct", -"contract-681060.cct", -"contract-683911.cct", -"contract-685393.cct", -"contract-695727.cct", -"contract-696156.cct", -"contract-703758.cct", -"contract-720460.cct", -"contract-722083.cct", -"contract-727788.cct", -"contract-735210.cct", -"contract-736394.cct", -"contract-736483.cct", -"contract-748113.cct", -"contract-751169.cct", -"contract-752502.cct", -"contract-765155.cct", -"contract-772173.cct", -"contract-773439.cct", -"contract-77492.cct", -"contract-778492.cct", -"contract-784712.cct", -"contract-785014.cct", -"contract-786215.cct", -"contract-789483.cct", -"contract-7918.cct", -"contract-796855.cct", -"contract-800839.cct", -"contract-801748.cct", -"contract-81208.cct", -"contract-817514.cct", -"contract-82882.cct", -"contract-843473.cct", -"contract-843884.cct", -"contract-847170.cct", -"contract-847956.cct", -"contract-848049.cct", -"contract-856399.cct", -"contract-862326.cct", -"contract-866043.cct", -"contract-866539.cct", -"contract-870914.cct", -"contract-887241.cct", -"contract-893688.cct", -"contract-89945.cct", -"contract-900580.cct", -"contract-915646.cct", -"contract-918325.cct", -"contract-9193.cct", -"contract-921551.cct", -"contract-942582.cct", -"contract-945836.cct", -"contract-947944.cct", -"contract-954121.cct", -"contract-957901.cct", -"contract-960362.cct", -"contract-963099.cct", -"contract-965221.cct", -"contract-979556.cct", -"contract-985969.cct", -"contract-992733.cct", -"contract-996245.cct", -"contract-997464.cct"]; -for (let file of files) { - ns.rm(file) -} -} \ No newline at end of file diff --git a/local/path/home/scanFactionAugments.js b/local/path/home/scanFactionAugments.js new file mode 100644 index 0000000..ebbc94a --- /dev/null +++ b/local/path/home/scanFactionAugments.js @@ -0,0 +1,24 @@ +/** @param {NS} ns */ +export async function main(ns) { + + let aFactions = ns.getPlayer().factions; + ns.tprint("aFactions = " + aFactions); + let aAugmentations; + let sStats; + + for (let f = 0; f < aFactions.length; f++) { + //ns.tprint("f = " + f); + //sFaction = ns.singularity.faction + aAugmentations = ns.singularity.getAugmentationsFromFaction(aFactions[f]); + ns.tprint("aAugmentations = " + aAugmentations); + ns.tprint("----------------------------------------------------------------------------------------------------------------------------------------------------------"); + for (let a = 0; a < aFactions.length; a++) { + sStats = JSON.stringify(ns.singularity.getAugmentationStats(aAugmentations[a])); + ns.tprint(aAugmentations[f] + "sStats = " + sStats); + ns.tprint("----------------------------------------------------------------------------------------------------------------------------------------------------------"); + } + + } + + +} \ No newline at end of file diff --git a/local/path/home/serverList.txt b/local/path/home/serverList.txt index daa258f..b60a829 100644 --- a/local/path/home/serverList.txt +++ b/local/path/home/serverList.txt @@ -1 +1 @@ -{"home":{"serverName":"home","maxRam":512,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["Backdoor.js","BruteSSH.exe","CorpControl.js","CrackAndRootAll.js","FTPCrack.exe","FactionBoost.js","FactionRAMShare.js","HTTPWorm.exe","NUKE.exe","RMbreach.js","RMcontroller.js","RMgrow.js","RMhack.js","RMweaken.js","Ramses-grow.js","Ramses-hack.js","Ramses-weaken.js","RamsesUtils.js","S2controller.js","S2tGrow.js","S2tHack.js","S2tWeaken.js","S2utils.js","S4controller.js","S4logHelper.js","S4tGrow.js","S4tHack.js","S4tWeaken.js","S4utils.js","ServerRouteList.txt","Serverlist.js","StartControllers.js","Startup.js","analyzeContract.js","b1t_flum3.exe","batch.js","bestTarget.txt","controller.js","corp/Autosell.js","corp/HireWorkers.js","corp/SetupExport.js","corp/Smart.js","corp/UpgradeOffice.js","corporation-management-handbook.lit","csec-test.msg","fl1ght.exe","hackers-starting-handbook.lit","j0.msg","j1.msg","j2.msg","killAllScript.js","nitesec-test.msg","purchaseServers.js","relaySMTP.exe","removefiles.js","serverList.txt","tGrow.js","tHack.js","tWeaken.js","test.js","utils.js"]},"pserv-24":{"serverName":"pserv-24","maxRam":128,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"pserv-23":{"serverName":"pserv-23","maxRam":32,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"pserv-22":{"serverName":"pserv-22","maxRam":64,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"pserv-21":{"serverName":"pserv-21","maxRam":32,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"pserv-20":{"serverName":"pserv-20","maxRam":512,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"pserv-19":{"serverName":"pserv-19","maxRam":16,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"pserv-18":{"serverName":"pserv-18","maxRam":64,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"pserv-17":{"serverName":"pserv-17","maxRam":32,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"pserv-16":{"serverName":"pserv-16","maxRam":16,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"pserv-15":{"serverName":"pserv-15","maxRam":128,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"pserv-14":{"serverName":"pserv-14","maxRam":16,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"pserv-13":{"serverName":"pserv-13","maxRam":64,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"pserv-12":{"serverName":"pserv-12","maxRam":32,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"pserv-11":{"serverName":"pserv-11","maxRam":64,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"pserv-10":{"serverName":"pserv-10","maxRam":256,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"pserv-9":{"serverName":"pserv-9","maxRam":32,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"pserv-8":{"serverName":"pserv-8","maxRam":64,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"pserv-7":{"serverName":"pserv-7","maxRam":32,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"pserv-6":{"serverName":"pserv-6","maxRam":64,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"pserv-5":{"serverName":"pserv-5","maxRam":16,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"pserv-4":{"serverName":"pserv-4","maxRam":128,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"pserv-3":{"serverName":"pserv-3","maxRam":16,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"pserv-2":{"serverName":"pserv-2","maxRam":32,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"pserv-1":{"serverName":"pserv-1","maxRam":64,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"pserv-0":{"serverName":"pserv-0","maxRam":32,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"darkweb":{"serverName":"darkweb","maxRam":0,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":false,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":[]},"iron-gym":{"serverName":"iron-gym","maxRam":32,"maxMoney":20000000,"minSec":10,"minPorts":1,"minHackLvl":100,"rootAccess":true,"factorMoneyPerTime":0.017066666666666667,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"harakiri-sushi":{"serverName":"harakiri-sushi","maxRam":16,"maxMoney":4000000,"minSec":5,"minPorts":0,"minHackLvl":40,"rootAccess":true,"factorMoneyPerTime":0.01024,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"CSEC":{"serverName":"CSEC","maxRam":8,"maxMoney":0,"minSec":1,"minPorts":1,"minHackLvl":59,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js","democracy-is-dead.lit"]},"silver-helix":{"serverName":"silver-helix","maxRam":64,"maxMoney":45000000,"minSec":10,"minPorts":2,"minHackLvl":150,"rootAccess":true,"factorMoneyPerTime":0.027105882352941178,"openPorts":1,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js","new-triads.lit"]},"crush-fitness":{"serverName":"crush-fitness","maxRam":0,"maxMoney":52267814,"minSec":12,"minPorts":2,"minHackLvl":258,"rootAccess":true,"factorMoneyPerTime":0.016238544155339808,"openPorts":1,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"syscore":{"serverName":"syscore","maxRam":0,"maxMoney":402262996,"minSec":21,"minPorts":4,"minHackLvl":583,"rootAccess":true,"factorMoneyPerTime":0.03310434042465644,"openPorts":3,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"johnson-ortho":{"serverName":"johnson-ortho","maxRam":0,"maxMoney":82963936,"minSec":22,"minPorts":2,"minHackLvl":258,"rootAccess":true,"factorMoneyPerTime":0.01445797659360109,"openPorts":1,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"I.I.I.I":{"serverName":"I.I.I.I","maxRam":16,"maxMoney":0,"minSec":1,"minPorts":3,"minHackLvl":354,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":2,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js","democracy-is-dead.lit"]},"aevum-police":{"serverName":"aevum-police","maxRam":32,"maxMoney":277087702,"minSec":25,"minPorts":4,"minHackLvl":445,"rootAccess":true,"factorMoneyPerTime":0.025054110979955847,"openPorts":3,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"snap-fitness":{"serverName":"snap-fitness","maxRam":0,"maxMoney":450000000,"minSec":16,"minPorts":4,"minHackLvl":734,"rootAccess":true,"factorMoneyPerTime":0.03858004018754186,"openPorts":3,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"summit-uni":{"serverName":"summit-uni","maxRam":64,"maxMoney":322287556,"minSec":21,"minPorts":3,"minHackLvl":465,"rootAccess":true,"factorMoneyPerTime":0.03311815929192173,"openPorts":2,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js","secret-societies.lit","synthetic-muscles.lit","the-failed-frontier.lit"]},"millenium-fitness":{"serverName":"millenium-fitness","maxRam":16,"maxMoney":250000000,"minSec":17,"minPorts":3,"minHackLvl":494,"rootAccess":true,"factorMoneyPerTime":0.029774366131658528,"openPorts":2,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"computek":{"serverName":"computek","maxRam":0,"maxMoney":232036024,"minSec":21,"minPorts":3,"minHackLvl":383,"rootAccess":true,"factorMoneyPerTime":0.02882505017299527,"openPorts":2,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js","man-and-machine.lit"]},"zb-institute":{"serverName":"zb-institute","maxRam":16,"maxMoney":926443792,"minSec":28,"minPorts":5,"minHackLvl":773,"rootAccess":false,"factorMoneyPerTime":0.04342970348873832,"openPorts":0,"serverFiles":[]},"alpha-ent":{"serverName":"alpha-ent","maxRam":128,"maxMoney":616689214,"minSec":21,"minPorts":4,"minHackLvl":580,"rootAccess":true,"factorMoneyPerTime":0.051008865519870765,"openPorts":3,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js","sector-12-crime.lit"]},"galactic-cyber":{"serverName":"galactic-cyber","maxRam":0,"maxMoney":841319318,"minSec":20,"minPorts":5,"minHackLvl":849,"rootAccess":false,"factorMoneyPerTime":0.05014615725448196,"openPorts":0,"serverFiles":[]},"lexo-corp":{"serverName":"lexo-corp","maxRam":128,"maxMoney":776022357,"minSec":22,"minPorts":4,"minHackLvl":684,"rootAccess":true,"factorMoneyPerTime":0.05211482775236096,"openPorts":3,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"global-pharm":{"serverName":"global-pharm","maxRam":16,"maxMoney":1718048665,"minSec":27,"minPorts":4,"minHackLvl":754,"rootAccess":true,"factorMoneyPerTime":0.08557650709991245,"openPorts":3,"serverFiles":["A-Green-Tomorrow.lit","S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"deltaone":{"serverName":"deltaone","maxRam":0,"maxMoney":1467966501,"minSec":28,"minPorts":5,"minHackLvl":899,"rootAccess":false,"factorMoneyPerTime":0.05924632260066215,"openPorts":0,"serverFiles":[]},"zeus-med":{"serverName":"zeus-med","maxRam":0,"maxMoney":1376135808,"minSec":29,"minPorts":5,"minHackLvl":812,"rootAccess":false,"factorMoneyPerTime":0.05933817868418393,"openPorts":0,"serverFiles":[]},"univ-energy":{"serverName":"univ-energy","maxRam":128,"maxMoney":1197585990,"minSec":27,"minPorts":4,"minHackLvl":840,"rootAccess":true,"factorMoneyPerTime":0.053598254097902094,"openPorts":3,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"taiyang-digital":{"serverName":"taiyang-digital","maxRam":0,"maxMoney":857694312,"minSec":24,"minPorts":5,"minHackLvl":936,"rootAccess":false,"factorMoneyPerTime":0.03875216093752206,"openPorts":0,"serverFiles":["A-Green-Tomorrow.lit","brighter-than-the-sun.lit"]},"applied-energetics":{"serverName":"applied-energetics","maxRam":0,"maxMoney":987324069,"minSec":26,"minPorts":4,"minHackLvl":788,"rootAccess":true,"factorMoneyPerTime":0.04886986884454756,"openPorts":3,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"helios":{"serverName":"helios","maxRam":32,"maxMoney":734014213,"minSec":30,"minPorts":5,"minHackLvl":854,"rootAccess":false,"factorMoneyPerTime":0.029110401011309066,"openPorts":0,"serverFiles":["beyond-man.lit"]},"stormtech":{"serverName":"stormtech","maxRam":0,"maxMoney":1066092443,"minSec":30,"minPorts":5,"minHackLvl":941,"rootAccess":false,"factorMoneyPerTime":0.038398827352514944,"openPorts":0,"serverFiles":[]},"omnia":{"serverName":"omnia","maxRam":32,"maxMoney":970395703,"minSec":31,"minPorts":5,"minHackLvl":852,"rootAccess":false,"factorMoneyPerTime":0.03733974146520367,"openPorts":0,"serverFiles":["history-of-synthoids.lit"]},"defcomm":{"serverName":"defcomm","maxRam":0,"maxMoney":868433685,"minSec":32,"minPorts":5,"minHackLvl":878,"rootAccess":false,"factorMoneyPerTime":0.031427625581000845,"openPorts":0,"serverFiles":[]},"zb-def":{"serverName":"zb-def","maxRam":0,"maxMoney":915888027,"minSec":21,"minPorts":4,"minHackLvl":796,"rootAccess":true,"factorMoneyPerTime":0.0554427370328683,"openPorts":3,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js","synthetic-muscles.lit"]},"microdyne":{"serverName":"microdyne","maxRam":64,"maxMoney":579265634,"minSec":22,"minPorts":5,"minHackLvl":808,"rootAccess":false,"factorMoneyPerTime":0.0329977753235425,"openPorts":0,"serverFiles":["synthetic-muscles.lit"]},"vitalife":{"serverName":"vitalife","maxRam":128,"maxMoney":711887246,"minSec":28,"minPorts":5,"minHackLvl":869,"rootAccess":false,"factorMoneyPerTime":0.029715169570520138,"openPorts":0,"serverFiles":["A-Green-Tomorrow.lit"]},".":{"serverName":".","maxRam":16,"maxMoney":0,"minSec":1,"minPorts":4,"minHackLvl":522,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":3,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"clarkinc":{"serverName":"clarkinc","maxRam":0,"maxMoney":20319452615,"minSec":19,"minPorts":5,"minHackLvl":969,"rootAccess":false,"factorMoneyPerTime":1.1180011540357853,"openPorts":0,"serverFiles":["beyond-man.lit","cost-of-immortality.lit"]},"megacorp":{"serverName":"megacorp","maxRam":0,"maxMoney":45088926725,"minSec":33,"minPorts":5,"minHackLvl":1128,"rootAccess":false,"factorMoneyPerTime":1.2337286491663104,"openPorts":0,"serverFiles":[]},"ecorp":{"serverName":"ecorp","maxRam":0,"maxMoney":42257055444,"minSec":33,"minPorts":5,"minHackLvl":1333,"rootAccess":false,"factorMoneyPerTime":0.9792306857963747,"openPorts":0,"serverFiles":[]},"nwo":{"serverName":"nwo","maxRam":0,"maxMoney":38531364256,"minSec":33,"minPorts":5,"minHackLvl":1093,"rootAccess":false,"factorMoneyPerTime":1.0878744106025533,"openPorts":0,"serverFiles":["the-hidden-world.lit"]},"The-Cave":{"serverName":"The-Cave","maxRam":0,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":925,"rootAccess":false,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["alpha-omega.lit"]},"blade":{"serverName":"blade","maxRam":256,"maxMoney":10648396943,"minSec":30,"minPorts":5,"minHackLvl":953,"rootAccess":false,"factorMoneyPerTime":0.37874117643737404,"openPorts":0,"serverFiles":["beyond-man.lit"]},"fulcrumassets":{"serverName":"fulcrumassets","maxRam":0,"maxMoney":1000000,"minSec":33,"minPorts":5,"minHackLvl":1134,"rootAccess":false,"factorMoneyPerTime":0.000027218117059167507,"openPorts":0,"serverFiles":[]},"b-and-a":{"serverName":"b-and-a","maxRam":0,"maxMoney":18724850396,"minSec":29,"minPorts":5,"minHackLvl":1069,"rootAccess":false,"factorMoneyPerTime":0.6145394957053941,"openPorts":0,"serverFiles":[]},"kuai-gong":{"serverName":"kuai-gong","maxRam":0,"maxMoney":26866270396,"minSec":32,"minPorts":5,"minHackLvl":977,"rootAccess":false,"factorMoneyPerTime":0.8743662879959319,"openPorts":0,"serverFiles":[]},"nectar-net":{"serverName":"nectar-net","maxRam":16,"maxMoney":2750000,"minSec":7,"minPorts":0,"minHackLvl":20,"rootAccess":true,"factorMoneyPerTime":0.008282352941176472,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"phantasy":{"serverName":"phantasy","maxRam":32,"maxMoney":24000000,"minSec":7,"minPorts":2,"minHackLvl":100,"rootAccess":true,"factorMoneyPerTime":0.027306666666666667,"openPorts":1,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"neo-net":{"serverName":"neo-net","maxRam":32,"maxMoney":5000000,"minSec":8,"minPorts":1,"minHackLvl":50,"rootAccess":true,"factorMoneyPerTime":0.008533333333333334,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js","the-hidden-world.lit"]},"avmnite-02h":{"serverName":"avmnite-02h","maxRam":128,"maxMoney":0,"minSec":1,"minPorts":2,"minHackLvl":219,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":1,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js","democracy-is-dead.lit"]},"hong-fang-tea":{"serverName":"hong-fang-tea","maxRam":16,"maxMoney":3000000,"minSec":5,"minPorts":0,"minHackLvl":30,"rootAccess":true,"factorMoneyPerTime":0.008777142857142857,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js","brighter-than-the-sun.lit"]},"joesguns":{"serverName":"joesguns","maxRam":16,"maxMoney":2500000,"minSec":5,"minPorts":0,"minHackLvl":10,"rootAccess":true,"factorMoneyPerTime":0.01024,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"sigma-cosmetics":{"serverName":"sigma-cosmetics","maxRam":16,"maxMoney":2300000,"minSec":3,"minPorts":0,"minHackLvl":5,"rootAccess":true,"factorMoneyPerTime":0.010954418604651163,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"max-hardware":{"serverName":"max-hardware","maxRam":32,"maxMoney":10000000,"minSec":5,"minPorts":1,"minHackLvl":80,"rootAccess":true,"factorMoneyPerTime":0.017066666666666667,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"zer0":{"serverName":"zer0","maxRam":32,"maxMoney":7500000,"minSec":8,"minPorts":1,"minHackLvl":75,"rootAccess":true,"factorMoneyPerTime":0.0096,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"omega-net":{"serverName":"omega-net","maxRam":32,"maxMoney":69174578,"minSec":10,"minPorts":2,"minHackLvl":202,"rootAccess":true,"factorMoneyPerTime":0.0319075530954955,"openPorts":1,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js","the-new-god.lit"]},"netlink":{"serverName":"netlink","maxRam":128,"maxMoney":275000000,"minSec":27,"minPorts":3,"minHackLvl":422,"rootAccess":true,"factorMoneyPerTime":0.02428842504743833,"openPorts":2,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js","simulated-reality.lit"]},"catalyst":{"serverName":"catalyst","maxRam":128,"maxMoney":385146539,"minSec":21,"minPorts":3,"minHackLvl":400,"rootAccess":true,"factorMoneyPerTime":0.045859308829767444,"openPorts":2,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js","tensions-in-tech-race.lit"]},"rothman-uni":{"serverName":"rothman-uni","maxRam":16,"maxMoney":197917621,"minSec":18,"minPorts":3,"minHackLvl":392,"rootAccess":true,"factorMoneyPerTime":0.027931042434399117,"openPorts":2,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js","secret-societies.lit","tensions-in-tech-race.lit","the-failed-frontier.lit"]},"rho-construction":{"serverName":"rho-construction","maxRam":16,"maxMoney":664249104,"minSec":16,"minPorts":3,"minHackLvl":515,"rootAccess":true,"factorMoneyPerTime":0.08059136048530806,"openPorts":2,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"aerocorp":{"serverName":"aerocorp","maxRam":0,"maxMoney":1015107875,"minSec":28,"minPorts":5,"minHackLvl":903,"rootAccess":false,"factorMoneyPerTime":0.04078914079422383,"openPorts":0,"serverFiles":["man-and-machine.lit"]},"unitalife":{"serverName":"unitalife","maxRam":16,"maxMoney":1080390337,"minSec":24,"minPorts":4,"minHackLvl":799,"rootAccess":true,"factorMoneyPerTime":0.05709742491164327,"openPorts":3,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"solaris":{"serverName":"solaris","maxRam":32,"maxMoney":748993919,"minSec":26,"minPorts":5,"minHackLvl":750,"rootAccess":false,"factorMoneyPerTime":0.03893247578964467,"openPorts":0,"serverFiles":["A-Green-Tomorrow.lit","the-failed-frontier.lit"]},"nova-med":{"serverName":"nova-med","maxRam":0,"maxMoney":1102985284,"minSec":26,"minPorts":4,"minHackLvl":813,"rootAccess":true,"factorMoneyPerTime":0.05293171481938326,"openPorts":3,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js","contract-694250.cct"]},"run4theh111z":{"serverName":"run4theh111z","maxRam":512,"maxMoney":0,"minSec":1,"minPorts":4,"minHackLvl":505,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":3,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js","simulated-reality.lit","the-new-god.lit"]},"icarus":{"serverName":"icarus","maxRam":0,"maxMoney":973856267,"minSec":31,"minPorts":5,"minHackLvl":867,"rootAccess":false,"factorMoneyPerTime":0.03682936874129335,"openPorts":0,"serverFiles":[]},"infocomm":{"serverName":"infocomm","maxRam":0,"maxMoney":821494209,"minSec":28,"minPorts":5,"minHackLvl":912,"rootAccess":false,"factorMoneyPerTime":0.032686123329810385,"openPorts":0,"serverFiles":[]},"titan-labs":{"serverName":"titan-labs","maxRam":128,"maxMoney":851353254,"minSec":25,"minPorts":5,"minHackLvl":849,"rootAccess":false,"factorMoneyPerTime":0.04069011585045507,"openPorts":0,"serverFiles":["coded-intelligence.lit"]},"fulcrumtech":{"serverName":"fulcrumtech","maxRam":512,"maxMoney":1469881765,"minSec":30,"minPorts":5,"minHackLvl":1099,"rootAccess":false,"factorMoneyPerTime":0.045377115687669584,"openPorts":0,"serverFiles":["simulated-reality.lit"]},"4sigma":{"serverName":"4sigma","maxRam":0,"maxMoney":21062718422,"minSec":23,"minPorts":5,"minHackLvl":1051,"rootAccess":false,"factorMoneyPerTime":0.884922810656382,"openPorts":0,"serverFiles":[]},"powerhouse-fitness":{"serverName":"powerhouse-fitness","maxRam":32,"maxMoney":900000000,"minSec":19,"minPorts":5,"minHackLvl":1051,"rootAccess":false,"factorMoneyPerTime":0.04569388665774208,"openPorts":0,"serverFiles":[]},"omnitek":{"serverName":"omnitek","maxRam":128,"maxMoney":13664841468,"minSec":31,"minPorts":5,"minHackLvl":1048,"rootAccess":false,"factorMoneyPerTime":0.42807139204698974,"openPorts":0,"serverFiles":["coded-intelligence.lit","history-of-synthoids.lit"]},"the-hub":{"serverName":"the-hub","maxRam":8,"maxMoney":153800542,"minSec":13,"minPorts":2,"minHackLvl":318,"rootAccess":true,"factorMoneyPerTime":0.036338660592524226,"openPorts":1,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]},"foodnstuff":{"serverName":"foodnstuff","maxRam":16,"maxMoney":2000000,"minSec":3,"minPorts":0,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0.010088669950738916,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js","sector-12-crime.lit"]},"n00dles":{"serverName":"n00dles","maxRam":4,"maxMoney":70000,"minSec":1,"minPorts":0,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0.0003566169154228856,"openPorts":0,"serverFiles":["S4tGrow.js","S4tHack.js","S4tWeaken.js"]}} \ No newline at end of file +{"home":{"serverName":"home","maxRam":32768,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["AutoLink.exe","BruteSSH.exe","DeepscanV1.exe","DeepscanV2.exe","EveryServerRun.js","FTPCrack.exe","HTTPWorm.exe","HackingLog.txt","Minimum_Path_Sum_in_a_Triangle.js","NUKE.exe","RMbreach.js","RMcontroller.js","RMgrow.js","RMhack.js","RMweaken.js","SQLInject.exe","ServerRouteList.txt","algorithm.js","ascension.js","ascii/detective.txt","ascii/detective2.txt","ascii/detective3.txt","ascii/hacker.txt","ascii/judge.txt","ascii/noir.txt","autoexec.js","automatedstart.js","b1t_flum3.exe","backdoor.js","batch.js","batch2.js","bestTarget.txt","bitnodeStart.js","breach.js","contract.js","controllerwithautocancel.js","crack.js","csec-test.msg","early-hack-template.js","factionboost.js","fixpserv.js","fl1ght.exe","gang/argFunctions.js","gang/auto-gang.js","gang/auto-gang2.js","gang/gangManager.js","growrepeater.js","hackers-starting-handbook.lit","hacknet.js","hacknetmanager.js","hacknrestart.js","j0.msg","j1.msg","j2.msg","j3.msg","killallall.js","maxGrow.js","myLibrary.js","n00dles.js","nitesec-test.msg","notes.txt","progress.js","pserv.js","purchase-server-8gb.js","relaySMTP.exe","restart.js","scanFactionAugments.js","serverList.txt","serverlister.js","settings.txt","sharePserv.js","singularity/RMroutelist.js","singularity/manualalgo.js","siphon.js","sonic.js","test.js","testLibrary.js","testhack.js","testhackgrow.js","upgrade.js"],"hackingChance":1},"pserv-25":{"serverName":"pserv-25","maxRam":1024,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js"],"hackingChance":1},"pserv-24":{"serverName":"pserv-24","maxRam":1024,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js"],"hackingChance":1},"pserv-23":{"serverName":"pserv-23","maxRam":1024,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js"],"hackingChance":1},"pserv-22":{"serverName":"pserv-22","maxRam":1024,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js"],"hackingChance":1},"pserv-21":{"serverName":"pserv-21","maxRam":1024,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js"],"hackingChance":1},"pserv-20":{"serverName":"pserv-20","maxRam":1024,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js"],"hackingChance":1},"pserv-19":{"serverName":"pserv-19","maxRam":1024,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js"],"hackingChance":1},"pserv-18":{"serverName":"pserv-18","maxRam":1024,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js"],"hackingChance":1},"pserv-17":{"serverName":"pserv-17","maxRam":1024,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js"],"hackingChance":1},"pserv-16":{"serverName":"pserv-16","maxRam":1024,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js"],"hackingChance":1},"pserv-15":{"serverName":"pserv-15","maxRam":1024,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js"],"hackingChance":1},"pserv-14":{"serverName":"pserv-14","maxRam":1024,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js"],"hackingChance":1},"pserv-13":{"serverName":"pserv-13","maxRam":1024,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js"],"hackingChance":1},"pserv-12":{"serverName":"pserv-12","maxRam":1024,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js"],"hackingChance":1},"pserv-11":{"serverName":"pserv-11","maxRam":1024,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js"],"hackingChance":1},"pserv-10":{"serverName":"pserv-10","maxRam":1024,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js"],"hackingChance":1},"pserv-09":{"serverName":"pserv-09","maxRam":1024,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js"],"hackingChance":1},"pserv-08":{"serverName":"pserv-08","maxRam":1024,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js"],"hackingChance":1},"pserv-07":{"serverName":"pserv-07","maxRam":1024,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js"],"hackingChance":1},"pserv-06":{"serverName":"pserv-06","maxRam":1024,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js"],"hackingChance":1},"pserv-05":{"serverName":"pserv-05","maxRam":1024,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js"],"hackingChance":1},"pserv-04":{"serverName":"pserv-04","maxRam":1024,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js"],"hackingChance":1},"pserv-03":{"serverName":"pserv-03","maxRam":1024,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js"],"hackingChance":1},"pserv-02":{"serverName":"pserv-02","maxRam":1024,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js"],"hackingChance":1},"pserv-01":{"serverName":"pserv-01","maxRam":1024,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js"],"hackingChance":1},"darkweb":{"serverName":"darkweb","maxRam":0,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":[],"hackingChance":0},"iron-gym":{"serverName":"iron-gym","maxRam":32,"maxMoney":56250000,"minSec":10,"minPorts":1,"minHackLvl":100,"rootAccess":true,"factorMoneyPerTime":0.0774375,"openPorts":0,"serverFiles":["factionboost.js"],"hackingChance":0.7794502647993277},"harakiri-sushi":{"serverName":"harakiri-sushi","maxRam":16,"maxMoney":11250000,"minSec":5,"minPorts":0,"minHackLvl":40,"rootAccess":true,"factorMoneyPerTime":0.0464625,"openPorts":0,"serverFiles":["factionboost.js"],"hackingChance":1},"hong-fang-tea":{"serverName":"hong-fang-tea","maxRam":16,"maxMoney":8437500,"minSec":5,"minPorts":0,"minHackLvl":30,"rootAccess":true,"factorMoneyPerTime":0.03982499999999999,"openPorts":0,"serverFiles":["brighter-than-the-sun.lit","factionboost.js"],"hackingChance":1},"joesguns":{"serverName":"joesguns","maxRam":16,"maxMoney":7031250,"minSec":5,"minPorts":0,"minHackLvl":10,"rootAccess":true,"factorMoneyPerTime":0.0464625,"openPorts":0,"serverFiles":["factionboost.js"],"hackingChance":1},"sigma-cosmetics":{"serverName":"sigma-cosmetics","maxRam":16,"maxMoney":6468750,"minSec":3,"minPorts":0,"minHackLvl":5,"rootAccess":true,"factorMoneyPerTime":0.049704069767441864,"openPorts":0,"serverFiles":["factionboost.js"],"hackingChance":1},"CSEC":{"serverName":"CSEC","maxRam":8,"maxMoney":0,"minSec":1,"minPorts":1,"minHackLvl":57,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":0,"serverFiles":["democracy-is-dead.lit","factionboost.js"],"hackingChance":1},"foodnstuff":{"serverName":"foodnstuff","maxRam":16,"maxMoney":5625000,"minSec":3,"minPorts":0,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0.04577586206896552,"openPorts":0,"serverFiles":["factionboost.js","sector-12-crime.lit"],"hackingChance":1},"max-hardware":{"serverName":"max-hardware","maxRam":32,"maxMoney":28125000,"minSec":5,"minPorts":1,"minHackLvl":80,"rootAccess":true,"factorMoneyPerTime":0.0774375,"openPorts":0,"serverFiles":["factionboost.js"],"hackingChance":0.9818410505113837},"omega-net":{"serverName":"omega-net","maxRam":32,"maxMoney":196514330.625,"minSec":11,"minPorts":2,"minHackLvl":210,"rootAccess":true,"factorMoneyPerTime":0.12933931242729083,"openPorts":1,"serverFiles":["factionboost.js","the-new-god.lit"],"hackingChance":0.7872795714853008},"avmnite-02h":{"serverName":"avmnite-02h","maxRam":32,"maxMoney":0,"minSec":1,"minPorts":2,"minHackLvl":208,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":1,"serverFiles":["democracy-is-dead.lit","factionboost.js"],"hackingChance":0.8799357426547211},"I.I.I.I":{"serverName":"I.I.I.I","maxRam":128,"maxMoney":0,"minSec":1,"minPorts":3,"minHackLvl":363,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":2,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","democracy-is-dead.lit","myLibrary.js"],"hackingChance":0.560708030281446},"lexo-corp":{"serverName":"lexo-corp","maxRam":16,"maxMoney":2069915557.5,"minSec":21,"minPorts":4,"minHackLvl":674,"rootAccess":true,"factorMoneyPerTime":0.23822631329176533,"openPorts":3,"serverFiles":[],"hackingChance":0},"snap-fitness":{"serverName":"snap-fitness","maxRam":0,"maxMoney":1265625000,"minSec":17,"minPorts":4,"minHackLvl":720,"rootAccess":true,"factorMoneyPerTime":0.16807174437299036,"openPorts":3,"serverFiles":[],"hackingChance":0},"aerocorp":{"serverName":"aerocorp","maxRam":0,"maxMoney":2964352080.9375,"minSec":28,"minPorts":5,"minHackLvl":915,"rootAccess":true,"factorMoneyPerTime":0.1896634251630035,"openPorts":4,"serverFiles":["man-and-machine.lit"],"hackingChance":0},"unitalife":{"serverName":"unitalife","maxRam":64,"maxMoney":2954374959.375,"minSec":23,"minPorts":4,"minHackLvl":799,"rootAccess":true,"factorMoneyPerTime":0.262724198357512,"openPorts":3,"serverFiles":[],"hackingChance":0},"univ-energy":{"serverName":"univ-energy","maxRam":16,"maxMoney":3187267405.3125,"minSec":27,"minPorts":4,"minHackLvl":815,"rootAccess":true,"factorMoneyPerTime":0.2371252309649291,"openPorts":3,"serverFiles":[],"hackingChance":0},"nova-med":{"serverName":"nova-med","maxRam":0,"maxMoney":3119127378.75,"minSec":24,"minPorts":4,"minHackLvl":849,"rootAccess":true,"factorMoneyPerTime":0.25042760641985806,"openPorts":3,"serverFiles":[],"hackingChance":0},"applied-energetics":{"serverName":"applied-energetics","maxRam":0,"maxMoney":2018441970,"minSec":25,"minPorts":4,"minHackLvl":838,"rootAccess":true,"factorMoneyPerTime":0.15765797325957448,"openPorts":3,"serverFiles":[],"hackingChance":0},"stormtech":{"serverName":"stormtech","maxRam":0,"maxMoney":2971835586.5625,"minSec":31,"minPorts":5,"minHackLvl":1032,"rootAccess":true,"factorMoneyPerTime":0.15250597629849807,"openPorts":4,"serverFiles":[],"hackingChance":0},"kuai-gong":{"serverName":"kuai-gong","maxRam":0,"maxMoney":60301613368.125,"minSec":32,"minPorts":5,"minHackLvl":1106,"rootAccess":true,"factorMoneyPerTime":2.798894843901509,"openPorts":4,"serverFiles":[],"hackingChance":0},"clarkinc":{"serverName":"clarkinc","maxRam":0,"maxMoney":45937777148.4375,"minSec":18,"minPorts":5,"minHackLvl":1153,"rootAccess":true,"factorMoneyPerTime":3.6217050610489046,"openPorts":4,"serverFiles":["beyond-man.lit","cost-of-immortality.lit"],"hackingChance":0},"megacorp":{"serverName":"megacorp","maxRam":0,"maxMoney":155265627000.9375,"minSec":33,"minPorts":5,"minHackLvl":1130,"rootAccess":true,"factorMoneyPerTime":6.8417928995878565,"openPorts":4,"serverFiles":[],"hackingChance":0},"blade":{"serverName":"blade","maxRam":64,"maxMoney":107670895371.5625,"minSec":30,"minPorts":5,"minHackLvl":1177,"rootAccess":true,"factorMoneyPerTime":5.009076855922873,"openPorts":4,"serverFiles":["beyond-man.lit"],"hackingChance":0},"fulcrumtech":{"serverName":"fulcrumtech","maxRam":512,"maxMoney":4090821741.5625,"minSec":29,"minPorts":5,"minHackLvl":977,"rootAccess":true,"factorMoneyPerTime":0.23684987618060668,"openPorts":4,"serverFiles":["simulated-reality.lit"],"hackingChance":0},".":{"serverName":".","maxRam":16,"maxMoney":0,"minSec":1,"minPorts":4,"minHackLvl":514,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":3,"serverFiles":[],"hackingChance":0.2497184524210297},"b-and-a":{"serverName":"b-and-a","maxRam":0,"maxMoney":79095950848.125,"minSec":27,"minPorts":5,"minHackLvl":1149,"rootAccess":true,"factorMoneyPerTime":4.184944137369968,"openPorts":4,"serverFiles":[],"hackingChance":0},"ecorp":{"serverName":"ecorp","maxRam":0,"maxMoney":167282154509.0625,"minSec":33,"minPorts":5,"minHackLvl":1193,"rootAccess":true,"factorMoneyPerTime":6.984005642017015,"openPorts":4,"serverFiles":[],"hackingChance":0},"4sigma":{"serverName":"4sigma","maxRam":0,"maxMoney":67097355693.75,"minSec":23,"minPorts":5,"minHackLvl":1093,"rootAccess":true,"factorMoneyPerTime":4.374475378115751,"openPorts":4,"serverFiles":[],"hackingChance":0},"deltaone":{"serverName":"deltaone","maxRam":0,"maxMoney":4563772689.375,"minSec":28,"minPorts":5,"minHackLvl":857,"rootAccess":true,"factorMoneyPerTime":0.3115949943316044,"openPorts":4,"serverFiles":[],"hackingChance":0},"zeus-med":{"serverName":"zeus-med","maxRam":0,"maxMoney":3656464233.75,"minSec":29,"minPorts":5,"minHackLvl":818,"rootAccess":true,"factorMoneyPerTime":0.2525072700507901,"openPorts":4,"serverFiles":[],"hackingChance":0},"icarus":{"serverName":"icarus","maxRam":0,"maxMoney":2728379078.4375,"minSec":30,"minPorts":5,"minHackLvl":883,"rootAccess":true,"factorMoneyPerTime":0.1688753180059479,"openPorts":4,"serverFiles":[],"hackingChance":0},"zb-def":{"serverName":"zb-def","maxRam":0,"maxMoney":2635448774.0625,"minSec":20,"minPorts":4,"minHackLvl":794,"rootAccess":true,"factorMoneyPerTime":0.27075630439995335,"openPorts":3,"serverFiles":["synthetic-muscles.lit"],"hackingChance":0},"microdyne":{"serverName":"microdyne","maxRam":16,"maxMoney":1828178758.125,"minSec":23,"minPorts":5,"minHackLvl":814,"rootAccess":true,"factorMoneyPerTime":0.15961057543718954,"openPorts":4,"serverFiles":["synthetic-muscles.lit"],"hackingChance":0},"taiyang-digital":{"serverName":"taiyang-digital","maxRam":0,"maxMoney":2281447456.875,"minSec":24,"minPorts":5,"minHackLvl":880,"rootAccess":true,"factorMoneyPerTime":0.1767800749886257,"openPorts":4,"serverFiles":["A-Green-Tomorrow.lit","brighter-than-the-sun.lit"],"hackingChance":0},"titan-labs":{"serverName":"titan-labs","maxRam":16,"maxMoney":2374794447.1875,"minSec":25,"minPorts":5,"minHackLvl":812,"rootAccess":true,"factorMoneyPerTime":0.19137367935384147,"openPorts":4,"serverFiles":["coded-intelligence.lit"],"hackingChance":0},"vitalife":{"serverName":"vitalife","maxRam":32,"maxMoney":2137470136.875,"minSec":29,"minPorts":5,"minHackLvl":824,"rootAccess":true,"factorMoneyPerTime":0.14654302233223357,"openPorts":4,"serverFiles":["A-Green-Tomorrow.lit"],"hackingChance":0},"omnitek":{"serverName":"omnitek","maxRam":512,"maxMoney":54581820887.8125,"minSec":30,"minPorts":5,"minHackLvl":929,"rootAccess":true,"factorMoneyPerTime":3.2122966906543016,"openPorts":4,"serverFiles":["coded-intelligence.lit","history-of-synthoids.lit"],"hackingChance":0},"powerhouse-fitness":{"serverName":"powerhouse-fitness","maxRam":16,"maxMoney":2531250000,"minSec":21,"minPorts":5,"minHackLvl":1041,"rootAccess":true,"factorMoneyPerTime":0.18954829790127375,"openPorts":4,"serverFiles":[],"hackingChance":0},"The-Cave":{"serverName":"The-Cave","maxRam":0,"maxMoney":0,"minSec":1,"minPorts":5,"minHackLvl":925,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":4,"serverFiles":["alpha-omega.lit"],"hackingChance":0},"fulcrumassets":{"serverName":"fulcrumassets","maxRam":0,"maxMoney":2812500,"minSec":33,"minPorts":5,"minHackLvl":1498,"rootAccess":true,"factorMoneyPerTime":0.00009361022686061973,"openPorts":4,"serverFiles":[],"hackingChance":0},"nwo":{"serverName":"nwo","maxRam":0,"maxMoney":102925863644.0625,"minSec":33,"minPorts":5,"minHackLvl":950,"rootAccess":true,"factorMoneyPerTime":5.389335237400673,"openPorts":4,"serverFiles":["the-hidden-world.lit"],"hackingChance":0},"infocomm":{"serverName":"infocomm","maxRam":0,"maxMoney":1815631956.5625,"minSec":29,"minPorts":5,"minHackLvl":902,"rootAccess":true,"factorMoneyPerTime":0.11379558358909059,"openPorts":4,"serverFiles":[],"hackingChance":0},"run4theh111z":{"serverName":"run4theh111z","maxRam":64,"maxMoney":0,"minSec":1,"minPorts":4,"minHackLvl":518,"rootAccess":true,"factorMoneyPerTime":0,"openPorts":3,"serverFiles":["simulated-reality.lit","the-new-god.lit"],"hackingChance":0.24148031790817098},"helios":{"serverName":"helios","maxRam":64,"maxMoney":1752766000.3125,"minSec":29,"minPorts":5,"minHackLvl":871,"rootAccess":true,"factorMoneyPerTime":0.11373460986355513,"openPorts":4,"serverFiles":["beyond-man.lit"],"hackingChance":0},"catalyst":{"serverName":"catalyst","maxRam":16,"maxMoney":1409611246.875,"minSec":21,"minPorts":3,"minHackLvl":419,"rootAccess":true,"factorMoneyPerTime":0.2587707278405934,"openPorts":2,"serverFiles":["factionboost.js","tensions-in-tech-race.lit"],"hackingChance":0.16645296406820898},"syscore":{"serverName":"syscore","maxRam":0,"maxMoney":1311487849.6875,"minSec":22,"minPorts":4,"minHackLvl":630,"rootAccess":true,"factorMoneyPerTime":0.154095158441234,"openPorts":3,"serverFiles":[],"hackingChance":0.0038226192341863337},"aevum-police":{"serverName":"aevum-police","maxRam":64,"maxMoney":906136543.125,"minSec":27,"minPorts":4,"minHackLvl":414,"rootAccess":true,"factorMoneyPerTime":0.13156420893324838,"openPorts":3,"serverFiles":[],"hackingChance":0.09205491217020151},"global-pharm":{"serverName":"global-pharm","maxRam":64,"maxMoney":4779752239.6875,"minSec":27,"minPorts":4,"minHackLvl":832,"rootAccess":true,"factorMoneyPerTime":0.3484005780075781,"openPorts":3,"serverFiles":["A-Green-Tomorrow.lit"],"hackingChance":0},"omnia":{"serverName":"omnia","maxRam":16,"maxMoney":2634518927.8125,"minSec":31,"minPorts":5,"minHackLvl":912,"rootAccess":true,"factorMoneyPerTime":0.15285983663761768,"openPorts":4,"serverFiles":["history-of-synthoids.lit"],"hackingChance":0},"solaris":{"serverName":"solaris","maxRam":32,"maxMoney":2214169056.5625,"minSec":24,"minPorts":5,"minHackLvl":772,"rootAccess":true,"factorMoneyPerTime":0.19531222134991724,"openPorts":4,"serverFiles":["A-Green-Tomorrow.lit","the-failed-frontier.lit"],"hackingChance":0},"defcomm":{"serverName":"defcomm","maxRam":0,"maxMoney":2563498515.9375,"minSec":32,"minPorts":5,"minHackLvl":1032,"rootAccess":true,"factorMoneyPerTime":0.12746507188564743,"openPorts":4,"serverFiles":[],"hackingChance":0},"rho-construction":{"serverName":"rho-construction","maxRam":32,"maxMoney":1749766941.5625,"minSec":13,"minPorts":3,"minHackLvl":516,"rootAccess":true,"factorMoneyPerTime":0.4184445552202157,"openPorts":2,"serverFiles":["factionboost.js"],"hackingChance":0.14884811222096989},"phantasy":{"serverName":"phantasy","maxRam":32,"maxMoney":67500000,"minSec":7,"minPorts":2,"minHackLvl":100,"rootAccess":true,"factorMoneyPerTime":0.12390000000000002,"openPorts":1,"serverFiles":["factionboost.js"],"hackingChance":0.8908003026278031},"zer0":{"serverName":"zer0","maxRam":32,"maxMoney":21093750,"minSec":8,"minPorts":1,"minHackLvl":75,"rootAccess":true,"factorMoneyPerTime":0.04355859375,"openPorts":0,"serverFiles":["factionboost.js"],"hackingChance":0.8741316024297525},"silver-helix":{"serverName":"silver-helix","maxRam":64,"maxMoney":126562500,"minSec":10,"minPorts":2,"minHackLvl":150,"rootAccess":true,"factorMoneyPerTime":0.1229889705882353,"openPorts":1,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js","new-triads.lit"],"hackingChance":0.706638469862445},"crush-fitness":{"serverName":"crush-fitness","maxRam":0,"maxMoney":126678588.75,"minSec":13,"minPorts":2,"minHackLvl":266,"rootAccess":true,"factorMoneyPerTime":0.05720968524193549,"openPorts":1,"serverFiles":[],"hackingChance":0.4762619506821487},"johnson-ortho":{"serverName":"johnson-ortho","maxRam":0,"maxMoney":206727837.1875,"minSec":21,"minPorts":2,"minHackLvl":279,"rootAccess":true,"factorMoneyPerTime":0.05636481053536062,"openPorts":1,"serverFiles":[],"hackingChance":0.26680322001871964},"netlink":{"serverName":"netlink","maxRam":32,"maxMoney":773437500,"minSec":20,"minPorts":3,"minHackLvl":401,"rootAccess":true,"factorMoneyPerTime":0.15544023722627737,"openPorts":2,"serverFiles":["factionboost.js","simulated-reality.lit"],"hackingChance":0.19005438731274993},"zb-institute":{"serverName":"zb-institute","maxRam":64,"maxMoney":2995904390.625,"minSec":28,"minPorts":5,"minHackLvl":768,"rootAccess":true,"factorMoneyPerTime":0.22803326821380854,"openPorts":4,"serverFiles":[],"hackingChance":0},"alpha-ent":{"serverName":"alpha-ent","maxRam":128,"maxMoney":1837465740,"minSec":19,"minPorts":4,"minHackLvl":505,"rootAccess":true,"factorMoneyPerTime":0.3099023381807044,"openPorts":3,"serverFiles":["sector-12-crime.lit"],"hackingChance":0.11922411336664969},"galactic-cyber":{"serverName":"galactic-cyber","maxRam":0,"maxMoney":2278745147.8125,"minSec":19,"minPorts":5,"minHackLvl":854,"rootAccess":true,"factorMoneyPerTime":0.22917855742032445,"openPorts":4,"serverFiles":[],"hackingChance":0},"the-hub":{"serverName":"the-hub","maxRam":32,"maxMoney":483168296.25,"minSec":13,"minPorts":2,"minHackLvl":318,"rootAccess":true,"factorMoneyPerTime":0.1841702873569451,"openPorts":1,"serverFiles":["factionboost.js"],"hackingChance":0.40919188586028893},"rothman-uni":{"serverName":"rothman-uni","maxRam":128,"maxMoney":601140065.625,"minSec":16,"minPorts":3,"minHackLvl":371,"rootAccess":true,"factorMoneyPerTime":0.16184540228365385,"openPorts":2,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js","secret-societies.lit","tensions-in-tech-race.lit","the-failed-frontier.lit"],"hackingChance":0.2858591069222009},"millenium-fitness":{"serverName":"millenium-fitness","maxRam":128,"maxMoney":703125000,"minSec":16,"minPorts":3,"minHackLvl":486,"rootAccess":true,"factorMoneyPerTime":0.14563220912738215,"openPorts":2,"serverFiles":["RMgrow.js","RMhack.js","RMweaken.js","batch.js","myLibrary.js"],"hackingChance":0.16455985739985005},"n00dles":{"serverName":"n00dles","maxRam":4,"maxMoney":196875,"minSec":1,"minPorts":0,"minHackLvl":1,"rootAccess":true,"factorMoneyPerTime":0.0016180970149253734,"openPorts":0,"serverFiles":["factionboost.js"],"hackingChance":1},"nectar-net":{"serverName":"nectar-net","maxRam":16,"maxMoney":7734375,"minSec":7,"minPorts":0,"minHackLvl":20,"rootAccess":true,"factorMoneyPerTime":0.03757996323529412,"openPorts":0,"serverFiles":["factionboost.js"],"hackingChance":1},"neo-net":{"serverName":"neo-net","maxRam":32,"maxMoney":14062500,"minSec":8,"minPorts":1,"minHackLvl":50,"rootAccess":true,"factorMoneyPerTime":0.03871875,"openPorts":0,"serverFiles":["factionboost.js","the-hidden-world.lit"],"hackingChance":0.9131379211459395},"computek":{"serverName":"computek","maxRam":0,"maxMoney":678530463.75,"minSec":19,"minPorts":3,"minHackLvl":311,"rootAccess":true,"factorMoneyPerTime":0.18348867672532332,"openPorts":2,"serverFiles":["contract-545076.cct","man-and-machine.lit"],"hackingChance":0.2968016795327152},"summit-uni":{"serverName":"summit-uni","maxRam":32,"maxMoney":684528077.8125,"minSec":20,"minPorts":3,"minHackLvl":439,"rootAccess":true,"factorMoneyPerTime":0.1259287733347717,"openPorts":2,"serverFiles":["factionboost.js","secret-societies.lit","synthetic-muscles.lit","the-failed-frontier.lit"],"hackingChance":0.1633064543584366}} \ No newline at end of file diff --git a/local/path/home/RamsesUtils.js b/local/path/home/serverlister.js similarity index 54% rename from local/path/home/RamsesUtils.js rename to local/path/home/serverlister.js index 24d0ef4..7194340 100644 --- a/local/path/home/RamsesUtils.js +++ b/local/path/home/serverlister.js @@ -1,97 +1,83 @@ + + +// Custom color coding. +const cCyan = "\u001b[36m"; +const cGreen = "\u001b[32m"; +const cRed = "\u001b[31m"; +const cReset = "\u001b[0m"; + + + + + /** @param {NS} ns */ export async function main(ns) { - ns.tprint("This is just a function library, it doesn't do anything."); -} + let reset = ns.args[0]; + const bSilent = ns.args[1] === true ? true : false; // if true supress feedback + //ns.tprint("bSilent = " + bSilent); + //host and script info + const sThisRunner = ns.getHostname(); + const sThisScript = ns.getScriptName(); + const nThisPID = ns.pid; -/** @param {NS} ns */ -export function getCracks(ns) { + //open log for this script + if (!bSilent) ns.tail(nThisPID, sThisRunner, ns.args); + + const funnyScript = ["breach.js", "batch.js", "grow.js", "weaken.js", "hack.js"]; + const sScript = "breach.js"; + //write function to purchase scripts from tor network and rerun getCracks() then recrack and reroot let cracks = {}; - if (ns.fileExists("BruteSSH.exe", "home")) { - cracks["BruteSSH.exe"] = ns.brutessh; - }; - if (ns.fileExists("FTPCrack.exe", "home")) { - cracks["FTPCrack.exe"] = ns.ftpcrack; - }; - if (ns.fileExists("relaySMTP.exe", "home")) { - cracks["relaySMTP.exe"] = ns.relaysmtp; - }; - if (ns.fileExists("HTTPWorm.exe", "home")) { - cracks["HTTPWorm.exe"] = ns.httpworm; - }; - if (ns.fileExists("SQLInject.exe", "home")) { - cracks["SQLInject.exe"] = ns.sqlinject; - }; - return cracks; -} + cracks = getCracks(ns); + let maxPorts = Object.keys(cracks).length; + scanServerList(ns, bSilent); + let manualTargetOverride = ""; + let nHackingLevel = ns.getHackingLevel(); + let nServerMaxSecurity = 100; -/** @param {NS} ns */ -export function scanServerList(ns) { - const home = "home"; - let serverList = {}; - let unscanned = []; - unscanned.push(home); - while (unscanned.length > 0) { - let currentServer = unscanned.pop(); - if (!serverList[currentServer]) { - let maxRam = ns.getServerMaxRam(currentServer); - let minPorts = ns.getServerNumPortsRequired(currentServer); - let minSecLevel = ns.getServerMinSecurityLevel(currentServer); - let minHackLevel = ns.getServerRequiredHackingLevel(currentServer); - let rootAccess = ns.hasRootAccess(currentServer); - let serverMoney = ns.getServerMaxMoney(currentServer); - let serverFiles = ns.ls(currentServer); - let skillFactor = (2.5 * minHackLevel * minSecLevel + 500) / (ns.getHackingLevel() + 50); - let compareTimeFactor = serverMoney / skillFactor / 10e7; - serverList[currentServer] = - { - serverName: currentServer, - maxRam: maxRam, - maxMoney: serverMoney, - minSec: minSecLevel, - minPorts: minPorts, - minHackLvl: minHackLevel, - rootAccess: rootAccess, - factorMoneyPerTime: compareTimeFactor, - openPorts: 0, - serverFiles: serverFiles, - }; - let neighbours = ns.scan(currentServer); - for (let i = 0; i < neighbours.length; i++) { - let neighbour = neighbours[i]; - if (serverList[neighbour]) { - continue - } - unscanned.push(neighbour); - } + + if (nHackingLevel < 10) { + manualTargetOverride = "n00dles"; + } + + + + //ns.tprint("find best target"); + findBestTarget(ns, nServerMaxSecurity, maxPorts, ns.getHackingLevel(), manualTargetOverride); + //ns.tprint("Best Target found? "); + //let bestTarget = ns.read("bestTarget.txt"); + //ns.tprint("Best Target: " + bestTarget); + //ns.tprint(Object.keys(JSON.parse(ns.read("serverList.txt"))).length); + crackingAndRooting(ns, cracks, funnyScript); + //ns.exec(funnyScript[0], "home", 1, JSON.parse(bestTarget).serverName); + //ns.print(reset); + if (reset === true) { + //ns.tprint("reset === true") + findBestTarget(ns, nServerMaxSecurity, maxPorts, ns.getHackingLevel(), manualTargetOverride); + let serverList = JSON.parse(ns.read("serverList.txt")); + for (const [name, entry] of Object.entries(serverList)) { + //copyAndRunSript(ns, funnyScript, name); } } - ns.write("serverList.txt", JSON.stringify(serverList), "w"); + /*let serverListForFiles = JSON.parse(ns.read("serverList.txt")); + for (const [name2, entry2] of Object.entries(serverListForFiles)) { + ns.tprint(name2 + " Files: " + entry2.serverFiles) + }*/ + //await ns.sleep(500000); + //await purchaseAndUpgradeServers(ns, funnyScript); + //await runScriptsFromServers(ns, sScript, JSON.parse(bestTarget).serverName); + let oBestTarget = JSON.parse(ns.read("bestTarget.txt")); + let sBestTarget = oBestTarget.serverName; + //ns.exec(sScript, "home", 1, sBestTarget); + + /* + if(){ + ns.exec(sScript,"home",1); + } + */ } /** @param {NS} ns */ -export function findBestTarget(ns, maxSec, maxPorts, currentHackLevel, manualTargetOverride) { - if (!ns.fileExists("serverList.txt", "home")) scanServerList(); - let serverList = JSON.parse(ns.read("serverList.txt")); - let bestEntry = null; - let compareTime = 0; - for (const [name, entry] of Object.entries(serverList)) { - if (entry.minSec <= maxSec && entry.minPorts <= maxPorts && entry.minHackLvl < currentHackLevel) { - if (entry.factorMoneyPerTime > compareTime) { - compareTime = entry.factorMoneyPerTime; - bestEntry = name; - } - } - } - if (manualTargetOverride.length > 0) { - bestEntry = manualTargetOverride; - } - ns.write("bestTarget.txt", JSON.stringify(serverList[bestEntry]), "w"); -} - - -/** @param {NS} ns */ -export function crackingAndRooting(ns, cracks, funnyScript, copy) { - if (!ns.fileExists("serverList.txt", "home")) scanServerList(); +function crackingAndRooting(ns, cracks, funnyScript) { let serverList = JSON.parse(ns.read("serverList.txt")); for (const [name, entry] of Object.entries(serverList)) { let cracked = false; @@ -107,8 +93,8 @@ export function crackingAndRooting(ns, cracks, funnyScript, copy) { ns.nuke(name); if (ns.hasRootAccess(name)) { serverList[name].rootAccess = true; - if (serverList[name].maxRam > 0 && copy === true) { - copyAndRunScript(ns, funnyScript, name); + if (serverList[name].maxRam > 0) { + copyAndRunSript(ns, funnyScript, name); } } } @@ -117,13 +103,73 @@ export function crackingAndRooting(ns, cracks, funnyScript, copy) { ns.tprint("Cracking and rooting done"); } +/** @param {NS} ns */ +async function purchaseAndUpgradeServers(ns, funnyScript) { + let maxPurchasedServers = ns.getPurchasedServerLimit(); + let purchasedServers = []; + let count = listPurchasedServers(ns).length; + let currentMoney = 0; + let serverList = {}; + while (count < maxPurchasedServers) { + purchasedServers = listPurchasedServers(ns); + currentMoney = ns.getServerMoneyAvailable("home"); + let targetRamInitial = 16; + if (ns.getPurchasedServerCost(targetRamInitial) < currentMoney) { + let hostname = ns.purchaseServer("pserv-" + purchasedServers.length, 16); + count = listPurchasedServers(ns).length; + serverList = JSON.parse(ns.read("serverList.txt")); + serverList[hostname] = { + serverName: hostname, + maxRam: 16, + maxMoney: 0, + minSec: 0, + minPorts: 5, + minHackLvl: 1, + rootAccess: true, + factorMoneyPerTime: 99999999, + openPorts: 0, + }; + ns.write("serverList.txt", JSON.stringify(serverList), "w"); + copyAndRunSript(ns, funnyScript, hostname); + continue + } else { + await ns.sleep(5000); + } + } + let i = 5; + while (i < 21) { + let targetRam = 2 ** i; + purchasedServers = listPurchasedServers(ns); + for (let currentServer of purchasedServers) { + currentMoney = ns.getServerMoneyAvailable("home"); + if (ns.getPurchasedServerUpgradeCost(currentServer, targetRam) < currentMoney) { + if (ns.upgradePurchasedServer(currentServer, targetRam)) { + ns.print(currentServer + " upgraded to " + targetRam + " GB RAM"); + copyAndRunSript(ns, funnyScript, currentServer); + serverList = JSON.parse(ns.read("serverList.txt")); + serverList[currentServer].maxRam = targetRam; + ns.write("serverList.txt", JSON.stringify(serverList), "w"); + } + } else { + await ns.sleep(5000); + continue + }; + } + ++i; + } + ns.tprint("Extiting purchaseServers script!") +} /** @param {NS} ns */ -export function copyAndRunScript(ns, funnyScript, currentServer) { +function listPurchasedServers(ns) { + return ns.getPurchasedServers(); +} + +/** @param {NS} ns */ +function copyAndRunSript(ns, funnyScript, currentServer) { // change to run for one specific server with bestTarget from file //let minRam = ns.getScriptRam(funnyScript); let bestTarget = JSON.parse(ns.read("bestTarget.txt")); - let name = currentServer; let serverList = JSON.parse(ns.read("serverList.txt")); ns.print(name); @@ -137,16 +183,15 @@ export function copyAndRunScript(ns, funnyScript, currentServer) { if (serverList[name].maxRam > 0) { ns.scp(funnyScript, name, "home"); let maxProcesses = 1; - if (serverList[name].maxRam >= 8) { - maxProcesses = Math.max(Math.floor((serverList[name].maxRam) / 8), 1); + if (serverList[name].maxRam - 64 > 512) { + + maxProcesses = Math.max(Math.floor((serverList[name].maxRam - 64) / 512), 1); } else { maxProcesses = 1 }; - for (let n = 1; n <= maxProcesses; n++) { ns.exec(funnyScript[0], name, 1, bestTarget.serverName); } - /*let maxThreads = 0; if (name === "home") { maxThreads = Math.floor((serverList[name].maxRam - ns.getServerUsedRam(name) - 32) / minRam); @@ -171,108 +216,156 @@ export function copyAndRunScript(ns, funnyScript, currentServer) { } /** @param {NS} ns */ -export async function purchaseAndUpgradeServers(ns) { - ns.disableLog("sleep"); - ns.disableLog("getServerMoneyAvailable"); - ns.disableLog("getServerMaxRam"); - let maxPurchasedServers = ns.getPurchasedServerLimit(); - let purchasedServers = []; - let count = listPurchasedServers(ns).length; - let currentMoney = 0; +function getCracks(ns) { + let cracks = {}; + if (ns.fileExists("BruteSSH.exe", "home")) { + cracks["BruteSSH.exe"] = ns.brutessh; + }; + if (ns.fileExists("FTPCrack.exe", "home")) { + cracks["FTPCrack.exe"] = ns.ftpcrack; + }; + if (ns.fileExists("relaySMTP.exe", "home")) { + cracks["relaySMTP.exe"] = ns.relaysmtp; + }; + if (ns.fileExists("HTTPWorm.exe", "home")) { + cracks["HTTPWorm.exe"] = ns.httpworm; + }; + if (ns.fileExists("SQLInject.exe", "home")) { + cracks["SQLInject.exe"] = ns.sqlinject; + }; + return cracks; +} + +/** @param {NS} ns */ +function scanServerList(ns, bSilent) { + const home = "home"; let serverList = {}; - while (count < maxPurchasedServers) { - purchasedServers = listPurchasedServers(ns); - currentMoney = ns.getServerMoneyAvailable("home"); - let targetRamInitial = 16; - if (ns.getPurchasedServerCost(targetRamInitial) < currentMoney) { - let hostname = ns.purchaseServer("pserv-" + purchasedServers.length, 16); - - count = listPurchasedServers(ns).length; - serverList = JSON.parse(ns.read("serverList.txt")); - serverList[hostname] = { - serverName: hostname, - maxRam: 16, - maxMoney: 0, - minSec: 0, - minPorts: 5, - minHackLvl: 1, - rootAccess: true, - factorMoneyPerTime: 99999999, - openPorts: 0, - }; - ns.write("serverList.txt", JSON.stringify(serverList), "w"); - continue - } else { - await ns.sleep(5000); - } - } - - let i = 5; - while (i < 21) { - let targetRam = 2 ** i; - purchasedServers = listPurchasedServers(ns); - for (let currentServer of purchasedServers) { - currentMoney = ns.getServerMoneyAvailable("home"); - - if (ns.getServerMaxRam(currentServer) < targetRam && ns.getPurchasedServerUpgradeCost(currentServer, targetRam) < currentMoney) { - if (ns.upgradePurchasedServer(currentServer, targetRam)) { - ns.print(currentServer + " upgraded to " + targetRam + " GB RAM"); - serverList = JSON.parse(ns.read("serverList.txt")); - serverList[currentServer].maxRam = targetRam; - ns.write("serverList.txt", JSON.stringify(serverList), "w"); - } - } else { - await ns.sleep(5000); - continue - }; - } - ++i; - } - ns.tprint("Extiting purchaseServers script!") -} - -/** @param {NS} ns */ -function listPurchasedServers(ns) { - return ns.getPurchasedServers(); -} - -/** @param {NS} ns */ -export async function runControllerOnPserv(ns) { - let purchasedServers = listPurchasedServers(ns); - let nPID = 0; - nPID = ns.exec("S2controller.js", "home"); - ns.tprint("Started S2controller.js on " + "home" + " with PID " + nPID) - for (let currentServer of purchasedServers) { - ns.scp(["S2tGrow.js", "S2tWeaken.js", "S2tHack.js", "S2controller.js", "S2utils.js"], currentServer, "home"); - nPID = ns.exec("S2controller.js", currentServer); - if (nPID > 0) { - ns.tprint("Started S2controller.js on " + currentServer + " with PID " + nPID) - } - } -} - -/** @param {NS} ns */ -export async function backdoor(ns) { - let serverList = JSON.parse(ns.read("serverList.txt")); - let lasthackingLevel = 0; - let currentHackingLevel = 0; - while (true) { - currentHackingLevel = ns.getHackingLevel(); - if (currentHackingLevel > lasthackingLevel) { - lasthackingLevel = currentHackingLevel; - for (const [name, entry] of Object.entries(serverList)) { - if (entry.minHackLvl <= lasthackingLevel && entry.hasBackdoor !== true) { - ns.singularity.connect(name); - await ns.singularity.installBackdoor(); - ns.singularity.connect("home"); - serverList[name].hasBackdoor = true; - ns.tprint("Backdoor on: " + name); - } + let unscanned = []; + let nHackingLevel = ns.getHackingLevel(); + let oServer; + unscanned.push(home); + while (unscanned.length > 0) { + let currentServer = unscanned.pop(); + if (!serverList[currentServer]) { + let maxRam = ns.getServerMaxRam(currentServer); + let minPorts = ns.getServerNumPortsRequired(currentServer); + let minSecLevel = ns.getServerMinSecurityLevel(currentServer); + let minHackLevel = ns.getServerRequiredHackingLevel(currentServer); + let rootAccess = ns.hasRootAccess(currentServer); + let serverMoney = ns.getServerMaxMoney(currentServer); + let serverFiles = ns.ls(currentServer); + let skillFactor = (2.5 * minHackLevel * minSecLevel + 500) / (nHackingLevel + 50); + let compareTimeFactor = serverMoney / skillFactor / 10e7; + let nHackingChance = ns.hackAnalyzeChance(currentServer); + oServer = ns.getServer(currentServer); + let sOrg = oServer.organizationName; + let nCores = oServer.cpuCores; + if (minHackLevel <= nHackingLevel && !currentServer.includes("home") && !currentServer.includes("pserv") && serverMoney > 0 && !bSilent) { + //if (!currentServer.includes("home") && !currentServer.includes("pserv") && !bSilent) { + ns.tprint("Server : " + currentServer); + ns.tprint("sOrg : " + sOrg); + ns.tprint("Hacking : " + minHackLevel); + ns.tprint("RAM : " + maxRam); + ns.tprint("Cores : " + nCores); + ns.tprint("Money : " + Math.floor(serverMoney).toLocaleString()); + ns.tprint("Hack chance : " + Math.floor(nHackingChance * 10000) / 100 + " %"); + ns.tprint("Security : " + minSecLevel); + ns.tprint("--------------------------------------------------------------"); } - ns.write("serverList.txt", JSON.stringify(serverList), "w"); - } else { - await ns.sleep(30000) - }; - + serverList[currentServer] = + { + serverName: currentServer, + maxRam: maxRam, + maxMoney: serverMoney, + minSec: minSecLevel, + minPorts: minPorts, + minHackLvl: minHackLevel, + rootAccess: rootAccess, + factorMoneyPerTime: compareTimeFactor, + openPorts: 0, + serverFiles: serverFiles, + hackingChance: nHackingChance + }; + let neighbours = ns.scan(currentServer); + for (let i = 0; i < neighbours.length; i++) { + let neighbour = neighbours[i]; + if (serverList[neighbour]) { + continue + } + unscanned.push(neighbour); + } + } } + ns.write("serverList.txt", JSON.stringify(serverList), "w"); } + +/** @param {NS} ns */ +function findBestTarget(ns, maxSec, maxPorts, currentHackLevel, manualTargetOverride) { + //ns.tprint("start of findBestTarget "); + const bSilent = ns.args[1] === true ? true : false; // if true supress feedback + //ns.tprint("bSilent = " +bSilent); + let sCurrentBestTarget = JSON.parse(ns.read("bestTarget.txt")); + //let sCurrentBestTarget = "n00dles"; + //ns.tprint("sCurrentBestTarget = " +JSON.stringify(sCurrentBestTarget)); + //if (!bSilent) ns.tprint("sCurrentBestTarget = " + sCurrentBestTarget.serverName); + let serverList = JSON.parse(ns.read("serverList.txt")); + let bestEntry = null; + let compareTime = 0; + let nMaxMoneyPerChance = 0; + let nBestMoneyPerChance = 0; + //ns.tprint("before for loop "); + for (const [name, entry] of Object.entries(serverList)) { + if (entry.minSec <= maxSec && entry.minPorts <= maxPorts && entry.minHackLvl < currentHackLevel) { + nMaxMoneyPerChance = (entry.maxMoney * entry.hackingChance) / entry.minSec; + //ns.tprint("nMaxMoneyPerChance " + nMaxMoneyPerChance); + /* + if (entry.factorMoneyPerTime > compareTime) { + compareTime = entry.factorMoneyPerTime; + bestEntry = name; + } + */ + if (nMaxMoneyPerChance > nBestMoneyPerChance) { + nBestMoneyPerChance = nMaxMoneyPerChance; + bestEntry = name; + if (!bSilent) ns.tprint("bestEntry " + bestEntry); + if (!bSilent) ns.tprint("╚ value = " + Math.floor(nMaxMoneyPerChance)); + + } + } + } + + if (manualTargetOverride.length > 0) { + bestEntry = manualTargetOverride; + } + + if (sCurrentBestTarget.serverName === bestEntry) { + if (!bSilent) ns.tprint("Same target = " + bestEntry); + } + else { + ns.tprint("New best target = " + cCyan + bestEntry + cReset); + } + ns.write("bestTarget.txt", JSON.stringify(serverList[bestEntry]), "w"); +} + +/** @param {NS} ns */ +async function runScriptsFromServers(ns, sScript, sTarget) { + let serverList = JSON.parse(ns.read("serverList.txt")); + let nScripts; + let nMaxRam = 0; + const nScriptRAM = ns.getScriptRam(sScript); + for (const [name, entry] of Object.entries(serverList)) { + //let rootAccess = ns.hasRootAccess(currentServer); + nMaxRam = ns.getServerMaxRam(entry.serverName); + nScripts = Math.floor(nMaxRam / nScriptRAM); + if (entry.maxRam >= 8 && serverList[name].rootAccess === true && !entry.serverName.includes("home") && !entry.serverName.includes("pserv")) { + //ns.killall(entry.serverName); + ns.scriptKill(sScript, entry.serverName); + ns.scp(sScript, entry.serverName); + while (nScripts > 0) { + ns.exec(sScript, entry.serverName, 1, sTarget); + nScripts--; + await ns.sleep(10); + } + } + } +} \ No newline at end of file diff --git a/local/path/home/settings.txt b/local/path/home/settings.txt new file mode 100644 index 0000000..95d0f21 --- /dev/null +++ b/local/path/home/settings.txt @@ -0,0 +1,4 @@ +{"setting":{ +"autoUpgrades":true, +"autoPurchaseServers":true +}} \ No newline at end of file diff --git a/local/path/home/sharePserv.js b/local/path/home/sharePserv.js new file mode 100644 index 0000000..0663fec --- /dev/null +++ b/local/path/home/sharePserv.js @@ -0,0 +1,34 @@ +/** @param {NS} ns */ +export async function main(ns) { + const bKill = ns.args[0]; // if true kill all existing processess + + //host and script info + const sThisRunner = ns.getHostname(); + //const sThisScript = ns.getScriptName(); + const nThisPID = ns.pid; + + //open log for this script + ns.tail(nThisPID, sThisRunner, ns.args); + + + //my servers + const nServ = ns.getPurchasedServers(); + + const sShareScript = "factionboost.js"; + let nScripts = 0; + + //kill all scripts + for (let i = 0; i < nServ.length; i++) { + + nScripts = Math.floor(ns.getServerMaxRam(nServ[i]) / ns.getScriptRam(sShareScript)); + + if (bKill) { ns.killall(nServ[i]); } + else { ns.scriptKill(sShareScript, nServ[i]); } + ns.scp(sShareScript, nServ[i], "home"); + + let nShare = Math.floor(((ns.getServerMaxRam(nServ[i]) - ns.getServerUsedRam(nServ[i])) / ns.getScriptRam(sShareScript))); + if (nShare > 0) { + ns.exec(sShareScript, nServ[i], nShare); + } + } +} \ No newline at end of file diff --git a/local/path/home/singularity/RMroutelist.js b/local/path/home/singularity/RMroutelist.js new file mode 100644 index 0000000..b869d2e --- /dev/null +++ b/local/path/home/singularity/RMroutelist.js @@ -0,0 +1,52 @@ +/** @param {NS} ns */ +export async function main(ns) { + ns.tail(); + let serverRoutes = await scanRecursiveWrapper(ns); + let currentHackingLevel = ns.getHackingLevel(); + let currentArray = []; + let currentHop = ""; + + for (const [name, entry] of Object.entries(serverRoutes)) { + if (ns.getServerRequiredHackingLevel(name) < currentHackingLevel && ns.hasRootAccess(name) === true) { + currentArray = entry; + if (entry.length > 0) { + while (currentArray.length > 0) { + currentHop = currentArray.shift(); + if (ns.singularity.connect(currentHop) === false) ns.tprint("Error when trying to connect to: " + currentHop); + } + ns.tprint("Trying to backdoor " + currentHop) + await ns.singularity.installBackdoor(currentHop); + ns.tprint("Success on " + currentHop) + ns.singularity.connect("home"); + } + } + } +} + +/** @param {NS} ns */ +async function scanRecursiveWrapper(ns) { + let startTime = Date.now(); + ns.rm("ServerRouteList.txt"); + await scanRecursive(ns, [], "home", startTime); + let result = JSON.parse("[" + ns.read("ServerRouteList.txt") + "{}]").reduce((acc, obj) => ({ ...acc, ...obj }), {}); + ns.write("ServerRouteList.txt", JSON.stringify(result, "w")); + return result; +} + +/** @param {NS} ns */ +async function scanRecursive(ns, parents, currentServer, startTime) { + let currentTime = Date.now(); + if (currentTime > startTime + 5) { + return + } else { + let currentChildren = ns.scan(currentServer); + let parentsSet = new Set(parents); + let cleanedChildren = currentChildren.filter(element => !parentsSet.has(element)); + let tempServername = String(currentServer); + ns.write("ServerRouteList.txt", JSON.stringify({ [tempServername]: parents }) + ",", "a"); + parents.push(currentServer); + for (let child in cleanedChildren) { + await scanRecursive(ns, parents, cleanedChildren[child], startTime) + } + } +} \ No newline at end of file diff --git a/local/path/home/singularity/manualalgo.js b/local/path/home/singularity/manualalgo.js new file mode 100644 index 0000000..682fa96 --- /dev/null +++ b/local/path/home/singularity/manualalgo.js @@ -0,0 +1,71 @@ +/** @param {NS} ns */ +export async function main(ns) { + const sNode = ns.args[0]; // target server + + //logs + ns.disableLog("getServerSecurityLevel"); + ns.disableLog("getServerMoneyAvailable"); + + //server info + const nMinSec = ns.getServerMinSecurityLevel(sNode); + const nMaxCash = ns.getServerMaxMoney(sNode); + while (true) { + + //timestamp + let currentDate = new Date(); + let ntimeStamp = currentDate.toLocaleTimeString('sw-SV') + " -"; + + const nCurrSec = ns.getServerSecurityLevel(sNode); + const nCurrCash = ns.getServerMoneyAvailable(sNode); + + ns.print(ntimeStamp + "---------------------------------------------------------------"); + ns.print("Cash: " + (Math.floor(nCurrCash * 1000) / 1000) + " / " + nMaxCash); + ns.print("Security: " + (Math.floor(nCurrSec * 1000) / 1000) + " / " + nMinSec); + + if (nCurrSec > (nMinSec + 1)) { + + //Calculate estimate time of completion + let nOffset = ns.getWeakenTime(sNode); + let nWeakTime = new Date(currentDate.getTime() + nOffset); + let sWeakTime = nWeakTime.toLocaleTimeString('sw-SV'); + + //Print estimated time of completion + ns.print("Weakening " + sNode + " Estimated complete at " + sWeakTime); + + //run weaken + await ns.weaken(sNode); + ns.print("-------------------------------------------------------------------------"); + } + else if (nCurrCash < (nMaxCash * 0.9)) { + + //Calculate estimate time of completion + let nOffset = ns.getGrowTime(sNode); + let nGrowTime = new Date(currentDate.getTime() + nOffset); + let sGrowTime = nGrowTime.toLocaleTimeString('sw-SV'); + + //Print estimated time of completion + ns.print("Growing " + sNode + " Estimated complete at " + sGrowTime); + + //run grow + await ns.grow(sNode); + ns.print("-------------------------------------------------------------------------"); + } + else { + + + //Calculate estimate time of completion + let nOffset = ns.getHackTime(sNode); + let nHackTime = new Date(currentDate.getTime() + nOffset); + let sHackTime = nHackTime.toLocaleTimeString('sw-SV'); + + + //Print estimated time of completion + ns.print("Hacking " + sNode + " Estimated complete at " + sHackTime); + + //run hack + //await ns.hack(sNode); + await ns.singularity.manualHack(); + ns.print("-------------------------------------------------------------------------"); + } + } +} \ No newline at end of file diff --git a/local/path/home/tGrow.js b/local/path/home/tGrow.js deleted file mode 100644 index 6277f0f..0000000 --- a/local/path/home/tGrow.js +++ /dev/null @@ -1,24 +0,0 @@ -/* - Workers are mostly the same, aside from uncommented portions allowing the hack and grow workers to report. - I've also generally commented out the terminal logging, as it gets rather laggy when there's a lot of scripts - writing to terminal. -*/ - -/** @param {NS} ns */ -export async function main(ns) { - const job = JSON.parse(ns.args[0]); - let delay = job.end - job.time - Date.now(); - if (delay < 0) { - ns.tprint(`WARN: Batch ${job.batch} ${job.type} was ${-delay}ms late. (${job.end})\n`); - ns.writePort(ns.pid, -delay); - delay = 0; - } else { - ns.writePort(ns.pid, 0); - } - await ns.grow(job.target, { additionalMsec: delay }); - const end = Date.now(); - ns.atExit(() => { - if (job.report) ns.writePort(job.port, job.type + job.server); - // ns.tprint(`Batch ${job.batch}: ${job.type} finished at ${end.toString().slice(-6)}/${Math.round(job.end).toString().slice(-6)}\n`); - }); -} \ No newline at end of file diff --git a/local/path/home/tHack.js b/local/path/home/tHack.js deleted file mode 100644 index 114029a..0000000 --- a/local/path/home/tHack.js +++ /dev/null @@ -1,24 +0,0 @@ -/* - Workers are mostly the same, aside from uncommented portions allowing the hack and grow workers to report. - I've also generally commented out the terminal logging, as it gets rather laggy when there's a lot of scripts - writing to terminal. -*/ - -/** @param {NS} ns */ -export async function main(ns) { - const job = JSON.parse(ns.args[0]); - let delay = job.end - job.time - Date.now(); - if (delay < 0) { - ns.tprint(`WARN: Batch ${job.batch} ${job.type} was ${-delay}ms late. (${job.end})\n`); - ns.writePort(ns.pid, -delay); - delay = 0; - } else { - ns.writePort(ns.pid, 0); - } - await ns.hack(job.target, { additionalMsec: delay }); - const end = Date.now(); - ns.atExit(() => { - if (job.report) ns.writePort(job.port, job.type + job.server); - // ns.tprint(`Batch ${job.batch}: ${job.type} finished at ${end.toString().slice(-6)}/${Math.round(job.end).toString().slice(-6)}\n`); - }); -} \ No newline at end of file diff --git a/local/path/home/tWeaken.js b/local/path/home/tWeaken.js deleted file mode 100644 index 6694afb..0000000 --- a/local/path/home/tWeaken.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - Workers are mostly the same, aside from uncommented portions allowing the hack and grow workers to report. - I've also generally commented out the terminal logging, as it gets rather laggy when there's a lot of scripts - writing to terminal. -*/ - -/** @param {NS} ns */ -export async function main(ns) { - const job = JSON.parse(ns.args[0]); - - let delay = job.end - job.time - Date.now(); - if (delay < 0) { - // We write back to the controller if jobs are delayed so that it can adjust the other jobs to match. - ns.tprint(`WARN: Batch ${job.batch} ${job.type} was ${-delay}ms late. (${job.end})\n`); - ns.writePort(ns.pid, -delay); - delay = 0; - } else { - ns.writePort(ns.pid, 0); - } - await ns.weaken(job.target, { additionalMsec: delay }); - const end = Date.now(); - - // Write back to let the controller know that we're done. - ns.atExit(() => { - if (job.report) ns.writePort(job.port, job.type + job.server); - // ns.tprint(`Batch ${job.batch}: ${job.type} finished at ${end.toString().slice(-6)}/${Math.round(job.end).toString().slice(-6)}\n`); - }); -} \ No newline at end of file diff --git a/local/path/home/template.js b/local/path/home/template.js deleted file mode 100644 index 2b0c5b9..0000000 --- a/local/path/home/template.js +++ /dev/null @@ -1,4 +0,0 @@ -export async function main(ns) { - ns.tprint("Hello World!"); -} -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkM6L2dhbWVzL0JpdEJ1cm5lckdpdC92aXRlYnVybmVyLXRlbXBsYXRlL3NyYy90ZW1wbGF0ZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBOUyB9IGZyb20gJ0Bucyc7XHJcblxyXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbWFpbihuczogTlMpIHtcclxuICBucy50cHJpbnQoJ0hlbGxvIFdvcmxkIScpO1xyXG59XHJcbiJdLCJtYXBwaW5ncyI6IkFBRUEsc0JBQXNCLEtBQUssSUFBUTtBQUNqQyxLQUFHLE9BQU8sY0FBYztBQUMxQjsiLCJuYW1lcyI6W119 \ No newline at end of file diff --git a/local/path/home/test.js b/local/path/home/test.js index 75087d4..8a83ac5 100644 --- a/local/path/home/test.js +++ b/local/path/home/test.js @@ -1,161 +1,16 @@ /** @param {NS} ns */ export async function main(ns) { - ns.tprint(ns.codingcontract.getContractTypes()) - let testcontract = ns.codingcontract.createDummyContract("Total Ways to Sum") - let contractType = ns.codingcontract.getContractType(testcontract); - ns.tprint(ns.codingcontract.getDescription(testcontract)) - let n = ns.codingcontract.getData(testcontract); - ns.tprint("Data: " + n); - let answer = ""; - if (contractType === "Find Largest Prime Factor") { - answer = largestPrimeFactor(n); - } - if (contractType === "Subarray with Maximum Sum") { - answer = SubarrayWithMaximumSum(ns, n) - } - if (contractType === "Total Ways to Sum") { - answer = TotalWaysToSum(ns, n) - } + let oSettings = JSON.parse(ns.read("settings.txt")); + // let variable = someJSON.missingKey || "" + //let tempVar = oSettings.settings.missingKey || ""; + //ns.tprint(tempVar) - ns.tprint(answer); + ns.tprint(oSettings); + ns.tprint(JSON.stringify(oSettings)); + ns.tprint(oSettings.setting.autoUpgrades); - ns.tprint(ns.codingcontract.attempt(answer, testcontract)); -} -/* -5: -4 1 -3 2 -3 1 1 -2 2 1 -2 1 1 1 -1 1 1 1 1 + //let tempVar = oSettings.settings.missingKey || ""; + //ns.tprint(tempVar) -6: -5 1 -4 2 -4 1 1 -3 3 -3 2 1 -3 1 1 1 -2 2 2 -2 2 1 1 -2 1 1 1 1 -1 1 1 1 1 1 - -# Start with one position m filling it with the integers between 1 and target -# For each m, fill the next position n with integers between 1 and m -# Repeat as long as the sum is smaller than target. -# append all iterations to the Array and count -*/ - -function TotalWaysToSum(ns, target) { - let sumArray = []; - let inputArray = []; - let unfinishedArray = []; - let rollingSum = 0; - for (let i = 1; i < target; i++) { - inputArray.push([i]); - } - let z = 1 - while (inputArray.length > 0) { - z++ - inputArray.forEach((element) => { - rollingSum = element.reduce((a, b) => a + b, 0); - if (rollingSum === target) { - sumArray.push(element) - } else { - - for (let k = 1; k <= element[element.length-1] && k <= target - rollingSum; k++) { - - unfinishedArray.push(element.concat([k])) - } - } - } - ) - inputArray = unfinishedArray; - } - ns.tprint("Target: " +target) - ns.tprint("Length: " + sumArray.length) - return sumArray.length -} - - - - - - - - -function SubarrayWithMaximumSum(ns, givenArray) { - let arrayLength = givenArray.length; - let maxSum = -10000; - let runningSum = 0; - for (let i = 1; i <= arrayLength; i++) { - for (let j = 0; j <= arrayLength - i; j++) { - runningSum = eval(givenArray.slice(j, i + j).join('+')); - //ns.tprint("i: "+i+ " j: "+ j + " Array: "+givenArray.slice(j,i+j)+ " eval: "+ givenArray.slice(j,i+j).join('+')+"runningSum: "+runningSum); - if (maxSum < runningSum) { maxSum = runningSum }; - } - } - return maxSum -} - - -function FindLargestPrimeFactor(number) { - - let factor = 2; - while (factor * factor <= number) { - if (number % factor === 0) { - number /= factor; - } else { - factor++ - } - } - return number; -} - -/* -function FindLargestPrimeFactor(n) { - let x = Math.ceil(Math.random()*10); - let y = x; - let d = 1; - - while (d === 1) { - x = g(x, n); - y = g(g(y, n), n) - d = gcd(n, Math.abs(x - y)) - //ns.tprint("x:" + x + " y: " + y + " d: " + d) - } - if (d === n) { - return ("failure") - } - else { - return (d) - } -} - -function g(x, n) { - return (x * x) % n -} - -function gcd(a,b) { - a = Math.abs(a); - b = Math.abs(b); - if (b > a) {var temp = a; a = b; b = temp;} - while (true) { - if (b == 0) return a; - a %= b; - if (a == 0) return b; - b %= a; - } -} - - -function gcd(a, b) { - if (!b) { - return a; - } - return gcd(b, a % b); -} -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/local/path/home/testhackgrow.js b/local/path/home/testhackgrow.js new file mode 100644 index 0000000..c981745 --- /dev/null +++ b/local/path/home/testhackgrow.js @@ -0,0 +1,41 @@ +/** @param {NS} ns */ +export async function main(ns) { + ns.tail(); + const sTarget = ns.args[0]; // run on this target instead of best + const nHackThreads = ns.args[1] ? ns.args[1] : 1; + + ns.disableLog("sleep"); + + ns.print("nHackThreads = " + nHackThreads); + + //ns.tprint(ns.getHackingMultipliers()); + + let nHackAmountPercent = ns.hackAnalyze(sTarget) * nHackThreads; + let nTargetMoney = ns.getServerMoneyAvailable(sTarget); + let nHackAmount = nTargetMoney * nHackAmountPercent; + ns.print("nHackAmountPercent = " + nHackAmountPercent); + ns.print("nTargetMoney = " + nTargetMoney); + ns.print("nHackAmount = " + nHackAmount); + + let nGrowthThreads = ns.growthAnalyze(sTarget, 1 + nHackAmountPercent, 1); + ns.print("nGrowthThreads = " + nGrowthThreads); + let nGrowThreadsINT = Math.ceil(nGrowthThreads); + ns.print("Hack() : Grow() Ratio = " + nHackThreads + ":" + nGrowThreadsINT); + + + + //test hack() and grow() + /* + let nHackPID = ns.exec("RMhack.js", "home", nHackThreads, sTarget); + ns.tail(nHackPID); + let nGrowPID = ns.exec("RMgrow.js", "home", nGrowThreadsINT, sTarget); + ns.tail(nGrowPID); + ns.print("Wait for Hack and Grow..."); + while (ns.isRunning(nHackPID) || ns.isRunning(nGrowPID)) { + await ns.sleep(1000); + } + ns.print("Wait complete"); + nTargetMoney = ns.getServerMoneyAvailable(sTarget); + ns.print("nTargetMoney = " + nTargetMoney); + */ +} \ No newline at end of file diff --git a/local/path/home/upgrade.js b/local/path/home/upgrade.js new file mode 100644 index 0000000..283be81 --- /dev/null +++ b/local/path/home/upgrade.js @@ -0,0 +1,66 @@ +import { listPurchasedServers, getSetting } from "myLibrary.js"; + +// Custom color coding. +const cCyan = "\u001b[36m"; +const cGreen = "\u001b[32m"; +const cRed = "\u001b[31m"; +const cReset = "\u001b[0m"; + +/** @param {NS} ns */ +export async function main(ns) { + ns.disableLog("ALL"); + + //host and script info + const sThisRunner = ns.getHostname(); + + //open log for this script + ns.tail(ns.pid, sThisRunner); + + //const npServ = ["pserv-0", "pserv-1", "pserv-2", "pserv-3", "pserv-4", "pserv-5", "pserv-6", "pserv-7", "pserv-8", "pserv-9", "pserv-10", "pserv-11", "pserv-12", "pserv-13", "pserv-14", "pserv-15", "pserv-16", "pserv-17", "pserv-18", "pserv-19", "pserv-20", "pserv-21", "pserv-22", "pserv-23", "pserv-24"]; + const npServ = listPurchasedServers(ns); + let nCurrentRAM = 4; + let nMyMoney = ns.getServerMoneyAvailable("home"); + let bAutoUpgrade = getSetting(ns, "autoUpgrades"); + while (bAutoUpgrade && nCurrentRAM < 2 ** 20) { + + //for (let i = 0; i < npServ.length; i++) { + for (let i = 0; i < npServ.length && bAutoUpgrade; i++) { + ns.print("----------------------------------------------------------------------"); + nMyMoney = ns.getServerMoneyAvailable("home"); + + let nNextRAM = nCurrentRAM * 2; + let nUpgradeCost = ns.getPurchasedServerUpgradeCost(npServ[i], nNextRAM); + + ns.print("npServ = " + npServ[i]); + ns.print("nMyMoney = " + Math.ceil(nMyMoney).toLocaleString()); + ns.print("nCurrentRAM = " + nCurrentRAM.toLocaleString()); + ns.print("nNextRAM = " + nNextRAM); + ns.print("nUpgradeCost = " + Math.ceil(nUpgradeCost).toLocaleString()); + + while (bAutoUpgrade && nMyMoney < nUpgradeCost) { + ns.print("Money Treshold = " + Math.ceil(nMyMoney).toLocaleString() + " / " + Math.ceil(nUpgradeCost).toLocaleString()); + await ns.sleep(1000); + bAutoUpgrade = getSetting(ns, "autoUpgrades"); + if (bAutoUpgrade === false) { + return; + } + nMyMoney = ns.getServerMoneyAvailable("home"); + } + + if (ns.upgradePurchasedServer(npServ[i], nNextRAM)) { + ns.print("Server: " + npServ[i] + " upgraded to: " + nNextRAM + "GB"); + ns.tprint(cCyan + "Server: " + npServ[i] + " upgraded to: " + nNextRAM.toLocaleString() + " GB" + cReset); + ns.toast("Server: " + npServ[i] + " upgraded to: " + nNextRAM.toLocaleString() + " GB", "info", 10000); + } + else { + ns.print("Server: " + npServ[i] + " could not be upgraded to : " + nNextRAM + "GB it is currently at: " + ns.getServerMaxRam(npServ[i]) + "GB"); + } + bAutoUpgrade = getSetting(ns, "autoUpgrades"); + if (bAutoUpgrade === false) { + return; + } + } + nCurrentRAM *= 2; + } + ns.print("----------------------------------------------------------------------"); +} \ No newline at end of file diff --git a/local/path/home/utils.js b/local/path/home/utils.js deleted file mode 100644 index 609a1e5..0000000 --- a/local/path/home/utils.js +++ /dev/null @@ -1,218 +0,0 @@ -/* - This file remains unchanged from the previous part, aside from updating the file paths. - I didn't even bother removing the old comments. -*/ - -/** @param {NS} ns */ -export async function main(ns) { - ns.tprint("This is just a function library, it doesn't do anything."); -} - -// The recursive server navigation algorithm. The lambda predicate determines which servers to add to the final list. -// You can also plug other functions into the lambda to perform other tasks that check all servers at the same time. -/** @param {NS} ns */ -export function getServers(ns, lambdaCondition = () => true, hostname = "home", servers = [], visited = []) { - if (visited.includes(hostname)) return; - visited.push(hostname); - if (lambdaCondition(hostname)) servers.push(hostname); - const connectedNodes = ns.scan(hostname); - if (hostname !== "home") connectedNodes.shift(); - for (const node of connectedNodes) getServers(ns, lambdaCondition, node, servers, visited); - return servers; -} - -// Here are a couple of my own getServers modules. -// This one finds the best target for hacking. It tries to balance expected return with time taken. -/** @param {NS} ns */ -export function checkTarget(ns, server, target = "n00dles", forms = false) { - if (!ns.hasRootAccess(server)) return target; - const player = ns.getPlayer(); - const serverSim = ns.getServer(server); - const pSim = ns.getServer(target); - let previousScore; - let currentScore; - if (serverSim.requiredHackingSkill <= player.skills.hacking / (forms ? 1 : 2)) { - if (forms) { - serverSim.hackDifficulty = serverSim.minDifficulty; - pSim.hackDifficulty = pSim.minDifficulty; - previousScore = pSim.moneyMax / ns.formulas.hacking.weakenTime(pSim, player) * ns.formulas.hacking.hackChance(pSim, player); - currentScore = serverSim.moneyMax / ns.formulas.hacking.weakenTime(serverSim, player) * ns.formulas.hacking.hackChance(serverSim, player); - } else { - previousScore = pSim.moneyMax / pSim.minDifficulty / ns.getWeakenTime(pSim.hostname); - currentScore = serverSim.moneyMax / serverSim.minDifficulty / ns.getWeakenTime(serverSim.hostname); - } - if (currentScore > previousScore) target = server; - } - return target; -} - -// A simple function for copying a list of scripts to a server. -/** @param {NS} ns */ -export function copyScripts(ns, server, scripts, overwrite = false) { - for (const script of scripts) { - if ((!ns.fileExists(script, server) || overwrite) && ns.hasRootAccess(server)) { - ns.scp(script, server); - } - } -} - -// A generic function to check that a given server is prepped. Mostly just a convenience. -export function isPrepped(ns, server) { - const tolerance = 0.0001; - const maxMoney = ns.getServerMaxMoney(server); - const money = ns.getServerMoneyAvailable(server); - const minSec = ns.getServerMinSecurityLevel(server); - const sec = ns.getServerSecurityLevel(server); - const secFix = Math.abs(sec - minSec) < tolerance; - return (money === maxMoney && secFix) ? true : false; -} - -/* - This prep function isn't part of the tutorial, but the rest of the code wouldn't work without it. - I don't make any guarantees, but I've been using it and it's worked well enough. I'll comment it anyway. - The prep strategy uses a modified proto-batching technique, which will be covered in part 2. -*/ -/** @param {NS} ns */ -export async function prep(ns, values, ramNet) { - const maxMoney = values.maxMoney; - const minSec = values.minSec; - let money = values.money; - let sec = values.sec; - while (!isPrepped(ns, values.target)) { - const wTime = ns.getWeakenTime(values.target); - const gTime = wTime * 0.8; - const dataPort = ns.getPortHandle(ns.pid); - dataPort.clear(); - - const pRam = ramNet.cloneBlocks(); - const maxThreads = Math.floor(ramNet.maxBlockSize / 1.75); - const totalThreads = ramNet.prepThreads; - let wThreads1 = 0; - let wThreads2 = 0; - let gThreads = 0; - let batchCount = 1; - let script, mode; - /* - Modes: - 0: Security only - 1: Money only - 2: One shot - */ - - if (money < maxMoney) { - gThreads = Math.ceil(ns.growthAnalyze(values.target, maxMoney / money)); - wThreads2 = Math.ceil(ns.growthAnalyzeSecurity(gThreads) / 0.05); - } - if (sec > minSec) { - wThreads1 = Math.ceil((sec - minSec) * 20); - if (!(wThreads1 + wThreads2 + gThreads <= totalThreads && gThreads <= maxThreads)) { - gThreads = 0; - wThreads2 = 0; - batchCount = Math.ceil(wThreads1 / totalThreads); - if (batchCount > 1) wThreads1 = totalThreads; - mode = 0; - } else mode = 2; - } else if (gThreads > maxThreads || gThreads + wThreads2 > totalThreads) { - mode = 1; - const oldG = gThreads; - wThreads2 = Math.max(Math.floor(totalThreads / 13.5), 1); - gThreads = Math.floor(wThreads2 * 12.5); - batchCount = Math.ceil(oldG / gThreads); - } else mode = 2; - - // Big buffer here, since all the previous calculations can take a while. One second should be more than enough. - const wEnd1 = Date.now() + wTime + 1000; - const gEnd = wEnd1 + values.spacer; - const wEnd2 = gEnd + values.spacer; - - // "metrics" here is basically a mock Job object. Again, this is just an artifact of repurposed old code. - const metrics = { - batch: "prep", - target: values.target, - type: "none", - time: 0, - end: 0, - port: ns.pid, - log: values.log, - report: false - }; - - // Actually assigning threads. We actually allow grow threads to be spread out in mode 1. - // This is because we don't mind if the effect is a bit reduced from higher security unlike a normal batcher. - // We're not trying to grow a specific amount, we're trying to grow as much as possible. - for (const block of pRam) { - while (block.ram >= 1.75) { - const bMax = Math.floor(block.ram / 1.75) - let threads = 0; - if (wThreads1 > 0) { - script = "tWeaken.js"; - metrics.type = "pWeaken1"; - metrics.time = wTime; - metrics.end = wEnd1; - threads = Math.min(wThreads1, bMax); - if (wThreads2 === 0 && wThreads1 - threads <= 0) metrics.report = true; - wThreads1 -= threads; - } else if (wThreads2 > 0) { - script = "tWeaken.js"; - metrics.type = "pWeaken2"; - metrics.time = wTime; - metrics.end = wEnd2; - threads = Math.min(wThreads2, bMax); - if (wThreads2 - threads === 0) metrics.report = true; - wThreads2 -= threads; - } else if (gThreads > 0 && mode === 1) { - script = "tGrow.js"; - metrics.type = "pGrow"; - metrics.time = gTime; - metrics.end = gEnd; - threads = Math.min(gThreads, bMax); - metrics.report = false; - gThreads -= threads; - } else if (gThreads > 0 && bMax >= gThreads) { - script = "tGrow.js"; - metrics.type = "pGrow"; - metrics.time = gTime; - metrics.end = gEnd; - threads = gThreads; - metrics.report = false; - gThreads = 0; - } else break; - metrics.server = block.server; - const pid = ns.exec(script, block.server, { threads: threads, temporary: true }, JSON.stringify(metrics)); - if (!pid) throw new Error("Unable to assign all jobs."); - block.ram -= 1.75 * threads; - } - } - - // Fancy UI stuff to update you on progress. - const tEnd = ((mode === 0 ? wEnd1 : wEnd2) - Date.now()) * batchCount + Date.now(); - const timer = setInterval(() => { - ns.clearLog(); - switch (mode) { - case 0: - ns.print(`Weakening security on ${values.target}...`); - break; - case 1: - ns.print(`Maximizing money on ${values.target}...`); - break; - case 2: - ns.print(`Finalizing preparation on ${values.target}...`); - } - ns.print(`Security: +${ns.formatNumber(sec - minSec, 3)}`); - ns.print(`Money: \$${ns.formatNumber(money, 2)}/${ns.formatNumber(maxMoney, 2)}`); - const time = tEnd - Date.now(); - ns.print(`Estimated time remaining: ${ns.tFormat(time)}`); - ns.print(`~${batchCount} ${(batchCount === 1) ? "batch" : "batches"}.`); - }, 200); - ns.atExit(() => clearInterval(timer)); - - // Wait for the last weaken to finish. - do await dataPort.nextWrite(); while (!dataPort.read().startsWith("pWeaken")); - clearInterval(timer); - await ns.sleep(100); - - money = ns.getServerMoneyAvailable(values.target); - sec = ns.getServerSecurityLevel(values.target); - } - return true; -} \ No newline at end of file