Last active
January 1, 2024 07:57
-
-
Save NiciusB/f5c8b6be0a5dc0d4f03a981410f962d7 to your computer and use it in GitHub Desktop.
automated hack for early bitburner
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
/** @type {NS} ns **/ | |
export function getAllServers(ns, rootHost = 'home') { | |
ns.disableLog('scan') | |
let pendingScan = [rootHost] | |
const list = new Set(pendingScan) | |
while (pendingScan.length) { | |
const hostname = pendingScan.shift() | |
list.add(hostname) | |
pendingScan.push(...ns.scan(hostname)) | |
pendingScan = pendingScan.filter(host => !list.has(host)) | |
} | |
return [...list] | |
} |
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 { getAllServers } from "get-servers.js" | |
/** @type {NS} ns **/ | |
let ns | |
const projectedTargetsDatas = {} | |
export async function main(_ns) { | |
ns = _ns | |
ns.disableLog('ALL') | |
while (true) { | |
await hackRootedServers() | |
await ns.sleep(1000) | |
} | |
} | |
async function hackRootedServers() { | |
const allServers = getAllServers(ns) | |
.filter(host => host !== 'home') | |
const serversRootAccessIndexed = await Promise.all(allServers.map(host => tryToGetRootAccess(host))) | |
const possibleTargetServers = allServers | |
.filter((host, index) => { | |
return serversRootAccessIndexed[index] && | |
ns.getServerMaxMoney(host) !== 0 && | |
ns.getServerRequiredHackingLevel(host) <= ns.getHackingLevel() | |
}) | |
// Hack from all servers | |
for (const remoteHost of allServers) { | |
if (ns.getServerMaxRam(remoteHost) === 0) { | |
continue | |
} | |
const targetData = await findBestServerToHackFromPossibleTargetList(possibleTargetServers) | |
if (targetData) { | |
await runLoopForServer(remoteHost, targetData) | |
await ns.sleep(20) | |
} | |
} | |
} | |
async function findBestServerToHackFromPossibleTargetList(possibleTargetServers) { | |
possibleTargetServers = JSON.parse(JSON.stringify(possibleTargetServers)) | |
while (possibleTargetServers.length > 0) { | |
const targetHost = findBestServerToHack(possibleTargetServers) | |
possibleTargetServers.splice(possibleTargetServers.indexOf(targetHost), 1) | |
projectedTargetsDatas[targetHost] = projectedTargetsDatas[targetHost] ?? { | |
securityLevel: ns.getServerSecurityLevel(targetHost), | |
moneyAvailable: ns.getServerMoneyAvailable(targetHost), | |
} | |
const targetData = { | |
host: targetHost, | |
minSecurityLevel: ns.getServerMinSecurityLevel(targetHost), | |
maxMoney: ns.getServerMaxMoney(targetHost), | |
projected: projectedTargetsDatas[targetHost], | |
actual: { | |
securityLevel: ns.getServerSecurityLevel(targetHost), | |
moneyAvailable: ns.getServerMoneyAvailable(targetHost), | |
} | |
} | |
if ( | |
!( | |
targetData.projected.moneyAvailable / targetData.maxMoney > 0.95 && | |
targetData.actual.moneyAvailable / targetData.maxMoney < 0.5 | |
) | |
) { | |
return targetData | |
} | |
} | |
} | |
async function tryToGetRootAccess(host) { | |
let openPorts = 0 | |
if (ns.fileExists('ftpcrack.exe')) { | |
openPorts++ | |
ns.ftpcrack(host) | |
} | |
if (ns.fileExists('brutessh.exe')) { | |
openPorts++ | |
ns.brutessh(host) | |
} | |
if (ns.fileExists('httpworm.exe')) { | |
openPorts++ | |
ns.httpworm(host) | |
} | |
if (ns.fileExists('relaysmtp.exe')) { | |
openPorts++ | |
ns.relaysmtp(host) | |
} | |
if (ns.fileExists('sqlinject.exe')) { | |
openPorts++ | |
ns.sqlinject(host) | |
} | |
if (ns.getServerNumPortsRequired(host) > openPorts) { | |
return false | |
} | |
ns.nuke(host) | |
if (host === 'CSEC') { | |
// This does not seem to be automatable for now? | |
// await ns.installBackdoor(host) | |
} | |
return true | |
} | |
async function runLoopForServer(remoteHost, targetData) { | |
const cores = 1 // TODO: look into this | |
let waitMs | |
let threads | |
// Weaken | |
const weakenPerThread = ns.weakenAnalyze(1, cores) | |
const maxWeakenThreads = Math.floor((targetData.projected.securityLevel - targetData.minSecurityLevel) / weakenPerThread) | |
if (maxWeakenThreads > 0) { | |
({ waitMs, threads } = await weaken(remoteHost, targetData.host, maxWeakenThreads)) | |
if (threads) { | |
targetData.projected.securityLevel -= ns.weakenAnalyze(threads, cores) | |
targetData.projected.securityLevel = Math.max(targetData.projected.securityLevel, targetData.minSecurityLevel) | |
ns.print([ | |
'Weakening'.padEnd(9), | |
remoteHost.padEnd(15), | |
targetData.host.padEnd(15), | |
`${Math.ceil(waitMs / 1000)}s`, | |
`${threads} threads`, | |
`${Math.round((targetData.projected.securityLevel - targetData.minSecurityLevel) * 100) / 100} lvls left` | |
].join(' | ')) | |
} | |
return | |
} | |
// Growth | |
const maxGrowthThreads = ns.growthAnalyze(targetData.host, targetData.maxMoney / targetData.projected.moneyAvailable, cores) | |
if (maxGrowthThreads >= 1) { | |
({ waitMs, threads } = await grow(remoteHost, targetData.host, Math.floor(maxGrowthThreads))) | |
if (threads) { | |
targetData.projected.securityLevel += ns.growthAnalyzeSecurity(threads) | |
targetData.projected.moneyAvailable += threads / maxGrowthThreads * targetData.maxMoney | |
targetData.projected.moneyAvailable = Math.min(targetData.projected.moneyAvailable, targetData.maxMoney) | |
ns.print([ | |
'Growing'.padEnd(9), | |
remoteHost.padEnd(15), | |
targetData.host.padEnd(15), | |
`${Math.ceil(waitMs / 1000)}s`, | |
`${threads} threads`, | |
`${Math.round(targetData.projected.moneyAvailable / targetData.maxMoney * 1000) / 10}% money` | |
].join(' | ')) | |
} | |
return | |
} | |
// Hack | |
const hackProbability = ns.hackAnalyzeChance(targetData.host) | |
let maxHackThreads = 0 | |
let calcMoney = targetData.projected.moneyAvailable | |
while (calcMoney > targetData.maxMoney * 0.5) { | |
calcMoney -= calcMoney * ns.hackAnalyze(targetData.host) * hackProbability | |
maxHackThreads++ | |
} | |
maxHackThreads-- | |
if (maxHackThreads > 0) { | |
({ waitMs, threads } = await hack(remoteHost, targetData.host, maxHackThreads)) | |
if (threads) { | |
const moneyWon = targetData.projected.moneyAvailable * ns.hackAnalyze(targetData.host) * threads * hackProbability | |
targetData.projected.moneyAvailable -= moneyWon | |
targetData.projected.securityLevel += ns.hackAnalyzeSecurity(threads) * hackProbability | |
ns.print([ | |
'Hacking'.padEnd(9), | |
remoteHost.padEnd(15), | |
targetData.host.padEnd(15), | |
`${Math.ceil(waitMs / 1000)}s`, | |
`${threads} threads`, | |
`${Math.round(moneyWon / 1e6 * 100) / 100}M` | |
].join(' | ')) | |
} | |
} | |
} | |
function findBestServerToHack(servers) { | |
return servers | |
.map(host => { | |
const weights = { | |
maxMoney: 1.7, | |
growthRate: 0.9, | |
growTime: 0.8, | |
minSecurityLevel: 1, | |
} | |
const score = | |
Math.pow(ns.getServerMaxMoney(host) / 1e5, weights.maxMoney) * | |
Math.pow(ns.getServerGrowth(host), weights.growthRate) / | |
Math.pow(ns.getGrowTime(host), weights.growTime) / | |
Math.pow(ns.getServerMinSecurityLevel(host), weights.minSecurityLevel) | |
return { host, score: Math.round(score * 100) / 100 } | |
}) | |
.sort((a, b) => b.score - a.score) | |
.map(x => { | |
//ns.print(`${x.host}: ${x.score}`) | |
return x | |
})[0].host | |
} | |
async function hack(remoteHost, targetHost, maxThreadsAllowed) { | |
const result = await execRemote(remoteHost, 'just-hack.js', maxThreadsAllowed, targetHost) | |
return { | |
waitMs: result.threads ? ns.getHackTime(targetHost) : null, | |
threads: result.threads, | |
} | |
} | |
async function grow(remoteHost, targetHost, maxThreadsAllowed) { | |
const result = await execRemote(remoteHost, 'just-grow.js', maxThreadsAllowed, targetHost) | |
return { | |
waitMs: result.threads ? ns.getGrowTime(targetHost) : null, | |
threads: result.threads, | |
} | |
} | |
async function weaken(remoteHost, targetHost, maxThreadsAllowed) { | |
const result = await execRemote(remoteHost, 'just-weaken.js', maxThreadsAllowed, targetHost) | |
return { | |
waitMs: result.threads ? ns.getWeakenTime(targetHost) : null, | |
threads: result.threads, | |
} | |
} | |
async function execRemote(remoteHost, script, maxThreadsAllowed, ...args) { | |
if (!ns.isRunning(script, remoteHost)) { | |
await ns.scp(script, 'home', remoteHost) | |
} | |
const ramNeeded = ns.getScriptRam(script) | |
const serverFreeRam = ns.getServerMaxRam(remoteHost) - ns.getServerUsedRam(remoteHost) | |
let threads = Math.min(maxThreadsAllowed, Math.floor(serverFreeRam / ramNeeded)) | |
if (threads > 0) { | |
const didSucceed = ns.exec(script, remoteHost, threads, ...args, 'rand-' + Math.random().toString().slice(2)) | |
if (didSucceed === 0) { | |
threads = 0 | |
} | |
} | |
return { threads } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Looks good - would suggest for completion's sake you post just-grow, just-hack, and just-weaken, even though I assume they're the basic ones.