Last active
May 9, 2018 04:36
-
-
Save jaguilar/99808272740f64cdd50cb5bc11e1d383 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {getHosts, getAllHosts, schedule} from "hack-dist.js"; | |
const target = args[0]; | |
const numBatchWeaken = 9; | |
const numBatchGrow = 9; | |
const numBatchHack = 3; | |
export const allowedRam = 1000; | |
function killAllMatching(...args) { | |
getAllHosts().forEach(h => { | |
kill(args[0], h.address, ...args.slice(1, args.length)); | |
}); | |
} | |
async function reset() { | |
killAllMatching("weaken.js", target, "initial"); | |
killAllMatching("weaken.js", target, "secondary"); | |
killAllMatching("grow.js", target, "initial"); | |
for (let i = 0; i < 9; ++i) { | |
killAllMatching("weaken.js", target, i); | |
killAllMatching("grow.js", target, i); | |
killAllMatching("hack.js", target, i); | |
} | |
await sleep(12000); | |
} | |
function maxThreads(script, ram) { | |
return Math.floor(ram / getScriptRam(script, "home")); | |
} | |
function numWeaks(numHacks, numGrows) { | |
return (numHacks * 0.002 * 4 + numGrows * 0.004 * 2) / 0.05; | |
} | |
function scaleToAllowed(counts) { | |
// Figure out how much RAM we're going to use on each thing. | |
let hackR = counts.hackT * getScriptRam("hack.js", "home"); | |
let growR = counts.growT * getScriptRam("grow.js", "home"); | |
let weakR = counts.weakT * getScriptRam("weaken.js", "home"); | |
// Scale to the amount of ram available. | |
const scale = allowedRam / (hackR + growR + weakR); | |
hackR *= scale; | |
growR *= scale; | |
weakR *= scale; | |
counts.hackT = Math.floor(hackR / getScriptRam("hack.js", "home")); | |
counts.growT = Math.ceil(growR / getScriptRam("grow.js", "home")); | |
counts.weakT = Math.ceil(weakR / getScriptRam("weaken.js", "home")); | |
} | |
// Lowers security to the minimum. | |
async function lowerSecurity() { | |
let counts = { | |
hackT: 0, | |
growT: 0, | |
weakT: 1 | |
}; | |
scaleToAllowed(counts); | |
tprint(JSON.stringify(counts)); | |
// Reduce security using the maximum number of threads. | |
await schedule(getHosts(), { | |
script: "weaken.js", | |
threads: counts.weakT, | |
args: [target, "initial"] | |
}); | |
while (getServerSecurityLevel(target) > 1 + getServerMinSecurityLevel(target)) { | |
await sleep(2000); | |
} | |
} | |
// Grows money to the maximum, while maintaining a low security level. | |
async function growMoney() { | |
let counts = { | |
hackT: 0, | |
growT: 1, | |
weakT: numWeaks(0, 1) | |
}; | |
scaleToAllowed(counts); | |
tprint(JSON.stringify(counts)); | |
await schedule(getHosts(), { | |
script: "weaken.js", | |
threads: Math.max(1, counts.weakT), | |
args: [target, "secondary"] | |
}); | |
await schedule(getHosts(), { | |
script: "grow.js", | |
threads: counts.growT, | |
args: [target, "initial"] | |
}); | |
while (getServerMoneyAvailable(target) < 0.99 * getServerMaxMoney(target)) { | |
await sleep(2000); | |
} | |
} | |
async function hackForever(hackPerGrow) { | |
let counts = { | |
hackT: 1, | |
growT: 1 / hackPerGrow, | |
// hack cost 0.002 sec, runs ~4 times per weak. | |
// grow costs 0.004 sec, runs ~1.3 times per weak (round up). | |
// weaken weakens the security level by 0.05. | |
weakT: numWeaks(1, 1 / hackPerGrow) | |
}; | |
scaleToAllowed(counts); | |
tprint(JSON.stringify(counts)); | |
// Stagger start -- try to spread the grow, weaken, and hack operations across the timeframe. | |
const staggerWindow = getHackTime(target); | |
for (let i = 0; i < 9; ++i) { | |
const remainingPasses = 9 - i; | |
if (true) { | |
const t = Math.round(counts.weakT / remainingPasses); | |
await schedule(getHosts(), {script: "weaken.js", threads: t, args: [target, i]}); | |
counts.weakT -= t; | |
} | |
if (true) { | |
const t = Math.round(counts.growT / remainingPasses); | |
await schedule(getHosts(), {script: "grow.js", threads: t, args: [target, i]}); | |
counts.growT -= t; | |
} | |
// Since hack occurs with roughly triple the frequency, we schedule a third as many jobs. | |
if ((i % 3) === 0) { | |
const t = Math.round(counts.hackT / remainingPasses) | |
await schedule(getHosts(), {script: "hack.js", threads: t, args: [target, i]}); | |
counts.hackT -= t; | |
} | |
await sleep(staggerWindow * 1000 / 9); | |
} | |
} | |
class MoneyStats { | |
constructor() { | |
this.data = []; | |
} | |
observe() { | |
this.data.push(getServerMoneyAvailable(target) / getServerMaxMoney(target)); | |
while (this.data.length > 40) { | |
this.data.shift(); | |
} | |
} | |
average() { | |
const sum = this.data.reduce((acc, v) => acc + v); | |
return sum / this.data.length; | |
} | |
empty() { | |
return this.data.length === 0; | |
} | |
num_samples() { | |
return this.data.length; | |
} | |
} | |
export async function main() { | |
disableLog("getScriptRam"); | |
// Strategy: | |
// - Compute the number of threads of each type that are allowed, | |
// given a desired ratio of hacks to grows. | |
// - Scale the number of threads to the allowable amount of RAM. | |
// - Stagger-schedule the jobs. | |
// - Wait one cycle. | |
// - Measure the average server money available for one cycle. | |
// - If it's above the target, scale up the hack-to-grow ratio slightly. | |
// - Restart thse process. | |
// | |
// TODO: shut down if not present in file. | |
let targetRatio = 1/10; | |
while (true) { | |
reset(); | |
await lowerSecurity(); | |
reset(); | |
await growMoney(); | |
reset(); | |
await hackForever(targetRatio); | |
// Automatically adjust the ratio of hacks to grows. | |
const r = new MoneyStats(); | |
let samplingRate = 4; // Number of times we sample per loop. | |
for (let i = 0; i < 10 && (r.num_samples() < samplingRate || r.average() > 0.9); ++i) { | |
for (let s = 0; s < samplingRate; ++s) { | |
await sleep(getGrowTime(target) * 1000/samplingRate); | |
r.observe(); | |
} | |
} | |
// We're adjusting slowly, since we have a lot of time. | |
if (r.average() > 0.99) targetRatio += 0.01; | |
else if (r.average() < 0.9) targetRatio -= 0.01; | |
else continue; | |
tprint(target + ": new ratio=" + targetRatio); | |
targetRatio = Math.max(0.01, Math.min(0.99, targetRatio)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment