Skip to content

Instantly share code, notes, and snippets.

@heathkit
Created May 19, 2022 17:52
Show Gist options
  • Save heathkit/117a960ac5c88fa6fbc1d9105d1349d5 to your computer and use it in GitHub Desktop.
Save heathkit/117a960ac5c88fa6fbc1d9105d1349d5 to your computer and use it in GitHub Desktop.
// optimal_hack.js
/**
* TODO
* - split jobs to fit in available machines
* - 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);
await ns.sleep(5000);
}
}
/**
* 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 + 1000)
}
/**
* @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 SCRIPT = 'hgw.js';
/**
* Search for a node to run the given job on
*
* TODO: Split job to fit into available memory
*
* @param {NS} ns
* @param {threads} number
* @param {target} string
* @param {mode} string
* @param {delay} number
*/
async function runJob(ns, threads, target, mode, delay) {
let ramCost = ns.getScriptRam(SCRIPT);
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)/ramCost;
if (maxThreads > threads) {
runHost = host;
break;
}
}
if (!runHost) {
throw new Error(`Unable to find host to run job with ${threads} threads`);
}
await ns.scp(SCRIPT, runHost);
await ns.exec(SCRIPT, runHost, threads, target, mode, delay);
}
// hgw.js
/** @param {NS} ns */
export async function main(ns) {
let host = ns.args[0];
let mode = ns.args[1];
if (!host || !mode) {
ns.toast('Must specify host and mode!');
}
let delay = ns.args[2];
if(delay) {
await ns.sleep(delay);
}
switch(mode) {
case 'weaken':
await ns.weaken(host);
break;
case 'grow':
await ns.grow(host);
break;
case 'hack':
await ns.hack(host);
break;
default:
ns.toast('Unknown mode ${mode}');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment