Skip to content

Instantly share code, notes, and snippets.

@heathkit
Created May 19, 2022 02:16
Show Gist options
  • Save heathkit/c9d7cab0804e39c8384ccef9ab67cff1 to your computer and use it in GitHub Desktop.
Save heathkit/c9d7cab0804e39c8384ccef9ab67cff1 to your computer and use it in GitHub Desktop.
/**
* TODO
* - job chunking
* - determine ideal growth factor based on resource?
* - determine hack amount based on resources (or as parameter)
*/
/** @param {NS} ns */
export async function main(ns) {
let target = ns.args[0]
ns.disableLog('ALL')
ns.enableLog('exec')
ns.tail()
let server = ns.getServer(target);
ns.print(`Target: ${server.hostname}, Difficulty: ${server.hackDifficulty}`)
ns.print(`=== WEAKEN PHASE ===`)
let delta = server.hackDifficulty - server.minDifficulty
if (delta > 1) {
await weakenServerToMin(ns, server)
}
// Grow the server to max
ns.print(`=== GROW PHASE ===`)
await growToMax(ns, target, 4)
// Exploit the server
ns.print(`=== EXPLOIT PHASE ===`)
await exploit(ns, target, 0.5)
}
/**
* Optimally exploit the target server.
*
* @param {NS} ns
* @param {string} target
* @param {number} hackPerc
*/
async function exploit(ns, target, hackPerc) {
while(true) {
let server = ns.getServer(target)
ns.print(`## Starting Hack Loop ##`)
ns.print(`Money: ${server.moneyAvailable}`)
ns.print(`Difficulty: ${server.hackDifficulty}`)
await exploitLoop(ns, target, hackPerc);
}
}
/**
* Runs the inner loop for the exploit algorithm
*
* @param {NS} ns
* @param {string} target
* @param {number} hackPerc
*/
async function exploitLoop(ns, target, hackPerc) {
let server = ns.getServer(target)
let hackThreads = hackPerc/ns.hackAnalyze(target);
let weakenFactor = ns.weakenAnalyze(1,1);
let weakenBaseThreads = (server.hackDifficulty - server.minDifficulty)/weakenFactor
let weakenTime = ns.getWeakenTime(target);
let growTime = ns.getGrowTime(target);
let hackTime = ns.getHackTime(target);
let weakenHackThreads = Math.ceil(ns.hackAnalyzeSecurity(hackThreads, target)/weakenFactor + 1);
let growThreads = Math.ceil(ns.growthAnalyze(target, 1/(1-hackPerc)));
ns.print(`Growth threads: ${growThreads}`)
ns.print(`Growth inc: ${ns.growthAnalyzeSecurity(growThreads, target, 1)}`)
let weakenGrowThreads = weakenBaseThreads + Math.ceil(ns.growthAnalyzeSecurity(growThreads, target, 1)/weakenFactor) + 1;
// Finish the hack just before the first weaken
let hackDelay = weakenTime - hackTime - 500;
// Finish the grow just after the first weaken
let growDelay = (weakenTime + 1000) - growTime - 500;
ns.print(`Finish hack: ${hackDelay + hackTime}`);
ns.print(`Finish weaken1: ${weakenTime}`);
ns.print(`Finish grow: ${growDelay + growTime}`);
ns.print(`Finish weaken2: ${weakenTime + 1000}`);
await runJob(ns, weakenHackThreads, target, "weaken", 0);
await runJob(ns, weakenGrowThreads, target, "weaken", 1000);
await runJob(ns, growThreads, target, "grow", growDelay);
await runJob(ns, hackThreads, target, "hack", hackDelay);
await ns.sleep(weakenTime + 2)
}
/**
* @param {NS} ns
* @param {string} target
* @param {number} factor
*/
async function growToMax(ns, target, factor) {
ns.print(`current: ${ns.getServerMoneyAvailable(target)} max: ${ns.getServerMaxMoney(target)}`)
while (ns.getServerMoneyAvailable(target) < ns.getServerMaxMoney(target)) {
let delta = ns.getServerMaxMoney(target) - ns.getServerMoneyAvailable(target)
ns.print(`Delta: ${delta}`)
let growThreads = Math.ceil(ns.growthAnalyze(target, factor))
let weakenFactor = ns.weakenAnalyze(1,1);
let weakenThreads = ns.growthAnalyzeSecurity(growThreads,target, 1)/weakenFactor
ns.print(`Threads to double: ${growThreads}`)
ns.print(`Time to double: ${ns.getGrowTime(target)/1000/60}`)
ns.print(`Threads to weaken: ${weakenThreads}`)
ns.print(`Time to weaken: ${ns.getWeakenTime(target)/1000/60}`)
// start a grow and a weaken in parallel
let weakenTime = ns.getWeakenTime(target)
let minutes = (weakenTime/1000/60).toFixed(2);
await runJob(ns, weakenThreads, target, "weaken", 0)
await runJob(ns, growThreads, target, "grow", 0)
ns.print(`Will finish in ${minutes} minutes`)
await ns.sleep(weakenTime)
}
}
/**
* @param {NS} ns
* @param {Server} server
*/
async function weakenServerToMin(ns, server) {
// Weaken server to minimum
let delta = server.hackDifficulty - server.minDifficulty;
let weakenFactor = ns.weakenAnalyze(1,1);
let weakenThreads = Math.ceil(delta / weakenFactor);
ns.print(`Weaking server. threads:${weakenThreads} delta:${delta} factor:${weakenFactor}`);
await runJob(ns, weakenThreads, server.hostname, "weaken", 0);
let weakenTime = ns.getWeakenTime(server.hostname);
let minutes = (weakenTime/1000/60).toFixed(2);
ns.print(`Will finish in ${minutes} minutes`);
await ns.sleep(weakenTime);
}
// Assume the 2G HGW script
const RAM_COST = 2;
/**
* Search for a node to run the given job on
* @param {NS} ns
* @param {threads} number
* @param {target} string
* @param {mode} string
* @param {delay} number
*/
async function runJob(ns, threads, target, mode, delay) {
let remoteServers = JSON.parse(ns.read('servers.txt'));
// Add any current pservs
let pservs = ns.scan('home').filter(s => s.includes('pserv'));
let servers = ['home'].concat(pservs)
let runHost;
for (let host of servers) {
let server = ns.getServer(host);
if (!server.hasAdminRights) continue;
let maxThreads = (server.maxRam - server.ramUsed)/RAM_COST;
if (maxThreads > threads) {
runHost = host;
break;
}
}
if (!runHost) {
throw new Error(`Unable to find host to run job with ${threads} threads`);
}
await ns.scp('hgw.js', runHost);
await ns.exec('hgw.js', runHost, threads, target, mode, delay);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment