├── .gitignore ├── LICENSE.md ├── README.md ├── augmentations ├── README.md ├── buy.js ├── graft.js ├── info.js └── unlock.js ├── batch ├── README.md ├── manage.js └── prep.js ├── bladeburner ├── actions.ns ├── init.ns ├── progress.ns └── skills.ns ├── botnet ├── README.md ├── manager.js ├── prep.js ├── stop.js ├── system-diagram.svg ├── thread-pool.js ├── worker-grow.js ├── worker-hack.js ├── worker-weaken.js └── worker.js ├── contracts ├── find-and-solve.js └── solvers.js ├── corporation ├── buyback-shares.js └── init.js ├── exploit ├── bypass.ns ├── console.js ├── dev-menu.js ├── embed_player.py ├── exploit.ns ├── extract_player.py ├── hax.script ├── printHTML.js └── select-next-bitnode.js ├── gang ├── ascend.js ├── buy-augs.js ├── info.js └── manage.js ├── hacking ├── README.md ├── batch-model.js ├── batch-view.js ├── doc │ ├── HWGW.svg │ └── gameplay-loop.svg ├── planner.js └── worker.js ├── hacknet ├── nodes.ns ├── servers.js └── spend-hashes.js ├── init.js ├── inspect ├── bitnode.js ├── get-info.js └── server.js ├── lib ├── README.md ├── box-drawing.js └── port-service.js ├── net ├── README.md ├── auto-link.js ├── buy-server.js ├── deploy-script.js ├── register-servers.js ├── server-list.js └── upgrade-home-server.js ├── old ├── BACKUP_lib.ns ├── attack-optimal-targets.script ├── attack-targets.script ├── batch-analyze.js ├── batch-manage.js ├── buy-bull.script ├── buy-stocks.script ├── cloud-manage.script ├── cloud-purchase.script ├── cloud-run-one.script ├── cloud-run.script ├── cloud-setup.script ├── cloud-spawn.script ├── create-programs.script ├── crime.script ├── dequeue-servers.script ├── dist-0port.script ├── early-hack-template.script ├── enqueue-servers.script ├── farm-init.script ├── farm.script ├── find-contracts.ns ├── find-farms.script ├── find-targets.script ├── get-info.script ├── getInfo.script ├── grow.script ├── hack.script ├── hacknet.script ├── init-aug.script ├── init-bitnode.script ├── init-farms.script ├── init.script ├── iterate-servers.script ├── letmein.script ├── lib.ns ├── list-servers.ns ├── maintain.script ├── manage-stocks.script ├── map.ns ├── purchase-server-4gb.script ├── remote-manage.script ├── remote-run-one.script ├── remote-run.script ├── remote-setup.script ├── scan-bfs.script ├── scan-dfs.script ├── scan.script ├── sell-bear.script ├── sell.script ├── singularity-progress.script ├── smart-farm.script ├── soft-reset.ns ├── spawn-farms.ns ├── spawn-farms.script ├── traceroute.script ├── v1_DETECTED_CHANGES.txt ├── value-stocks.script ├── weaken.script ├── work.script └── workout.script ├── player ├── backdoor-servers.js ├── create-programs.js ├── crime.js ├── info.js ├── join-factions.js ├── prestige.js ├── train.js └── tunnel.js ├── service ├── README.md ├── compute.js ├── hack-planning.js └── server-info.js ├── share ├── deploy.js └── share.js ├── sleeves ├── buy-augs.js ├── crime.js ├── init.js ├── train.js └── work.js ├── stanek ├── charge-x-y.js ├── deploy.js ├── info.js └── respec.js ├── stocks ├── companies.js ├── sell.js └── trader.js └── unmanaged-hacking ├── deploy.js ├── hack-grow-weaken.js └── stop.js /.gitignore: -------------------------------------------------------------------------------- 1 | /.vscode 2 | global.d.ts 3 | NetscriptDefinitions.d.ts 4 | 5 | *.graffle 6 | 7 | /xsinx/* 8 | /DoctorNightmares/* 9 | -------------------------------------------------------------------------------- /augmentations/README.md: -------------------------------------------------------------------------------- 1 | ## Bitburner Augmentation Scripts 2 | 3 | ### [`info.js`](info.js) (32.6 GB) 4 | 5 | List owned augmentations or show stats of a named augmentation. 6 | 7 | Example: List installed augmentations 8 | ``` 9 | > run /augmentations/info.js 10 | ``` 11 | 12 | Example: Show stats of a specific augmentation (supports autocomplete) 13 | ``` 14 | > run /augmentations/info.js Cranial Signal Processors - Gen III 15 | 16 | Cranial Signal Processors - Gen III 17 | Status: Not Owned 18 | Price: $550.0m 19 | Value: 1.279x 20 | Stats: { 21 | "hacking_mult": 1.09, 22 | "hacking_speed_mult": 1.02, 23 | "hacking_money_mult": 1.15 24 | } 25 | Prereqs: ["Cranial Signal Processors - Gen II"] ✗ 26 | Factions: 27 | BitRunners: 158k / 50k rep ✓ 28 | The Black Hand: 186k / 50k rep ✓ 29 | NiteSec: 451k / 50k rep ✓ 30 | ``` 31 | 32 | ----- 33 | 34 | ### [`buy.js`](buy.js) (35.6 GB) 35 | 36 | List the best augmentations available now, most expensive first. Optionally buy them. 37 | 38 | Usage: 39 | ``` 40 | /augmentations/buy.js [ hacking | charisma | combat | crime | faction | hacknet | bladeburner | all ... ] [ --buy ] 41 | ``` 42 | 43 | Example: See all augs that increase hacking or hacknet stats 44 | ``` 45 | > run /augmentations/buy.js hacking hacknet 46 | 47 | Augmentation Buying Plan: hacking, hacknet 48 | 'Neuralstimulator' from Sector-12 for $3.0b 49 | 'Neural-Retention Enhancement' from NiteSec for $250.0m 50 | 'Embedded Netburner Module' from NiteSec for $250.0m 51 | 'Cranial Signal Processors - Gen I' from NiteSec for $70.0m 52 | 'Cranial Signal Processors - Gen II' from NiteSec for $125.0m 53 | 'Power Recirculation Core' from NiteSec for $180.0m 54 | ... 55 | ``` 56 | 57 | Example: Buy all augs that increase hacking, including NeuroFlux Governor repeatedly 58 | ``` 59 | > run /augmentations/buy.js hacking --buy 60 | ``` 61 | 62 | ----- 63 | 64 | ### [`unlock.js`](unlock.js) (34.1 GB) 65 | 66 | List the best augmentations available soon, sorted by least reputation required. Optionally work for those factions. 67 | 68 | Example: Show all augs that improve combat or crime, and the closest faction to selling them 69 | ``` 70 | > run /augmentations/unlock.js combat crime 71 | 72 | Augmentation Unlocking Plan: combat, crime 73 | 1,777 more reputation with Speakers for the Dead for 'The Shadow's Simulacrum' 74 | 37,042 more reputation with Tian Di Hui for 'Neuroreceptor Management Implant' 75 | 62,465 more reputation with NiteSec for 'Graphene BrachiBlades Upgrade' 76 | 70,744 more reputation with The Syndicate for 'Bionic Legs' 77 | 89,045 more reputation with The Black Hand for 'The Black Hand' 78 | ... 79 | ``` 80 | 81 | ----- 82 | 83 | ### [`graft.js`](graft.js) (43.1 GB) 84 | 85 | List the best augmentations available to graft, sorted by (multipliers / time). Optionally graft them. 86 | 87 | Usage: 88 | ``` 89 | /augmentations/graft.js [ hacking | charisma | combat | crime | faction | hacknet | bladeburner | all ... ] [ --begin ] 90 | ``` 91 | 92 | Example: List all augmentations that increase charisma or faction rep gain. 93 | ``` 94 | > run /augmentations/graft.js charisma faction 95 | 96 | Augmentation Grafting Plan: charisma, faction 97 | $15.9b (1.2 hr) for (1.96x) 'Unstable Circadian Modulator' 98 | $4.1b (1.1 hr) for (1.86x) 'Enhanced Social Interaction Implant' 99 | $8.3b (1.5 hr) for (2.12x) 'SmartJaw' 100 | $22.5b (1.3 hr) for (1.84x) 'PC Direct-Neural Interface NeuroNet Injector' 101 | ... 102 | ``` 103 | 104 | Example: Graft all augmentations that increase hacking stats. 105 | ``` 106 | > run /augmentations/graft.js hacking --begin 107 | ``` 108 | 109 | ----- 110 | 111 | ### See Also 112 | 113 | - [`/sleeves/buy-augs.js`](../sleeves/buy-augs.js) - Buy augmentations for sleeves. 114 | 115 | - [`/gang/buy-augs.js`](../gang/buy-augs.js) - Buy equipment for gang members. 116 | 117 | - [`/player/prestige.js`](../player/prestige.js) - Run final activities before installing augmentations. 118 | -------------------------------------------------------------------------------- /augmentations/unlock.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | /augmentations/unlock.js (34.1 GB) 4 | 5 | List augmentations that can be unlocked soon, sorted by least reputation required. 6 | Optionally work to unlock them. 7 | 8 | Usage: 9 | run /augmentations/unlock.js [ hacking | charisma | combat | crime | faction | hacknet | bladeburner | all ... ] [ --begin ] 10 | 11 | */ 12 | 13 | import { DOMAINS, getAllAugmentations, averageValue } from "augmentations/info.js"; 14 | import { canPurchaseFrom } from "augmentations/buy.js"; 15 | 16 | const FLAGS = [ 17 | ['help', false], 18 | ['begin', false] 19 | ]; 20 | 21 | export function autocomplete(data, args) { 22 | data.flags(FLAGS); 23 | return Object.keys(DOMAINS); 24 | } 25 | 26 | /** @param {NS} ns **/ 27 | export async function main(ns) { 28 | ns.disableLog("sleep"); 29 | ns.clearLog(); 30 | 31 | const flags = ns.flags(FLAGS); 32 | let domains = flags._; 33 | if (domains.length == 0) { 34 | domains = ['all']; 35 | } 36 | 37 | if (flags.help) { 38 | ns.tprint([ 39 | 'List augmentations that can be unlocked soon, sorted by least reputation required. Optionally work to unlock them.', 40 | '', 41 | 'Usage: ', 42 | `> ${ns.getScriptName()} [ ${Object.keys(DOMAINS).join(' | ')} ... ] [ --begin ]`, 43 | '', 44 | 'Example: List all augmentations that increase combat or crime stats.', 45 | `> run ${ns.getScriptName()} combat crime`, 46 | '', 47 | 'Example: Work for all factions that will unlock hacking augmentations.', 48 | `> run ${ns.getScriptName()} hacking --begin`, 49 | ' ' 50 | ].join("\n")); 51 | return; 52 | } 53 | 54 | const futureAugs = getFutureAugs(ns, {domains}); 55 | const summary = [`Augmentation Unlocking Plan: ${domains.join(', ')}`]; 56 | for (const aug of futureAugs) { 57 | const faction = aug.neededFactions[0]; 58 | const rep = sprintf("%+12s", ns.nFormat(faction.repNeeded, '0,0')); 59 | const value = averageValue(aug, domains).toFixed(2); 60 | summary.push(`${rep} more rep with ${faction.name} for '${aug.name}' (${value}x)`); 61 | } 62 | ns.print(summary.join("\n"), "\n"); 63 | 64 | if (flags.begin) { 65 | await unlockAugs(ns, domains); 66 | } 67 | else { 68 | ns.tail(); 69 | } 70 | } 71 | 72 | export async function unlockAugs(ns, domains) { 73 | let futureAugs = getFutureAugs(ns, {domains, requireWorkable: true}); 74 | while (futureAugs.length > 0) { 75 | const aug = futureAugs[0]; 76 | const faction = aug.canWorkNow; 77 | const player = ns.getPlayer(); 78 | if (player.isWorking && player.workType !== "Working for Faction") { 79 | ns.tprint(`Not starting faction work because player is already ${player.workType}.`); 80 | return; 81 | } 82 | for (const workType of getWorkTypes(player)) { 83 | if (ns.workForFaction(faction.name, workType, false)) { 84 | break; 85 | } 86 | } 87 | await ns.sleep(60*1000); 88 | if (!ns.getPlayer().isWorking) { 89 | // Support manually exiting the process. 90 | return; 91 | } 92 | futureAugs = getFutureAugs(ns, {domains, requireWorkable: true}); 93 | } 94 | } 95 | 96 | export function getFutureAugs(ns, {domains, requireWorkable}) { 97 | const allAugs = Object.values(getAllAugmentations(ns)); 98 | const ownedAugs = ns.singularity.getOwnedAugmentations(true); 99 | 100 | const futureAugs = allAugs.map(function(aug){ 101 | aug.canPurchaseFrom = canPurchaseFrom(ns, aug); 102 | aug.neededFactions = factionsToWork(aug); 103 | aug.canWorkNow = aug.neededFactions.filter((fac)=>canWorkForFaction(ns, fac.name))[0]; 104 | return aug; 105 | }).filter(function(aug){ 106 | return ( 107 | (!requireWorkable || aug.canWorkNow) && 108 | (!ownedAugs.includes(aug.name)) && 109 | (aug.neededFactions.length > 0) && 110 | (averageValue(aug, domains) > 1.0) 111 | ) 112 | }).map(function(aug){ 113 | aug.sortKey = averageValue(aug, domains) / aug.neededFactions[0].repNeeded; 114 | return aug; 115 | }).sort(function(a,b){ 116 | return b.sortKey - a.sortKey; 117 | }); 118 | 119 | return futureAugs; 120 | } 121 | 122 | export function factionsToWork(aug) { 123 | if (aug.canPurchaseFrom) { 124 | return []; 125 | }; 126 | const neededFactions = Object.entries(aug.factions).map(function([faction, [rep, repReq]]){ 127 | return { 128 | name: faction, 129 | rep: rep, 130 | repNeeded: aug.repReq - rep 131 | } 132 | }).filter(function(faction){ 133 | return (faction.repNeeded > 0) 134 | }).sort(function(a,b){ 135 | return (a.repNeeded - b.repNeeded) 136 | }); 137 | 138 | return neededFactions; 139 | } 140 | 141 | export function canWorkForFaction(ns, faction) { 142 | const specialFactions = ["Church of the Machine God", "Bladeburners"] 143 | if (ns.gang.inGang()) { 144 | specialFactions.push(ns.gang.getGangInformation().faction); 145 | } 146 | if (specialFactions.includes(faction)) { 147 | return false; 148 | } 149 | return ns.getPlayer().factions.includes(faction); 150 | } 151 | 152 | export function getWorkTypes(player) { 153 | if (player.hacking > player.strength) { 154 | return ["hacking contracts", "field work", "security"]; 155 | } 156 | else { 157 | return ["field work", "security", "hacking contracts"]; 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /batch/README.md: -------------------------------------------------------------------------------- 1 | ## Bitburner batch scripts 2 | 3 | Scripts for running batches of hack/weaken/grow/weaken attacks against Bitburner servers. 4 | 5 | This has mostly been supplanted by the [hacking](../hacking/) folder. 6 | 7 | ----- 8 | 9 | ### `manage.js` 10 | 11 | Daemon which attacks the most profitable targets. 12 | 13 | Can optionally specify individual targets on CLI. 14 | 15 | #### CLI Usage: 16 | ```bash 17 | # automatically select targets 18 | > run /batch/manage.js 19 | 20 | # specify any number of targets 21 | > run /batch/manage.js ecorp foodnstuff 22 | ``` 23 | -------------------------------------------------------------------------------- /batch/manage.js: -------------------------------------------------------------------------------- 1 | import { ServerPool } from "/net/deploy-script"; 2 | import { HackPlanner, HackableServer } from "/hacking/planner"; 3 | 4 | /* 5 | 6 | batch-based hacking using a pool of hosts 7 | 8 | list all usable hosts 9 | calculate total number of 1.75gb RAM slots 10 | skip hacknet servers and home server 11 | identify most profitable targets 12 | for each target: 13 | schedule a net-positive HWGW batch that will fit in available RAM 14 | allocate each job to one or more hosts when needed 15 | 16 | */ 17 | 18 | 19 | const FLAGS = [ 20 | ["help", false], 21 | ["tDelta", 100], 22 | ["moneyPercent", 0.05], 23 | ["reserveRam", false] 24 | ]; 25 | 26 | export function autocomplete(data, args) { 27 | data.flags(FLAGS); 28 | return data.servers; 29 | } 30 | 31 | /** @param {NS} ns **/ 32 | export async function main(ns) { 33 | ns.disableLog("scan"); 34 | ns.disableLog("asleep"); 35 | ns.disableLog("exec"); 36 | ns.disableLog("scp"); 37 | ns.clearLog(); 38 | // ns.tail(); 39 | 40 | const flags = ns.flags(FLAGS); 41 | flags.ns = ns; 42 | if (flags.help) { 43 | ns.tprint("This script manages batches of hack/weaken/grow/weaken cycles against multiple target servers."); 44 | ns.tprint(`Usage: run ${ns.getScriptName()} [target...]`); 45 | ns.tprint(`Exmaple: run ${ns.getScriptName()} ecorp foodnstuff`); 46 | return; 47 | } 48 | if (flags._.length > 0) { 49 | flags.targets = flags._; 50 | delete flags._; 51 | } 52 | 53 | const serverPool = new ServerPool(ns, {logLevel: 4, logFunc: ns.print}); 54 | while (true) { 55 | await runMultiHWGW({...flags, serverPool}); 56 | await ns.asleep(getNextBatchDelay()); 57 | } 58 | } 59 | 60 | const t0_by_target = {}; 61 | const next_start_by_target = {}; 62 | const SCRIPT_RAM = 1.75; 63 | 64 | function getNextBatchDelay() { 65 | let earliestStart = Infinity; 66 | for (const startTime of Object.values(next_start_by_target)) { 67 | if (startTime < earliestStart) { 68 | earliestStart = startTime; 69 | } 70 | } 71 | return earliestStart - performance.now() - 100; 72 | } 73 | 74 | export async function runMultiHWGW(params) { 75 | let {ns, serverPool, targets} = params; 76 | 77 | if (targets === undefined) { 78 | // continually recalculate most profitable targets 79 | const hackPlanner = new HackPlanner(ns); 80 | targets = hackPlanner.mostProfitableServers(params).map((plan)=>plan.server.hostname).slice(0,8); 81 | } 82 | 83 | serverPool.threadsUsed = 0; 84 | for (const target of targets) { 85 | if (serverPool.threadsUsed > serverPool.totalThreadsAvailable(SCRIPT_RAM) * 0.9) { 86 | break; 87 | } 88 | serverPool.threadsUsed += await runHWGW({...params, target}); 89 | } 90 | } 91 | 92 | let batchID = 0; 93 | export async function runHWGW(params) { 94 | const {ns, target, tDelta, serverPool} = params; 95 | const server = new HackableServer(ns, target); 96 | batchID++; 97 | 98 | if (t0_by_target[target] === undefined) { 99 | const batch = server.planPrepBatch(params); 100 | const scripts = convertToScripts({batchID}); 101 | await serverPool.deployBatch(scripts); 102 | t0_by_target[target] = performance.now() + scripts.totalDuration(tDelta); 103 | return batch.peakThreads(); 104 | } 105 | const t0 = t0_by_target[target]; 106 | 107 | const batch = server.planHackingBatch(params); 108 | batch.setFirstEndTime(t0, tDelta); 109 | adjustSchedule(batch); 110 | 111 | const scripts = batch.convertToScripts({batchID}); 112 | await serverPool.deployBatch(scripts); 113 | t0_by_target[target] = scripts.lastEndTime() + tDelta; 114 | next_start_by_target[target] = scripts.earliestStartTime() + 5 * tDelta; 115 | 116 | const threadsUsed = batch.peakThreads(); 117 | return threadsUsed; 118 | } 119 | 120 | function adjustSchedule(jobs=[]) { 121 | let earliestStartTime = Infinity; 122 | for (const job of jobs) { 123 | if (job.startTime !== undefined && job.startTime < earliestStartTime) { 124 | earliestStartTime = job.startTime; 125 | } 126 | else if (job.args?.includes('--startTime') && job.args[job.args.indexOf('--startTime')+1] < earliestStartTime) { 127 | earliestStartTime = job.args[job.args.indexOf('--startTime')+1]; 128 | } 129 | } 130 | 131 | // If planned start time was in the past, shift entire batch to future 132 | // and update times in-place. 133 | let startTimeAdjustment = performance.now() - earliestStartTime; 134 | if (startTimeAdjustment > 0) { 135 | startTimeAdjustment += 100; 136 | console.log(`Adjusting start time by ${startTimeAdjustment}`); 137 | for (const job of jobs) { 138 | if ('startTime' in job) { 139 | job.startTime += startTimeAdjustment; 140 | } 141 | if ('endTime' in job) { 142 | job.endTime += startTimeAdjustment; 143 | } 144 | if (job.args?.includes('--startTime')) { 145 | job.args[job.args.indexOf('--startTime')+1] += startTimeAdjustment; 146 | } 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /batch/prep.js: -------------------------------------------------------------------------------- 1 | import { ServerPool } from "/net/deploy-script"; 2 | import { HackPlanner, HackableServer } from "/hacking/planner"; 3 | 4 | const FLAGS = [ 5 | ["help", false], 6 | ["tDelta", 1000], 7 | ["reserveRam", true], 8 | ["verbose", false] 9 | ]; 10 | 11 | export function autocomplete(data, args) { 12 | data.flags(FLAGS); 13 | return data.servers; 14 | } 15 | 16 | /** @param {NS} ns **/ 17 | export async function main(ns) { 18 | ns.disableLog("scan"); 19 | ns.disableLog("asleep"); 20 | ns.disableLog("exec"); 21 | ns.disableLog("scp"); 22 | ns.clearLog(); 23 | 24 | const args = ns.flags(FLAGS); 25 | args.ns = ns; 26 | if (args.help) { 27 | ns.tprint([ 28 | "Prepare servers for hacking.", "", 29 | `Usage: run ${ns.getScriptName()} [target...]`, "", 30 | `Exmaple: run ${ns.getScriptName()} ecorp foodnstuff`, " " 31 | ].join("\n")); 32 | return; 33 | } 34 | 35 | for (const target of args._) { 36 | await runPrep({...args, target}); 37 | } 38 | await ns.asleep(1*1000); 39 | } 40 | 41 | export async function runPrep(params) { 42 | const {ns, target, tDelta} = params; 43 | const server = new HackableServer(ns, target); 44 | 45 | const batch = server.planPrepBatch(params); 46 | batch.setStartTime(performance.now() + 100, tDelta); 47 | batch.setAdditionalMsec(); 48 | ns.tprint(`batch: ${batch.longSummary()}`); 49 | const scripts = batch.convertToScripts({...params, batchID:0, repeatPeriod:0}); 50 | 51 | const serverPool = new ServerPool(ns, {logLevel: 4, logFunc: ns.print}); 52 | const processes = await serverPool.deployBatch(scripts); 53 | Object.assign(globalThis, {batch, scripts}); 54 | return scripts; 55 | } 56 | -------------------------------------------------------------------------------- /bladeburner/actions.ns: -------------------------------------------------------------------------------- 1 | export async function main(ns) { 2 | ns.disableLog("sleep"); 3 | while (true) { 4 | await startBestAction(ns); 5 | await ns.sleep(60*1000); 6 | } 7 | } 8 | 9 | export function startBestAction(ns) { 10 | if (ns.isBusy() && !ns.getOwnedAugmentations().includes("The Blade's Simulacrum")) { 11 | return; 12 | } 13 | const action = selectAction(ns); 14 | const currentAction = ns.bladeburner.getCurrentAction(); 15 | if (currentAction.name == action.name) { 16 | return; 17 | } 18 | ns.bladeburner.startAction(action.type, action.name); 19 | } 20 | 21 | export function selectAction(ns) { 22 | const stamina = ns.bladeburner.getStamina(); 23 | const percentage = stamina[0] / stamina[1]; 24 | if (percentage < 0.6) { 25 | ns.print("Selected regeneration"); 26 | return { 27 | type: "general", 28 | name: "Hyperbolic Regeneration Chamber" 29 | }; 30 | } 31 | 32 | let city = ns.bladeburner.getCity(); 33 | if (ns.bladeburner.getCityChaos(city) > 100 || 34 | ns.bladeburner.getCityEstimatedPopulation(city) < 1 || 35 | ns.bladeburner.getCityCommunities(city) < 1) { 36 | city = randomCity(); 37 | ns.bladeburner.switchCity(city); 38 | } 39 | 40 | const actionTypes = { 41 | "blackop": ns.bladeburner.getBlackOpNames(), // lowest rank first 42 | "operation": ns.bladeburner.getOperationNames().reverse(), // highest rank first 43 | "contract": ns.bladeburner.getContractNames().reverse(), // highest rank first 44 | //"general": ns.bladeburner.getGeneralActionNames() // "Training" first 45 | }; 46 | const actions = []; 47 | for (const actionType in actionTypes) { 48 | for (const name of actionTypes[actionType]) { 49 | actions.push({ 50 | type: actionType, 51 | name: name, 52 | chance: ns.bladeburner.getActionEstimatedSuccessChance(actionType, name), 53 | count: ns.bladeburner.getActionCountRemaining(actionType, name) 54 | }); 55 | } 56 | } 57 | let blackopSeen = false; 58 | const viableActions = actions.filter((a)=> { 59 | if (a.type == "blackop") { 60 | if (a.name == "Operation Daedalus") { 61 | return false; 62 | } 63 | if (blackopSeen) { 64 | return false; 65 | } 66 | if (ns.bladeburner.getBlackOpRank(a.name) <= ns.bladeburner.getRank() && a.count > 0) { 67 | blackopSeen = true; 68 | return (a.chance[1] > 0.99); 69 | } 70 | } 71 | else if (a.name == "Raid") { 72 | return false; 73 | } 74 | else { 75 | return (a.count > 5 && a.chance[1] > 0.99); 76 | } 77 | }); 78 | if (viableActions.length > 0) { 79 | const action = viableActions[0]; 80 | ns.print(`Selected action: ${JSON.stringify(action)}`); 81 | return action; 82 | } 83 | if (ns.bladeburner.getCityChaos(city) > 10) { 84 | return { 85 | type: "general", 86 | name: "Diplomacy" 87 | }; 88 | } 89 | //ns.print("Selected training"); 90 | return { 91 | type: "general", 92 | name: "Training" 93 | }; 94 | } 95 | 96 | function takeRandom(items) { 97 | return items[Math.floor(Math.random()*items.length)]; 98 | } 99 | 100 | function randomCity() { 101 | return takeRandom([ 102 | "Sector-12", 103 | "Aevum", 104 | "Volhaven", 105 | "Ishima", 106 | "New Tokyo", 107 | "Chongqing" 108 | ]); 109 | } 110 | -------------------------------------------------------------------------------- /bladeburner/init.ns: -------------------------------------------------------------------------------- 1 | export async function main(ns) { 2 | if (ns.bladeburner.joinBladeburnerDivision()) { 3 | ns.spawn('/bladeburner/progress.ns', 1); 4 | } 5 | } -------------------------------------------------------------------------------- /bladeburner/progress.ns: -------------------------------------------------------------------------------- 1 | import {upgradeSkills} from "/bladeburner/skills.ns"; 2 | import {startBestAction} from "/bladeburner/actions.ns"; 3 | 4 | export async function main(ns) { 5 | if (ns.bladeburner.joinBladeburnerDivision()) { 6 | ns.disableLog("sleep"); 7 | while (true) { 8 | await upgradeSkills(ns); 9 | await startBestAction(ns); 10 | await ns.sleep(60*1000); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /bladeburner/skills.ns: -------------------------------------------------------------------------------- 1 | export async function main(ns) { 2 | ns.disableLog("sleep"); 3 | while (true) { 4 | await upgradeSkills(ns); 5 | await ns.sleep(60*1000); 6 | } 7 | } 8 | 9 | export async function upgradeSkills(ns) { 10 | while (upgradeSkill(ns)) { 11 | await ns.sleep(100); 12 | } 13 | } 14 | 15 | export function upgradeSkill(ns) { 16 | const skillPriorities = { 17 | "Overclock": 1, 18 | "Evasive System": 3, 19 | "Reaper": 4, 20 | "Blade's Intuition": 3, 21 | "Digital Observer": 4, 22 | "Short-Circuit": 6, 23 | "Cloak": 10, 24 | "Tracer": 12, 25 | }; 26 | if (ns.bladeburner.getRank() < 20000 || 27 | ns.bladeburner.getSkillLevel("Overclock") >= 90) { 28 | delete skillPriorities.Overclock; 29 | } 30 | const firstSkills = Object.keys(skillPriorities).filter((name)=>{ 31 | return ns.bladeburner.getSkillUpgradeCost(name) <= ns.bladeburner.getSkillPoints(); 32 | }).sort((a,b)=>{ 33 | const va = ns.bladeburner.getSkillUpgradeCost(a) * skillPriorities[a]; 34 | const vb = ns.bladeburner.getSkillUpgradeCost(b) * skillPriorities[b]; 35 | return va - vb; 36 | }); 37 | if (firstSkills.length > 0) { 38 | return ns.bladeburner.upgradeSkill(firstSkills[0]); 39 | } 40 | return false; 41 | } -------------------------------------------------------------------------------- /botnet/README.md: -------------------------------------------------------------------------------- 1 | ## HVMind Distributed Computing System 2 | 3 | **Deprecation notice: This system depended on the ability to write arbitrary objects to NetScript ports, which is no longer supported.** 4 | 5 | ### ThreadPool 6 | 7 | [ThreadPool](thread-pool.js) is a [grid computing](https://en.wikipedia.org/wiki/Grid_computing) system that dispatches jobs to long-lived worker processes running in the cloud. 8 | 9 | The system is controlled through a `ThreadPool` process which communicates with `Worker` processes through a [Netscript Port](https://bitburner.readthedocs.io/en/latest/netscript/netscriptmisc.html#netscript-ports). The processes can connect to each other after being launched in any order, including reloading from save. 10 | 11 | An application can dispatch tasks to the `ThreadPool` and it will launch an appropriate size `Worker` on any available server (using [ServerPool](../net/deploy-script.js)), or assign the task to an already running `Worker`. 12 | 13 | ![System Diagram](system-diagram.svg) 14 | 15 | 16 | #### ThreadPool API 17 | 18 | Applications can run jobs by calling `threadPool.dispatchJob(job)`, where a job is an object defining the `task`. For example: 19 | 20 | ```JavaScript 21 | { 22 | task: 'hack', // a key in worker.capabilities 23 | args: ['foodnstuff'], 24 | threads: 5, 25 | duration: 1000, // optional 26 | startTime: 1649093514728, // optional (will start immediately if omitted) 27 | endTime: 1649093515728 // optional 28 | } 29 | ``` 30 | 31 | When the job runs, this object will be updated with `startTimeActual` and `endTimeActual`. Other fields will be preserved, so a user can record expectations here and compare them against results. 32 | 33 | To run multiple jobs at once, call `threadPool.dispatchJobs(batch)`. This will return a falsey value if the entire batch cannot be run. This will update each job’s `startTime` and `endTime` 34 | 35 | 36 | 37 | #### ThreadPool Command-Line Interface 38 | 39 | Start the thread pool: 40 | ``` 41 | > run /botnet/thread-pool.js --tail 42 | ``` 43 | 44 | Run an application on the pool: 45 | ``` 46 | > run /hacking/manager.js foodnstuff 47 | ``` 48 | 49 | -------------------------------------------------------------------------------- /botnet/prep.js: -------------------------------------------------------------------------------- 1 | import { getThreadPool } from "/botnet/worker"; 2 | import { HackableServer } from "/hacking/planner"; 3 | 4 | const FLAGS = [ 5 | ["help", false], 6 | ["backendPort", 3], // default port for ThreadPool 7 | ["tDelta", 100], // milliseconds between effects 8 | ["maxTotalRam", 0], // optional (will be read from backend) 9 | ["maxThreadsPerJob", 0], // optional (will be read from backend) 10 | ["reserveRam", true], // whether to calculate batch RAM requirement based on peak amount 11 | ["secMargin", 0.5], // how much security level to allow between "grow" operations 12 | ["naiveSplit", false], // whether to split large jobs based solely on thread count 13 | ["cores", 1], // not currently used 14 | ]; 15 | 16 | export function autocomplete(data, args) { 17 | data.flags(FLAGS); 18 | return data.servers; 19 | } 20 | 21 | /** @param {NS} ns **/ 22 | export async function main(ns) { 23 | ns.disableLog('scan'); 24 | ns.disableLog('asleep'); 25 | ns.clearLog(); 26 | const flags = ns.flags(FLAGS); 27 | if (flags.help) { 28 | ns.tprint("Prepare a server for hacking.") 29 | return; 30 | } 31 | delete flags.help; 32 | 33 | const backend = await getThreadPool(ns, flags.backendPort); 34 | delete flags.backendPort; 35 | 36 | flags.maxTotalRam ||= backend.getMaxTotalRam(); 37 | flags.maxThreadsPerJob ||= backend.getMaxThreadsPerJob(); 38 | 39 | const targets = flags._; 40 | delete flags._; 41 | 42 | const manager = new PrepManager(ns, backend, targets, flags) 43 | await manager.work(); 44 | } 45 | 46 | export class PrepManager { 47 | constructor(ns, backend, targets=[], params={}) { 48 | this.ns = ns; 49 | this.backend = backend; 50 | this.params = params; 51 | 52 | this.targets = targets.map((hostname)=>( 53 | new HackableServer(ns, hostname) 54 | )); 55 | } 56 | 57 | async work() { 58 | const {ns, targets} = this; 59 | 60 | for (const target of this.targets) { 61 | await this.prepTarget(target); 62 | } 63 | } 64 | 65 | async prepTarget(server) { 66 | const {ns, params} = this; 67 | const now = performance.now() + params.tDelta; 68 | 69 | // TODO: investigate infinite loop in this program when very little RAM is available. it is happening in 'manager.js' too. 70 | 71 | const prepBatch = server.planPrepBatch(this.params); 72 | prepBatch.setStartTime(now); 73 | 74 | for (const job of prepBatch) { 75 | let result = await this.backend.dispatchJob(job); // TODO: confirm that this job can be added to an existing queue 76 | while (!result) { 77 | await ns.asleep(1000); 78 | let result = await this.backend.dispatchJob(job); 79 | } 80 | } 81 | if (prepBatch.length > 0) { 82 | server.nextStartTime = prepBatch.lastEndTime(); 83 | await ns.asleep(prepBatch.lastEndTime() - performance.now()); 84 | } 85 | ns.tprint(`INFO: ${server.hostname} is prepared for hacking.`); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /botnet/stop.js: -------------------------------------------------------------------------------- 1 | import { getThreadPool } from "/botnet/worker"; 2 | 3 | const FLAGS = [ 4 | ["port", 3], 5 | ["force", false] 6 | ]; 7 | 8 | /** @param {NS} ns **/ 9 | export async function main(ns) { 10 | ns.disableLog("asleep"); 11 | const flags = ns.flags(FLAGS) 12 | await stopWorkers(ns, flags.port, flags.force); 13 | } 14 | 15 | export async function stopWorkers(ns, portNum, force) { 16 | const threadPool = await getThreadPool(ns, portNum) || {workers:[]}; 17 | 18 | // gracefully stop the thread pool 19 | threadPool.running = false; 20 | 21 | // gracefully stop all workers 22 | for (const worker of Object.values(threadPool.workers)) { 23 | worker.running = false; 24 | } 25 | 26 | if (force) { 27 | // terminate the pool 28 | await ns.asleep(2000); 29 | if (threadPool?.process?.pid) { 30 | ns.kill(threadPool.process.pid); 31 | } 32 | 33 | // terminate remaining workers 34 | await ns.asleep(1000); 35 | for (const worker of Object.values(threadPool.workers)) { 36 | if (worker?.process?.pid) { 37 | ns.kill(worker.process.pid); 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /botnet/worker-grow.js: -------------------------------------------------------------------------------- 1 | import { Worker } from "/botnet/worker"; 2 | 3 | /** @param {NS} ns **/ 4 | export async function main(ns) { 5 | // List the functions this worker is capable of, for static RAM calculation. 6 | const capabilities = { 7 | "grow": ns.grow 8 | } 9 | const worker = new Worker(ns, capabilities); 10 | await worker.work(); 11 | } 12 | -------------------------------------------------------------------------------- /botnet/worker-hack.js: -------------------------------------------------------------------------------- 1 | import { Worker } from "/botnet/worker"; 2 | 3 | /** @param {NS} ns **/ 4 | export async function main(ns) { 5 | // List the functions this worker is capable of, for static RAM calculation. 6 | const capabilities = { 7 | "hack": ns.hack 8 | } 9 | const worker = new Worker(ns, capabilities); 10 | await worker.work(); 11 | } 12 | -------------------------------------------------------------------------------- /botnet/worker-weaken.js: -------------------------------------------------------------------------------- 1 | import { Worker } from "/botnet/worker"; 2 | 3 | /** @param {NS} ns **/ 4 | export async function main(ns) { 5 | // List the functions this worker is capable of, for static RAM calculation. 6 | const capabilities = { 7 | "weaken": ns.weaken 8 | } 9 | const worker = new Worker(ns, capabilities); 10 | await worker.work(); 11 | } 12 | -------------------------------------------------------------------------------- /contracts/find-and-solve.js: -------------------------------------------------------------------------------- 1 | import {solvers} from "contracts/solvers.js"; 2 | 3 | export async function main(ns) { 4 | ns.disableLog("scan"); 5 | ns.disableLog("sleep"); 6 | while (true) { 7 | await attemptAllContracts(ns); 8 | await ns.sleep(60*1000); 9 | } 10 | } 11 | 12 | export async function attemptAllContracts(ns) { 13 | const contracts = getContracts(ns); 14 | ns.print(`Found ${contracts.length} contracts.`); 15 | for (const contract of contracts) { 16 | await attemptContract(ns, contract); 17 | } 18 | } 19 | 20 | export function getContracts(ns) { 21 | const contracts = []; 22 | for (const host of getAllHosts(ns)) { 23 | for (const file of ns.ls(host)) { 24 | if (file.match(/\.cct$/)) { 25 | const contract = { 26 | host: host, 27 | file: file, 28 | type: ns.codingcontract.getContractType(file, host), 29 | triesRemaining: ns.codingcontract.getNumTriesRemaining(file, host) 30 | }; 31 | contracts.push(contract); 32 | } 33 | } 34 | } 35 | return contracts; 36 | } 37 | 38 | export async function attemptContract(ns, contract) { 39 | const solver = solvers[contract.type]; 40 | if (solver) { 41 | ns.print("Attempting " +JSON.stringify(contract,null,2)); 42 | const data = ns.codingcontract.getData(contract.file, contract.host); 43 | try { 44 | const solution = await runInWebWorker(solver, [data]); 45 | const reward = ns.codingcontract.attempt(solution, contract.file, contract.host, {returnReward:true}); 46 | if (reward) { 47 | ns.tprint(`${reward} for solving "${contract.type}" on ${contract.host}`); 48 | ns.print(`${reward} for solving "${contract.type}" on ${contract.host}`); 49 | } 50 | else { 51 | ns.tprint(`ERROR: Failed to solve "${contract.type}" on ${contract.host}`); 52 | delete solvers[contract.type]; 53 | } 54 | } 55 | catch (error) { 56 | ns.print(`ERROR solving ${contract.type}: ${error}`); 57 | } 58 | } 59 | else { 60 | ns.print(`WARNING: No solver for "${contract.type}" on ${contract.host}`); 61 | } 62 | } 63 | 64 | function getAllHosts(ns) { 65 | getAllHosts.cache ||= {}; 66 | const scanned = getAllHosts.cache; 67 | const toScan = ['home']; 68 | while (toScan.length > 0) { 69 | const host = toScan.shift(); 70 | scanned[host] = true; 71 | for (const nextHost of ns.scan(host)) { 72 | if (!(nextHost in scanned)) { 73 | toScan.push(nextHost); 74 | } 75 | } 76 | } 77 | const allHosts = Object.keys(scanned); 78 | return allHosts; 79 | } 80 | 81 | async function runInWebWorker(fn, args, maxMs=1000) { 82 | return new Promise((resolve, reject)=>{ 83 | let running = true; 84 | const worker = makeWorker(fn, (result)=>{ 85 | running = false; 86 | resolve(result); 87 | }); 88 | setTimeout(()=>{ 89 | if (running) { 90 | reject(`${maxMs} ms elapsed.`); 91 | } 92 | worker.terminate(); 93 | }, maxMs); 94 | worker.postMessage(args); 95 | }); 96 | } 97 | 98 | function makeWorker(workerFunction, cb) { 99 | const workerSrc = ` 100 | handler = (${workerFunction}); 101 | onmessage = (e) => { 102 | result = handler.apply(this, e.data); 103 | postMessage(result); 104 | };`; 105 | const workerBlob = new Blob([workerSrc]); 106 | const workerBlobURL = URL.createObjectURL(workerBlob, { type: 'application/javascript; charset=utf-8' }); 107 | const worker = new Worker(workerBlobURL); 108 | worker.onmessage = (e)=>{ 109 | cb(e.data); 110 | }; 111 | return worker; 112 | } 113 | -------------------------------------------------------------------------------- /corporation/buyback-shares.js: -------------------------------------------------------------------------------- 1 | export async function main(ns) { 2 | const player = ns.getPlayer(); 3 | if (player.hasCorporation) { 4 | const corpAPI = eval("ns.corporation"); 5 | const corp = corpAPI.getCorporation(); 6 | if (corp.public) { 7 | if (corp.issuedShares > 0) { 8 | const buybackPrice = corp.sharePrice * 1.1; 9 | const buybackMoney = Math.min(player.money, corp.issuedShares * buybackPrice); 10 | const numShares = buybackMoney / buybackPrice; 11 | corpAPI.buyBackShares(numShares); 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /corporation/init.js: -------------------------------------------------------------------------------- 1 | export async function main(ns) { 2 | const player = ns.getPlayer(); 3 | if (player.hasCorporation) { 4 | const corpAPI = eval("ns.corporation"); 5 | const corp = corpAPI.getCorporation(); 6 | // use a public corporation as a piggy bank: 7 | if (corp.public) { 8 | // sell some shares when they amount to more cash than we have on hand 9 | if (corp.shareSaleCooldown <= 0 && corp.sharePrice * 1e7 > player.money) { 10 | corpAPI.sellShares(1e7); 11 | } 12 | // buyback shares when we can. 13 | else if (corp.issuedShares > 0) { 14 | const buybackPrice = corp.sharePrice * 1.1; 15 | if (player.money > (corp.issuedShares * buybackPrice) * 2) { 16 | corpAPI.buyBackShares(corp.issuedShares); 17 | } 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /exploit/bypass.ns: -------------------------------------------------------------------------------- 1 | export async function main(ns) { 2 | let doc = eval("document"); 3 | // ns.tprint("args: "+ns.args); 4 | // let doc = ns.args[0]; 5 | ns.bypass(doc); 6 | ns.tprint(doc); 7 | } -------------------------------------------------------------------------------- /exploit/console.js: -------------------------------------------------------------------------------- 1 | export async function beeper(ns, value) { 2 | while (true) { 3 | ns.tprint("beep "+value); 4 | await ns.sleep(1000); 5 | } 6 | } 7 | 8 | export async function delayedAction(ns) { 9 | await ns.sleep(2000); 10 | ns.tprint("delayed action now"); 11 | } 12 | 13 | export async function main(ns) { 14 | window.ns = ns; 15 | await ns.asleep(60*60*1000); 16 | //document.$hacknet = ns.hacknet; 17 | return; 18 | // ns.tprint(ns.getBitNodeMultipliers()); 19 | // ns.tprint(ns.getServerMaxMoney('pserv-1')); 20 | // ns.run("exploit.ns", 1, document); 21 | // ns.tprint(ns.heart.break()); 22 | // 23 | // delayedAction(ns); 24 | // let result = beeper(ns, 1); 25 | // ns.tprint(result); 26 | // await ns.sleep(500); 27 | // beeper(ns, 2); 28 | // await ns.sleep(5000); 29 | } 30 | -------------------------------------------------------------------------------- /exploit/dev-menu.js: -------------------------------------------------------------------------------- 1 | /** @param {NS} ns **/ 2 | export async function main(ns) { 3 | Object.entries(eval("document").getElementsByClassName("jss3 MuiBox-root")[0]) 4 | .find(x => x[0].startsWith("__reactProps"))[1].children.props.router.toDevMenu(); 5 | } 6 | -------------------------------------------------------------------------------- /exploit/embed_player.py: -------------------------------------------------------------------------------- 1 | import base64 2 | import json 3 | from pathlib import Path 4 | import argparse 5 | 6 | 7 | def main(): 8 | parser = argparse.ArgumentParser() 9 | parser.add_argument('save_path', type=Path, nargs='?', default='bitburnerSave.json') 10 | parser.add_argument('player_path', type=Path, nargs='?', default='decodedPlayer.json') 11 | args = parser.parse_args() 12 | 13 | with args.save_path.open() as f: 14 | b64_data = f.read() 15 | 16 | json_data = base64.b64decode(b64_data) 17 | dict_data = json.loads(json_data) 18 | save_data = dict_data['data'] 19 | PlayerSave = json.loads(save_data['PlayerSave']) 20 | 21 | with args.player_path.open('r') as f: 22 | PlayerSave = json.load(f) 23 | 24 | save_data['PlayerSave'] = json.dumps(PlayerSave) 25 | dict_data['data'] = save_data 26 | json_data = json.dumps(dict_data).encode('ascii') 27 | b64_data = base64.b64encode(json_data).decode('ascii') 28 | 29 | output_path = args.save_path.with_name(args.save_path.stem + '-edited.json') 30 | with output_path.open('w') as f: 31 | f.write(b64_data) 32 | 33 | 34 | if __name__ == "__main__": 35 | main() 36 | -------------------------------------------------------------------------------- /exploit/exploit.ns: -------------------------------------------------------------------------------- 1 | export async function main(ns) { 2 | let doc = document; 3 | ns.run("bypass.ns", 1, doc); 4 | 5 | let ucEl = doc.getElementById('unclickable'); 6 | 7 | const nativeGetComputedStyle = window.getComputedStyle; 8 | window.getComputedStyle = function(el, pel){ 9 | if (el === ucEl) { 10 | return {display: 'none'}; 11 | } 12 | else { 13 | return nativeGetComputedStyle(el, pel); 14 | } 15 | }; 16 | 17 | ucEl.style.display = 'block'; 18 | ucEl.style.position = 'fixed'; 19 | ucEl.addEventListener(function(event){ 20 | window.getComputedStyle = nativeGetComputedStyle; 21 | event.target.style.display = 'none'; 22 | }); 23 | } -------------------------------------------------------------------------------- /exploit/extract_player.py: -------------------------------------------------------------------------------- 1 | import base64 2 | import json 3 | from pathlib import Path 4 | import argparse 5 | 6 | 7 | def main(): 8 | parser = argparse.ArgumentParser() 9 | parser.add_argument('save_path', type=Path, nargs='?', default='bitburnerSave.json') 10 | parser.add_argument('player_path', type=Path, nargs='?', default='decodedPlayer.json') 11 | args = parser.parse_args() 12 | 13 | with args.save_path.open() as f: 14 | b64_data = f.read() 15 | 16 | json_data = base64.b64decode(b64_data) 17 | dict_data = json.loads(json_data) 18 | save_data = dict_data['data'] 19 | PlayerSave = json.loads(save_data['PlayerSave']) 20 | 21 | with args.player_path.open('w') as f: 22 | json.dump(PlayerSave, f, indent=2) 23 | 24 | 25 | if __name__ == "__main__": 26 | main() 27 | -------------------------------------------------------------------------------- /exploit/hax.script: -------------------------------------------------------------------------------- 1 | c = 'constructor' 2 | f = [c][c][c] 3 | 4 | alert = f('str','alert(str)') 5 | 6 | alert('hello') -------------------------------------------------------------------------------- /exploit/printHTML.js: -------------------------------------------------------------------------------- 1 | export async function main(ns) { 2 | ns.disableLog("asleep"); 3 | const svgEl = render(template); 4 | logHTML(ns, svgEl); 5 | 6 | await ns.asleep(1000); 7 | for (let i=0; i < 100; i++) { 8 | await ns.asleep(100); 9 | setValues(svgEl, {circ: Math.random()*100}); 10 | svgEl.appendChild(render(` 11 | 12 | `)) 13 | } 14 | await ns.asleep(60*1000); 15 | } 16 | 17 | const template = ` 18 | 21 | 22 | 23 | 24 | 25 | 26 | SVG 27 | 28 | 29 | `; 30 | 31 | const template2 = ``; 32 | 33 | export function logHTML(ns, el) { 34 | ns.tail(); 35 | const doc = eval('document'); 36 | const command = ns.getScriptName() + ' ' + ns.args.join(' '); 37 | const logEl = doc.querySelector(`[title="${command}"]`).parentElement.nextElementSibling.querySelector('span'); 38 | logEl.appendChild(el); 39 | } 40 | 41 | export function render(template='', globals, locals) { 42 | const context = Object.assign({}, globals, locals); 43 | 44 | const doc = eval('document'); 45 | const container = doc.createElement('div'); 46 | const html = template.innerHTML || template; 47 | container.innerHTML = html.trim(); 48 | const el = container.firstChild; 49 | 50 | setValues(el, context); 51 | 52 | return el; 53 | } 54 | 55 | function setValues(el, context) { 56 | Object.keys(context).forEach(function(name){ 57 | const value = context[name]; 58 | const selector = '[name="'+name+'"]'; // e.g.: [name="team1_color"] 59 | for (const item of el.querySelectorAll(selector)) { 60 | setValue(item, value); 61 | } 62 | if (el.matches(selector)) { 63 | setValue(el, value); 64 | } 65 | }); 66 | } 67 | 68 | function setValue(el, value) { 69 | // TODO: consider supporting 'data-index' for compound values 70 | var target = el.getAttribute('data-target') || 'value'; 71 | if (target == 'value') { 72 | // when no 'data-target' is given, set the 'value' which varies by tag 73 | if (el.tagName == 'INPUT') { 74 | if (el.type == 'checkbox') { 75 | el.checked = !!value; 76 | } 77 | else { 78 | el.value = value; 79 | } 80 | } 81 | else { 82 | if ('textContent' in el) { 83 | el.textContent = value; 84 | } 85 | else { 86 | el.innerText = value; // IE8 support 87 | } 88 | } 89 | } 90 | else { 91 | var parts = target.split('.'); 92 | if (parts.length == 1) { 93 | // when some 'data-target' is given, set that attribute 94 | // e.g.: would run 95 | // el.width = value; 96 | el.setAttribute(target, value); 97 | } 98 | else { 99 | // but if 'data-target' has more than one part, drill down to set it 100 | // e.g.: would run 101 | // el.style.width = value; 102 | var cursor = el; 103 | while (parts.length > 1) { 104 | cursor = cursor[parts.shift()]; 105 | } 106 | cursor[parts[0]] = value; 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /exploit/select-next-bitnode.js: -------------------------------------------------------------------------------- 1 | export async function main(ns) { 2 | let bitnodeNumber = ns.args[0] || 12; 3 | let script = ns.args[1] || 'init.js'; 4 | 5 | setTimeout(()=>{ 6 | selectNextBitnode(bitnodeNumber, script); 7 | }, 0); 8 | } 9 | 10 | async function selectNextBitnode(n=12, script='init.js') { 11 | let button = await waitForElement(`[aria-label*="BitNode-${n}"`); 12 | button.click(); 13 | 14 | button = await waitForElement(`[aria-label*="enter-bitnode-${n}"`); 15 | button.click(); 16 | 17 | await sleep(1000); 18 | 19 | await runTerminalCommand(`run ${script}`); 20 | } 21 | 22 | async function waitForElement(selector) { 23 | const doc = eval("document"); 24 | let el = doc.querySelector(selector); 25 | while (!el) { 26 | await sleep(1000); 27 | el = doc.querySelector(selector); 28 | } 29 | return el; 30 | } 31 | 32 | function sleep(ms) { 33 | return new Promise((resolve) => setTimeout(resolve, ms)); 34 | } 35 | 36 | async function runTerminalCommand(command) { 37 | const terminalInput = await waitForElement('#terminal-input'); 38 | terminalInput.value = command; 39 | 40 | const handler = Object.keys(terminalInput)[1]; 41 | terminalInput[handler].onChange({target:terminalInput}); 42 | terminalInput[handler].onKeyDown({keyCode:13,preventDefault:()=>null}); 43 | terminalInput.dispatchEvent(new KeyboardEvent('keydown', { 44 | bubbles: true, cancelable: true, keyCode: 13 45 | })); 46 | terminalInput.dispatchEvent(new KeyboardEvent('keyup', { 47 | bubbles: true, cancelable: true, keyCode: 13 48 | })); 49 | } 50 | -------------------------------------------------------------------------------- /gang/ascend.js: -------------------------------------------------------------------------------- 1 | /** @param {NS} ns **/ 2 | export async function main(ns) { 3 | const growthFactor = ns.args[0]; 4 | 5 | for (const memberName of ns.gang.getMemberNames()) { 6 | const member = ns.gang.getMemberInformation(memberName); 7 | ascendIfReady(ns, member, growthFactor); 8 | } 9 | } 10 | 11 | export function ascendIfReady(ns, member, factor=2.0) { 12 | const ascResult = ns.gang.getAscensionResult(member.name); 13 | if (!ascResult) { 14 | return; 15 | } 16 | // TODO: check ascResult.respect 17 | const largestMult = Math.max(ascResult.hack, ascResult.str, ascResult.def, ascResult.dex, ascResult.agi, ascResult.cha); 18 | if (largestMult > factor) { 19 | ns.gang.ascendMember(member.name); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /gang/buy-augs.js: -------------------------------------------------------------------------------- 1 | /** @param {NS} ns **/ 2 | export async function main(ns) { 3 | if (!ns.gang.inGang()) { 4 | return; 5 | } 6 | buyAugsForAllMembers(ns); 7 | } 8 | 9 | export function buyAugsForAllMembers(ns) { 10 | for (const memberName of ns.gang.getMemberNames()) { 11 | buyAugs(ns, member); 12 | } 13 | } 14 | 15 | export function buyAugs(ns, member) { 16 | const player = ns.getPlayer(); 17 | const gang = ns.gang.getGangInformation(); 18 | for (const equip of getEquipments(ns)) { 19 | if (member.upgrades.includes(equip.name) || member.augmentations.includes(equip.name)) { 20 | continue; 21 | } 22 | let fundsFraction = 0.0001; 23 | if (equip.type == "Augmentation") { 24 | fundsFraction = 0.001; 25 | } 26 | else if ((equip.type == "Rootkit") != (gang.isHacking)) { 27 | fundsFraction = 0.00005; 28 | } 29 | if (equip.cost < player.money * fundsFraction) { 30 | ns.gang.purchaseEquipment(member.name, equip.name); 31 | } 32 | } 33 | } 34 | 35 | export function getEquipments(ns) { 36 | const equipments = ns.gang.getEquipmentNames().map(function(name){ 37 | return { 38 | name: name, 39 | type: ns.gang.getEquipmentType(name), 40 | cost: ns.gang.getEquipmentCost(name), 41 | stats: ns.gang.getEquipmentStats(name) 42 | } 43 | }); 44 | return equipments; 45 | } 46 | -------------------------------------------------------------------------------- /gang/info.js: -------------------------------------------------------------------------------- 1 | import { getEquipments } from "gang/buy-augs.js"; 2 | 3 | export function autocomplete(data, args) { 4 | return ["gang", "members", "otherGangs", "tasks", "equipments"]; 5 | } 6 | 7 | /** @param {NS} ns **/ 8 | export async function main(ns) { 9 | ns.clearLog(); 10 | ns.tail(); 11 | 12 | const gang = ns.gang.getGangInformation(); 13 | if (ns.args.includes("gang")) { 14 | ns.print(JSON.stringify(gang,null,2)); 15 | } 16 | if (ns.args.includes("members")) { 17 | for (const memberName of ns.gang.getMemberNames()) { 18 | const member = ns.gang.getMemberInformation(memberName); 19 | ns.print(JSON.stringify(member, null, 2)); 20 | } 21 | } 22 | if (ns.args.includes("otherGangs")) { 23 | ns.print(JSON.stringify(ns.gang.getOtherGangInformation(), null, 2)); 24 | } 25 | if (ns.args.includes("tasks")) { 26 | for (const taskName of ns.gang.getTaskNames()) { 27 | const task = ns.gang.getTaskStats(taskName); 28 | ns.print(JSON.stringify(task, null, 2)); 29 | } 30 | } 31 | if (ns.args.includes("equipments")) { 32 | for (const equipment of getEquipments(ns)) { 33 | ns.print(JSON.stringify(equipment, null, 2)) 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /gang/manage.js: -------------------------------------------------------------------------------- 1 | import { ascendIfReady } from "gang/ascend.js"; 2 | import { buyAugs } from "gang/buy-augs.js"; 3 | 4 | /** @param {NS} ns **/ 5 | export async function main(ns) { 6 | ns.disableLog("sleep"); 7 | 8 | if (!ns.gang.inGang()) { 9 | return; 10 | } 11 | 12 | while (true) { 13 | await updateMembers(ns); 14 | await ns.sleep(10*1000); 15 | updateTerritory(ns); 16 | } 17 | } 18 | 19 | async function updateMembers(ns) { 20 | if (ns.gang.canRecruitMember()) { 21 | ns.gang.recruitMember(makeid()); 22 | } 23 | for (const memberName of ns.gang.getMemberNames()) { 24 | const member = ns.gang.getMemberInformation(memberName); 25 | await ns.sleep(2500); 26 | updateMember(ns, member); 27 | } 28 | } 29 | 30 | function updateMember(ns, member) { 31 | const gang = ns.gang.getGangInformation(); 32 | 33 | ascendIfReady(ns, member, 3.0); 34 | 35 | buyAugs(ns, member); 36 | 37 | const wantedStats = { 38 | cha_exp: 1000, 39 | str_exp: (gang.isHacking ? 1000 : 10000), 40 | hack_exp: (gang.isHacking ? 10000 : 1000) 41 | }; 42 | 43 | if (member.cha_exp < wantedStats.cha_exp) { 44 | ns.gang.setMemberTask(member.name, "Train Charisma") 45 | } 46 | else if (member.hack_exp < wantedStats.hack_exp) { 47 | ns.gang.setMemberTask(member.name, "Train Hacking") 48 | } 49 | else if (member.str_exp < wantedStats.str_exp) { 50 | ns.gang.setMemberTask(member.name, "Train Combat") 51 | } 52 | else if (gang.wantedLevelGainRate > 0) { 53 | // gang.wantedPenalty < 0.95 54 | if (gang.isHacking && (member.hack > member.str)) { 55 | ns.gang.setMemberTask(member.name, "Ethical Hacking"); 56 | } 57 | else { 58 | ns.gang.setMemberTask(member.name, "Vigilante Justice"); 59 | } 60 | } 61 | else if (gang.territory < 0.99 && member.str > 50000) { 62 | ns.gang.setMemberTask(member.name, "Territory Warfare"); 63 | } 64 | else { 65 | // TODO: check if task.isHacking matches our gang 66 | // TODO: check if effective wanted level change < gang.wantedLevelGainRate 67 | if (gang.isHacking) { 68 | ns.gang.setMemberTask(member.name, "Cyberterrorism"); 69 | } 70 | else { 71 | ns.gang.setMemberTask(member.name, "Strongarm Civilians"); 72 | } 73 | } 74 | } 75 | 76 | function updateTerritory(ns) { 77 | const gang = ns.gang.getGangInformation(); 78 | const allGangs = ns.gang.getOtherGangInformation(); 79 | 80 | if (gang.territory > 0.99 && gang.territoryWarfareEngaged) { 81 | ns.gang.setTerritoryWarfare(false); 82 | return; 83 | } 84 | 85 | let anyStronger = false; 86 | for (const gangName of Object.keys(allGangs)) { 87 | if (gangName == gang.faction) { 88 | continue; 89 | } 90 | // TODO: maybe check actual ns.gang.getChanceToWinClash(gangName) 91 | if (allGangs[gangName].power > gang.power) { 92 | anyStronger = true; 93 | break; 94 | } 95 | } 96 | 97 | if (anyStronger && gang.territoryWarfareEngaged) { 98 | ns.gang.setTerritoryWarfare(false); 99 | } 100 | else if (!anyStronger && !gang.territoryWarfareEngaged) { 101 | ns.gang.setTerritoryWarfare(true); 102 | } 103 | } 104 | 105 | function makeid(length=6) { 106 | var result = ''; 107 | var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; 108 | var charactersLength = characters.length; 109 | for ( var i = 0; i < length; i++ ) { 110 | result += characters.charAt(Math.floor(Math.random() * charactersLength)); 111 | } 112 | return result; 113 | } 114 | -------------------------------------------------------------------------------- /hacking/doc/gameplay-loop.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | Produced by OmniGraffle 7.19.2\n2022-05-16 19:04:37 +0000 17 | 18 | Game Loop 19 | 20 | Basic Game Loop 21 | 22 | 23 | 24 | 25 | Make Money 26 | 27 | 28 | 29 | 30 | Buy servers 31 | with more RAM 32 | 33 | 34 | 35 | 36 | Run money-making 37 | programs in RAM 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 | RAM Allocated to Hacking 67 | 68 | 69 | 70 | 71 | Money Drained / Second 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | Sequential 80 | 81 | 82 | 83 | 84 | Parallel 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /hacking/worker.js: -------------------------------------------------------------------------------- 1 | const FLAGS = [ 2 | ["startTime", 0], 3 | ["repeatPeriod", 0], 4 | ["additionalMsec", 0], 5 | ["stock", false], 6 | ["verbose", false], 7 | ["help", false], 8 | ["id", ''] 9 | ]; 10 | 11 | const TASKS = [ 12 | 'hack', 13 | 'grow', 14 | 'weaken' 15 | ]; 16 | 17 | export function autocomplete(data, args) { 18 | data.flags(FLAGS); 19 | return [...TASKS, ...data.servers]; 20 | } 21 | 22 | /** @param {NS} ns **/ 23 | export async function main(ns) { 24 | ns.grow; // for static RAM calculation 25 | 26 | const flags = ns.flags(FLAGS); 27 | const task = flags._.shift(); 28 | const args = flags._; 29 | const options = { 30 | additionalMsec: flags.additionalMsec, 31 | stock: flags.stock 32 | }; 33 | 34 | if (flags.help || !TASKS.includes(task) || args.length < 1) { 35 | ns.tprint([ 36 | 'Perform a hack / grow / weaken task on a server.', ' ', 37 | 'Usage:', 38 | `> run ${ns.getScriptName()} [ ${TASKS.join(' | ')} ] hostname [ --startTime ms ] [ --repeatPeriod ms ]`, ' ', 39 | 'Example: weaken foodnstuff one time with 10 threads', 40 | `> run ${ns.getScriptName()} -t 10 weaken foodnstuff`, ' ' 41 | ].join('\n')); 42 | return; 43 | } 44 | 45 | let now = performance.now(); 46 | let startTime = flags.startTime || now; 47 | while (startTime >= now) { 48 | // Wait until startTime. 49 | if (startTime > now) { 50 | await ns.asleep(startTime - now); 51 | } 52 | 53 | // Run the task. 54 | if (flags.verbose) { ns.tprint(` [${formatTimestamp()}] Starting ${task} ${args.join(' ')} ${JSON.stringify(options)} (${formatTimeDiff(performance.now(), startTime)})`); } 55 | await ns[task](args[0], options); 56 | if (flags.verbose) { ns.tprint(` [${formatTimestamp()}] Finished ${task} ${args.join(' ')}`); } 57 | 58 | // Update startTime if repeat is enabled. 59 | now = performance.now(); 60 | if (flags.repeatPeriod > 0) { 61 | const numPeriods = Math.ceil((now - startTime) / flags.repeatPeriod); 62 | startTime += numPeriods * flags.repeatPeriod; 63 | } 64 | } 65 | } 66 | 67 | function formatTimestamp(timestamp, precision=3) { 68 | timestamp ||= new Date(); 69 | let timeStr = timestamp.toTimeString().slice(0,8); 70 | if (precision > 0) { 71 | const msStr = (timestamp / 1000 - Math.floor(timestamp/1000)).toFixed(precision); 72 | timeStr += msStr.substring(1); 73 | } 74 | return timeStr; 75 | } 76 | 77 | function formatTimeDiff(expected, observed) { 78 | return `${expected >= observed ? '+' : ''}${expected - observed} ms`; 79 | } 80 | -------------------------------------------------------------------------------- /hacknet/nodes.ns: -------------------------------------------------------------------------------- 1 | function gainFromLevelUpgrade(X, Y, Z) { 2 | return (1*1.6) * Math.pow(1.035,Y-1) * ((Z+5)/6); 3 | } 4 | function gainFromRamUpgrade(X, Y, Z) { 5 | return (X*1.6) * (Math.pow(1.035,(2*Y)-1) - Math.pow(1.035,Y-1)) * ((Z+5)/6); 6 | } 7 | function gainFromCoreUpgrade(X, Y, Z) { 8 | return (X*1.6) * Math.pow(1.035,Y-1) * (1/6); 9 | } 10 | function log2(num){ 11 | return Math.log(num)/Math.log(2); 12 | } 13 | 14 | async function upgradeAllToMatchNode(ns, baseIndex) { 15 | let baseNode = ns.hacknet.getNodeStats(baseIndex); 16 | for(let i = 0; i < ns.hacknet.numNodes(); i++){ 17 | let currNode = ns.hacknet.getNodeStats(i); 18 | if(currNode.level < baseNode.level){ 19 | await waitTillCash(ns, ns.hacknet.getLevelUpgradeCost(i, baseNode.level - currNode.level)); 20 | ns.hacknet.upgradeLevel(i, baseNode.level - currNode.level); 21 | } 22 | if(currNode.ram < baseNode.ram){ 23 | await waitTillCash(ns, ns.hacknet.getRamUpgradeCost(i, log2(baseNode.ram/currNode.ram))); 24 | ns.hacknet.upgradeRam(i, log2(baseNode.ram/currNode.ram)); 25 | } 26 | if(currNode.cores < baseNode.cores){ 27 | await waitTillCash(ns, ns.hacknet.getCoreUpgradeCost(i, baseNode.cores - currNode.cores)); 28 | ns.hacknet.upgradeCore(i, baseNode.cores - currNode.cores); 29 | } 30 | } 31 | } 32 | 33 | async function waitTillCash(ns, target){ 34 | if(ns.getServerMoneyAvailable("home") < target) 35 | ns.print(`Waiting for cash to reach ${target}`); 36 | while(ns.getServerMoneyAvailable("home") < target) 37 | await ns.sleep(5000); 38 | } 39 | 40 | let breakevenTime = 60 * 60 * 1;//Time in seconds 41 | 42 | export async function main(ns) { 43 | ns.disableLog("ALL"); 44 | if (ns.args.length > 0) { 45 | breakevenTime = 60 * 60 * ns.args[0]; 46 | } 47 | 48 | while(ns.hacknet.numNodes() === 0) ns.hacknet.purchaseNode(); 49 | 50 | let weakestIndex = 0; 51 | let weakestNode = ns.hacknet.getNodeStats(0); 52 | for(let i = 1; i < ns.hacknet.numNodes(); i++){ 53 | if(ns.hacknet.getNodeStats(i).production < weakestNode.production){ 54 | weakestNode = ns.hacknet.getNodeStats(i); 55 | weakestIndex = i; 56 | } 57 | } 58 | ns.print(weakestIndex); 59 | 60 | let bestBEven = 0; 61 | let gainMul = ns.getHacknetMultipliers().production * ns.getBitNodeMultipliers().HacknetNodeMoney; 62 | 63 | while (bestBEven < breakevenTime){ 64 | weakestNode = ns.hacknet.getNodeStats(weakestIndex); 65 | let X = weakestNode.level; 66 | let Y = weakestNode.ram; 67 | let Z = weakestNode.cores; 68 | let cost, gain; 69 | let choice = "X"; 70 | bestBEven = breakevenTime; 71 | 72 | //Try upgrading Level 73 | cost = ns.hacknet.getLevelUpgradeCost(weakestIndex, 1); 74 | gain = gainMul * gainFromLevelUpgrade(X, Y, Z); 75 | //ns.print(cost/gain); 76 | if((cost/gain) <= bestBEven){ 77 | bestBEven = cost/gain; 78 | choice = "L"; 79 | } 80 | ns.tprint(`L cost: ${cost}, gain: ${gain}, beven: ${cost/gain}, bestBEven: ${bestBEven}`); 81 | 82 | // //Try upgrading RAM 83 | // cost = ns.hacknet.getRamUpgradeCost(weakestIndex, 1); 84 | // gain = gainMul * gainFromRamUpgrade(X, Y, Z); 85 | // //ns.print(cost/gain); 86 | // if((cost/gain) < bestBEven){ 87 | // bestBEven = cost/gain; 88 | // choice = "R"; 89 | // } 90 | // //ns.tprint(`R cost: ${cost}, gain: ${gain}, beven: ${cost/gain}, bestBEven: ${bestBEven}`); 91 | 92 | //Try upgrading Cores 93 | cost = ns.hacknet.getCoreUpgradeCost(weakestIndex, 1); 94 | gain = gainMul * gainFromCoreUpgrade(X, Y, Z); 95 | //ns.print(cost/gain); 96 | if((cost/gain) < bestBEven){ 97 | bestBEven = cost/gain; 98 | choice = "C"; 99 | } 100 | ns.tprint(`C cost: ${cost}, gain: ${gain}, beven: ${cost/gain}, bestBEven: ${bestBEven}`); 101 | 102 | //Try buying new Node 103 | cost = ns.hacknet.getPurchaseNodeCost(); 104 | gain = weakestNode.production; 105 | //ns.print(cost/gain); 106 | if((cost/gain) < bestBEven){ 107 | bestBEven = cost/gain; 108 | choice = "N"; 109 | } 110 | ns.tprint(`N cost: ${cost}, gain: ${gain}, beven: ${cost/gain}, bestBEven: ${bestBEven}`); 111 | 112 | ns.print(`choice :${choice}`); 113 | switch(choice){ 114 | case "X"://Do nothing 115 | break; 116 | case "L": 117 | await waitTillCash(ns, ns.hacknet.getLevelUpgradeCost(weakestIndex, 1)); 118 | ns.hacknet.upgradeLevel(weakestIndex, 1); 119 | break; 120 | case "R": 121 | await waitTillCash(ns, ns.hacknet.getRamUpgradeCost(weakestIndex, 1)); 122 | ns.hacknet.upgradeRam(weakestIndex, 1); 123 | break; 124 | case "C": 125 | await waitTillCash(ns, ns.hacknet.getCoreUpgradeCost(weakestIndex, 1)); 126 | ns.hacknet.upgradeCore(weakestIndex, 1); 127 | break; 128 | case "N": 129 | await waitTillCash(ns, ns.hacknet.getPurchaseNodeCost()); 130 | ns.hacknet.purchaseNode(); 131 | break; 132 | } 133 | await upgradeAllToMatchNode(ns, weakestIndex); 134 | await ns.sleep(100); 135 | } 136 | ns.tprint("Done."); 137 | await ns.sleep(10000); 138 | } -------------------------------------------------------------------------------- /hacknet/spend-hashes.js: -------------------------------------------------------------------------------- 1 | const UPGRADES = [ 2 | "Sell for Money", 3 | "Sell for Corporation Funds", 4 | "Reduce Minimum Security", 5 | "Increase Maximum Money", 6 | "Improve Studying", 7 | "Improve Gym Training", 8 | "Exchange for Corporation Research", 9 | "Exchange for Bladeburner Rank", 10 | "Exchange for Bladeburner SP", 11 | "Bladeburner", 12 | "Generate Coding Contract", 13 | ]; 14 | 15 | const FLAGS = [ 16 | ["help", false], 17 | ["target"], 18 | ["verbose", true], 19 | ["ongoing", false] 20 | ]; 21 | 22 | export function autocomplete(data, args) { 23 | data.flags(FLAGS); 24 | if (args[args.length-2] == "--target") { 25 | return data.servers; 26 | } 27 | const escapedUpgrades = UPGRADES.map((s)=>`"${s}"`); 28 | return escapedUpgrades; 29 | } 30 | 31 | /** @param {NS} ns **/ 32 | export async function main(ns) { 33 | ns.disableLog("sleep"); 34 | 35 | let flags = ns.flags(FLAGS); 36 | if (flags._.length == 0) { 37 | flags._.push("Sell for Money"); 38 | } 39 | if (flags.verbose && !flags.ongoing) { 40 | ns.print = ns.tprint; 41 | } 42 | const upgrades = flags._; 43 | 44 | if (flags.help) { 45 | ns.tprint([ 46 | "Spend hashes on a named upgrade", 47 | "", 48 | "Example: Sell all hashes for bladeburner rank and money, then terminate", 49 | `run ${ns.getScriptName()} "Bladeburner" "Sell for Money"`, 50 | "", 51 | "Example: Continually spend all hashes on increasing server money", 52 | `run ${ns.getScriptName()} --ongoing --tail --target the-hub "Increase Maximum Money"`, 53 | " " 54 | ].join("\n")); 55 | return; 56 | } 57 | 58 | buyUpgrades(ns, upgrades, flags.target); 59 | while (flags.ongoing) { 60 | await ns.sleep(60*1000); 61 | buyUpgrades(ns, upgrades, flags.target); 62 | } 63 | } 64 | 65 | export function buyUpgrades(ns, upgrades, target) { 66 | const startingHashes = ns.hacknet.numHashes(); 67 | for (const upgrade of upgrades) { 68 | if (upgrade == "Sell for Money") { 69 | continue; 70 | } 71 | else if (upgrade.match(/Corporation/) && !ns.getPlayer().hasCorporation) { 72 | continue; 73 | } 74 | else if (upgrade == "Bladeburner") { 75 | buyBladeburnerUpgrades(ns); 76 | } 77 | else { 78 | buyMaxUpgrades(ns, upgrade, target); 79 | } 80 | } 81 | if (upgrades.includes("Sell for Money")) { 82 | sellHashesForMoney(ns); 83 | } 84 | if (upgrades.length > 1) { 85 | ns.print(`Spent ${startingHashes - ns.hacknet.numHashes()} hashes on upgrades.`); 86 | } 87 | } 88 | 89 | export function buyMaxUpgrades(ns, upgrade, target) { 90 | while (ns.hacknet.numHashes() >= ns.hacknet.hashCost(upgrade)) { 91 | const cost = ns.hacknet.hashCost(upgrade); 92 | const success = ns.hacknet.spendHashes(upgrade, target); 93 | if (success) { 94 | ns.print(`Spent ${cost} hashes on ${upgrade}.`) 95 | } 96 | } 97 | } 98 | 99 | export function buyBladeburnerUpgrades(ns) { 100 | const rankUG = "Exchange for Bladeburner Rank"; 101 | const spUG = "Exchange for Bladeburner SP"; 102 | let rankCost = ns.hacknet.hashCost(rankUG); 103 | let spCost = ns.hacknet.hashCost(spUG); 104 | let numHashes = ns.hacknet.numHashes(); 105 | let upgrade; 106 | while (numHashes >= spCost) { 107 | if (rankCost < 3 * spCost) { 108 | upgrade = rankUG; 109 | } 110 | else { 111 | upgrade = spUG; 112 | } 113 | const cost = ns.hacknet.hashCost(upgrade); 114 | const success = ns.hacknet.spendHashes(upgrade); 115 | if (success) { 116 | ns.print(`Spent ${cost} hashes on ${upgrade}.`) 117 | } 118 | else { 119 | break; 120 | } 121 | rankCost = ns.hacknet.hashCost(rankUG); 122 | spCost = ns.hacknet.hashCost(spUG); 123 | numHashes = ns.hacknet.numHashes(); 124 | } 125 | } 126 | 127 | export function sellHashesForMoney(ns, reservedHashes=0) { 128 | let moneyCost = 0; 129 | const cost = ns.hacknet.hashCost("Sell for Money"); 130 | while (ns.hacknet.numHashes() >= cost + reservedHashes) { 131 | ns.hacknet.spendHashes("Sell for Money"); 132 | moneyCost += cost; 133 | } 134 | if (moneyCost > 0) { 135 | ns.print(`Spent ${moneyCost} hashes for money.`) 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /init.js: -------------------------------------------------------------------------------- 1 | import { prepareStats } from "player/train.js"; 2 | 3 | // init.js 4 | // main script to run when starting game. 5 | 6 | 7 | /* 8 | 9 | if home server ram is sufficient: 10 | 11 | sell a small amount of corp shares, if possible 12 | 13 | manage coding contracts 14 | manage hacknet servers (default to 1-hour payback time) 15 | manage sleeves 16 | manage bladeburner 17 | manage stock market 18 | 19 | crack all servers (can terminate) 20 | create or buy all programs (can terminate) 21 | 22 | backdoor faction servers (can terminate) 23 | join factions 24 | 25 | farm servers 26 | 27 | */ 28 | 29 | export async function main(ns) { 30 | await ns.sleep( 0*1000); ns.run("/contracts/find-and-solve.js"); 31 | await ns.sleep( 0*1000); ns.run("/sleeves/init.js"); 32 | await ns.sleep( 0*1000); ns.run("/corporation/init.js"); 33 | // await ns.sleep( 0*1000); ns.run("/gang/manage.js"); 34 | await ns.sleep( 1*1000); ns.run("/stanek/deploy.js"); 35 | await ns.sleep( 1*1000); ns.run("/share/deploy.js"); 36 | await prepareStats(ns, { 37 | "hacking": 10 38 | }); 39 | await ns.sleep( 0*1000); ns.run("/net/register-servers.js"); 40 | await prepareStats(ns, { 41 | "strength": 5, 42 | "defense": 5, 43 | "dexterity": 10, 44 | "agility": 10 45 | }); 46 | await ns.sleep( 0*1000); ns.run("/player/crime.js"); 47 | await ns.sleep( 1*1000); ns.run("/player/create-programs.js"); 48 | await ns.sleep( 1*1000); ns.run("/player/backdoor-servers.js"); 49 | await ns.sleep( 1*1000); ns.run("/player/join-factions.js"); 50 | await ns.sleep( 1*1000); ns.run("/bladeburner/progress.ns"); 51 | 52 | // await ns.sleep( 5*1000); ns.run("/net/buy-server.js"); 53 | // await ns.sleep( 5*1000); ns.run("/batch/manage.js", 1, "phantasy", "--moneyPercent", "0.01"); 54 | 55 | await ns.sleep( 5*1000); ns.run("/hacknet/servers.js"); //, 1, 4, 1); 56 | await ns.sleep( 5*1000); ns.run("/stocks/trader.js"); 57 | 58 | // await ns.sleep(30*1000); ns.run("/batch/manage.js", 1, "--moneyPercent", "0.01"); 59 | } 60 | -------------------------------------------------------------------------------- /inspect/bitnode.js: -------------------------------------------------------------------------------- 1 | export async function main(ns) { 2 | ns.clearLog(); 3 | ns.tail(); 4 | 5 | ns.print(JSON.stringify(ns.getBitNodeMultipliers(), null, 2)); 6 | ns.print(JSON.stringify(ns.formulas.hacknetServers.constants(), null, 2)); 7 | } 8 | -------------------------------------------------------------------------------- /inspect/get-info.js: -------------------------------------------------------------------------------- 1 | import { ALL_AUGMENTATIONS } from "augmentations/info.js"; 2 | 3 | const FLAGS = [ 4 | ["help", false], 5 | ]; 6 | 7 | export function autocomplete(data, args) { 8 | data.flags(FLAGS); 9 | return ["player", "bitnode", "gang", "augmentations", ...ALL_AUGMENTATIONS, ...data.servers]; 10 | } 11 | 12 | /** @param {NS} ns **/ 13 | export async function main(ns) { 14 | const args = ns.flags(FLAGS); 15 | if (args.help) { 16 | ns.tprint([ 17 | "Show info about a game object.", 18 | "", 19 | `Usage: run ${ns.getScriptName()} [object]`, 20 | "", 21 | "Example: see player info", 22 | `> run ${ns.getScriptName()} player`, 23 | "", 24 | "Example: see some server info", 25 | `> run ${ns.getScriptName()} CSEC`, 26 | "", 27 | "Example: see some augmentation info", 28 | `> run ${ns.getScriptName()} NeuroFlux Governor`, 29 | " " 30 | ].join("\n")) 31 | return; 32 | } 33 | 34 | if (ALL_AUGMENTATIONS.includes(args._.join(' '))) { 35 | ns.run("/augmentations/info.js", 1, ...args._); 36 | return; 37 | } 38 | const arg = args._[0]; 39 | if (arg == "player") { 40 | ns.run("/player/info.js", 1, ...args._.slice(1)); 41 | } 42 | else if (arg == "bitnode") { 43 | ns.run("/inspect/bitnode.js", 1, ...args._.slice(1)); 44 | } 45 | else if (arg == "augmentations") { 46 | ns.run("/augmentations/info.js", 1, ...args._.slice(1)); 47 | } 48 | else if (arg == "gang") { 49 | ns.run("/gang/info.js", 1, ...args._.slice(1)); 50 | } 51 | else if (ns.serverExists(arg)) { 52 | ns.run("/inspect/server.js", 1, ...args._.slice(1)); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /inspect/server.js: -------------------------------------------------------------------------------- 1 | const FLAGS = [ 2 | ['refreshrate', 200], 3 | ['help', false], 4 | ]; 5 | 6 | export function autocomplete(data, args) { 7 | data.flags(FLAGS); 8 | return data.servers; 9 | } 10 | 11 | /** @param {NS} ns **/ 12 | export async function main(ns) { 13 | const flags = ns.flags(FLAGS); 14 | if (flags._.length === 0 || flags.help) { 15 | ns.tprint("This script helps visualize the money and security of a server."); 16 | ns.tprint(`USAGE: run ${ns.getScriptName()} SERVER_NAME`); 17 | ns.tprint("Example:"); 18 | ns.tprint(`> run ${ns.getScriptName()} n00dles`) 19 | return; 20 | } 21 | const host = flags._.shift(); 22 | 23 | ns.tail(); 24 | ns.disableLog('ALL'); 25 | while (true) { 26 | ns.clearLog(); 27 | 28 | const server = ns.getServer(host); 29 | 30 | const money = server.moneyAvailable; 31 | const maxMoney = server.moneyMax; 32 | const minSec = server.minDifficulty; 33 | const sec = server.hackDifficulty; 34 | 35 | ns.print("server = " + JSON.stringify(server, null, 2), "\n\n\n\n\n\n\n\n\n\n\n"); 36 | 37 | ns.print(`${host}:`); 38 | if (server.organizationName) { 39 | ns.print(` Organization: ${server.organizationName}`); 40 | } 41 | const stockInfo = getStockInfo(ns, server); 42 | if (stockInfo) { 43 | ns.print(` ${stockInfo.symbol} stock: ${ns.nFormat(stockInfo.netShares || 0, "0.[0]a")} shares held (${ns.nFormat(stockInfo.netValue || 0, "$0.[0]a")})`); 44 | } 45 | ns.print(`\n Required Hacking Skill: ${server.requiredHackingSkill} ${ns.getPlayer().hacking >= server.requiredHackingSkill ? '✓' : '✗'}`); 46 | ns.print(` Ports Open: ${server.openPortCount} / ${server.numOpenPortsRequired} ${server.hasAdminRights ? '(admin ✓)' : ''} ${server.backdoorInstalled ? '(backdoor ✓)' : ''}`); 47 | ns.print(` RAM: ${ns.nFormat(server.ramUsed * 1e9, "0.[0] b")} / ${ns.nFormat(server.maxRam * 1e9, "0.[0] b")}\n`) 48 | // ns.print(` Admin Access: ${server.hasAdminRights ? '✓' : '✗'}, Backdoor: ${server.backdoorInstalled ? '✓' : '✗'}`); 49 | ns.print(` money: ${ns.nFormat(money, "$0.[000]a")} / ${ns.nFormat(maxMoney, "$0.[000]a")} (${((money / maxMoney * 100) || 0).toFixed(2)}%)`); 50 | const secString = (sec == 0) ? '0' : `${ns.nFormat(minSec, "0.[00]")} + ${(sec - minSec).toFixed(2)}`; 51 | ns.print(` security: ${secString}`); 52 | if (!server.purchasedByPlayer) { 53 | ns.print(` hack: ${ns.tFormat(ns.getHackTime(host))} (t=${Math.ceil(ns.hackAnalyzeThreads(host, money))})`); 54 | ns.print(` grow: ${ns.tFormat(ns.getGrowTime(host))} (t=${Math.ceil(ns.growthAnalyze(host, Math.max(1, maxMoney) / Math.max(1,money))) || 0})`); 55 | ns.print(` weaken: ${ns.tFormat(ns.getWeakenTime(host))} (t=${Math.ceil((sec - minSec) * 20)})`); 56 | } 57 | 58 | await ns.sleep(flags.refreshrate); 59 | } 60 | } 61 | 62 | function getStockInfo(ns, server={}, portNum=5) { 63 | if (!server.organizationName) { 64 | return null; 65 | } 66 | const port = ns.getPortHandle(portNum); 67 | if (port.empty()) { 68 | return null; 69 | } 70 | const stockService = port.peek(); 71 | const stockInfo = stockService.getStockInfo(server.organizationName); 72 | return stockInfo; 73 | } 74 | -------------------------------------------------------------------------------- /lib/README.md: -------------------------------------------------------------------------------- 1 | ## Library Scripts 2 | 3 | This folder is for scripts that: 4 | 5 | - have 0 RAM import cost 6 | - can be used in more than one context 7 | - have no `main` functionality (other than usage example) 8 | 9 | --- 10 | 11 | ### box-drawing.js 12 | 13 | [box-drawing.js](box-drawing.js) is a library for drawing tables with unicode [box-drawing characters](https://en.wikipedia.org/wiki/Box-drawing_character). 14 | 15 | Example output: 16 | ``` 17 | ┌───────┬───────┬────────┬─────────────┐ 18 | │ Name │ Count │ Status │ Time │ 19 | ├───────┼───────┼────────┼─────────────┤ 20 | │ A │ 2 │ │ │ 21 | │ B │ 10 │ │ │ 22 | │ C │ │ idle │ │ 23 | │ D │ │ │ 20:05:15 │ 24 | │ E │ │ longe… │ │ 25 | └───────┴───────┴────────┴─────────────┘ 26 | ``` 27 | 28 | --- 29 | 30 | ### port-service.js 31 | 32 | [port-service.js](port-service.js) defines the `PortService` class, which makes an object available through a [Netscript Port](https://bitburner.readthedocs.io/en/latest/netscript/netscriptmisc.html#netscript-ports). It is useful for avoiding redundant RAM costs for optional functionality. 33 | 34 | ###### Example: Load stock information if it is available 35 | 36 | ```javascript 37 | import { getService } from "/lib/port-service"; 38 | const stockService = getService(ns, 5); 39 | const sharesHeld = stockService?.getStockInfo("Four Sigma")?.shares || 0; 40 | ``` 41 | -------------------------------------------------------------------------------- /lib/box-drawing.js: -------------------------------------------------------------------------------- 1 | export async function main(ns) { 2 | // Print an example table to demonstrate functionality. 3 | const columns = [ 4 | {header: "Name ", field: "name", align: "center"}, 5 | {header: "Count", field: "count"}, 6 | {header: "Status", field: "status", align: "left", truncate: true}, 7 | {header: "Time ", field: "time", format: drawTable.time} 8 | ]; 9 | const rows = [ 10 | {name: "A", count: 2}, 11 | {name: "B", count: 10}, 12 | {name: "C", status: "idle"}, 13 | {name: "D", time: performance.now()}, 14 | {name: "E", status: "longer_status"} 15 | ]; 16 | ns.tprint("\n" + drawTable(columns, rows)); 17 | } 18 | 19 | /* 20 | columns: {width, header, field, format, align, truncate} 21 | rows: obj with each [field] 22 | */ 23 | export function drawTable(columns, ...rowsets) { 24 | let totalWidth = 3*columns.length + 1; 25 | for (const col of columns) { 26 | col.width ||= col.header.length; 27 | totalWidth += col.width; 28 | } 29 | 30 | let lines = []; 31 | 32 | if (columns.title) { 33 | lines.push(' '); 34 | lines.push(pad(columns.title, totalWidth, ' ', 'center')); 35 | } 36 | 37 | lines.push(drawHR(columns, ['┌', '┬', '─', '┐'])); 38 | lines.push('│ ' + columns.map((col)=> 39 | pad(col.header || col.field, col.width, ' ', col.align || 'left') 40 | ).join(' │ ') + ' │'); 41 | 42 | for (const rows of rowsets) { 43 | lines.push(drawHR(columns, ['├', '┼', '─', '┤'])); 44 | 45 | for (const row of rows) { 46 | const values = []; 47 | for (const col of columns) { 48 | let val = getField(row, col.field); 49 | if (Array.isArray(col.field)) { 50 | val = col.field.map((f)=>getField(row,f)); 51 | } 52 | if (Array.isArray(col.format)) { 53 | const vals = (val || []).map((v)=>( 54 | col.format[0](v, ...(col.formatArgs||[])) 55 | )); 56 | val = formatFraction(vals, col.itemWidth); 57 | } 58 | else if (typeof(col.format) == 'function') { 59 | if (!Number.isNaN(val)) { 60 | val = col.format(val, ...(col.formatArgs||[])); 61 | } 62 | } 63 | val = pad(`${val || ''}`, col.width, ' ', col.align || 'right'); 64 | if (col.truncate && val.length > col.width) { 65 | val = val.substring(0,col.width-1) + "…"; 66 | } 67 | values.push(val); 68 | } 69 | lines.push('│ ' + values.join(' │ ') + ' │'); 70 | } 71 | } 72 | 73 | lines.push(drawHR(columns, ['└', '┴', '─', '┘'])); 74 | return lines.join('\n'); 75 | } 76 | 77 | function drawHR(columns, glyphs=['└', '┴', '─', '┘']) { 78 | let line = glyphs[0]; 79 | const segments = []; 80 | for (const col of columns) { 81 | const segment = pad('', col.width+2, glyphs[2]); 82 | segments.push(segment); 83 | } 84 | line = glyphs[0] + segments.join(glyphs[1]) + glyphs[3]; 85 | return line; 86 | } 87 | 88 | function pad(str, length, filler=' ', align='right') { 89 | if (align == 'right') { 90 | while (str.length < length) { 91 | str = filler + str; 92 | } 93 | } 94 | else if (align == 'left') { 95 | while (str.length < length) { 96 | str = str + filler; 97 | } 98 | } 99 | else { 100 | while (str.length < length) { 101 | str = str + filler; 102 | if (str.length < length) { 103 | str = filler + str; 104 | } 105 | } 106 | } 107 | return str; 108 | } 109 | 110 | function getField(obj, fieldName) { 111 | let cursor = obj; 112 | for (const part of `${fieldName || ''}`.split('.')) { 113 | cursor = cursor[part]; 114 | } 115 | return cursor; 116 | } 117 | 118 | export function formatTime(timeMS, precision=0) { 119 | if (!timeMS) { 120 | return ''; 121 | } 122 | let sign = ''; 123 | if (timeMS < 0) { 124 | sign = '-'; 125 | timeMS = Math.abs(timeMS); 126 | } 127 | const d = new Date(2000, 1, 1, 0, 0, timeMS/1000) 128 | let timeStr = d.toTimeString().slice(0,8); 129 | if (timeMS >= 60 * 60 * 1000) { 130 | timeStr = timeStr.slice(0,8); 131 | } 132 | else if (timeMS >= 10 * 60 * 1000) { 133 | timeStr = timeStr.slice(3,8); 134 | } 135 | else { 136 | timeStr = timeStr.slice(4,8); 137 | } 138 | if (precision > 0) { 139 | let msStr = (timeMS / 1000 - Math.floor(timeMS/1000)).toFixed(precision); 140 | timeStr += msStr.substring(1); 141 | } 142 | return sign + timeStr; 143 | } 144 | drawTable.time = formatTime; 145 | 146 | export function formatFraction(fraction, itemWidth=0) { 147 | const values = fraction.filter((val)=> 148 | !!val 149 | ).map((val)=> 150 | pad(val, itemWidth) 151 | ); 152 | return values.join(" / "); 153 | } 154 | drawTable.fraction = formatFraction; 155 | -------------------------------------------------------------------------------- /lib/port-service.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get a service from a Netscript port. 3 | * Returns undefined if no service is running right now. 4 | * @param {NS} ns 5 | * @param {number} portNum 6 | */ 7 | export function getService(ns, portNum) { 8 | const portHandle = ns.getPortHandle(portNum); 9 | if (!portHandle.empty()) { 10 | return portHandle.peek(); 11 | } 12 | } 13 | 14 | /** 15 | * Get a service from a Netscript port. 16 | * Wait up to 2.5 seconds for the service to start (such as after reloading from save). 17 | * @param {NS} ns 18 | * @param {number} portNum 19 | */ 20 | export async function waitForService(ns, portNum) { 21 | const port = ns.getPortHandle(portNum); 22 | let tries = 50; 23 | while (port.empty() && tries-- > 0) { 24 | await ns.asleep(50); 25 | } 26 | if (port.empty()) { 27 | return null; 28 | } 29 | return port.peek(); 30 | } 31 | 32 | /** 33 | * @typedef {Object} PortService - Service that makes an object available to other proecesses through a Netscript port. 34 | */ 35 | export class PortService { 36 | constructor(ns, portNum=1, obj) { 37 | this.ns = ns; 38 | this.portNum = portNum; 39 | this.portHandle = ns.getPortHandle(portNum); 40 | this.publishObject(obj); 41 | } 42 | 43 | publishObject(obj) { 44 | const {ns} = this; 45 | obj ||= this; 46 | 47 | obj._service = this; 48 | this.object = obj; 49 | this.objectClassName = obj.constructor.name; 50 | this.objectName ||= this.objectClassName.substr(0,1).toLowerCase() + this.objectClassName.substr(1); 51 | 52 | // Replace any existing service on the same port. 53 | if (!this.portHandle.empty()) { 54 | const otherObj = this.portHandle.read(); 55 | if (otherObj?._service && otherObj._service !== this) { 56 | otherObj._service.running = false; 57 | // await ns.asleep(1000); 58 | } 59 | } 60 | 61 | // Publish this service on the port. 62 | this.portHandle.clear(); 63 | this.portHandle.write(this.object); 64 | 65 | // Publish this service in the browser's developer console. 66 | eval('window')[this.objectName] = this.object; 67 | eval('window')[`port${this.portNum}`] = this.object; 68 | 69 | // Unpublish this service when the process ends for any reason. 70 | ns.atExit(this.tearDown.bind(this)); 71 | 72 | ns.tprint(`INFO: Started ${this.objectClassName} Service on port ${this.portNum}`); 73 | } 74 | 75 | // Block until something sets `this.running` to false. 76 | async serve() { 77 | const {ns} = this; 78 | ns.disableLog("asleep"); 79 | this.running = true; 80 | while (this.running) { 81 | if (typeof(this.object.update) === "function") { 82 | this.object.update(); 83 | } 84 | if (typeof(this.object.report) === "function") { 85 | ns.clearLog(); 86 | ns.print(this.object.report()); 87 | } 88 | await ns.asleep(1000); 89 | } 90 | this.tearDown(); 91 | ns.tprint(`Stopped ${this.objectClassName} Service on port ${this.portNum}`); 92 | } 93 | 94 | tearDown() { 95 | if (this.object !== this && typeof(this.object?.tearDown) === "function") { 96 | this.object.tearDown(); 97 | } 98 | this.running = false; 99 | if (this.portHandle.peek() === this.object) { 100 | this.portHandle.read(); 101 | } 102 | if (eval('window')[this.objectName] === this.object) { 103 | delete eval('window')[this.objectName]; 104 | } 105 | if (eval('window')[`port${this.portNum}`] === this) { 106 | delete eval('window')[`port${this.portNum}`]; 107 | } 108 | } 109 | } 110 | 111 | /** 112 | * Example program to demonstrate functionality 113 | * @param {NS} ns 114 | */ 115 | export async function main(ns) { 116 | const flags = ns.flags([ 117 | ['port', 20] 118 | ]); 119 | 120 | function NetscriptConsole() { 121 | // 25 GB RAM to run this script, but still 0 GB import cost 122 | window.ns = ns; 123 | } 124 | const netscriptConsole = new NetscriptConsole(); 125 | 126 | const service = new PortService(ns, flags.port, netscriptConsole); 127 | await service.serve(); 128 | } 129 | -------------------------------------------------------------------------------- /net/README.md: -------------------------------------------------------------------------------- 1 | ## Bitburner Net Scripts 2 | 3 | Scripts for managing servers and RAM. 4 | 5 | --- 6 | 7 | ### deploy-script.js 8 | 9 | Library for running scripts on any available host. 10 | 11 | #### API Usage: 12 | ```javascript 13 | import { deploy } from "net/deploy-script.js"; 14 | 15 | // Define a job. 16 | const job = { 17 | script: "script.js", 18 | args: ["foo"], 19 | threads: 100, // Optional (default 1) 20 | startTime: performance.now() // Optional. Schedule the job to start at a certain time. 21 | }; 22 | const options = { 23 | allowSplit: true, // Whether to allow splitting threads among different servers. 24 | } 25 | 26 | // Launch a batch of jobs. 27 | // Will cancel if there is not enough RAM for the entire batch. 28 | // Will adjust the `startTime` of the entire batch if any are in the past. 29 | const batch = [job]; 30 | await deploy(ns, batch, options); 31 | ``` 32 | 33 | #### CLI Usage: 34 | Convenience interface to launch a single job in the cloud. 35 | ```bash 36 | > run /net/deploy-script.js --threads 1000 /batch/grow.js ecorp 37 | 38 | /net/deploy-script.js: Running on omnitek: 292x /batch/grow.js ecorp 39 | /net/deploy-script.js: Running on helios: 146x /batch/grow.js ecorp 40 | /net/deploy-script.js: Running on fulcrumtech: 73x /batch/grow.js ecorp 41 | ... 42 | ``` 43 | -------------------------------------------------------------------------------- /net/auto-link.js: -------------------------------------------------------------------------------- 1 | /** @type {NS} */ 2 | let ns; 3 | 4 | /** @param {NS} _ns */ 5 | export async function main(_ns) { 6 | ns = _ns; 7 | ns.disableLog("scan"); 8 | ns.disableLog("asleep"); 9 | ns.clearLog(); 10 | ns.tail(); 11 | 12 | ns.printRaw(React.createElement(ServerNode, {hostname: "home"})); 13 | await ns.asleep(24*60*60*1000); 14 | } 15 | 16 | function getConnectCommand(path) { 17 | const commands = path.map((hostname)=>( 18 | hostname == 'home' ? 'home' : `connect ${hostname}` 19 | )); 20 | return commands.join('; '); 21 | } 22 | 23 | function getNeighborNodes(hostname, path) { 24 | const neighborNodes = ns.scan(hostname).filter((h)=>( 25 | !path.includes(h) 26 | )).map((h)=>( 27 | React.createElement(ServerNode, { key: h, hostname: h, path: [...path, hostname] }) 28 | )); 29 | return neighborNodes; 30 | }; 31 | 32 | function ServerNode({ hostname, path }) { 33 | path ??= []; 34 | const [neighbors, setNeighbors] = React.useState(null); 35 | if (neighbors === null) { 36 | setNeighbors(getNeighborNodes(hostname, path)); 37 | } 38 | const connectCommand = getConnectCommand([...path, hostname]); 39 | const hostnameEl = React.createElement("a", { 40 | href: `javascript:navigator.clipboard.writeText("${connectCommand}");`, 41 | onClick: ()=>{ ns.toast("Connection command copied to clipboard") } 42 | }, hostname); 43 | return React.createElement( 44 | "div", 45 | { key: hostname, style: { paddingLeft: "1em" } }, 46 | [hostnameEl, neighbors] 47 | ); 48 | } 49 | -------------------------------------------------------------------------------- /net/buy-server.js: -------------------------------------------------------------------------------- 1 | export async function main(ns) { 2 | const fundsFraction = ns.args[0] || 0.8; 3 | buyServer(ns, fundsFraction); 4 | } 5 | 6 | export function buyServer(ns, fundsFraction=0.8) { 7 | const funds = fundsFraction * ns.getServerMoneyAvailable('home'); 8 | 9 | // let costMult = 1; 10 | // costMult = ns.getBitNodeMultipliers().PurchasedServerCost; 11 | // const power = Math.floor(Math.log2(funds/(50000*costMult))); 12 | // const size = Math.min(ns.getPurchasedServerMaxRam(), Math.pow(2, power)); 13 | 14 | const size = largestServerSize(ns, funds); 15 | const cost = ns.getPurchasedServerCost(size); 16 | 17 | let servers = ns.getPurchasedServers(); 18 | 19 | deleteServerIfNeeded(ns); 20 | 21 | let hostname = `pserv-${servers.length}`; 22 | hostname = ns.purchaseServer(hostname, size); 23 | if (hostname) { 24 | ns.tprint(`Purchased server '${hostname}' with ${ns.nFormat(size*1e9, "0.0 b")} RAM for ${ns.nFormat(cost, "$0,0a")}`); 25 | } 26 | else { 27 | ns.tprint("Failed to purchase server"); 28 | } 29 | return hostname; 30 | } 31 | 32 | export function largestServerSize(ns, funds) { 33 | let size = 1; 34 | let cost; 35 | while (size <= ns.getPurchasedServerMaxRam()) { 36 | size *= 2; 37 | cost = ns.getPurchasedServerCost(size); 38 | if (cost > funds) { 39 | break; 40 | } 41 | } 42 | return size / 2; 43 | } 44 | 45 | export function deleteServerIfNeeded(ns) { 46 | const servers = ns.getPurchasedServers().map((hostname)=>ns.getServer(hostname)); 47 | if (servers.length >= ns.getPurchasedServerLimit()) { 48 | deleteSmallestServer(ns); 49 | } 50 | } 51 | 52 | export function deleteSmallestServer(ns, servers) { 53 | servers ||= ns.getPurchasedServers().map((hostname)=>ns.getServer(hostname)); 54 | const smallestServer = servers.sort((a,b)=>a.maxRam-b.maxRam)[0]; 55 | ns.killall(smallestServer.hostname); 56 | // await ns.sleep(100); 57 | const success = ns.deleteServer(smallestServer.hostname); 58 | if (success) { 59 | ns.tprint(`Decomissioned server ${smallestServer.hostname}`); 60 | } 61 | else { 62 | ns.tprint(`Failed to delete server ${smallestServer.hostname}`); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /net/register-servers.js: -------------------------------------------------------------------------------- 1 | // register-servers.js (2.35 GB) 2 | // 3 | // This script will register admin accounts on all servers 4 | // (waiting in the background for more port-opening programs to become available) 5 | // and then terminate after all servers are ready. 6 | 7 | export async function main(ns) { 8 | ns.disableLog("sleep"); 9 | ns.disableLog("scan"); 10 | ns.disableLog("getServerNumPortsRequired"); 11 | ns.clearLog(); 12 | await openAllServers(ns); 13 | } 14 | 15 | export async function openAllServers(ns) { 16 | // Repeatedly try to open all reachable servers 17 | let closedServers = getClosedServers(ns); 18 | while (closedServers.length > 0) { 19 | for (const server of closedServers) { 20 | const result = openServer(ns, server); 21 | if (result == false) { 22 | // Reached the end of servers openable with current programs 23 | ns.print("Waiting for more programs..."); 24 | await ns.sleep(30*1000); 25 | break; 26 | } 27 | } 28 | closedServers = getClosedServers(ns); 29 | } 30 | ns.tprint("INFO: Registered admin accounts on all servers."); 31 | } 32 | 33 | export function openServer(ns, server) { 34 | // Attempt to enable admin rights on a server. 35 | // Returns true for success and false for failure (not enough programs). 36 | if (server.hasAdminRights || server.purchasedByPlayer) { 37 | return true; 38 | } 39 | const portOpeners = { 40 | 'BruteSSH.exe': ns.brutessh, 41 | 'FTPCrack.exe': ns.ftpcrack, 42 | 'relaySMTP.exe': ns.relaysmtp, 43 | 'HTTPWorm.exe': ns.httpworm, 44 | 'SQLInject.exe': ns.sqlinject 45 | }; 46 | let numOpenPorts = 0; 47 | for (const [file, program] of Object.entries(portOpeners)) { 48 | if (ns.fileExists(file, 'home')) { 49 | program(server.hostname); 50 | numOpenPorts += 1; 51 | } 52 | } 53 | if (numOpenPorts >= server.numOpenPortsRequired) { 54 | ns.nuke(server.hostname); 55 | ns.print(`Admin rights granted on ${server.hostname}.`); 56 | return true; 57 | } 58 | return false; 59 | } 60 | 61 | function getClosedServers(ns) { 62 | // Returns an array of server objects with hasAdminRights = false 63 | // sorted by numOpenPortsRequired (ascending) 64 | const closedServers = getAllHostnames(ns).map(function(hostname){ 65 | return { 66 | hostname: hostname, 67 | hasAdminRights: ns.hasRootAccess(hostname), 68 | numOpenPortsRequired: ns.getServerNumPortsRequired(hostname) 69 | }; 70 | }).filter(function(server){ 71 | return !server.hasAdminRights; 72 | }).sort(function(a,b){ 73 | return a.numOpenPortsRequired - b.numOpenPortsRequired; 74 | }); 75 | return closedServers; 76 | } 77 | 78 | export function getAllHostnames(ns) { 79 | getAllHostnames.cache ||= new Set(); 80 | const scanned = getAllHostnames.cache; 81 | const toScan = ['home']; 82 | while (toScan.length > 0) { 83 | const hostname = toScan.shift(); 84 | scanned.add(hostname); 85 | for (const nextHost of ns.scan(hostname)) { 86 | if (!scanned.has(nextHost)) { 87 | toScan.push(nextHost); 88 | } 89 | } 90 | } 91 | return Array.from(scanned); 92 | } 93 | -------------------------------------------------------------------------------- /net/upgrade-home-server.js: -------------------------------------------------------------------------------- 1 | export async function main(ns) { 2 | await upgradeHomeComputer(ns, ns.args[0]); 3 | } 4 | 5 | export async function upgradeHomeComputer(ns, moneyFraction=0.75) { 6 | while (ns.getPlayer().money * moneyFraction > ns.getUpgradeHomeRamCost()) { 7 | const cost = ns.nFormat(ns.getUpgradeHomeRamCost(), "$0.0 a"); 8 | ns.upgradeHomeRam(); 9 | ns.tprint(`Upgraded home computer RAM for ${cost}`); 10 | await ns.sleep(100); 11 | } 12 | while (ns.getPlayer().money * moneyFraction > ns.getUpgradeHomeCoresCost()) { 13 | const cost = ns.nFormat(ns.getUpgradeHomeCoresCost(), "$0.0 a"); 14 | ns.upgradeHomeCores(); 15 | ns.tprint(`Upgraded home computer cores for ${cost}`); 16 | await ns.sleep(100); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /old/attack-targets.script: -------------------------------------------------------------------------------- 1 | // usage: 2 | // run find-targets.script 3 | // run cloud-run-one.script attack-targets.script [targets...] 4 | 5 | 6 | //Define Variables 7 | currentScanLength = 0; 8 | scanArray = ['home']; 9 | Servers = []; 10 | ServersM = []; // Money 11 | ServersHL = []; // HackingLevel 12 | ServersHP = []; // HackingPorts 13 | ServersP = []; // Profits 14 | basehackinglevel = -101; 15 | hackinglevel = getHackingLevel(); 16 | target = 'foodnstuff'; 17 | host = getHostname(); 18 | mults = getHackingMultipliers(); 19 | 20 | //Skill Multiplier Constants 21 | hackmult = mults.money; 22 | growmult = mults.growth; 23 | //Bitnode Multiplier Constants, update after changing Bitnodes 24 | bitnodehackmult = 1.0000; 25 | bitnodegrowmult = 1.0000; 26 | bitnodeweakenmult = 1.0000; 27 | 28 | 29 | 30 | OptimalTargetList = []; 31 | OptimalTargetListM = []; 32 | OptimalTargetListG = []; 33 | OptimalTargetListHL = []; 34 | OptimalTargetListMS = []; 35 | 36 | 37 | for (i = 0; i < args.length; i++) { 38 | arg = args[i]; 39 | OptimalTargetList.push(arg); 40 | OptimalTargetListG.push(getServerGrowth(arg)); 41 | OptimalTargetListHL.push(getServerRequiredHackingLevel(arg)); 42 | OptimalTargetListMS.push(Math.max(round(getServerBaseSecurityLevel(arg)/3),1)); 43 | OptimalTargetListM.push(getServerMaxMoney(arg)); 44 | } 45 | 46 | 47 | 48 | //Main Loop 49 | while (true) { 50 | //Loop Through Targets 51 | for (k = 0; k < Math.min(OptimalTargetList.length,10); k++) { 52 | homeram = getServerRam(host); 53 | 54 | if (homeram[0] - homeram[1] < 2) { 55 | print('Not enough RAM available'); 56 | k = 1000; 57 | break; 58 | } 59 | 60 | freememory = homeram[0] - homeram[1]; 61 | target = OptimalTargetList[k]; 62 | minsecurity = OptimalTargetListMS[k]; 63 | reqHack = OptimalTargetListHL[k]; 64 | maxmoney = OptimalTargetListM[k]; 65 | growth = OptimalTargetListG[k]; 66 | 67 | //Calculate number of Hack Threads Required 68 | perhack = (100-minsecurity) * ((hackinglevel-reqHack+1)/hackinglevel) / 24000 * hackmult * bitnodehackmult; 69 | hacks = Math.ceil(1/perhack); 70 | 71 | security = minsecurity + hacks * 0.002; 72 | //Calculate number of Grow Threads Required 73 | growpercent = Math.min(1 + 0.03/security,1.0035); 74 | pergrow = Math.pow(growpercent,growth/100 * growmult * bitnodegrowmult); 75 | var1 = maxmoney * Math.log(pergrow); 76 | lambert = Math.log(var1)-Math.log(Math.log(var1))-Math.log(1-Math.log(Math.log(var1))/Math.log(var1)); 77 | grows = Math.ceil(lambert/Math.log(pergrow)); 78 | 79 | //Calculate number of Weaken Threads Required 80 | weakens = Math.ceil((((hacks * 0.002) + (grows * 0.004)) / (0.05 * bitnodeweakenmult))); 81 | maxweakens = (100 - minsecurity) / (0.05 * bitnodeweakenmult); 82 | if (weakens > maxweakens) {weakens = maxweakens} 83 | 84 | //Adjust if max threads > max memory 85 | if (weakens * 1.55 > freememory) { 86 | weakens = Math.max(Math.floor(freememory / 1.555),1); 87 | } 88 | if (hacks * 1.5 > freememory) { 89 | hacks = Math.max(Math.floor(freememory / 1.555),1); 90 | } 91 | if (grows * 1.55 > freememory) { 92 | grows = Math.max(Math.floor(freememory / 1.555),1); 93 | } 94 | 95 | script = ''; 96 | threads = 1; 97 | if (isRunning('weaken.script',host,target) == false && isRunning('hack.script',host,target) == false && isRunning('grow.script',host,target) == false) { 98 | if (getServerSecurityLevel(target) > getServerBaseSecurityLevel(target) / 3 + 6) { 99 | script = 'weaken.script'; 100 | threads = weakens; 101 | } else if (getServerMoneyAvailable(target) >= 0.75 * getServerMaxMoney(target)) { 102 | script = 'hack.script'; 103 | threads = hacks; 104 | } else { 105 | script = 'grow.script'; 106 | threads = grows; 107 | } 108 | } 109 | exec(script, host, threads, target); 110 | } 111 | } -------------------------------------------------------------------------------- /old/buy-bull.script: -------------------------------------------------------------------------------- 1 | symbols = ["ECP","MGCP","BLD","CLRK","OMTK","FSIG","KGI","FLCM","STM","DCOMM","HLS","VITA","ICRS","UNV","AERO","OMN","SLRS","GPH","NVMD","WDS","LXO","RHOC","APHE","SYSC","CTK","NTLK","OMGA","SGC","JGN","CTYS","MDYN","TITN"]; 2 | 3 | c = 'constructor' 4 | f = [c][c][c] 5 | makeObj = f('a', 'o = {}; for (var i = 0; i < a.length; i=i+2) {o[a[i]] = a[i+1]} return o;'); 6 | // setObj = f('o', 'a', 'for (var i = 0; i < a.length; i=i+2) {o[a[i]] = a[i+1]} return o;'); 7 | funcs = makeObj(["stock.getPrice", stock.getPrice, "stock.buy", stock.buy, "stock.sell", stock.sell, "stock.short", stock.short, "stock.sellShort", stock.sellShort, "stock.placeOrder", stock.placeOrder, "stock.cancelOrder", stock.cancelOrder, "stock.getPosition", stock.getPosition, "stock.placeOrder", stock.placeOrder]); 8 | 9 | // sellAll = f('symbol', 'pos=this.stock.getPosition(symbol); this.stock.sell(symbol, pos[0])').bind(funcs); 10 | 11 | 12 | moneyToSpend = getServerMoneyAvailable('home') - (args.length > 0 && args[0] || 1000000); 13 | moneyPerStock = moneyToSpend / symbols.length; 14 | 15 | if (moneyPerStock < 500000) { 16 | exit(); 17 | } 18 | 19 | 20 | // buyFixedValue = f('moneyPerStock', 'symbol', 'price=this.stock.getPrice(symbol); shares=(moneyPerStock-100000)/price; this.stock.buy(symbol, shares);').bind(funcs, moneyPerStock); 21 | buyLimit = f('moneyPerStock', 'symbol', 'price=this.stock.getPrice(symbol); shares=(moneyPerStock-100000)/price; this.stock.placeOrder(symbol, shares, price*1.05, "stopbuy");').bind(funcs, moneyPerStock); 22 | 23 | symbols.forEach(buyLimit); -------------------------------------------------------------------------------- /old/buy-stocks.script: -------------------------------------------------------------------------------- 1 | symbols = ["ECP","MGCP","BLD","CLRK","OMTK","FSIG","KGI","FLCM","STM","DCOMM","HLS","VITA","ICRS","UNV","AERO","OMN","SLRS","GPH","NVMD","WDS","LXO","RHOC","APHE","SYSC","CTK","NTLK","OMGA","SGC","JGN","CTYS","MDYN","TITN"]; 2 | 3 | c = 'constructor' 4 | f = [c][c][c] 5 | makeObj = f('a', 'o = {}; for (var i = 0; i < a.length; i=i+2) {o[a[i]] = a[i+1]} return o;'); 6 | // setObj = f('o', 'a', 'for (var i = 0; i < a.length; i=i+2) {o[a[i]] = a[i+1]} return o;'); 7 | funcs = makeObj(["stock.getPrice", stock.getPrice, "stock.buy", stock.buy, "stock.sell", stock.sell, "stock.short", stock.short, "stock.sellShort", stock.sellShort, "stock.placeOrder", stock.placeOrder, "stock.cancelOrder", stock.cancelOrder, "stock.getPosition", stock.getPosition]); 8 | 9 | // sellAll = f('symbol', 'pos=this.stock.getPosition(symbol); this.stock.sell(symbol, pos[0])').bind(funcs); 10 | 11 | 12 | moneyToSpend = getServerMoneyAvailable('home') - (args.length > 0 && args[0] || 1000000); 13 | moneyPerStock = moneyToSpend / symbols.length; 14 | 15 | if (moneyPerStock < 500000) { 16 | exit(); 17 | } 18 | 19 | 20 | buyFixedValue = f('moneyPerStock', 'symbol', 'price=this.stock.getPrice(symbol); shares=(moneyPerStock-100000)/price; this.stock.buy(symbol, shares);').bind(funcs, moneyPerStock); 21 | 22 | symbols.forEach(buyFixedValue); -------------------------------------------------------------------------------- /old/cloud-manage.script: -------------------------------------------------------------------------------- 1 | // cloud-manage.script 2 | 3 | target = args[0]; 4 | moneyThresh = args[1]; 5 | securityThresh = args[2]; 6 | 7 | servers = getPurchasedServers(); 8 | while(true) { 9 | for (i = 0; i < servers.length; i++) { 10 | server = servers[i]; 11 | ram = getServerRam(server); 12 | freeRam = ram[0] - ram[1]; 13 | threads = Math.floor(freeRam / getScriptRam(script, server)); 14 | tprint("Running "+threads+"x "+script+" on "+server); 15 | if (threads > 0) { 16 | exec(script, server, threads, target, moneyThresh, securityThresh); 17 | } 18 | } 19 | } 20 | 21 | while(true) { 22 | script = ""; 23 | scriptRam=1.55; 24 | delay = 0; 25 | 26 | if (getServerSecurityLevel(target) > securityThresh) { 27 | script = "weaken.script"; 28 | delay = getWeakenTime(target); 29 | } else if (getServerMoneyAvailable(target) < moneyThresh) { 30 | script = "grow.script"; 31 | delay = getGrowTime(target); 32 | } else { 33 | script = "hack.script"; 34 | delay = getHackTime(target); 35 | } 36 | ram = getServerRam(server); 37 | freeRam = ram[0] - ram[1]; 38 | 39 | threads = Math.floor(freeRam / scriptRam); 40 | if (threads > 0) { 41 | exec(script, server, threads, target, moneyThresh, securityThresh); 42 | } 43 | sleep((delay+1)*1000); 44 | } -------------------------------------------------------------------------------- /old/cloud-purchase.script: -------------------------------------------------------------------------------- 1 | // cloud-purchase.script [files...]] 2 | 3 | count = 1; // (args.length > 0) && args[0] || 1; 4 | fundsFraction = 0.93; 5 | funds = fundsFraction * getServerMoneyAvailable('home') / count; 6 | power = Math.floor(Math.log2(funds/50000)); 7 | size = Math.pow(2, power); 8 | 9 | tprint("Purchasing "+count+"x servers with "+size+"GB RAM") 10 | 11 | servers = getPurchasedServers(); 12 | 13 | delCount = count + servers.length - 25; 14 | for (i = 0; i < delCount; i++) { 15 | killall(servers[i]); 16 | } 17 | for (i = 0; i < delCount; i++) { 18 | deleteServer(servers[i]); 19 | } 20 | 21 | for (i = 0; i < count; i++) { 22 | hostname = "pserv"; //-"+(servers.length+i); 23 | hostname = purchaseServer(hostname, size); 24 | for (j = 0; j < args.length; j++) { 25 | scp(args[j], hostname); 26 | } 27 | if (args.length > 0) { 28 | exec(args[0], hostname, 1); 29 | } 30 | } -------------------------------------------------------------------------------- /old/cloud-run-one.script: -------------------------------------------------------------------------------- 1 | // cloud-run-one.script [script] [target] 2 | 3 | script = args[0]; 4 | 5 | servers = getPurchasedServers(); 6 | for (i = 0; i < servers.length; i++) { 7 | server = servers[i]; 8 | threads = 1; 9 | tprint("Running "+threads+"x "+script+" on "+server); 10 | if (threads > 0) { 11 | exec(script, server, threads); 12 | // exec(script, server, threads, args[1] ,args[2] ,args[3] ,args[4] ,args[5] ,args[6] ,args[7] ,args[8] ,args[9] ,args[10]); 13 | } 14 | } -------------------------------------------------------------------------------- /old/cloud-run.script: -------------------------------------------------------------------------------- 1 | // cloud-run.script [script] [target] [arg1] [arg2] 2 | 3 | script = args[0]; 4 | target = args[1]; 5 | arg1 = args[2]; 6 | arg2 = args[3]; 7 | 8 | servers = getPurchasedServers(); 9 | for (i = 0; i < servers.length; i++) { 10 | server = servers[i]; 11 | ram = getServerRam(server); 12 | freeRam = ram[0] - ram[1]; 13 | threads = Math.floor(freeRam / getScriptRam(script, server)); 14 | tprint("Running "+threads+"x "+script+" on "+server); 15 | if (threads > 0) { 16 | exec(script, server, threads, target, arg1, arg2); 17 | } 18 | } -------------------------------------------------------------------------------- /old/cloud-setup.script: -------------------------------------------------------------------------------- 1 | // cloud-setup.script [scripts...] 2 | 3 | servers = getPurchasedServers(); 4 | for (i = 0; i < servers.length; i++) { 5 | server = servers[i]; 6 | killall(server); 7 | for (j = 0; j < args.length; j++) { 8 | script = args[j]; 9 | scp(script, server); 10 | } 11 | } -------------------------------------------------------------------------------- /old/cloud-spawn.script: -------------------------------------------------------------------------------- 1 | // cloud-spawn.script [targets] [scripts] 2 | targets = args[0]; 3 | scripts = ["farm.script"]; 4 | 5 | count = 1; 6 | fundsFraction = 0.25; 7 | funds = fundsFraction * getServerMoneyAvailable('home') / count; 8 | power = Math.floor(Math.log2(funds/50000)); 9 | size = Math.pow(2, power); 10 | 11 | tprint("Purchasing "+count+"x servers with "+size+"GB RAM") 12 | 13 | servers = getPurchasedServers(); 14 | 15 | delCount = count + servers.length - 25; 16 | for (i = 0; i < delCount; i++) { 17 | killall(servers[i]); 18 | } 19 | for (i = 0; i < delCount; i++) { 20 | deleteServer(servers[i]); 21 | } 22 | 23 | hostname = "pserv-"+(servers.length+i); 24 | hostname = purchaseServer(hostname, size); 25 | tprint("Purchased server "+hostname); 26 | scp(scripts[0], hostname); 27 | threads = size / 2.4; // getScriptRam(...) 28 | targetCount = 8; 29 | for (j = Math.max(0,targets.length-1-targetCount); j < targets.length; j++) { 30 | target = targets[j]; 31 | moneyThresh = 0.8 * target.maxMoney; 32 | securityThresh = Math.max(10, target.minSecurityLevel+2); 33 | exec(scripts[0], hostname, threads/targetCount, target.name, moneyThresh, securityThresh); 34 | } -------------------------------------------------------------------------------- /old/create-programs.script: -------------------------------------------------------------------------------- 1 | programs = [ 2 | ["BruteSSH.exe", 50], 3 | ["AutoLink.exe", 25], 4 | ["FTPCrack.exe", 100], 5 | ["relaySMTP.exe", 250], 6 | ["HTTPWorm.exe", 500], 7 | ["SQLInject.exe", 750], 8 | ["DeepScanV2.exe", 750], 9 | ["ServerProfiler.exe", 750] 10 | ]; 11 | 12 | for (i=0; i 0 && args[0] || "deal drugs"; 15 | 16 | while(true) { 17 | delay = commitCrime(crime); 18 | sleep(0.9*delay); 19 | while(isBusy()){ 20 | sleep(0.1*delay); 21 | } 22 | } -------------------------------------------------------------------------------- /old/dequeue-servers.script: -------------------------------------------------------------------------------- 1 | servers = []; 2 | 3 | while (true) { 4 | host = read(1); 5 | if (host === 'NULL PORT DATA') { 6 | break; 7 | } 8 | servers.push(host); 9 | } 10 | 11 | tprint(servers); -------------------------------------------------------------------------------- /old/dist-0port.script: -------------------------------------------------------------------------------- 1 | servers = ["foodnstuff", "sigma-cosmetics", "joesguns", "nectar-net", "hong-fang-tea", "harakiri-sushi"]; 2 | 3 | i = 0; 4 | while (i < servers.length) { 5 | //Wait for player to reach the correct hacking level 6 | while (getHackingLevel() < getServerRequiredHackingLevel(servers[i])) { 7 | sleep(20000); 8 | } 9 | 10 | //Copy our generic hacking script and weaken script over to the target server 11 | scp("early-hack-template.script", servers[i]); 12 | scp("weaken.script", servers[i]); 13 | 14 | //NUKE the target server to gain root access 15 | nuke(servers[i]); 16 | 17 | //Execute our scripts on the target server 18 | if (servers[i] == "joesguns") { 19 | exec("early-hack-template.script", servers[i], 2, servers[i], 50000000, 10); 20 | } else { 21 | exec("early-hack-template.script", servers[i], 2, servers[i], 2000000, 10); 22 | } 23 | exec("weaken.script", servers[i], 1, servers[i]); 24 | 25 | ++i; 26 | } -------------------------------------------------------------------------------- /old/early-hack-template.script: -------------------------------------------------------------------------------- 1 | target = args[0]; 2 | moneyThresh = args[1]; 3 | securityThresh = args[2]; 4 | 5 | while(true) { 6 | if (getServerSecurityLevel(target) > securityThresh) { 7 | //If the server's security level is above our threshold, weaken it 8 | weaken(target); 9 | } else if (getServerMoneyAvailable(target) < moneyThresh) { 10 | //If the server's money is less than our threshold, grow it 11 | grow(target); 12 | } else { 13 | //Otherwise, hack it 14 | hack(target); 15 | } 16 | } -------------------------------------------------------------------------------- /old/enqueue-servers.script: -------------------------------------------------------------------------------- 1 | while (read(1) !== 'NULL PORT DATA') { 2 | // clear the queue 3 | } 4 | 5 | portBusters = ['BruteSSH.exe', 'FTPCrack.exe', 'relaySMTP.exe', 'HTTPWorm.exe', 'SQLInject.exe']; 6 | canBust = 0; 7 | for (i = 0; i < portBusters.length; i++) { 8 | if (fileExists(portBusters[i], "home")) { 9 | canBust++; 10 | } 11 | } 12 | 13 | // sorted by (required ports), then (required hacking level) 14 | hostsByPort = [ 15 | ["foodnstuff", "sigma-cosmetics", "joesguns", "nectar-net", "hong-fang-tea", "harakiri-sushi"], 16 | ["neo-net", "CSEC", "zer0", "max-hardware", "iron-gym"], 17 | ["phantasy", "silver-helix", "omega-net", "avmnite-02h", "crush-fitness", "the-hub", "johnson-ortho"], 18 | ["I.I.I.I", "comptek", "netlink", "rothman-uni", "catalyst", "summit-uni", "rho-construction", "millenium-fitness"], 19 | ["aevum-police", "alpha-ent", "syscore", "lexo-corp", "snap-fitness", "global-pharm", "unitalife", "univ-energy"], 20 | ["zb-institute", "galactic-cyber", "solaris", "zeus-med", "aerocorp", "deltaone", "omnia", "defcomm", "icarus"] 21 | ]; 22 | 23 | maxLevel = Math.min(hostsByPort.length, canBust+1); 24 | for (i = 0; i < maxLevel; i++) { 25 | for (j = 0; j < hostsByPort[i].length; j++) { 26 | host = hostsByPort[i][j]; 27 | write(1, host); 28 | } 29 | } -------------------------------------------------------------------------------- /old/farm-init.script: -------------------------------------------------------------------------------- 1 | target = args[0]; 2 | maxMoney = args[1]; 3 | minSecurityLevel = args[2]; 4 | host = getHostname(); 5 | script = 'farm.script'; 6 | 7 | while (!hasRootAccess(target)) { 8 | sleep(60*1000); 9 | } 10 | 11 | moneyThresh = 0.8 * maxMoney; 12 | securityThresh = Math.max(10, minSecurityLevel+2); 13 | ram = getServerRam(host); 14 | freeRam = ram[0] - ram[1]; 15 | scriptRam = 2.4; //getScriptRam(script, host); 16 | ramFraction = 0.1; 17 | threads = ramFraction * (freeRam / scriptRam); 18 | threads = Math.floor(threads); 19 | 20 | tprint("Running "+threads+"x "+script+" on "+host); 21 | if (threads > 0) { 22 | run(script, threads, target, moneyThresh, securityThresh); 23 | } -------------------------------------------------------------------------------- /old/farm.script: -------------------------------------------------------------------------------- 1 | // run farm.script [target] [moneyThresh] [securityThresh] 2 | 3 | target = args[0]; 4 | moneyThresh = args[1]; 5 | securityThresh = args[2]; 6 | 7 | while(true) { 8 | if (getServerSecurityLevel(target) > securityThresh) { 9 | //If the server's security level is above our threshold, weaken it 10 | weaken(target); 11 | } else if (getServerMoneyAvailable(target) < moneyThresh) { 12 | //If the server's money is less than our threshold, grow it 13 | grow(target); 14 | } else { 15 | //Otherwise, hack it 16 | hack(target); 17 | } 18 | } -------------------------------------------------------------------------------- /old/find-contracts.ns: -------------------------------------------------------------------------------- 1 | import {getAllHosts} from "lib.ns"; 2 | 3 | export async function main(ns) { 4 | for (const host of getAllHosts(ns)) { 5 | for (const file of ns.ls(host)) { 6 | if (file.match(/\.cct$/)) { 7 | ns.tprint(`${host}: ${file}`); 8 | } 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /old/find-farms.script: -------------------------------------------------------------------------------- 1 | keepRam = args.length > 0 && args[0] || 0; 2 | c = 'constructor'; 3 | f = [c][c][c]; 4 | // json = f('return JSON')(); 5 | makeObj = f('a', 'o = {}; for (var i = 0; i < a.length; i=i+2) {o[a[i]] = a[i+1]} return o;'); 6 | setObj = f('o', 'a', 'for (var i = 0; i < a.length; i=i+2) {o[a[i]] = a[i+1]} return o;'); 7 | 8 | allHosts = ["iron-gym","foodnstuff","sigma-cosmetics","joesguns","hong-fang-tea","harakiri-sushi","nectar-net","max-hardware","CSEC","zer0","phantasy","omega-net","neo-net","silver-helix","netlink","the-hub","comptek","johnson-ortho","avmnite-02h","crush-fitness","catalyst","zb-institute","syscore","summit-uni","I.I.I.I","rothman-uni","alpha-ent","lexo-corp","millenium-fitness","rho-construction","aevum-police","global-pharm","aerocorp","galactic-cyber","snap-fitness","unitalife","deltaone","omnia","zeus-med","univ-energy","solaris","icarus","defcomm","taiyang-digital","infocomm","nova-med","zb-def","applied-energetics","microdyne","run4theh111z","titan-labs","helios","vitalife","stormtech","fulcrumtech","kuai-gong","4sigma","omnitek",".","powerhouse-fitness","clarkeinc","blade","b-and-a","nwo","The-Cave","megacorp","ecorp"]; // "fulcrumassets" 9 | // allHosts = ["fulcrumassets"]; 10 | 11 | getters = makeObj(["serverExists", serverExists, "hasRootAccess", hasRootAccess, "getServerMoneyAvailable", getServerMoneyAvailable, "getServerMaxMoney", getServerMaxMoney, "getServerGrowth", getServerGrowth, "getServerSecurityLevel", getServerSecurityLevel, "getServerBaseSecurityLevel", getServerBaseSecurityLevel, "getServerMinSecurityLevel", getServerMinSecurityLevel, "getServerRequiredHackingLevel", getServerRequiredHackingLevel, "getServerNumPortsRequired", getServerNumPortsRequired, "getServerRam", getServerRam, "getHackTime", getHackTime, "getGrowTime", getGrowTime, "getWeakenTime", getWeakenTime, "getHackingLevel", getHackingLevel]); 12 | getInfo = f('host', 'return {name: host, maxMoney: this.getServerMaxMoney(host), growth: this.getServerGrowth(host), baseSecurityLevel: this.getServerBaseSecurityLevel(host), minSecurityLevel: this.getServerMinSecurityLevel(host), requiredHackingLevel: this.getServerRequiredHackingLevel(host), numPortsRequired: this.getServerNumPortsRequired(host), maxRam: this.getServerRam(host)[0], hackTime: this.getHackTime(host), growTime: this.getGrowTime(host), weakenTime: this.getWeakenTime(host)}').bind(getters); 13 | allServers = allHosts.map(getInfo); 14 | 15 | hasMoney = f('server', 'return server.maxMoney > 0'); 16 | canHack = f('server', 'return (this.hasRootAccess(server.name) && server.requiredHackingLevel < this.getHackingLevel())').bind(getters); 17 | byHackReq = f('a', 'b', 'return a.requiredHackingLevel - b.requiredHackingLevel'); 18 | hackableServers = allServers.filter(hasMoney).filter(canHack).sort(byHackReq); 19 | 20 | // serversByHackReq = serversWithMoney.sort(byHackReq); 21 | // getName = f('server', 'return server.name'); 22 | // hostsByHackReq = serversByHackReq.map(getName); 23 | // tprint(json.stringify(hostsByHackReq)); 24 | // hackableHosts = ["foodnstuff","sigma-cosmetics","joesguns","nectar-net","hong-fang-tea","harakiri-sushi","neo-net","zer0","max-hardware","iron-gym","phantasy","silver-helix","omega-net","crush-fitness","johnson-ortho","the-hub","comptek","rothman-uni","netlink","aevum-police","catalyst","summit-uni","rho-construction","millenium-fitness","alpha-ent","syscore","zb-institute","lexo-corp","snap-fitness","global-pharm","zb-def","nova-med","microdyne","titan-labs","unitalife","solaris","univ-energy","helios","applied-energetics","zeus-med","galactic-cyber","aerocorp","deltaone","icarus","vitalife","defcomm","omnia","taiyang-digital","infocomm","stormtech","kuai-gong","fulcrumtech","omnitek","powerhouse-fitness","b-and-a","blade","nwo","4sigma","clarkeinc","ecorp","megacorp","fulcrumassets"]; 25 | 26 | host = getHostname(); 27 | ram = getServerRam(host); 28 | freeRam = ram[0] - ram[1] - keepRam; 29 | script = "farm.script"; 30 | scriptRam = 2.4; 31 | threads = Math.floor(freeRam / scriptRam / hackableServers.length); 32 | 33 | for (i = 0; i < hackableServers.length; i++) { 34 | server = hackableServers[i]; 35 | target = server.name; 36 | moneyThresh = 0.8 * server.maxMoney; 37 | securityThresh = Math.max(10, server.minSecurityLevel+2); 38 | 39 | print("Running "+threads+"x "+script+" "+target+" on "+host); 40 | if (threads > 0) { 41 | run(script, threads, target, moneyThresh, securityThresh); 42 | } 43 | } -------------------------------------------------------------------------------- /old/find-targets.script: -------------------------------------------------------------------------------- 1 | //Define Variables 2 | currentScanLength = 0; 3 | scanArray = ['home']; 4 | Servers = []; 5 | ServersM = []; // Money 6 | ServersHL = []; // HackingLevel 7 | ServersHP = []; // HackingPorts 8 | ServersP = []; // Profits 9 | basehackinglevel = -101; 10 | target = 'foodnstuff'; 11 | host = getHostname(); 12 | mults = getHackingMultipliers(); 13 | 14 | //Skill Multiplier Constants 15 | hackmult = mults.money; 16 | growmult = mults.growth; 17 | //Bitnode Multiplier Constants, update after changing Bitnodes 18 | bitnodehackmult = 1.0000; 19 | bitnodegrowmult = 1.0000; 20 | bitnodeweakenmult = 1.0000; 21 | 22 | 23 | //Scan Loop 24 | while (currentScanLength < scanArray.length) { 25 | currentHost = scanArray[currentScanLength]; 26 | newScan = scan(currentHost); 27 | for (j = 0; j < newScan.length; j++) { 28 | if (scanArray.indexOf(newScan[j]) == -1) { 29 | scanArray.push(newScan[j]); 30 | money = getServerMaxMoney(newScan[j]); 31 | if (money > 0) { 32 | Servers.push(newScan[j]); 33 | ServersM.push(money); 34 | ServersHP.push(getServerNumPortsRequired(newScan[j])); 35 | ServersHL.push(getServerRequiredHackingLevel(newScan[j])); 36 | time = 2 * getWeakenTime(newScan[j]) + getGrowTime(newScan[j]) + getHackTime(newScan[j]); 37 | profit = round(money / time); 38 | ServersP.push(profit); 39 | } 40 | } 41 | } 42 | currentScanLength++; 43 | } 44 | 45 | portBusters = ['BruteSSH.exe', 'FTPCrack.exe', 'relaySMTP.exe', 'HTTPWorm.exe', 'SQLInject.exe']; 46 | numPortBreakers = 0; 47 | for (i = 0; i < portBusters.length; i++) { 48 | if (fileExists(portBusters[i], 'home')) { 49 | numPortBreakers++; 50 | } 51 | } 52 | 53 | hackinglevel = getHackingLevel(); 54 | print(basehackinglevel); 55 | 56 | //Recalc & RetargetProfits if Hacking level has increased by 100 57 | if (hackinglevel > basehackinglevel + 100) { 58 | basehackinglevel = hackinglevel; 59 | //Reset Profits 60 | ServersP = []; 61 | for (j = 0; j < Servers.length; j++) { 62 | time = 2 * getWeakenTime(Servers[j]) + getGrowTime(Servers[j]) + getHackTime(Servers[j]); 63 | profit = round(ServersM[j] / time); 64 | ServersP.push(profit); 65 | } 66 | 67 | print(Servers); 68 | print('Create Eligable Target List'); 69 | targetlist = []; 70 | targetlistP = []; 71 | for (j = 0; j < Servers.length; j++) { 72 | if (ServersHP[j] <= numPortBreakers && ServersHL[j] <= hackinglevel) { 73 | targetlist.push(Servers[j]); 74 | targetlistP.push(ServersP[j]); 75 | } 76 | } 77 | 78 | print(targetlist); 79 | print('Find Optimal Target List'); 80 | 81 | OptimalTargetList = []; 82 | OptimalTargetListM = []; 83 | OptimalTargetListG = []; 84 | OptimalTargetListHL = []; 85 | OptimalTargetListMS = []; 86 | 87 | for (i = 0; i < Math.min(targetlist.length,10); i++) { 88 | targetmaxprofit = 0; 89 | for (j = 0; j < targetlist.length; j++) { 90 | if (targetlistP[j] > targetmaxprofit) { 91 | targetmaxprofit = targetlistP[j]; 92 | } 93 | } 94 | index = targetlistP.indexOf(targetmaxprofit); 95 | OptimalTargetList.push(targetlist[index]); 96 | OptimalTargetListG.push(getServerGrowth(targetlist[index])); 97 | OptimalTargetListHL.push(getServerRequiredHackingLevel(targetlist[index])); 98 | OptimalTargetListMS.push(Math.max(round(getServerBaseSecurityLevel(targetlist[index])/3),1)); 99 | OptimalTargetListM.push(getServerMaxMoney(targetlist[index])); 100 | targetlistP[index] = 0; 101 | } 102 | tprint(OptimalTargetList); 103 | 104 | } -------------------------------------------------------------------------------- /old/get-info.script: -------------------------------------------------------------------------------- 1 | // get-info.script 2 | startTime = Date.now(); 3 | 4 | host = args[0]; 5 | 6 | c ='constructor' 7 | f = [c][c][c] 8 | makeObj = f('a', 'o = {}; for (var i = 0; i < a.length; i=i+2) {o[a[i]] = a[i+1]} return o;'); 9 | setObj = f('o', 'a', 'for (var i = 0; i < a.length; i=i+2) {o[a[i]] = a[i+1]} return o;'); 10 | 11 | server = makeObj([ 12 | 'exists', serverExists(host), 13 | 'hasRootAccess', hasRootAccess(host), 14 | 'moneyAvailable', getServerMoneyAvailable(host), 15 | 'maxMoney', getServerMaxMoney(host), 16 | 'growth', getServerGrowth(host), 17 | 'securityLevel', getServerSecurityLevel(host), 18 | 'baseSecurityLevel', getServerBaseSecurityLevel(host), 19 | 'minSecurityLevel', getServerMinSecurityLevel(host), 20 | 'requiredHackingLevel', getServerRequiredHackingLevel(host), 21 | 'numPortsRequired', getServerNumPortsRequired(host), 22 | 'ram', getServerRam(host), 23 | 'hackTime', getHackTime(host), 24 | 'growTime', getGrowTime(host), 25 | 'weakenTime', getWeakenTime(host) 26 | ]); 27 | profit = server.maxMoney / (2*server.weakenTime + server.growTime + server.hackTime); 28 | server = setObj(server, ['profit', profit]); 29 | 30 | 31 | 32 | portBusters = ['BruteSSH.exe', 'FTPCrack.exe', 'relaySMTP.exe', 'HTTPWorm.exe', 'SQLInject.exe']; 33 | canGetPorts = 0; 34 | for (i = 0; i < portBusters.length; i++) { 35 | if (fileExists(portBusters[i], "home")) { 36 | canGetPorts++; 37 | } 38 | } 39 | haveHacking = getHackingLevel(); 40 | 41 | tprint(host+": Ports: "+[canGetPorts, server.numPortsRequired].join(" / ")+(server.hasRootAccess && ' √' || '')); 42 | 43 | // canNuke = (canGetPorts >= server.numPortsRequired); 44 | // canHack = canNuke && (haveHacking >= server.requiredHackingLevel); 45 | tprint(host+": Hacking: "+[haveHacking, server.requiredHackingLevel].join(" / ")+(haveHacking >= server.requiredHackingLevel && ' √' || '')); 46 | 47 | sec = [server.minSecurityLevel, server.securityLevel.toFixed(1), server.baseSecurityLevel]; 48 | tprint(host+": Security: "+sec.join(" < ")); 49 | 50 | moneyPct = 100*(server.moneyAvailable/(server.maxMoney+1)); 51 | tprint(host+": Money: "+Math.floor(server.moneyAvailable)+" / "+server.maxMoney+" ("+moneyPct.toFixed(1)+"%)"); 52 | tprint(host+": Growth: "+server.growth); 53 | tprint(host+": Hack: "+round(server.hackTime)+"s, Grow: "+round(server.growTime)+"s, Weaken: "+round(server.weakenTime)+"s"); 54 | tprint(host+": Profit: "+round(0.003*profit)+"/s"); 55 | 56 | tprint(host+": Ram: "+[server.ram[1], server.ram[0]].join(' / ')); -------------------------------------------------------------------------------- /old/getInfo.script: -------------------------------------------------------------------------------- 1 | tprint(getPlayer()); 2 | tprint(getServer(args[0])); -------------------------------------------------------------------------------- /old/grow.script: -------------------------------------------------------------------------------- 1 | // grow.script [target] [growTime] 2 | target = args[0]; 3 | growTime = args[2]*1000; 4 | 5 | while (true) { 6 | weakenTime = growTime*20/16; 7 | delay = weakenTime-growTime; 8 | sleep(delay); 9 | startTime = Date.now(); 10 | grow(args[0]); 11 | growTime = Date.now() - startTime; 12 | } -------------------------------------------------------------------------------- /old/hack.script: -------------------------------------------------------------------------------- 1 | // hack.script [target] 2 | 3 | while(true){ 4 | hack(args[0]); 5 | } -------------------------------------------------------------------------------- /old/hacknet.script: -------------------------------------------------------------------------------- 1 | if (hacknetnodes.length < 1) { 2 | purchaseHacknetNode(); 3 | } 4 | 5 | //1% of current funds, per cycle. 6 | allowancePercentage = 0.01; 7 | while (true) { 8 | for (i = 0; i < hacknetnodes.length; i++) { 9 | gain = [0,0,0]; 10 | currentCash = getServerMoneyAvailable('home'); 11 | currentCash *= allowancePercentage; 12 | 13 | if (getNextHacknetNodeCost() <= currentCash) { 14 | purchaseHacknetNode(); 15 | } 16 | 17 | node = hacknetnodes[i]; 18 | 19 | if (node.level < 200) { 20 | gain[0] = ((node.level + 1) * 1.6) * Math.pow(1.035, (node.ram - 1)) * ((node.cores + 5) / 6) / node.getLevelUpgradeCost(1); 21 | } else { 22 | gain[0] = 0; 23 | } 24 | 25 | if (node.ram < 64) { 26 | gain[1] = (node.level * 1.6) * Math.pow(1.035, (node.ram * 2) - 1) * ((node.cores + 5) / 6) /node.getRamUpgradeCost(); 27 | } else { 28 | gain[1] = 0; 29 | } 30 | 31 | if (node.cores < 16) { 32 | gain[2] = (node.level * 1.6) * Math.pow(1.035, node.ram - 1) * ((node.cores + 6) / 6) / node.getCoreUpgradeCost(); 33 | } else { 34 | gain[2] = 0; 35 | } 36 | 37 | print('Level Upgrade: ' + gain[0]); 38 | print('Ram Upgrade: ' + gain[1]); 39 | print('Core Upgrade: ' + gain[2]); 40 | 41 | topgain = 0; 42 | 43 | for (j = 0; j < 3; j++) { 44 | if (gain[j] > topgain) { 45 | topgain = gain[j]; 46 | } 47 | } 48 | 49 | if (topgain === 0) { 50 | print('All Gains maxed on Node' + i); 51 | break; 52 | } 53 | 54 | if (topgain == gain[0] && node.getLevelUpgradeCost(1) < currentCash) { 55 | print('Upgrading Level on Node' + i); 56 | node.upgradeLevel(1); 57 | } else if (topgain == gain[1] && node.getRamUpgradeCost(1) < currentCash) { 58 | print('Upgrading Ram on Node' + i); 59 | node.upgradeRam(); 60 | } else if (topgain == gain[2] && node.getCoreUpgradeCost(1) < currentCash) { 61 | print('Upgrading Core on Node' + i); 62 | node.upgradeCore(); 63 | } else { 64 | print('Cannot afford upgrades on Node' + i); 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /old/init-aug.script: -------------------------------------------------------------------------------- 1 | // toScan = [getHostname()]; 2 | // scanned = []; 3 | // hostsByPort = [[], [], [], [], [], []]; 4 | 5 | // f = ''.constructor.constructor; 6 | // json = f('return JSON')(); 7 | // makeObj = f('a', 'o = {}; for (var i = 0; i < a.length; i=i+2) {o[a[i]] = a[i+1]} return o;'); 8 | // setObj = f('o', 'a', 'for (var i = 0; i < a.length; i=i+2) {o[a[i]] = a[i+1]} return o;'); 9 | // notIncludes = f('x', 'return !this.includes(x)'); 10 | // getters = makeObj(["serverExists", serverExists, "hasRootAccess", hasRootAccess, "getServerMoneyAvailable", getServerMoneyAvailable, "getServerMaxMoney", getServerMaxMoney, "getServerGrowth", getServerGrowth, "getServerSecurityLevel", getServerSecurityLevel, "getServerBaseSecurityLevel", getServerBaseSecurityLevel, "getServerMinSecurityLevel", getServerMinSecurityLevel, "getServerRequiredHackingLevel", getServerRequiredHackingLevel, "getServerNumPortsRequired", getServerNumPortsRequired, "getServerRam", getServerRam, "getHackTime", getHackTime, "getGrowTime", getGrowTime, "getWeakenTime", getWeakenTime]); 11 | // getInfo = f('host', 'return {name: host, maxMoney: this.getServerMaxMoney(host), growth: this.getServerGrowth(host), baseSecurityLevel: this.getServerBaseSecurityLevel(host), minSecurityLevel: this.getServerMinSecurityLevel(host), requiredHackingLevel: this.getServerRequiredHackingLevel(host), numPortsRequired: this.getServerNumPortsRequired(host), maxRam: this.getServerRam(host)[0], hackTime: this.getHackTime(host), growTime: this.getGrowTime(host), weakenTime: this.getWeakenTime(host)}').bind(getters); 12 | 13 | portBusters = ['BruteSSH.exe', 'FTPCrack.exe', 'relaySMTP.exe', 'HTTPWorm.exe', 'SQLInject.exe']; 14 | portBusterFuncs = [brutessh, ftpcrack, relaysmtp, httpworm, sqlinject]; 15 | 16 | function crack(target) { 17 | if (!hasRootAccess(target)) { 18 | tprint("Cracking server "+target); 19 | for (i = 0; i < portBusters.length; i++) { 20 | if (fileExists(portBusters[i], 'home')) { 21 | portBusterFuncs[i](target); 22 | } 23 | } 24 | nuke(target); 25 | } 26 | } 27 | 28 | function playerPortLevel() { 29 | portLevel = fileExists('BruteSSH.exe','home') + fileExists('FTPCrack.exe','home') + fileExists('relaySMTP.exe','home') + fileExists('HTTPWorm.exe','home') + fileExists('SQLInject.exe','home'); 30 | return portLevel; 31 | } 32 | // if (false) { 33 | // while (toScan.length > 0) { 34 | // host = toScan.shift(); 35 | // if (!scanned.includes(host)) { 36 | // tprint("Scanning "+host); 37 | // scanned.push(host); 38 | // results = scan(host); 39 | // // newResults = results.filter(notIncludes.bind(scanned)); 40 | // toScan = toScan.concat(results); 41 | 42 | // portReq = getServerNumPortsRequired(host); 43 | // hostsByPort[portReq].push(host); 44 | // } 45 | // } 46 | // } 47 | 48 | // tprint("Discovered "+scanned.length+" servers: "+json.stringify(hostsByPort)); 49 | 50 | hostsByPort = [ 51 | ["foodnstuff","sigma-cosmetics","joesguns","hong-fang-tea","harakiri-sushi","nectar-net"], 52 | ["iron-gym","max-hardware","zer0","CSEC","neo-net"], 53 | ["omega-net","silver-helix","phantasy","the-hub","johnson-ortho","crush-fitness","avmnite-02h"], 54 | ["netlink","comptek","catalyst","summit-uni","rothman-uni","I.I.I.I","millenium-fitness","rho-construction"], 55 | ["syscore","lexo-corp","aevum-police","alpha-ent","global-pharm","snap-fitness","unitalife","univ-energy","nova-med","zb-def","applied-energetics","run4theh111z","."], 56 | ["zb-institute","galactic-cyber","aerocorp","omnia","deltaone","icarus","solaris","defcomm","zeus-med","taiyang-digital","infocomm","microdyne","titan-labs","helios","stormtech","vitalife","fulcrumtech","4sigma","omnitek","kuai-gong","powerhouse-fitness","clarkeinc","blade","b-and-a","nwo","megacorp","fulcrumassets","ecorp","The-Cave"] 57 | ] 58 | 59 | portLevel = playerPortLevel(); 60 | for (i = 0; i < hostsByPort.length; i++) { 61 | while (portLevel < i) { 62 | sleep(60*1000); 63 | portLevel = playerPortLevel(); 64 | } 65 | for (j = 0; j < hostsByPort[i].length; j++) { 66 | host = hostsByPort[i][j]; 67 | crack(host); 68 | target = "joesguns"; 69 | if (getServerMaxMoney(host) > 0 && getServerRequiredHackingLevel(host) <= getHackingLevel()) { 70 | target = host; 71 | } 72 | moneyThresh = 0.8 * getServerMaxMoney(target); 73 | securityThresh = Math.min(10, getServerMinSecurityLevel(target)+2); 74 | 75 | script = "farm.script"; 76 | scp(script, host); 77 | 78 | ram = getServerRam(host); 79 | freeRam = ram[0] - ram[1]; 80 | threads = freeRam / getScriptRam(script, host); 81 | threads = Math.floor(threads); 82 | if (threads >= 1) { 83 | tprint("Running "+threads+"x "+script+" "+target+" on "+host); 84 | exec(script, host, threads, target, moneyThresh, securityThresh); 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /old/init-bitnode.script: -------------------------------------------------------------------------------- 1 | // init-bitnode.script 2 | // goal: get cashRoot starter kit and upgrade home RAM 3 | 4 | function money(){ 5 | return (getServerMoneyAvailable)("home"); 6 | } 7 | function killTime() { 8 | // universityCourse("Rothman University", "Study Computer Science"); 9 | sleep((commitCrime)("larceny")); 10 | // sleep(60*1000); 11 | } 12 | 13 | run("init-aug.script"); 14 | 15 | programs = [ 16 | ["BruteSSH.exe", 800000], 17 | ["FTPCrack.exe", 2000000], 18 | ["relaySMTP.exe", 5000000] 19 | ]; 20 | for (i=0; i 0 && args[0] || 0; 3 | self = 'home'; //getHostname(); 4 | 5 | portBusters = ['BruteSSH.exe', 'FTPCrack.exe', 'relaySMTP.exe', 'HTTPWorm.exe', 'SQLInject.exe']; 6 | canBust = 0; 7 | for (i = 0; i < portBusters.length; i++) { 8 | if (fileExists(portBusters[i], "home")) { 9 | canBust++; 10 | } 11 | } 12 | 13 | // sorted by (required ports), then (required hacking level) 14 | hostsByPort = [ 15 | ["foodnstuff", "sigma-cosmetics", "joesguns", "nectar-net", "hong-fang-tea", "harakiri-sushi"], 16 | ["neo-net", "CSEC", "zer0", "max-hardware", "iron-gym"], 17 | ["phantasy", "silver-helix", "omega-net", "avmnite-02h", "crush-fitness", "the-hub", "johnson-ortho"], 18 | ["I.I.I.I", "comptek", "netlink", "rothman-uni", "catalyst", "summit-uni", "rho-construction", "millenium-fitness"], 19 | ["aevum-police", "alpha-ent", "syscore", "lexo-corp", "snap-fitness", "global-pharm", "unitalife", "univ-energy"], 20 | ["zb-institute", "galactic-cyber", "solaris", "zeus-med", "aerocorp", "deltaone", "omnia", "defcomm", "icarus"] 21 | ]; 22 | 23 | for (i = startPort; i < hostsByPort.length; i++) { 24 | if (canBust >= i) { 25 | for (j = 0; j < hostsByPort[i].length; j++) { 26 | host = hostsByPort[i][j]; 27 | if (serverExists(host)) { 28 | //tprint("Trying server "+host); 29 | if (!hasRootAccess(host)) { 30 | tprint("Cracking server "+host); 31 | portBusters = ['BruteSSH.exe', 'FTPCrack.exe', 'relaySMTP.exe', 'HTTPWorm.exe', 'SQLInject.exe']; 32 | for (k = 0; k < portBusters.length; k++) { 33 | if (fileExists(portBusters[k], "home")) { 34 | if (k === 0) { 35 | brutessh(host); 36 | } 37 | if (k === 1) { 38 | ftpcrack(host); 39 | } 40 | if (k === 2) { 41 | relaysmtp(host); 42 | } 43 | if (k === 3) { 44 | httpworm(host); 45 | } 46 | if (k === 4) { 47 | sqlinject(host); 48 | } 49 | } 50 | } 51 | nuke(host); 52 | } 53 | //killall(host); 54 | // sleep(1000); 55 | target = "joesguns"; 56 | if (getServerMaxMoney(host) > 0) { 57 | target = host; 58 | //if (getHackingLevel() >= getServerRequiredHackingLevel(host)) { 59 | // run("farm-init.script", 1, host); 60 | //} 61 | } 62 | 63 | script = "maintain.script"; 64 | scp(script, host); 65 | 66 | ram = getServerRam(host); 67 | freeRam = ram[0] - ram[1]; 68 | threads = freeRam / getScriptRam(script, host); 69 | threads = Math.floor(threads); 70 | tprint("Running "+threads+"x "+script+" on "+host); 71 | if (threads >= 1) { 72 | exec(script, host, threads, target); 73 | } 74 | // while (getServerRequiredHackingLevel(host) > getHackingLevel()) { 75 | // sleep(15000); 76 | // } 77 | // run(script, 1, host); 78 | // while(scriptRunning(script, self)) { 79 | // sleep(1000); 80 | // } 81 | } 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /old/letmein.script: -------------------------------------------------------------------------------- 1 | // letmein.script [host...] 2 | for (h = 0; h < args.length; h++) { 3 | host = args[h]; 4 | if (!hasRootAccess(host)) { 5 | tprint("Cracking server "+host); 6 | portBusters = ['BruteSSH.exe', 'FTPCrack.exe', 'relaySMTP.exe', 'HTTPWorm.exe', 'SQLInject.exe']; 7 | for (i = 0; i < portBusters.length; i++) { 8 | if (fileExists(portBusters[i], "home")) { 9 | if (i === 0) { 10 | brutessh(host); 11 | } 12 | if (i === 1) { 13 | ftpcrack(host); 14 | } 15 | if (i === 2) { 16 | relaysmtp(host); 17 | } 18 | if (i === 3) { 19 | httpworm(host); 20 | } 21 | if (i === 4) { 22 | sqlinject(host); 23 | } 24 | } 25 | } 26 | nuke(host); 27 | tprint("Cracked server "+host); 28 | } 29 | } -------------------------------------------------------------------------------- /old/list-servers.ns: -------------------------------------------------------------------------------- 1 | // scan-bfs.ns 2 | 3 | import {getAllHosts, groupByPortReq} from "lib.ns"; 4 | 5 | export async function main(ns) { 6 | const hosts = await getAllHosts(ns); 7 | ns.tprint("Discovered " + hosts.length + " servers: " + hosts); 8 | ns.tprint(groupByPortReq(ns, hosts)); 9 | } -------------------------------------------------------------------------------- /old/maintain.script: -------------------------------------------------------------------------------- 1 | while(true){ 2 | weaken(args[0]); 3 | grow(args[0]); 4 | } -------------------------------------------------------------------------------- /old/manage-stocks.script: -------------------------------------------------------------------------------- 1 | while(true) { 2 | run("buy-stocks.script"); 3 | 4 | sleep(1000*60*30); 5 | 6 | run("sell-bear.script"); 7 | 8 | sleep(1000*30); 9 | 10 | run("buy-stocks.script"); 11 | 12 | sleep(1000*60*60*4); 13 | 14 | run("sell-stocks.script"); 15 | 16 | sleep(1000*30); 17 | } -------------------------------------------------------------------------------- /old/map.ns: -------------------------------------------------------------------------------- 1 | // scan-dfs.script [start]; 2 | // depth-first search, like scan-analyze 3 | 4 | import {scanNetwork} from "lib.ns"; 5 | 6 | export async function main(ns) { 7 | const entry = ns.getHostname(); 8 | if (ns.args.length == 0) { 9 | let hosts = scanNetwork(ns, entry, null, true); 10 | } 11 | else { 12 | const target = ns.args[0]; 13 | let hosts = scanNetwork(ns, entry, target, false); 14 | } 15 | //ns.tprint("Discovered "+hosts.length+" servers: "+hosts); 16 | } -------------------------------------------------------------------------------- /old/purchase-server-4gb.script: -------------------------------------------------------------------------------- 1 | i = 0; 2 | while(i < 25) { 3 | if (getServerMoneyAvailable("home") > 200000) { 4 | hostname = purchaseServer("pserv-" + i, 4); 5 | scp("early-hack-template.script", hostname); 6 | exec("early-hack-template.script", hostname, 1, "joesguns", 50000000, 10); 7 | ++i; 8 | } 9 | } -------------------------------------------------------------------------------- /old/remote-manage.script: -------------------------------------------------------------------------------- 1 | // remote-manage.script [hosts...] 2 | 3 | scripts = ["weaken", "grow", "hack"]; 4 | 5 | while (true) { 6 | for (i = 0; i < args.length; i++) { 7 | host = args[i]; 8 | moneyThresh = getServerMaxMoney(host)*0.8; 9 | securityThresh = Math.max(10, getServerMinSecurityLevel(host)+1); 10 | 11 | if (getServerSecurityLevel(host) > securityThresh) { 12 | script = "weaken.script"; 13 | } else if (getServerMoneyAvailable(host) < moneyThresh) { 14 | script = "grow.script"; 15 | } else { 16 | script = "hack.script"; 17 | } 18 | 19 | ram = getServerRam(host); 20 | freeRam = ram[0] - ram[1]; 21 | threads = Math.floor(freeRam / getScriptRam(script, host)); 22 | print("Running "+threads+"x "+script+" on "+host); 23 | if (threads >= 1) { 24 | exec(script, host, threads, host, moneyThresh, securityThresh); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /old/remote-run-one.script: -------------------------------------------------------------------------------- 1 | // remote-run.script [script] [hosts...] 2 | 3 | script = args[0]; 4 | 5 | for (i = 1; i < args.length; i++) { 6 | host = args[i]; 7 | 8 | scp(script, host); 9 | 10 | threads = 1; 11 | print("Running "+threads+"x "+script+" on "+host); 12 | if (threads >= 1) { 13 | exec(script, host, threads, host); 14 | } 15 | } -------------------------------------------------------------------------------- /old/remote-run.script: -------------------------------------------------------------------------------- 1 | // remote-run.script [script] [hosts...] 2 | 3 | script = args[0]; 4 | 5 | for (i = 1; i < args.length; i++) { 6 | host = args[i]; 7 | 8 | scp(script, host); 9 | 10 | ram = getServerRam(host); 11 | freeRam = ram[0] - ram[1]; 12 | threads = Math.floor(freeRam / getScriptRam(script, host)); 13 | print("Running "+threads+"x "+script+" on "+host); 14 | if (threads >= 1) { 15 | exec(script, host, threads, host); 16 | } 17 | } -------------------------------------------------------------------------------- /old/remote-setup.script: -------------------------------------------------------------------------------- 1 | // remote-setup.script [hosts...] 2 | 3 | scripts = ["weaken", "grow", "hack", "maintain", "early-hack-template"]; 4 | 5 | for (i = 0; i < args.length; i++) { 6 | host = args[i]; 7 | if (getServerMaxMoney(host) > 0) { 8 | if (!hasRootAccess(host)) { 9 | tprint("Cracking server "+host); 10 | portBusters = ['BruteSSH.exe', 'FTPCrack.exe', 'relaySMTP.exe', 'HTTPWorm.exe', 'SQLInject.exe']; 11 | for (i = 0; i < portBusters.length; i++) { 12 | if (fileExists(portBusters[i], "home")) { 13 | if (i === 0) { 14 | brutessh(host); 15 | } 16 | if (i === 1) { 17 | ftpcrack(host); 18 | } 19 | if (i === 2) { 20 | relaysmtp(host); 21 | } 22 | if (i === 3) { 23 | httpworm(host); 24 | } 25 | if (i === 4) { 26 | sqlinject(host); 27 | } 28 | } 29 | } 30 | nuke(host); 31 | } 32 | tprint("Preparing server "+host); 33 | killall(host); 34 | for (k = 0; k < scripts.length; k++) { 35 | scp(scripts[k]+".script", host); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /old/scan-bfs.script: -------------------------------------------------------------------------------- 1 | toScan = [getHostname()]; 2 | scanned = []; 3 | 4 | newFunc = ''.constructor.constructor; 5 | notIncludes = newFunc('x', 'return !this.includes(x)'); 6 | 7 | while (toScan.length > 0) { 8 | host = toScan.shift(); 9 | scanned.push(host); 10 | results = scan(host); 11 | newResults = results.filter(notIncludes.bind(scanned)); 12 | toScan = toScan.concat(newResults); 13 | } 14 | 15 | tprint("Discovered "+scanned.length+" servers: "+scanned); 16 | 17 | /* 18 | home 19 | iron-gym 20 | foodnstuff 21 | sigma-cosmetics 22 | joesguns 23 | hong-fang-tea 24 | harakiri-sushi 25 | darkweb 26 | nectar-net 27 | max-hardware 28 | CSEC 29 | zer0 30 | phantasy 31 | omega-net 32 | neo-net 33 | silver-helix 34 | netlink 35 | the-hub 36 | comptek 37 | johnson-ortho 38 | avmnite-02h 39 | crush-fitness 40 | catalyst 41 | zb-institute 42 | syscore 43 | summit-uni 44 | I.I.I.I 45 | rothman-uni 46 | alpha-ent 47 | lexo-corp 48 | millenium-fitness 49 | rho-construction 50 | aevum-police 51 | global-pharm 52 | aerocorp 53 | galactic-cyber 54 | snap-fitness 55 | unitalife 56 | deltaone 57 | omnia 58 | zeus-med 59 | univ-energy 60 | solaris 61 | icarus 62 | defcomm 63 | taiyang-digital 64 | infocomm 65 | nova-med 66 | zb-def 67 | applied-energetics 68 | microdyne 69 | run4theh111z 70 | titan-labs 71 | helios 72 | vitalife 73 | stormtech 74 | fulcrumtech 75 | kuai-gong 76 | 4sigma 77 | omnitek 78 | . 79 | powerhouse-fitness 80 | clarkeinc 81 | blade 82 | b-and-a 83 | nwo 84 | The-Cave 85 | megacorp 86 | fulcrumassets 87 | ecorp 88 | */ -------------------------------------------------------------------------------- /old/scan-dfs.script: -------------------------------------------------------------------------------- 1 | // scan-dfs.script [start]; 2 | // depth-first search, like scan-analyze 3 | 4 | toScan = [getHostname()]; 5 | depth = [1]; 6 | if (args.length > 0) { 7 | toScan = [args[0]]; 8 | } 9 | scanned = []; 10 | 11 | newFunc = ''.constructor.constructor; 12 | notIncludes = newFunc('x', 'return !this.includes(x)'); 13 | replace = newFunc('return this'); 14 | padding = '------------------------------------------------------------'; 15 | 16 | while (toScan.length > 0) { 17 | host = toScan.pop(); 18 | d = depth.pop(); 19 | scanned.push(host); 20 | tprint(padding.slice(-3*d+2)+'> '+host+' ('+getServerRequiredHackingLevel(host)+')'); 21 | results = scan(host).reverse(); 22 | newResults = results.filter(notIncludes.bind(scanned)); 23 | toScan = toScan.concat(newResults); 24 | depth = depth.concat(newResults.map(replace.bind(d+1))); 25 | } 26 | 27 | tprint("Discovered "+scanned.length+" servers: "+scanned); 28 | 29 | /* 30 | -> home 31 | ----> iron-gym 32 | -------> nectar-net 33 | ----------> phantasy 34 | -------------> netlink 35 | ----------------> catalyst 36 | -------------------> alpha-ent 37 | ----------------------> global-pharm 38 | -------------------------> unitalife 39 | ----------------------> aerocorp 40 | -------------------------> deltaone 41 | ----------------------------> zeus-med 42 | -------------------------------> taiyang-digital 43 | ----------------------------------> applied-energetics 44 | -------------------------------------> helios 45 | ----------------------------------------> kuai-gong 46 | ----------------------------------> microdyne 47 | -------------------------------------> vitalife 48 | ----------------------------------------> 4sigma 49 | -------------------------------------------> powerhouse-fitness 50 | -------------------------------------------> clarkeinc 51 | ----------------------------------------------> The-Cave 52 | ----------------------------------------> omnitek 53 | -------------------------------------------> blade 54 | ----------------------------------------------> megacorp 55 | -------------------------------------------> b-and-a 56 | ----------------------------> univ-energy 57 | -------------------------------> infocomm 58 | ----------------------------------> run4theh111z 59 | -------------------------------------> stormtech 60 | -------------------------------------> fulcrumtech 61 | ----------------------------------------> . 62 | -------------------------------------------> nwo 63 | ----------------------------------------------> fulcrumassets 64 | ----------------------------------------------> ecorp 65 | -------------------------> omnia 66 | ----------------------------> solaris 67 | -------------------------------> nova-med 68 | ----------------------------> icarus 69 | -------------------------------> zb-def 70 | ----------------------------------> titan-labs 71 | ----------------------------> defcomm 72 | ----------------------> galactic-cyber 73 | ----------------> zb-institute 74 | -------------------> lexo-corp 75 | ----------------------> snap-fitness 76 | -------------> the-hub 77 | ----> foodnstuff 78 | ----> sigma-cosmetics 79 | ----> joesguns 80 | -------> max-hardware 81 | ----------> omega-net 82 | -------> CSEC 83 | ----------> neo-net 84 | -------------> comptek 85 | ----------------> syscore 86 | -------------------> millenium-fitness 87 | -------------> johnson-ortho 88 | -------------> avmnite-02h 89 | ----------------> summit-uni 90 | ----------------> I.I.I.I 91 | ----> hong-fang-tea 92 | ----> harakiri-sushi 93 | -------> zer0 94 | ----------> silver-helix 95 | -------------> crush-fitness 96 | ----------------> rothman-uni 97 | -------------------> rho-construction 98 | -------------------> aevum-police 99 | ----> darkweb 100 | */ -------------------------------------------------------------------------------- /old/scan.script: -------------------------------------------------------------------------------- 1 | tprint(scan(args[0])); -------------------------------------------------------------------------------- /old/sell-bear.script: -------------------------------------------------------------------------------- 1 | symbols = ["ECP","MGCP","BLD","CLRK","OMTK","FSIG","KGI","FLCM","STM","DCOMM","HLS","VITA","ICRS","UNV","AERO","OMN","SLRS","GPH","NVMD","WDS","LXO","RHOC","APHE","SYSC","CTK","NTLK","OMGA","SGC","JGN","CTYS","MDYN","TITN","FNS"]; 2 | 3 | c = 'constructor' 4 | f = [c][c][c] 5 | makeObj = f('a', 'o = {}; for (var i = 0; i < a.length; i=i+2) {o[a[i]] = a[i+1]} return o;'); 6 | // setObj = f('o', 'a', 'for (var i = 0; i < a.length; i=i+2) {o[a[i]] = a[i+1]} return o;'); 7 | funcs = makeObj(["stock.buy", stock.buy, "stock.sell", stock.sell, "stock.short", stock.short, "stock.sellShort", stock.sellShort, "stock.placeOrder", stock.placeOrder, "stock.cancelOrder", stock.cancelOrder, "stock.getPosition", stock.getPosition, "stock.getPrice", stock.getPrice, "tprint", tprint]); 8 | 9 | sellAll = f('symbol', 'price=this.stock.getPrice(symbol); pos=this.stock.getPosition(symbol); avgPx=pos[1]; if (price < 0.955*avgPx){this.stock.sell(symbol, pos[0])}').bind(funcs); 10 | 11 | symbols.forEach(sellAll); -------------------------------------------------------------------------------- /old/sell.script: -------------------------------------------------------------------------------- 1 | symbols = ["ECP","MGCP","BLD","CLRK","OMTK","FSIG","KGI","FLCM","STM","DCOMM","HLS","VITA","ICRS","UNV","AERO","OMN","SLRS","GPH","NVMD","WDS","LXO","RHOC","APHE","SYSC","CTK","NTLK","OMGA","SGC","JGN","CTYS","MDYN","TITN","FNS"]; 2 | 3 | c = 'constructor' 4 | f = [c][c][c] 5 | makeObj = f('a', 'o = {}; for (var i = 0; i < a.length; i=i+2) {o[a[i]] = a[i+1]} return o;'); 6 | // setObj = f('o', 'a', 'for (var i = 0; i < a.length; i=i+2) {o[a[i]] = a[i+1]} return o;'); 7 | funcs = makeObj(["stock.buy", stock.buy, "stock.sell", stock.sell, "stock.short", stock.short, "stock.sellShort", stock.sellShort, "stock.placeOrder", stock.placeOrder, "stock.cancelOrder", stock.cancelOrder, "stock.getPosition", stock.getPosition]); 8 | 9 | sellAll = f('symbol', 'pos=this.stock.getPosition(symbol); this.stock.sell(symbol, pos[0])').bind(funcs); 10 | 11 | symbols.forEach(sellAll); -------------------------------------------------------------------------------- /old/singularity-progress.script: -------------------------------------------------------------------------------- 1 | // universityCourse("Rothman University", "Algorithms"); 2 | // sleep(5*60*1000); 3 | // universityCourse("Rothman University", "Leadership"); 4 | // sleep(5*60*1000); 5 | 6 | while(true){ 7 | (travelToCity)("Sector-12"); 8 | (universityCourse)("Rothman University", "Leadership"); 9 | sleep(2*60*1000); 10 | (gymWorkout)("Powerhouse Gym", "str"); 11 | sleep(2*60*1000); 12 | (gymWorkout)("Powerhouse Gym", "def"); 13 | sleep(2*60*1000); 14 | (gymWorkout)("Powerhouse Gym", "dex"); 15 | sleep(2*60*1000); 16 | (gymWorkout)("Powerhouse Gym", "agi"); 17 | sleep(2*60*1000); 18 | } 19 | 20 | repGoals = [ 21 | // ["CyberSec", 10000, "hacking"], 22 | ["Netburners", 12500, "hacking"], 23 | // ["Sector-12", 12500, "hacking"], 24 | ["Aevum", 7500, "hacking"], 25 | ["Slum Snakes", 22500, "security"], 26 | // ["NiteSec", 45000, "hacking"], 27 | // ["Tetrads", 62500, "security"], 28 | ["BitRunners", 250000, "hacking"], 29 | ["The Black Hand", 100000, "hacking"], 30 | ["Tian Di Hui", 7500, "hacking"], 31 | ["Bachman & Associates", 100000, "hacking"] 32 | ]; 33 | 34 | while (true) { 35 | for (i = 0; i < repGoals.length; i++) { 36 | goal = repGoals[i]; 37 | faction = goal[0]; 38 | rep = goal[1]; 39 | workType = goal[2] || "hacking"; 40 | //joinFaction(faction); 41 | if(getFactionRep(faction) < rep) { 42 | print("working for "+faction+" until "+rep+" rep"); 43 | if (workForFaction(faction, workType)) { 44 | sleep(5*60*1000); 45 | } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /old/smart-farm.script: -------------------------------------------------------------------------------- 1 | //startTime = Date.now(); 2 | f = ''.constructor.constructor; 3 | makeObj = f('a', 'o = {}; for (var i = 0; i < a.length; i=i+2) {o[a[i]] = a[i+1]} return o;'); 4 | setObj = f('o', 'a', 'for (var i = 0; i < a.length; i=i+2) {o[a[i]] = a[i+1]} return o;'); 5 | getters = makeObj(["serverExists", serverExists, "hasRootAccess", hasRootAccess, "getServerMoneyAvailable", getServerMoneyAvailable, "getServerMaxMoney", getServerMaxMoney, "getServerGrowth", getServerGrowth, "getServerSecurityLevel", getServerSecurityLevel, "getServerBaseSecurityLevel", getServerBaseSecurityLevel, "getServerMinSecurityLevel", getServerMinSecurityLevel, "getServerRequiredHackingLevel", getServerRequiredHackingLevel, "getServerNumPortsRequired", getServerNumPortsRequired, "getServerRam", getServerRam, "getHackTime", getHackTime, "getGrowTime", getGrowTime, "getWeakenTime", getWeakenTime, "getHackingLevel", getHackingLevel]); 6 | getInfo = f('host', 'return {name: host, maxMoney: this.getServerMaxMoney(host), growth: this.getServerGrowth(host), baseSecurityLevel: this.getServerBaseSecurityLevel(host), minSecurityLevel: this.getServerMinSecurityLevel(host), requiredHackingLevel: this.getServerRequiredHackingLevel(host), numPortsRequired: this.getServerNumPortsRequired(host), maxRam: this.getServerRam(host)[0], hackTime: this.getHackTime(host), growTime: this.getGrowTime(host), weakenTime: this.getWeakenTime(host)}').bind(getters); 7 | 8 | target = args[0]; 9 | server = getInfo(target); 10 | 11 | mults = (getHackingMultipliers)(); 12 | playerHackingMoneyMult = mults.money; 13 | playerHackingGrowMult = mults.growth; 14 | bitnodeGrowMult = 1.00; 15 | bitnodeWeakenMult = 1.00; 16 | ServerGrowthRate = 1; 17 | ServerWeakenRate = 1; 18 | ScriptHackMoney = 0.2; 19 | playerHackingMoneyMult *= mults.ScriptHackMoney; 20 | bitnodeGrowMult = mults.ServerGrowthRate; 21 | bitnodeWeakenMult = mults.ServerWeakenRate; 22 | 23 | percentageToSteal = 0.1; 24 | 25 | constantGrowthRate = server.growthRate; 26 | unadjustedGrowthRate = 1.03; 27 | maxGrowthRate = 1.0035; 28 | maxMoney = server.maxMoney; 29 | minSecurity = server.minSecurity; 30 | serverHackingLevel = server.requiredHackingLevel; 31 | 32 | 33 | threads=1; 34 | // run("weaken.script", threads, server.name); 35 | // run("hack.script", threads, server.name); 36 | // run("grow.script", threads, server.name, server.growTime);() -------------------------------------------------------------------------------- /old/soft-reset.ns: -------------------------------------------------------------------------------- 1 | export async function main(ns) { 2 | ns.softReset(); 3 | } -------------------------------------------------------------------------------- /old/spawn-farms.ns: -------------------------------------------------------------------------------- 1 | // run spawn-farms.ns host [target ...] 2 | 3 | import {spawnFarms, mostProfitableTargets, getAllHosts} from "lib.ns"; 4 | 5 | export async function main(ns) { 6 | let host = 'home'; 7 | if (ns.args.length > 0) { 8 | host = ns.args[0]; 9 | } 10 | const targets = ns.args.slice(1); 11 | spawnFarms(ns, host, targets); 12 | } -------------------------------------------------------------------------------- /old/spawn-farms.script: -------------------------------------------------------------------------------- 1 | f = ''.constructor.constructor; 2 | json = f('return JSON')(); 3 | makeObj = f('a', 'o = {}; for (var i = 0; i < a.length; i=i+2) {o[a[i]] = a[i+1]} return o;'); 4 | setObj = f('o', 'a', 'for (var i = 0; i < a.length; i=i+2) {o[a[i]] = a[i+1]} return o;'); 5 | 6 | allHosts = ["iron-gym","foodnstuff","sigma-cosmetics","joesguns","hong-fang-tea","harakiri-sushi","nectar-net","max-hardware","CSEC","zer0","phantasy","omega-net","neo-net","silver-helix","netlink","the-hub","comptek","johnson-ortho","avmnite-02h","crush-fitness","catalyst","zb-institute","syscore","summit-uni","I.I.I.I","rothman-uni","alpha-ent","lexo-corp","millenium-fitness","rho-construction","aevum-police","global-pharm","aerocorp","galactic-cyber","snap-fitness","unitalife","deltaone","omnia","zeus-med","univ-energy","solaris","icarus","defcomm","taiyang-digital","infocomm","nova-med","zb-def","applied-energetics","microdyne","run4theh111z","titan-labs","helios","vitalife","stormtech","fulcrumtech","kuai-gong","4sigma","omnitek",".","powerhouse-fitness","clarkeinc","blade","b-and-a","nwo","The-Cave","megacorp","fulcrumassets","ecorp"]; 7 | 8 | getters = makeObj(["serverExists", serverExists, "hasRootAccess", hasRootAccess, "getServerMoneyAvailable", getServerMoneyAvailable, "getServerMaxMoney", getServerMaxMoney, "getServerGrowth", getServerGrowth, "getServerSecurityLevel", getServerSecurityLevel, "getServerBaseSecurityLevel", getServerBaseSecurityLevel, "getServerMinSecurityLevel", getServerMinSecurityLevel, "getServerRequiredHackingLevel", getServerRequiredHackingLevel, "getServerNumPortsRequired", getServerNumPortsRequired, "getServerRam", getServerRam, "getHackTime", getHackTime, "getGrowTime", getGrowTime, "getWeakenTime", getWeakenTime, "getHackingLevel", getHackingLevel]); 9 | getInfo = f('host', 'return {name: host, maxMoney: this.getServerMaxMoney(host), growth: this.getServerGrowth(host), baseSecurityLevel: this.getServerBaseSecurityLevel(host), minSecurityLevel: this.getServerMinSecurityLevel(host), requiredHackingLevel: this.getServerRequiredHackingLevel(host), numPortsRequired: this.getServerNumPortsRequired(host), maxRam: this.getServerRam(host)[0], hackTime: this.getHackTime(host), growTime: this.getGrowTime(host), weakenTime: this.getWeakenTime(host)}').bind(getters); 10 | allServers = allHosts.map(getInfo); 11 | 12 | hasMoney = f('server', 'return server.maxMoney > 0'); 13 | serversWithMoney = allServers.filter(hasMoney); 14 | 15 | canHack = f('server', 'return (this.hasRootAccess(server.name) && server.requiredHackingLevel < this.getHackingLevel())').bind(getters); 16 | 17 | targets = []; 18 | while (true) { 19 | newTargets = serversWithMoney.filter(canHack); 20 | while (newTargets.length <= targets.length) { 21 | sleep(60*1000); 22 | newTargets = serversWithMoney.filter(canHack); 23 | } 24 | targets = newTargets; 25 | 26 | run("cloud-spawn.script", 1, targets, ["farm.script"]); 27 | } 28 | 29 | // byHackReq = f('a', 'b', 'return a.requiredHackingLevel - b.requiredHackingLevel'); 30 | // serversByHackReq = serversWithMoney.sort(byHackReq); 31 | // getName = f('server', 'return server.name'); 32 | // hostsByHackReq = serversByHackReq.map(getName); 33 | // tprint(json.stringify(hostsByHackReq)); 34 | 35 | // hostsByHackReq = ["foodnstuff","sigma-cosmetics","joesguns","nectar-net","hong-fang-tea","harakiri-sushi","neo-net","zer0","max-hardware","iron-gym","phantasy","silver-helix","omega-net","crush-fitness","johnson-ortho","the-hub","comptek","rothman-uni","netlink","aevum-police","catalyst","summit-uni","rho-construction","millenium-fitness","alpha-ent","syscore","zb-institute","lexo-corp","snap-fitness","global-pharm","zb-def","nova-med","microdyne","titan-labs","unitalife","solaris","univ-energy","helios","applied-energetics","zeus-med","galactic-cyber","aerocorp","deltaone","icarus","vitalife","defcomm","omnia","taiyang-digital","infocomm","stormtech","kuai-gong","fulcrumtech","omnitek","powerhouse-fitness","b-and-a","blade","nwo","4sigma","clarkeinc","ecorp","megacorp","fulcrumassets"]; 36 | 37 | // for (i = 0; i < hostsByHackReq.length; i++) { 38 | // host = hostsByHackReq[i]; 39 | // while (getHackingLevel() < getServerRequiredHackingLevel(host)) { 40 | // sleep(60*1000); 41 | // } 42 | // tprint("starting farm for "+host); 43 | // run("farm-init.script", 1, host, getServerMaxMoney(host), getServerMinSecurityLevel(host)); 44 | // sleep(1000); 45 | // } -------------------------------------------------------------------------------- /old/traceroute.script: -------------------------------------------------------------------------------- 1 | // scan-dfs.script [target]; 2 | // depth-first search, like scan-analyze 3 | 4 | target = args[0]; 5 | toScan = [[getHostname()]]; 6 | scanned = []; 7 | 8 | c = 'constructor'; 9 | f = [c][c][c]; 10 | notIncludes = f('x', 'return !this.includes(x)'); 11 | padding = '------------------------------------------------------------'; 12 | 13 | makeObj = f('a', 'o = {}; for (var i = 0; i < a.length; i=i+2) {o[a[i]] = a[i+1]} return o;'); 14 | scope = makeObj(["scan", scan, "scanned", scanned, "notIncludes", notIncludes.bind(scanned), "toScan", toScan]); 15 | // iterate = f('route', 'var d=route.length, host=route[d-1]; this.scanned.push(host); var results=this.scan(host).reverse().filter(this.notIncludes).map(function(h){return route.concat(h)}); return results;').bind(scope); 16 | 17 | traceroute = f('target', 'while(this.toScan.length > 0){var route=this.toScan.pop(), d=route.length, host=route[d-1]; if (host==target){return route} this.scanned.push(host); var results=this.scan(host).reverse().filter(this.notIncludes).map(function(h){return route.concat(h)}); this.toScan = this.toScan.concat(results);}').bind(scope); 18 | tprint(traceroute(target)); 19 | 20 | // while (toScan.length > 0) { 21 | // route = toScan.pop(); 22 | // (route[route.length-1] == target) && tprint(route); 23 | // // tprint(padding.slice(-3*route.length+2)+'> '+route[route.length-1]); 24 | // toScan = toScan.concat(iterate(route)); 25 | // } 26 | 27 | // //tprint("Discovered "+scanned.length+" servers: "+scanned); -------------------------------------------------------------------------------- /old/v1_DETECTED_CHANGES.txt: -------------------------------------------------------------------------------- 1 | // Detected change getHackTime, reason: returns milliseconds 2 | /old/get-info.script:23 3 | /old/cloud-manage.script:34 4 | /old/attack-optimal-targets.script:36 5 | /old/attack-optimal-targets.script:65 6 | /old/find-targets.script:36 7 | /old/find-targets.script:62 8 | /old/find-farms.script:11 9 | /old/find-farms.script:12 10 | /old/spawn-farms.script:8 11 | /old/spawn-farms.script:9 12 | /old/init-aug.script:10 13 | /old/init-aug.script:11 14 | /old/smart-farm.script:5 15 | /old/smart-farm.script:6 16 | lib.ns:64 17 | lib.ns:82 18 | // Detected change getGrowTime, reason: returns milliseconds 19 | /old/get-info.script:24 20 | /old/cloud-manage.script:31 21 | /old/attack-optimal-targets.script:36 22 | /old/attack-optimal-targets.script:65 23 | /old/find-targets.script:36 24 | /old/find-targets.script:62 25 | /old/find-farms.script:11 26 | /old/find-farms.script:12 27 | /old/spawn-farms.script:8 28 | /old/spawn-farms.script:9 29 | /old/init-aug.script:10 30 | /old/init-aug.script:11 31 | /old/smart-farm.script:5 32 | /old/smart-farm.script:6 33 | lib.ns:64 34 | lib.ns:83 35 | // Detected change getWeakenTime, reason: returns milliseconds 36 | /old/get-info.script:25 37 | /old/cloud-manage.script:28 38 | /old/attack-optimal-targets.script:36 39 | /old/attack-optimal-targets.script:65 40 | /old/find-targets.script:36 41 | /old/find-targets.script:62 42 | /old/find-farms.script:11 43 | /old/find-farms.script:12 44 | /old/spawn-farms.script:8 45 | /old/spawn-farms.script:9 46 | /old/init-aug.script:10 47 | /old/init-aug.script:11 48 | /old/smart-farm.script:5 49 | /old/smart-farm.script:6 50 | lib.ns:64 51 | lib.ns:84 52 | // Detected change write, reason: needs to be awaited 53 | /old/enqueue-servers.script:27 54 | // Detected change scp, reason: needs to be awaited 55 | /old/purchase-server-4gb.script:5 56 | /old/iterate-servers.script:64 57 | /old/remote-setup.script:35 58 | /old/cloud-setup.script:9 59 | /old/dist-0port.script:11 60 | /old/dist-0port.script:12 61 | /old/remote-run.script:8 62 | /old/cloud-purchase.script:25 63 | /old/cloud-spawn.script:26 64 | /old/remote-run-one.script:8 65 | /old/init-aug.script:76 66 | lib.ns:125 67 | // Detected change sleep, reason: Can no longer be called simultenaously. 68 | /old/grow.script:8 69 | /old/iterate-servers.script:54 70 | /old/iterate-servers.script:75 71 | /old/iterate-servers.script:79 72 | /old/cloud-manage.script:43 73 | /old/dist-0port.script:7 74 | /old/farm-init.script:8 75 | /old/spawn-farms.script:21 76 | /old/spawn-farms.script:40 77 | /old/spawn-farms.script:44 78 | /old/init-aug.script:62 79 | /old/init.script:8 80 | /old/init.script:38 81 | /old/init-farms.script:3 82 | /old/singularity-progress.script:2 83 | /old/singularity-progress.script:4 84 | /old/singularity-progress.script:9 85 | /old/singularity-progress.script:11 86 | /old/singularity-progress.script:13 87 | /old/singularity-progress.script:15 88 | /old/singularity-progress.script:17 89 | /old/singularity-progress.script:44 90 | /old/init-bitnode.script:9 91 | /old/init-bitnode.script:10 92 | /old/init-bitnode.script:51 93 | /old/crime.script:8 94 | /old/crime.script:18 95 | /old/crime.script:20 96 | /old/create-programs.script:25 97 | /old/workout.script:7 98 | /old/manage-stocks.script:4 99 | /old/manage-stocks.script:8 100 | /old/manage-stocks.script:12 101 | /old/manage-stocks.script:16 102 | lib.ns:203 103 | /net/crack-servers.ns:6 104 | /net/crack-servers.ns:42 105 | /net/crack-servers.ns:46 106 | test.ns:4 107 | test.ns:9 108 | test.ns:15 109 | test.ns:26 110 | test.ns:28 111 | /hacknet/nodes.ns:37 112 | /hacknet/nodes.ns:134 113 | /hacknet/nodes.ns:137 114 | /progress/programs.ns:17 115 | /progress/crime.ns:30 116 | /progress/crime.ns:35 117 | /stocks/trader.ns:120 118 | /stocks/trader.ns:125 119 | /progress/contracts.ns:6 120 | /progress/all.ns:4 121 | /progress/all.ns:5 122 | /progress/all.ns:6 123 | /progress/all.ns:10 124 | /progress/all.ns:17 125 | /progress/all.ns:18 126 | /progress/all.ns:19 127 | /progress/all.ns:20 128 | /progress/all.ns:21 129 | /progress/all.ns:22 130 | /progress/all.ns:23 131 | /progress/factions.ns:27 132 | /stocks/naive-trader.ns:173 133 | /stocks/naive-trader.ns:178 134 | /stocks/naive-trader.ns:181 135 | /hacknet/servers.ns:5 136 | /hacknet/servers.ns:18 137 | /hacknet/servers.ns:36 138 | /hacknet/servers.ns:49 139 | /hacknet/servers.ns:75 140 | /hacknet/spend-hashes.ns:6 141 | /bladeburner/actions.ns:2 142 | /bladeburner/actions.ns:5 143 | /net/backdoor-servers.ns:7 144 | /net/backdoor-servers.ns:18 145 | /net/backdoor-servers.ns:23 146 | /bladeburner/skills.ns:2 147 | /bladeburner/skills.ns:5 148 | /bladeburner/skills.ns:11 149 | /bladeburner/progress.ns:6 150 | /bladeburner/progress.ns:10 151 | /net/init.ns:6 152 | /net/init.ns:10 153 | /net/init.ns:12 154 | // Detected change hacking_skill, reason: renamed 'hacking' 155 | lib.ns:193 156 | /progress/all.ns:8 157 | /net/backdoor-servers.ns:22 158 | -------------------------------------------------------------------------------- /old/value-stocks.script: -------------------------------------------------------------------------------- 1 | symbols = ["ECP","MGCP","BLD","CLRK","OMTK","FSIG","KGI","FLCM","STM","DCOMM","HLS","VITA","ICRS","UNV","AERO","OMN","SLRS","GPH","NVMD","WDS","LXO","RHOC","APHE","SYSC","CTK","NTLK","OMGA","SGC","JGN","CTYS","MDYN","TITN"]; 2 | 3 | c = 'constructor' 4 | f = [c][c][c]; 5 | makeObj = f('a', 'o = {}; for (var i = 0; i < a.length; i=i+2) {o[a[i]] = a[i+1]} return o;'); 6 | // setObj = f('o', 'a', 'for (var i = 0; i < a.length; i=i+2) {o[a[i]] = a[i+1]} return o;'); 7 | funcs = makeObj(["stock.getPrice", stock.getPrice, "stock.buy", stock.buy, "stock.sell", stock.sell, "stock.short", stock.short, "stock.sellShort", stock.sellShort, "stock.placeOrder", stock.placeOrder, "stock.cancelOrder", stock.cancelOrder, "stock.getPosition", stock.getPosition]); 8 | 9 | // sellAll = f('symbol', 'pos=this.stock.getPosition(symbol); this.stock.sell(symbol, pos[0])').bind(funcs); 10 | 11 | 12 | // moneyToSpend = getServerMoneyAvailable('home') - (args.length > 0 && args[0] || 1000000); 13 | // moneyPerStock = moneyToSpend / symbols.length; 14 | // if (moneyPerStock < 200000) { 15 | // exit(); 16 | // } 17 | 18 | 19 | // buyFixedValue = f('moneyPerStock', 'symbol', 'price=this.stock.getPrice(symbol); shares=(moneyPerStock-100000)/price; this.stock.buy(symbol, shares);').bind(funcs, moneyPerStock); 20 | getValue = f('symbol', 'pos=this.stock.getPosition(symbol); price=this.stock.getPrice(symbol); return pos[0]*price;').bind(funcs); 21 | sum = f('acc', 'value', 'return acc+value'); 22 | 23 | values = symbols.map(getValue); 24 | total = values.reduce(sum); 25 | 26 | tprint(total) -------------------------------------------------------------------------------- /old/weaken.script: -------------------------------------------------------------------------------- 1 | // weaken.script [target] 2 | 3 | while(true) { 4 | weaken(args[0]); 5 | } -------------------------------------------------------------------------------- /old/work.script: -------------------------------------------------------------------------------- 1 | workForCompany(); -------------------------------------------------------------------------------- /old/workout.script: -------------------------------------------------------------------------------- 1 | statNames = ["str", "def", "dex", "agi"]; 2 | 3 | // travelToCity("Sector-12"); 4 | while(true) { 5 | for (i = 0; i < statNames.length; i++) { 6 | (gymWorkout)("Powerhouse Gym", statNames[i]); 7 | sleep(1*60*1000); 8 | } 9 | } -------------------------------------------------------------------------------- /player/backdoor-servers.js: -------------------------------------------------------------------------------- 1 | import { connectToHost } from "/player/tunnel.js"; 2 | 3 | export async function main(ns) { 4 | await installBackdoors(ns); 5 | } 6 | 7 | const factionHosts = ['CSEC', 'avmnite-02h', 'I.I.I.I', 'run4theh111z', 'powerhouse-fitness', 'fulcrumassets']; 8 | 9 | function getServersToBackdoor(ns) { 10 | return factionHosts.map(ns.getServer).filter((server)=>!server.backdoorInstalled); 11 | } 12 | 13 | export async function installBackdoors(ns) { 14 | ns.disableLog("sleep"); 15 | let toBackdoor = getServersToBackdoor(ns); 16 | while (toBackdoor.length > 0) { 17 | const skipped = []; 18 | for (const server of toBackdoor) { 19 | await installBackdoorOnServer(ns, server); 20 | } 21 | toBackdoor = getServersToBackdoor(ns); 22 | if (toBackdoor.length > 0) { 23 | await ns.sleep(60*1000); 24 | } 25 | } 26 | ns.tprint("INFO: Installed backdoors on all faction servers."); 27 | } 28 | 29 | export async function installBackdoorOnServer(ns, server) { 30 | ns.print(`Checking ${server.hostname}...`); 31 | if (server.backdoorInstalled) { 32 | ns.print(`${server.hostname} already has backdoor installed`); 33 | return true; 34 | } 35 | if (!server.hasAdminRights) { 36 | ns.print(`Need admin rights for ${server.hostname}`); 37 | return false; 38 | } 39 | if (server.requiredHackingSkill > ns.getPlayer().hacking) { 40 | ns.print(`Need ${server.requiredHackingSkill} hacking skill for ${server.hostname}`); 41 | return false; 42 | } 43 | const prevHost = ns.getHostname(); 44 | connectToHost(ns, server.hostname); 45 | await ns.installBackdoor(); 46 | ns.tprint(`Installed backdoor on ${server.hostname}.`); 47 | connectToHost(ns, prevHost); 48 | return true; 49 | } 50 | -------------------------------------------------------------------------------- /player/create-programs.js: -------------------------------------------------------------------------------- 1 | export const programs = [ 2 | ["BruteSSH.exe", 50, 500000], 3 | ["FTPCrack.exe", 100, 1500000], 4 | ["relaySMTP.exe", 250, 5000000], 5 | ["HTTPWorm.exe", 500, 30000000], 6 | ["SQLInject.exe", 750, 250000000], 7 | ["AutoLink.exe", 200, 1000000], 8 | ["ServerProfiler.exe", 200, 1000000], 9 | ["DeepscanV1.exe", 250, 500000], 10 | ["DeepscanV2.exe", 500, 25000000] 11 | ]; 12 | 13 | export async function waitForMoney(ns, amount) { 14 | if (ns.getServerMoneyAvailable('home') < amount) { 15 | ns.print(`Waiting for ${ns.nFormat(amount, "$0.0a")}`); 16 | while (ns.getServerMoneyAvailable('home') < amount) { 17 | await ns.sleep(10*1000); 18 | } 19 | } 20 | } 21 | 22 | export async function main(ns) { 23 | await waitForMoney(ns, 200000); 24 | ns.purchaseTor(); 25 | 26 | for (const program of programs) { 27 | if (!ns.fileExists(program[0])) { 28 | ns.print(`Next program: ${program[0]}`); 29 | await waitForMoney(ns, program[2]); 30 | ns.purchaseProgram(program[0]); 31 | } 32 | //if (!ns.isBusy()) { 33 | // if (ns.getHackingLevel() < program[1]) { 34 | // ns.universityCourse("Rothman University", "Algorithms"); 35 | // } 36 | // else { 37 | // ns.createProgram(program[0]); 38 | // } 39 | //} 40 | } 41 | ns.tprint("INFO: Installed all programs."); 42 | } 43 | -------------------------------------------------------------------------------- /player/crime.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Usage: 4 | /player/crime.js "deal drugs" 5 | 6 | */ 7 | 8 | import { prepareStats } from "player/train.js"; 9 | 10 | const CRIME_NAMES = ["shoplift", "rob store", "mug", "larceny", "deal drugs", "bond forgery", "traffick arms", "homicide", "grand theft auto", "kidnap", "assassinate", "heist"]; 11 | 12 | export function autocomplete(data, args) { 13 | return CRIME_NAMES; 14 | } 15 | 16 | export async function doCrimes(ns, forcedSelection=null) { 17 | while (true) { 18 | let crimes = {}; 19 | for (const crimeName of CRIME_NAMES) { 20 | crimes[crimeName] = { 21 | name: crimeName, 22 | chance: ns.getCrimeChance(crimeName) 23 | }; 24 | } 25 | //crimes = crimes.sort(function(a, b){ 26 | // return a.chance - b.chance; // ascending 27 | //}); 28 | 29 | let selectedCrime = crimes[0]; 30 | for (const crime of Object.values(crimes).reverse()) { 31 | if (crime.chance > 0.75) { 32 | selectedCrime = crime; 33 | break; 34 | } 35 | } 36 | const player = ns.getPlayer(); 37 | const karma = ns.heart.break(); 38 | if (player.numPeopleKilled < 30 && crimes.homicide.chance > 0.9) { 39 | selectedCrime = crimes.homicide; 40 | } 41 | if (selectedCrime == crimes.homicide && player.numPeopleKilled > 100 && karma < -1e6) { 42 | return; 43 | } 44 | 45 | //ns.tprint(crimes); 46 | //ns.tprint(`Selected ${selectedCrime.name}: chance=${selectedCrime.chance}`); 47 | //return; 48 | 49 | let delay = ns.commitCrime(forcedSelection || selectedCrime.name); 50 | await ns.sleep(0.6*delay); 51 | if (!ns.isBusy()) { 52 | return; 53 | } 54 | while(ns.isBusy()){ 55 | await ns.sleep(0.1*delay); 56 | } 57 | } 58 | } 59 | 60 | export async function main(ns) { 61 | const targetStats = { 62 | "strength": 5, 63 | "defense": 5, 64 | "dexterity": 10, 65 | "agility": 10 66 | }; 67 | await prepareStats(ns, targetStats); 68 | ns.stopAction(); 69 | await doCrimes(ns, ns.args[0]); 70 | } 71 | 72 | -------------------------------------------------------------------------------- /player/info.js: -------------------------------------------------------------------------------- 1 | import { getService } from "/lib/port-service"; 2 | 3 | /** @param {NS} ns **/ 4 | export async function main(ns) { 5 | let player = ns.getPlayer(); 6 | player.karma = ns.heart.break(); 7 | 8 | player.stocksValue = getService(ns, 5)?.getPortfolioValue() || 0; 9 | 10 | const factions = player.factions; 11 | player.factions = {}; 12 | for (const f of factions) { 13 | player.factions[f] = `${ns.getFactionFavor(f)} favor, ${parseInt(ns.getFactionRep(f))} rep`; 14 | } 15 | 16 | ns.clearLog(); 17 | ns.tail(); 18 | ns.print("player = ", JSON.stringify(player, null, 2), "\n\n\n\n\n"); 19 | 20 | const dashboard = [ 21 | `Player`, 22 | `------`, 23 | // ` HP: ${player.hp} / ${player.max_hp}`, 24 | ]; 25 | if (player.stocksValue) { 26 | dashboard.push( 27 | ` Net Worth: ${ns.nFormat(player.money + player.stocksValue, '$0.0a')}`, 28 | ` Stocks: ${ns.nFormat(player.stocksValue, '$0.0a')}`, 29 | ); 30 | } 31 | dashboard.push( 32 | ` Cash: ${ns.nFormat(player.money, '$0.0a')}`, 33 | // ` Hacking Skill: ${player.hacking}`, 34 | // ` Intelligence: ${player.intelligence}`, 35 | // ` Strength: ${player.strength}`, 36 | ` City: ${player.city}`, 37 | ` Kills: ${player.numPeopleKilled}`, 38 | ` Karma: ${player.karma}`, 39 | ` Jobs: ${Object.keys(player.jobs).length}`, 40 | ` Factions: ${Object.keys(player.factions).length}`, 41 | ` In Bladeburner: ${player.inBladeburner}`, 42 | ` Has Corporation: ${player.hasCorporation}`, 43 | ` In Gang: ${ns.gang.inGang()}`, 44 | ` Time Since Aug: ${ns.tFormat(player.playtimeSinceLastAug)}`, 45 | `` 46 | ); 47 | ns.print(dashboard.join("\n")); 48 | } 49 | -------------------------------------------------------------------------------- /player/join-factions.js: -------------------------------------------------------------------------------- 1 | export function acceptInvites(ns) { 2 | for (const faction of ns.checkFactionInvitations()) { 3 | if (!(exclusiveFactions[faction])) { 4 | ns.joinFaction(faction); 5 | ns.tprint(`Joined faction ${faction}.`); 6 | } 7 | } 8 | } 9 | 10 | export const exclusiveFactions = { 11 | "Aevum": true, 12 | "Sector-12": true, 13 | "Volhaven": true, 14 | "Chongqing": true, 15 | "New Tokyo": true, 16 | "Ishima": true 17 | }; 18 | 19 | export async function main(ns) { 20 | //if (!ns.getOwnedAugmentations().includes("CashRoot Starter Kit")) { 21 | // exclusiveFactions["Sector-12"] = false; 22 | // exclusiveFactions.Aevum = false; 23 | //} 24 | 25 | while (true) { 26 | acceptInvites(ns); 27 | await ns.sleep(60*1000); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /player/prestige.js: -------------------------------------------------------------------------------- 1 | /* 2 | Finished buying augmentations. Don't forget: 3 | - Buy augmentations for sleeves 4 | - Buy equipment for gang members 5 | - Upgrade home server 6 | - Spend hacknet hashes on Bladeburner rank and SP 7 | - Spend hacknet hashes on corporation research and funds 8 | - TODO: create a gang if possible 9 | - TODO: create a corp if possible 10 | - Buyback corporation shares 11 | */ 12 | 13 | /** @param {NS} ns **/ 14 | export async function main(ns) { 15 | ns.disableLog('sleep'); 16 | ns.clearLog(); 17 | ns.tail(); 18 | await ns.sleep( 0*1000); ns.run("/botnet/stop.js", 1, "--force"); 19 | await ns.sleep( 0*1000); ns.run("/hacknet/spend-hashes.js", 1, "Bladeburner", "Exchange for Corporation Research", "Sell for Corporation Funds", "Sell for Money"); 20 | await ns.sleep( 1*1000); ns.run("/sleeves/buy-augs.js"); 21 | await ns.sleep( 1*1000); ns.run("/sleeves/train.js"); 22 | await ns.sleep( 1*1000); ns.run("/gang/buy-augs.js"); 23 | await ns.sleep( 1*1000); ns.run("/net/upgrade-home-server.js"); 24 | await ns.sleep( 3*1000); ns.run("/corporation/buyback-shares.js"); 25 | for (let i = 3; i >= 0; i--) { 26 | ns.print(`Installing augmentations in ${i}...`); 27 | await ns.sleep(1000); 28 | } 29 | ns.installAugmentations(ns.args[0] || "init.js"); 30 | } 31 | -------------------------------------------------------------------------------- /player/train.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | run player/train.js --strength 100 --defense 100 --dexterity 100 --agility 100 --focus 4 | 5 | */ 6 | 7 | const FLAGS = [ 8 | ['hacking', 0], 9 | ['charisma', 0], 10 | ['strength', 0], 11 | ['defense', 0], 12 | ['dexterity', 0], 13 | ['agility', 0], 14 | ['focus', false] 15 | ]; 16 | 17 | export function autocomplete(data, args) { 18 | data.flags(FLAGS); 19 | return []; 20 | } 21 | 22 | /** @param {NS} ns **/ 23 | export async function main(ns) { 24 | ns.disableLog("sleep"); 25 | const flags = ns.flags(FLAGS); 26 | const focus = flags.focus; 27 | delete flags.focus; 28 | delete flags._; 29 | await prepareStats(ns, flags, focus); 30 | } 31 | 32 | export async function prepareStats(ns, targetStats, focus=false) { 33 | for (const [stat, statTarget] of Object.entries(targetStats)) { 34 | while (ns.getPlayer()[stat] < statTarget) { 35 | if (!ns.isBusy()) { 36 | trainStat(ns, stat, focus); 37 | } 38 | await ns.sleep(1*1000); 39 | } 40 | ns.stopAction(); 41 | } 42 | } 43 | 44 | export function trainStat(ns, stat, focus=false) { 45 | if (stat == 'hacking') { 46 | ns.universityCourse("Rothman University", "Algorithms", focus); 47 | } 48 | else if (stat == 'charisma') { 49 | ns.universityCourse("Rothman University", "Leadership", focus); 50 | } 51 | else { 52 | ns.gymWorkout("Powerhouse Gym", stat, focus); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /player/tunnel.js: -------------------------------------------------------------------------------- 1 | const FLAGS = [ 2 | ["help", false], 3 | ["verbose", true], 4 | ["silent", false] 5 | ]; 6 | 7 | export function autocomplete(data, args) { 8 | data.flags(FLAGS); 9 | return [...data.servers]; 10 | } 11 | 12 | export async function main(ns) { 13 | const flags = ns.flags(FLAGS); 14 | const verbose = flags.verbose && !flags.silent; 15 | const target = flags._[0]; 16 | 17 | if (flags.help) { 18 | ns.tprint([ 19 | "Connect to any server.", 20 | "", 21 | "Usage:", 22 | `alias tunnel="run ${ns.getScriptName()}"`, 23 | "tunnel [host]", 24 | " " 25 | ].join("\n")); 26 | return; 27 | } 28 | 29 | connectToHost(ns, target, verbose); 30 | } 31 | 32 | export function connectToHost(ns, target, verbose=false) { 33 | const entry = ns.getCurrentServer(); 34 | const path = pathToTarget(ns, entry, target); 35 | for (const host of path.slice(1)) { 36 | if (ns.connect(host) && verbose) { 37 | ns.tprint(`Connected to ${host}`); 38 | } 39 | } 40 | } 41 | 42 | export function pathToTarget(ns, entry, target) { 43 | let scanned = {}; 44 | 45 | function findTargetFrom(host) { 46 | if (host in scanned) { 47 | return null; 48 | } 49 | scanned[host] = true; 50 | if (host.toLowerCase() == target.toLowerCase()) { 51 | return [host]; 52 | } 53 | for (const neighbor of ns.scan(host).reverse()) { 54 | const path = findTargetFrom(neighbor); 55 | if (path != null) { 56 | return [host].concat(path); 57 | } 58 | } 59 | return null; 60 | } 61 | 62 | return findTargetFrom(entry) || []; 63 | } 64 | -------------------------------------------------------------------------------- /service/README.md: -------------------------------------------------------------------------------- 1 | ## Netscript Port Services 2 | 3 | Netscript port numbers used in this repository: 4 | 5 | - Port 1: [ServerList](#ServerList_Service) - Information about servers 6 | - Port 2: [ServerPool](#ServerPool_Service) - Run scripts on any server 7 | - Port 3: [ThreadPool](../botnet/) - Run netscript functions on a grid computing system 8 | - Port 4: [HackPlanner](#Hack_Planning_Service) - Plan hack/grow/weaken operations 9 | - Port 5: [StockTrader](../stocks/trader.js) - Information about stocks 10 | 11 | --- 12 | 13 | ### ServerList Service 14 | 15 | [server-list.js](../net/server-list.js) defines these data structures: 16 | 17 | ServerList 18 | - loadServer(hostname) -> Server 19 | - getAllServers() -> Map[hostname: Server] 20 | - getScriptableServers() -> Array[Server] 21 | - getHackableServers(player) -> Array[Server] 22 | 23 | Server 24 | - canRunScripts() 25 | - canBeHacked(player) 26 | - availableThreads(scriptRam) 27 | - getStockInfo() 28 | 29 | **Usage:** Run the service (3.8 GB daemon): 30 | 31 | ```bash 32 | > run /service/server-info.js 33 | ``` 34 | 35 | Then you can read server info with no RAM cost for the client: 36 | 37 | ```javascript 38 | import { getService } from "/lib/port-service"; 39 | const serverList = getService(ns, 1); 40 | const server = serverList.loadServer("foodnstuff"); 41 | server.hackDifficulty; // 10 42 | await ns.hack(server.hostname); 43 | server.reload(); 44 | server.hackDifficulty; // 12 45 | ``` 46 | 47 | The service is also available in the browser console: 48 | ```javascript 49 | > serverList.getAllHosts().size 50 | 72 51 | > serverList.getScriptableServers().length 52 | 46 53 | > serverList.getHackableServers({hacking:166}).length 54 | 13 55 | ``` 56 | 57 | --- 58 | 59 | ### ServerPool Service 60 | 61 | ServerPool is a subclass of ServerList, extended with script execution methods. 62 | 63 | ServerPool 64 | - deploy({script, threads, args, [dependencies]}) 65 | - deployLater({script, threads, args, [dependencies], [startTime]}) 66 | - deployBatch([jobs]) - will run all jobs or none of them 67 | 68 | **Usage:** Run the service (5.8 GB daemon): 69 | 70 | ```bash 71 | > run /service/compute.js 72 | ``` 73 | 74 | Then you can deploy scripts to any available server, with no RAM cost for the client: 75 | 76 | ```javascript 77 | import { getService } from "/lib/port-service"; 78 | const serverPool = getService(ns, 2); 79 | const job = {script: "/batch/weaken.js", args: ["foodnstuff"], threads: 100}) 80 | serverPool.deploy(job); 81 | ``` 82 | 83 | --- 84 | 85 | ### Hack Planning Service 86 | 87 | Service for [HackPlanner](../hacking/) 88 | 89 | **Usage:** Run the service (7.3 GB daemon): 90 | 91 | ```bash 92 | > run /service/hack-planning.js 93 | ``` 94 | 95 | Then you can plan hacking jobs based on various parameters. 96 | 97 | ```javascript 98 | import { getService } from "/lib/port-service"; 99 | const hackPlanner = getService(ns, 4); 100 | server = hackPlanner.loadServer("phantasy"); 101 | server.planBatchCycle(server.mostProfitableParamsSync()); // " 7.6% HWGW" 102 | ``` 103 | -------------------------------------------------------------------------------- /service/compute.js: -------------------------------------------------------------------------------- 1 | import { PortService } from "/lib/port-service"; 2 | import { ServerPool } from "/net/deploy-script"; 3 | 4 | const FLAGS = [ 5 | ["help", false], 6 | ["port", 2] 7 | ] 8 | 9 | /** @param {NS} ns **/ 10 | export async function main(ns) { 11 | ns.clearLog(); 12 | 13 | const flags = ns.flags(FLAGS); 14 | if (flags.help) { 15 | ns.tprint("Provide script deployment services on a netscript port"); 16 | return; 17 | } 18 | 19 | const serverPool = new ServerPool(ns); 20 | const service = new PortService(ns, flags.port, serverPool); 21 | await service.serve(); 22 | } 23 | -------------------------------------------------------------------------------- /service/hack-planning.js: -------------------------------------------------------------------------------- 1 | import { PortService } from "/lib/port-service"; 2 | import { HackPlanner } from "/hacking/planner"; 3 | 4 | const FLAGS = [ 5 | ["help", false], 6 | ["port", 4] 7 | ] 8 | 9 | /** @param {NS} ns **/ 10 | export async function main(ns) { 11 | ns.clearLog(); 12 | 13 | const flags = ns.flags(FLAGS); 14 | if (flags.help) { 15 | ns.tprint("Provide hack/grow/weaken planning services on a netscript port"); 16 | return; 17 | } 18 | 19 | const hackPlanner = new HackPlanner(ns); 20 | const service = new PortService(ns, flags.port, hackPlanner); 21 | await service.serve(); 22 | } 23 | -------------------------------------------------------------------------------- /service/server-info.js: -------------------------------------------------------------------------------- 1 | import { PortService } from "/lib/port-service"; 2 | import { ServerList } from "/net/server-list"; 3 | 4 | const FLAGS = [ 5 | ["help", false], 6 | ["port", 1] 7 | ] 8 | 9 | /** @param {NS} ns **/ 10 | export async function main(ns) { 11 | ns.clearLog(); 12 | 13 | const flags = ns.flags(FLAGS); 14 | if (flags.help) { 15 | ns.tprint("Provide server information on a netscript port"); 16 | return; 17 | } 18 | 19 | const serverList = new ServerList(ns); 20 | const service = new PortService(ns, flags.port, serverList); 21 | await service.serve(); 22 | } 23 | -------------------------------------------------------------------------------- /share/deploy.js: -------------------------------------------------------------------------------- 1 | import { deploy } from "net/deploy-script"; 2 | 3 | export function autocomplete(data) { 4 | return data.servers; 5 | } 6 | 7 | /** @param {NS} ns **/ 8 | export async function main(ns) { 9 | if (ns.args.length == 0 && ns.getPurchasedServers().length == 0) { 10 | // do not automatically pick a host right after augmentation 11 | return; 12 | } 13 | 14 | const host = ns.args[0]; 15 | const reservedRam = ns.args[1]; 16 | const script = "/share/share.js"; 17 | 18 | await deploy(ns, {host, script, reservedRam, threads:'max'}, {logLevel: 4}); 19 | } 20 | -------------------------------------------------------------------------------- /share/share.js: -------------------------------------------------------------------------------- 1 | /** @param {NS} ns **/ 2 | export async function main(ns) { 3 | while (true) { 4 | await ns.share(); 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /sleeves/buy-augs.js: -------------------------------------------------------------------------------- 1 | const EXCLUDED_AUGS = { 2 | "CashRoot Starter Kit": true 3 | }; 4 | 5 | export async function main(ns) { 6 | let fundsFraction = 0.01; 7 | if (ns.args.length > 0) { 8 | fundsFraction = ns.args[0]; 9 | } 10 | for (let i = 0; i < ns.sleeve.getNumSleeves(); i++) { 11 | for (const aug of ns.sleeve.getSleevePurchasableAugs(i)) { 12 | if (aug.name in EXCLUDED_AUGS) { 13 | continue; 14 | } 15 | if (aug.cost < fundsFraction*ns.getPlayer().money) { 16 | if (ns.sleeve.purchaseSleeveAug(i, aug.name)) { 17 | ns.tprint(`Sleeve ${i} purchased ${aug.name}`); 18 | } 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /sleeves/crime.js: -------------------------------------------------------------------------------- 1 | export async function main(ns) { 2 | let crimeName = ns.args[0]; 3 | for (let i = 0; i < ns.sleeve.getNumSleeves(); i++) { 4 | const stats = ns.sleeve.getSleeveStats(i); 5 | let defaultCrime = "mug"; 6 | if (stats.strength > 200) { 7 | defaultCrime = "homicide"; 8 | } 9 | ns.sleeve.setToCommitCrime(i, crimeName || defaultCrime); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /sleeves/init.js: -------------------------------------------------------------------------------- 1 | import { trainSleeve } from "sleeves/train.js"; 2 | import { workSleeve, clearSleeves } from "sleeves/work.js"; 3 | 4 | export async function main(ns) { 5 | const player = ns.getPlayer(); 6 | clearSleeves(ns); 7 | for (let i = 0; i < ns.sleeve.getNumSleeves(); i++) { 8 | const stats = ns.sleeve.getSleeveStats(i); 9 | if (stats.shock > 20) { 10 | ns.sleeve.setToShockRecovery(i); 11 | } 12 | else if (stats.sync < 100) { 13 | ns.sleeve.setToSynchronize(i); 14 | } 15 | else if (stats.hacking < 50 || player.hacking < 50) { 16 | trainSleeve(ns, i); 17 | } 18 | else { 19 | workSleeve(ns, i); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /sleeves/train.js: -------------------------------------------------------------------------------- 1 | export async function main(ns) { 2 | for (let i = 0; i < ns.sleeve.getNumSleeves(); i++) { 3 | trainSleeve(ns, i); 4 | } 5 | } 6 | 7 | export function trainSleeve(ns, i) { 8 | if (i == 0) { 9 | ns.sleeve.setToUniversityCourse(i, "Rothman University", "Algorithms"); 10 | } 11 | else if (i == 1) { 12 | ns.sleeve.setToGymWorkout(i, "Powerhouse Gym", "Strength"); 13 | } 14 | else if (i == 2) { 15 | ns.sleeve.setToGymWorkout(i, "Powerhouse Gym", "Defense"); 16 | } 17 | else if (i == 3) { 18 | ns.sleeve.setToGymWorkout(i, "Powerhouse Gym", "Dexterity"); 19 | } 20 | else if (i == 4) { 21 | ns.sleeve.setToGymWorkout(i, "Powerhouse Gym", "Agility"); 22 | } 23 | else if (i == 5) { 24 | ns.sleeve.setToUniversityCourse(i, "Rothman University", "Leadership"); 25 | } 26 | else { 27 | // ns.sleeve.setToCommitCrime(i, "Mug"); 28 | ns.sleeve.setToUniversityCourse(i, "Rothman University", "Algorithms"); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /sleeves/work.js: -------------------------------------------------------------------------------- 1 | export async function main(ns) { 2 | clearSleeves(ns); 3 | for (let i = 0; i < ns.sleeve.getNumSleeves(); i++) { 4 | workSleeve(ns, i); 5 | } 6 | } 7 | 8 | export function clearSleeves(ns) { 9 | for (let i = 0; i < ns.sleeve.getNumSleeves(); i++) { 10 | ns.sleeve.setToSynchronize(i); 11 | } 12 | } 13 | 14 | export function workSleeve(ns, i) { 15 | const player = ns.getPlayer(); 16 | const jobs = Object.keys(player.jobs); 17 | const specialFactions = ["Church of the Machine God", "Bladeburners"] 18 | if (ns.gang.inGang()) { 19 | specialFactions.push(ns.gang.getGangInformation().faction); 20 | } 21 | const factions = player.factions.filter(function(faction){ 22 | return !specialFactions.includes(faction); 23 | }); 24 | 25 | let j = i - jobs.length; 26 | if (i < jobs.length) { 27 | ns.sleeve.setToCompanyWork(i, jobs[i]); 28 | } 29 | else if (j < factions.length) { 30 | const faction = factions[j]; 31 | // ns.tprint(`sleeve ${i} working for faction ${faction}`) 32 | ns.sleeve.setToFactionWork(i, faction, "Field Work"); 33 | if (ns.sleeve.getTask(i).task == "Idle") { 34 | ns.sleeve.setToFactionWork(i, faction, "Hacking Contracts"); 35 | } 36 | } 37 | else { 38 | // ns.sleeve.setToUniversityCourse(i, "Rothman University", "Algorithms"); 39 | ns.sleeve.setToCommitCrime(i, "Mug"); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /stanek/charge-x-y.js: -------------------------------------------------------------------------------- 1 | /** @param {NS} ns **/ 2 | export async function main(ns) { 3 | if (ns.args.length < 2) { 4 | ns.tprint("No fragments to charge. Exiting."); 5 | return; 6 | } 7 | while (true) { 8 | for (let i = 0; i < ns.args.length; i += 2) { 9 | const x = ns.args[i]; 10 | const y = ns.args[i+1]; 11 | await ns.stanek.chargeFragment(x, y); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /stanek/deploy.js: -------------------------------------------------------------------------------- 1 | import { deploy } from "/net/deploy-script"; 2 | 3 | export function autocomplete(data) { 4 | return data.servers; 5 | } 6 | 7 | /** @param {NS} ns **/ 8 | export async function main(ns) { 9 | const fragments = ns.stanek.activeFragments(); 10 | if (fragments.length == 0) { 11 | ns.tprint("No fragments to charge."); 12 | return; 13 | } 14 | const xy = []; 15 | for (const fragment of fragments) { 16 | if (fragment.limit == 1) { 17 | xy.push(fragment.x); 18 | xy.push(fragment.y); 19 | } 20 | } 21 | 22 | const host = ns.args[0]; 23 | const reservedRam = ns.args[1] || 0; 24 | const script = "/stanek/charge-x-y.js"; 25 | const args = xy; 26 | 27 | await deploy(ns, {host, script, args, reservedRam, threads:'max'}, {logLevel: 4}); 28 | } 29 | -------------------------------------------------------------------------------- /stanek/info.js: -------------------------------------------------------------------------------- 1 | /** @param {NS} ns **/ 2 | export async function main(ns) { 3 | const fragments = ns.stanek.activeFragments(); 4 | ns.print("["); 5 | for (const fragment of fragments) { 6 | ns.print(' ', JSON.stringify(fragment), ','); 7 | } 8 | ns.print("]"); 9 | ns.tail(); 10 | } 11 | -------------------------------------------------------------------------------- /stanek/respec.js: -------------------------------------------------------------------------------- 1 | /** @param {NS} ns **/ 2 | export async function main(ns) { 3 | ns.stanek.clearGift(); 4 | 5 | for (const fragment of hackingSpec7x7) { 6 | ns.stanek.placeFragment(fragment.x, fragment.y, fragment.rotation, fragment.id); 7 | } 8 | } 9 | 10 | const hackingSpec6x5 = [ 11 | {"id": 25, "x": 0, "y": 3, "rotation": 0, "type": 14, "power": 0.5, "limit": 1}, 12 | {"id": 1, "x": 0, "y": 2, "rotation": 0, "type": 6, "power": 1, "limit": 1}, 13 | {"id": 0, "x": 3, "y": 3, "rotation": 0, "type": 6, "power": 1, "limit": 1}, 14 | {"id": 107, "x": 2, "y": 1, "rotation": 0, "type": 18, "power": 1.1, "limit": 99}, 15 | {"id": 5, "x": 4, "y": 0, "rotation": 1, "type": 3, "power": 1.3, "limit": 1}, 16 | {"id": 6, "x": 1, "y": 0, "rotation": 0, "type": 4, "power": 2, "limit": 1}, 17 | {"id": 7, "x": 0, "y": 0, "rotation": 0, "type": 5, "power": 0.5, "limit": 1} 18 | ]; 19 | 20 | const hackingSpec6x6 = [ 21 | {"id":20,"x":0,"y":0,"rotation":0,"shape":[[true,true,true,true]],"type":12,"power":1,"limit":1}, 22 | {"id":25,"x":0,"y":4,"rotation":0,"shape":[[true,false,false],[true,true,true]],"type":14,"power":0.5,"limit":1}, 23 | {"id":5,"x":0,"y":1,"rotation":3,"shape":[[true,true,true],[false,true,false]],"type":3,"power":1.3,"limit":1}, 24 | {"id":1,"x":1,"y":1,"rotation":0,"shape":[[true,true,false],[false,true,true]],"type":6,"power":1,"limit":1}, 25 | {"id":0,"x":3,"y":0,"rotation":0,"shape":[[false,true,true],[true,true,false]],"type":6,"power":1,"limit":1}, 26 | {"id":7,"x":3,"y":4,"rotation":0,"shape":[[true,false,false],[true,true,true]],"type":5,"power":0.5,"limit":1}, 27 | {"id":21,"x":1,"y":3,"rotation":0,"shape":[[true,true],[true,true]],"type":13,"power":2,"limit":1}, 28 | {"id":6,"x":5,"y":1,"rotation":3,"shape":[[true,true,true,true]],"type":4,"power":2,"limit":1}, 29 | {"id":10,"x":3,"y":2,"rotation":1,"shape":[[true,true,true],[false,true,false]],"type":7,"power":2,"limit":1} 30 | ]; 31 | 32 | const hackingSpec7x7 = [ 33 | {"id":5,"x":0,"y":4,"rotation":3,"shape":[[true,true,true],[false,true,false]],"type":3,"power":1.3,"limit":1}, 34 | {"id":0,"x":1,"y":5,"rotation":2,"shape":[[false,true,true],[true,true,false]],"type":6,"power":1,"limit":1}, 35 | {"id":25,"x":5,"y":4,"rotation":3,"shape":[[true,false,false],[true,true,true]],"type":14,"power":0.5,"limit":1}, 36 | {"id":30,"x":3,"y":5,"rotation":2,"shape":[[false,true,true],[true,true,false]],"type":17,"power":0.4,"limit":1}, 37 | {"id":106,"x":1,"y":2,"rotation":3,"shape":[[true,false,false],[true,true,true],[true,false,false]],"type":18,"power":1.1,"limit":99}, 38 | {"id":7,"x":1,"y":1,"rotation":1,"shape":[[true,false,false],[true,true,true]],"type":5,"power":0.5,"limit":1}, 39 | {"id":6,"x":0,"y":0,"rotation":1,"shape":[[true,true,true,true]],"type":4,"power":2,"limit":1}, 40 | {"id":20,"x":1,"y":0,"rotation":2,"shape":[[true,true,true,true]],"type":12,"power":1,"limit":1}, 41 | {"id":1,"x":3,"y":3,"rotation":0,"shape":[[true,true,false],[false,true,true]],"type":6,"power":1,"limit":1}, 42 | {"id":21,"x":3,"y":1,"rotation":0,"shape":[[true,true],[true,true]],"type":13,"power":2,"limit":1}, 43 | {"id":101,"x":5,"y":0,"rotation":3,"shape":[[true,true,true,true],[true,false,false,false]],"type":18,"power":1.1,"limit":99}, 44 | ]; 45 | -------------------------------------------------------------------------------- /stocks/companies.js: -------------------------------------------------------------------------------- 1 | export const LocationName = {}; 2 | 3 | // Cities 4 | LocationName.Aevum = "Aevum"; 5 | LocationName.Chongqing = "Chongqing"; 6 | LocationName.Ishima = "Ishima"; 7 | LocationName.NewTokyo = "New Tokyo"; 8 | LocationName.Sector12 = "Sector-12"; 9 | LocationName.Volhaven = "Volhaven"; 10 | 11 | // Aevum Locations 12 | LocationName.AevumAeroCorp = "AeroCorp"; 13 | LocationName.AevumBachmanAndAssociates = "Bachman & Associates"; 14 | LocationName.AevumClarkeIncorporated = "Clarke Incorporated"; 15 | LocationName.AevumCrushFitnessGym = "Crush Fitness Gym"; 16 | LocationName.AevumECorp = "ECorp"; 17 | LocationName.AevumFulcrumTechnologies = "Fulcrum Technologies"; 18 | LocationName.AevumGalacticCybersystems = "Galactic Cybersystems"; 19 | LocationName.AevumNetLinkTechnologies = "NetLink Technologies"; 20 | LocationName.AevumPolice = "Aevum Police Headquarters"; 21 | LocationName.AevumRhoConstruction = "Rho Construction"; 22 | LocationName.AevumSnapFitnessGym = "Snap Fitness Gym"; 23 | LocationName.AevumSummitUniversity = "Summit University"; 24 | LocationName.AevumWatchdogSecurity = "Watchdog Security"; 25 | LocationName.AevumCasino = "Iker Molina Casino"; 26 | 27 | // Chongqing locations 28 | LocationName.ChongqingKuaiGongInternational = "KuaiGong International"; 29 | LocationName.ChongqingSolarisSpaceSystems = "Solaris Space Systems"; 30 | LocationName.ChongqingChurchOfTheMachineGod = "Church of the Machine God"; 31 | 32 | // Sector 12 33 | LocationName.Sector12AlphaEnterprises = "Alpha Enterprises"; 34 | LocationName.Sector12BladeIndustries = "Blade Industries"; 35 | LocationName.Sector12CIA = "Central Intelligence Agency"; 36 | LocationName.Sector12CarmichaelSecurity = "Carmichael Security"; 37 | LocationName.Sector12CityHall = "Sector-12 City Hall"; 38 | LocationName.Sector12DeltaOne = "DeltaOne"; 39 | LocationName.Sector12FoodNStuff = "FoodNStuff"; 40 | LocationName.Sector12FourSigma = "Four Sigma"; 41 | LocationName.Sector12IcarusMicrosystems = "Icarus Microsystems"; 42 | LocationName.Sector12IronGym = "Iron Gym"; 43 | LocationName.Sector12JoesGuns = "Joe's Guns"; 44 | LocationName.Sector12MegaCorp = "MegaCorp"; 45 | LocationName.Sector12NSA = "National Security Agency"; 46 | LocationName.Sector12PowerhouseGym = "Powerhouse Gym"; 47 | LocationName.Sector12RothmanUniversity = "Rothman University"; 48 | LocationName.Sector12UniversalEnergy = "Universal Energy"; 49 | 50 | // New Tokyo 51 | LocationName.NewTokyoDefComm = "DefComm"; 52 | LocationName.NewTokyoGlobalPharmaceuticals = "Global Pharmaceuticals"; 53 | LocationName.NewTokyoNoodleBar = "Noodle Bar"; 54 | LocationName.NewTokyoVitaLife = "VitaLife"; 55 | 56 | // Ishima 57 | LocationName.IshimaNovaMedical = "Nova Medical"; 58 | LocationName.IshimaOmegaSoftware = "Omega Software"; 59 | LocationName.IshimaStormTechnologies = "Storm Technologies"; 60 | LocationName.IshimaGlitch = "0x6C1"; 61 | 62 | // Volhaven 63 | LocationName.VolhavenCompuTek = "CompuTek"; 64 | LocationName.VolhavenHeliosLabs = "Helios Labs"; 65 | LocationName.VolhavenLexoCorp = "LexoCorp"; 66 | LocationName.VolhavenMilleniumFitnessGym = "Millenium Fitness Gym"; 67 | LocationName.VolhavenNWO = "NWO"; 68 | LocationName.VolhavenOmniTekIncorporated = "OmniTek Incorporated"; 69 | LocationName.VolhavenOmniaCybersystems = "Omnia Cybersystems"; 70 | LocationName.VolhavenSysCoreSecurities = "SysCore Securities"; 71 | LocationName.VolhavenZBInstituteOfTechnology = "ZB Institute of Technology"; 72 | 73 | // Generic locations 74 | LocationName.Hospital = "Hospital"; 75 | LocationName.Slums = "The Slums"; 76 | LocationName.TravelAgency = "Travel Agency"; 77 | LocationName.WorldStockExchange = "World Stock Exchange"; 78 | 79 | // Default name for Location objects 80 | LocationName.Void = "The Void"; 81 | 82 | export const StockSymbols = {}; 83 | 84 | // Stocks for companies at which you can work 85 | StockSymbols[LocationName.AevumECorp] = "ECP"; 86 | StockSymbols[LocationName.Sector12MegaCorp] = "MGCP"; 87 | StockSymbols[LocationName.Sector12BladeIndustries] = "BLD"; 88 | StockSymbols[LocationName.AevumClarkeIncorporated] = "CLRK"; 89 | StockSymbols[LocationName.VolhavenOmniTekIncorporated] = "OMTK"; 90 | StockSymbols[LocationName.Sector12FourSigma] = "FSIG"; 91 | StockSymbols[LocationName.ChongqingKuaiGongInternational] = "KGI"; 92 | StockSymbols[LocationName.AevumFulcrumTechnologies] = "FLCM"; 93 | StockSymbols[LocationName.IshimaStormTechnologies] = "STM"; 94 | StockSymbols[LocationName.NewTokyoDefComm] = "DCOMM"; 95 | StockSymbols[LocationName.VolhavenHeliosLabs] = "HLS"; 96 | StockSymbols[LocationName.NewTokyoVitaLife] = "VITA"; 97 | StockSymbols[LocationName.Sector12IcarusMicrosystems] = "ICRS"; 98 | StockSymbols[LocationName.Sector12UniversalEnergy] = "UNV"; 99 | StockSymbols[LocationName.AevumAeroCorp] = "AERO"; 100 | StockSymbols[LocationName.VolhavenOmniaCybersystems] = "OMN"; 101 | StockSymbols[LocationName.ChongqingSolarisSpaceSystems] = "SLRS"; 102 | StockSymbols[LocationName.NewTokyoGlobalPharmaceuticals] = "GPH"; 103 | StockSymbols[LocationName.IshimaNovaMedical] = "NVMD"; 104 | StockSymbols[LocationName.AevumWatchdogSecurity] = "WDS"; 105 | StockSymbols[LocationName.VolhavenLexoCorp] = "LXO"; 106 | StockSymbols[LocationName.AevumRhoConstruction] = "RHOC"; 107 | StockSymbols[LocationName.Sector12AlphaEnterprises] = "APHE"; 108 | StockSymbols[LocationName.VolhavenSysCoreSecurities] = "SYSC"; 109 | StockSymbols[LocationName.VolhavenCompuTek] = "CTK"; 110 | StockSymbols[LocationName.AevumNetLinkTechnologies] = "NTLK"; 111 | StockSymbols[LocationName.IshimaOmegaSoftware] = "OMGA"; 112 | StockSymbols[LocationName.Sector12FoodNStuff] = "FNS"; 113 | StockSymbols[LocationName.Sector12JoesGuns] = "JGN"; 114 | 115 | // Stocks for other companies 116 | StockSymbols["Sigma Cosmetics"] = "SGC"; 117 | StockSymbols["Catalyst Ventures"] = "CTYS"; 118 | StockSymbols["Microdyne Technologies"] = "MDYN"; 119 | StockSymbols["Titan Laboratories"] = "TITN"; 120 | -------------------------------------------------------------------------------- /stocks/sell.js: -------------------------------------------------------------------------------- 1 | export async function main(ns) { 2 | sellAllStocks(ns); 3 | } 4 | 5 | export function sellAllStocks(ns, short=false) { 6 | let netMoney = 0; 7 | for (const symbol of ns.stock.getSymbols()) { 8 | const [shares, avgPrice, sharesShort, avgPriceShort] = ns.stock.getPosition(symbol); 9 | const salePrice = ns.stock.sell(symbol, shares); 10 | netMoney += shares * salePrice; 11 | if (short) { 12 | const saleCost = ns.stock.sellShort(symbol, sharesShort); 13 | netMoney -= sharesShort * saleCost; 14 | } 15 | } 16 | ns.tprint(`INFO: Sold all stocks for ${ns.nFormat(netMoney, "$0.0a")}`); 17 | } 18 | -------------------------------------------------------------------------------- /unmanaged-hacking/deploy.js: -------------------------------------------------------------------------------- 1 | import { deploy } from "net/deploy-script.js"; 2 | 3 | const FLAGS = []; 4 | 5 | export function autocomplete(data, args) { 6 | data.flags(FLAGS); 7 | return data.servers; 8 | } 9 | 10 | /** @param {NS} ns **/ 11 | export async function main(ns) { 12 | const flags = ns.flags(FLAGS); 13 | const target = flags._.shift(); 14 | 15 | const minSecurity = ns.getServerMinSecurityLevel(target); 16 | const maxMoney = ns.getServerMaxMoney(target); 17 | const money = ns.getServerMoneyAvailable(target); 18 | const threads = Math.ceil(ns.growthAnalyze(target, maxMoney / Math.max(1,money)) / 2); 19 | 20 | const script = "/unmanaged-hacking/hack-grow-weaken.js"; 21 | const args = [target, "--minSecurity", minSecurity, "--maxMoney", maxMoney]; 22 | 23 | // ns.run(script, threads, ...args); 24 | await deploy(ns, {script, threads, args}, {allowSplit: true, logLevel: 3}); 25 | } 26 | -------------------------------------------------------------------------------- /unmanaged-hacking/hack-grow-weaken.js: -------------------------------------------------------------------------------- 1 | const FLAGS = [ 2 | ["minSecurity", 1], 3 | ["maxMoney", 1e7] 4 | ]; 5 | 6 | export function autocomplete(data, args) { 7 | data.flags(FLAGS); 8 | return data.servers; 9 | } 10 | 11 | /** @param {NS} ns **/ 12 | export async function main(ns) { 13 | const flags = ns.flags(FLAGS); 14 | const target = flags._.shift(); 15 | 16 | while (true) { 17 | if (ns.getServerSecurityLevel(target) > 1 + flags.minSecurity) { 18 | await ns.weaken(target); 19 | } 20 | else if (ns.getServerMoneyAvailable(target) < 0.9 * flags.maxMoney) { 21 | await ns.grow(target); 22 | } 23 | else { 24 | await ns.hack(target); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /unmanaged-hacking/stop.js: -------------------------------------------------------------------------------- 1 | import { ServerPool } from "/net/deploy-script"; 2 | 3 | export async function main(ns) { 4 | const script = "/unmanaged-hacking/hack-grow-weaken.js"; 5 | const serverPool = new ServerPool(ns); 6 | let numKilled = 0; 7 | for (const server of serverPool) { 8 | const result = ns.scriptKill(script, server.hostname); 9 | if (result) { 10 | numKilled++; 11 | } 12 | } 13 | ns.tprint(`INFO: Stopped ${numKilled} scripts.`); 14 | } 15 | --------------------------------------------------------------------------------