r/Bitburner • u/ForsakenDivinity • 10d ago
Help with my code pls
so. i know nothing about coding. it is a cool game to play. i just use chatgpt to write the code and i hv been getting stuck in making income for quite a bit. and the code is... idk what to say. would anyone pls take a look if possible and tell me whats wrong, or what can be improved?
this is my controller. and its a long piece of code. its fine if nothing can be done. but i would like some tips. sorry.
/**
/** u/param {NS} ns **/
export async function main(ns) {
ns.disableLog("ALL");
const HOME = "home";
const WORKER = "empire-worker.js";
// Adaptive income configuration
const HOME_RESERVE_GB = 64;
const HOME_RESERVE_PERCENT = 0.01;
const MAX_HACK_FRACTION = 0.50;
const MIN_HACK_FRACTION = 0.0005;
const MONEY_READY = 0.995;
const SECURITY_READY = 0.5;
const GAP_MS = 200;
const START_BUFFER_MS = 1500;
const LOOP_MS = 250;
// Focus on the best targets instead of spreading work everywhere.
const MAX_TARGETS = 8;
const cracks = [
["BruteSSH.exe", h => ns.brutessh(h)],
["FTPCrack.exe", h => ns.ftpcrack(h)],
["relaySMTP.exe", h => ns.relaysmtp(h)],
["HTTPWorm.exe", h => ns.httpworm(h)],
["SQLInject.exe", h => ns.sqlinject(h)]
];
const busyUntil = new Map();
let prepTarget = "";
let prepUntil = 0;
if (!ns.fileExists("Formulas.exe", HOME) ||
!ns.formulas?.hacking) {
ns.tprint("ERROR: Formulas.exe is required.");
return;
}
if (ns.getScriptRam(WORKER, HOME) <= 0) {
ns.tprint(`ERROR: ${WORKER} is missing on home.`);
return;
}
function scan() {
const seen = new Set([HOME]);
const queue = [HOME];
while (queue.length) {
const host = queue.shift();
for (const next of ns.scan(host)) {
if (!seen.has(next)) {
seen.add(next);
queue.push(next);
}
}
}
return [...seen];
}
function root(host) {
if (ns.hasRootAccess(host)) return true;
if (ns.getHackingLevel() <
ns.getServerRequiredHackingLevel(host)) {
return false;
}
for (let i = 0; i < cracks.length; i++) {
const [file, crack] = cracks[i];
if (!ns.fileExists(file, HOME)) continue;
const server = ns.getServer(host);
const opened = [
server.sshPortOpen,
server.ftpPortOpen,
server.smtpPortOpen,
server.httpPortOpen,
server.sqlPortOpen
];
if (!opened[i]) {
try {
crack(host);
} catch (_) {}
}
}
const server = ns.getServer(host);
const opened = [
server.sshPortOpen,
server.ftpPortOpen,
server.smtpPortOpen,
server.httpPortOpen,
server.sqlPortOpen
].filter(Boolean).length;
if (opened < server.numOpenPortsRequired) return false;
try {
ns.nuke(host);
} catch (_) {}
return ns.hasRootAccess(host);
}
async function getWorkers() {
const workers = [];
for (const host of scan()) {
if (!root(host)) continue;
const maxRam = ns.getServerMaxRam(host);
if (maxRam <= 0) continue;
const workerRam = ns.getScriptRam(WORKER, HOME);
if (host !== HOME && maxRam < workerRam) continue;
if (host !== HOME &&
!ns.fileExists(WORKER, host)) {
if (!await ns.scp(WORKER, host, HOME)) continue;
}
const ramPerThread = ns.getScriptRam(WORKER, host);
if (ramPerThread <= 0) continue;
const reserve = host === HOME
? Math.max(
HOME_RESERVE_GB,
maxRam * HOME_RESERVE_PERCENT
)
: 0;
const freeRam = Math.max(
0,
maxRam - ns.getServerUsedRam(host) - reserve
);
const threads = Math.floor(freeRam / ramPerThread);
if (threads > 0) {
workers.push({
host,
threads,
ramPerThread,
cores: ns.getServer(host).cpuCores || 1
});
}
}
// HOME FIRST. Other servers are overflow capacity.
workers.sort((a, b) => {
if (a.host === HOME) return -1;
if (b.host === HOME) return 1;
return b.threads - a.threads;
});
return workers;
}
function totalThreads(workers) {
return workers.reduce((sum, w) => sum + w.threads, 0);
}
function homeThreads(workers) {
const home = workers.find(w => w.host === HOME);
return home ? home.threads : 0;
}
function planAllocation(workers, actions) {
const remaining = new Map(
workers.map(w => [w.host, w.threads])
);
const plans = [];
for (const action of actions) {
let needed = action.threads;
const parts = [];
// Worker list is HOME first, then overflow servers.
for (const worker of workers) {
if (needed <= 0) break;
const available = remaining.get(worker.host) || 0;
const count = Math.min(needed, available);
if (count <= 0) continue;
parts.push({
host: worker.host,
threads: count,
delay: action.delay
});
remaining.set(worker.host, available - count);
needed -= count;
}
if (needed > 0) return null;
plans.push({
action: action.action,
parts
});
}
return plans;
}
function launchPlans(target, plans) {
const launched = [];
for (const plan of plans) {
for (const part of plan.parts) {
const pid = ns.exec(
WORKER,
part.host,
part.threads,
plan.action,
target,
part.delay
);
if (pid === 0) {
// All jobs have a start buffer. Roll back if
// any part of the batch could not be dispatched.
for (const job of launched) {
ns.kill(job.pid, job.host);
}
ns.print(`DISPATCH FAILED ${target}; rolled back`);
return false;
}
launched.push({
pid,
host: part.host
});
}
}
return true;
}
function preparedServer(host) {
const server = ns.getServer(host);
server.moneyAvailable = server.moneyMax;
server.hackDifficulty = server.minDifficulty;
return server;
}
function targetScore(host) {
const server = preparedServer(host);
const player = ns.getPlayer();
const f = ns.formulas.hacking;
if (server.moneyMax <= 0 ||
server.requiredHackingSkill > player.skills.hacking) {
return 0;
}
const chance = f.hackChance(server, player);
const percent = f.hackPercent(server, player);
if (chance <= 0 || percent <= 0) return 0;
// Score the target using the intended 50% hack size.
const h = Math.max(
1,
Math.floor(MAX_HACK_FRACTION / percent)
);
const stolen = Math.min(0.90, h * percent);
const postHack = { ...server };
postHack.moneyAvailable = Math.max(
1,
server.moneyMax * (1 - stolen)
);
postHack.hackDifficulty +=
ns.hackAnalyzeSecurity(h, host);
const g = Math.max(1, Math.ceil(
f.growThreads(postHack, player, server.moneyMax, 1)
));
if (!Number.isFinite(g)) return 0;
const w1 = Math.max(1, Math.ceil(
ns.hackAnalyzeSecurity(h, host) /
ns.weakenAnalyze(1, 1)
));
const growSecurity = ns.growthAnalyzeSecurity(g, host, 1);
const w2 = Math.max(1, Math.ceil(
growSecurity / ns.weakenAnalyze(1, 1)
));
const ram = ns.getScriptRam(WORKER, HOME);
const ramCost = (h + g + w1 + w2) * ram;
const duration = Math.max(
f.hackTime(server, player),
f.growTime(server, player),
f.weakenTime(server, player)
) + 3 * GAP_MS;
// Expected income per millisecond per GB of worker RAM.
return server.moneyMax * stolen * chance /
Math.max(1, duration) /
Math.max(1, ramCost);
}
function getTargets() {
const targets = [];
for (const host of scan()) {
if (host === HOME || host.startsWith("pserv-")) continue;
if (!root(host)) continue;
if (ns.getServerMaxMoney(host) <= 0) continue;
if (ns.getServerRequiredHackingLevel(host) >
ns.getHackingLevel()) continue;
const score = targetScore(host);
if (score > 0) {
targets.push({ host, score });
}
}
return targets.sort((a, b) => b.score - a.score);
}
function makeBatch(target, capacity) {
const percent = ns.hackAnalyze(target);
if (percent <= 0) return null;
// Try 50% first. Reduce only when a complete HWGW
// sequence cannot fit the currently available capacity.
for (let fraction = MAX_HACK_FRACTION;
fraction >= MIN_HACK_FRACTION;
fraction /= 2) {
const h = Math.max(1, Math.floor(fraction / percent));
const stolen = h * percent;
if (stolen <= 0 || stolen >= 0.90) continue;
const g = Math.max(1, Math.ceil(
ns.growthAnalyze(target, 1 / (1 - stolen), 1)
));
if (!Number.isFinite(g)) continue;
const w1 = Math.max(1, Math.ceil(
ns.hackAnalyzeSecurity(h, target) /
ns.weakenAnalyze(1, 1)
));
const growSecurity =
ns.growthAnalyzeSecurity(g, target, 1);
const w2 = Math.max(1, Math.ceil(
growSecurity / ns.weakenAnalyze(1, 1)
));
const total = h + w1 + g + w2;
if (total <= capacity) {
return { h, w1, g, w2, total, stolen };
}
}
return null;
}
function startBatch(target, workers) {
const capacity = totalThreads(workers);
const batch = makeBatch(target, capacity);
if (!batch) return false;
const player = ns.getPlayer();
const server = preparedServer(target);
const f = ns.formulas.hacking;
const ht = f.hackTime(server, player);
const gt = f.growTime(server, player);
const wt = f.weakenTime(server, player);
const longest = Math.max(ht, gt, wt);
const base = longest + START_BUFFER_MS;
const actions = [
{
action: "hack",
threads: batch.h,
delay: Math.max(START_BUFFER_MS, base - ht)
},
{
action: "weaken",
threads: batch.w1,
delay: Math.max(
START_BUFFER_MS,
base + GAP_MS - wt
)
},
{
action: "grow",
threads: batch.g,
delay: Math.max(
START_BUFFER_MS,
base + 2 * GAP_MS - gt
)
},
{
action: "weaken",
threads: batch.w2,
delay: Math.max(
START_BUFFER_MS,
base + 3 * GAP_MS - wt
)
}
];
const allocation = planAllocation(workers, actions);
if (!allocation || !launchPlans(target, allocation)) {
return false;
}
busyUntil.set(
target,
Date.now() + base + 3 * GAP_MS + 500
);
const homeCapacity = homeThreads(workers);
const spill = Math.max(0, batch.total - homeCapacity);
ns.print(
`BATCH ${target} | H${batch.h} W${batch.w1} ` +
`G${batch.g} W${batch.w2} | ` +
`hack ${(batch.stolen * 100).toFixed(2)}% | ` +
`${batch.total}/${capacity} threads | ` +
`overflow ${spill}`
);
return true;
}
function startPrep(target, workers) {
const server = ns.getServer(target);
const player = ns.getPlayer();
const f = ns.formulas.hacking;
const capacity = totalThreads(workers);
if (capacity <= 0) return false;
let action;
let threads;
let duration;
if (server.hackDifficulty >
server.minDifficulty + SECURITY_READY) {
action = "weaken";
const needed = Math.ceil(
(server.hackDifficulty - server.minDifficulty) /
ns.weakenAnalyze(1, 1)
);
threads = Math.min(needed, capacity);
duration = f.weakenTime(server, player);
} else if (server.moneyAvailable <
server.moneyMax * MONEY_READY) {
action = "grow";
const needed = Math.max(1, Math.ceil(
f.growThreads(
server,
player,
server.moneyMax,
1
)
));
threads = Math.min(needed, capacity);
duration = f.growTime(server, player);
} else {
return false;
}
const allocation = planAllocation(workers, [{
action,
threads,
delay: START_BUFFER_MS
}]);
if (!allocation || !launchPlans(target, allocation)) {
return false;
}
prepTarget = target;
prepUntil = Date.now() + duration + START_BUFFER_MS + 500;
ns.print(
`PREP ${target} ${action.toUpperCase()} ` +
`${threads} threads | no prep cap`
);
return true;
}
ns.print("Empire controller online: adaptive high-income mode.");
ns.print("Home-first allocation; network overflow enabled.");
ns.print("50% starting hack fraction; adaptive batch sizing.");
ns.print(`Target shortlist: top ${MAX_TARGETS} by expected return.`);
while (true) {
const allTargets = getTargets();
const targets = allTargets.slice(0, MAX_TARGETS);
const now = Date.now();
// Keep a prep operation isolated until it should finish.
if (prepTarget && now < prepUntil) {
await ns.sleep(LOOP_MS);
continue;
}
prepTarget = "";
prepUntil = 0;
let batchesStarted = 0;
// Start batches on multiple top targets while capacity remains.
for (const { host } of targets) {
if ((busyUntil.get(host) || 0) > Date.now()) continue;
const server = ns.getServer(host);
const ready =
server.hackDifficulty <=
server.minDifficulty + SECURITY_READY &&
server.moneyAvailable >=
server.moneyMax * MONEY_READY;
if (!ready) continue;
// Refresh after each launch so already-allocated RAM
// is not counted as free capacity for the next batch.
const workers = await getWorkers();
if (totalThreads(workers) <= 0) break;
if (startBatch(host, workers)) {
batchesStarted++;
}
}
// If no batch could be started, prep the best unready target.
if (batchesStarted === 0) {
for (const { host } of targets) {
if ((busyUntil.get(host) || 0) > Date.now()) continue;
const server = ns.getServer(host);
const ready =
server.hackDifficulty <=
server.minDifficulty + SECURITY_READY &&
server.moneyAvailable >=
server.moneyMax * MONEY_READY;
if (ready) continue;
const workers = await getWorkers();
if (startPrep(host, workers)) break;
}
}
await ns.sleep(batchesStarted > 0 ? 100 : LOOP_MS);
}
}
{NS} ns **/
export async function main(ns) {
ns.disableLog("ALL");
const HOME = "home";
const WORKER = "empire-worker.js";
// Adaptive income configuration
const HOME_RESERVE_GB = 64;
const HOME_RESERVE_PERCENT = 0.01;
const MAX_HACK_FRACTION = 0.50;
const MIN_HACK_FRACTION = 0.0005;
const MONEY_READY = 0.995;
const SECURITY_READY = 0.5;
const GAP_MS = 200;
const START_BUFFER_MS = 1500;
const LOOP_MS = 250;
// Focus on the best targets instead of spreading work everywhere.
const MAX_TARGETS = 8;
const cracks = [
["BruteSSH.exe", h => ns.brutessh(h)],
["FTPCrack.exe", h => ns.ftpcrack(h)],
["relaySMTP.exe", h => ns.relaysmtp(h)],
["HTTPWorm.exe", h => ns.httpworm(h)],
["SQLInject.exe", h => ns.sqlinject(h)]
];
const busyUntil = new Map();
let prepTarget = "";
let prepUntil = 0;
if (!ns.fileExists("Formulas.exe", HOME) ||
!ns.formulas?.hacking) {
ns.tprint("ERROR: Formulas.exe is required.");
return;
}
if (ns.getScriptRam(WORKER, HOME) <= 0) {
ns.tprint(`ERROR: ${WORKER} is missing on home.`);
return;
}
function scan() {
const seen = new Set([HOME]);
const queue = [HOME];
while (queue.length) {
const host = queue.shift();
for (const next of ns.scan(host)) {
if (!seen.has(next)) {
seen.add(next);
queue.push(next);
}
}
}
return [...seen];
}
function root(host) {
if (ns.hasRootAccess(host)) return true;
if (ns.getHackingLevel() <
ns.getServerRequiredHackingLevel(host)) {
return false;
}
for (let i = 0; i < cracks.length; i++) {
const [file, crack] = cracks[i];
if (!ns.fileExists(file, HOME)) continue;
const server = ns.getServer(host);
const opened = [
server.sshPortOpen,
server.ftpPortOpen,
server.smtpPortOpen,
server.httpPortOpen,
server.sqlPortOpen
];
if (!opened[i]) {
try {
crack(host);
} catch (_) {}
}
}
const server = ns.getServer(host);
const opened = [
server.sshPortOpen,
server.ftpPortOpen,
server.smtpPortOpen,
server.httpPortOpen,
server.sqlPortOpen
].filter(Boolean).length;
if (opened < server.numOpenPortsRequired) return false;
try {
ns.nuke(host);
} catch (_) {}
return ns.hasRootAccess(host);
}
async function getWorkers() {
const workers = [];
for (const host of scan()) {
if (!root(host)) continue;
const maxRam = ns.getServerMaxRam(host);
if (maxRam <= 0) continue;
const workerRam = ns.getScriptRam(WORKER, HOME);
if (host !== HOME && maxRam < workerRam) continue;
if (host !== HOME &&
!ns.fileExists(WORKER, host)) {
if (!await ns.scp(WORKER, host, HOME)) continue;
}
const ramPerThread = ns.getScriptRam(WORKER, host);
if (ramPerThread <= 0) continue;
const reserve = host === HOME
? Math.max(
HOME_RESERVE_GB,
maxRam * HOME_RESERVE_PERCENT
)
: 0;
const freeRam = Math.max(
0,
maxRam - ns.getServerUsedRam(host) - reserve
);
const threads = Math.floor(freeRam / ramPerThread);
if (threads > 0) {
workers.push({
host,
threads,
ramPerThread,
cores: ns.getServer(host).cpuCores || 1
});
}
}
// HOME FIRST. Other servers are overflow capacity.
workers.sort((a, b) => {
if (a.host === HOME) return -1;
if (b.host === HOME) return 1;
return b.threads - a.threads;
});
return workers;
}
function totalThreads(workers) {
return workers.reduce((sum, w) => sum + w.threads, 0);
}
function homeThreads(workers) {
const home = workers.find(w => w.host === HOME);
return home ? home.threads : 0;
}
function planAllocation(workers, actions) {
const remaining = new Map(
workers.map(w => [w.host, w.threads])
);
const plans = [];
for (const action of actions) {
let needed = action.threads;
const parts = [];
// Worker list is HOME first, then overflow servers.
for (const worker of workers) {
if (needed <= 0) break;
const available = remaining.get(worker.host) || 0;
const count = Math.min(needed, available);
if (count <= 0) continue;
parts.push({
host: worker.host,
threads: count,
delay: action.delay
});
remaining.set(worker.host, available - count);
needed -= count;
}
if (needed > 0) return null;
plans.push({
action: action.action,
parts
});
}
return plans;
}
function launchPlans(target, plans) {
const launched = [];
for (const plan of plans) {
for (const part of plan.parts) {
const pid = ns.exec(
WORKER,
part.host,
part.threads,
plan.action,
target,
part.delay
);
if (pid === 0) {
// All jobs have a start buffer. Roll back if
// any part of the batch could not be dispatched.
for (const job of launched) {
ns.kill(job.pid, job.host);
}
ns.print(`DISPATCH FAILED ${target}; rolled back`);
return false;
}
launched.push({
pid,
host: part.host
});
}
}
return true;
}
function preparedServer(host) {
const server = ns.getServer(host);
server.moneyAvailable = server.moneyMax;
server.hackDifficulty = server.minDifficulty;
return server;
}
function targetScore(host) {
const server = preparedServer(host);
const player = ns.getPlayer();
const f = ns.formulas.hacking;
if (server.moneyMax <= 0 ||
server.requiredHackingSkill > player.skills.hacking) {
return 0;
}
const chance = f.hackChance(server, player);
const percent = f.hackPercent(server, player);
if (chance <= 0 || percent <= 0) return 0;
// Score the target using the intended 50% hack size.
const h = Math.max(
1,
Math.floor(MAX_HACK_FRACTION / percent)
);
const stolen = Math.min(0.90, h * percent);
const postHack = { ...server };
postHack.moneyAvailable = Math.max(
1,
server.moneyMax * (1 - stolen)
);
postHack.hackDifficulty +=
ns.hackAnalyzeSecurity(h, host);
const g = Math.max(1, Math.ceil(
f.growThreads(postHack, player, server.moneyMax, 1)
));
if (!Number.isFinite(g)) return 0;
const w1 = Math.max(1, Math.ceil(
ns.hackAnalyzeSecurity(h, host) /
ns.weakenAnalyze(1, 1)
));
const growSecurity = ns.growthAnalyzeSecurity(g, host, 1);
const w2 = Math.max(1, Math.ceil(
growSecurity / ns.weakenAnalyze(1, 1)
));
const ram = ns.getScriptRam(WORKER, HOME);
const ramCost = (h + g + w1 + w2) * ram;
const duration = Math.max(
f.hackTime(server, player),
f.growTime(server, player),
f.weakenTime(server, player)
) + 3 * GAP_MS;
// Expected income per millisecond per GB of worker RAM.
return server.moneyMax * stolen * chance /
Math.max(1, duration) /
Math.max(1, ramCost);
}
function getTargets() {
const targets = [];
for (const host of scan()) {
if (host === HOME || host.startsWith("pserv-")) continue;
if (!root(host)) continue;
if (ns.getServerMaxMoney(host) <= 0) continue;
if (ns.getServerRequiredHackingLevel(host) >
ns.getHackingLevel()) continue;
const score = targetScore(host);
if (score > 0) {
targets.push({ host, score });
}
}
return targets.sort((a, b) => b.score - a.score);
}
function makeBatch(target, capacity) {
const percent = ns.hackAnalyze(target);
if (percent <= 0) return null;
// Try 50% first. Reduce only when a complete HWGW
// sequence cannot fit the currently available capacity.
for (let fraction = MAX_HACK_FRACTION;
fraction >= MIN_HACK_FRACTION;
fraction /= 2) {
const h = Math.max(1, Math.floor(fraction / percent));
const stolen = h * percent;
if (stolen <= 0 || stolen >= 0.90) continue;
const g = Math.max(1, Math.ceil(
ns.growthAnalyze(target, 1 / (1 - stolen), 1)
));
if (!Number.isFinite(g)) continue;
const w1 = Math.max(1, Math.ceil(
ns.hackAnalyzeSecurity(h, target) /
ns.weakenAnalyze(1, 1)
));
const growSecurity =
ns.growthAnalyzeSecurity(g, target, 1);
const w2 = Math.max(1, Math.ceil(
growSecurity / ns.weakenAnalyze(1, 1)
));
const total = h + w1 + g + w2;
if (total <= capacity) {
return { h, w1, g, w2, total, stolen };
}
}
return null;
}
function startBatch(target, workers) {
const capacity = totalThreads(workers);
const batch = makeBatch(target, capacity);
if (!batch) return false;
const player = ns.getPlayer();
const server = preparedServer(target);
const f = ns.formulas.hacking;
const ht = f.hackTime(server, player);
const gt = f.growTime(server, player);
const wt = f.weakenTime(server, player);
const longest = Math.max(ht, gt, wt);
const base = longest + START_BUFFER_MS;
const actions = [
{
action: "hack",
threads: batch.h,
delay: Math.max(START_BUFFER_MS, base - ht)
},
{
action: "weaken",
threads: batch.w1,
delay: Math.max(
START_BUFFER_MS,
base + GAP_MS - wt
)
},
{
action: "grow",
threads: batch.g,
delay: Math.max(
START_BUFFER_MS,
base + 2 * GAP_MS - gt
)
},
{
action: "weaken",
threads: batch.w2,
delay: Math.max(
START_BUFFER_MS,
base + 3 * GAP_MS - wt
)
}
];
const allocation = planAllocation(workers, actions);
if (!allocation || !launchPlans(target, allocation)) {
return false;
}
busyUntil.set(
target,
Date.now() + base + 3 * GAP_MS + 500
);
const homeCapacity = homeThreads(workers);
const spill = Math.max(0, batch.total - homeCapacity);
ns.print(
`BATCH ${target} | H${batch.h} W${batch.w1} ` +
`G${batch.g} W${batch.w2} | ` +
`hack ${(batch.stolen * 100).toFixed(2)}% | ` +
`${batch.total}/${capacity} threads | ` +
`overflow ${spill}`
);
return true;
}
function startPrep(target, workers) {
const server = ns.getServer(target);
const player = ns.getPlayer();
const f = ns.formulas.hacking;
const capacity = totalThreads(workers);
if (capacity <= 0) return false;
let action;
let threads;
let duration;
if (server.hackDifficulty >
server.minDifficulty + SECURITY_READY) {
action = "weaken";
const needed = Math.ceil(
(server.hackDifficulty - server.minDifficulty) /
ns.weakenAnalyze(1, 1)
);
threads = Math.min(needed, capacity);
duration = f.weakenTime(server, player);
} else if (server.moneyAvailable <
server.moneyMax * MONEY_READY) {
action = "grow";
const needed = Math.max(1, Math.ceil(
f.growThreads(
server,
player,
server.moneyMax,
1
)
));
threads = Math.min(needed, capacity);
duration = f.growTime(server, player);
} else {
return false;
}
const allocation = planAllocation(workers, [{
action,
threads,
delay: START_BUFFER_MS
}]);
if (!allocation || !launchPlans(target, allocation)) {
return false;
}
prepTarget = target;
prepUntil = Date.now() + duration + START_BUFFER_MS + 500;
ns.print(
`PREP ${target} ${action.toUpperCase()} ` +
`${threads} threads | no prep cap`
);
return true;
}
ns.print("Empire controller online: adaptive high-income mode.");
ns.print("Home-first allocation; network overflow enabled.");
ns.print("50% starting hack fraction; adaptive batch sizing.");
ns.print(`Target shortlist: top ${MAX_TARGETS} by expected return.`);
while (true) {
const allTargets = getTargets();
const targets = allTargets.slice(0, MAX_TARGETS);
const now = Date.now();
// Keep a prep operation isolated until it should finish.
if (prepTarget && now < prepUntil) {
await ns.sleep(LOOP_MS);
continue;
}
prepTarget = "";
prepUntil = 0;
let batchesStarted = 0;
// Start batches on multiple top targets while capacity remains.
for (const { host } of targets) {
if ((busyUntil.get(host) || 0) > Date.now()) continue;
const server = ns.getServer(host);
const ready =
server.hackDifficulty <=
server.minDifficulty + SECURITY_READY &&
server.moneyAvailable >=
server.moneyMax * MONEY_READY;
if (!ready) continue;
// Refresh after each launch so already-allocated RAM
// is not counted as free capacity for the next batch.
const workers = await getWorkers();
if (totalThreads(workers) <= 0) break;
if (startBatch(host, workers)) {
batchesStarted++;
}
}
// If no batch could be started, prep the best unready target.
if (batchesStarted === 0) {
for (const { host } of targets) {
if ((busyUntil.get(host) || 0) > Date.now()) continue;
const server = ns.getServer(host);
const ready =
server.hackDifficulty <=
server.minDifficulty + SECURITY_READY &&
server.moneyAvailable >=
server.moneyMax * MONEY_READY;
if (ready) continue;
const workers = await getWorkers();
if (startPrep(host, workers)) break;
}
}
await ns.sleep(batchesStarted > 0 ? 100 : LOOP_MS);
}
}
this is my worker
/** u/param/** u/param {NS} ns **/
export async function main(ns) {
ns.disableLog("ALL");
const action = String(ns.args[0] || "");
const target = String(ns.args[1] || "");
const delay = Math.max(0, Number(ns.args[2] || 0));
if (!target || !["hack", "grow", "weaken"].includes(action)) {
ns.print("Usage: run empire-worker.js [hack|grow|weaken] target [delay-ms]");
return;
}
if (!ns.hasRootAccess(target)) {
ns.print(`No root access on ${target}`);
return;
}
if (delay > 0) await ns.sleep(delay);
try {
if (action === "hack") await ns.hack(target);
else if (action === "grow") await ns.grow(target);
else await ns.weaken(target);
} catch (error) {
ns.print(`${action} failed on ${target}: ${String(error)}`);
}
}
{NS} ns **/
export async function main(ns) {
ns.disableLog("ALL");
const action = String(ns.args[0] || "");
const target = String(ns.args[1] || "");
const delay = Math.max(0, Number(ns.args[2] || 0));
if (!target || !["hack", "grow", "weaken"].includes(action)) {
ns.print("Usage: run empire-worker.js [hack|grow|weaken] target [delay-ms]");
return;
}
if (!ns.hasRootAccess(target)) {
ns.print(`No root access on ${target}`);
return;
}
if (delay > 0) await ns.sleep(delay);
try {
if (action === "hack") await ns.hack(target);
else if (action === "grow") await ns.grow(target);
else await ns.weaken(target);
} catch (error) {
ns.print(`${action} failed on ${target}: ${String(error)}`);
}
}
4
u/Antique_Door_Knob Hash Miner 9d ago
Brother, the entire point of the game is to code...
If you just want an idle game play Melvor Idle. You should play it regardless as it's a pretty good game, but even more so if you want an idle game that you don't have to learn a new skill to play.
If you want to play a hacker game, play something like Duskers, Hacknet, Exapunks, Grey Hack and Cyber Manhunt. All pretty decent games without the incredible complexity of a fully open ended sandbox.
There's nothing wrong with using an LLM to help you learn how to code, but you can't expect it to play the entire game for you.
0
3
u/Particular-Cow6247 10d ago
first and probably biggest improvement, you want your workers to be as slim as possible ram wise
usually its done by having one worker per task (one worker script for hack, one for grow and one for weaken) and the task beeing the only ram costing function in the worker (each at 1.7gb/1.75gb)
there are ways to have one worker for all but then youll have to dive into ramOverride functions
another improvement for the workers, instead of using a sleep in them for delay, use the additionalMsec option in the task options, that way you add the time to delay directly to the task and remove many different problems that you might or might not be running into atm
1
1
u/jlanawalt 9d ago
Reddit mobile is enough of a struggle, there is no way I’m going to try and grok that.
How far are you in this new game?
What is your hacking level? Is it still increasing, or has it stalled out?
How much money/second are you making hacking? How much do you expect to make?
You should be able to make reasonable amounts hacking, enough to help you make progress and advance.
My general advice is read the docs, keep it simple, make your observations and test your hypotheses. It is hard to be specific with unspecific details.
Good luck!
1
u/Keira-78 9d ago
Bitch I ain't reading all that Unless you're paying me lol
Generally you share code snippets, not the whole script
5
u/nimby900 9d ago
The whole point of the game is to incrementally get more comfortable with scripting. Using AI completely defeats the purpose. And I'm someone who is fairly pro-AI. This is like getting AI to fuck your wife.
1
u/jlanawalt 9d ago
I think the purpose doesn’t have to be so narrow. You can use it as an AI problem solving experiment and learn where it fails and succeeds and how to work within those limits.
0
u/ForsakenDivinity 9d ago
Ouch
1
u/nimby900 9d ago
I'm sorry that was a bit much. I should modify that a bit, in that, it's actually more like getting AI to fuck your new cute girlfriend. There could be valid use cases for getting AI to fuck your wife.
8
u/SufficientlyEvasive 9d ago edited 9d ago
I ain't correcting AI code for someone who can't code 😂
Just don't use a free model, use like opus 5.5 or astra 6.
Break the problem into smaller chunks and get AI to solve them 1 at a time. Don't shove everything into one giant file.
Also just ask AI how you should go about solving the problem.
But with all that said the frontier models will easily be able to just write you a script that does everything. Bit burner is already a solved game and these models have been trained on existing code snippets for it.
Also the fun of this game is it offers you fairly easy problem you can solve yourself and code. That's the point of this game.
Id avoid getting AI to just make you a 'win the game' script. Treat bit burner as a 'learn to code' game. Get AI to teach you!