-
Notifications
You must be signed in to change notification settings - Fork 0
/
hnet.js
131 lines (121 loc) · 3.8 KB
/
hnet.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/**
* Copyright (C) 2023 Duck McSouls
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { MyArray } from "/quack/lib/array.js";
import { hnet_t } from "/quack/lib/constant/hnet.js";
import { log } from "/quack/lib/log.js";
import { money } from "/quack/lib/money.js";
import { assert } from "/quack/lib/util.js";
/**
* All nodes in our Hacknet farm.
*
* @param {NS} ns The Netscript API.
* @returns {array<number>} An array of node IDs. An empty array if we have
* zero nodes.
*/
function hacknet_nodes(ns) {
const n = ns.hacknet.numNodes();
return n < 1 ? [] : MyArray.sequence(n);
}
/**
* Whether we have sufficient money to cover a given cost.
*
* @param {NS} ns The Netscript API.
* @param {number} cost Do we have enough funds to cover this cost?
* @returns {boolean} True if we have funds to cover the given cost;
* false otherwise.
*/
function has_funds(ns, cost) {
assert(cost > 0);
return money(ns) > cost;
}
/**
* Setup our farm of Hacknet nodes, each at base stat.
*
* @param {NS} ns The Netscript API.
* @param {number} n How many Hacknet nodes in our farm.
*/
async function setup_farm(ns, n) {
const nNode = Math.floor(n);
assert(nNode > 0);
assert(nNode <= ns.hacknet.maxNumNodes());
if (ns.hacknet.numNodes() >= nNode) {
return;
}
// Purchase Hacknet nodes for our farm.
for (let i = ns.hacknet.numNodes(); i < nNode; i++) {
if (!has_funds(ns, ns.hacknet.getPurchaseNodeCost())) {
await ns.sleep(hnet_t.TICK);
continue;
}
const id = ns.hacknet.purchaseNode();
assert(id >= 0);
log(ns, `Purchased Hacknet node ${id}`);
}
}
/**
* Suppress various log messages.
*
* @param {NS} ns The Netscript API.
*/
function shush(ns) {
ns.disableLog("getServerMoneyAvailable");
ns.disableLog("sleep");
}
/**
* Upgrade the level of each Hacknet node by one point.
*
* @param {NS} ns The Netscript API.
*/
function upgrade_level(ns) {
const howmany = 1;
const level = (node) => ns.hacknet.getNodeStats(node).level;
const not_max = (node) => level(node) < hnet_t.MAX_LEVEL;
hacknet_nodes(ns)
.filter(not_max)
.forEach((node) => {
const cost = ns.hacknet.getLevelUpgradeCost(node, howmany);
if (Number.isFinite(cost) && has_funds(ns, cost)) {
ns.hacknet.upgradeLevel(node, howmany);
}
});
}
/**
* Manage a farm of Hacknet nodes.
*
* Usage: run quack/hnet.js
*
* @param {NS} ns The Netscript API.
*/
export async function main(ns) {
shush(ns);
await setup_farm(ns, hnet_t.SEED_NODE);
// Occassionally expand and upgrade the farm.
const threshold = Array.from(hnet_t.threshold);
for (;;) {
if (!MyArray.is_empty(threshold) && has_funds(ns, threshold[0][0])) {
const min_nodes = threshold[0][1];
await setup_farm(ns, min_nodes);
// Ensure our Hacknet farm has at least the given number of nodes
// before moving on to the next money/node thresholds.
if (ns.hacknet.numNodes() >= min_nodes) {
threshold.shift();
}
}
upgrade_level(ns);
await ns.sleep(hnet_t.TICK);
}
}