Hack-Weaken-Grow-Weaken script and more

0. Credits To Referenced Scripts

Scripting 101 By Suikoudan

Simple hacknet manager By Kirtle

Kupos automated HWGW Manager - centralized prep and farm of one or many servers By Kupo

1. Shared Scripts

These scripts must be put under the `shared` folder.

They are distributed by the deployer to other servers.

home:~/shared/weaken.js

/** @param {NS} ns **/ export async function main(ns) { // Sleep for given amount, const sleep = ns.args[1] || 1; await ns.sleep(sleep); // and then weaken! await ns.weaken(ns.args[0]); }

home:~/shared/grow.js

/** @param {NS} ns **/ export async function main(ns) { // Sleep for given amount, const sleep = ns.args[1] || 1; await ns.sleep(sleep); // and then grow! await ns.grow(ns.args[0]); }

home:~/shared/hack.js

/** @param {NS} ns **/ export async function main(ns) { // Sleep for given amount, const sleep = ns.args[1] || 1; await ns.sleep(sleep); // and then hack! await ns.hack(ns.args[0]); }

2. Deployer Script

home:~/v1/deployer.js

/** * Automates the process of hacking servers by deploying scripts and cracking open their security. * The script first gathers all servers accessible from the starting point ("home"). It then attempts * to breach the servers' security using available hacking programs and, if successful, deploys hacking scripts * to the compromised servers. This enables automated hacking activities on those servers. * * @param {NS} ns - The namespace object provided by the game, which includes * functions for interacting with the game's systems. * @async */ export async function main(ns) { // Retrieve a list of all reachable servers from "home". const SERVERS = getAllServers(ns); // Define the available hacking programs and their corresponding action functions. const PROGRAMS = [ { file: "BruteSSH.exe", action: ns.brutessh }, { file: "FTPCrack.exe", action: ns.ftpcrack }, { file: "RelaySMTP.exe", action: ns.relaysmtp }, { file: "HTTPWorm.exe", action: ns.httpworm }, { file: "SQLInject.exe", action: ns.sqlinject } ]; // Iterate through each server, excluding "home", and attempt to compromise and deploy scripts. for (let server of SERVERS) { if (server === "home") continue; // Transfer necessary scripts to the server. ns.scp(["/shared/weaken.js", "/shared/grow.js", "/shared/hack.js"], server); let open_ports = 0; // Attempt to run each hacking program that exists on "home", and count successfully opened ports. PROGRAMS.forEach(program => { if (ns.fileExists(program.file)) { program.action(server); open_ports++; } }); // If the number of open ports meets or exceeds the server's requirements, run the nuke command. if (ns.getServerNumPortsRequired(server) <= open_ports) ns.nuke(server); } /** * Discovers all servers connected to the starting server ("home"), using a depth-first search. * Unique servers are recorded to ensure each is processed only once. * @param {NS} ns - The namespace object for accessing game functions. * @returns {string[]} An array of unique server names. */ function getAllServers(ns) { let servers = []; let stack = ["home"]; while (stack.length > 0) { const CURRENT = stack.pop(); if (!servers.includes(CURRENT)) { servers.push(CURRENT); stack.push(...ns.scan(CURRENT).filter(next => !servers.includes(next))); } } return servers; } }

3. FileSystem Script

Abstracts the creation, writing, and reading of files.

home:~data/file-system.js

export class FileSystem { #ns; #file; /** * Creates an instance of the FileSystem class. * @param {object} ns - The namespace API that includes file operations. * @param {string} file - The name of the file to be managed. */ constructor(ns, file) { this.#ns = ns; this.#file = file; } /** * Creates a new file or clears an existing one. */ async newFile() { await this.#ns.write(this.#file, "", "w"); } /** * Appends or writes data to the file. * @param {any} data - The data to write into the file. * @param {string} mode - The writing mode, 'a' for append and 'w' for write (overwrite). */ async write(data, mode = "a") { const formattedData = JSON.stringify(data); await this.#ns.write(this.#file, formattedData, mode); } /** * Reads data from the file and parses it from JSON. * @returns {Promise<any>} A promise that resolves to the parsed data from the file. */ async read() { let dataString = await this.#ns.read(this.#file); return dataString.length > 0 ? JSON.parse(dataString) : []; } }

4. Data Scripts

home:~/v1/rooted-servers.js

import { FileSystem } from "/data/file-system.js"; /** * Retrieves and records the names of all servers with root access within a game environment. * The script first collects all servers accessible from a starting point and checks each for root access. * Servers with root access are sorted by their maximum RAM capacity in descending order, * and the list is saved to a specified file. * This script leverages a modular approach, using a custom `FileSystem` class for file operations. * * @param {NS} ns - The namespace object provided by the game, which includes * functions for interacting with the game's systems. * @async */ export async function main(ns) { // Instantiate the FileSystem class for file operations, targeting a specific file. const ROOTED_SERVERS = new FileSystem(ns, "/data/rooted-servers.txt"); // Retrieve a list of all servers accessible from the "home" server. const SERVERS = getAllServers(ns); let results = []; // Filter servers to find those with root access. for (let s of SERVERS) { if (ns.hasRootAccess(s)) results.push(s); } // Sort the servers with root access by their maximum RAM, in descending order. results.sort((a, b) => ns.getServerMaxRam(b) - ns.getServerMaxRam(a)); // Write the sorted list of servers to the targeted file. await ROOTED_SERVERS.write(results, "w"); /** * Discovers all servers connected to the starting server ("home"), using a depth-first search. * Unique servers are recorded to ensure each is processed only once. * @param {NS} ns - The namespace object for accessing game functions. * @returns {string[]} An array of unique server names. */ function getAllServers(ns) { let servers = []; let stack = ["home"]; while (stack.length > 0) { const CURRENT = stack.pop(); if (!servers.includes(CURRENT)) { servers.push(CURRENT); stack.push(...ns.scan(CURRENT).filter(next => !servers.includes(next))); } } return servers; } }

home:~/v1/hackable-targets.js

import { FileSystem } from "/data/file-system.js"; /** * Identifies servers that are hackable based on their security and economic attributes, * and records their names, sorted by potential profitability. This script first gathers all accessible servers, * excluding the starting point ("home"), and then checks each for hackability criteria: * root access, hacking level requirement, and the presence of money. It records the names of qualifying servers, * sorted by their maximum money capacity, to a file. * This script leverages a custom `FileSystem` class to handle file operations. * * @param {NS} ns - The namespace object provided by the game, which includes * functions for interacting with the game's systems. * @async */ export async function main(ns) { // Instantiate the FileSystem class for file operations, targeting a specific file for hackable targets. const HACKABLE_TARGETS = new FileSystem(ns, "/data/hackable-targets.txt"); // Retrieve a list of all servers accessible from the "home" server. const SERVERS = getAllServers(ns); let results = []; // Filter servers based on hackability criteria. for (let server of SERVERS) { if (server === "home") continue; let has_root = ns.hasRootAccess(server); let is_hackable = ns.getServerRequiredHackingLevel(server) < ns.getHackingLevel(); let has_money = ns.getServerMaxMoney(server) > 0; if (is_hackable && has_root && has_money) results.push(server); } // Sort the hackable servers by their maximum money capacity, in descending order. results.sort((a, b) => ns.getServerMaxMoney(b) - ns.getServerMaxMoney(a)); // Write the sorted list of hackable servers to the targeted file. await HACKABLE_TARGETS.write(results, "w"); /** * Discovers all servers connected to the starting server ("home"), using a depth-first search. * Unique servers are recorded to ensure each is processed only once. * @param {NS} ns - The namespace object for accessing game functions. * @returns {string[]} An array of unique server names. */ function getAllServers(ns) { let servers = []; let stack = ["home"]; while (stack.length > 0) { const CURRENT = stack.pop(); if (!servers.includes(CURRENT)) { servers.push(CURRENT); stack.push(...ns.scan(CURRENT).filter(next => !servers.includes(next))); } } return servers; } }

home:~/v1/best-target.js

import { FileSystem } from "/data/file-system.js"; /** * Evaluates a list of hackable servers and identifies the most profitable target * for hacking activities, based on a scoring system. The script reads a list of previously identified * hackable servers, assesses each based on its profitability and security level, and records * the best target into a file. The decision is based on the ratio of potential money gains to the * minimum security level of each server, while excluding servers that take too long to weaken. * This script uses a custom `FileSystem` class to facilitate file operations. * * @param {NS} ns - The namespace object provided by the game, which includes * functions for interacting with the game's systems. * @async */ export async function main(ns) { // Instantiate FileSystem classes for file operations, targeting specific files for hackable targets and the best target. const HACKABLE_TARGETS = new FileSystem(ns, "/data/hackable-targets.txt"); const BEST_TARGET = new FileSystem(ns, "/data/best-target.txt"); // Read the list of hackable targets from the file. const TARGETS = await HACKABLE_TARGETS.read(); // Define the maximum allowed time for weakening a server in minutes. const MAX_MINUTES = 30; let score = 0; let results = "n00dles"; // Default target if no other server qualifies. // Evaluate each target based on its weaken time and profitability-security ratio. for (let target of TARGETS) { let has_long_weaken_time = ns.getWeakenTime(target) > 1000 * 60 * MAX_MINUTES; if (has_long_weaken_time) continue; // Skip servers that take too long to weaken. // Calculate the score as the ratio of maximum potential money to minimum security level. let new_score = ns.getServerMaxMoney(target) / ns.getServerMinSecurityLevel(target); if (new_score > score) { score = new_score; // Update the best score found. results = target; // Update the best target found. } } // Write the name of the best target server to the file. await BEST_TARGET.write(results, "w"); }

5a. Hack-Weaken-Grow-Weaken Script

/** * Conducts optimized batch operations on servers to maximize hacking effectiveness in a simulated hacking environment. * The script reads from three files to obtain lists of rooted servers, hackable targets, and the best target. It * adjusts operations based on the game's progression, focusing on maximizing money from servers by adjusting security * levels and money available. Operations are batched with delays to ensure effective synchronization and avoid * operation collisions. The script dynamically adjusts thread allocations based on server capabilities and * operation needs, and continuously iterates through targets and servers to apply the most effective hacking strategy. * * @param {NS} ns - The namespace object provided by the game, which includes functions for interacting with the game's systems. * @async */

5b. Hack-Weaken-Grow-Weaken Script

home:~/v1/hwgw.js

import { FileSystem } from "/data/file-system.js"; export async function main(ns) { // Disable verbose logging for specific methods to clean up the output. const DISABLED_LOGS = [ 'sleep', 'getHackingLevel', 'getServerMaxMoney', 'getServerMinSecurityLevel', 'getServerSecurityLevel', 'getServerMoneyAvailable', 'getServerMaxRam', 'getServerUsedRam', ]; DISABLED_LOGS.forEach(log => ns.disableLog(log)); // Opens a tail window in the game to display log outputs. ns.tail(); // File system management for tracking servers and targets. const rooted_servers = new FileSystem(ns, "/data/rooted-servers.txt"); const hackable_targets = new FileSystem(ns, "/data/hackable-targets.txt"); const best_target = new FileSystem(ns, "/data/best-target.txt"); // Constants for script execution. const RAM_PER_THREAD = ns.getScriptRam("/shared/weaken.js"); // RAM requirement per thread. const RESERVED_HOME_RAM = 20; // Amount of RAM reserved on the 'home' server. const BATCH_THREAD_DELAY = 100; // Delay between batch operations in milliseconds. const CALCULATION_DELAY = 5; // Delay for recalculations to manage execution speed vs performance. const LOOP_DELAY = 1000 * 3; // Delay after completing an iteration over all targets and servers. const INITIAL_HACK_THREADS = 8; // Initial number of threads reserved for hacking operations. let batch_number = 1; // Identifier for each batch operation to ensure uniqueness. while (true) { // Read server and target data from files. const SERVERS = await rooted_servers.read(); const TARGETS = await hackable_targets.read(); const BEST_TARGET = await best_target.read(); // Determine if the game is in an early stage. let is_early_game = ns.getHackingLevel() < 750; for (let target of TARGETS) { if (is_early_game) target = BEST_TARGET; // Focus on the best target during early game stages. // Gather target's financial and security details. let max_money = ns.getServerMaxMoney(target); let min_security_level = ns.getServerMinSecurityLevel(target); let security_level = ns.getServerSecurityLevel(target); let money = Math.max(1, ns.getServerMoneyAvailable(target)); // Avoid division by zero. let has_growth_been_calculated = false; let required_grow_threads = 0; let batch_delay = 0; for (let server of SERVERS) { // Calculate the number of available threads for operations. let available_ram = ns.getServerMaxRam(server) - ns.getServerUsedRam(server) - (server === "home" ? RESERVED_HOME_RAM : 0); let available_threads = Math.floor(available_ram / RAM_PER_THREAD); if (available_threads < 1) continue; // Skip servers with no available threads. // Adjust operations based on server's security state and financial potential. let cores = (server === "home") ? ns.getServer("home").cpuCores : 1; // Multi-core support for home server. let security_decrease = ns.weakenAnalyze(1, cores); let hack_weaken_ratio = ns.hackAnalyzeSecurity(1, target) / security_decrease; let grow_weaken_ratio = ns.growthAnalyzeSecurity(1, target, cores) / cores; // Prioritize operations based on server state: weaken, grow, or hack. if (security_level > min_security_level) { // Security reduction operations. let reduced_security_level = security_decrease * available_threads; if (security_level - reduced_security_level < min_security_level) { available_threads = Math.ceil((security_level - min_security_level) / security_decrease); security_level = min_security_level; } else { security_level -= reduced_security_level; } ns.exec("/shared/weaken.js", server, available_threads, target, 0, batch_number++); } else if (money < max_money && (required_grow_threads != 0 || !has_growth_been_calculated)) { // Money maximization operations. if (!has_growth_been_calculated) { required_grow_threads = Math.ceil(ns.growthAnalyze(target, max_money / money, cores)); has_growth_been_calculated = true; } available_threads = Math.min(required_grow_threads, available_threads); required_grow_threads -= available_threads; security_level += ns.growthAnalyzeSecurity(available_threads, target, cores); ns.exec("/shared/grow.js", server, available_threads, target, 0, batch_number++); } else { if (available_threads < 4) continue; // Minimally need 4 threads to run a HWGW batch. // Hack-Weaken-Grow-Weaken batch operations. let hack_amount = ns.hackAnalyze(target); // Percentage of money per hack thread. if (hack_amount == 0) continue; let hack_threads = Math.ceil(available_threads / INITIAL_HACK_THREADS); let grow_threads, weaken_threads, weaken_threads_2, is_over_allocated = false; while (true) { // Optimal thread calculation loop. // Calculate the minimum number of threads to hack the server. if (hack_amount * hack_threads > 1) hack_threads = Math.ceil(1 / hack_amount); // Calculate grow and weaken threads required to account for hack threads. grow_threads = Math.ceil(ns.growthAnalyze(target, 1 / (1 - Math.min(0.99, hack_amount * hack_threads)), cores)); weaken_threads = Math.ceil(hack_weaken_ratio * hack_threads); weaken_threads_2 = Math.max(1, Math.ceil(grow_weaken_ratio * grow_threads)); // grow threads could be 0 so we set it to 1. // Calculate batch thread utilization. let thread_usage = (hack_threads + grow_threads + weaken_threads + weaken_threads_2) / available_threads; // Prioritize operations based on thread allocation state: over, under, good. if (thread_usage > 1) { // Over allocation. if (hack_threads > 1) { hack_threads--; // Adjust hack threads to manage over-allocation. is_over_allocated = true; } else break; // Recompute. } else if (Math.floor((1 - thread_usage) * hack_threads) > 1) { // Under allocation. let additional_threads = Math.floor((1 - thread_usage) * hack_threads / 2); // Checking if adding threads won't cause an over-hack. if (hack_amount * (hack_threads + additional_threads) <= 1) { hack_threads += additional_threads; // Adjust hack threads to manage under-allocation. } else break; // Recompute. if (is_over_allocated) break; // flag to prevent softlock from increasing and reducing by 1 thread. } else break; // Good allocation. await ns.sleep(CALCULATION_DELAY); } ns.exec("/shared/weaken.js", server, weaken_threads, target, batch_delay, batch_number); ns.exec("/shared/weaken.js", server, weaken_threads_2, target, batch_delay + BATCH_THREAD_DELAY * 2, batch_number); ns.exec("/shared/grow.js", server, grow_threads, target, batch_delay + BATCH_THREAD_DELAY + ns.getWeakenTime(target) - ns.getGrowTime(target), batch_number); ns.exec("/shared/hack.js", server, hack_threads, target, batch_delay - BATCH_THREAD_DELAY + ns.getWeakenTime(target) - ns.getHackTime(target), batch_number++); // Prevents intersection of HWGW batches. batch_delay += 4 * BATCH_THREAD_DELAY; } await ns.sleep(CALCULATION_DELAY); } await ns.sleep(CALCULATION_DELAY); } await ns.sleep(LOOP_DELAY); } }

6. Initialization And Start Script

home:~/init.js

/** * Executes a loop that periodically runs a set of scripts to manage various aspects of a game environment. * It repeatedly executes scripts related to deploying resources, analyzing server vulnerabilities, * identifying hackable targets, and determining the best targets for hacking. * The loop runs indefinitely, pausing for a specified interval between each iteration. * * @param {NS} ns - The namespace object provided by the game, which includes * functions for interacting with the game's systems. * @async */ export async function main(ns) { // Log settings: Currently, no logs are disabled, but this array can be populated with log identifiers // to suppress verbose output from specific game functions. const DISABLED_LOGS = []; DISABLED_LOGS.forEach(log => ns.disableLog(log)); // Opens a tail window in the game to display log outputs. ns.tail(); // LOOP_DELAY: Time in milliseconds to wait between script executions. // Set to 3000 milliseconds (3 seconds). const LOOP_DELAY = 1000 * 3; // Continuously loop to manage various scripting tasks. while (true) { // Run scripts to manage deployment, server vulnerabilities, hackable targets, and optimal targets. // Each script is launched with a single thread. ns.run("v1/deployer.js", 1); // Script to hack servers and deploying scripts. ns.run("v1/rooted-servers.js", 1); // Script to identify servers with root access. ns.run("v1/hackable-targets.js", 1); // Script to identify servers that can be hacked. ns.run("v1/best-target.js", 1); // Script to identify the best server for hacking. // Pause the loop for the specified delay, allowing time for scripts to execute before the next iteration. await ns.sleep(LOOP_DELAY); } }

home:~/start.js

/** @param {NS} ns **/ export async function main(ns) { ns.run("v1/hwgw.js", 1); }

7. How To Run

First we need to run init.js to generate our data files in the data folder.

run init.js

Then we need to run the HWGW script.

run start.js

8. Server Manager And Hacknet Manager Scripts

home:~/server-manager.js

/** * Manages the upgrade and acquisition of servers based on their RAM capacity in a game environment. * This script periodically checks all purchased servers, upgrading their RAM or purchasing new servers * if they do not meet a specified RAM requirement. The RAM requirement doubles each loop iteration, * starting from a base level. The script ensures that all operations are affordable before proceeding. * Verbose logging for certain operations is disabled to streamline the output. * * @param {NS} ns - The namespace object provided by the game, which includes * functions for interacting with the game's systems. * @async */ export async function main(ns) { // Disable verbose logging for specific methods to clean up the output. const DISABLED_LOGS = ['getServerMaxRam', 'getServerMoneyAvailable']; DISABLED_LOGS.forEach(log => ns.disableLog(log)); // Opens a tail window in the game to display log outputs. ns.tail(); // Set default delay times for looping and calculations. const LOOP_DELAY = ns.args[0] || 1000 * 3; // Default loop delay is 3 seconds. const CALCULATION_DELAY = 5; // Delay after calculations or server actions. let ram = 8; // Initial RAM threshold for server actions. let servers = ns.getPurchasedServers(); // Get a list of currently owned servers. // Continuously evaluate and manage servers. while (true) { ns.printf("Checking for servers with %s RAM.", ns.formatRam(ram)); for (let i = 0; i < ns.getPurchasedServerLimit(); i++) { let server = "server-" + i; if (servers.includes(server)) { // If server exists, check if it needs an upgrade. if (ns.getServerMaxRam(server) < ram) { let cost = ns.getPurchasedServerUpgradeCost(server, ram); // Wait for sufficient funds for the upgrade. while (ns.getServerMoneyAvailable("home") < cost) { ns.printf("%s needs %s to upgrade to %s.", server, ns.formatNumber(cost), ns.formatRam(ram)); await ns.sleep(LOOP_DELAY); } // Upgrade the server when funds are sufficient. if (ns.upgradePurchasedServer(server, ram)) { ns.printf("%s upgraded to %s", server, ns.formatRam(ram)); servers = ns.getPurchasedServers(); // Refresh the server list. } } } else { // If server does not exist, check cost and attempt to purchase. let cost = ns.getPurchasedServerCost(ram); while (ns.getServerMoneyAvailable("home") < cost) { ns.printf("Need %s to purchase %s with %s", ns.formatNumber(cost), server, ns.formatRam(ram)); await ns.sleep(LOOP_DELAY); } if (ns.purchaseServer(server, ram)) { ns.printf("Purchased %s with %s", server, ns.formatRam(ram)); servers = ns.getPurchasedServers(); // Refresh the server list. } } } // Double the RAM requirement for the next loop iteration. ram *= 2; // Pause the script briefly after handling all servers. await ns.sleep(CALCULATION_DELAY); } }

home:~hacknet-manager.js

/** * This function automates the management of hacknet nodes in a game, * where nodes can be purchased or upgraded to enhance their performance. * It runs indefinitely, checking if enough funds are available to perform upgrades * or purchase new nodes, and executing these actions when possible. * * @param {object} ns - The namespace object provided by the game, which includes * functions for interacting with the game's systems. * @async */ export async function main(ns) { // Log settings: Disable verbose logging for the specified function. const DISABLED_LOGS = ['getServerMoneyAvailable']; DISABLED_LOGS.forEach(log => ns.disableLog(log)); // Opens a tail window in the game to display log outputs. ns.tail(); // LOOP_DELAY: Time in milliseconds to wait when funds are insufficient for upgrades. // Default value is 3000 milliseconds (3 seconds). const LOOP_DELAY = ns.args[0] || 1000 * 3; // THRESHOLD: Multiplier to determine the minimum funds needed relative to the cost of the next upgrade. // Default value is 1000, i.e., funds must be at least 1000 times the upgrade cost. const THRESHOLD = ns.args[1] || 1000; // CALCULATION_DELAY: Time in milliseconds to delay after executing an upgrade, // intended to manage load on system resources. Default value is 5 milliseconds. const CALCULATION_DELAY = 5; // Continuously loop to manage node upgrades or purchases. while (true) { let owned_nodes = ns.hacknet.numNodes(); // Get the current number of owned nodes. let min_cost = ns.hacknet.getPurchaseNodeCost(); // Cost of purchasing a new node. let node_index = owned_nodes; // Index for node to upgrade, initialized to the next new node. let upgrade_type = -1; // Type of upgrade to perform: -1 for purchase, 0 for level, 1 for RAM, 2 for core. // Evaluate the cost and type of the cheapest possible upgrade among existing nodes. for (let i = 0; i < owned_nodes; i++) { let upgrades = [ ns.hacknet.getLevelUpgradeCost(i, 1), ns.hacknet.getRamUpgradeCost(i, 1), ns.hacknet.getCoreUpgradeCost(i, 1) ]; let new_cost = Math.min.apply(Math, upgrades); if (new_cost < min_cost) { min_cost = new_cost; node_index = i; upgrade_type = upgrades.indexOf(new_cost); } } // Wait until there are sufficient funds for the selected upgrade. while (ns.getServerMoneyAvailable("home") < min_cost * THRESHOLD) { ns.printf("Node %d needs %s * %d for next upgrade.", node_index, ns.formatNumber(min_cost), THRESHOLD); await ns.sleep(LOOP_DELAY); } // Execute the selected upgrade or node purchase. switch (upgrade_type) { case -1: ns.hacknet.purchaseNode(); ns.printf("Purchased a new hacknet node."); break; case 0: ns.hacknet.upgradeLevel(node_index, 1); ns.printf("Upgraded node %d's level.", node_index); break; case 1: ns.hacknet.upgradeRam(node_index, 1); ns.printf("Upgraded node %d's ram.", node_index); break; case 2: ns.hacknet.upgradeCore(node_index, 1); ns.printf("Upgraded node %d's cores.", node_index); break; } // Delay after upgrade to manage system performance. await ns.sleep(CALCULATION_DELAY); } }

9a. Misc Scripts

home:~/misc/get-server-stats.js

/** * Monitors and displays detailed financial and security information about servers in a simulated hacking environment. * The script lists each server that is hackable and profitable based on the player's current hacking level and the server's * financial attributes. It continuously updates and prints this information at a specified interval, highlighting the money * available, security levels, and estimated times for hacking-related actions. Logging for specific operations is disabled to * reduce clutter. * * @param {NS} ns - The namespace object provided by the game, which includes functions for interacting with the game's systems. * @async */ export async function main(ns) { // Disable verbose logging for specific operations to make the output cleaner. const DISABLED_LOGS = [ 'scan', 'getServerMoneyAvailable', 'getServerMaxMoney', 'getServerRequiredHackingLevel', 'getServerSecurityLevel', 'getServerMinSecurityLevel', 'getHackingLevel' ]; DISABLED_LOGS.forEach(log => ns.disableLog(log)); // Opens a tail window in the game to display log outputs. ns.tail(); // Determine the list of servers to monitor: either all reachable servers or a specific server passed as an argument. let servers = (ns.args[0] == null) ? getAllServers(ns) : [ns.args[0]]; // Sort servers by their maximum potential money in descending order. servers.sort((a, b) => ns.getServerMaxMoney(b) - ns.getServerMaxMoney(a)); for (let server of servers) { if (server === "home") continue; // Skip the "home" server. // Gather financial and security details of each server. const MONEY = ns.getServerMoneyAvailable(server); const MAX_MONEY = Math.max(1, ns.getServerMaxMoney(server)); const MONEY_PERCENT = ns.formatPercent(MONEY / MAX_MONEY); const HACK_LEVEL = ns.getServerRequiredHackingLevel(server); const SECURITY_LEVEL = ns.getServerSecurityLevel(server); const MIN_SECURITY_LEVEL = ns.getServerMinSecurityLevel(server); const WEAKEN_TIME = formatTime(ns.getWeakenTime(server)); const GROW_TIME = formatTime(ns.getGrowTime(server)); const HACK_TIME = formatTime(ns.getHackTime(server)); let is_hackable = HACK_LEVEL < ns.getHackingLevel(); let has_money = MAX_MONEY > 1; if (is_hackable && has_money) { // Print detailed server information if it's hackable and profitable. ns.tprintf("| %18s | $ %8s / %8s | %7s | HL:%4d | SL:%3d / %2d | WT:%2dh %2dm %2ds | GT:%2dh %2dm %2ds | HT:%2dh %2dm %2ds |", server, ns.formatNumber(MONEY), ns.formatNumber(MAX_MONEY), MONEY_PERCENT, HACK_LEVEL, SECURITY_LEVEL, MIN_SECURITY_LEVEL, ...WEAKEN_TIME, ...GROW_TIME, ...HACK_TIME); } } // Helper function to retrieve all reachable servers from "home". function getAllServers(ns) { let servers = []; let stack = ["home"]; while (stack.length > 0) { const CURRENT = stack.pop(); if (!servers.includes(CURRENT)) { servers.push(CURRENT); stack.push(...ns.scan(CURRENT).filter(next => !servers.includes(next))); } } return servers; } // Helper function to format milliseconds into hours, minutes, and seconds for readability. function formatTime(milliseconds) { const SECONDS = Math.floor((milliseconds / 1000) % 60); const MINUTES = Math.floor(((milliseconds / 1000) / 60) % 60); const HOURS = Math.floor(((milliseconds / 1000) / 3600)); return [HOURS, MINUTES, SECONDS]; } }

9b. Misc Scripts

home:~/misc/ram.js

/** * Monitors and displays the RAM usage details for specified servers, including the "home" server * and any purchased servers. The script outputs the maximum RAM, used RAM, and available RAM for each server, * refreshing the data at a specified interval. Verbose logging for RAM-related methods is disabled * to keep the output clear and focused. * * @param {NS} ns - The namespace object provided by the game, which includes functions for interacting with the game's systems. * @async */ export async function main(ns) { // Disable verbose logging for RAM-related operations to streamline output. const DISABLED_LOGS = ['getServerMaxRam', 'getServerUsedRam']; DISABLED_LOGS.forEach(log => ns.disableLog(log)); // Opens a tail window in the game to display log outputs. ns.tail(); // Set the interval between updates to 3 seconds. const SLEEP_DELAY = 1000 * 3; // Include the "home" server and any purchased servers in the list to monitor. const SERVERS = ["home"].concat(ns.getPurchasedServers()); // Continuously loop to monitor and display RAM usage for each server. while (true) { for (let server of SERVERS) { // Calculate and fetch RAM details for each server. let max_ram = ns.getServerMaxRam(server); let used_ram = ns.getServerUsedRam(server); let avail_ram = max_ram - used_ram; // Output the RAM usage details in a formatted manner. ns.printf("| %9s | Used: %8s / %8s | Free: %8s |", server, ns.formatRam(used_ram), ns.formatRam(max_ram), ns.formatRam(avail_ram)); } // Wait for the specified delay before the next update. await ns.sleep(SLEEP_DELAY); } }

10. Aliases

alias init="run init.js" alias start="run start.js" alias server="run server-manager.js" alias hacknet="run hacknet-manager.js" alias get="run misc/get-server-stats.js" alias poll="run misc/poll-server-stats.js" alias ram="run misc/ram.js"

Source: https://steamcommunity.com/sharedfiles/filedetails/?id=3241603650					

More Bitburner guilds