Skip to content

Commit f35a140

Browse files
committed
working, ship it
1 parent f488081 commit f35a140

2 files changed

Lines changed: 184 additions & 45 deletions

File tree

scripts/bitlib.js

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ export async function main(_ns) {
2020
let servers = getAllServerInfo( {}, ns )
2121
ns.tprint(JSON.stringify(servers))
2222

23-
ns.tprint("findTargets(servers, 5):")
24-
let targets = findTargets(servers, 5, playerInfo, ns)
23+
ns.tprint("findTargets:")
24+
let targets = findTargets(servers, playerInfo, ns).slice(5)
2525
for (const target of targets) {
2626
ns.tprint(target)
27-
tprintSeverAsTarget(target, ns)
27+
tprintServerAsTarget(target, ns)
2828
}
2929
}
3030

@@ -36,18 +36,55 @@ export async function getPlayerInfo(ns) {
3636
}
3737
}
3838

39-
export function printSeverAsTarget(server, _ns){
39+
export function pad(pad, str, padLeft) {
40+
if (typeof str === 'undefined')
41+
return pad;
42+
if (padLeft) {
43+
return (pad + str).slice(-pad.length);
44+
} else {
45+
return (str + pad).substring(0, pad.length);
46+
}
47+
}
48+
49+
export function tprintServerAsTarget(server, _ns) {
50+
ns = _ns
51+
const lines = printfSeverAsTarget(server, ns)
52+
for (const line of lines) {
53+
ns.tprint(line)
54+
}
55+
56+
}
57+
export function printfSeverAsTarget(server, _ns){
4058
ns = _ns
4159
// Try to keep it to two or three lines per server, or it will never fit in a log window, even with just a few targets
42-
const width = 35
4360
const moneyCur = ns.nFormat(server.currentMoney, "$0.0a")
44-
const moneyMax = ns.nFormat(server.maxMoney, "$0.0a")
45-
const moneyPercent = ns.nFormat(server.currentMoney / server.maxMoney, "0%")
46-
const secBase = ns.nFormat(server.securityBase, "0")
47-
const secIncr = ns.nFormat(server.securityCurrent - server.securityBase, "0.0")
61+
const moneyPercent = pad(' ', ns.nFormat(100*server.currentMoney / server.maxMoney, "0"), true)+'%'
62+
const moneyStr = `${moneyCur} (${moneyPercent})`
63+
64+
const secBase = pad(' ',ns.nFormat(server.securityBase, "0"), true)
65+
const secIncr = pad(' ', ns.nFormat(server.securityCurrent - server.securityBase, "0.0"))
66+
const secStr = `Sec ${secBase} +${secIncr}`
67+
68+
const hacksRunning = ns.nFormat(server.runningHackThreads || 0, "0")
69+
const hacksWanted = ns.nFormat(server.desiredHackThreads || 0, "0")
70+
const growsRunning = ns.nFormat(server.runningGrowThreads || 0, "0")
71+
const growsWanted = ns.nFormat(server.desiredGrowThreads || 0, "0")
72+
const weakensRunning = ns.nFormat(server.runningWeakenThreads || 0, "0")
73+
const weakensWanted = ns.nFormat(server.desiredWeakenThreads || 0, "0")
74+
75+
const hackStr = pad(Array(16).join('─'), `Hack ${hacksRunning}/${hacksWanted}├`)
76+
const growStr = pad(Array(17).join('─'), `┤Grow ${growsRunning}/${growsWanted}├`)
77+
const weakenStr = pad(Array(18).join('─'), `┤Weaken ${weakensRunning}/${weakensWanted}`, true)
78+
79+
let line1 = `╭─┤`
80+
line1 += pad(Array(17).join('─'), server.name + '├')
81+
line1 += pad(Array(17).join('─'), '┤ ' + moneyStr, true) + ' ├─'
82+
line1 += '┤' + secStr + `├─╮`
83+
84+
let line2 = `╰─┤${hackStr}${growStr}${weakenStr}├─╯`
85+
let line3 = ''
4886

49-
ns.print(`┌┤ ${server.name} [${moneyCur}/${moneyMax} (${moneyPercent})] SecLevel ${secBase}+${secIncr} ├───`)
50-
ns.print(`└─ Hack: [${server.runningHackThreads || 0}/${server.desiredHackThreads || 0}] Grow: [${server.runningGrowThreads || 0}/${server.desiredGrowThreads || 0}], Weaken: [${server.runningWeakenThreads || 0}/${server.desiredWeakenThreads || 0}] ───`)
87+
return [line1, line2, line3]
5188
}
5289

5390
export function getServerInfo(server, _ns) {
@@ -77,7 +114,7 @@ export function getServerInfo(server, _ns) {
77114

78115
}
79116

80-
export function findTargets(servers, num, playerInfo, _ns){
117+
export function findTargets(servers, playerInfo, _ns){
81118
ns = _ns
82119
let targets = []
83120
// Calculate a theoretical profitiablity score for each server
@@ -91,7 +128,7 @@ export function findTargets(servers, num, playerInfo, _ns){
91128
// sort the target array by score
92129
targets.sort((a,b) => a.score - b.score)
93130
targets.reverse()
94-
return targets.slice(0,num)
131+
return targets
95132
}
96133

97134
export function evaluateTarget(server, playerInfo, _ns) {

scripts/net-hack.js

Lines changed: 134 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,49 @@
11
/** @type import(".").NS */
22
let ns = null;
33

4-
import { getPlayerInfo, getAllServerInfo, getServerInfo, root, findTargets, printSeverAsTarget, evaluateTarget, worker_size, stopscript } from "/scripts/bitlib.js";
4+
import { getPlayerInfo, getAllServerInfo, getServerInfo, root, findTargets, printfSeverAsTarget, evaluateTarget, worker_size, stopscript } from "/scripts/bitlib.js";
55

66
const script_purchaseServers = "/scripts/purchaseServers.js";
77
const script_grow = "/scripts/growOnce.js";
88
const script_weaken = "/scripts/weakenOnce.js";
99
const script_hack = "/scripts/hackOnce.js";
10-
const num_targets = 5;
10+
const max_targets = 100;
1111

12-
async function runStart(numTargets, _ns) {
12+
// Globals so we can access them from other running instances of this porgram if we like.
13+
var targets
14+
var servers
15+
16+
export async function main(_ns) {
17+
ns = _ns;
18+
// Do something with arguments
19+
await runStart(ns);
20+
ns.tprint("Goodnight, Gracie!")
21+
}
22+
23+
async function runMonitor(_ns) {
1324
ns = _ns
25+
ns.tail()
26+
while(true){
27+
printFancyLog(ns)
28+
await ns.sleep(100)
29+
}
30+
}
1431

32+
async function runStop(_ns) {
33+
ns = _ns
34+
ns.kill(ns.getScriptName(), ns.getHostname(), "start")
35+
ns.kill(ns.getScriptName(), ns.getHostname(), "run")
36+
ns.kill(ns.getScriptName(), ns.getHostname(), "hack")
37+
ns.kill(ns.getScriptName(), ns.getHostname(), "monitor")
38+
ns.kill(ns.getScriptName(), ns.getHostname(), "status")
39+
ns.kill(ns.getScriptName(), ns.getHostname())
40+
}
41+
42+
async function runStart(_ns) {
43+
ns = _ns
44+
targets = []
45+
servers = {}
46+
ns.tail()
1547
ns.tprint('Starting hacking controller.')
1648

1749
ns.disableLog('getServerRequiredHackingLevel');
@@ -22,11 +54,13 @@ async function runStart(numTargets, _ns) {
2254
ns.disableLog('getServerMinSecurityLevel');
2355
ns.disableLog('getServerSecurityLevel');
2456
ns.disableLog('getHackingLevel');
57+
ns.disableLog('sleep');
2558

2659
validateScripts(ns);
2760

2861
let playerInfo = await getPlayerInfo(ns);
29-
let servers = await getAllServerInfo({}, ns);
62+
// let servers = await getAllServerInfo({}, ns);
63+
servers = await getAllServerInfo({}, ns);
3064
// Force a root check on available servers
3165
servers = await rootServers(servers, ns)
3266

@@ -40,69 +74,137 @@ async function runStart(numTargets, _ns) {
4074
}
4175
await ns.sleep(100);
4276

43-
// Get the best targets based on our evaluation function
44-
let targets = findTargets(servers, numTargets, playerInfo, ns)
77+
// Everyone loves a noodle shop. Let's start there.
78+
let firstTarget = getServerInfo('n00dles', ns)
79+
firstTarget = evaluateTarget(firstTarget, playerInfo, ns)
80+
targets.unshift(firstTarget)
4581

46-
// Everyone loves a noodle shop.
47-
let additionalTarget = getServerInfo('n00dles', ns)
48-
additionalTarget = evaluateTarget(additionalTarget, playerInfo, ns)
49-
targets.unshift(additionalTarget)
82+
// How many extra targets should we start with?
83+
let pool = getPoolFromServers(servers, ns)
84+
let additionalTargets = Math.floor(pool.free / 2000)
85+
additionalTargets = Math.min(additionalTargets, max_targets)
86+
if (pool.free > 5000 && additionalTargets) {
87+
addTargets(playerInfo, additionalTargets);
88+
}
5089

90+
91+
//Set up a few timers (approx 30sec, 1min, 10min)
92+
let on30 = 0, on60 = 0, on600 = 0
5193
while (true) {
94+
on30 = ++on30 % 30; on60 = ++on60 % 60; on600 = ++on600 % 600;
5295
// Root any available servers
5396
const oldExploitCount = playerInfo.exploits
5497
playerInfo = await getPlayerInfo(ns);
55-
if (oldExploitCount != playerInfo.exploits) {
56-
// It's only worth evaluating new targets to root when we get a new exploit.
98+
if (oldExploitCount != playerInfo.exploits || on60 == 0) {
99+
// We either have a new exploit, or it's been a little while.
100+
// Let's refresh our server info, and make sure there's nothing new to root.
57101
servers = await rootServers(servers, ns)
58102
}
59-
// ns.tprint(JSON.stringify(servers))
60103

61104
// re-evaluate our targets.
62105
for (let i = 0; i < targets.length; i++) {
63106
let target = targets[i]
64107
// Update server information
65108
target = { ...target, ...getServerInfo(target.name, ns) }
66-
// Re-evaluate targetting criteria
109+
// Re-evaluate targetting criteria, including desired attack threads
67110
target = await evaluateTarget(target, playerInfo, ns);
68111
targets[i] = target
69112
}
70113

71114
// Allocate any free server slots
72115
servers = await allocateThreads(servers, targets, ns)
116+
pool = getPoolFromServers(servers, ns)
73117

74-
// Display some status before we sleep
75-
ns.clearLog()
76-
for (const target of targets) {
77-
printSeverAsTarget(target, ns)
118+
// Occasionally consider adding a new target
119+
if (on30 == 0) {
120+
// If we have a bunch of free threads, go ahead and add new targets
121+
let additionalTargets = Math.floor(pool.free / 1000) + 1
122+
additionalTargets = Math.min(additionalTargets, max_targets - targets.length)
123+
if (pool.free > 1000 && additionalTargets) {
124+
addTargets(playerInfo, additionalTargets);
125+
}
78126
}
79127

128+
// Display some status before we sleep
129+
printFancyLog(ns)
130+
80131
// Sleep
81132
await ns.sleep(1 * 1000);
82133
} // End while(True)
83134
}
84135

85-
export async function main(_ns) {
86-
ns = _ns;
87-
const args = ns.args
88-
if (args.length > 1) {
89-
await runStart(args[0], ns)
90-
} else {
91-
await runStart(num_targets, ns);
136+
function addTargets(playerInfo, numTargets) {
137+
let potentialTargets = findTargets(servers, playerInfo, ns);
138+
let done = false;
139+
let x = potentialTargets.shift();
140+
while (!done && x) {
141+
let existing = targets.find(target => target.name == x.name);
142+
if (!existing) {
143+
targets.push(x);
144+
done = targets.length >= numTargets + 1;
145+
}
146+
x = potentialTargets.shift();
92147
}
148+
}
149+
150+
function printFancyLog(_ns) {
151+
ns = _ns
152+
ns.clearLog()
153+
154+
let pool = getPoolFromServers(servers, ns)
155+
let free = ns.nFormat(pool.free, "0a")
156+
let running = ns.nFormat(pool.running, "0a")
157+
158+
// One column
159+
if (false) {
160+
for (const target of targets) {
161+
const lines = printfSeverAsTarget(target, ns)
162+
for (const line of lines) {
163+
ns.print(line)
164+
}
165+
}
166+
}
167+
168+
// Two-Column. Assumes everything is pretty uniform.
169+
let displayData = []
170+
for (const target of targets) {
171+
const lines = printfSeverAsTarget(target, ns)
172+
displayData.unshift(lines)
173+
}
174+
while (displayData.length > 1) {
175+
let col1Lines = displayData.pop()
176+
let col2Lines = displayData.pop()
177+
for (let i = 0; i < col1Lines.length; i++) {
178+
let col1 = col1Lines[i];
179+
let col2 = col2Lines[i];
180+
ns.print(col1 + ' ' + col2)
181+
}
182+
} // Then print any leftovers
183+
for (const data of displayData) {
184+
for (const line of data) {
185+
ns.print(line)
186+
}
187+
}
188+
ns.print('Worker Status')
189+
ns.print(`Free: ${free}, Running: ${running}`)
93190

94-
ns.tprint("Goodnight, Gracie!")
95191
}
96192

97-
function getPoolFromServers(servers, ns) {
98-
let pool = { slots: 0, grow: 0, hack: 0, weaken: 0 }
193+
function getPoolFromServers(servers, _ns) {
194+
ns = _ns
195+
let pool = { free: 0, grow: 0, hack: 0, weaken: 0, running: 0 }
99196
for (const server in servers) {
100197
const info = servers[server];
101198
// Treat undefined as 0 here.
102-
pool.slots += info.slots || 0;
103-
pool.grow += info.g || 0;
104-
pool.hack += info.h || 0;
105-
pool.weaken += info.w || 0;
199+
const free = info.slots || 0;
200+
const grow = info.g || 0;
201+
const hack = info.h || 0;
202+
const weaken = info.w || 0;
203+
pool.free += free
204+
pool.grow += grow
205+
pool.hack += hack
206+
pool.weaken += weaken
207+
pool.running += grow + hack + weaken
106208
}
107209
return pool;
108210
}

0 commit comments

Comments
 (0)